处理prompt_toolkit
This commit is contained in:
parent
badcce5d2d
commit
30c6532f23
@ -79,7 +79,7 @@ packaging/
|
||||
- 本地已安装 `langgraph` 和 `mcp`,并完成 LangGraph fake 全局流程 smoke。
|
||||
- CLI `analyze` 输出已做敏感字段脱敏。
|
||||
- 增加 `chat` 常驻式 CLI 对话框,支持自然语言分析、参数设置、执行确认、显式回滚、状态查看、事件查看、checkpoint 选择和续跑。
|
||||
- chat 在开发环境可选启用 `rich` / `prompt_toolkit`;PyInstaller 打包环境默认使用普通文本输入,避免交互兼容问题。
|
||||
- chat 在开发环境和默认发布包中都会优先启用 `rich` / `prompt_toolkit`;如果增强输入初始化失败,会自动降级到普通 `input()`。
|
||||
- chat 执行前会归一化参数并展示实际写入脚本配置的值;`script_only` / `hybrid_node_mcp` 会提前检查 `ZIP_FILE_PATH` 是否存在。
|
||||
- chat 执行中会播报每个 action 的开始、完成或失败;action 执行失败会停在当前 checkpoint,不再误报 LangGraph 不可用。
|
||||
- 每个 action 完成后都会进入一次 LLM/规则审核;如果审核建议停止,流程会暂停并给出建议,等待用户 `resume`。
|
||||
|
||||
@ -34,7 +34,7 @@ pam-deploy-agent-linux-x86_64/
|
||||
./run.sh run-deploy --help
|
||||
```
|
||||
|
||||
发布包默认使用普通文本输入,避免 PyInstaller 环境下 `prompt_toolkit` 兼容性问题;输出仍会在可用时使用 `rich` 做更清晰的文本展示。
|
||||
发布包默认会优先使用 `prompt_toolkit` 增强输入,支持更稳定的退格、历史记录和补全;如果增强输入初始化失败,会自动降级到普通 `input()`。输出仍会在可用时使用 `rich` 做更清晰的文本展示。
|
||||
逐 IP action 失败后会保存 checkpoint 并暂停;修复外部环境后输入 `resume` 会从失败 action 重试。回滚不再属于主 workflow 自动分支,需要时在 chat 内输入 `rollback [IP]` 显式执行。
|
||||
chat 会在执行前归一化并展示实际写入脚本配置的参数;`script_only` / `hybrid_node_mcp` 会先检查 `ZIP_FILE_PATH` 是否存在,避免脚本运行后才用默认路径失败。执行过程中每个 action 都会输出开始、完成或失败状态;每个 action 完成后还会自动进入一次 LLM/规则审核,并播报审核开始和审核结果。
|
||||
|
||||
|
||||
@ -44,6 +44,14 @@ else
|
||||
python -m pip install -e .
|
||||
fi
|
||||
|
||||
PYINSTALLER_EXTRA_ARGS=()
|
||||
if python -c "import importlib.util; raise SystemExit(0 if importlib.util.find_spec('prompt_toolkit') else 1)"; then
|
||||
PYINSTALLER_EXTRA_ARGS+=(--collect-submodules prompt_toolkit --collect-data prompt_toolkit)
|
||||
fi
|
||||
if python -c "import importlib.util; raise SystemExit(0 if importlib.util.find_spec('rich') else 1)"; then
|
||||
PYINSTALLER_EXTRA_ARGS+=(--collect-submodules rich)
|
||||
fi
|
||||
|
||||
echo "==> 使用 PyInstaller 生成自带 Python 运行时的可执行目录"
|
||||
python -m PyInstaller \
|
||||
--clean \
|
||||
@ -57,6 +65,7 @@ python -m PyInstaller \
|
||||
--collect-submodules pam_deploy_graph \
|
||||
--collect-submodules langgraph \
|
||||
--hidden-import pam_deploy_graph.cli \
|
||||
"${PYINSTALLER_EXTRA_ARGS[@]}" \
|
||||
packaging/pyinstaller_entry.py
|
||||
|
||||
echo "==> 组装发布目录"
|
||||
|
||||
@ -8,7 +8,6 @@ import shlex
|
||||
import builtins
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
from dataclasses import asdict
|
||||
from pathlib import Path
|
||||
from typing import Any, Callable
|
||||
@ -1058,14 +1057,12 @@ def _build_prompt_input(input_func: InputFunc) -> InputFunc:
|
||||
"""如果安装了 prompt_toolkit,则启用历史记录和命令补全。"""
|
||||
if input_func is not builtins.input:
|
||||
return input_func
|
||||
if getattr(sys, "frozen", False):
|
||||
return input_func
|
||||
try:
|
||||
from prompt_toolkit import PromptSession
|
||||
from prompt_toolkit.completion import WordCompleter
|
||||
from prompt_toolkit.history import FileHistory
|
||||
except ImportError:
|
||||
return input_func
|
||||
return _build_readline_input(input_func)
|
||||
|
||||
commands = [
|
||||
"help",
|
||||
@ -1099,13 +1096,28 @@ def _build_prompt_input(input_func: InputFunc) -> InputFunc:
|
||||
except OSError:
|
||||
history = None
|
||||
|
||||
try:
|
||||
session = PromptSession(
|
||||
history=history,
|
||||
completer=WordCompleter(commands, ignore_case=True, sentence=True),
|
||||
)
|
||||
except Exception:
|
||||
logger.exception("chat prompt_toolkit 初始化失败,降级为普通 input")
|
||||
return _build_readline_input(input_func)
|
||||
return session.prompt
|
||||
|
||||
|
||||
def _build_readline_input(input_func: InputFunc) -> InputFunc:
|
||||
"""在没有 prompt_toolkit 时尽量启用 GNU readline,改善 Linux 终端退格键兼容。"""
|
||||
if input_func is not builtins.input or os.name == "nt":
|
||||
return input_func
|
||||
try:
|
||||
import readline # noqa: F401
|
||||
except ImportError:
|
||||
logger.debug("chat readline 不可用,使用普通 input")
|
||||
return input_func
|
||||
|
||||
|
||||
def _build_output_func(output_func: OutputFunc) -> OutputFunc:
|
||||
"""如果安装了 rich,则使用 rich 输出;否则保持原输出函数。"""
|
||||
if output_func is not builtins.print:
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import builtins
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
@ -370,3 +371,15 @@ def test_prompt_history_creates_runtime_dir(tmp_path: Path, monkeypatch):
|
||||
|
||||
assert callable(prompt)
|
||||
assert (tmp_path / "runtime").is_dir()
|
||||
|
||||
|
||||
def test_prompt_toolkit_enabled_when_frozen(tmp_path: Path, monkeypatch):
|
||||
pytest.importorskip("prompt_toolkit")
|
||||
monkeypatch.chdir(tmp_path)
|
||||
monkeypatch.setattr(sys, "frozen", True, raising=False)
|
||||
|
||||
prompt = _build_prompt_input(builtins.input)
|
||||
|
||||
assert callable(prompt)
|
||||
assert prompt is not builtins.input
|
||||
assert (tmp_path / "runtime").is_dir()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user