jarvis-ai-assistant 0.1.195__py3-none-any.whl → 0.1.196__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.
jarvis/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  """Jarvis AI Assistant"""
3
3
 
4
- __version__ = "0.1.195"
4
+ __version__ = "0.1.196"
@@ -1,6 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  # 标准库导入
3
3
  import datetime
4
+ import os
4
5
  from pathlib import Path
5
6
  import platform
6
7
  from typing import Any, Callable, Dict, List, Optional, Protocol, Tuple, Union
@@ -18,7 +19,7 @@ from jarvis.jarvis_utils.config import (get_data_dir, get_max_token_count,
18
19
  get_max_tool_call_count,
19
20
  is_auto_complete,
20
21
  is_execute_tool_confirm,
21
- is_use_analysis, is_use_methodology)
22
+ is_use_analysis, get_history_count, is_use_methodology)
22
23
  from jarvis.jarvis_utils.embedding import get_context_token_count
23
24
  from jarvis.jarvis_utils.globals import (delete_agent, get_interrupt,
24
25
  make_agent_name, set_agent,
@@ -159,6 +160,7 @@ class Agent:
159
160
  use_methodology: Optional[bool] = None,
160
161
  use_analysis: Optional[bool] = None,
161
162
  files: List[str] = [],
163
+ history_count: Optional[int] = None,
162
164
  ):
163
165
  self.files = files
164
166
  """初始化Jarvis Agent实例
@@ -238,7 +240,11 @@ class Agent:
238
240
  self.after_tool_call_cb: Optional[Callable[[Agent], None]] = None
239
241
 
240
242
  self.history = JarvisHistory()
241
- self.history.start_record(str(Path(get_data_dir())/"history"))
243
+ self.history_dir = str(Path(get_data_dir())/"history")
244
+ self.history.start_record(self.history_dir)
245
+
246
+ self.history_count = history_count if history_count is not None else get_history_count()
247
+
242
248
 
243
249
  self.execute_tool_confirm = (
244
250
  execute_tool_confirm
@@ -782,31 +788,9 @@ arguments:
782
788
  set_agent(self.name, self)
783
789
 
784
790
  while True:
791
+ history_md = ""
785
792
  if self.first:
786
- # 如果有上传文件,先上传文件
787
- if self.model and self.model.support_upload_files():
788
- if self.use_methodology:
789
- if not upload_methodology(self.model, other_files=self.files):
790
- if self.files:
791
- PrettyOutput.print("文件上传失败,将忽略文件列表", OutputType.WARNING)
792
- # 上传失败则回退到本地加载
793
- msg = self.prompt
794
- for handler in self.input_handler:
795
- msg, _ = handler(msg, self)
796
- self.prompt = f"{self.prompt}\n\n以下是历史类似问题的执行经验,可参考:\n{load_methodology(msg, self.get_tool_registry())}"
797
- elif self.files:
798
- if not self.model.upload_files(self.files):
799
- PrettyOutput.print("文件上传失败,将忽略文件列表", OutputType.WARNING)
800
- else:
801
- if self.files:
802
- PrettyOutput.print("不支持上传文件,将忽略文件列表", OutputType.WARNING)
803
- if self.use_methodology:
804
- msg = self.prompt
805
- for handler in self.input_handler:
806
- msg, _ = handler(msg, self)
807
- self.prompt = f"{self.prompt}\n\n以下是历史类似问题的执行经验,可参考:\n{load_methodology(msg, self.get_tool_registry())}"
808
-
809
- self.first = False
793
+ history_md = self._first_run()
810
794
  try:
811
795
  current_response = self._call_model(self.prompt, True)
812
796
  self.prompt = ""
@@ -849,6 +833,8 @@ arguments:
849
833
  return self._complete_task()
850
834
 
851
835
  except Exception as e:
836
+ if history_md:
837
+ os.remove(history_md)
852
838
  PrettyOutput.print(f"任务失败: {str(e)}", OutputType.ERROR)
853
839
  return f"Task failed: {str(e)}"
854
840
 
@@ -856,6 +842,41 @@ arguments:
856
842
  PrettyOutput.print(f"任务失败: {str(e)}", OutputType.ERROR)
857
843
  return f"Task failed: {str(e)}"
858
844
 
845
+ def _first_run(self):
846
+ history_md = ""
847
+ if self.history_count > 0 and self.model and self.model.support_upload_files():
848
+ import tempfile
849
+ timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
850
+ history_md = str(Path(tempfile.gettempdir())/f"{self.name}_history_{timestamp}.md")
851
+ self.history.export_history_to_markdown(tempfile.gettempdir(), history_md, max_files=self.history_count)
852
+ self.files.append(history_md)
853
+
854
+ # 如果有上传文件,先上传文件
855
+ if self.model and self.model.support_upload_files():
856
+ if self.use_methodology:
857
+ if not upload_methodology(self.model, other_files=self.files):
858
+ if self.files:
859
+ PrettyOutput.print("文件上传失败,将忽略文件列表", OutputType.WARNING)
860
+ # 上传失败则回退到本地加载
861
+ msg = self.prompt
862
+ for handler in self.input_handler:
863
+ msg, _ = handler(msg, self)
864
+ self.prompt = f"{self.prompt}\n\n以下是历史类似问题的执行经验,可参考:\n{load_methodology(msg, self.get_tool_registry())}"
865
+ elif self.files:
866
+ if not self.model.upload_files(self.files):
867
+ PrettyOutput.print("文件上传失败,将忽略文件列表", OutputType.WARNING)
868
+ else:
869
+ if self.files:
870
+ PrettyOutput.print("不支持上传文件,将忽略文件列表", OutputType.WARNING)
871
+ if self.use_methodology:
872
+ msg = self.prompt
873
+ for handler in self.input_handler:
874
+ msg, _ = handler(msg, self)
875
+ self.prompt = f"{self.prompt}\n\n以下是历史类似问题的执行经验,可参考:\n{load_methodology(msg, self.get_tool_registry())}"
876
+
877
+ self.first = False
878
+ return history_md
879
+
859
880
  def clear_history(self):
860
881
  """清空对话历史但保留系统提示
861
882
 
@@ -201,6 +201,11 @@
201
201
  "description": "是否打印提示",
202
202
  "default": false
203
203
  },
204
+ "JARVIS_USE_HISTORY_COUNT": {
205
+ "type": "number",
206
+ "description": "使用的历史记录数量",
207
+ "default": 0
208
+ },
204
209
  "JARVIS_REPLACE_MAP": {
205
210
  "type": "object",
206
211
  "description": "自定义替换映射表配置",
@@ -265,6 +265,16 @@ def is_print_prompt() -> bool:
265
265
  return GLOBAL_CONFIG_DATA.get("JARVIS_PRINT_PROMPT", False) == True
266
266
 
267
267
 
268
+ def get_history_count() -> int:
269
+ """
270
+ 获取是否启用历史记录功能。
271
+
272
+ 返回:
273
+ bool: 如果启用历史记录则返回True,默认为False
274
+ """
275
+ return GLOBAL_CONFIG_DATA.get("JARVIS_USE_HISTORY_COUNT", 0)
276
+
277
+
268
278
  def get_mcp_config() -> List[Dict[str, Any]]:
269
279
  """
270
280
  获取MCP配置列表。
@@ -1,6 +1,7 @@
1
+ import glob
1
2
  import os
2
3
  from datetime import datetime
3
- from typing import Dict, List, Optional
4
+ from typing import Dict, List, Optional, Union
4
5
 
5
6
  import yaml
6
7
 
@@ -41,3 +42,55 @@ class JarvisHistory:
41
42
 
42
43
  self.current_file = None
43
44
  self.records = []
45
+
46
+ @staticmethod
47
+ def export_history_to_markdown(
48
+ input_dir: str, output_file: str, max_files: Optional[int] = None
49
+ ) -> None:
50
+ """
51
+ Export all history files in the directory to a single markdown file
52
+
53
+ Args:
54
+ input_dir: Directory containing history YAML files
55
+ output_file: Path to output markdown file
56
+ max_files: Maximum number of history files to export (None for all)
57
+ """
58
+ # Find all history files in the directory
59
+ history_files = glob.glob(os.path.join(input_dir, "history_*.yaml"))
60
+
61
+ if not history_files:
62
+ raise FileNotFoundError(f"No history files found in {input_dir}")
63
+
64
+ # Sort files by modification time (newest first) and limit to max_files
65
+ history_files.sort(key=os.path.getmtime, reverse=True)
66
+ if max_files is not None:
67
+ history_files = history_files[:max_files]
68
+
69
+ # Ensure output directory exists
70
+ os.makedirs(os.path.dirname(output_file), exist_ok=True)
71
+
72
+ with open(output_file, "w", encoding="utf-8") as md_file:
73
+ md_file.write("# Jarvis Conversation History\n\n")
74
+
75
+ for history_file in sorted(history_files):
76
+ # Read YAML file
77
+ with open(history_file, "r", encoding="utf-8") as f:
78
+ data = yaml.safe_load(f)
79
+
80
+ if not data or "conversation" not in data:
81
+ continue
82
+
83
+ # Write file header with timestamp from filename
84
+ timestamp = os.path.basename(history_file)[
85
+ 8:-5
86
+ ] # Extract timestamp from "history_YYYYMMDD_HHMMSS.yaml"
87
+ md_file.write(
88
+ f"## Conversation at {timestamp[:4]}-{timestamp[4:6]}-{timestamp[6:8]} "
89
+ f"{timestamp[9:11]}:{timestamp[11:13]}:{timestamp[13:15]}\n\n"
90
+ )
91
+
92
+ # Write conversation messages
93
+ for msg in data["conversation"]:
94
+ md_file.write(f"**{msg['role']}**: {msg['message']}\n\n")
95
+
96
+ md_file.write("\n---\n\n")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jarvis-ai-assistant
3
- Version: 0.1.195
3
+ Version: 0.1.196
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
@@ -538,6 +538,7 @@ OPENAI_API_BASE: https://api.openai.com/v1
538
538
  | `JARVIS_PRINT_PROMPT` | false | 是否打印提示 |
539
539
  | `JARVIS_USE_METHODOLOGY` | true | 是否启用方法论功能 |
540
540
  | `JARVIS_USE_ANALYSIS` | true | 是否启用任务分析功能 |
541
+ | `JARVIS_USE_HISTORY` | false | 是否启用历史记录功能 |
541
542
  | `JARVIS_DATA_PATH` | ~/.jarvis | Jarvis数据存储目录路径 |
542
543
 
543
544
  ## 🛠️ 工具说明 <a id="tools"></a>
@@ -1,5 +1,5 @@
1
- jarvis/__init__.py,sha256=BtvIF-tEcm-J883lHUbiv2FXU6ggOOfOjPVy85nlDJM,75
2
- jarvis/jarvis_agent/__init__.py,sha256=mBtXEkj60R_dFl99r3dWfO3_D3OYhdBnCT-xjabOG5c,31841
1
+ jarvis/__init__.py,sha256=kYWJwIMa2ypcsRdrrfHUmeaXSvmV7v53HTQlUE3nCcs,75
2
+ jarvis/jarvis_agent/__init__.py,sha256=l826UsXr8_hVj9RSaOnJtkDgnINWnOzLltRTBcMO0l8,32501
3
3
  jarvis/jarvis_agent/builtin_input_handler.py,sha256=4CCEtVLRBIpkhDUKd54VcX1JFCIWCvDqDh4B1H-eSn0,2187
4
4
  jarvis/jarvis_agent/jarvis.py,sha256=GH2zi8eXNpW8twiY3LKDEZgGmFC5geB0jlkwFrm7hOQ,6279
5
5
  jarvis/jarvis_agent/main.py,sha256=c6bQe-8LXvW2-NBn9Rn_yPYdrwnkJ8KQaSFY2cPvkxw,2775
@@ -29,7 +29,7 @@ jarvis/jarvis_code_analysis/checklists/shell.py,sha256=aRFYhQQvTgbYd-uY5pc8UHIUA
29
29
  jarvis/jarvis_code_analysis/checklists/sql.py,sha256=vR0T6qC7b4dURjJVAd7kSVxyvZEQXPG1Jqc2sNTGp5c,2355
30
30
  jarvis/jarvis_code_analysis/checklists/swift.py,sha256=TPx4I6Gupvs6tSerRKmTSKEPQpOLEbH2Y7LXg1uBgxc,2566
31
31
  jarvis/jarvis_code_analysis/checklists/web.py,sha256=25gGD7pDadZQybNFvALYxWvK0VRjGQb1NVJQElwjyk0,3943
32
- jarvis/jarvis_data/config_schema.json,sha256=u_I8KawgwUltW-tVw3t37rLv4TqdBynZaNGhOFH2Zf8,6397
32
+ jarvis/jarvis_data/config_schema.json,sha256=yMXCNy8-CRL44r9GKBClvX6LBX20cpm7QOW9TSffAbs,6533
33
33
  jarvis/jarvis_data/huggingface.tar.gz,sha256=dWKnc_tvyx-I_ZkXo91O0b38KxDmLW1ZbmJ3E6fCl_k,1120205
34
34
  jarvis/jarvis_dev/main.py,sha256=zzVDrPQlPJFnHxNjChBAYA8YwIaQYmPxG-bHjIxdL3s,40940
35
35
  jarvis/jarvis_git_details/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -79,20 +79,20 @@ jarvis/jarvis_tools/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG
79
79
  jarvis/jarvis_tools/cli/main.py,sha256=Mg6TQDxMdzB1Ua1UrZ2EE-uQWsbaeojWaEGHJp2HimA,6375
80
80
  jarvis/jarvis_utils/__init__.py,sha256=67h0ldisGlh3oK4DAeNEL2Bl_VsI3tSmfclasyVlueM,850
81
81
  jarvis/jarvis_utils/builtin_replace_map.py,sha256=s7C5wKhoKkv-O4ltMcDzNpv5oGPC1EbXgiohPHAqksw,4892
82
- jarvis/jarvis_utils/config.py,sha256=e-nrbpAbGtFKkRuqzG021OgDZCvlYjMdlmPUqt2_zGo,7121
82
+ jarvis/jarvis_utils/config.py,sha256=OomZRIeRHiBntKXdqYP1ArI8aqRFqtMlLkd9-VSd5dA,7364
83
83
  jarvis/jarvis_utils/embedding.py,sha256=suqKOgH4cq2HYj4xvNpqDPN9pyc3hTCl934xYonF6qk,3922
84
84
  jarvis/jarvis_utils/file_processors.py,sha256=XiM248SHS7lLgQDCbORVFWqinbVDUawYxWDOsLXDxP8,3043
85
85
  jarvis/jarvis_utils/git_utils.py,sha256=F1558EbJ3dRl12DMwmT24XjkC8XqddBjhpWxLgyI0aI,15688
86
86
  jarvis/jarvis_utils/globals.py,sha256=9NTMfCVd0jvtloOv14-KE6clhcVStFmyN9jWxLmQ5so,3369
87
87
  jarvis/jarvis_utils/input.py,sha256=WOs9hYSiZE3ao5K-UJmC7KyZByYnC1opHGJTUZm7DVo,7884
88
- jarvis/jarvis_utils/jarvis_history.py,sha256=VG8THVUuuxwbGdFhYeM9mVlGzRCCqYZeW0PpSz_vXFU,1456
88
+ jarvis/jarvis_utils/jarvis_history.py,sha256=TCfxJvEP321iY5CFpEOxo6sVKNw5tWEQFaWf9cV4Als,3597
89
89
  jarvis/jarvis_utils/methodology.py,sha256=MhPrMxMqElyAn54BDfpQdUqrRr7IbSlrLvAI39LCgTM,8487
90
90
  jarvis/jarvis_utils/output.py,sha256=PRCgudPOB8gMEP3u-g0FGD2c6tBgJhLXUMqNPglfjV8,10813
91
91
  jarvis/jarvis_utils/tag.py,sha256=f211opbbbTcSyzCDwuIK_oCnKhXPNK-RknYyGzY1yD0,431
92
92
  jarvis/jarvis_utils/utils.py,sha256=55kIbFXPFEd6770mdy2fZDh96XH0rIFJw2w3rYhE2Cc,11895
93
- jarvis_ai_assistant-0.1.195.dist-info/licenses/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
94
- jarvis_ai_assistant-0.1.195.dist-info/METADATA,sha256=Zz3_o4jZtHVoB_SRn9aguPc4WGj-jmTwzF69ZqgtXa8,20134
95
- jarvis_ai_assistant-0.1.195.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
96
- jarvis_ai_assistant-0.1.195.dist-info/entry_points.txt,sha256=Gy3DOP1PYLMK0GCj4rrP_9lkOyBQ39EK_lKGUSwn41E,869
97
- jarvis_ai_assistant-0.1.195.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
98
- jarvis_ai_assistant-0.1.195.dist-info/RECORD,,
93
+ jarvis_ai_assistant-0.1.196.dist-info/licenses/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
94
+ jarvis_ai_assistant-0.1.196.dist-info/METADATA,sha256=xGxSUcjUBvI2jzh5z_dv6hoOKgjouRgtaNpCQijpA5s,20200
95
+ jarvis_ai_assistant-0.1.196.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
96
+ jarvis_ai_assistant-0.1.196.dist-info/entry_points.txt,sha256=Gy3DOP1PYLMK0GCj4rrP_9lkOyBQ39EK_lKGUSwn41E,869
97
+ jarvis_ai_assistant-0.1.196.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
98
+ jarvis_ai_assistant-0.1.196.dist-info/RECORD,,