feat: sap-cli skill v2.1.0 — self-contained distributable package

- assets/: sap-cli source (v2.1.0, 26 commands, 16 object types)
- references/: tool constraints + error handling (self-contained)
- scripts/setup.py: one-click install/config/verify
- SKILL.md: full command reference + dual-platform install guide
- VERSION: 2.1.0

Built from D:/Codespace/sap-cli via scripts/pack_skill.py
This commit is contained in:
2026-06-13 20:52:24 +08:00
commit 1e39b6da88
49 changed files with 7172 additions and 0 deletions
+124
View File
@@ -0,0 +1,124 @@
"""凭证管理模块。
使用 keyring 库安全存储 SAP 密码,优雅降级到 config.ini。
服务名格式: sap-cli:{host}:{client}
"""
from __future__ import annotations
import argparse
import getpass
import logging
# 从独立模块导入,避免与 config 循环 import
from sapcli.password import ( # noqa: F401 re-export
_KEYRING_AVAILABLE,
_keyring,
_keyring_mod,
_service_name,
get_password,
resolve_password,
)
logger = logging.getLogger("sapcli.auth")
def set_password(host: str, client: str, user: str, password: str) -> bool:
"""存储密码到 keyring。
Returns:
是否成功存储
"""
if not _KEYRING_AVAILABLE:
print(" ✗ keyring 库不可用,无法安全存储密码")
print(" 安装方法: pip install keyring")
return False
try:
_keyring.set_password(_service_name(host, client), user, password)
return True
except Exception as e:
print(f" ✗ 存储密码失败: {e}")
return False
def delete_password(host: str, client: str, user: str) -> bool:
"""从 keyring 删除密码。
Returns:
是否成功删除
"""
if not _KEYRING_AVAILABLE:
print(" ✗ keyring 库不可用")
return False
try:
_keyring.delete_password(_service_name(host, client), user)
return True
except _keyring_mod.errors.PasswordDeleteError:
print(" keyring 中未找到该密码")
return False
except Exception as e:
print(f" ✗ 删除密码失败: {e}")
return False
def cmd_auth_login(args: argparse.Namespace, client=None) -> None:
"""auth login: 交互式保存密码到 keyring。"""
import os
from sapcli.config import load_config
try:
cfg, _ = load_config(getattr(args, "config", None))
except Exception as e:
print(f" ✗ 无法加载配置: {e}")
return
print("=" * 60)
print(" sap-cli 密钥登录")
print("=" * 60)
print(f" 主机: {cfg.host}")
print(f" Client: {cfg.client}")
print(f" 用户: {cfg.user}")
password = getpass.getpass(" 请输入密码: ")
if not password:
print(" ✗ 密码不能为空")
return
if set_password(cfg.host, cfg.client, cfg.user, password):
print(f" ✓ 密码已安全存储到 keyring")
print(f" 服务名: {_service_name(cfg.host, cfg.client)}")
else:
print(" ✗ 密码存储失败")
def cmd_auth_logout(args: argparse.Namespace, client=None) -> None:
"""auth logout: 从 keyring 删除密码。"""
from sapcli.config import load_config
try:
cfg, _ = load_config(getattr(args, "config", None))
except Exception as e:
print(f" ✗ 无法加载配置: {e}")
return
if delete_password(cfg.host, cfg.client, cfg.user):
print(" ✓ 密码已从 keyring 删除")
else:
print(" ✗ 删除失败")
def cmd_auth_status(args: argparse.Namespace, client=None) -> None:
"""auth status: 显示 keyring 状态。"""
print("=" * 60)
print(" sap-cli 密钥状态")
print("=" * 60)
if _KEYRING_AVAILABLE:
print(f" keyring: ✓ 可用")
try:
backend = _keyring.get_keyring().__class__.__name__
print(f" 后端: {backend}")
except Exception:
logger.debug("获取 keyring 后端名称失败", exc_info=True)
else:
print(f" keyring: ✗ 不可用")
print(f" 安装方法: pip install keyring")