jarvis-ai-assistant 0.1.220__py3-none-any.whl → 0.1.222__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 (32) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +110 -395
  3. jarvis/jarvis_agent/edit_file_handler.py +32 -185
  4. jarvis/jarvis_agent/jarvis.py +14 -9
  5. jarvis/jarvis_agent/main.py +13 -6
  6. jarvis/jarvis_agent/prompt_builder.py +57 -0
  7. jarvis/jarvis_agent/prompts.py +188 -0
  8. jarvis/jarvis_agent/protocols.py +30 -0
  9. jarvis/jarvis_agent/session_manager.py +84 -0
  10. jarvis/jarvis_agent/tool_executor.py +49 -0
  11. jarvis/jarvis_code_agent/code_agent.py +14 -23
  12. jarvis/jarvis_code_analysis/code_review.py +1 -1
  13. jarvis/jarvis_data/config_schema.json +13 -18
  14. jarvis/jarvis_git_details/main.py +1 -1
  15. jarvis/jarvis_platform/kimi.py +4 -2
  16. jarvis/jarvis_rag/__init__.py +2 -2
  17. jarvis/jarvis_rag/cache.py +28 -30
  18. jarvis/jarvis_rag/cli.py +141 -52
  19. jarvis/jarvis_rag/embedding_manager.py +32 -46
  20. jarvis/jarvis_rag/llm_interface.py +32 -34
  21. jarvis/jarvis_rag/query_rewriter.py +11 -12
  22. jarvis/jarvis_rag/rag_pipeline.py +40 -43
  23. jarvis/jarvis_rag/reranker.py +18 -18
  24. jarvis/jarvis_rag/retriever.py +29 -29
  25. jarvis/jarvis_tools/edit_file.py +11 -36
  26. jarvis/jarvis_utils/config.py +20 -25
  27. {jarvis_ai_assistant-0.1.220.dist-info → jarvis_ai_assistant-0.1.222.dist-info}/METADATA +25 -20
  28. {jarvis_ai_assistant-0.1.220.dist-info → jarvis_ai_assistant-0.1.222.dist-info}/RECORD +32 -27
  29. {jarvis_ai_assistant-0.1.220.dist-info → jarvis_ai_assistant-0.1.222.dist-info}/entry_points.txt +9 -0
  30. {jarvis_ai_assistant-0.1.220.dist-info → jarvis_ai_assistant-0.1.222.dist-info}/WHEEL +0 -0
  31. {jarvis_ai_assistant-0.1.220.dist-info → jarvis_ai_assistant-0.1.222.dist-info}/licenses/LICENSE +0 -0
  32. {jarvis_ai_assistant-0.1.220.dist-info → jarvis_ai_assistant-0.1.222.dist-info}/top_level.txt +0 -0
@@ -9,6 +9,16 @@ from typing import Any, Callable, Dict, List, Optional, Protocol, Tuple, Union
9
9
 
10
10
  # 本地库导入
11
11
  # jarvis_agent 相关
12
+ from jarvis.jarvis_agent.prompt_builder import build_action_prompt
13
+ from jarvis.jarvis_agent.protocols import OutputHandlerProtocol
14
+ from jarvis.jarvis_agent.session_manager import SessionManager
15
+ from jarvis.jarvis_agent.tool_executor import execute_tool_call
16
+ from jarvis.jarvis_agent.prompts import (
17
+ DEFAULT_SUMMARY_PROMPT,
18
+ SUMMARY_REQUEST_PROMPT,
19
+ TASK_ANALYSIS_PROMPT,
20
+ )
21
+
12
22
  # jarvis_platform 相关
13
23
  from jarvis.jarvis_platform.base import BasePlatform
14
24
  from jarvis.jarvis_platform.registry import PlatformRegistry
@@ -16,6 +26,10 @@ from jarvis.jarvis_platform.registry import PlatformRegistry
16
26
  # jarvis_utils 相关
17
27
  from jarvis.jarvis_utils.config import (
18
28
  get_max_token_count,
29
+ get_normal_model_name,
30
+ get_normal_platform_name,
31
+ get_thinking_model_name,
32
+ get_thinking_platform_name,
19
33
  is_execute_tool_confirm,
20
34
  is_use_analysis,
21
35
  is_use_methodology,
@@ -67,32 +81,12 @@ origin_agent_system_prompt = f"""
67
81
  """
68
82
 
69
83
 
70
- class OutputHandlerProtocol(Protocol):
71
- def name(self) -> str:
72
- ...
73
-
74
- def can_handle(self, response: str) -> bool:
75
- ...
76
-
77
- def prompt(self) -> str:
78
- ...
79
-
80
- def handle(self, response: str, agent: Any) -> Tuple[bool, Any]:
81
- ...
82
-
83
-
84
84
  class Agent:
85
85
  def clear(self):
86
- """清除当前对话历史,保留系统消息。
87
-
88
- 该方法将:
89
- 1. 调用模型的delete_chat方法清除对话历史
90
- 2. 重置对话长度计数器
91
- 3. 清空当前提示
92
86
  """
93
- self.model.reset() # type: ignore
94
- self.conversation_length = 0
95
- self.prompt = ""
87
+ Clears the current conversation history by delegating to the session manager.
88
+ """
89
+ self.session.clear()
96
90
 
97
91
  def __del__(self):
98
92
  # 只有在记录启动时才停止记录
@@ -103,8 +97,7 @@ class Agent:
103
97
  system_prompt: str,
104
98
  name: str = "Jarvis",
105
99
  description: str = "",
106
- platform: Union[Optional[BasePlatform], Optional[str]] = None,
107
- model_name: Optional[str] = None,
100
+ llm_type: str = "normal",
108
101
  summary_prompt: Optional[str] = None,
109
102
  auto_complete: bool = False,
110
103
  output_handler: List[OutputHandlerProtocol] = [],
@@ -124,8 +117,7 @@ class Agent:
124
117
  system_prompt: 系统提示词,定义Agent的行为准则
125
118
  name: Agent名称,默认为"Jarvis"
126
119
  description: Agent描述信息
127
- platform: 平台实例或平台名称字符串
128
- model_name: 使用的模型名称
120
+ llm_type: LLM类型,可以是 'normal' 或 'thinking'
129
121
  summary_prompt: 任务总结提示模板
130
122
  auto_complete: 是否自动完成任务
131
123
  output_handler: 输出处理器列表
@@ -140,26 +132,30 @@ class Agent:
140
132
  self.name = make_agent_name(name)
141
133
  self.description = description
142
134
  # 初始化平台和模型
143
- if platform is not None:
144
- if isinstance(platform, str):
145
- self.model = PlatformRegistry().create_platform(platform)
146
- if self.model is None:
147
- PrettyOutput.print(f"平台 {platform} 不存在,将使用普通模型", OutputType.WARNING)
148
- self.model = PlatformRegistry().get_normal_platform()
149
- else:
150
- self.model = platform
151
- else:
152
- self.model = (
153
- PlatformRegistry.get_global_platform_registry().get_normal_platform()
135
+ if llm_type == "thinking":
136
+ platform_name = get_thinking_platform_name()
137
+ model_name = get_thinking_model_name()
138
+ else: # 默认为 normal
139
+ platform_name = get_normal_platform_name()
140
+ model_name = get_normal_model_name()
141
+
142
+ self.model = PlatformRegistry().create_platform(platform_name)
143
+ if self.model is None:
144
+ PrettyOutput.print(
145
+ f"平台 {platform_name} 不存在,将使用普通模型", OutputType.WARNING
154
146
  )
147
+ self.model = PlatformRegistry().get_normal_platform()
155
148
 
156
- if model_name is not None:
149
+ if model_name:
157
150
  self.model.set_model_name(model_name)
158
151
 
159
152
  self.user_data: Dict[str, Any] = {}
160
153
 
161
154
  self.model.set_suppress_output(False)
162
155
 
156
+ # Initialize the session manager
157
+ self.session = SessionManager(model=self.model, agent_name=self.name)
158
+
163
159
  from jarvis.jarvis_tools.registry import ToolRegistry
164
160
 
165
161
  self.output_handler = output_handler if output_handler else [ToolRegistry()]
@@ -180,13 +176,10 @@ class Agent:
180
176
  self.use_analysis = (
181
177
  use_analysis if use_analysis is not None else is_use_analysis()
182
178
  )
183
- self.prompt = ""
184
- self.conversation_length = 0 # Use length counter instead
185
179
  self.system_prompt = system_prompt
186
180
  self.input_handler = input_handler if input_handler is not None else []
187
181
  self.need_summary = need_summary
188
182
  # Load configuration from environment variables
189
- self.addon_prompt = ""
190
183
 
191
184
  self.after_tool_call_cb: Optional[Callable[[Agent], None]] = None
192
185
 
@@ -197,24 +190,7 @@ class Agent:
197
190
  )
198
191
 
199
192
  self.summary_prompt = (
200
- summary_prompt
201
- if summary_prompt
202
- else f"""<report>
203
- 请生成任务执行的简明总结报告,包括:
204
-
205
- <content>
206
- 1. 任务目标:任务重述
207
- 2. 执行结果:成功/失败
208
- 3. 关键信息:执行过程中提取的重要信息
209
- 4. 重要发现:任何值得注意的发现
210
- 5. 后续建议:如果有的话
211
- </content>
212
-
213
- <format>
214
- 请使用简洁的要点描述,突出重要信息。
215
- </format>
216
- </report>
217
- """
193
+ summary_prompt if summary_prompt else DEFAULT_SUMMARY_PROMPT
218
194
  )
219
195
 
220
196
  self.max_token_count = get_max_token_count()
@@ -223,46 +199,7 @@ class Agent:
223
199
 
224
200
  PrettyOutput.print(welcome_message, OutputType.SYSTEM)
225
201
 
226
- action_prompt = """
227
- <actions>
228
- # 🧰 可用操作
229
- 以下是您可以使用的操作:
230
- """
231
-
232
- # 添加工具列表概览
233
- action_prompt += "\n<overview>\n## Action List\n"
234
- action_prompt += (
235
- "[" + ", ".join([handler.name() for handler in self.output_handler]) + "]"
236
- )
237
- action_prompt += "\n</overview>"
238
-
239
- # 添加每个工具的详细说明
240
- action_prompt += "\n\n<details>\n# 📝 Action Details\n"
241
- for handler in self.output_handler:
242
- action_prompt += f"\n<tool>\n## {handler.name()}\n"
243
- # 获取工具的提示词并确保格式正确
244
- handler_prompt = handler.prompt().strip()
245
- # 调整缩进以保持层级结构
246
- handler_prompt = "\n".join(
247
- " " + line if line.strip() else line
248
- for line in handler_prompt.split("\n")
249
- )
250
- action_prompt += handler_prompt + "\n</tool>\n"
251
-
252
- # 添加工具使用总结
253
- action_prompt += """
254
- </details>
255
-
256
- <rules>
257
- # ❗ 重要操作使用规则
258
- 1. 一次对话只能使用一个操作,否则会出错
259
- 2. 严格按照每个操作的格式执行
260
- 3. 等待操作结果后再进行下一个操作
261
- 4. 处理完结果后再调用新的操作
262
- 5. 如果对操作使用不清楚,请请求帮助
263
- </rules>
264
- </actions>
265
- """
202
+ action_prompt = build_action_prompt(self.output_handler) # type: ignore
266
203
 
267
204
  self.model.set_system_prompt(
268
205
  f"""
@@ -274,12 +211,12 @@ class Agent:
274
211
  self.first = True
275
212
 
276
213
  def set_user_data(self, key: str, value: Any):
277
- """设置用户数据"""
278
- self.user_data[key] = value
214
+ """Sets user data in the session."""
215
+ self.session.set_user_data(key, value)
279
216
 
280
217
  def get_user_data(self, key: str) -> Optional[Any]:
281
- """获取用户数据"""
282
- return self.user_data.get(key, None)
218
+ """Gets user data from the session."""
219
+ return self.session.get_user_data(key)
283
220
 
284
221
  def set_use_tools(self, use_tools):
285
222
  """设置要使用的工具列表"""
@@ -292,12 +229,8 @@ class Agent:
292
229
  break
293
230
 
294
231
  def set_addon_prompt(self, addon_prompt: str):
295
- """设置附加提示。
296
-
297
- 参数:
298
- addon_prompt: 附加提示内容
299
- """
300
- self.addon_prompt = addon_prompt
232
+ """Sets the addon prompt in the session."""
233
+ self.session.set_addon_prompt(addon_prompt)
301
234
 
302
235
  def set_after_tool_call_cb(self, cb: Callable[[Any], None]): # type: ignore
303
236
  """设置工具调用后回调函数。
@@ -308,39 +241,13 @@ class Agent:
308
241
  self.after_tool_call_cb = cb
309
242
 
310
243
  def save_session(self) -> bool:
311
- """保存当前会话状态到文件"""
312
- if not self.model:
313
- PrettyOutput.print("没有可用的模型实例来保存会话。", OutputType.ERROR)
314
- return False
315
- session_dir = os.path.join(os.getcwd(), ".jarvis")
316
- os.makedirs(session_dir, exist_ok=True)
317
- platform_name = self.model.platform_name()
318
- model_name = self.model.name().replace("/", "_").replace("\\", "_")
319
- session_file = os.path.join(
320
- session_dir, f"saved_session_{self.name}_{platform_name}_{model_name}.json"
321
- )
322
- return self.model.save(session_file)
244
+ """Saves the current session state by delegating to the session manager."""
245
+ return self.session.save_session()
323
246
 
324
247
  def restore_session(self) -> bool:
325
- """从文件恢复会话状态"""
326
- if not self.model:
327
- return False # No model, cannot restore
328
- platform_name = self.model.platform_name()
329
- model_name = self.model.name().replace("/", "_").replace("\\", "_")
330
- session_file = os.path.join(
331
- os.getcwd(),
332
- ".jarvis",
333
- f"saved_session_{self.name}_{platform_name}_{model_name}.json",
334
- )
335
- if not os.path.exists(session_file):
336
- return False
337
-
338
- if self.model.restore(session_file):
339
- try:
340
- os.remove(session_file)
341
- PrettyOutput.print("会话已恢复,并已删除会话文件。", OutputType.SUCCESS)
342
- except OSError as e:
343
- PrettyOutput.print(f"删除会话文件失败: {e}", OutputType.ERROR)
248
+ """Restores the session state by delegating to the session manager."""
249
+ if self.session.restore_session():
250
+ self.first = False
344
251
  return True
345
252
  return False
346
253
 
@@ -374,21 +281,23 @@ class Agent:
374
281
  if need_return:
375
282
  return message
376
283
 
377
- if self.addon_prompt:
378
- message += f"\n\n{self.addon_prompt}"
379
- self.addon_prompt = ""
284
+ if self.session.addon_prompt:
285
+ message += f"\n\n{self.session.addon_prompt}"
286
+ self.session.addon_prompt = ""
380
287
  else:
381
288
  message += f"\n\n{self.make_default_addon_prompt(need_complete)}"
382
289
 
383
290
  # 累加对话长度
384
- self.conversation_length += get_context_token_count(message)
291
+ self.session.conversation_length += get_context_token_count(message)
385
292
 
386
- if self.conversation_length > self.max_token_count:
293
+ if self.session.conversation_length > self.max_token_count:
387
294
  message = self._summarize_and_clear_history() + "\n\n" + message
388
- self.conversation_length += get_context_token_count(message)
295
+ self.session.conversation_length += get_context_token_count(message)
389
296
 
297
+ if not self.model:
298
+ raise RuntimeError("Model not initialized")
390
299
  response = self.model.chat_until_success(message) # type: ignore
391
- self.conversation_length += get_context_token_count(response)
300
+ self.session.conversation_length += get_context_token_count(response)
392
301
 
393
302
  return response
394
303
 
@@ -402,31 +311,12 @@ class Agent:
402
311
  仅生成摘要,不修改对话状态
403
312
  """
404
313
  print("📄 正在总结对话历史...")
405
- summary_prompt = """
406
- <summary_request>
407
- <objective>
408
- 请对当前对话历史进行简明扼要的总结,提取关键信息和重要决策点。这个总结将作为上下文继续任务,因此需要保留对后续对话至关重要的内容。
409
- </objective>
410
-
411
- <guidelines>
412
- 1. 提取关键信息:任务目标、已确定的事实、重要决策、达成的共识
413
- 2. 保留技术细节:命令、代码片段、文件路径、配置设置等技术细节
414
- 3. 记录任务进展:已完成的步骤、当前所处阶段、待解决的问题
415
- 4. 包含用户偏好:用户表达的明确偏好、限制条件或特殊要求
416
- 5. 省略冗余内容:问候语、重复信息、不相关的讨论
417
- </guidelines>
418
-
419
- <format>
420
- - 使用简洁、客观的语言
421
- - 按时间顺序或主题组织信息
422
- - 使用要点列表增强可读性
423
- - 总结应控制在500词以内
424
- </format>
425
- </summary_request>
426
- """
427
-
428
314
  try:
429
- summary = self.model.chat_until_success(self.prompt + "\n" + summary_prompt) # type: ignore
315
+ if not self.model:
316
+ raise RuntimeError("Model not initialized")
317
+ summary = self.model.chat_until_success(
318
+ self.session.prompt + "\n" + SUMMARY_REQUEST_PROMPT
319
+ ) # type: ignore
430
320
  print("✅ 总结对话历史完成")
431
321
  return summary
432
322
  except Exception as e:
@@ -486,46 +376,10 @@ class Agent:
486
376
  os.remove(tmp_file_name)
487
377
 
488
378
  def _call_tools(self, response: str) -> Tuple[bool, Any]:
489
- """调用工具执行响应
490
-
491
- 参数:
492
- response: 包含工具调用信息的响应字符串
493
-
494
- 返回:
495
- Tuple[bool, Any]:
496
- - 第一个元素表示是否需要返回结果
497
- - 第二个元素是返回结果或错误信息
498
-
499
- 注意:
500
- 1. 一次只能执行一个工具
501
- 2. 如果配置了确认选项,会在执行前请求用户确认
502
- 3. 使用spinner显示执行状态
503
379
  """
504
- tool_list = []
505
- for handler in self.output_handler:
506
- if handler.can_handle(response):
507
- tool_list.append(handler)
508
- if len(tool_list) > 1:
509
- PrettyOutput.print(
510
- f"操作失败:检测到多个操作。一次只能执行一个操作。尝试执行的操作:{', '.join([handler.name() for handler in tool_list])}",
511
- OutputType.WARNING,
512
- )
513
- return (
514
- False,
515
- f"操作失败:检测到多个操作。一次只能执行一个操作。尝试执行的操作:{', '.join([handler.name() for handler in tool_list])}",
516
- )
517
- if len(tool_list) == 0:
518
- return False, ""
519
-
520
- if not self.execute_tool_confirm or user_confirm(
521
- f"需要执行{tool_list[0].name()}确认执行?", True
522
- ):
523
- print(f"🔧 正在执行{tool_list[0].name()}...")
524
- result = tool_list[0].handle(response, self)
525
- print(f"✅ {tool_list[0].name()}执行完成")
526
-
527
- return result
528
- return False, ""
380
+ Delegates the tool execution to the external `execute_tool_call` function.
381
+ """
382
+ return execute_tool_call(response, self)
529
383
 
530
384
  def _complete_task(self) -> str:
531
385
  """完成任务并生成总结(如果需要)
@@ -542,8 +396,10 @@ class Agent:
542
396
  self._analysis_task()
543
397
  if self.need_summary:
544
398
  print("📄 正在生成总结...")
545
- self.prompt = self.summary_prompt
546
- ret = self.model.chat_until_success(self.prompt) # type: ignore
399
+ self.session.prompt = self.summary_prompt
400
+ if not self.model:
401
+ raise RuntimeError("Model not initialized")
402
+ ret = self.model.chat_until_success(self.session.prompt) # type: ignore
547
403
  print("✅ 总结生成完成")
548
404
  return ret
549
405
 
@@ -553,154 +409,12 @@ class Agent:
553
409
  print("🔍 正在分析任务...")
554
410
  try:
555
411
  # 让模型判断是否需要生成方法论
556
- analysis_prompt = f"""<task_analysis>
557
- <request>
558
- 当前任务已结束,请分析该任务的解决方案:
559
- 1. 首先检查现有工具或方法论是否已经可以完成该任务,如果可以,直接说明即可,无需生成新内容
560
- 2. 如果现有工具/方法论不足,评估当前任务是否可以通过编写新工具来自动化解决
561
- 3. 如果可以通过工具解决,请设计并提供工具代码
562
- 4. 如果无法通过编写通用工具完成,评估当前的执行流程是否可以总结为通用方法论
563
- 5. 如果以上都不可行,给出详细理由
564
- 请根据分析结果采取相应行动:说明现有工具/方法论、创建新工具、生成新方法论或说明原因。
565
- </request>
566
- <evaluation_criteria>
567
- 现有资源评估:
568
- 1. 现有工具 - 检查系统中是否已有可以完成该任务的工具
569
- 2. 现有方法论 - 检查是否已有适用于该任务的方法论
570
- 3. 组合使用 - 评估现有工具和方法论组合使用是否可以解决问题
571
- 工具评估标准:
572
- 1. 通用性 - 该工具是否可以解决一类问题,而不仅仅是当前特定问题
573
- 2. 自动化 - 该工具是否可以减少人工干预,提高效率
574
- 3. 可靠性 - 该工具是否可以在不同场景下稳定工作
575
- 4. 简单性 - 该工具是否易于使用,参数设计是否合理
576
- 方法论评估标准:
577
- 1. 方法论应聚焦于通用且可重复的解决方案流程
578
- 2. 方法论应该具备足够的通用性,可应用于同类问题
579
- 3. 特别注意用户在执行过程中提供的修正、反馈和改进建议
580
- 4. 如果用户明确指出了某个解决步骤的优化方向,这应该被纳入方法论
581
- 5. 方法论要严格按照实际的执行流程来总结,不要遗漏或增加任何步骤
582
- </evaluation_criteria>
583
- <tool_requirements>
584
- 工具代码要求:
585
- 1. 工具类名应与工具名称保持一致
586
- 2. 必须包含name、description、parameters属性
587
- 3. 必须实现execute方法处理输入参数
588
- 4. 可选实现check方法验证环境
589
- 5. 工具描述应详细说明用途、适用场景和使用示例
590
- 6. 参数定义应遵循JSON Schema格式
591
- 7. 不要包含特定任务的细节,保持通用性
592
- 工具设计关键点:
593
- 1. **使用PrettyOutput打印执行过程**:强烈建议在工具中使用PrettyOutput显示执行过程,
594
- 这样用户可以了解工具在做什么,提升用户体验。示例:
595
- ```python
596
- from jarvis.jarvis_utils.output import PrettyOutput, OutputType
597
- # 执行中打印信息
598
- PrettyOutput.print("正在处理数据...", OutputType.INFO)
599
- # 成功信息
600
- PrettyOutput.print("操作成功完成", OutputType.SUCCESS)
601
- # 警告信息
602
- PrettyOutput.print("发现潜在问题", OutputType.WARNING)
603
- # 错误信息
604
- PrettyOutput.print("操作失败", OutputType.ERROR)
605
- ```
606
- 2. **结构化返回结果**:工具应该始终返回结构化的结果字典,包含以下字段:
607
- - success: 布尔值,表示操作是否成功
608
- - stdout: 字符串,包含工具的主要输出内容
609
- - stderr: 字符串,包含错误信息(如果有)
610
- 3. **异常处理**:工具应该妥善处理可能发生的异常,并在失败时清理已创建的资源
611
- ```python
612
- try:
613
- # 执行逻辑
614
- return {{
615
- "success": True,
616
- "stdout": "成功结果",
617
- "stderr": ""
618
- }}
619
- except Exception as e:
620
- PrettyOutput.print(f"操作失败: {{str(e)}}", OutputType.ERROR)
621
- # 清理资源(如果有创建)
622
- return {{
623
- "success": False,
624
- "stdout": "",
625
- "stderr": f"操作失败: {{str(e)}}"
626
- }}
627
- ```
628
- </tool_requirements>
629
- <methodology_requirements>
630
- 方法论格式要求:
631
- 1. 问题重述: 简明扼要的问题归纳,不含特定细节
632
- 2. 最优解决方案: 经过用户验证的、最终有效的解决方案(将每个步骤要使用的工具也列举出来)
633
- 3. 注意事项: 执行中可能遇到的常见问题和注意点,尤其是用户指出的问题
634
- 4. 可选步骤: 对于有多种解决路径的问题,标注出可选步骤和适用场景
635
- </methodology_requirements>
636
- <output_requirements>
637
- 根据分析结果,输出以下三种情况之一:
638
- 1. 如果现有工具/方法论可以解决,直接输出说明:
639
- 已有工具/方法论可以解决该问题,无需创建新内容。
640
- 可用的工具/方法论:[列出工具名称或方法论名称]
641
- 使用方法:[简要说明如何使用]
642
- 2. 工具创建(如果需要创建新工具):
643
- {ot("TOOL_CALL")}
644
- want: 创建新工具来解决XXX问题
645
- name: generate_new_tool
646
- arguments:
647
- tool_name: 工具名称
648
- tool_code: |2
649
- # -*- coding: utf-8 -*-
650
- from typing import Dict, Any
651
- from jarvis.jarvis_utils.output import PrettyOutput, OutputType
652
- class 工具名称:
653
- name = "工具名称"
654
- description = "Tool for text transformation"
655
- Tool description
656
- 适用场景:1. 格式化文本; 2. 处理标题; 3. 标准化输出
657
- \"\"\"
658
- parameters = {{
659
- "type": "object",
660
- "properties": {{
661
- # 参数定义
662
- }},
663
- "required": []
664
- }}
665
- @staticmethod
666
- def check() -> bool:
667
- return True
668
- def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
669
- try:
670
- # 使用PrettyOutput显示执行过程
671
- PrettyOutput.print("开始执行操作...", OutputType.INFO)
672
- # 实现逻辑
673
- # ...
674
- PrettyOutput.print("操作已完成", OutputType.SUCCESS)
675
- return {{
676
- "success": True,
677
- "stdout": "结果输出",
678
- "stderr": ""
679
- }}
680
- except Exception as e:
681
- PrettyOutput.print(f"操作失败: {{str(e)}}", OutputType.ERROR)
682
- return {{
683
- "success": False,
684
- "stdout": "",
685
- "stderr": f"操作失败: {{str(e)}}"
686
- }}
687
- {ct("TOOL_CALL")}
688
- 3. 方法论创建(如果需要创建新方法论):
689
- {ot("TOOL_CALL")}
690
- want: 添加/更新xxxx的方法论
691
- name: methodology
692
- arguments:
693
- operation: add/update
694
- problem_type: 方法论类型,不要过于细节,也不要过于泛化
695
- content: |2
696
- 方法论内容
697
- {ct("TOOL_CALL")}
698
- 如果以上三种情况都不适用,则直接输出原因分析,不要使用工具调用格式。
699
- </output_requirements>
700
- </task_analysis>"""
701
-
702
- self.prompt = analysis_prompt
703
- response = self.model.chat_until_success(self.prompt) # type: ignore
412
+ analysis_prompt = TASK_ANALYSIS_PROMPT
413
+
414
+ self.session.prompt = analysis_prompt
415
+ if not self.model:
416
+ raise RuntimeError("Model not initialized")
417
+ response = self.model.chat_until_success(self.session.prompt) # type: ignore
704
418
  self._call_tools(response)
705
419
  print("✅ 分析完成")
706
420
  except Exception as e:
@@ -756,7 +470,7 @@ arguments:
756
470
  4. 自动加载相关方法论(如果是首次运行)
757
471
  """
758
472
 
759
- self.prompt = f"{user_input}"
473
+ self.session.prompt = f"{user_input}"
760
474
  try:
761
475
  set_agent(self.name, self)
762
476
 
@@ -764,33 +478,41 @@ arguments:
764
478
  if self.first:
765
479
  self._first_run()
766
480
  try:
767
- current_response = self._call_model(self.prompt, True)
768
- self.prompt = ""
481
+ current_response = self._call_model(self.session.prompt, True)
482
+ self.session.prompt = ""
769
483
 
770
484
  if get_interrupt():
771
485
  set_interrupt(False)
772
- user_input = self.multiline_inputer(f"模型交互期间被中断,请输入用户干预信息:")
486
+ user_input = self.multiline_inputer(
487
+ f"模型交互期间被中断,请输入用户干预信息:"
488
+ )
773
489
  if user_input:
774
490
  # 如果有工具调用且用户确认继续,则将干预信息和工具执行结果拼接为prompt
775
491
  if any(
776
492
  handler.can_handle(current_response)
777
493
  for handler in self.output_handler
778
494
  ):
779
- if user_confirm("检测到有工具调用,是否继续处理工具调用?", True):
780
- self.prompt = f"{user_input}\n\n{current_response}"
495
+ if user_confirm(
496
+ "检测到有工具调用,是否继续处理工具调用?", True
497
+ ):
498
+ self.session.prompt = (
499
+ f"{user_input}\n\n{current_response}"
500
+ )
781
501
  continue
782
- self.prompt += f"{user_input}"
502
+ self.session.prompt += f"{user_input}"
783
503
  continue
784
504
 
785
- need_return, self.prompt = self._call_tools(current_response)
505
+ need_return, self.session.prompt = self._call_tools(
506
+ current_response
507
+ )
786
508
 
787
509
  if need_return:
788
- return self.prompt
510
+ return self.session.prompt
789
511
 
790
512
  if self.after_tool_call_cb:
791
513
  self.after_tool_call_cb(self)
792
514
 
793
- if self.prompt or self.addon_prompt:
515
+ if self.session.prompt or self.session.addon_prompt:
794
516
  continue
795
517
 
796
518
  if self.auto_complete and ot("!!!COMPLETE!!!") in current_response:
@@ -802,7 +524,7 @@ arguments:
802
524
  )
803
525
 
804
526
  if user_input:
805
- self.prompt = user_input
527
+ self.session.prompt = user_input
806
528
  continue
807
529
 
808
530
  if not user_input:
@@ -822,46 +544,39 @@ arguments:
822
544
  if self.use_methodology:
823
545
  if not upload_methodology(self.model, other_files=self.files):
824
546
  if self.files:
825
- PrettyOutput.print("文件上传失败,将忽略文件列表", OutputType.WARNING)
547
+ PrettyOutput.print(
548
+ "文件上传失败,将忽略文件列表", OutputType.WARNING
549
+ )
826
550
  # 上传失败则回退到本地加载
827
- msg = self.prompt
551
+ msg = self.session.prompt
828
552
  for handler in self.input_handler:
829
553
  msg, _ = handler(msg, self)
830
- self.prompt = f"{self.prompt}\n\n以下是历史类似问题的执行经验,可参考:\n{load_methodology(msg, self.get_tool_registry())}"
554
+ self.session.prompt = f"{self.session.prompt}\n\n以下是历史类似问题的执行经验,可参考:\n{load_methodology(msg, self.get_tool_registry())}"
831
555
  else:
832
556
  if self.files:
833
- self.prompt = (
834
- f"{self.prompt}\n\n上传的文件包含历史对话信息和方法论文件,可以从中获取一些经验信息。"
835
- )
557
+ self.session.prompt = f"{self.session.prompt}\n\n上传的文件包含历史对话信息和方法论文件,可以从中获取一些经验信息。"
836
558
  else:
837
- self.prompt = f"{self.prompt}\n\n上传的文件包含历史对话信息,可以从中获取一些经验信息。"
559
+ self.session.prompt = f"{self.session.prompt}\n\n上传的文件包含历史对话信息,可以从中获取一些经验信息。"
838
560
  elif self.files:
839
561
  if not self.model.upload_files(self.files):
840
- PrettyOutput.print("文件上传失败,将忽略文件列表", OutputType.WARNING)
562
+ PrettyOutput.print(
563
+ "文件上传失败,将忽略文件列表", OutputType.WARNING
564
+ )
841
565
  else:
842
- self.prompt = f"{self.prompt}\n\n上传的文件包含历史对话信息,可以从中获取一些经验信息。"
566
+ self.session.prompt = f"{self.session.prompt}\n\n上传的文件包含历史对话信息,可以从中获取一些经验信息。"
843
567
  else:
844
568
  if self.files:
845
569
  PrettyOutput.print("不支持上传文件,将忽略文件列表", OutputType.WARNING)
846
570
  if self.use_methodology:
847
- msg = self.prompt
571
+ msg = self.session.prompt
848
572
  for handler in self.input_handler:
849
573
  msg, _ = handler(msg, self)
850
- self.prompt = f"{self.prompt}\n\n以下是历史类似问题的执行经验,可参考:\n{load_methodology(msg, self.get_tool_registry())}"
574
+ self.session.prompt = f"{self.session.prompt}\n\n以下是历史类似问题的执行经验,可参考:\n{load_methodology(msg, self.get_tool_registry())}"
851
575
 
852
576
  self.first = False
853
577
 
854
578
  def clear_history(self):
855
- """清空对话历史但保留系统提示
856
-
857
- 该方法将:
858
- 1. 清空当前提示
859
- 2. 重置模型状态
860
- 3. 重置对话长度计数器
861
-
862
- 注意:
863
- 用于重置Agent状态而不影响系统消息
864
579
  """
865
- self.prompt = ""
866
- self.model.reset() # type: ignore
867
- self.conversation_length = 0 # 重置对话长度
580
+ Clears conversation history by delegating to the session manager.
581
+ """
582
+ self.session.clear_history()