jarvis-ai-assistant 0.3.19__tar.gz → 0.3.20__tar.gz
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_ai_assistant-0.3.19/src/jarvis_ai_assistant.egg-info → jarvis_ai_assistant-0.3.20}/PKG-INFO +1 -1
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/pyproject.toml +1 -1
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/setup.py +1 -1
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/__init__.py +1 -1
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/__init__.py +9 -2
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/config_editor.py +1 -1
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/shell_input_handler.py +17 -2
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_platform/ai8.py +0 -4
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_platform_manager/service.py +2 -2
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_smart_shell/main.py +1 -1
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_stats/cli.py +2 -1
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_stats/stats.py +5 -5
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_utils/clipboard.py +1 -1
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_utils/input.py +253 -7
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_utils/output.py +215 -129
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20/src/jarvis_ai_assistant.egg-info}/PKG-INFO +1 -1
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/LICENSE +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/MANIFEST.in +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/README.md +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/setup.cfg +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/agent_manager.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/builtin_input_handler.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/edit_file_handler.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/file_methodology_manager.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/jarvis.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/main.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/memory_manager.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/methodology_share_manager.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/output_handler.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/prompt_builder.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/prompts.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/protocols.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/session_manager.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/share_manager.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/task_analyzer.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/task_manager.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/tool_executor.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/tool_share_manager.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_agent/__init__.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_agent/code_agent.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_agent/lint.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/__init__.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/c_cpp.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/csharp.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/data_format.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/devops.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/docs.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/go.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/infrastructure.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/java.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/javascript.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/kotlin.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/loader.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/php.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/python.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/ruby.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/rust.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/shell.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/sql.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/swift.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/web.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/code_review.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_data/config_schema.json +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_data/tiktoken/9b5ad71b2ce5302211f9c61530b329a4922fc6a4 +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_git_squash/__init__.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_git_squash/main.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_git_utils/git_commiter.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_mcp/__init__.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_mcp/sse_mcp_client.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_mcp/stdio_mcp_client.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_mcp/streamable_mcp_client.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_memory_organizer/__init__.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_memory_organizer/memory_organizer.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_methodology/main.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_multi_agent/__init__.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_multi_agent/main.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_platform/__init__.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_platform/base.py +2 -2
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_platform/human.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_platform/kimi.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_platform/openai.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_platform/registry.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_platform/tongyi.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_platform/yuanbao.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_platform_manager/__init__.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_platform_manager/main.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_rag/__init__.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_rag/cache.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_rag/cli.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_rag/embedding_manager.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_rag/llm_interface.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_rag/query_rewriter.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_rag/rag_pipeline.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_rag/reranker.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_rag/retriever.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_smart_shell/__init__.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_stats/__init__.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_stats/storage.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_stats/visualizer.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/__init__.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/ask_user.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/base.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/clear_memory.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/cli/__init__.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/cli/main.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/edit_file.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/execute_script.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/file_analyzer.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/generate_new_tool.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/methodology.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/read_code.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/read_webpage.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/registry.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/retrieve_memory.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/rewrite_file.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/save_memory.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/search_web.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/virtual_tty.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_utils/__init__.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_utils/builtin_replace_map.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_utils/config.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_utils/embedding.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_utils/file_processors.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_utils/git_utils.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_utils/globals.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_utils/http.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_utils/methodology.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_utils/tag.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_utils/utils.py +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis_ai_assistant.egg-info/SOURCES.txt +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis_ai_assistant.egg-info/dependency_links.txt +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis_ai_assistant.egg-info/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis_ai_assistant.egg-info/requires.txt +0 -0
- {jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis_ai_assistant.egg-info/top_level.txt +0 -0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = "jarvis-ai-assistant"
|
7
|
-
version = "0.3.
|
7
|
+
version = "0.3.20"
|
8
8
|
description = "Jarvis: An AI assistant that uses tools to interact with the system"
|
9
9
|
readme = "README.md"
|
10
10
|
authors = [{ name = "skyfire", email = "skyfireitdiy@hotmail.com" }]
|
@@ -3,7 +3,7 @@ from setuptools import setup, find_packages # type: ignore
|
|
3
3
|
|
4
4
|
setup(
|
5
5
|
name="jarvis-ai-assistant",
|
6
|
-
version="0.3.
|
6
|
+
version="0.3.20",
|
7
7
|
author="skyfire",
|
8
8
|
author_email="skyfireitdiy@hotmail.com",
|
9
9
|
description="An AI assistant that uses various tools to interact with the system",
|
{jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/__init__.py
RENAMED
@@ -223,6 +223,7 @@ class Agent:
|
|
223
223
|
use_analysis: Optional[bool] = None,
|
224
224
|
force_save_memory: Optional[bool] = None,
|
225
225
|
files: Optional[List[str]] = None,
|
226
|
+
confirm_callback: Optional[Callable[[str, bool], bool]] = None,
|
226
227
|
):
|
227
228
|
"""初始化Jarvis Agent实例
|
228
229
|
|
@@ -241,6 +242,7 @@ class Agent:
|
|
241
242
|
use_methodology: 是否使用方法论
|
242
243
|
use_analysis: 是否使用任务分析
|
243
244
|
force_save_memory: 是否强制保存记忆
|
245
|
+
confirm_callback: 用户确认回调函数,签名为 (tip: str, default: bool) -> bool;默认使用CLI的user_confirm
|
244
246
|
"""
|
245
247
|
# 基础属性初始化
|
246
248
|
self.files = files or []
|
@@ -254,6 +256,11 @@ class Agent:
|
|
254
256
|
self.user_data: Dict[str, Any] = {}
|
255
257
|
self.after_tool_call_cb: Optional[Callable[[Agent], None]] = None
|
256
258
|
|
259
|
+
# 用户确认回调:默认使用 CLI 的 user_confirm,可由外部注入以支持 TUI/GUI
|
260
|
+
self.user_confirm: Callable[[str, bool], bool] = (
|
261
|
+
confirm_callback or user_confirm # type: ignore[assignment]
|
262
|
+
)
|
263
|
+
|
257
264
|
# 初始化模型和会话
|
258
265
|
self._init_model(llm_type, model_group)
|
259
266
|
self._init_session()
|
@@ -811,7 +818,7 @@ class Agent:
|
|
811
818
|
return self._complete_task(auto_completed=False)
|
812
819
|
|
813
820
|
if any(handler.can_handle(current_response) for handler in self.output_handler):
|
814
|
-
if user_confirm("检测到有工具调用,是否继续处理工具调用?", True):
|
821
|
+
if self.user_confirm("检测到有工具调用,是否继续处理工具调用?", True):
|
815
822
|
self.session.prompt = f"被用户中断,用户补充信息为:{user_input}\n\n用户同意继续工具调用。"
|
816
823
|
return None # 继续执行工具调用
|
817
824
|
else:
|
@@ -905,7 +912,7 @@ class Agent:
|
|
905
912
|
f"并且存在3个以上标签重叠的记忆。\n"
|
906
913
|
f"是否立即整理记忆库以优化性能和相关性?"
|
907
914
|
)
|
908
|
-
if user_confirm(prompt,
|
915
|
+
if self.user_confirm(prompt, True):
|
909
916
|
PrettyOutput.print(
|
910
917
|
f"正在开始整理 '{scope_name}' ({memory_type}) 记忆库...",
|
911
918
|
OutputType.INFO,
|
{jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/config_editor.py
RENAMED
@@ -40,7 +40,7 @@ class ConfigEditor:
|
|
40
40
|
|
41
41
|
if editor:
|
42
42
|
try:
|
43
|
-
subprocess.run([editor, str(config_file_path)], check=True)
|
43
|
+
subprocess.run([editor, str(config_file_path)], check=True, shell=(platform.system() == "Windows"))
|
44
44
|
raise typer.Exit(code=0)
|
45
45
|
except (subprocess.CalledProcessError, FileNotFoundError) as e:
|
46
46
|
PrettyOutput.print(f"Failed to open editor: {e}", OutputType.ERROR)
|
@@ -11,9 +11,24 @@ def shell_input_handler(user_input: str, agent: Any) -> Tuple[str, bool]:
|
|
11
11
|
if len(cmdline) == 0:
|
12
12
|
return user_input, False
|
13
13
|
else:
|
14
|
-
|
14
|
+
marker = "# JARVIS-NOCONFIRM"
|
15
|
+
|
16
|
+
def _clean(line: str) -> str:
|
17
|
+
s = line[1:] # remove leading '!'
|
18
|
+
# strip no-confirm marker if present
|
19
|
+
idx = s.find(marker)
|
20
|
+
if idx != -1:
|
21
|
+
s = s[:idx]
|
22
|
+
return s.rstrip()
|
23
|
+
|
24
|
+
# Build script while stripping the no-confirm marker from each line
|
25
|
+
script = "\n".join([_clean(c) for c in cmdline])
|
15
26
|
PrettyOutput.print(script, OutputType.CODE, lang="bash")
|
16
|
-
|
27
|
+
|
28
|
+
# If any line contains the no-confirm marker, skip the pre-execution confirmation
|
29
|
+
no_confirm = any(marker in c for c in cmdline)
|
30
|
+
|
31
|
+
if no_confirm or user_confirm(f"是否要执行以上shell脚本?", default=True):
|
17
32
|
from jarvis.jarvis_tools.registry import ToolRegistry
|
18
33
|
|
19
34
|
output = ToolRegistry().handle_tool_calls(
|
@@ -50,10 +50,6 @@ class AI8Model(BasePlatform):
|
|
50
50
|
}
|
51
51
|
|
52
52
|
self.model_name = os.getenv("JARVIS_MODEL") or "deepseek-chat"
|
53
|
-
if self.model_name not in self.get_available_models():
|
54
|
-
PrettyOutput.print(
|
55
|
-
f"警告: 选择的模型 {self.model_name} 不在可用列表中", OutputType.WARNING
|
56
|
-
)
|
57
53
|
|
58
54
|
def set_model_name(self, model_name: str):
|
59
55
|
"""Set model name"""
|
@@ -108,7 +108,7 @@ def start_service(
|
|
108
108
|
OutputType.INFO,
|
109
109
|
)
|
110
110
|
|
111
|
-
|
111
|
+
|
112
112
|
|
113
113
|
# Platform and model cache
|
114
114
|
platform_instances: Dict[str, Any] = {}
|
@@ -178,7 +178,7 @@ def start_service(
|
|
178
178
|
}
|
179
179
|
)
|
180
180
|
except Exception as exc:
|
181
|
-
print(f"Error getting models for {default_platform}: {str(exc)}")
|
181
|
+
PrettyOutput.print(f"Error getting models for {default_platform}: {str(exc)}", OutputType.ERROR)
|
182
182
|
|
183
183
|
# Return model list
|
184
184
|
return {"object": "list", "data": model_list}
|
@@ -16,6 +16,7 @@ from pathlib import Path
|
|
16
16
|
from .stats import StatsManager
|
17
17
|
from jarvis.jarvis_utils.utils import init_env
|
18
18
|
from jarvis.jarvis_utils.config import get_data_dir
|
19
|
+
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
19
20
|
|
20
21
|
app = typer.Typer(help="Jarvis 统计模块命令行工具")
|
21
22
|
console = Console()
|
@@ -291,7 +292,7 @@ def export(
|
|
291
292
|
|
292
293
|
if output == "json":
|
293
294
|
# JSON格式输出
|
294
|
-
print(json.dumps(data, indent=2, ensure_ascii=False))
|
295
|
+
PrettyOutput.print(json.dumps(data, indent=2, ensure_ascii=False), OutputType.CODE, lang="json")
|
295
296
|
else:
|
296
297
|
# CSV格式输出
|
297
298
|
records = data.get("records", [])
|
@@ -9,6 +9,7 @@ from typing import Dict, List, Optional, Union, Any
|
|
9
9
|
|
10
10
|
from jarvis.jarvis_stats.storage import StatsStorage
|
11
11
|
from jarvis.jarvis_stats.visualizer import StatsVisualizer
|
12
|
+
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
12
13
|
|
13
14
|
|
14
15
|
class StatsManager:
|
@@ -307,7 +308,6 @@ class StatsManager:
|
|
307
308
|
"""
|
308
309
|
storage = StatsManager._get_storage()
|
309
310
|
storage.delete_old_data(days_to_keep)
|
310
|
-
print(f"已清理 {days_to_keep} 天前的数据")
|
311
311
|
|
312
312
|
@staticmethod
|
313
313
|
def remove_metric(metric_name: str) -> bool:
|
@@ -440,7 +440,7 @@ class StatsManager:
|
|
440
440
|
)
|
441
441
|
|
442
442
|
if not aggregated:
|
443
|
-
print(f"没有找到指标 '{metric_name}' 的数据")
|
443
|
+
PrettyOutput.print(f"没有找到指标 '{metric_name}' 的数据", OutputType.WARNING)
|
444
444
|
return
|
445
445
|
|
446
446
|
# 获取指标信息
|
@@ -474,7 +474,7 @@ class StatsManager:
|
|
474
474
|
show_values=True,
|
475
475
|
)
|
476
476
|
|
477
|
-
print(chart)
|
477
|
+
PrettyOutput.print(chart, OutputType.CODE, lang="text")
|
478
478
|
|
479
479
|
# 显示时间范围
|
480
480
|
from rich.panel import Panel
|
@@ -550,7 +550,7 @@ class StatsManager:
|
|
550
550
|
)
|
551
551
|
|
552
552
|
if not aggregated:
|
553
|
-
print(f"没有找到指标 '{metric_name}' 的数据")
|
553
|
+
PrettyOutput.print(f"没有找到指标 '{metric_name}' 的数据", OutputType.WARNING)
|
554
554
|
return
|
555
555
|
|
556
556
|
# 获取指标信息
|
@@ -560,7 +560,7 @@ class StatsManager:
|
|
560
560
|
# 显示汇总
|
561
561
|
summary = visualizer.show_summary(aggregated, metric_name, unit, tags)
|
562
562
|
if summary: # 如果返回了内容才打印(兼容性)
|
563
|
-
print(summary)
|
563
|
+
PrettyOutput.print(summary, OutputType.INFO)
|
564
564
|
|
565
565
|
# 显示时间范围
|
566
566
|
from rich.panel import Panel
|
{jarvis_ai_assistant-0.3.19 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_utils/clipboard.py
RENAMED
@@ -12,7 +12,7 @@ def copy_to_clipboard(text: str) -> None:
|
|
12
12
|
text: 要复制的文本
|
13
13
|
"""
|
14
14
|
PrettyOutput.print("--- 剪贴板内容开始 ---", OutputType.INFO)
|
15
|
-
|
15
|
+
print(text)
|
16
16
|
PrettyOutput.print("--- 剪贴板内容结束 ---", OutputType.INFO)
|
17
17
|
|
18
18
|
system = platform.system()
|
@@ -9,7 +9,10 @@
|
|
9
9
|
- 用于输入控制的自定义键绑定
|
10
10
|
"""
|
11
11
|
import os
|
12
|
+
import sys
|
13
|
+
import base64
|
12
14
|
from typing import Iterable, List
|
15
|
+
import wcwidth
|
13
16
|
|
14
17
|
from colorama import Fore
|
15
18
|
from colorama import Style as ColoramaStyle
|
@@ -41,10 +44,63 @@ from jarvis.jarvis_utils.tag import ot
|
|
41
44
|
|
42
45
|
# Sentinel value to indicate that Ctrl+O was pressed
|
43
46
|
CTRL_O_SENTINEL = "__CTRL_O_PRESSED__"
|
47
|
+
# Sentinel prefix to indicate that Ctrl+F (fzf) inserted content should prefill next prompt
|
48
|
+
FZF_INSERT_SENTINEL_PREFIX = "__FZF_INSERT__::"
|
49
|
+
# Sentinel to request running fzf outside the prompt and then prefill next prompt
|
50
|
+
FZF_REQUEST_SENTINEL_PREFIX = "__FZF_REQUEST__::"
|
44
51
|
|
45
52
|
# Persistent hint marker for multiline input (shown only once across runs)
|
46
53
|
_MULTILINE_HINT_MARK_FILE = os.path.join(get_data_dir(), "multiline_enter_hint_shown")
|
47
54
|
|
55
|
+
def _display_width(s: str) -> int:
|
56
|
+
"""Calculate printable width of a string in terminal columns (handles wide chars)."""
|
57
|
+
try:
|
58
|
+
w = 0
|
59
|
+
for ch in s:
|
60
|
+
cw = wcwidth.wcwidth(ch)
|
61
|
+
if cw is None or cw < 0:
|
62
|
+
# Fallback for unknown width chars (e.g. emoji on some terminals)
|
63
|
+
cw = 1
|
64
|
+
w += cw
|
65
|
+
return w
|
66
|
+
except Exception:
|
67
|
+
return len(s)
|
68
|
+
|
69
|
+
def _calc_prompt_rows(prev_text: str) -> int:
|
70
|
+
"""
|
71
|
+
Estimate how many terminal rows the previous prompt occupied.
|
72
|
+
Considers prompt prefix and soft-wrapping across terminal columns.
|
73
|
+
"""
|
74
|
+
try:
|
75
|
+
cols = os.get_terminal_size().columns
|
76
|
+
except Exception:
|
77
|
+
cols = 80
|
78
|
+
prefix = "👤 > "
|
79
|
+
prefix_w = _display_width(prefix)
|
80
|
+
|
81
|
+
if prev_text is None:
|
82
|
+
return 1
|
83
|
+
|
84
|
+
lines = prev_text.splitlines()
|
85
|
+
if not lines:
|
86
|
+
lines = [""]
|
87
|
+
# If the text ends with a newline, there is a visible empty line at the end.
|
88
|
+
if prev_text.endswith("\n"):
|
89
|
+
lines.append("")
|
90
|
+
total_rows = 0
|
91
|
+
for i, line in enumerate(lines):
|
92
|
+
lw = _display_width(line)
|
93
|
+
if i == 0:
|
94
|
+
width = prefix_w + lw
|
95
|
+
else:
|
96
|
+
width = lw
|
97
|
+
rows = max(1, (width + cols - 1) // cols)
|
98
|
+
total_rows += rows
|
99
|
+
return max(1, total_rows)
|
100
|
+
|
101
|
+
|
102
|
+
|
103
|
+
|
48
104
|
|
49
105
|
def _multiline_hint_already_shown() -> bool:
|
50
106
|
"""Check if the multiline Enter hint has been shown before (persisted)."""
|
@@ -71,7 +127,7 @@ def get_single_line_input(tip: str, default: str = "") -> str:
|
|
71
127
|
"""
|
72
128
|
session: PromptSession = PromptSession(history=None)
|
73
129
|
style = PromptStyle.from_dict({"prompt": "ansicyan", "bottom-toolbar": "fg:#888888"})
|
74
|
-
prompt = FormattedText([("class:prompt", f"👤
|
130
|
+
prompt = FormattedText([("class:prompt", f"👤 > {tip}")])
|
75
131
|
return session.prompt(prompt, default=default, style=style)
|
76
132
|
|
77
133
|
|
@@ -333,7 +389,7 @@ def _show_history_and_copy():
|
|
333
389
|
break
|
334
390
|
|
335
391
|
|
336
|
-
def _get_multiline_input_internal(tip: str) -> str:
|
392
|
+
def _get_multiline_input_internal(tip: str, preset: str | None = None, preset_cursor: int | None = None) -> str:
|
337
393
|
"""
|
338
394
|
Internal function to get multiline input using prompt_toolkit.
|
339
395
|
Returns a sentinel value if Ctrl+O is pressed.
|
@@ -385,6 +441,64 @@ def _get_multiline_input_internal(tip: str) -> str:
|
|
385
441
|
"""Handle Ctrl+O by exiting the prompt and returning the sentinel value."""
|
386
442
|
event.app.exit(result=CTRL_O_SENTINEL)
|
387
443
|
|
444
|
+
@bindings.add("c-t", filter=has_focus(DEFAULT_BUFFER))
|
445
|
+
def _(event):
|
446
|
+
"""Return a shell command like '!bash' for upper input_handler to execute."""
|
447
|
+
def _gen_shell_cmd() -> str: # type: ignore
|
448
|
+
try:
|
449
|
+
import os
|
450
|
+
import shutil
|
451
|
+
|
452
|
+
if os.name == "nt":
|
453
|
+
# Prefer PowerShell if available, otherwise fallback to cmd
|
454
|
+
for name in ("pwsh", "powershell", "cmd"):
|
455
|
+
if name == "cmd" or shutil.which(name):
|
456
|
+
return f"!{name}"
|
457
|
+
else:
|
458
|
+
shell_path = os.environ.get("SHELL", "")
|
459
|
+
if shell_path:
|
460
|
+
base = os.path.basename(shell_path)
|
461
|
+
if base:
|
462
|
+
return f"!{base}"
|
463
|
+
for name in ("fish", "zsh", "bash", "sh"):
|
464
|
+
if shutil.which(name):
|
465
|
+
return f"!{name}"
|
466
|
+
return "!bash"
|
467
|
+
except Exception:
|
468
|
+
return "!bash"
|
469
|
+
|
470
|
+
# Append a special marker to indicate no-confirm execution in shell_input_handler
|
471
|
+
event.app.exit(result=_gen_shell_cmd() + " # JARVIS-NOCONFIRM")
|
472
|
+
|
473
|
+
|
474
|
+
@bindings.add("@", filter=has_focus(DEFAULT_BUFFER), eager=True)
|
475
|
+
def _(event):
|
476
|
+
"""
|
477
|
+
使用 @ 触发 fzf(当 fzf 存在);否则仅插入 @ 以启用内置补全
|
478
|
+
逻辑:
|
479
|
+
- 若检测到系统存在 fzf,则先插入 '@',随后请求外层运行 fzf 并在返回后进行替换/插入
|
480
|
+
- 若不存在 fzf 或发生异常,则直接插入 '@'
|
481
|
+
"""
|
482
|
+
try:
|
483
|
+
import shutil
|
484
|
+
buf = event.current_buffer
|
485
|
+
if shutil.which("fzf") is None:
|
486
|
+
buf.insert_text("@")
|
487
|
+
return
|
488
|
+
# 先插入 '@',以便外层根据最后一个 '@' 进行片段替换
|
489
|
+
buf.insert_text("@")
|
490
|
+
doc = buf.document
|
491
|
+
text = doc.text
|
492
|
+
cursor = doc.cursor_position
|
493
|
+
payload = f"{cursor}:{base64.b64encode(text.encode('utf-8')).decode('ascii')}"
|
494
|
+
event.app.exit(result=FZF_REQUEST_SENTINEL_PREFIX + payload)
|
495
|
+
return
|
496
|
+
except Exception:
|
497
|
+
try:
|
498
|
+
event.current_buffer.insert_text("@")
|
499
|
+
except Exception:
|
500
|
+
pass
|
501
|
+
|
388
502
|
style = PromptStyle.from_dict(
|
389
503
|
{
|
390
504
|
"prompt": "ansibrightmagenta bold",
|
@@ -414,11 +528,17 @@ def _get_multiline_input_internal(tip: str) -> str:
|
|
414
528
|
("class:bt.key", "Ctrl+O"),
|
415
529
|
("class:bt.label", " 历史复制 "),
|
416
530
|
("class:bt.sep", " • "),
|
531
|
+
("class:bt.key", "@"),
|
532
|
+
("class:bt.label", " FZF文件 "),
|
533
|
+
("class:bt.sep", " • "),
|
534
|
+
("class:bt.key", "Ctrl+T"),
|
535
|
+
("class:bt.label", " 终端(!SHELL) "),
|
536
|
+
("class:bt.sep", " • "),
|
417
537
|
("class:bt.key", "Ctrl+C/D"),
|
418
538
|
("class:bt.label", " 取消 "),
|
419
539
|
]
|
420
540
|
)
|
421
|
-
|
541
|
+
|
422
542
|
history_dir = get_data_dir()
|
423
543
|
session: PromptSession = PromptSession(
|
424
544
|
history=FileHistory(os.path.join(history_dir, "multiline_input_history")),
|
@@ -431,14 +551,26 @@ def _get_multiline_input_internal(tip: str) -> str:
|
|
431
551
|
)
|
432
552
|
|
433
553
|
# Tip is shown in bottom toolbar; avoid extra print
|
434
|
-
prompt = FormattedText([("class:prompt", "👤
|
554
|
+
prompt = FormattedText([("class:prompt", "👤 > ")])
|
555
|
+
|
556
|
+
def _pre_run():
|
557
|
+
try:
|
558
|
+
from prompt_toolkit.application.current import get_app as _ga
|
559
|
+
app = _ga()
|
560
|
+
buf = app.current_buffer
|
561
|
+
if preset is not None and preset_cursor is not None:
|
562
|
+
cp = max(0, min(len(buf.text), preset_cursor))
|
563
|
+
buf.cursor_position = cp
|
564
|
+
except Exception:
|
565
|
+
pass
|
435
566
|
|
436
567
|
try:
|
437
568
|
return session.prompt(
|
438
569
|
prompt,
|
439
570
|
style=style,
|
440
|
-
pre_run=
|
571
|
+
pre_run=_pre_run,
|
441
572
|
bottom_toolbar=_bottom_toolbar,
|
573
|
+
default=(preset or ""),
|
442
574
|
).strip()
|
443
575
|
except (KeyboardInterrupt, EOFError):
|
444
576
|
return ""
|
@@ -453,14 +585,128 @@ def get_multiline_input(tip: str, print_on_empty: bool = True) -> str:
|
|
453
585
|
tip: 提示文本,将显示在底部工具栏中
|
454
586
|
print_on_empty: 当输入为空字符串时,是否打印“输入已取消”提示。默认打印。
|
455
587
|
"""
|
588
|
+
preset: str | None = None
|
589
|
+
preset_cursor: int | None = None
|
456
590
|
while True:
|
457
|
-
user_input = _get_multiline_input_internal(tip)
|
591
|
+
user_input = _get_multiline_input_internal(tip, preset=preset, preset_cursor=preset_cursor)
|
458
592
|
|
459
593
|
if user_input == CTRL_O_SENTINEL:
|
460
594
|
_show_history_and_copy()
|
461
595
|
tip = "请继续输入(或按Ctrl+J确认):"
|
462
596
|
continue
|
597
|
+
elif isinstance(user_input, str) and user_input.startswith(FZF_REQUEST_SENTINEL_PREFIX):
|
598
|
+
# Handle fzf request outside the prompt, then prefill new text.
|
599
|
+
try:
|
600
|
+
payload = user_input[len(FZF_REQUEST_SENTINEL_PREFIX) :]
|
601
|
+
sep_index = payload.find(":")
|
602
|
+
cursor = int(payload[:sep_index])
|
603
|
+
text = base64.b64decode(payload[sep_index + 1 :].encode("ascii")).decode("utf-8")
|
604
|
+
except Exception:
|
605
|
+
# Malformed payload; just continue without change.
|
606
|
+
preset = None
|
607
|
+
tip = "FZF 预填失败,继续输入:"
|
608
|
+
continue
|
609
|
+
|
610
|
+
# Run fzf to get a file selection synchronously (outside prompt)
|
611
|
+
selected_path = ""
|
612
|
+
try:
|
613
|
+
import shutil
|
614
|
+
import subprocess
|
615
|
+
|
616
|
+
if shutil.which("fzf") is None:
|
617
|
+
PrettyOutput.print("未检测到 fzf,无法打开文件选择器。", OutputType.WARNING)
|
618
|
+
else:
|
619
|
+
files: list[str] = []
|
620
|
+
try:
|
621
|
+
r = subprocess.run(
|
622
|
+
["git", "ls-files"],
|
623
|
+
stdout=subprocess.PIPE,
|
624
|
+
stderr=subprocess.PIPE,
|
625
|
+
text=True,
|
626
|
+
)
|
627
|
+
if r.returncode == 0:
|
628
|
+
files = [line for line in r.stdout.splitlines() if line.strip()]
|
629
|
+
except Exception:
|
630
|
+
files = []
|
631
|
+
|
632
|
+
if not files:
|
633
|
+
import os as _os
|
634
|
+
for root, _, fnames in _os.walk(".", followlinks=False):
|
635
|
+
for name in fnames:
|
636
|
+
files.append(_os.path.relpath(_os.path.join(root, name), "."))
|
637
|
+
if len(files) > 10000:
|
638
|
+
break
|
639
|
+
|
640
|
+
if not files:
|
641
|
+
PrettyOutput.print("未找到可选择的文件。", OutputType.INFO)
|
642
|
+
else:
|
643
|
+
try:
|
644
|
+
specials = [ot("Summary"), ot("Clear"), ot("ToolUsage"), ot("ReloadConfig"), ot("SaveSession")]
|
645
|
+
except Exception:
|
646
|
+
specials = []
|
647
|
+
items = [s for s in specials if isinstance(s, str) and s.strip()] + files
|
648
|
+
proc = subprocess.run(
|
649
|
+
["fzf", "--prompt", "Files> ", "--height", "40%", "--border"],
|
650
|
+
input="\n".join(items),
|
651
|
+
stdout=subprocess.PIPE,
|
652
|
+
stderr=subprocess.PIPE,
|
653
|
+
text=True,
|
654
|
+
)
|
655
|
+
sel = proc.stdout.strip()
|
656
|
+
if sel:
|
657
|
+
selected_path = sel
|
658
|
+
except Exception as e:
|
659
|
+
PrettyOutput.print(f"FZF 执行失败: {e}", OutputType.ERROR)
|
660
|
+
|
661
|
+
# Compute new text based on selection (or keep original if none)
|
662
|
+
if selected_path:
|
663
|
+
text_before = text[:cursor]
|
664
|
+
last_at = text_before.rfind("@")
|
665
|
+
if last_at != -1 and " " not in text_before[last_at + 1 :]:
|
666
|
+
# Replace @... segment
|
667
|
+
inserted = f"'{selected_path}'"
|
668
|
+
new_text = text[:last_at] + inserted + text[cursor:]
|
669
|
+
new_cursor = last_at + len(inserted)
|
670
|
+
else:
|
671
|
+
# Plain insert
|
672
|
+
inserted = f"'{selected_path}'"
|
673
|
+
new_text = text[:cursor] + inserted + text[cursor:]
|
674
|
+
new_cursor = cursor + len(inserted)
|
675
|
+
preset = new_text
|
676
|
+
preset_cursor = new_cursor
|
677
|
+
tip = "已插入文件,继续编辑或按Ctrl+J确认:"
|
678
|
+
else:
|
679
|
+
# No selection; keep original text and cursor
|
680
|
+
preset = text
|
681
|
+
preset_cursor = cursor
|
682
|
+
tip = "未选择文件或已取消,继续编辑:"
|
683
|
+
# 清除上一条输入行(多行安全),避免多清,保守仅按提示行估算
|
684
|
+
try:
|
685
|
+
rows_total = _calc_prompt_rows(text)
|
686
|
+
for _ in range(rows_total):
|
687
|
+
sys.stdout.write("\x1b[1A") # 光标上移一行
|
688
|
+
sys.stdout.write("\x1b[2K\r") # 清除整行
|
689
|
+
sys.stdout.flush()
|
690
|
+
except Exception:
|
691
|
+
pass
|
692
|
+
continue
|
693
|
+
elif isinstance(user_input, str) and user_input.startswith(FZF_INSERT_SENTINEL_PREFIX):
|
694
|
+
# 从哨兵载荷中提取新文本,作为下次进入提示的预填内容
|
695
|
+
preset = user_input[len(FZF_INSERT_SENTINEL_PREFIX) :]
|
696
|
+
preset_cursor = len(preset)
|
697
|
+
|
698
|
+
# 清除上一条输入行(多行安全),避免多清,保守仅按提示行估算
|
699
|
+
try:
|
700
|
+
rows_total = _calc_prompt_rows(preset)
|
701
|
+
for _ in range(rows_total):
|
702
|
+
sys.stdout.write("\x1b[1A")
|
703
|
+
sys.stdout.write("\x1b[2K\r")
|
704
|
+
sys.stdout.flush()
|
705
|
+
except Exception:
|
706
|
+
pass
|
707
|
+
tip = "已插入文件,继续编辑或按Ctrl+J确认:"
|
708
|
+
continue
|
463
709
|
else:
|
464
710
|
if not user_input and print_on_empty:
|
465
|
-
PrettyOutput.print("
|
711
|
+
PrettyOutput.print("输入已取消", OutputType.INFO)
|
466
712
|
return user_input
|