Files
ai-shell/ai_shell/main.py
zackeryyy wang c4d1510ce9 feat: 新增现代化命令替代功能 v0.2.0
🎯 主要功能:
- 智能检测系统中已安装的现代化命令行工具
- 支持 44 种默认命令映射 (ls→eza, cat→bat, find→fd 等)
- 灵活的环境变量配置系统
- AI 提示词集成,优先推荐现代化工具
- 完整的配置状态显示

⚙️ 配置方式:
- 环境变量: AI_SHELL_MODERN_COMMANDS="ls:eza,cat:bat"
- .env 文件配置支持
- 动态配置检测和合并

🔧 技术实现:
- 新增 get_modern_commands() 配置管理
- 新增 get_available_modern_commands() 系统检测
- 新增 generate_modern_commands_prompt() 提示词生成
- 更新 AI agent 系统提示词
- 完善配置显示和测试脚本

📊 支持的现代化工具:
文件操作: eza, bat, fd, tree
文本处理: rg, sd, choose, delta
系统监控: procs, htop, ncdu, duf
网络工具: gping, httpie, aria2c
编辑器: nvim, micro
其他: zoxide, trash, ouch, pnpm
2025-07-12 22:32:09 +08:00

166 lines
5.1 KiB
Python

"""
Main entry point for AI Shell
"""
import os
import sys
import argparse
from typing import List, Optional
from .agent import create_agent
from . import __version__
def execute_command(command: str) -> None:
"""Execute a shell command"""
os.system(command)
def get_user_confirmation(command: str) -> bool:
"""Get user confirmation before executing command"""
print(f"(AI Answer): {command}")
response = input("Execute? [Y/n]: ").strip().lower()
return response in ["", "y", "yes"]
def process_prompt(prompt: str) -> None:
"""Process user prompt and generate shell command"""
if not prompt.strip():
print("Error: No prompt provided")
sys.exit(1)
# Create AI agent
agent = create_agent()
try:
# Generate response
resp = agent.run_sync(prompt)
answer = resp.output
if answer.success and answer.cmd is not None:
if get_user_confirmation(answer.cmd):
execute_command(answer.cmd)
else:
print(f"(AI Answer): {answer.failure}")
print("Command generation failed")
sys.exit(1)
except Exception as e:
print(f"Error: {e}")
sys.exit(1)
def create_parser() -> argparse.ArgumentParser:
"""Create command line argument parser"""
parser = argparse.ArgumentParser(
prog="ai",
description="AI-powered shell command generator using DeepSeek V3",
epilog="Examples:\n"
" ai list files\n"
" ai \"show disk usage\"\n"
" ai 显示当前目录\n",
formatter_class=argparse.RawDescriptionHelpFormatter
)
parser.add_argument(
"prompt",
nargs="*",
help="Natural language description of the command you want"
)
parser.add_argument(
"--version",
action="version",
version=f"ai-shell {__version__}"
)
parser.add_argument(
"--config",
action="store_true",
help="Show current configuration"
)
return parser
def show_config() -> None:
"""Show current configuration"""
from .config import (get_api_key, get_base_url, get_model, get_timeout,
get_max_retries, validate_config, get_available_modern_commands)
print("AI Shell Configuration:")
print(f" Model: {get_model()}")
print(f" Base URL: {get_base_url()}")
try:
api_key = get_api_key()
print(f" API Key: {api_key[:8]}...{api_key[-4:]}")
except ValueError as e:
print(f" API Key: ❌ {e}")
print(f" Timeout: {get_timeout()}s")
print(f" Max Retries: {get_max_retries()}")
print(f"\nConfiguration Status: {'✅ Valid' if validate_config() else '❌ Invalid'}")
print("\nConfiguration Sources (in priority order):")
print(" 1. Environment variables")
print(" 2. .env file in current directory")
print(" 3. .env file in package directory")
print(" 4. ~/.ai-shell/.env file")
print(" 5. Default values")
print("\nEnvironment Variables:")
print(" AI_SHELL_API_KEY - API key")
print(" AI_SHELL_BASE_URL - API base URL")
print(" AI_SHELL_MODEL - Model name")
print(" AI_SHELL_TIMEOUT - Request timeout (seconds)")
print(" AI_SHELL_MAX_RETRIES - Maximum retry attempts")
print(" AI_SHELL_MODERN_COMMANDS - Custom modern command alternatives")
# Show modern commands configuration
modern_commands = get_available_modern_commands()
if modern_commands:
print(f"\n现代化命令替代 ({len(modern_commands)} 个可用):")
# Group commands for better display
active_alternatives = {k: v for k, v in modern_commands.items() if k != v}
unchanged_commands = {k: v for k, v in modern_commands.items() if k == v}
if active_alternatives:
print(" 已启用的替代:")
for old_cmd, new_cmd in sorted(active_alternatives.items()):
print(f" {old_cmd}{new_cmd}")
if unchanged_commands:
print(f" 保持原样: {', '.join(sorted(unchanged_commands.keys()))}")
print("\n 自定义配置格式:")
print(" export AI_SHELL_MODERN_COMMANDS=\"old1:new1,old2:new2\"")
print(" 例如: export AI_SHELL_MODERN_COMMANDS=\"ls:exa,cat:bat,find:fd\"")
else:
print("\n现代化命令替代: 未检测到可用的现代化工具")
def main() -> None:
"""Main entry point"""
parser = create_parser()
args = parser.parse_args()
if args.config:
show_config()
return
if not args.prompt:
parser.print_help()
sys.exit(1)
# Validate configuration before processing
from .config import validate_config
if not validate_config():
print("❌ Configuration error: API key not configured.")
print("Please set AI_SHELL_API_KEY in .env file or environment variable.")
print("Run 'ai --config' to see current configuration.")
sys.exit(1)
# Join all prompt arguments into a single string
prompt = " ".join(args.prompt)
process_prompt(prompt)
if __name__ == "__main__":
main()