MindOS_CLI/mindcli/capability.py
lidf aecd81ec8b feat: 无状态原子化改造 v0.2.0 — pipelines/ 分层 + 双工录音 + pipx 自动更新修复
## 架构改造

将 recorder/tunnel/managed_mcp 三个有状态单例模块拆成
mindcli/pipelines/ 下的无状态管线 + health.py 调用方持有状态。
参照 hermes-overlay/infra/pipelines/anyfile2md.py 的分层模式。

### pipelines/ 层(无状态)
- audio_capture.py: capture() 工厂函数返回独立 CaptureHandle,
  无单例无互斥,双工模式(system+mic 并行)在代码层面可用
- tunnel_session.py: connect() 工厂函数 + on_status 回调,
  消除 health ⇄ tunnel 循环耦合(单向数据流)
- tool_proxy.py: ToolProxy 替代 ManagedMCP,非单例

### health.py 改造
- _active_captures dict 按 chatId 索引,可多实例并存
- _tunnel_handle 由调用方持有,on_status 回调更新状态
- /record/stop 支持 ?chatId= 停单路或全停
- /record/status 返回所有活跃录音列表

### cli.py 改造
- chat/ask 走 run_agent headless + Cloud Gateway JWT(铁律 A)
- 保留 --offline 走 vendor TUI(铁律 C:断开即自治)
- mind update 修复 pipx 场景:
  - 检测 pipx venv → pipx reinstall
  - 非 pipx → sys.executable -m pip(修复 venv 里 pip 找不到)
  - 防降级保护(远端版本低于本地时不升级)
  - 远端 upgradeCmd 字段下发

### 顺手修复
- health.py / capability.py 的 HERMES_COMMIT → VENDOR_COMMIT
- 版本号 0.1.0 → 0.2.0(__init__.py + pyproject.toml)
- 新增 versions.json 仓库模板(installCmd 改为 pipx,新增 upgradeCmd)

### 删除
- recorder.py → 逻辑迁入 pipelines/audio_capture.py
- tunnel.py → 逻辑迁入 pipelines/tunnel_session.py
- managed_mcp.py → 逻辑迁入 pipelines/tool_proxy.py

SPEC: docs/SPEC_mindcli_atomization.md
2026-07-01 14:56:16 +08:00

80 lines
2.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Mind CLI — 能力扫描器。
扫描本地可用的内置工具和 MCP Server生成 capability report
供 Tunnel 握手时上报给 Cloud。
"""
import os
import platform
from typing import Any
import mindcli
# ── 内置工具注册表 ────────────────────────────────────
# 只暴露 Cloud 端有意义的本地工具(文件操作、终端、搜索等)
# 浏览器工具、TTS 等纯交互工具不上报
_BUILTIN_TOOLS: list[dict[str, str]] = [
{"name": "terminal", "type": "builtin", "desc": "执行终端命令"},
{"name": "file_read", "type": "builtin", "desc": "读取本地文件"},
{"name": "file_write", "type": "builtin", "desc": "写入本地文件"},
{"name": "file_ops", "type": "builtin", "desc": "文件操作(复制/移动/删除)"},
{"name": "grep", "type": "builtin", "desc": "文本搜索"},
{"name": "code_execution", "type": "builtin", "desc": "执行代码片段"},
]
def scan_capabilities() -> dict[str, Any]:
"""
扫描本地可用工具,返回 capability report。
返回格式:
{
"version": "0.1.0",
"vendor": "16f9d020",
"platform": "Darwin",
"arch": "arm64",
"python": "3.12.11",
"tools": [
{"name": "terminal", "type": "builtin", "desc": "..."},
...
],
"mcp_servers": [] # Phase 2+ 从 config.yaml 读取
}
"""
import sys
return {
"version": mindcli.__version__,
"vendor": _get_vendor_commit(),
"platform": platform.system(),
"arch": platform.machine(),
"python": f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}",
"tools": list(_BUILTIN_TOOLS),
"mcp_servers": _scan_mcp_servers(),
}
def get_tool_names() -> list[str]:
"""返回所有内置工具名称列表。"""
return [t["name"] for t in _BUILTIN_TOOLS]
def _scan_mcp_servers() -> list[dict[str, str]]:
"""
扫描用户配置的第三方 MCP Server。
TODO: 从 ~/.mindcli/config.yaml 的 mcp_servers 段读取。
"""
return []
def _get_vendor_commit() -> str:
commit_file = os.path.join(mindcli._VENDOR_DIR, "VENDOR_COMMIT")
try:
with open(commit_file) as f:
return f.read().strip()
except FileNotFoundError:
return "unknown"