jarvis-ai-assistant 0.3.27__py3-none-any.whl → 0.3.29__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 (66) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +73 -29
  3. jarvis/jarvis_agent/agent_manager.py +6 -0
  4. jarvis/jarvis_agent/config_editor.py +1 -1
  5. jarvis/jarvis_agent/event_bus.py +2 -2
  6. jarvis/jarvis_agent/events.py +157 -0
  7. jarvis/jarvis_agent/file_methodology_manager.py +18 -7
  8. jarvis/jarvis_agent/jarvis.py +11 -4
  9. jarvis/jarvis_agent/memory_manager.py +4 -4
  10. jarvis/jarvis_agent/prompts.py +2 -2
  11. jarvis/jarvis_agent/protocols.py +4 -1
  12. jarvis/jarvis_agent/run_loop.py +9 -24
  13. jarvis/jarvis_agent/shell_input_handler.py +7 -2
  14. jarvis/jarvis_agent/task_analyzer.py +19 -15
  15. jarvis/jarvis_agent/task_manager.py +6 -4
  16. jarvis/jarvis_agent/user_interaction.py +1 -1
  17. jarvis/jarvis_agent/utils.py +50 -0
  18. jarvis/jarvis_code_agent/code_agent.py +2 -2
  19. jarvis/jarvis_code_analysis/code_review.py +0 -1
  20. jarvis/jarvis_git_utils/git_commiter.py +13 -4
  21. jarvis/jarvis_mcp/sse_mcp_client.py +1 -1
  22. jarvis/jarvis_mcp/stdio_mcp_client.py +1 -1
  23. jarvis/jarvis_memory_organizer/memory_organizer.py +6 -9
  24. jarvis/jarvis_methodology/main.py +0 -2
  25. jarvis/jarvis_multi_agent/__init__.py +3 -3
  26. jarvis/jarvis_platform/base.py +1 -1
  27. jarvis/jarvis_platform/kimi.py +1 -1
  28. jarvis/jarvis_platform/registry.py +1 -1
  29. jarvis/jarvis_platform/tongyi.py +1 -1
  30. jarvis/jarvis_platform/yuanbao.py +1 -2
  31. jarvis/jarvis_platform_manager/service.py +1 -1
  32. jarvis/jarvis_rag/cli.py +1 -1
  33. jarvis/jarvis_rag/embedding_manager.py +0 -1
  34. jarvis/jarvis_rag/llm_interface.py +0 -3
  35. jarvis/jarvis_rag/retriever.py +3 -3
  36. jarvis/jarvis_smart_shell/main.py +0 -1
  37. jarvis/jarvis_stats/cli.py +2 -3
  38. jarvis/jarvis_stats/stats.py +3 -4
  39. jarvis/jarvis_stats/storage.py +3 -3
  40. jarvis/jarvis_tools/clear_memory.py +1 -3
  41. jarvis/jarvis_tools/cli/main.py +0 -1
  42. jarvis/jarvis_tools/edit_file.py +3 -4
  43. jarvis/jarvis_tools/execute_script.py +2 -2
  44. jarvis/jarvis_tools/generate_new_tool.py +3 -5
  45. jarvis/jarvis_tools/registry.py +2 -3
  46. jarvis/jarvis_tools/retrieve_memory.py +2 -3
  47. jarvis/jarvis_tools/save_memory.py +3 -3
  48. jarvis/jarvis_tools/search_web.py +2 -2
  49. jarvis/jarvis_tools/sub_agent.py +21 -2
  50. jarvis/jarvis_tools/sub_code_agent.py +18 -2
  51. jarvis/jarvis_tools/virtual_tty.py +3 -14
  52. jarvis/jarvis_utils/builtin_replace_map.py +4 -4
  53. jarvis/jarvis_utils/config.py +32 -17
  54. jarvis/jarvis_utils/fzf.py +4 -3
  55. jarvis/jarvis_utils/git_utils.py +1 -1
  56. jarvis/jarvis_utils/globals.py +1 -2
  57. jarvis/jarvis_utils/input.py +5 -5
  58. jarvis/jarvis_utils/methodology.py +3 -5
  59. jarvis/jarvis_utils/output.py +1 -1
  60. jarvis/jarvis_utils/utils.py +160 -31
  61. {jarvis_ai_assistant-0.3.27.dist-info → jarvis_ai_assistant-0.3.29.dist-info}/METADATA +1 -1
  62. {jarvis_ai_assistant-0.3.27.dist-info → jarvis_ai_assistant-0.3.29.dist-info}/RECORD +66 -64
  63. {jarvis_ai_assistant-0.3.27.dist-info → jarvis_ai_assistant-0.3.29.dist-info}/WHEEL +0 -0
  64. {jarvis_ai_assistant-0.3.27.dist-info → jarvis_ai_assistant-0.3.29.dist-info}/entry_points.txt +0 -0
  65. {jarvis_ai_assistant-0.3.27.dist-info → jarvis_ai_assistant-0.3.29.dist-info}/licenses/LICENSE +0 -0
  66. {jarvis_ai_assistant-0.3.27.dist-info → jarvis_ai_assistant-0.3.29.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,8 @@
1
1
  # -*- coding: utf-8 -*-
2
- from typing import Any, Protocol, Tuple
2
+ from typing import Any, Protocol, Tuple, runtime_checkable
3
3
 
4
4
 
5
+ @runtime_checkable
5
6
  class OutputHandlerProtocol(Protocol):
6
7
  """
7
8
  Defines the interface for an output handler, which is responsible for
@@ -28,3 +29,5 @@ class OutputHandlerProtocol(Protocol):
28
29
  A tuple containing a boolean (whether to return) and the result.
29
30
  """
30
31
  ...
32
+
33
+ __all__ = ["OutputHandlerProtocol"]
@@ -11,7 +11,8 @@ from enum import Enum
11
11
  from typing import Any, TYPE_CHECKING
12
12
 
13
13
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
14
- from jarvis.jarvis_utils.tag import ot
14
+ from jarvis.jarvis_agent.events import BEFORE_TOOL_CALL, AFTER_TOOL_CALL
15
+ from jarvis.jarvis_agent.utils import join_prompts, is_auto_complete, normalize_next_action
15
16
 
16
17
  if TYPE_CHECKING:
17
18
  # 仅用于类型标注,避免运行时循环依赖
@@ -63,7 +64,7 @@ class AgentRunLoop:
63
64
  # 广播工具调用前事件(不影响主流程)
64
65
  try:
65
66
  ag.event_bus.emit(
66
- "before_tool_call",
67
+ BEFORE_TOOL_CALL,
67
68
  agent=ag,
68
69
  current_response=current_response,
69
70
  )
@@ -72,12 +73,7 @@ class AgentRunLoop:
72
73
  need_return, tool_prompt = ag._call_tools(current_response)
73
74
 
74
75
  # 将上一个提示和工具提示安全地拼接起来
75
- prompt_parts = []
76
- if ag.session.prompt:
77
- prompt_parts.append(ag.session.prompt)
78
- if tool_prompt:
79
- prompt_parts.append(tool_prompt)
80
- ag.session.prompt = "\n\n".join(prompt_parts)
76
+ ag.session.prompt = join_prompts([ag.session.prompt, tool_prompt])
81
77
 
82
78
  if need_return:
83
79
  return ag.session.prompt
@@ -88,7 +84,7 @@ class AgentRunLoop:
88
84
  # 广播工具调用后的事件(不影响主流程)
89
85
  try:
90
86
  ag.event_bus.emit(
91
- "after_tool_call",
87
+ AFTER_TOOL_CALL,
92
88
  agent=ag,
93
89
  current_response=current_response,
94
90
  need_return=need_return,
@@ -102,27 +98,16 @@ class AgentRunLoop:
102
98
  continue
103
99
 
104
100
  # 检查自动完成
105
- if ag.auto_complete and ot("!!!COMPLETE!!!") in current_response:
101
+ if ag.auto_complete and is_auto_complete(current_response):
106
102
  return ag._complete_task(auto_completed=True)
107
103
 
108
104
  # 获取下一步用户输入
109
105
  next_action = ag._get_next_user_action()
110
- if (
111
- next_action == "continue"
112
- or (
113
- isinstance(next_action, Enum)
114
- and getattr(next_action, "value", None) == "continue"
115
- )
116
- ):
106
+ action = normalize_next_action(next_action)
107
+ if action == "continue":
117
108
  run_input_handlers = True
118
109
  continue
119
- elif (
120
- next_action == "complete"
121
- or (
122
- isinstance(next_action, Enum)
123
- and getattr(next_action, "value", None) == "complete"
124
- )
125
- ):
110
+ elif action == "complete":
126
111
  return ag._complete_task(auto_completed=False)
127
112
 
128
113
  except Exception as e:
@@ -3,6 +3,7 @@ from typing import Any, Tuple
3
3
 
4
4
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
5
5
  from jarvis.jarvis_utils.input import user_confirm
6
+ from jarvis.jarvis_agent.utils import join_prompts
6
7
 
7
8
 
8
9
  def shell_input_handler(user_input: str, agent: Any) -> Tuple[str, bool]:
@@ -28,7 +29,7 @@ def shell_input_handler(user_input: str, agent: Any) -> Tuple[str, bool]:
28
29
  # If any line contains the no-confirm marker, skip the pre-execution confirmation
29
30
  no_confirm = any(marker in c for c in cmdline)
30
31
 
31
- if no_confirm or user_confirm(f"是否要执行以上shell脚本?", default=True):
32
+ if no_confirm or user_confirm("是否要执行以上shell脚本?", default=True):
32
33
  from jarvis.jarvis_tools.registry import ToolRegistry
33
34
 
34
35
  output = ToolRegistry().handle_tool_calls(
@@ -41,7 +42,11 @@ def shell_input_handler(user_input: str, agent: Any) -> Tuple[str, bool]:
41
42
  )
42
43
  if user_confirm("是否将执行结果反馈给Agent?", default=True):
43
44
  return (
44
- f"{user_input}\n\n用户执行以下脚本:\n{script}\n\n执行结果:\n{output}",
45
+ join_prompts([
46
+ user_input,
47
+ f"用户执行以下脚本:\n{script}",
48
+ f"执行结果:\n{output}",
49
+ ]),
45
50
  False,
46
51
  )
47
52
  return "", True
@@ -3,12 +3,13 @@
3
3
  任务分析器模块
4
4
  负责处理任务分析和方法论生成功能
5
5
  """
6
- from typing import Optional
7
6
 
8
7
  from jarvis.jarvis_utils.globals import get_interrupt, set_interrupt
9
8
 
10
9
  from jarvis.jarvis_agent.prompts import TASK_ANALYSIS_PROMPT
11
10
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
11
+ from jarvis.jarvis_agent.utils import join_prompts
12
+ from jarvis.jarvis_agent.events import BEFORE_TOOL_CALL, AFTER_TOOL_CALL, BEFORE_SUMMARY, TASK_COMPLETED
12
13
 
13
14
 
14
15
  class TaskAnalyzer:
@@ -44,7 +45,7 @@ class TaskAnalyzer:
44
45
  # 循环处理工具调用,直到没有工具调用为止
45
46
  self._process_analysis_loop()
46
47
 
47
- except Exception as e:
48
+ except Exception:
48
49
  PrettyOutput.print("分析失败", OutputType.ERROR)
49
50
  finally:
50
51
  # 标记已完成一次分析,避免事件回调重复执行
@@ -56,10 +57,7 @@ class TaskAnalyzer:
56
57
 
57
58
  def _prepare_analysis_prompt(self, satisfaction_feedback: str) -> str:
58
59
  """准备分析提示"""
59
- analysis_prompt = TASK_ANALYSIS_PROMPT
60
- if satisfaction_feedback:
61
- analysis_prompt += satisfaction_feedback
62
- return analysis_prompt
60
+ return join_prompts([TASK_ANALYSIS_PROMPT, satisfaction_feedback])
63
61
 
64
62
  def _process_analysis_loop(self):
65
63
  """处理分析循环"""
@@ -75,7 +73,7 @@ class TaskAnalyzer:
75
73
  # 执行工具调用(补充事件:before_tool_call/after_tool_call)
76
74
  try:
77
75
  self.agent.event_bus.emit(
78
- "before_tool_call",
76
+ BEFORE_TOOL_CALL,
79
77
  agent=self.agent,
80
78
  current_response=response,
81
79
  )
@@ -85,7 +83,7 @@ class TaskAnalyzer:
85
83
  self.agent.session.prompt = tool_prompt
86
84
  try:
87
85
  self.agent.event_bus.emit(
88
- "after_tool_call",
86
+ AFTER_TOOL_CALL,
89
87
  agent=self.agent,
90
88
  current_response=response,
91
89
  need_return=need_return,
@@ -131,9 +129,15 @@ class TaskAnalyzer:
131
129
  def _handle_interrupt_with_tool_calls(self, user_input: str) -> str:
132
130
  """处理有工具调用时的中断"""
133
131
  if self.agent.user_confirm("检测到有工具调用,是否继续处理工具调用?", True):
134
- return f"被用户中断,用户补充信息为:{user_input}\n\n用户同意继续工具调用。"
132
+ return join_prompts([
133
+ f"被用户中断,用户补充信息为:{user_input}",
134
+ "用户同意继续工具调用。"
135
+ ])
135
136
  else:
136
- return f"被用户中断,用户补充信息为:{user_input}\n\n检测到有工具调用,但被用户拒绝执行。请根据用户的补充信息重新考虑下一步操作。"
137
+ return join_prompts([
138
+ f"被用户中断,用户补充信息为:{user_input}",
139
+ "检测到有工具调用,但被用户拒绝执行。请根据用户的补充信息重新考虑下一步操作。"
140
+ ])
137
141
 
138
142
  def collect_satisfaction_feedback(self, auto_completed: bool) -> str:
139
143
  """收集满意度反馈"""
@@ -141,18 +145,18 @@ class TaskAnalyzer:
141
145
 
142
146
  if not auto_completed and self.agent.use_analysis:
143
147
  if self.agent.user_confirm("您对本次任务的完成是否满意?", True):
144
- satisfaction_feedback = "\n\n用户对本次任务的完成表示满意。"
148
+ satisfaction_feedback = "用户对本次任务的完成表示满意。"
145
149
  else:
146
150
  feedback = self.agent._multiline_input(
147
151
  "请提供您的反馈意见(可留空直接回车):", False
148
152
  )
149
153
  if feedback:
150
154
  satisfaction_feedback = (
151
- f"\n\n用户对本次任务的完成不满意,反馈意见如下:\n{feedback}"
155
+ f"用户对本次任务的完成不满意,反馈意见如下:\n{feedback}"
152
156
  )
153
157
  else:
154
158
  satisfaction_feedback = (
155
- "\n\n用户对本次任务的完成不满意,未提供具体反馈意见。"
159
+ "用户对本次任务的完成不满意,未提供具体反馈意见。"
156
160
  )
157
161
 
158
162
  return satisfaction_feedback
@@ -163,9 +167,9 @@ class TaskAnalyzer:
163
167
  def _subscribe_events(self) -> None:
164
168
  bus = self.agent.get_event_bus() # type: ignore[attr-defined]
165
169
  # 在生成总结前触发(保持与原顺序一致)
166
- bus.subscribe("before_summary", self._on_before_summary)
170
+ bus.subscribe(BEFORE_SUMMARY, self._on_before_summary)
167
171
  # 当无需总结时,作为兜底触发分析
168
- bus.subscribe("task_completed", self._on_task_completed)
172
+ bus.subscribe(TASK_COMPLETED, self._on_task_completed)
169
173
 
170
174
  def _on_before_summary(self, **payload) -> None:
171
175
  if self._analysis_done:
@@ -14,6 +14,7 @@ from jarvis.jarvis_agent import (
14
14
  get_multiline_input,
15
15
  user_confirm,
16
16
  )
17
+ from jarvis.jarvis_agent.utils import join_prompts
17
18
  from jarvis.jarvis_utils.config import get_data_dir
18
19
  from jarvis.jarvis_utils.fzf import fzf_select
19
20
 
@@ -109,7 +110,7 @@ class TaskManager:
109
110
  if need_additional:
110
111
  additional_input = get_multiline_input("请输入补充信息:")
111
112
  if additional_input:
112
- selected_task = f"{selected_task}\n\n补充信息:\n{additional_input}"
113
+ selected_task = join_prompts([selected_task, f"补充信息:\n{additional_input}"])
113
114
  return selected_task
114
115
  except Exception:
115
116
  # 如果解析失败,则回退到手动输入
@@ -138,9 +139,10 @@ class TaskManager:
138
139
  if need_additional:
139
140
  additional_input = get_multiline_input("请输入补充信息:")
140
141
  if additional_input:
141
- selected_task = (
142
- f"{selected_task}\n\n补充信息:\n{additional_input}"
143
- )
142
+ selected_task = join_prompts([
143
+ selected_task,
144
+ f"补充信息:\n{additional_input}"
145
+ ])
144
146
  return selected_task
145
147
  PrettyOutput.print(
146
148
  "无效的选择。请选择列表中的一个号码。", OutputType.WARNING
@@ -6,7 +6,7 @@ UserInteractionHandler: 抽象用户交互(多行输入与确认)逻辑,
6
6
  - 仅提供封装,不直接修改 Agent 的现有调用
7
7
  - 后续步骤在 Agent 中以旁路方式接入,保持向后兼容
8
8
  """
9
- from typing import Callable, Optional
9
+ from typing import Callable
10
10
 
11
11
 
12
12
 
@@ -0,0 +1,50 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ 工具函数(jarvis_agent.utils)
4
+
5
+ - join_prompts: 统一的提示拼接策略(仅拼接非空段落,使用双换行)
6
+ - is_auto_complete: 统一的自动完成标记检测
7
+ """
8
+ from typing import Iterable, List, Any
9
+ from enum import Enum
10
+ from jarvis.jarvis_utils.tag import ot
11
+
12
+ def join_prompts(parts: Iterable[str]) -> str:
13
+ """
14
+ 将多个提示片段按统一规则拼接:
15
+ - 过滤掉空字符串
16
+ - 使用两个换行分隔
17
+ - 不进行额外 strip,保持调用方原样语义
18
+ """
19
+ non_empty: List[str] = [p for p in parts if p]
20
+ return "\n\n".join(non_empty)
21
+
22
+ def is_auto_complete(response: str) -> bool:
23
+ """
24
+ 检测是否包含自动完成标记。
25
+ 当前实现:包含 ot('!!!COMPLETE!!!') 即视为自动完成。
26
+ """
27
+ try:
28
+ return ot("!!!COMPLETE!!!") in response
29
+ except Exception:
30
+ # 防御性处理:即使 ot 出现异常,也不阻塞主流程
31
+ return "!!!COMPLETE!!!" in response
32
+
33
+ def normalize_next_action(next_action: Any) -> str:
34
+ """
35
+ 规范化下一步动作为字符串:
36
+ - 如果是 Enum, 返回其 value(若为字符串)
37
+ - 如果是 str, 原样返回
38
+ - 其他情况返回空字符串
39
+ """
40
+ try:
41
+ if isinstance(next_action, Enum):
42
+ value = getattr(next_action, "value", None)
43
+ return value if isinstance(value, str) else ""
44
+ if isinstance(next_action, str):
45
+ return next_action
46
+ return ""
47
+ except Exception:
48
+ return ""
49
+
50
+ __all__ = ["join_prompts", "is_auto_complete", "normalize_next_action"]
@@ -262,7 +262,7 @@ class CodeAgent:
262
262
  if has_uncommitted_changes():
263
263
 
264
264
  git_commiter = GitCommitTool()
265
- git_commiter.execute({"prefix": prefix, "suffix": suffix, "agent": self.agent})
265
+ git_commiter.execute({"prefix": prefix, "suffix": suffix, "agent": self.agent, "model_group": getattr(self.agent.model, "model_group", None)})
266
266
 
267
267
  def _init_env(self, prefix: str, suffix: str) -> None:
268
268
  """初始化环境,组合以下功能:
@@ -522,7 +522,7 @@ class CodeAgent:
522
522
  check=True,
523
523
  )
524
524
  git_commiter = GitCommitTool()
525
- git_commiter.execute({"prefix": prefix, "suffix": suffix, "agent": self.agent})
525
+ git_commiter.execute({"prefix": prefix, "suffix": suffix, "agent": self.agent, "model_group": getattr(self.agent.model, "model_group", None)})
526
526
 
527
527
  # 在用户接受commit后,根据配置决定是否保存记忆
528
528
  if self.agent.force_save_memory:
@@ -3,7 +3,6 @@ import os
3
3
  import re
4
4
  import subprocess
5
5
  import tempfile
6
- import sys
7
6
  from typing import Any, Dict, List, Optional
8
7
 
9
8
  import typer
@@ -2,7 +2,6 @@
2
2
  import os
3
3
  import re
4
4
  import subprocess
5
- import sys
6
5
  import tempfile
7
6
  from typing import Any, Dict, Optional
8
7
 
@@ -138,7 +137,7 @@ class GitCommitTool:
138
137
  base_prompt = (
139
138
  custom_prompt
140
139
  if custom_prompt
141
- else f"""根据代码差异生成提交信息:
140
+ else """根据代码差异生成提交信息:
142
141
  提交信息应使用中文书写
143
142
  # 格式模板
144
143
  必须使用以下格式:
@@ -219,11 +218,21 @@ commit信息
219
218
  platform = PlatformRegistry().create_platform(platform_name)
220
219
  if platform and model_name:
221
220
  platform.set_model_name(model_name)
222
- if model_group:
223
- platform.model_group = model_group
221
+ if platform and model_group:
222
+ try:
223
+ platform.set_model_group(model_group)
224
+ except Exception:
225
+ # 兼容早期实现
226
+ platform.model_group = model_group # type: ignore
224
227
  else:
225
228
  platform = PlatformRegistry().get_normal_platform()
226
229
 
230
+ # 跳过模型可用性校验:
231
+ # 为避免某些平台/代理不支持 get_model_list 接口导致的噪音日志(如 404),
232
+ # 这里默认不调用 platform.get_model_list() 进行模型可用性校验。
233
+ # 如果未来需要恢复校验,可参考被移除的逻辑。
234
+ # no-op
235
+
227
236
  # Ensure platform is not None
228
237
  if not platform:
229
238
  return {
@@ -210,7 +210,7 @@ class SSEMcpClient(McpClient):
210
210
 
211
211
  # 调用已注册的处理器
212
212
  if method in self.notification_handlers:
213
- error_lines: list[str] = []
213
+ error_lines: List[str] = []
214
214
  for handler in self.notification_handlers[method]:
215
215
  try:
216
216
  handler(params)
@@ -73,7 +73,7 @@ class StdioMcpClient(McpClient):
73
73
  f"初始化失败: {response.get('error', 'Unknown error')}"
74
74
  )
75
75
 
76
- result = response["result"]
76
+ response["result"]
77
77
 
78
78
  # 发送initialized通知 - 使用正确的方法名格式
79
79
  self._send_notification("notifications/initialized", {})
@@ -7,14 +7,11 @@
7
7
  """
8
8
 
9
9
  import json
10
- import sys
11
10
  from collections import defaultdict
12
- from itertools import combinations
13
11
  from pathlib import Path
14
- from typing import Dict, List, Set, Tuple, Any, Optional
12
+ from typing import Dict, List, Set, Any, Optional
15
13
 
16
14
  import typer
17
- import yaml
18
15
 
19
16
  from jarvis.jarvis_utils.config import (
20
17
  get_data_dir,
@@ -66,7 +63,7 @@ class MemoryOrganizer:
66
63
  """加载指定类型的所有记忆"""
67
64
  memories = []
68
65
  memory_files = self._get_memory_files(memory_type)
69
- error_lines: list[str] = []
66
+ error_lines: List[str] = []
70
67
 
71
68
  for memory_file in memory_files:
72
69
  try:
@@ -311,7 +308,7 @@ tags:
311
308
  group_memories = [memories[i] for i in original_indices]
312
309
 
313
310
  # 显示将要合并的记忆(先拼接后统一打印,避免循环逐条输出)
314
- lines = [f"", f"准备合并 {len(group_memories)} 个记忆:"]
311
+ lines = ["", f"准备合并 {len(group_memories)} 个记忆:"]
315
312
  for mem in group_memories:
316
313
  lines.append(
317
314
  f" - ID: {mem.get('id', '未知')}, "
@@ -391,8 +388,8 @@ tags:
391
388
  )
392
389
 
393
390
  # 删除原始记忆文件(先汇总日志,最后统一打印)
394
- info_lines: list[str] = []
395
- warn_lines: list[str] = []
391
+ info_lines: List[str] = []
392
+ warn_lines: List[str] = []
396
393
  for orig_memory in original_memories:
397
394
  if "file_path" in orig_memory:
398
395
  try:
@@ -431,7 +428,7 @@ tags:
431
428
  导出的记忆数量
432
429
  """
433
430
  all_memories = []
434
- progress_lines: list[str] = []
431
+ progress_lines: List[str] = []
435
432
 
436
433
  for memory_type in memory_types:
437
434
  progress_lines.append(f"正在导出 {memory_type} 类型的记忆...")
@@ -11,8 +11,6 @@
11
11
  import hashlib
12
12
  import json
13
13
  import os
14
- import sys
15
- from typing import Optional
16
14
 
17
15
  import typer
18
16
  import yaml # type: ignore
@@ -73,7 +73,7 @@ content: |2
73
73
  if len(send_messages) > 1:
74
74
  return (
75
75
  False,
76
- f"Send multiple messages, please only send one message at a time.",
76
+ "Send multiple messages, please only send one message at a time.",
77
77
  )
78
78
  if len(send_messages) == 0:
79
79
  return False, ""
@@ -100,7 +100,7 @@ content: |2
100
100
  msg = yaml.safe_load(item)
101
101
  if "to" in msg and "content" in msg:
102
102
  ret.append(msg)
103
- except Exception as e:
103
+ except Exception:
104
104
  continue
105
105
  return ret
106
106
 
@@ -161,7 +161,7 @@ content: {msg['content']}
161
161
  """
162
162
  to_agent_name = msg.get("to")
163
163
  if not to_agent_name:
164
- return f"消息中未指定 `to` 字段"
164
+ return "消息中未指定 `to` 字段"
165
165
 
166
166
  if to_agent_name not in self.agents_config_map:
167
167
  PrettyOutput.print(
@@ -88,7 +88,7 @@ class BasePlatform(ABC):
88
88
  PrettyOutput.print(
89
89
  f"长上下文,分批提交,共{len(inputs)}部分...", OutputType.INFO
90
90
  )
91
- prefix_prompt = f"""
91
+ prefix_prompt = """
92
92
  我将分多次提供大量内容,在我明确告诉你内容已经全部提供完毕之前,每次仅需要输出"已收到",明白请输出"开始接收输入"。
93
93
  """
94
94
  while_true(lambda: while_success(lambda: self._chat(prefix_prompt), 5), 5)
@@ -194,7 +194,7 @@ class KimiModel(BasePlatform):
194
194
  uploaded_files = []
195
195
  for index, file_path in enumerate(file_list, 1):
196
196
  file_name = os.path.basename(file_path)
197
- log_lines: list[str] = [f"处理文件 [{index}/{len(file_list)}]: {file_name}"]
197
+ log_lines: List[str] = [f"处理文件 [{index}/{len(file_list)}]: {file_name}"]
198
198
  try:
199
199
  mime_type, _ = mimetypes.guess_type(file_path)
200
200
  action = (
@@ -39,7 +39,7 @@ class PlatformRegistry:
39
39
  # 创建 __init__.py 使其成为 Python 包
40
40
  with open(
41
41
  os.path.join(user_platform_dir, "__init__.py"), "w", errors="ignore"
42
- ) as f:
42
+ ):
43
43
  pass
44
44
  except Exception as e:
45
45
  PrettyOutput.print(f"创建平台目录失败: {str(e)}", OutputType.ERROR)
@@ -276,7 +276,7 @@ class TongyiPlatform(BasePlatform):
276
276
 
277
277
  for file_path in file_list:
278
278
  file_name = os.path.basename(file_path)
279
- log_lines: list[str] = []
279
+ log_lines: List[str] = []
280
280
  log_lines.append(f"上传文件 {file_name}")
281
281
  try:
282
282
  if not os.path.exists(file_path):
@@ -69,7 +69,6 @@ class YuanbaoPlatform(BasePlatform):
69
69
  "X-Requested-With": "XMLHttpRequest",
70
70
  "chat_version": "v1",
71
71
  "X-Instance-ID": "5",
72
- "X-Requested-With": "XMLHttpRequest",
73
72
  "Accept": "application/json, text/plain, */*",
74
73
  "Content-Type": "application/json",
75
74
  "sec-ch-ua-mobile": "?0",
@@ -134,7 +133,7 @@ class YuanbaoPlatform(BasePlatform):
134
133
 
135
134
  for file_path in file_list:
136
135
  file_name = os.path.basename(file_path)
137
- log_lines: list[str] = []
136
+ log_lines: List[str] = []
138
137
  log_lines.append(f"上传文件 {file_name}")
139
138
  try:
140
139
  # 1. Prepare the file information
@@ -10,7 +10,7 @@ import time
10
10
  import threading
11
11
  import uuid
12
12
  from datetime import datetime
13
- from typing import Any, Dict, List, Optional, Union
13
+ from typing import Any, Dict, List, Optional
14
14
 
15
15
  import uvicorn
16
16
  from fastapi import FastAPI, HTTPException
jarvis/jarvis_rag/cli.py CHANGED
@@ -1,7 +1,7 @@
1
1
  import os
2
2
  import sys
3
3
  from pathlib import Path
4
- from typing import Optional, List, Literal, cast, Tuple
4
+ from typing import Optional, List, Tuple
5
5
  import mimetypes
6
6
 
7
7
  import pathspec # type: ignore
@@ -43,7 +43,6 @@ class EmbeddingManager:
43
43
  try:
44
44
  # First try to load model from local cache without any network access
45
45
  try:
46
- from sentence_transformers import SentenceTransformer
47
46
  local_dir = None
48
47
  # Prefer explicit local dir via env or direct path
49
48
 
@@ -1,7 +1,4 @@
1
1
  from abc import ABC, abstractmethod
2
- import os
3
- import os
4
- from abc import ABC, abstractmethod
5
2
 
6
3
  from jarvis.jarvis_agent import Agent as JarvisAgent
7
4
  from jarvis.jarvis_platform.base import BasePlatform
@@ -185,7 +185,7 @@ class ChromaRetriever:
185
185
  if not changed and not deleted:
186
186
  return
187
187
  # 为避免在循环中逐条打印,先拼接后统一打印
188
- lines: list[str] = []
188
+ lines: List[str] = []
189
189
  if changed:
190
190
  lines.append(
191
191
  f"检测到 {len(changed)} 个已索引文件发生变化,建议重新索引以保证检索准确性。"
@@ -247,7 +247,7 @@ class ChromaRetriever:
247
247
  return
248
248
 
249
249
  # 先处理删除
250
- delete_errors: list[str] = []
250
+ delete_errors: List[str] = []
251
251
  for src in deleted:
252
252
  try:
253
253
  self.collection.delete(where={"source": src}) # type: ignore[arg-type]
@@ -258,7 +258,7 @@ class ChromaRetriever:
258
258
 
259
259
  # 再处理变更(重建)
260
260
  docs_to_add: List[Document] = []
261
- rebuild_errors: list[str] = []
261
+ rebuild_errors: List[str] = []
262
262
  for src in changed:
263
263
  try:
264
264
  # 删除旧条目
@@ -1,7 +1,6 @@
1
1
  #!/usr/bin/env python3
2
2
  # -*- coding: utf-8 -*-
3
3
  import os
4
- import sys
5
4
  from typing import Optional, Tuple
6
5
 
7
6
  import typer
@@ -16,7 +16,6 @@ from pathlib import Path
16
16
  from .stats import StatsManager
17
17
  from jarvis.jarvis_utils.utils import init_env
18
18
  from jarvis.jarvis_utils.config import get_data_dir
19
- from jarvis.jarvis_utils.output import OutputType, PrettyOutput
20
19
 
21
20
  app = typer.Typer(help="Jarvis 统计模块命令行工具")
22
21
  console = Console()
@@ -310,7 +309,7 @@ def remove(
310
309
  unit = info.get("unit", "-")
311
310
  last_updated = info.get("last_updated", "-")
312
311
 
313
- rprint(f"\n[yellow]准备删除指标:[/yellow]")
312
+ rprint("\n[yellow]准备删除指标:[/yellow]")
314
313
  rprint(f" 名称: {metric}")
315
314
  rprint(f" 单位: {unit}")
316
315
  rprint(f" 最后更新: {last_updated}")
@@ -340,7 +339,7 @@ def demo():
340
339
  stats = StatsManager(_get_stats_dir())
341
340
 
342
341
  # 添加演示数据
343
- with console.status("[bold green]正在生成演示数据...") as status:
342
+ with console.status("[bold green]正在生成演示数据..."):
344
343
  # API响应时间
345
344
  for i in range(20):
346
345
  response_time = random.uniform(0.1, 2.0)