jarvis-ai-assistant 0.7.8__py3-none-any.whl → 1.0.2__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 +567 -222
- jarvis/jarvis_agent/agent_manager.py +19 -12
- jarvis/jarvis_agent/builtin_input_handler.py +79 -11
- jarvis/jarvis_agent/config_editor.py +7 -2
- jarvis/jarvis_agent/event_bus.py +24 -13
- jarvis/jarvis_agent/events.py +19 -1
- jarvis/jarvis_agent/file_context_handler.py +67 -64
- jarvis/jarvis_agent/file_methodology_manager.py +38 -24
- jarvis/jarvis_agent/jarvis.py +186 -114
- jarvis/jarvis_agent/language_extractors/__init__.py +8 -1
- jarvis/jarvis_agent/language_extractors/c_extractor.py +7 -4
- jarvis/jarvis_agent/language_extractors/cpp_extractor.py +9 -4
- jarvis/jarvis_agent/language_extractors/go_extractor.py +7 -4
- jarvis/jarvis_agent/language_extractors/java_extractor.py +27 -20
- jarvis/jarvis_agent/language_extractors/javascript_extractor.py +22 -17
- jarvis/jarvis_agent/language_extractors/python_extractor.py +7 -4
- jarvis/jarvis_agent/language_extractors/rust_extractor.py +7 -4
- jarvis/jarvis_agent/language_extractors/typescript_extractor.py +22 -17
- jarvis/jarvis_agent/language_support_info.py +250 -219
- jarvis/jarvis_agent/main.py +19 -23
- jarvis/jarvis_agent/memory_manager.py +9 -6
- jarvis/jarvis_agent/methodology_share_manager.py +21 -15
- jarvis/jarvis_agent/output_handler.py +4 -2
- jarvis/jarvis_agent/prompt_builder.py +7 -6
- jarvis/jarvis_agent/prompt_manager.py +113 -8
- jarvis/jarvis_agent/prompts.py +317 -85
- jarvis/jarvis_agent/protocols.py +5 -2
- jarvis/jarvis_agent/run_loop.py +192 -32
- jarvis/jarvis_agent/session_manager.py +7 -3
- jarvis/jarvis_agent/share_manager.py +23 -13
- jarvis/jarvis_agent/shell_input_handler.py +12 -8
- jarvis/jarvis_agent/stdio_redirect.py +25 -26
- jarvis/jarvis_agent/task_analyzer.py +29 -23
- jarvis/jarvis_agent/task_list.py +869 -0
- jarvis/jarvis_agent/task_manager.py +26 -23
- jarvis/jarvis_agent/tool_executor.py +6 -5
- jarvis/jarvis_agent/tool_share_manager.py +24 -14
- jarvis/jarvis_agent/user_interaction.py +3 -3
- jarvis/jarvis_agent/utils.py +9 -1
- jarvis/jarvis_agent/web_bridge.py +37 -17
- jarvis/jarvis_agent/web_output_sink.py +5 -2
- jarvis/jarvis_agent/web_server.py +165 -36
- jarvis/jarvis_c2rust/__init__.py +1 -1
- jarvis/jarvis_c2rust/cli.py +260 -141
- jarvis/jarvis_c2rust/collector.py +37 -18
- jarvis/jarvis_c2rust/constants.py +60 -0
- jarvis/jarvis_c2rust/library_replacer.py +242 -1010
- jarvis/jarvis_c2rust/library_replacer_checkpoint.py +133 -0
- jarvis/jarvis_c2rust/library_replacer_llm.py +287 -0
- jarvis/jarvis_c2rust/library_replacer_loader.py +191 -0
- jarvis/jarvis_c2rust/library_replacer_output.py +134 -0
- jarvis/jarvis_c2rust/library_replacer_prompts.py +124 -0
- jarvis/jarvis_c2rust/library_replacer_utils.py +188 -0
- jarvis/jarvis_c2rust/llm_module_agent.py +98 -1044
- jarvis/jarvis_c2rust/llm_module_agent_apply.py +170 -0
- jarvis/jarvis_c2rust/llm_module_agent_executor.py +288 -0
- jarvis/jarvis_c2rust/llm_module_agent_loader.py +170 -0
- jarvis/jarvis_c2rust/llm_module_agent_prompts.py +268 -0
- jarvis/jarvis_c2rust/llm_module_agent_types.py +57 -0
- jarvis/jarvis_c2rust/llm_module_agent_utils.py +150 -0
- jarvis/jarvis_c2rust/llm_module_agent_validator.py +119 -0
- jarvis/jarvis_c2rust/loaders.py +28 -10
- jarvis/jarvis_c2rust/models.py +5 -2
- jarvis/jarvis_c2rust/optimizer.py +192 -1974
- jarvis/jarvis_c2rust/optimizer_build_fix.py +286 -0
- jarvis/jarvis_c2rust/optimizer_clippy.py +766 -0
- jarvis/jarvis_c2rust/optimizer_config.py +49 -0
- jarvis/jarvis_c2rust/optimizer_docs.py +183 -0
- jarvis/jarvis_c2rust/optimizer_options.py +48 -0
- jarvis/jarvis_c2rust/optimizer_progress.py +469 -0
- jarvis/jarvis_c2rust/optimizer_report.py +52 -0
- jarvis/jarvis_c2rust/optimizer_unsafe.py +309 -0
- jarvis/jarvis_c2rust/optimizer_utils.py +469 -0
- jarvis/jarvis_c2rust/optimizer_visibility.py +185 -0
- jarvis/jarvis_c2rust/scanner.py +229 -166
- jarvis/jarvis_c2rust/transpiler.py +531 -2732
- jarvis/jarvis_c2rust/transpiler_agents.py +503 -0
- jarvis/jarvis_c2rust/transpiler_build.py +1294 -0
- jarvis/jarvis_c2rust/transpiler_codegen.py +204 -0
- jarvis/jarvis_c2rust/transpiler_compile.py +146 -0
- jarvis/jarvis_c2rust/transpiler_config.py +178 -0
- jarvis/jarvis_c2rust/transpiler_context.py +122 -0
- jarvis/jarvis_c2rust/transpiler_executor.py +516 -0
- jarvis/jarvis_c2rust/transpiler_generation.py +278 -0
- jarvis/jarvis_c2rust/transpiler_git.py +163 -0
- jarvis/jarvis_c2rust/transpiler_mod_utils.py +225 -0
- jarvis/jarvis_c2rust/transpiler_modules.py +336 -0
- jarvis/jarvis_c2rust/transpiler_planning.py +394 -0
- jarvis/jarvis_c2rust/transpiler_review.py +1196 -0
- jarvis/jarvis_c2rust/transpiler_symbols.py +176 -0
- jarvis/jarvis_c2rust/utils.py +269 -79
- jarvis/jarvis_code_agent/after_change.py +233 -0
- jarvis/jarvis_code_agent/build_validation_config.py +37 -30
- jarvis/jarvis_code_agent/builtin_rules.py +68 -0
- jarvis/jarvis_code_agent/code_agent.py +976 -1517
- jarvis/jarvis_code_agent/code_agent_build.py +227 -0
- jarvis/jarvis_code_agent/code_agent_diff.py +246 -0
- jarvis/jarvis_code_agent/code_agent_git.py +525 -0
- jarvis/jarvis_code_agent/code_agent_impact.py +177 -0
- jarvis/jarvis_code_agent/code_agent_lint.py +283 -0
- jarvis/jarvis_code_agent/code_agent_llm.py +159 -0
- jarvis/jarvis_code_agent/code_agent_postprocess.py +105 -0
- jarvis/jarvis_code_agent/code_agent_prompts.py +46 -0
- jarvis/jarvis_code_agent/code_agent_rules.py +305 -0
- jarvis/jarvis_code_agent/code_analyzer/__init__.py +52 -48
- jarvis/jarvis_code_agent/code_analyzer/base_language.py +12 -10
- jarvis/jarvis_code_agent/code_analyzer/build_validator/__init__.py +12 -11
- jarvis/jarvis_code_agent/code_analyzer/build_validator/base.py +16 -12
- jarvis/jarvis_code_agent/code_analyzer/build_validator/cmake.py +26 -17
- jarvis/jarvis_code_agent/code_analyzer/build_validator/detector.py +558 -104
- jarvis/jarvis_code_agent/code_analyzer/build_validator/fallback.py +27 -16
- jarvis/jarvis_code_agent/code_analyzer/build_validator/go.py +22 -18
- jarvis/jarvis_code_agent/code_analyzer/build_validator/java_gradle.py +21 -16
- jarvis/jarvis_code_agent/code_analyzer/build_validator/java_maven.py +20 -16
- jarvis/jarvis_code_agent/code_analyzer/build_validator/makefile.py +27 -16
- jarvis/jarvis_code_agent/code_analyzer/build_validator/nodejs.py +47 -23
- jarvis/jarvis_code_agent/code_analyzer/build_validator/python.py +71 -37
- jarvis/jarvis_code_agent/code_analyzer/build_validator/rust.py +162 -35
- jarvis/jarvis_code_agent/code_analyzer/build_validator/validator.py +111 -57
- jarvis/jarvis_code_agent/code_analyzer/build_validator.py +18 -12
- jarvis/jarvis_code_agent/code_analyzer/context_manager.py +185 -183
- jarvis/jarvis_code_agent/code_analyzer/context_recommender.py +2 -1
- jarvis/jarvis_code_agent/code_analyzer/dependency_analyzer.py +24 -15
- jarvis/jarvis_code_agent/code_analyzer/file_ignore.py +227 -141
- jarvis/jarvis_code_agent/code_analyzer/impact_analyzer.py +321 -247
- jarvis/jarvis_code_agent/code_analyzer/language_registry.py +37 -29
- jarvis/jarvis_code_agent/code_analyzer/language_support.py +21 -13
- jarvis/jarvis_code_agent/code_analyzer/languages/__init__.py +15 -9
- jarvis/jarvis_code_agent/code_analyzer/languages/c_cpp_language.py +75 -45
- jarvis/jarvis_code_agent/code_analyzer/languages/go_language.py +87 -52
- jarvis/jarvis_code_agent/code_analyzer/languages/java_language.py +84 -51
- jarvis/jarvis_code_agent/code_analyzer/languages/javascript_language.py +94 -64
- jarvis/jarvis_code_agent/code_analyzer/languages/python_language.py +109 -71
- jarvis/jarvis_code_agent/code_analyzer/languages/rust_language.py +97 -63
- jarvis/jarvis_code_agent/code_analyzer/languages/typescript_language.py +103 -69
- jarvis/jarvis_code_agent/code_analyzer/llm_context_recommender.py +271 -268
- jarvis/jarvis_code_agent/code_analyzer/symbol_extractor.py +76 -64
- jarvis/jarvis_code_agent/code_analyzer/tree_sitter_extractor.py +92 -19
- jarvis/jarvis_code_agent/diff_visualizer.py +998 -0
- jarvis/jarvis_code_agent/lint.py +223 -524
- jarvis/jarvis_code_agent/rule_share_manager.py +158 -0
- jarvis/jarvis_code_agent/rules/clean_code.md +144 -0
- jarvis/jarvis_code_agent/rules/code_review.md +115 -0
- jarvis/jarvis_code_agent/rules/documentation.md +165 -0
- jarvis/jarvis_code_agent/rules/generate_rules.md +52 -0
- jarvis/jarvis_code_agent/rules/performance.md +158 -0
- jarvis/jarvis_code_agent/rules/refactoring.md +139 -0
- jarvis/jarvis_code_agent/rules/security.md +160 -0
- jarvis/jarvis_code_agent/rules/tdd.md +78 -0
- jarvis/jarvis_code_agent/test_rules/cpp_test.md +118 -0
- jarvis/jarvis_code_agent/test_rules/go_test.md +98 -0
- jarvis/jarvis_code_agent/test_rules/java_test.md +99 -0
- jarvis/jarvis_code_agent/test_rules/javascript_test.md +113 -0
- jarvis/jarvis_code_agent/test_rules/php_test.md +117 -0
- jarvis/jarvis_code_agent/test_rules/python_test.md +91 -0
- jarvis/jarvis_code_agent/test_rules/ruby_test.md +102 -0
- jarvis/jarvis_code_agent/test_rules/rust_test.md +86 -0
- jarvis/jarvis_code_agent/utils.py +36 -26
- jarvis/jarvis_code_analysis/checklists/loader.py +21 -21
- jarvis/jarvis_code_analysis/code_review.py +64 -33
- jarvis/jarvis_data/config_schema.json +285 -192
- jarvis/jarvis_git_squash/main.py +8 -6
- jarvis/jarvis_git_utils/git_commiter.py +53 -76
- jarvis/jarvis_mcp/__init__.py +5 -2
- jarvis/jarvis_mcp/sse_mcp_client.py +40 -30
- jarvis/jarvis_mcp/stdio_mcp_client.py +27 -19
- jarvis/jarvis_mcp/streamable_mcp_client.py +35 -26
- jarvis/jarvis_memory_organizer/memory_organizer.py +78 -55
- jarvis/jarvis_methodology/main.py +48 -39
- jarvis/jarvis_multi_agent/__init__.py +56 -23
- jarvis/jarvis_multi_agent/main.py +15 -18
- jarvis/jarvis_platform/base.py +179 -111
- jarvis/jarvis_platform/human.py +27 -16
- jarvis/jarvis_platform/kimi.py +52 -45
- jarvis/jarvis_platform/openai.py +101 -40
- jarvis/jarvis_platform/registry.py +51 -33
- jarvis/jarvis_platform/tongyi.py +68 -38
- jarvis/jarvis_platform/yuanbao.py +59 -43
- jarvis/jarvis_platform_manager/main.py +68 -76
- jarvis/jarvis_platform_manager/service.py +24 -14
- jarvis/jarvis_rag/README_CONFIG.md +314 -0
- jarvis/jarvis_rag/README_DYNAMIC_LOADING.md +311 -0
- jarvis/jarvis_rag/README_ONLINE_MODELS.md +230 -0
- jarvis/jarvis_rag/__init__.py +57 -4
- jarvis/jarvis_rag/cache.py +3 -1
- jarvis/jarvis_rag/cli.py +48 -68
- jarvis/jarvis_rag/embedding_interface.py +39 -0
- jarvis/jarvis_rag/embedding_manager.py +7 -230
- jarvis/jarvis_rag/embeddings/__init__.py +41 -0
- jarvis/jarvis_rag/embeddings/base.py +114 -0
- jarvis/jarvis_rag/embeddings/cohere.py +66 -0
- jarvis/jarvis_rag/embeddings/edgefn.py +117 -0
- jarvis/jarvis_rag/embeddings/local.py +260 -0
- jarvis/jarvis_rag/embeddings/openai.py +62 -0
- jarvis/jarvis_rag/embeddings/registry.py +293 -0
- jarvis/jarvis_rag/llm_interface.py +8 -6
- jarvis/jarvis_rag/query_rewriter.py +8 -9
- jarvis/jarvis_rag/rag_pipeline.py +61 -52
- jarvis/jarvis_rag/reranker.py +7 -75
- jarvis/jarvis_rag/reranker_interface.py +32 -0
- jarvis/jarvis_rag/rerankers/__init__.py +41 -0
- jarvis/jarvis_rag/rerankers/base.py +109 -0
- jarvis/jarvis_rag/rerankers/cohere.py +67 -0
- jarvis/jarvis_rag/rerankers/edgefn.py +140 -0
- jarvis/jarvis_rag/rerankers/jina.py +79 -0
- jarvis/jarvis_rag/rerankers/local.py +89 -0
- jarvis/jarvis_rag/rerankers/registry.py +293 -0
- jarvis/jarvis_rag/retriever.py +58 -43
- jarvis/jarvis_sec/__init__.py +66 -141
- jarvis/jarvis_sec/agents.py +21 -17
- jarvis/jarvis_sec/analysis.py +80 -33
- jarvis/jarvis_sec/checkers/__init__.py +7 -13
- jarvis/jarvis_sec/checkers/c_checker.py +356 -164
- jarvis/jarvis_sec/checkers/rust_checker.py +47 -29
- jarvis/jarvis_sec/cli.py +43 -21
- jarvis/jarvis_sec/clustering.py +430 -272
- jarvis/jarvis_sec/file_manager.py +99 -55
- jarvis/jarvis_sec/parsers.py +9 -6
- jarvis/jarvis_sec/prompts.py +4 -3
- jarvis/jarvis_sec/report.py +44 -22
- jarvis/jarvis_sec/review.py +180 -107
- jarvis/jarvis_sec/status.py +50 -41
- jarvis/jarvis_sec/types.py +3 -0
- jarvis/jarvis_sec/utils.py +160 -83
- jarvis/jarvis_sec/verification.py +411 -181
- jarvis/jarvis_sec/workflow.py +132 -21
- jarvis/jarvis_smart_shell/main.py +28 -41
- jarvis/jarvis_stats/cli.py +14 -12
- jarvis/jarvis_stats/stats.py +28 -19
- jarvis/jarvis_stats/storage.py +14 -8
- jarvis/jarvis_stats/visualizer.py +12 -7
- jarvis/jarvis_tools/base.py +5 -2
- jarvis/jarvis_tools/clear_memory.py +13 -9
- jarvis/jarvis_tools/cli/main.py +23 -18
- jarvis/jarvis_tools/edit_file.py +572 -873
- jarvis/jarvis_tools/execute_script.py +10 -7
- jarvis/jarvis_tools/file_analyzer.py +7 -8
- jarvis/jarvis_tools/meta_agent.py +287 -0
- jarvis/jarvis_tools/methodology.py +5 -3
- jarvis/jarvis_tools/read_code.py +305 -1438
- jarvis/jarvis_tools/read_symbols.py +50 -17
- jarvis/jarvis_tools/read_webpage.py +19 -18
- jarvis/jarvis_tools/registry.py +435 -156
- jarvis/jarvis_tools/retrieve_memory.py +16 -11
- jarvis/jarvis_tools/save_memory.py +8 -6
- jarvis/jarvis_tools/search_web.py +31 -31
- jarvis/jarvis_tools/sub_agent.py +32 -28
- jarvis/jarvis_tools/sub_code_agent.py +44 -60
- jarvis/jarvis_tools/task_list_manager.py +1811 -0
- jarvis/jarvis_tools/virtual_tty.py +29 -19
- jarvis/jarvis_utils/__init__.py +4 -0
- jarvis/jarvis_utils/builtin_replace_map.py +2 -1
- jarvis/jarvis_utils/clipboard.py +9 -8
- jarvis/jarvis_utils/collections.py +331 -0
- jarvis/jarvis_utils/config.py +699 -194
- jarvis/jarvis_utils/dialogue_recorder.py +294 -0
- jarvis/jarvis_utils/embedding.py +6 -3
- jarvis/jarvis_utils/file_processors.py +7 -1
- jarvis/jarvis_utils/fzf.py +9 -3
- jarvis/jarvis_utils/git_utils.py +71 -42
- jarvis/jarvis_utils/globals.py +116 -32
- jarvis/jarvis_utils/http.py +6 -2
- jarvis/jarvis_utils/input.py +318 -83
- jarvis/jarvis_utils/jsonnet_compat.py +119 -104
- jarvis/jarvis_utils/methodology.py +37 -28
- jarvis/jarvis_utils/output.py +201 -44
- jarvis/jarvis_utils/utils.py +986 -628
- {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/METADATA +49 -33
- jarvis_ai_assistant-1.0.2.dist-info/RECORD +304 -0
- jarvis/jarvis_code_agent/code_analyzer/structured_code.py +0 -556
- jarvis/jarvis_tools/generate_new_tool.py +0 -205
- jarvis/jarvis_tools/lsp_client.py +0 -1552
- jarvis/jarvis_tools/rewrite_file.py +0 -105
- jarvis_ai_assistant-0.7.8.dist-info/RECORD +0 -218
- {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/top_level.txt +0 -0
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
import json
|
|
3
3
|
import threading
|
|
4
|
-
from typing import Any
|
|
4
|
+
from typing import Any
|
|
5
|
+
from typing import Callable
|
|
6
|
+
from typing import Dict
|
|
7
|
+
from typing import List
|
|
8
|
+
from typing import cast
|
|
5
9
|
from urllib.parse import urljoin
|
|
6
10
|
|
|
7
|
-
import requests
|
|
11
|
+
import requests
|
|
8
12
|
|
|
9
13
|
from jarvis.jarvis_mcp import McpClient
|
|
14
|
+
from jarvis.jarvis_utils.output import PrettyOutput
|
|
10
15
|
|
|
11
16
|
|
|
12
17
|
class StreamableMcpClient(McpClient):
|
|
@@ -48,12 +53,12 @@ class StreamableMcpClient(McpClient):
|
|
|
48
53
|
self.timeout = config.get("timeout", (10, 300))
|
|
49
54
|
|
|
50
55
|
# 请求相关属性
|
|
51
|
-
self.pending_requests: Dict[
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
self.request_results: Dict[
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
self.pending_requests: Dict[
|
|
57
|
+
str, threading.Event
|
|
58
|
+
] = {} # 存储等待响应的请求 {id: Event}
|
|
59
|
+
self.request_results: Dict[
|
|
60
|
+
str, Dict[str, Any]
|
|
61
|
+
] = {} # 存储请求结果 {id: result}
|
|
57
62
|
self.notification_handlers: Dict[str, List[Callable]] = {}
|
|
58
63
|
self.event_lock = threading.Lock()
|
|
59
64
|
self.request_id_counter = 0
|
|
@@ -85,7 +90,7 @@ class StreamableMcpClient(McpClient):
|
|
|
85
90
|
self._send_notification("notifications/initialized", {})
|
|
86
91
|
|
|
87
92
|
except Exception as e:
|
|
88
|
-
|
|
93
|
+
PrettyOutput.auto_print(f"❌ MCP初始化失败: {str(e)}")
|
|
89
94
|
raise
|
|
90
95
|
|
|
91
96
|
def register_notification_handler(self, method: str, handler: Callable) -> None:
|
|
@@ -176,30 +181,34 @@ class StreamableMcpClient(McpClient):
|
|
|
176
181
|
notify_method = data.get("method", "")
|
|
177
182
|
params = data.get("params", {})
|
|
178
183
|
if notify_method in self.notification_handlers:
|
|
179
|
-
for handler in self.notification_handlers[
|
|
184
|
+
for handler in self.notification_handlers[
|
|
185
|
+
notify_method
|
|
186
|
+
]:
|
|
180
187
|
try:
|
|
181
188
|
handler(params)
|
|
182
189
|
except Exception as e:
|
|
183
|
-
error_lines.append(
|
|
190
|
+
error_lines.append(
|
|
191
|
+
f"处理通知时出错 ({notify_method}): {e}"
|
|
192
|
+
)
|
|
184
193
|
except Exception:
|
|
185
194
|
warning_lines.append(f"无法解析响应: {line}")
|
|
186
195
|
continue
|
|
187
196
|
|
|
188
197
|
if warning_lines:
|
|
189
|
-
joined_warnings =
|
|
190
|
-
|
|
198
|
+
joined_warnings = "\n".join(warning_lines)
|
|
199
|
+
PrettyOutput.auto_print(f"⚠️ {joined_warnings}")
|
|
191
200
|
if error_lines:
|
|
192
|
-
joined_errors =
|
|
193
|
-
|
|
201
|
+
joined_errors = "\n".join(error_lines)
|
|
202
|
+
PrettyOutput.auto_print(f"❌ {joined_errors}")
|
|
194
203
|
# Ensure response is closed after streaming
|
|
195
204
|
response.close()
|
|
196
205
|
if result is None:
|
|
197
206
|
raise RuntimeError(f"未收到响应: {method}")
|
|
198
207
|
|
|
199
|
-
return result
|
|
208
|
+
return cast(Dict[str, Any], result)
|
|
200
209
|
|
|
201
210
|
except Exception as e:
|
|
202
|
-
|
|
211
|
+
PrettyOutput.auto_print(f"❌ 发送请求失败: {str(e)}")
|
|
203
212
|
raise
|
|
204
213
|
finally:
|
|
205
214
|
# 清理请求状态
|
|
@@ -227,7 +236,7 @@ class StreamableMcpClient(McpClient):
|
|
|
227
236
|
response.close()
|
|
228
237
|
|
|
229
238
|
except Exception as e:
|
|
230
|
-
|
|
239
|
+
PrettyOutput.auto_print(f"❌ 发送通知失败: {str(e)}")
|
|
231
240
|
raise
|
|
232
241
|
|
|
233
242
|
def get_tool_list(self) -> List[Dict[str, Any]]:
|
|
@@ -270,10 +279,10 @@ class StreamableMcpClient(McpClient):
|
|
|
270
279
|
else:
|
|
271
280
|
error_msg += ": 未知错误"
|
|
272
281
|
|
|
273
|
-
|
|
282
|
+
PrettyOutput.auto_print(f"❌ {error_msg}")
|
|
274
283
|
return []
|
|
275
284
|
except Exception as e:
|
|
276
|
-
|
|
285
|
+
PrettyOutput.auto_print(f"❌ 获取工具列表失败: {str(e)}")
|
|
277
286
|
return []
|
|
278
287
|
|
|
279
288
|
def execute(self, tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:
|
|
@@ -312,7 +321,7 @@ class StreamableMcpClient(McpClient):
|
|
|
312
321
|
"stderr": response.get("error", "Unknown error"),
|
|
313
322
|
}
|
|
314
323
|
except Exception as e:
|
|
315
|
-
|
|
324
|
+
PrettyOutput.auto_print(f"❌ 执行工具失败: {str(e)}")
|
|
316
325
|
return {"success": False, "stdout": "", "stderr": str(e)}
|
|
317
326
|
|
|
318
327
|
def get_resource_list(self) -> List[Dict[str, Any]]:
|
|
@@ -328,17 +337,17 @@ class StreamableMcpClient(McpClient):
|
|
|
328
337
|
try:
|
|
329
338
|
response = self._send_request("resources/list", {})
|
|
330
339
|
if "result" in response and "resources" in response["result"]:
|
|
331
|
-
return response["result"]["resources"]
|
|
340
|
+
return cast(List[Dict[str, Any]], response["result"]["resources"])
|
|
332
341
|
else:
|
|
333
342
|
error_msg = "获取资源列表失败"
|
|
334
343
|
if "error" in response:
|
|
335
344
|
error_msg += f": {response['error']}"
|
|
336
345
|
else:
|
|
337
346
|
error_msg += ": 未知错误"
|
|
338
|
-
|
|
347
|
+
PrettyOutput.auto_print(f"❌ {error_msg}")
|
|
339
348
|
return []
|
|
340
349
|
except Exception as e:
|
|
341
|
-
|
|
350
|
+
PrettyOutput.auto_print(f"❌ 获取资源列表失败: {str(e)}")
|
|
342
351
|
return []
|
|
343
352
|
|
|
344
353
|
def get_resource(self, uri: str) -> Dict[str, Any]:
|
|
@@ -379,11 +388,11 @@ class StreamableMcpClient(McpClient):
|
|
|
379
388
|
error_msg += f": {response['error']}"
|
|
380
389
|
else:
|
|
381
390
|
error_msg += ": 未知错误"
|
|
382
|
-
|
|
391
|
+
PrettyOutput.auto_print(f"❌ {error_msg}")
|
|
383
392
|
return {"success": False, "stdout": "", "stderr": error_msg}
|
|
384
393
|
except Exception as e:
|
|
385
394
|
error_msg = f"获取资源内容失败: {str(e)}"
|
|
386
|
-
|
|
395
|
+
PrettyOutput.auto_print(f"❌ {error_msg}")
|
|
387
396
|
return {"success": False, "stdout": "", "stderr": error_msg}
|
|
388
397
|
|
|
389
398
|
def __del__(self):
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
3
1
|
"""
|
|
4
2
|
记忆整理工具 - 用于合并具有相似标签的记忆
|
|
5
3
|
|
|
@@ -9,16 +7,23 @@
|
|
|
9
7
|
import json
|
|
10
8
|
from collections import defaultdict
|
|
11
9
|
from pathlib import Path
|
|
12
|
-
|
|
10
|
+
|
|
11
|
+
from jarvis.jarvis_utils.output import PrettyOutput
|
|
12
|
+
|
|
13
|
+
#!/usr/bin/env python3
|
|
14
|
+
# -*- coding: utf-8 -*-
|
|
15
|
+
from typing import Any
|
|
16
|
+
from typing import Dict
|
|
17
|
+
from typing import List
|
|
18
|
+
from typing import Optional
|
|
19
|
+
from typing import Set
|
|
13
20
|
|
|
14
21
|
import typer
|
|
15
22
|
|
|
16
|
-
from jarvis.jarvis_utils.config import (
|
|
17
|
-
get_data_dir,
|
|
18
|
-
get_normal_platform_name,
|
|
19
|
-
get_normal_model_name,
|
|
20
|
-
)
|
|
21
23
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
24
|
+
from jarvis.jarvis_utils.config import get_data_dir
|
|
25
|
+
from jarvis.jarvis_utils.config import get_normal_model_name
|
|
26
|
+
from jarvis.jarvis_utils.config import get_normal_platform_name
|
|
22
27
|
from jarvis.jarvis_utils.utils import init_env
|
|
23
28
|
|
|
24
29
|
|
|
@@ -74,8 +79,8 @@ class MemoryOrganizer:
|
|
|
74
79
|
error_lines.append(f"读取记忆文件 {memory_file} 失败: {str(e)}")
|
|
75
80
|
|
|
76
81
|
if error_lines:
|
|
77
|
-
joined_errors =
|
|
78
|
-
|
|
82
|
+
joined_errors = "\n".join(error_lines)
|
|
83
|
+
PrettyOutput.auto_print(f"⚠️ {joined_errors}")
|
|
79
84
|
|
|
80
85
|
return memories
|
|
81
86
|
|
|
@@ -161,11 +166,11 @@ class MemoryOrganizer:
|
|
|
161
166
|
prompt = f"""请将以下{len(memories)}个相关记忆合并成一个综合性的记忆。
|
|
162
167
|
|
|
163
168
|
原始记忆(按时间从新到旧排序):
|
|
164
|
-
{"="*50}
|
|
169
|
+
{"=" * 50}
|
|
165
170
|
{memory_contents_str}
|
|
166
|
-
{"="*50}
|
|
171
|
+
{"=" * 50}
|
|
167
172
|
|
|
168
|
-
原始标签集合:{
|
|
173
|
+
原始标签集合:{", ".join(sorted(all_tags))}
|
|
169
174
|
|
|
170
175
|
请完成以下任务:
|
|
171
176
|
1. 分析这些记忆的共同主题和关键信息
|
|
@@ -193,14 +198,18 @@ class MemoryOrganizer:
|
|
|
193
198
|
"""
|
|
194
199
|
|
|
195
200
|
try:
|
|
201
|
+
if self.platform is None:
|
|
202
|
+
raise ValueError("Platform is not initialized")
|
|
203
|
+
|
|
196
204
|
# 调用大模型 - 收集完整响应
|
|
197
205
|
response_parts = []
|
|
198
|
-
for chunk in self.platform.chat(prompt):
|
|
206
|
+
for chunk in self.platform.chat(prompt):
|
|
199
207
|
response_parts.append(chunk)
|
|
200
208
|
response = "".join(response_parts)
|
|
201
209
|
|
|
202
210
|
# 解析响应
|
|
203
211
|
import re
|
|
212
|
+
|
|
204
213
|
from jarvis.jarvis_utils.jsonnet_compat import loads as json5_loads
|
|
205
214
|
|
|
206
215
|
# 提取 <merged_memory> 标签内的内容
|
|
@@ -226,7 +235,7 @@ class MemoryOrganizer:
|
|
|
226
235
|
raise ValueError("无法从模型响应中提取 <merged_memory> 标签内容")
|
|
227
236
|
|
|
228
237
|
except Exception as e:
|
|
229
|
-
|
|
238
|
+
PrettyOutput.auto_print(f"⚠️ 调用大模型合并记忆失败: {str(e)}")
|
|
230
239
|
# 返回 None 表示合并失败,跳过这组记忆
|
|
231
240
|
return None
|
|
232
241
|
|
|
@@ -247,15 +256,17 @@ class MemoryOrganizer:
|
|
|
247
256
|
返回:
|
|
248
257
|
整理结果统计
|
|
249
258
|
"""
|
|
250
|
-
|
|
259
|
+
PrettyOutput.auto_print(
|
|
260
|
+
f"ℹ️ 开始整理{memory_type}类型的记忆,最小重叠标签数: {min_overlap}"
|
|
261
|
+
)
|
|
251
262
|
|
|
252
263
|
# 加载记忆
|
|
253
264
|
memories = self._load_memories(memory_type)
|
|
254
265
|
if not memories:
|
|
255
|
-
|
|
266
|
+
PrettyOutput.auto_print("ℹ️ 没有找到需要整理的记忆")
|
|
256
267
|
return {"processed": 0, "merged": 0}
|
|
257
268
|
|
|
258
|
-
|
|
269
|
+
PrettyOutput.auto_print(f"ℹ️ 加载了 {len(memories)} 个记忆")
|
|
259
270
|
|
|
260
271
|
# 统计信息
|
|
261
272
|
stats = {
|
|
@@ -288,7 +299,9 @@ class MemoryOrganizer:
|
|
|
288
299
|
|
|
289
300
|
if overlap_count in overlap_groups:
|
|
290
301
|
groups = overlap_groups[overlap_count]
|
|
291
|
-
|
|
302
|
+
PrettyOutput.auto_print(
|
|
303
|
+
f"\nℹ️ 发现 {len(groups)} 个具有 {overlap_count} 个重叠标签的记忆组"
|
|
304
|
+
)
|
|
292
305
|
|
|
293
306
|
for group in groups:
|
|
294
307
|
# 将活跃索引转换回原始索引
|
|
@@ -306,8 +319,8 @@ class MemoryOrganizer:
|
|
|
306
319
|
f" - ID: {mem.get('id', '未知')}, "
|
|
307
320
|
f"标签: {', '.join(mem.get('tags', []))[:50]}..."
|
|
308
321
|
)
|
|
309
|
-
joined_lines =
|
|
310
|
-
|
|
322
|
+
joined_lines = "\n".join(lines)
|
|
323
|
+
PrettyOutput.auto_print(f"ℹ️ {joined_lines}")
|
|
311
324
|
|
|
312
325
|
if not dry_run:
|
|
313
326
|
# 合并记忆
|
|
@@ -315,7 +328,7 @@ class MemoryOrganizer:
|
|
|
315
328
|
|
|
316
329
|
# 如果合并失败,跳过这组
|
|
317
330
|
if merged_memory is None:
|
|
318
|
-
|
|
331
|
+
PrettyOutput.auto_print(" ⚠️ 跳过这组记忆的合并")
|
|
319
332
|
continue
|
|
320
333
|
|
|
321
334
|
# 保存新记忆
|
|
@@ -332,14 +345,14 @@ class MemoryOrganizer:
|
|
|
332
345
|
# 标记这些记忆已被删除
|
|
333
346
|
deleted_indices.update(original_indices)
|
|
334
347
|
else:
|
|
335
|
-
|
|
348
|
+
PrettyOutput.auto_print(" ℹ️ [模拟运行] 跳过实际合并")
|
|
336
349
|
|
|
337
350
|
# 显示统计信息
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
351
|
+
PrettyOutput.auto_print("\n✅ 整理完成!")
|
|
352
|
+
PrettyOutput.auto_print(f"ℹ️ 总记忆数: {stats['total_memories']}")
|
|
353
|
+
PrettyOutput.auto_print(f"ℹ️ 处理的组数: {stats['processed_groups']}")
|
|
354
|
+
PrettyOutput.auto_print(f"ℹ️ 合并的记忆数: {stats['merged_memories']}")
|
|
355
|
+
PrettyOutput.auto_print(f"ℹ️ 创建的新记忆数: {stats['created_memories']}")
|
|
343
356
|
|
|
344
357
|
return stats
|
|
345
358
|
|
|
@@ -371,7 +384,9 @@ class MemoryOrganizer:
|
|
|
371
384
|
with open(new_file, "w", encoding="utf-8") as f:
|
|
372
385
|
json.dump(memory, f, ensure_ascii=False, indent=2)
|
|
373
386
|
|
|
374
|
-
|
|
387
|
+
PrettyOutput.auto_print(
|
|
388
|
+
f"✅ 创建新记忆: {memory['id']} (标签: {', '.join(memory['tags'][:3])}...)"
|
|
389
|
+
)
|
|
375
390
|
|
|
376
391
|
# 删除原始记忆文件(先汇总日志,最后统一打印)
|
|
377
392
|
info_lines: List[str] = []
|
|
@@ -382,7 +397,9 @@ class MemoryOrganizer:
|
|
|
382
397
|
file_path = Path(orig_memory["file_path"])
|
|
383
398
|
if file_path.exists():
|
|
384
399
|
file_path.unlink()
|
|
385
|
-
info_lines.append(
|
|
400
|
+
info_lines.append(
|
|
401
|
+
f"删除原始记忆: {orig_memory.get('id', '未知')}"
|
|
402
|
+
)
|
|
386
403
|
else:
|
|
387
404
|
info_lines.append(
|
|
388
405
|
f"原始记忆文件已不存在,跳过删除: {orig_memory.get('id', '未知')}"
|
|
@@ -392,11 +409,11 @@ class MemoryOrganizer:
|
|
|
392
409
|
f"删除记忆文件失败 {orig_memory.get('file_path', '')}: {str(e)}"
|
|
393
410
|
)
|
|
394
411
|
if info_lines:
|
|
395
|
-
joined_info =
|
|
396
|
-
|
|
412
|
+
joined_info = "\n".join(info_lines)
|
|
413
|
+
PrettyOutput.auto_print(f"ℹ️ {joined_info}")
|
|
397
414
|
if warn_lines:
|
|
398
|
-
joined_warn =
|
|
399
|
-
|
|
415
|
+
joined_warn = "\n".join(warn_lines)
|
|
416
|
+
PrettyOutput.auto_print(f"⚠️ {joined_warn}")
|
|
400
417
|
|
|
401
418
|
def export_memories(
|
|
402
419
|
self,
|
|
@@ -441,15 +458,17 @@ class MemoryOrganizer:
|
|
|
441
458
|
|
|
442
459
|
# 统一展示导出进度日志
|
|
443
460
|
if progress_lines:
|
|
444
|
-
joined_progress =
|
|
445
|
-
|
|
461
|
+
joined_progress = "\n".join(progress_lines)
|
|
462
|
+
PrettyOutput.auto_print(f"ℹ️ {joined_progress}")
|
|
446
463
|
|
|
447
464
|
# 保存到文件
|
|
448
465
|
output_file.parent.mkdir(parents=True, exist_ok=True)
|
|
449
466
|
with open(output_file, "w", encoding="utf-8") as f:
|
|
450
467
|
json.dump(all_memories, f, ensure_ascii=False, indent=2)
|
|
451
468
|
|
|
452
|
-
|
|
469
|
+
PrettyOutput.auto_print(
|
|
470
|
+
f"✅ 成功导出 {len(all_memories)} 个记忆到 {output_file}"
|
|
471
|
+
)
|
|
453
472
|
|
|
454
473
|
return len(all_memories)
|
|
455
474
|
|
|
@@ -478,7 +497,7 @@ class MemoryOrganizer:
|
|
|
478
497
|
if not isinstance(memories, list):
|
|
479
498
|
raise ValueError("导入文件格式错误,应为记忆列表")
|
|
480
499
|
|
|
481
|
-
|
|
500
|
+
PrettyOutput.auto_print(f"ℹ️ 准备导入 {len(memories)} 个记忆")
|
|
482
501
|
|
|
483
502
|
# 统计导入结果
|
|
484
503
|
import_stats: Dict[str, int] = defaultdict(int)
|
|
@@ -496,7 +515,7 @@ class MemoryOrganizer:
|
|
|
496
515
|
elif memory_type == "global_long_term":
|
|
497
516
|
memory_dir = self.global_memory_dir / memory_type
|
|
498
517
|
else:
|
|
499
|
-
|
|
518
|
+
PrettyOutput.auto_print(f"⚠️ 跳过不支持的记忆类型: {memory_type}")
|
|
500
519
|
skipped_count += 1
|
|
501
520
|
continue
|
|
502
521
|
|
|
@@ -513,7 +532,7 @@ class MemoryOrganizer:
|
|
|
513
532
|
memory_file = memory_dir / f"{memory_id}.json"
|
|
514
533
|
|
|
515
534
|
if memory_file.exists() and not overwrite:
|
|
516
|
-
|
|
535
|
+
PrettyOutput.auto_print(f"ℹ️ 跳过已存在的记忆: {memory_id}")
|
|
517
536
|
skipped_count += 1
|
|
518
537
|
continue
|
|
519
538
|
|
|
@@ -535,14 +554,17 @@ class MemoryOrganizer:
|
|
|
535
554
|
import_stats[memory_type] += 1
|
|
536
555
|
|
|
537
556
|
# 显示导入结果
|
|
538
|
-
|
|
557
|
+
PrettyOutput.auto_print("\n✅ 导入完成!")
|
|
539
558
|
if import_stats:
|
|
540
|
-
lines = [
|
|
541
|
-
|
|
542
|
-
|
|
559
|
+
lines = [
|
|
560
|
+
f"{memory_type}: 导入了 {count} 个记忆"
|
|
561
|
+
for memory_type, count in import_stats.items()
|
|
562
|
+
]
|
|
563
|
+
joined_lines = "\n".join(lines)
|
|
564
|
+
PrettyOutput.auto_print(f"ℹ️ {joined_lines}")
|
|
543
565
|
|
|
544
566
|
if skipped_count > 0:
|
|
545
|
-
|
|
567
|
+
PrettyOutput.auto_print(f"⚠️ 跳过了 {skipped_count} 个记忆")
|
|
546
568
|
|
|
547
569
|
return dict(import_stats)
|
|
548
570
|
|
|
@@ -570,7 +592,6 @@ def organize(
|
|
|
570
592
|
llm_group: Optional[str] = typer.Option(
|
|
571
593
|
None, "-g", "--llm-group", help="使用的模型组,覆盖配置文件中的设置"
|
|
572
594
|
),
|
|
573
|
-
|
|
574
595
|
):
|
|
575
596
|
"""
|
|
576
597
|
整理和合并具有相似标签的记忆。
|
|
@@ -588,11 +609,13 @@ def organize(
|
|
|
588
609
|
"""
|
|
589
610
|
# 验证参数
|
|
590
611
|
if memory_type not in ["project_long_term", "global_long_term"]:
|
|
591
|
-
|
|
612
|
+
PrettyOutput.auto_print(
|
|
613
|
+
f"❌ 错误:不支持的记忆类型 '{memory_type}',请选择 'project_long_term' 或 'global_long_term'"
|
|
614
|
+
)
|
|
592
615
|
raise typer.Exit(1)
|
|
593
616
|
|
|
594
617
|
if min_overlap < 2:
|
|
595
|
-
|
|
618
|
+
PrettyOutput.auto_print("❌ 错误:最小重叠数必须大于等于2")
|
|
596
619
|
raise typer.Exit(1)
|
|
597
620
|
|
|
598
621
|
# 创建整理器并执行
|
|
@@ -612,7 +635,7 @@ def organize(
|
|
|
612
635
|
# typer.Exit 是正常的退出方式,直接传播
|
|
613
636
|
raise
|
|
614
637
|
except Exception as e:
|
|
615
|
-
|
|
638
|
+
PrettyOutput.auto_print(f"❌ 记忆整理失败: {str(e)}")
|
|
616
639
|
raise typer.Exit(1)
|
|
617
640
|
|
|
618
641
|
|
|
@@ -656,7 +679,7 @@ def export(
|
|
|
656
679
|
invalid_types = [mt for mt in memory_types if mt not in valid_types]
|
|
657
680
|
if invalid_types:
|
|
658
681
|
invalid_str = ", ".join(f"'{mt}'" for mt in invalid_types)
|
|
659
|
-
|
|
682
|
+
PrettyOutput.auto_print(f"❌ 错误:不支持的记忆类型: {invalid_str}")
|
|
660
683
|
raise typer.Exit(1)
|
|
661
684
|
|
|
662
685
|
count = organizer.export_memories(
|
|
@@ -668,11 +691,11 @@ def export(
|
|
|
668
691
|
if count > 0:
|
|
669
692
|
raise typer.Exit(0)
|
|
670
693
|
else:
|
|
671
|
-
|
|
694
|
+
PrettyOutput.auto_print("⚠️ 没有找到要导出的记忆")
|
|
672
695
|
raise typer.Exit(0)
|
|
673
696
|
|
|
674
697
|
except Exception as e:
|
|
675
|
-
|
|
698
|
+
PrettyOutput.auto_print(f"❌ 导出失败: {str(e)}")
|
|
676
699
|
raise typer.Exit(1)
|
|
677
700
|
|
|
678
701
|
|
|
@@ -712,14 +735,14 @@ def import_memories(
|
|
|
712
735
|
if total_imported > 0:
|
|
713
736
|
raise typer.Exit(0)
|
|
714
737
|
else:
|
|
715
|
-
|
|
738
|
+
PrettyOutput.auto_print("⚠️ 没有导入任何记忆")
|
|
716
739
|
raise typer.Exit(0)
|
|
717
740
|
|
|
718
741
|
except FileNotFoundError as e:
|
|
719
|
-
|
|
742
|
+
PrettyOutput.auto_print(f"❌ {str(e)}")
|
|
720
743
|
raise typer.Exit(1)
|
|
721
744
|
except Exception as e:
|
|
722
|
-
|
|
745
|
+
PrettyOutput.auto_print(f"❌ 导入失败: {str(e)}")
|
|
723
746
|
raise typer.Exit(1)
|
|
724
747
|
|
|
725
748
|
|