jarvis-ai-assistant 0.3.30__py3-none-any.whl → 0.7.6__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 +1 -1
- jarvis/jarvis_agent/__init__.py +458 -152
- jarvis/jarvis_agent/agent_manager.py +17 -13
- jarvis/jarvis_agent/builtin_input_handler.py +2 -6
- jarvis/jarvis_agent/config_editor.py +2 -7
- jarvis/jarvis_agent/event_bus.py +82 -12
- jarvis/jarvis_agent/file_context_handler.py +329 -0
- jarvis/jarvis_agent/file_methodology_manager.py +3 -4
- jarvis/jarvis_agent/jarvis.py +628 -55
- jarvis/jarvis_agent/language_extractors/__init__.py +57 -0
- jarvis/jarvis_agent/language_extractors/c_extractor.py +21 -0
- jarvis/jarvis_agent/language_extractors/cpp_extractor.py +21 -0
- jarvis/jarvis_agent/language_extractors/go_extractor.py +21 -0
- jarvis/jarvis_agent/language_extractors/java_extractor.py +84 -0
- jarvis/jarvis_agent/language_extractors/javascript_extractor.py +79 -0
- jarvis/jarvis_agent/language_extractors/python_extractor.py +21 -0
- jarvis/jarvis_agent/language_extractors/rust_extractor.py +21 -0
- jarvis/jarvis_agent/language_extractors/typescript_extractor.py +84 -0
- jarvis/jarvis_agent/language_support_info.py +486 -0
- jarvis/jarvis_agent/main.py +34 -10
- jarvis/jarvis_agent/memory_manager.py +7 -16
- jarvis/jarvis_agent/methodology_share_manager.py +10 -16
- jarvis/jarvis_agent/prompt_manager.py +1 -1
- jarvis/jarvis_agent/prompts.py +193 -171
- jarvis/jarvis_agent/protocols.py +8 -12
- jarvis/jarvis_agent/run_loop.py +105 -9
- jarvis/jarvis_agent/session_manager.py +2 -3
- jarvis/jarvis_agent/share_manager.py +20 -22
- jarvis/jarvis_agent/shell_input_handler.py +1 -2
- jarvis/jarvis_agent/stdio_redirect.py +295 -0
- jarvis/jarvis_agent/task_analyzer.py +31 -6
- jarvis/jarvis_agent/task_manager.py +11 -27
- jarvis/jarvis_agent/tool_executor.py +2 -3
- jarvis/jarvis_agent/tool_share_manager.py +12 -24
- jarvis/jarvis_agent/utils.py +5 -1
- jarvis/jarvis_agent/web_bridge.py +189 -0
- jarvis/jarvis_agent/web_output_sink.py +53 -0
- jarvis/jarvis_agent/web_server.py +786 -0
- jarvis/jarvis_c2rust/__init__.py +26 -0
- jarvis/jarvis_c2rust/cli.py +575 -0
- jarvis/jarvis_c2rust/collector.py +250 -0
- jarvis/jarvis_c2rust/constants.py +26 -0
- jarvis/jarvis_c2rust/library_replacer.py +1254 -0
- jarvis/jarvis_c2rust/llm_module_agent.py +1272 -0
- jarvis/jarvis_c2rust/loaders.py +207 -0
- jarvis/jarvis_c2rust/models.py +28 -0
- jarvis/jarvis_c2rust/optimizer.py +2157 -0
- jarvis/jarvis_c2rust/scanner.py +1681 -0
- jarvis/jarvis_c2rust/transpiler.py +2983 -0
- jarvis/jarvis_c2rust/utils.py +385 -0
- jarvis/jarvis_code_agent/build_validation_config.py +132 -0
- jarvis/jarvis_code_agent/code_agent.py +1371 -220
- jarvis/jarvis_code_agent/code_analyzer/__init__.py +65 -0
- jarvis/jarvis_code_agent/code_analyzer/base_language.py +74 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/__init__.py +44 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/base.py +106 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/cmake.py +74 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/detector.py +125 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/fallback.py +72 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/go.py +70 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/java_gradle.py +53 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/java_maven.py +47 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/makefile.py +61 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/nodejs.py +110 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/python.py +154 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/rust.py +110 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator/validator.py +153 -0
- jarvis/jarvis_code_agent/code_analyzer/build_validator.py +43 -0
- jarvis/jarvis_code_agent/code_analyzer/context_manager.py +648 -0
- jarvis/jarvis_code_agent/code_analyzer/context_recommender.py +18 -0
- jarvis/jarvis_code_agent/code_analyzer/dependency_analyzer.py +132 -0
- jarvis/jarvis_code_agent/code_analyzer/file_ignore.py +330 -0
- jarvis/jarvis_code_agent/code_analyzer/impact_analyzer.py +781 -0
- jarvis/jarvis_code_agent/code_analyzer/language_registry.py +185 -0
- jarvis/jarvis_code_agent/code_analyzer/language_support.py +110 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/__init__.py +49 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/c_cpp_language.py +299 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/go_language.py +215 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/java_language.py +212 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/javascript_language.py +254 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/python_language.py +269 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/rust_language.py +281 -0
- jarvis/jarvis_code_agent/code_analyzer/languages/typescript_language.py +280 -0
- jarvis/jarvis_code_agent/code_analyzer/llm_context_recommender.py +605 -0
- jarvis/jarvis_code_agent/code_analyzer/structured_code.py +556 -0
- jarvis/jarvis_code_agent/code_analyzer/symbol_extractor.py +252 -0
- jarvis/jarvis_code_agent/code_analyzer/tree_sitter_extractor.py +58 -0
- jarvis/jarvis_code_agent/lint.py +501 -8
- jarvis/jarvis_code_agent/utils.py +141 -0
- jarvis/jarvis_code_analysis/code_review.py +493 -584
- jarvis/jarvis_data/config_schema.json +128 -12
- jarvis/jarvis_git_squash/main.py +4 -5
- jarvis/jarvis_git_utils/git_commiter.py +82 -75
- jarvis/jarvis_mcp/sse_mcp_client.py +22 -29
- jarvis/jarvis_mcp/stdio_mcp_client.py +12 -13
- jarvis/jarvis_mcp/streamable_mcp_client.py +15 -14
- jarvis/jarvis_memory_organizer/memory_organizer.py +55 -74
- jarvis/jarvis_methodology/main.py +32 -48
- jarvis/jarvis_multi_agent/__init__.py +287 -55
- jarvis/jarvis_multi_agent/main.py +36 -4
- jarvis/jarvis_platform/base.py +524 -202
- jarvis/jarvis_platform/human.py +7 -8
- jarvis/jarvis_platform/kimi.py +30 -36
- jarvis/jarvis_platform/openai.py +88 -25
- jarvis/jarvis_platform/registry.py +26 -10
- jarvis/jarvis_platform/tongyi.py +24 -25
- jarvis/jarvis_platform/yuanbao.py +32 -43
- jarvis/jarvis_platform_manager/main.py +66 -77
- jarvis/jarvis_platform_manager/service.py +8 -13
- jarvis/jarvis_rag/cli.py +53 -55
- jarvis/jarvis_rag/embedding_manager.py +13 -18
- jarvis/jarvis_rag/llm_interface.py +8 -9
- jarvis/jarvis_rag/query_rewriter.py +10 -21
- jarvis/jarvis_rag/rag_pipeline.py +24 -27
- jarvis/jarvis_rag/reranker.py +4 -5
- jarvis/jarvis_rag/retriever.py +28 -30
- jarvis/jarvis_sec/__init__.py +305 -0
- jarvis/jarvis_sec/agents.py +143 -0
- jarvis/jarvis_sec/analysis.py +276 -0
- jarvis/jarvis_sec/checkers/__init__.py +32 -0
- jarvis/jarvis_sec/checkers/c_checker.py +2680 -0
- jarvis/jarvis_sec/checkers/rust_checker.py +1108 -0
- jarvis/jarvis_sec/cli.py +139 -0
- jarvis/jarvis_sec/clustering.py +1439 -0
- jarvis/jarvis_sec/file_manager.py +427 -0
- jarvis/jarvis_sec/parsers.py +73 -0
- jarvis/jarvis_sec/prompts.py +268 -0
- jarvis/jarvis_sec/report.py +336 -0
- jarvis/jarvis_sec/review.py +453 -0
- jarvis/jarvis_sec/status.py +264 -0
- jarvis/jarvis_sec/types.py +20 -0
- jarvis/jarvis_sec/utils.py +499 -0
- jarvis/jarvis_sec/verification.py +848 -0
- jarvis/jarvis_sec/workflow.py +226 -0
- jarvis/jarvis_smart_shell/main.py +38 -87
- jarvis/jarvis_stats/cli.py +2 -2
- jarvis/jarvis_stats/stats.py +8 -8
- jarvis/jarvis_stats/storage.py +15 -21
- jarvis/jarvis_stats/visualizer.py +1 -1
- jarvis/jarvis_tools/clear_memory.py +3 -20
- jarvis/jarvis_tools/cli/main.py +21 -23
- jarvis/jarvis_tools/edit_file.py +1019 -132
- jarvis/jarvis_tools/execute_script.py +83 -25
- jarvis/jarvis_tools/file_analyzer.py +6 -9
- jarvis/jarvis_tools/generate_new_tool.py +14 -21
- jarvis/jarvis_tools/lsp_client.py +1552 -0
- jarvis/jarvis_tools/methodology.py +2 -3
- jarvis/jarvis_tools/read_code.py +1736 -35
- jarvis/jarvis_tools/read_symbols.py +140 -0
- jarvis/jarvis_tools/read_webpage.py +12 -13
- jarvis/jarvis_tools/registry.py +427 -200
- jarvis/jarvis_tools/retrieve_memory.py +20 -19
- jarvis/jarvis_tools/rewrite_file.py +72 -158
- jarvis/jarvis_tools/save_memory.py +3 -15
- jarvis/jarvis_tools/search_web.py +18 -18
- jarvis/jarvis_tools/sub_agent.py +36 -43
- jarvis/jarvis_tools/sub_code_agent.py +25 -26
- jarvis/jarvis_tools/virtual_tty.py +55 -33
- jarvis/jarvis_utils/clipboard.py +7 -10
- jarvis/jarvis_utils/config.py +232 -45
- jarvis/jarvis_utils/embedding.py +8 -5
- jarvis/jarvis_utils/fzf.py +8 -8
- jarvis/jarvis_utils/git_utils.py +225 -36
- jarvis/jarvis_utils/globals.py +3 -3
- jarvis/jarvis_utils/http.py +1 -1
- jarvis/jarvis_utils/input.py +99 -48
- jarvis/jarvis_utils/jsonnet_compat.py +465 -0
- jarvis/jarvis_utils/methodology.py +52 -48
- jarvis/jarvis_utils/utils.py +819 -491
- jarvis_ai_assistant-0.7.6.dist-info/METADATA +600 -0
- jarvis_ai_assistant-0.7.6.dist-info/RECORD +218 -0
- {jarvis_ai_assistant-0.3.30.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/entry_points.txt +4 -0
- jarvis/jarvis_agent/config.py +0 -92
- jarvis/jarvis_agent/edit_file_handler.py +0 -296
- jarvis/jarvis_platform/ai8.py +0 -332
- jarvis/jarvis_tools/ask_user.py +0 -54
- jarvis_ai_assistant-0.3.30.dist-info/METADATA +0 -381
- jarvis_ai_assistant-0.3.30.dist-info/RECORD +0 -137
- {jarvis_ai_assistant-0.3.30.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.3.30.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.3.30.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/top_level.txt +0 -0
|
@@ -5,7 +5,6 @@ import subprocess
|
|
|
5
5
|
from typing import Any, Dict, List, Optional
|
|
6
6
|
|
|
7
7
|
from jarvis.jarvis_mcp import McpClient
|
|
8
|
-
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
9
8
|
|
|
10
9
|
|
|
11
10
|
class StdioMcpClient(McpClient):
|
|
@@ -50,7 +49,7 @@ class StdioMcpClient(McpClient):
|
|
|
50
49
|
)
|
|
51
50
|
|
|
52
51
|
except Exception as e:
|
|
53
|
-
|
|
52
|
+
print(f"❌ 启动MCP进程失败: {str(e)}")
|
|
54
53
|
raise
|
|
55
54
|
|
|
56
55
|
def _initialize(self) -> None:
|
|
@@ -79,7 +78,7 @@ class StdioMcpClient(McpClient):
|
|
|
79
78
|
self._send_notification("notifications/initialized", {})
|
|
80
79
|
|
|
81
80
|
except Exception as e:
|
|
82
|
-
|
|
81
|
+
print(f"❌ MCP初始化失败: {str(e)}")
|
|
83
82
|
raise
|
|
84
83
|
|
|
85
84
|
def _send_request(self, method: str, params: Dict[str, Any]) -> Dict[str, Any]:
|
|
@@ -108,7 +107,7 @@ class StdioMcpClient(McpClient):
|
|
|
108
107
|
return json.loads(response)
|
|
109
108
|
|
|
110
109
|
except Exception as e:
|
|
111
|
-
|
|
110
|
+
print(f"❌ 发送请求失败: {str(e)}")
|
|
112
111
|
raise
|
|
113
112
|
|
|
114
113
|
def _send_notification(self, method: str, params: Dict[str, Any]) -> None:
|
|
@@ -129,7 +128,7 @@ class StdioMcpClient(McpClient):
|
|
|
129
128
|
self.process.stdin.flush() # type: ignore
|
|
130
129
|
|
|
131
130
|
except Exception as e:
|
|
132
|
-
|
|
131
|
+
print(f"❌ 发送通知失败: {str(e)}")
|
|
133
132
|
raise
|
|
134
133
|
|
|
135
134
|
def get_tool_list(self) -> List[Dict[str, Any]]:
|
|
@@ -172,10 +171,10 @@ class StdioMcpClient(McpClient):
|
|
|
172
171
|
else:
|
|
173
172
|
error_msg += ": 未知错误"
|
|
174
173
|
|
|
175
|
-
|
|
174
|
+
print(f"❌ {error_msg}")
|
|
176
175
|
return []
|
|
177
176
|
except Exception as e:
|
|
178
|
-
|
|
177
|
+
print(f"❌ 获取工具列表失败: {str(e)}")
|
|
179
178
|
return []
|
|
180
179
|
|
|
181
180
|
def execute(self, tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:
|
|
@@ -214,7 +213,7 @@ class StdioMcpClient(McpClient):
|
|
|
214
213
|
"stderr": response.get("error", "Unknown error"),
|
|
215
214
|
}
|
|
216
215
|
except Exception as e:
|
|
217
|
-
|
|
216
|
+
print(f"❌ 执行工具失败: {str(e)}")
|
|
218
217
|
return {"success": False, "stdout": "", "stderr": str(e)}
|
|
219
218
|
|
|
220
219
|
def get_resource_list(self) -> List[Dict[str, Any]]:
|
|
@@ -237,10 +236,10 @@ class StdioMcpClient(McpClient):
|
|
|
237
236
|
error_msg += f": {response['error']}"
|
|
238
237
|
else:
|
|
239
238
|
error_msg += ": 未知错误"
|
|
240
|
-
|
|
239
|
+
print(f"❌ {error_msg}")
|
|
241
240
|
return []
|
|
242
241
|
except Exception as e:
|
|
243
|
-
|
|
242
|
+
print(f"❌ 获取资源列表失败: {str(e)}")
|
|
244
243
|
return []
|
|
245
244
|
|
|
246
245
|
def get_resource(self, uri: str) -> Dict[str, Any]:
|
|
@@ -281,11 +280,11 @@ class StdioMcpClient(McpClient):
|
|
|
281
280
|
error_msg += f": {response['error']}"
|
|
282
281
|
else:
|
|
283
282
|
error_msg += ": 未知错误"
|
|
284
|
-
|
|
283
|
+
print(f"❌ {error_msg}")
|
|
285
284
|
return {"success": False, "stdout": "", "stderr": error_msg}
|
|
286
285
|
except Exception as e:
|
|
287
286
|
error_msg = f"获取资源内容失败: {str(e)}"
|
|
288
|
-
|
|
287
|
+
print(f"❌ {error_msg}")
|
|
289
288
|
return {"success": False, "stdout": "", "stderr": error_msg}
|
|
290
289
|
|
|
291
290
|
def __del__(self):
|
|
@@ -296,6 +295,6 @@ class StdioMcpClient(McpClient):
|
|
|
296
295
|
self._send_notification("notifications/exit", {})
|
|
297
296
|
# 等待进程结束
|
|
298
297
|
self.process.wait(timeout=1)
|
|
299
|
-
except:
|
|
298
|
+
except Exception:
|
|
300
299
|
# 如果进程没有正常退出,强制终止
|
|
301
300
|
self.process.kill()
|
|
@@ -7,7 +7,6 @@ from urllib.parse import urljoin
|
|
|
7
7
|
import requests # type: ignore[import-untyped]
|
|
8
8
|
|
|
9
9
|
from jarvis.jarvis_mcp import McpClient
|
|
10
|
-
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
11
10
|
|
|
12
11
|
|
|
13
12
|
class StreamableMcpClient(McpClient):
|
|
@@ -86,7 +85,7 @@ class StreamableMcpClient(McpClient):
|
|
|
86
85
|
self._send_notification("notifications/initialized", {})
|
|
87
86
|
|
|
88
87
|
except Exception as e:
|
|
89
|
-
|
|
88
|
+
print(f"❌ MCP初始化失败: {str(e)}")
|
|
90
89
|
raise
|
|
91
90
|
|
|
92
91
|
def register_notification_handler(self, method: str, handler: Callable) -> None:
|
|
@@ -182,14 +181,16 @@ class StreamableMcpClient(McpClient):
|
|
|
182
181
|
handler(params)
|
|
183
182
|
except Exception as e:
|
|
184
183
|
error_lines.append(f"处理通知时出错 ({notify_method}): {e}")
|
|
185
|
-
except
|
|
184
|
+
except Exception:
|
|
186
185
|
warning_lines.append(f"无法解析响应: {line}")
|
|
187
186
|
continue
|
|
188
187
|
|
|
189
188
|
if warning_lines:
|
|
190
|
-
|
|
189
|
+
joined_warnings = '\n'.join(warning_lines)
|
|
190
|
+
print(f"⚠️ {joined_warnings}")
|
|
191
191
|
if error_lines:
|
|
192
|
-
|
|
192
|
+
joined_errors = '\n'.join(error_lines)
|
|
193
|
+
print(f"❌ {joined_errors}")
|
|
193
194
|
# Ensure response is closed after streaming
|
|
194
195
|
response.close()
|
|
195
196
|
if result is None:
|
|
@@ -198,7 +199,7 @@ class StreamableMcpClient(McpClient):
|
|
|
198
199
|
return result
|
|
199
200
|
|
|
200
201
|
except Exception as e:
|
|
201
|
-
|
|
202
|
+
print(f"❌ 发送请求失败: {str(e)}")
|
|
202
203
|
raise
|
|
203
204
|
finally:
|
|
204
205
|
# 清理请求状态
|
|
@@ -226,7 +227,7 @@ class StreamableMcpClient(McpClient):
|
|
|
226
227
|
response.close()
|
|
227
228
|
|
|
228
229
|
except Exception as e:
|
|
229
|
-
|
|
230
|
+
print(f"❌ 发送通知失败: {str(e)}")
|
|
230
231
|
raise
|
|
231
232
|
|
|
232
233
|
def get_tool_list(self) -> List[Dict[str, Any]]:
|
|
@@ -269,10 +270,10 @@ class StreamableMcpClient(McpClient):
|
|
|
269
270
|
else:
|
|
270
271
|
error_msg += ": 未知错误"
|
|
271
272
|
|
|
272
|
-
|
|
273
|
+
print(f"❌ {error_msg}")
|
|
273
274
|
return []
|
|
274
275
|
except Exception as e:
|
|
275
|
-
|
|
276
|
+
print(f"❌ 获取工具列表失败: {str(e)}")
|
|
276
277
|
return []
|
|
277
278
|
|
|
278
279
|
def execute(self, tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:
|
|
@@ -311,7 +312,7 @@ class StreamableMcpClient(McpClient):
|
|
|
311
312
|
"stderr": response.get("error", "Unknown error"),
|
|
312
313
|
}
|
|
313
314
|
except Exception as e:
|
|
314
|
-
|
|
315
|
+
print(f"❌ 执行工具失败: {str(e)}")
|
|
315
316
|
return {"success": False, "stdout": "", "stderr": str(e)}
|
|
316
317
|
|
|
317
318
|
def get_resource_list(self) -> List[Dict[str, Any]]:
|
|
@@ -334,10 +335,10 @@ class StreamableMcpClient(McpClient):
|
|
|
334
335
|
error_msg += f": {response['error']}"
|
|
335
336
|
else:
|
|
336
337
|
error_msg += ": 未知错误"
|
|
337
|
-
|
|
338
|
+
print(f"❌ {error_msg}")
|
|
338
339
|
return []
|
|
339
340
|
except Exception as e:
|
|
340
|
-
|
|
341
|
+
print(f"❌ 获取资源列表失败: {str(e)}")
|
|
341
342
|
return []
|
|
342
343
|
|
|
343
344
|
def get_resource(self, uri: str) -> Dict[str, Any]:
|
|
@@ -378,11 +379,11 @@ class StreamableMcpClient(McpClient):
|
|
|
378
379
|
error_msg += f": {response['error']}"
|
|
379
380
|
else:
|
|
380
381
|
error_msg += ": 未知错误"
|
|
381
|
-
|
|
382
|
+
print(f"❌ {error_msg}")
|
|
382
383
|
return {"success": False, "stdout": "", "stderr": error_msg}
|
|
383
384
|
except Exception as e:
|
|
384
385
|
error_msg = f"获取资源内容失败: {str(e)}"
|
|
385
|
-
|
|
386
|
+
print(f"❌ {error_msg}")
|
|
386
387
|
return {"success": False, "stdout": "", "stderr": error_msg}
|
|
387
388
|
|
|
388
389
|
def __del__(self):
|
|
@@ -18,7 +18,6 @@ from jarvis.jarvis_utils.config import (
|
|
|
18
18
|
get_normal_platform_name,
|
|
19
19
|
get_normal_model_name,
|
|
20
20
|
)
|
|
21
|
-
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
22
21
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
23
22
|
from jarvis.jarvis_utils.utils import init_env
|
|
24
23
|
|
|
@@ -75,7 +74,8 @@ class MemoryOrganizer:
|
|
|
75
74
|
error_lines.append(f"读取记忆文件 {memory_file} 失败: {str(e)}")
|
|
76
75
|
|
|
77
76
|
if error_lines:
|
|
78
|
-
|
|
77
|
+
joined_errors = '\n'.join(error_lines)
|
|
78
|
+
print(f"⚠️ {joined_errors}")
|
|
79
79
|
|
|
80
80
|
return memories
|
|
81
81
|
|
|
@@ -174,16 +174,13 @@ class MemoryOrganizer:
|
|
|
174
174
|
4. 确保合并后的记忆保留了所有重要信息
|
|
175
175
|
5. **重要**:越近期的记忆权重越高,优先保留最新记忆中的信息
|
|
176
176
|
|
|
177
|
-
请将合并结果放在 <merged_memory> 标签内,使用
|
|
177
|
+
请将合并结果放在 <merged_memory> 标签内,使用JSON格式:
|
|
178
178
|
|
|
179
179
|
<merged_memory>
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
- 标签1
|
|
185
|
-
- 标签2
|
|
186
|
-
- 标签3
|
|
180
|
+
{{
|
|
181
|
+
"content": "合并后的记忆内容,可以是多行文本",
|
|
182
|
+
"tags": ["标签1", "标签2", "标签3"]
|
|
183
|
+
}}
|
|
187
184
|
</merged_memory>
|
|
188
185
|
|
|
189
186
|
注意:
|
|
@@ -192,6 +189,7 @@ tags:
|
|
|
192
189
|
- 保持专业和客观的语气
|
|
193
190
|
- 最近的记忆信息优先级更高
|
|
194
191
|
- 只输出 <merged_memory> 标签内的内容,不要有其他说明
|
|
192
|
+
- JSON格式必须有效,字符串中的换行符使用 \\n 表示
|
|
195
193
|
"""
|
|
196
194
|
|
|
197
195
|
try:
|
|
@@ -203,32 +201,32 @@ tags:
|
|
|
203
201
|
|
|
204
202
|
# 解析响应
|
|
205
203
|
import re
|
|
206
|
-
import
|
|
204
|
+
from jarvis.jarvis_utils.jsonnet_compat import loads as json5_loads
|
|
207
205
|
|
|
208
206
|
# 提取 <merged_memory> 标签内的内容
|
|
209
|
-
|
|
207
|
+
json_match = re.search(
|
|
210
208
|
r"<merged_memory>(.*?)</merged_memory>",
|
|
211
209
|
response,
|
|
212
210
|
re.DOTALL | re.IGNORECASE,
|
|
213
211
|
)
|
|
214
212
|
|
|
215
|
-
if
|
|
216
|
-
|
|
213
|
+
if json_match:
|
|
214
|
+
json_content = json_match.group(1).strip()
|
|
217
215
|
try:
|
|
218
|
-
result =
|
|
216
|
+
result = json5_loads(json_content)
|
|
219
217
|
return {
|
|
220
218
|
"content": result.get("content", ""),
|
|
221
219
|
"tags": result.get("tags", []),
|
|
222
220
|
"type": memories[0].get("type", "unknown"),
|
|
223
221
|
"merged_from": [m.get("id", "") for m in memories],
|
|
224
222
|
}
|
|
225
|
-
except
|
|
226
|
-
raise ValueError(f"无法解析
|
|
223
|
+
except (ValueError, Exception) as e:
|
|
224
|
+
raise ValueError(f"无法解析JSON内容: {str(e)}")
|
|
227
225
|
else:
|
|
228
226
|
raise ValueError("无法从模型响应中提取 <merged_memory> 标签内容")
|
|
229
227
|
|
|
230
228
|
except Exception as e:
|
|
231
|
-
|
|
229
|
+
print(f"⚠️ 调用大模型合并记忆失败: {str(e)}")
|
|
232
230
|
# 返回 None 表示合并失败,跳过这组记忆
|
|
233
231
|
return None
|
|
234
232
|
|
|
@@ -249,18 +247,15 @@ tags:
|
|
|
249
247
|
返回:
|
|
250
248
|
整理结果统计
|
|
251
249
|
"""
|
|
252
|
-
|
|
253
|
-
f"开始整理{memory_type}类型的记忆,最小重叠标签数: {min_overlap}",
|
|
254
|
-
OutputType.INFO,
|
|
255
|
-
)
|
|
250
|
+
print(f"ℹ️ 开始整理{memory_type}类型的记忆,最小重叠标签数: {min_overlap}")
|
|
256
251
|
|
|
257
252
|
# 加载记忆
|
|
258
253
|
memories = self._load_memories(memory_type)
|
|
259
254
|
if not memories:
|
|
260
|
-
|
|
255
|
+
print("ℹ️ 没有找到需要整理的记忆")
|
|
261
256
|
return {"processed": 0, "merged": 0}
|
|
262
257
|
|
|
263
|
-
|
|
258
|
+
print(f"ℹ️ 加载了 {len(memories)} 个记忆")
|
|
264
259
|
|
|
265
260
|
# 统计信息
|
|
266
261
|
stats = {
|
|
@@ -293,10 +288,7 @@ tags:
|
|
|
293
288
|
|
|
294
289
|
if overlap_count in overlap_groups:
|
|
295
290
|
groups = overlap_groups[overlap_count]
|
|
296
|
-
|
|
297
|
-
f"\n发现 {len(groups)} 个具有 {overlap_count} 个重叠标签的记忆组",
|
|
298
|
-
OutputType.INFO,
|
|
299
|
-
)
|
|
291
|
+
print(f"\nℹ️ 发现 {len(groups)} 个具有 {overlap_count} 个重叠标签的记忆组")
|
|
300
292
|
|
|
301
293
|
for group in groups:
|
|
302
294
|
# 将活跃索引转换回原始索引
|
|
@@ -314,7 +306,8 @@ tags:
|
|
|
314
306
|
f" - ID: {mem.get('id', '未知')}, "
|
|
315
307
|
f"标签: {', '.join(mem.get('tags', []))[:50]}..."
|
|
316
308
|
)
|
|
317
|
-
|
|
309
|
+
joined_lines = '\n'.join(lines)
|
|
310
|
+
print(f"ℹ️ {joined_lines}")
|
|
318
311
|
|
|
319
312
|
if not dry_run:
|
|
320
313
|
# 合并记忆
|
|
@@ -322,9 +315,7 @@ tags:
|
|
|
322
315
|
|
|
323
316
|
# 如果合并失败,跳过这组
|
|
324
317
|
if merged_memory is None:
|
|
325
|
-
|
|
326
|
-
" 跳过这组记忆的合并", OutputType.WARNING
|
|
327
|
-
)
|
|
318
|
+
print(" ⚠️ 跳过这组记忆的合并")
|
|
328
319
|
continue
|
|
329
320
|
|
|
330
321
|
# 保存新记忆
|
|
@@ -341,16 +332,14 @@ tags:
|
|
|
341
332
|
# 标记这些记忆已被删除
|
|
342
333
|
deleted_indices.update(original_indices)
|
|
343
334
|
else:
|
|
344
|
-
|
|
335
|
+
print(" ℹ️ [模拟运行] 跳过实际合并")
|
|
345
336
|
|
|
346
337
|
# 显示统计信息
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
f"创建的新记忆数: {stats['created_memories']}", OutputType.INFO
|
|
353
|
-
)
|
|
338
|
+
print("\n✅ 整理完成!")
|
|
339
|
+
print(f"ℹ️ 总记忆数: {stats['total_memories']}")
|
|
340
|
+
print(f"ℹ️ 处理的组数: {stats['processed_groups']}")
|
|
341
|
+
print(f"ℹ️ 合并的记忆数: {stats['merged_memories']}")
|
|
342
|
+
print(f"ℹ️ 创建的新记忆数: {stats['created_memories']}")
|
|
354
343
|
|
|
355
344
|
return stats
|
|
356
345
|
|
|
@@ -382,10 +371,7 @@ tags:
|
|
|
382
371
|
with open(new_file, "w", encoding="utf-8") as f:
|
|
383
372
|
json.dump(memory, f, ensure_ascii=False, indent=2)
|
|
384
373
|
|
|
385
|
-
|
|
386
|
-
f"创建新记忆: {memory['id']} (标签: {', '.join(memory['tags'][:3])}...)",
|
|
387
|
-
OutputType.SUCCESS,
|
|
388
|
-
)
|
|
374
|
+
print(f"✅ 创建新记忆: {memory['id']} (标签: {', '.join(memory['tags'][:3])}...)")
|
|
389
375
|
|
|
390
376
|
# 删除原始记忆文件(先汇总日志,最后统一打印)
|
|
391
377
|
info_lines: List[str] = []
|
|
@@ -406,9 +392,11 @@ tags:
|
|
|
406
392
|
f"删除记忆文件失败 {orig_memory.get('file_path', '')}: {str(e)}"
|
|
407
393
|
)
|
|
408
394
|
if info_lines:
|
|
409
|
-
|
|
395
|
+
joined_info = '\n'.join(info_lines)
|
|
396
|
+
print(f"ℹ️ {joined_info}")
|
|
410
397
|
if warn_lines:
|
|
411
|
-
|
|
398
|
+
joined_warn = '\n'.join(warn_lines)
|
|
399
|
+
print(f"⚠️ {joined_warn}")
|
|
412
400
|
|
|
413
401
|
def export_memories(
|
|
414
402
|
self,
|
|
@@ -453,16 +441,15 @@ tags:
|
|
|
453
441
|
|
|
454
442
|
# 统一展示导出进度日志
|
|
455
443
|
if progress_lines:
|
|
456
|
-
|
|
444
|
+
joined_progress = '\n'.join(progress_lines)
|
|
445
|
+
print(f"ℹ️ {joined_progress}")
|
|
457
446
|
|
|
458
447
|
# 保存到文件
|
|
459
448
|
output_file.parent.mkdir(parents=True, exist_ok=True)
|
|
460
449
|
with open(output_file, "w", encoding="utf-8") as f:
|
|
461
450
|
json.dump(all_memories, f, ensure_ascii=False, indent=2)
|
|
462
451
|
|
|
463
|
-
|
|
464
|
-
f"成功导出 {len(all_memories)} 个记忆到 {output_file}", OutputType.SUCCESS
|
|
465
|
-
)
|
|
452
|
+
print(f"✅ 成功导出 {len(all_memories)} 个记忆到 {output_file}")
|
|
466
453
|
|
|
467
454
|
return len(all_memories)
|
|
468
455
|
|
|
@@ -491,7 +478,7 @@ tags:
|
|
|
491
478
|
if not isinstance(memories, list):
|
|
492
479
|
raise ValueError("导入文件格式错误,应为记忆列表")
|
|
493
480
|
|
|
494
|
-
|
|
481
|
+
print(f"ℹ️ 准备导入 {len(memories)} 个记忆")
|
|
495
482
|
|
|
496
483
|
# 统计导入结果
|
|
497
484
|
import_stats: Dict[str, int] = defaultdict(int)
|
|
@@ -509,9 +496,7 @@ tags:
|
|
|
509
496
|
elif memory_type == "global_long_term":
|
|
510
497
|
memory_dir = self.global_memory_dir / memory_type
|
|
511
498
|
else:
|
|
512
|
-
|
|
513
|
-
f"跳过不支持的记忆类型: {memory_type}", OutputType.WARNING
|
|
514
|
-
)
|
|
499
|
+
print(f"⚠️ 跳过不支持的记忆类型: {memory_type}")
|
|
515
500
|
skipped_count += 1
|
|
516
501
|
continue
|
|
517
502
|
|
|
@@ -528,7 +513,7 @@ tags:
|
|
|
528
513
|
memory_file = memory_dir / f"{memory_id}.json"
|
|
529
514
|
|
|
530
515
|
if memory_file.exists() and not overwrite:
|
|
531
|
-
|
|
516
|
+
print(f"ℹ️ 跳过已存在的记忆: {memory_id}")
|
|
532
517
|
skipped_count += 1
|
|
533
518
|
continue
|
|
534
519
|
|
|
@@ -550,13 +535,14 @@ tags:
|
|
|
550
535
|
import_stats[memory_type] += 1
|
|
551
536
|
|
|
552
537
|
# 显示导入结果
|
|
553
|
-
|
|
538
|
+
print("\n✅ 导入完成!")
|
|
554
539
|
if import_stats:
|
|
555
540
|
lines = [f"{memory_type}: 导入了 {count} 个记忆" for memory_type, count in import_stats.items()]
|
|
556
|
-
|
|
541
|
+
joined_lines = '\n'.join(lines)
|
|
542
|
+
print(f"ℹ️ {joined_lines}")
|
|
557
543
|
|
|
558
544
|
if skipped_count > 0:
|
|
559
|
-
|
|
545
|
+
print(f"⚠️ 跳过了 {skipped_count} 个记忆")
|
|
560
546
|
|
|
561
547
|
return dict(import_stats)
|
|
562
548
|
|
|
@@ -602,14 +588,11 @@ def organize(
|
|
|
602
588
|
"""
|
|
603
589
|
# 验证参数
|
|
604
590
|
if memory_type not in ["project_long_term", "global_long_term"]:
|
|
605
|
-
|
|
606
|
-
f"错误:不支持的记忆类型 '{memory_type}',请选择 'project_long_term' 或 'global_long_term'",
|
|
607
|
-
OutputType.ERROR,
|
|
608
|
-
)
|
|
591
|
+
print(f"❌ 错误:不支持的记忆类型 '{memory_type}',请选择 'project_long_term' 或 'global_long_term'")
|
|
609
592
|
raise typer.Exit(1)
|
|
610
593
|
|
|
611
594
|
if min_overlap < 2:
|
|
612
|
-
|
|
595
|
+
print("❌ 错误:最小重叠数必须大于等于2")
|
|
613
596
|
raise typer.Exit(1)
|
|
614
597
|
|
|
615
598
|
# 创建整理器并执行
|
|
@@ -629,7 +612,7 @@ def organize(
|
|
|
629
612
|
# typer.Exit 是正常的退出方式,直接传播
|
|
630
613
|
raise
|
|
631
614
|
except Exception as e:
|
|
632
|
-
|
|
615
|
+
print(f"❌ 记忆整理失败: {str(e)}")
|
|
633
616
|
raise typer.Exit(1)
|
|
634
617
|
|
|
635
618
|
|
|
@@ -672,10 +655,8 @@ def export(
|
|
|
672
655
|
valid_types = ["project_long_term", "global_long_term"]
|
|
673
656
|
invalid_types = [mt for mt in memory_types if mt not in valid_types]
|
|
674
657
|
if invalid_types:
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
OutputType.ERROR,
|
|
678
|
-
)
|
|
658
|
+
invalid_str = ", ".join(f"'{mt}'" for mt in invalid_types)
|
|
659
|
+
print(f"❌ 错误:不支持的记忆类型: {invalid_str}")
|
|
679
660
|
raise typer.Exit(1)
|
|
680
661
|
|
|
681
662
|
count = organizer.export_memories(
|
|
@@ -687,11 +668,11 @@ def export(
|
|
|
687
668
|
if count > 0:
|
|
688
669
|
raise typer.Exit(0)
|
|
689
670
|
else:
|
|
690
|
-
|
|
671
|
+
print("⚠️ 没有找到要导出的记忆")
|
|
691
672
|
raise typer.Exit(0)
|
|
692
673
|
|
|
693
674
|
except Exception as e:
|
|
694
|
-
|
|
675
|
+
print(f"❌ 导出失败: {str(e)}")
|
|
695
676
|
raise typer.Exit(1)
|
|
696
677
|
|
|
697
678
|
|
|
@@ -731,21 +712,21 @@ def import_memories(
|
|
|
731
712
|
if total_imported > 0:
|
|
732
713
|
raise typer.Exit(0)
|
|
733
714
|
else:
|
|
734
|
-
|
|
715
|
+
print("⚠️ 没有导入任何记忆")
|
|
735
716
|
raise typer.Exit(0)
|
|
736
717
|
|
|
737
718
|
except FileNotFoundError as e:
|
|
738
|
-
|
|
719
|
+
print(f"❌ {str(e)}")
|
|
739
720
|
raise typer.Exit(1)
|
|
740
721
|
except Exception as e:
|
|
741
|
-
|
|
722
|
+
print(f"❌ 导入失败: {str(e)}")
|
|
742
723
|
raise typer.Exit(1)
|
|
743
724
|
|
|
744
725
|
|
|
745
726
|
def main():
|
|
746
727
|
"""Application entry point"""
|
|
747
728
|
# 统一初始化环境
|
|
748
|
-
init_env(
|
|
729
|
+
init_env()
|
|
749
730
|
app()
|
|
750
731
|
|
|
751
732
|
|