Class: EasyAI::Command::AIToolBase

Inherits:
Command
  • Object
show all
Defined in:
lib/easyai/command/ai_tool_base.rb

Overview

AI 工具命令的公共基类:claude / gemini / codex 共享的运行流程

子类必须实现:

  • tool_name 返回 config.json 顶层键,如 'claude'
  • exec_command 返回子进程命令名,如 'claude'
  • install_hint 返回未安装时的中文安装提示

Direct Known Subclasses

Claude, Codex

Constant Summary collapse

PROTECTED_ENV_KEYS =

系统关键变量保护清单:永远不允许被 config 中的 env / proxy 覆盖

%w[PATH HOME USER SHELL].freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(argv) ⇒ AIToolBase

Returns a new instance of AIToolBase.



31
32
33
34
35
36
37
38
39
40
# File 'lib/easyai/command/ai_tool_base.rb', line 31

def initialize(argv)
  @platform = argv.option('platform')
  @verbose = argv.flag?('verbose')

  super

  remaining = @argv.remainder!
  @local_config_file = extract_local_config_file!(remaining)
  @passthrough_args = remaining
end

Class Method Details

.optionsObject



24
25
26
27
28
29
# File 'lib/easyai/command/ai_tool_base.rb', line 24

def self.options
  [
    ['--platform=PLATFORM', '指定平台(如 claude_official / kimi / deepseek)'],
    ['--verbose', '显示详细信息']
  ].concat(super)
end

Instance Method Details

#default_envObject

子类可选重写:返回该工具固定要注入的环境变量。 优先级低于 cfg.env(用户在 config.json 中显式声明的同名 key 会覆盖默认值)。



95
96
97
# File 'lib/easyai/command/ai_tool_base.rb', line 95

def default_env
  {}
end

#exec_commandObject

Raises:

  • (NotImplementedError)


85
86
87
# File 'lib/easyai/command/ai_tool_base.rb', line 85

def exec_command
  raise NotImplementedError, "#{self.class} 必须实现 #exec_command"
end

#extra_platformsObject

子类可选重写:向平台选择列表注入的虚拟平台 { key => data }(如 codex 的 ChatGPT Subscribe)。 默认空;与 config.json 真实平台合并参与交互选择。



108
109
110
# File 'lib/easyai/command/ai_tool_base.rb', line 108

def extra_platforms
  {}
end

#install_hintObject

Raises:

  • (NotImplementedError)


89
90
91
# File 'lib/easyai/command/ai_tool_base.rb', line 89

def install_hint
  raise NotImplementedError, "#{self.class} 必须实现 #install_hint"
end

#pre_execObject

子类可选重写:在 exec 启动子进程之前执行的钩子(如:写入子进程依赖的状态文件、 追加只对本次子进程生效的环境变量到 @env,如 codex 注入 CODEX_HOME)。 默认 no-op;不应阻塞主流程,异常应降级为 warning。



102
103
104
# File 'lib/easyai/command/ai_tool_base.rb', line 102

def pre_exec
  # no-op
end

#runObject



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/easyai/command/ai_tool_base.rb', line 49

def run
  cfg = resolve_config
  @resolved_config = cfg # 供子类 pre_exec 读取当前生效的平台配置
  print_platform_env(cfg)
  @env = build_environment(cfg) # 存 ivar:pre_exec 可按需追加(如 codex 注入 CODEX_HOME)
  export_environment_variables(@env)
  pre_exec
  exec(@env, exec_command, *@passthrough_args)
rescue Config::LocalConfig::NotFoundError => e
  print_error(e.message)
  puts "  请运行: #{'easyai setup'.yellow}"
  exit 1
rescue Config::LocalConfig::PlatformNotFoundError => e
  print_error(e.message)
  available = Config::LocalConfig.available_platforms(tool_name)
  puts "  当前可用平台:#{available.join(', ')}" unless available.empty?
  exit 1
rescue Config::LocalConfig::ToolNotConfiguredError => e
  print_error(e.message)
  puts "  请运行: #{"easyai setup --tool=#{tool_name}".yellow}"
  exit 1
rescue Config::LocalConfig::ParseError, Config::LocalConfig::IncompatibleVersionError => e
  print_error(e.message)
  puts "  可运行: #{'easyai setup --reset'.yellow} 重新生成配置"
  exit 1
rescue Interrupt
  puts
  print_error('用户取消操作')
  exit 130
end

#tool_nameObject

子类必须实现的抽象方法

Raises:

  • (NotImplementedError)


81
82
83
# File 'lib/easyai/command/ai_tool_base.rb', line 81

def tool_name
  raise NotImplementedError, "#{self.class} 必须实现 #tool_name"
end

#validate!Object



42
43
44
45
46
47
# File 'lib/easyai/command/ai_tool_base.rb', line 42

def validate!
  super
  return if Base::SystemInfo.which_command(exec_command)

  help! "未找到 #{exec_command} CLI。#{install_hint}"
end