diff --git a/distribution/linux/euler-copilot-shell.spec b/distribution/linux/euler-copilot-shell.spec index 608f1ccefa48b0af37a6d477fb9d7ea3c6e07227..2667921d1c5dfa7f0876224ca2de44507547dedb 100644 --- a/distribution/linux/euler-copilot-shell.spec +++ b/distribution/linux/euler-copilot-shell.spec @@ -1,4 +1,6 @@ %global pypi_name oi-cli +%global shortcut_name oi +%global debug_package %{nil} Name: euler-copilot-shell Version: 0.10.0 @@ -70,6 +72,9 @@ deactivate mkdir -p %{buildroot}%{_bindir} install -m 0755 dist/%{pypi_name} %{buildroot}%{_bindir}/%{pypi_name} +# 创建快捷链接 +ln -sf %{pypi_name} %{buildroot}%{_bindir}/%{shortcut_name} + # 安装部署脚本和资源 mkdir -p %{buildroot}/usr/lib/openeuler-intelligence/{scripts,resources} mkdir -p %{buildroot}%{_bindir} @@ -86,6 +91,7 @@ ln -sf /usr/lib/openeuler-intelligence/scripts/deploy %{buildroot}%{_bindir}/ope %license LICENSE %doc README.md %{_bindir}/%{pypi_name} +%{_bindir}/%{shortcut_name} %files -n openeuler-intelligence-installer %license LICENSE @@ -94,7 +100,7 @@ ln -sf /usr/lib/openeuler-intelligence/scripts/deploy %{buildroot}%{_bindir}/ope %{_bindir}/openeuler-intelligence-installer %changelog -* %{_builddate} openEuler - 0.10.0-1 +* Wed Aug 13 2025 openEuler - 0.10.0-1 - 重构为子包形式:openeuler-intelligence-cli 和 openeuler-intelligence-installer - openeuler-intelligence-cli 替换原 euler-copilot-shell 包 - 新增 openeuler-intelligence-installer 子包,包含部署安装脚本 \ No newline at end of file diff --git a/scripts/build/build_rpm.sh b/scripts/build/build_rpm.sh old mode 100644 new mode 100755 index a929b299b249eb0f27e586397809f208ef531558..951e0dfb9e3e9881b81892bed506f0b201cbf3a1 --- a/scripts/build/build_rpm.sh +++ b/scripts/build/build_rpm.sh @@ -7,7 +7,13 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" # Create the tarball and set BUILD_DIR and TARBALL -eval "$("${SCRIPT_DIR}/create_tarball.sh")" +eval "$("${SCRIPT_DIR}"/create_tarball.sh)" +set +u +if [[ -z "${BUILD_DIR:-}" || -z "${TARBALL:-}" ]]; then + echo "Error: BUILD_DIR 或 TARBALL 变量未设置,create_tarball.sh 执行失败。" >&2 + exit 1 +fi +set -u # Spec file path SPEC_FILE="${REPO_ROOT}/distribution/linux/euler-copilot-shell.spec" diff --git a/scripts/build/create_tarball.sh b/scripts/build/create_tarball.sh old mode 100644 new mode 100755 index 3f6c8bc5e758200c7e380d2692ba032fa820faa0..baeb4989d493a3590f67985130a2692777808bc5 --- a/scripts/build/create_tarball.sh +++ b/scripts/build/create_tarball.sh @@ -3,21 +3,23 @@ set -euo pipefail # Locate spec file relative to repo root -SPEC_FILE="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)/distribution/linux/euler-copilot-shell.spec" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" +SPEC_FILE="${REPO_ROOT}/distribution/linux/euler-copilot-shell.spec" # Extract name and version from spec NAME=$(grep -E '^Name:' "$SPEC_FILE" | awk '{print $2}') VERSION=$(grep -E '^Version:' "$SPEC_FILE" | awk '{print $2}') -# Create temporary build directory -BUILD_DIR=$(mktemp -d) +# Create build directory in repo +BUILD_DIR="${REPO_ROOT}/build" +mkdir -p "${BUILD_DIR}" TARBALL="${NAME}-${VERSION}.tar.gz" -echo "Creating tarball ${TARBALL} in ${BUILD_DIR}" +echo "Creating tarball ${TARBALL} in ${BUILD_DIR}" >&2 # Archive the current HEAD into tarball with proper prefix git archive --format=tar.gz --prefix="${NAME}-${VERSION}/" -o "${BUILD_DIR}/${TARBALL}" HEAD -# Export variables for reuse by build_rpm.sh -# Usage: eval "$(./create_tarball.sh)" -echo "export BUILD_DIR=${BUILD_DIR}" -echo "export TARBALL=${TARBALL}" +# 输出变量用于 build_rpm.sh 的 eval +echo "BUILD_DIR=${BUILD_DIR}" +echo "TARBALL=${TARBALL}" diff --git a/src/app/mcp_widgets.py b/src/app/mcp_widgets.py index 18a86bcbb470364e039e6cdf47ef20e4ab13cbca..9c930cc15637bfe849767d935a7d00ee98482f36 100644 --- a/src/app/mcp_widgets.py +++ b/src/app/mcp_widgets.py @@ -15,6 +15,10 @@ if TYPE_CHECKING: from backend.hermes.stream import HermesStreamEvent +# 常量定义 +MAX_DISPLAY_LENGTH = 30 # 文本显示最大长度 +TRUNCATE_LENGTH = 27 # 截断时保留的长度 + class MCPConfirmWidget(Container): """MCP 工具执行确认组件""" @@ -57,10 +61,10 @@ class MCPConfirmWidget(Container): markup=False, ) # 显示简化的说明文字,确保按钮可见 - if len(reason) > 30: - # 如果说明太长,显示更短的简化版本 + if len(reason) > MAX_DISPLAY_LENGTH: + # 如果说明太长,显示省略号 yield Static( - "💭 请确认执行", + f"💭 {reason[:TRUNCATE_LENGTH]}...", classes="confirm-reason", markup=False, ) @@ -127,7 +131,7 @@ class MCPConfirmWidget(Container): buttons[0].focus() # 确保组件本身也有焦点,以便键盘事件能正确处理 self.focus() - except Exception: + except (AttributeError, ValueError, IndexError): # 如果聚焦失败,至少确保组件本身有焦点 with contextlib.suppress(Exception): self.focus() @@ -162,8 +166,10 @@ class MCPParameterWidget(Container): # 紧凑的参数输入标题 yield Static("📝 参数输入", classes="param-header", markup=False) yield Static(f"🔧 {step_name}", classes="param-tool", markup=False) - # 只在说明较短时显示 - if len(message) <= 30: + # 显示说明文字,超长时显示省略号 + if len(message) > MAX_DISPLAY_LENGTH: + yield Static(f"💭 {message[:TRUNCATE_LENGTH]}...", classes="param-message", markup=False) + else: yield Static(f"💭 {message}", classes="param-message", markup=False) # 垂直布局的参数输入,更节省空间 diff --git a/src/backend/hermes/client.py b/src/backend/hermes/client.py index 36f2408a97c03820046eed4cec24f7c3ad713686..f1b4fc0db753c463aefe1affc82299d0e2c672fa 100644 --- a/src/backend/hermes/client.py +++ b/src/backend/hermes/client.py @@ -112,16 +112,6 @@ class HermesChatClient(LLMClientBase): self._current_agent_id = agent_id self.logger.info("设置当前智能体ID: %s", agent_id or "无智能体") - def get_current_agent(self) -> str: - """ - 获取当前使用的智能体ID - - Returns: - str: 当前智能体ID,空字符串表示不使用智能体 - - """ - return self._current_agent_id - def reset_conversation(self) -> None: """重置会话,下次聊天时会创建新的会话""" if self._conversation_manager is not None: diff --git a/src/backend/hermes/mcp_helpers.py b/src/backend/hermes/mcp_helpers.py index e7553497539e77e1f8fd6ea102ff1f09fc7425fe..a76a9af7b6dcd0ec05ab41450124d6ddfd7c43ea 100644 --- a/src/backend/hermes/mcp_helpers.py +++ b/src/backend/hermes/mcp_helpers.py @@ -271,21 +271,3 @@ def format_tool_message(tool_name: str, status: str, *, use_emoji: bool = True) return f"{emoji_map[status]} {MCPTextFragments.TOOL_WORD} `{tool_name}` {status}" return f"{MCPTextFragments.TOOL_WORD} `{tool_name}` {status}" - - -def clean_content_for_display(content: str) -> str: - """清理内容以用于显示,移除所有 MCP 标记""" - # 构建正则表达式组件 - replace_prefix = re.escape(MCPTags.REPLACE_PREFIX) - mcp_prefix = re.escape(MCPTags.MCP_PREFIX) - tag_suffix = re.escape(MCPTags.TAG_SUFFIX) - - # 移除 REPLACE 标记 - replace_pattern = f"{replace_prefix}[^{tag_suffix}]+{tag_suffix}" - content = re.sub(replace_pattern, "", content) - - # 移除 MCP 标记 - mcp_pattern = f"{mcp_prefix}[^{tag_suffix}]+{tag_suffix}" - content = re.sub(mcp_pattern, "", content) - - return content.strip() diff --git a/src/backend/hermes/stream.py b/src/backend/hermes/stream.py index b45fc99cfde8190b01cbfee607e846972086100f..020c089e8799759fff5d56a0f663ceab9ef48caa 100644 --- a/src/backend/hermes/stream.py +++ b/src/backend/hermes/stream.py @@ -168,7 +168,7 @@ class HermesStreamProcessor: should_replace = self._should_replace_progress(event, step_id) # 处理特殊的等待状态事件 - if event_type == "step.waiting_for_start": + if event_type == MCPEventTypes.STEP_WAITING_FOR_START: base_message = self._format_waiting_for_start(content, step_name) return self._handle_progress_message( event_type, @@ -178,7 +178,7 @@ class HermesStreamProcessor: should_replace=should_replace, ) - if event_type == "step.waiting_for_param": + if event_type == MCPEventTypes.STEP_WAITING_FOR_PARAM: base_message = self._format_waiting_for_param(content, step_name) return self._handle_progress_message( event_type, @@ -274,7 +274,6 @@ class HermesStreamProcessor: "step_id": step_id, # 保留step_id用于调试 } - # 核心修复:所有的MCP进度消息都应该标记为MCP状态,而不仅仅是需要替换的消息 # 使用工具名称作为标识,确保TUI层面能正确识别为MCP消息 if has_previous_progress: # 如果有之前的进度,说明这是一个状态更新,需要替换 @@ -316,7 +315,3 @@ class HermesStreamProcessor: return True return False - - def get_replacement_info(self, step_id: str) -> dict[str, Any] | None: - """获取指定步骤的替换信息""" - return self._current_tool_progress.get(step_id)