easyai 1.7.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,210 +1,61 @@
1
- require 'fileutils'
2
- require 'tmpdir'
1
+ # frozen_string_literal: true
2
+
3
3
  require 'colored2'
4
+ require_relative '../command'
4
5
 
5
6
  module EasyAI
6
7
  class Command
8
+ # 通过 RubyGems 自更新 EasyAI 自身。
9
+ #
10
+ # 设计要点(详见 docs/设计文档.md §2.7):
11
+ # - 用 system('gem', 'update', 'easyai') 触发 RubyGems 自更新
12
+ # - 不用 exec,便于子进程结束后继续打印中文提示
13
+ # - 启动时 EasyAIApp 识别到子命令为 update 会跳过强制版本阻塞,避免死循环
7
14
  class Update < Command
8
- self.summary = '从代码仓库安装最新开发版本(仅用于测试)'
15
+ self.summary = '通过 RubyGems 更新 EasyAI 到最新发布版本'
9
16
  self.description = <<-DESC
10
- Gitee 代码仓库下载并安装最新的开发版本。
11
-
12
- 主要功能:
13
-
14
- * 从远程仓库拉取最新代码
15
-
16
- * 自动构建 gem 包
17
-
18
- * 安装到本地系统
19
-
20
- 使用示例:
17
+ 通过 `gem update easyai` 将 EasyAI 升级到 RubyGems 上的最新版本,
18
+ 等价于手动执行该命令,但用 system 而非 exec,子进程结束后会打印中文成功 / 失败提示。
21
19
 
22
- $ easyai update # 安装 master 分支
20
+ 如果当前与 RubyGems 网络不通导致启动时被强制版本检查阻塞,可临时跳过:
23
21
 
24
- $ easyai update --branch=dev # 安装指定分支
22
+ $ EASYAI_SKIP_FORCE_UPDATE=1 easyai <子命令>
25
23
 
26
- $ easyai update --keep-source # 保留源代码
24
+ 使用示例:
27
25
 
28
- $ easyai update --verbose # 显示详细输出
29
- DESC
26
+ $ easyai update # 静默模式,仅打印必要提示
27
+ $ easyai update --verbose # 显示 gem 命令的完整输出
28
+ DESC
30
29
 
31
30
  def self.options
32
31
  [
33
- ['--branch=BRANCH', '指定要安装的分支(默认: master)'],
34
- ['--keep-source', '保留下载的源代码'],
35
- ['--verbose', '显示详细输出']
32
+ ['--verbose', '显示 gem update 命令的完整输出']
36
33
  ].concat(super)
37
34
  end
38
35
 
39
- def initialize(argv)
40
- @branch = argv.option('branch') || 'master'
41
- @keep_source = argv.flag?('keep-source')
42
- @verbose = argv.flag?('verbose')
43
- super
44
- end
45
-
46
- def validate!
47
- super
48
- help! '未找到 git 命令。请先安装 git。' unless git_available?
49
- end
50
-
51
36
  def run
52
- puts "\n╔#{'═' * 58}╗".cyan
53
- puts "║#{'EasyAI 开发版本更新工具'.center(58)}║".cyan
54
- puts "╚#{'═' * 58}╝\n".cyan
55
-
56
- puts "⚠️ 注意:此命令仅用于测试开发版本".yellow
57
- puts "📦 生产环境请使用: #{'gem update easyai'.green}\n\n"
58
-
59
- # 确认继续
60
- unless confirm_update?
61
- puts "❌ 更新已取消".red
62
- return
63
- end
64
-
65
- # 创建临时目录
66
- temp_dir = Dir.mktmpdir('easyai-update-')
67
-
68
- begin
69
- # 克隆仓库
70
- clone_repository(temp_dir)
71
-
72
- # 执行安装脚本
73
- install_from_source(temp_dir)
74
-
75
- # 显示成功信息
76
- show_success_message
77
-
78
- rescue => e
79
- puts "\n❌ 更新失败: #{e.message}".red
80
- puts " 请检查网络连接或稍后重试".red
81
- exit 1
82
- ensure
83
- # 清理临时文件
84
- cleanup_temp_files(temp_dir) unless @keep_source
85
- end
86
- end
87
-
88
- private
89
-
90
- def git_available?
91
- system('which git > /dev/null 2>&1')
92
- end
93
-
94
- def confirm_update?
95
- print "确认从 Gitee 安装开发版本?[y/N]: ".yellow
96
- begin
97
- response = STDIN.gets
98
- return false unless response
99
- response = response.chomp.downcase
100
- response == 'y' || response == 'yes'
101
- rescue => e
102
- puts "\n❌ 无法读取输入: #{e.message}".red
103
- false
104
- end
105
- end
106
-
107
- def clone_repository(temp_dir)
108
- repo_url = 'https://gitee.com/goodtools/EasyAI.git'
109
- clone_path = File.join(temp_dir, 'EasyAI')
110
-
111
- puts "📥 正在下载源代码...".cyan
112
- puts " 仓库: #{repo_url}"
113
- puts " 分支: #{@branch}"
114
-
115
- # 构建 git clone 命令
116
- git_cmd = "git clone --depth 1 --branch #{@branch} #{repo_url} #{clone_path}"
117
- git_cmd += " > /dev/null 2>&1" unless @verbose
118
-
119
- # 执行克隆
120
- success = system(git_cmd)
121
-
122
- unless success
123
- raise "无法克隆仓库。请检查网络连接和分支名称。"
124
- end
125
-
126
- puts " ✓ 源代码下载完成".green
127
-
128
- clone_path
129
- end
130
-
131
- def install_from_source(temp_dir)
132
- source_dir = File.join(temp_dir, 'EasyAI')
133
-
134
- unless File.exist?(source_dir)
135
- raise "源代码目录不存在: #{source_dir}"
136
- end
137
-
138
- # 检查 test_local.sh 是否存在
139
- install_script = File.join(source_dir, 'test_local.sh')
140
- unless File.exist?(install_script)
141
- raise "安装脚本不存在: test_local.sh"
142
- end
143
-
144
- puts "\n🔧 正在构建并安装...".cyan
145
-
146
- # 切换到源代码目录并执行安装脚本
147
- Dir.chdir(source_dir) do
148
- # 确保脚本可执行
149
- File.chmod(0755, 'test_local.sh')
150
-
151
- # 执行安装脚本
152
- install_cmd = "./test_local.sh"
153
- install_cmd += " > /dev/null 2>&1" unless @verbose
154
-
155
- success = system(install_cmd)
156
-
157
- unless success
158
- raise "安装脚本执行失败"
159
- end
160
- end
161
-
162
- puts " ✓ 安装完成".green
163
- end
164
-
165
- def cleanup_temp_files(temp_dir)
166
- if @keep_source
167
- puts "\n📁 源代码保留在: #{temp_dir}".cyan
168
- else
169
- puts "\n🧹 正在清理临时文件...".cyan
170
- FileUtils.rm_rf(temp_dir)
171
- puts " ✓ 清理完成".green
172
- end
173
- end
174
-
175
- def show_success_message
176
- # 获取安装后的版本
177
- installed_version = get_installed_version
178
-
179
- puts "\n" + "─" * 60
180
- puts "✅ #{'开发版本安装成功!'.green}"
181
- puts "─" * 60
182
-
183
- if installed_version
184
- puts "📌 当前版本: #{installed_version}"
185
- end
186
-
187
- puts "\n提示:".cyan
188
- puts " • 这是开发版本,可能包含未发布的功能"
189
- puts " • 如需回退到稳定版本: gem install easyai"
190
- puts " • 查看版本信息: easyai --version"
191
-
192
- if @branch != 'master'
193
- puts "\n📝 已安装分支: #{@branch}".yellow
194
- end
195
- end
196
-
197
- def get_installed_version
198
- # 尝试获取已安装的版本
199
- output = `easyai --version 2>&1`
200
- if output =~ /EasyAI 版本:\s*(\S+)/
201
- $1
37
+ puts "开始更新 EasyAI...".cyan
38
+ puts "正在执行:gem update easyai".cyan
39
+
40
+ ok = if @verbose
41
+ system('gem', 'update', 'easyai')
42
+ else
43
+ system('gem', 'update', 'easyai', out: File::NULL, err: File::NULL)
44
+ end
45
+
46
+ if ok
47
+ puts "✓ 更新完成".green
48
+ puts "请重新打开终端,然后运行 `easyai --version` 查看新版本".cyan
202
49
  else
203
- nil
50
+ puts "✗ 更新失败".red
51
+ puts "请尝试以下排查方式:".yellow
52
+ puts " • 检查网络连接是否能访问 https://rubygems.org"
53
+ puts " • 确认 RubyGems 源可用:gem sources -l"
54
+ puts " • 权限不足时尝试:sudo gem update easyai"
55
+ puts " • 重新执行并加 --verbose 查看详细输出"
56
+ exit($?.respond_to?(:exitstatus) && $?.exitstatus ? $?.exitstatus : 1)
204
57
  end
205
- rescue
206
- nil
207
58
  end
208
59
  end
209
60
  end
210
- end
61
+ end
@@ -4,22 +4,18 @@ module EasyAI
4
4
  self.summary = '实用工具集合'
5
5
  self.description = <<-DESC
6
6
  提供各种实用工具。
7
-
7
+
8
8
  可用命令:
9
9
 
10
10
  * encry - 文件加密工具
11
11
 
12
12
  * decry - 文件解密工具
13
13
 
14
- * export - 导出 AI 配置信息
15
-
16
14
  使用示例:
17
15
 
18
16
  $ easyai utils encry file.txt # 加密文件
19
17
 
20
18
  $ easyai utils decry file.encrypted # 解密文件
21
-
22
- $ easyai utils export # 导出配置
23
19
  DESC
24
20
 
25
21
  self.abstract_command = true
@@ -33,5 +29,4 @@ end
33
29
 
34
30
  # 加载子命令
35
31
  require_relative 'utils/encry'
36
- require_relative 'utils/decry'
37
- require_relative 'utils/export'
32
+ require_relative 'utils/decry'
@@ -1,8 +1,6 @@
1
1
  require 'claide'
2
- require 'yaml'
3
2
  require 'fileutils'
4
3
  require 'colored2'
5
- require_relative 'base/system_keychain'
6
4
  require_relative 'base/version_checker'
7
5
 
8
6
  module EasyAI
@@ -11,7 +9,7 @@ module EasyAI
11
9
  self.abstract_command = true
12
10
  self.command = 'easyai'
13
11
  self.version = VERSION
14
- self.description = '简化 AI 命令行工具的 CLI 包装器,支持 Claude、Gemini 和 GPT'
12
+ self.description = '简化 AI 命令行工具的 CLI 包装器,支持 Claude、Gemini 和 Codex'
15
13
  self.plugin_prefixes = %w(easyai)
16
14
 
17
15
  # 定义帮助标志访问器(类似 pindo)
@@ -0,0 +1,161 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'fileutils'
5
+
6
+ module EasyAI
7
+ module Config
8
+ # 本地配置门面:~/.easyai/config.json 的唯一读写入口
9
+ module LocalConfig
10
+ SCHEMA_VERSION = '2.0.0'
11
+
12
+ class Error < StandardError; end
13
+ class NotFoundError < Error; end
14
+ class ParseError < Error; end
15
+ class IncompatibleVersionError < Error; end
16
+ class ToolNotConfiguredError < Error; end
17
+ class PlatformNotFoundError < Error; end
18
+
19
+ module_function
20
+
21
+ # 注意:必须每次动态 expand_path,避免常量在加载期 freeze 路径,
22
+ # 让 spec 中切换 ENV['HOME'] 后定位失败
23
+ def config_path
24
+ File.expand_path('~/.easyai/config.json')
25
+ end
26
+
27
+ def exists?
28
+ File.file?(config_path)
29
+ end
30
+
31
+ def load
32
+ path = config_path
33
+ raise NotFoundError, "未找到本地配置文件 #{path},请运行 easyai setup" unless File.file?(path)
34
+
35
+ raw = File.read(path)
36
+ data = begin
37
+ JSON.parse(raw)
38
+ rescue JSON::ParserError => e
39
+ raise ParseError,
40
+ "配置解析失败 #{path}: #{e.message};可运行 easyai setup --reset 重新生成"
41
+ end
42
+
43
+ version = data['version']
44
+ unless version == SCHEMA_VERSION
45
+ raise IncompatibleVersionError,
46
+ "配置版本 #{version.inspect} 不被支持,期望 #{SCHEMA_VERSION}"
47
+ end
48
+
49
+ data
50
+ end
51
+
52
+ def save(cfg)
53
+ path = config_path
54
+ FileUtils.mkdir_p(File.dirname(path))
55
+ File.write(path, JSON.pretty_generate(cfg))
56
+ File.chmod(0o600, path) unless Gem.win_platform?
57
+ path
58
+ end
59
+
60
+ PLATFORM_DISPLAY_NAMES = {
61
+ 'claude_official' => 'Claude 官方',
62
+ 'deepseek' => 'DeepSeek',
63
+ 'glm' => 'GLM(Coding Plan)',
64
+ 'kimi' => 'Kimi',
65
+ 'minimax' => 'MiniMax'
66
+ }.freeze
67
+
68
+ def platform_display_name(key)
69
+ PLATFORM_DISPLAY_NAMES.fetch(key, key)
70
+ end
71
+
72
+ def available_platforms(tool)
73
+ return [] unless exists?
74
+
75
+ cfg = load
76
+ platforms = cfg.dig(tool, 'platforms')
77
+ platforms.is_a?(Hash) ? platforms.keys : []
78
+ rescue Error
79
+ []
80
+ end
81
+
82
+ # 解析平台配置。选定平台后会 yield 平台名(如果给了 block),
83
+ # 让上层(AIToolBase)负责打印 UI 提示,保持 LocalConfig 的输出最小化。
84
+ def resolve_platform(tool:, platform: nil, verbose: false)
85
+ cfg = load
86
+ tool_cfg = cfg[tool]
87
+ platforms = tool_cfg.is_a?(Hash) ? tool_cfg['platforms'] : nil
88
+ if !platforms.is_a?(Hash) || platforms.empty?
89
+ raise ToolNotConfiguredError,
90
+ "工具 #{tool} 未配置任何平台,请运行 easyai setup --tool=#{tool}"
91
+ end
92
+
93
+ available = platforms.keys
94
+ selected =
95
+ if platform && !platform.empty?
96
+ unless available.include?(platform)
97
+ raise PlatformNotFoundError,
98
+ "工具 #{tool} 未配置平台 #{platform}(可用:#{available.join(', ')})"
99
+ end
100
+
101
+ platform
102
+ elsif available.size == 1
103
+ only = available.first
104
+ puts "使用平台 #{platform_display_name(only)}" if verbose
105
+ only
106
+ else
107
+ interactive_select(tool, available)
108
+ end
109
+
110
+ yield(platform_display_name(selected)) if block_given?
111
+ platforms[selected]
112
+ end
113
+
114
+ def upsert_platform(tool, platform, data)
115
+ cfg = exists? ? load : { 'version' => SCHEMA_VERSION }
116
+ cfg['version'] ||= SCHEMA_VERSION
117
+ cfg[tool] ||= { 'platforms' => {} }
118
+ cfg[tool]['platforms'] ||= {}
119
+ cfg[tool]['platforms'][platform] = data
120
+ save(cfg)
121
+ cfg
122
+ end
123
+
124
+ def delete_platform(tool, platform)
125
+ return unless exists?
126
+
127
+ cfg = load
128
+ platforms = cfg.dig(tool, 'platforms')
129
+ return cfg unless platforms.is_a?(Hash) && platforms.key?(platform)
130
+
131
+ platforms.delete(platform)
132
+ cfg.delete(tool) if platforms.empty?
133
+ save(cfg)
134
+ cfg
135
+ end
136
+
137
+ # ----- private helpers -----
138
+
139
+ def interactive_select(tool, available)
140
+ puts "请选择平台(工具:#{tool}):"
141
+ available.each_with_index do |name, idx|
142
+ puts " #{idx + 1}) #{platform_display_name(name)}"
143
+ end
144
+ print '请输入序号 (q 取消): '
145
+ input = $stdin.gets
146
+ raise Interrupt, '用户取消平台选择' if input.nil?
147
+
148
+ input = input.chomp.strip
149
+ raise Interrupt, '用户取消平台选择' if input.empty? || input.casecmp('q').zero?
150
+
151
+ idx = Integer(input, 10) rescue nil
152
+ if idx.nil? || idx < 1 || idx > available.size
153
+ raise Interrupt, "非法输入:#{input}"
154
+ end
155
+
156
+ available[idx - 1]
157
+ end
158
+ private_class_method :interactive_select
159
+ end
160
+ end
161
+ end
@@ -1,3 +1,3 @@
1
1
  module EasyAI
2
- VERSION = '1.7.0'
2
+ VERSION = '2.0.0'
3
3
  end
data/lib/easyai.rb CHANGED
@@ -1,14 +1,16 @@
1
1
  require 'easyai/version'
2
- require 'easyai/config/config'
3
- require 'easyai/config/easyai_config'
2
+ require 'easyai/config/local_config'
4
3
  require 'easyai/command'
4
+ require 'easyai/command/ai_tool_base'
5
5
  require 'easyai/command/claude'
6
6
  require 'easyai/command/gemini'
7
- require 'easyai/command/gpt'
7
+ require 'easyai/command/codex'
8
8
  require 'easyai/command/utils'
9
9
  require 'easyai/command/clean'
10
10
  require 'easyai/command/update'
11
11
  require 'easyai/command/setup'
12
+ require 'easyai/command/backup'
13
+ require 'easyai/command/restore'
12
14
  require 'easyai/base/version_checker'
13
15
  require 'easyai/base/update_notifier'
14
16
  require 'easyai/base/system_info'
@@ -30,14 +32,8 @@ module EasyAI
30
32
  # 在运行命令前进行版本检查
31
33
  check_version_before_run(argv)
32
34
 
33
- # 设置退出时清理
34
- setup_cleanup_handler
35
-
36
35
  # 运行命令
37
36
  EasyAI::Command.run(argv)
38
- ensure
39
- # 确保清理临时文件
40
- cleanup_temp_files
41
37
  end
42
38
 
43
39
  private
@@ -64,21 +60,38 @@ module EasyAI
64
60
  require 'claide'
65
61
  require 'colored2'
66
62
  coerced_argv = CLAide::ARGV.coerce(argv)
67
-
63
+
64
+ # 识别第一个非选项位置参数(子命令名)
65
+ # 注意:CLAide::ARGV#arguments 返回剩余的位置参数列表
66
+ first_subcommand = coerced_argv.arguments.first
67
+
68
68
  # 如果是以下情况,跳过版本检查:
69
69
  # 1. 请求帮助信息 (--help)
70
70
  # 2. 显示版本信息 (--version)
71
71
  # 3. 主动检查更新 (--check-update)
72
- skip_check = coerced_argv.flag?('help') ||
73
- coerced_argv.flag?('version') ||
74
- coerced_argv.flag?('check-update')
75
-
72
+ # 4. 紧急跳过开关 (EASYAI_SKIP_FORCE_UPDATE=1)
73
+ # 5. 子命令为 update —— 避免"过期必须更新 → update 命令本身被阻塞"死循环
74
+ skip_reason =
75
+ if coerced_argv.flag?('help')
76
+ '--help'
77
+ elsif coerced_argv.flag?('version')
78
+ '--version'
79
+ elsif coerced_argv.flag?('check-update')
80
+ '--check-update'
81
+ elsif ENV['EASYAI_SKIP_FORCE_UPDATE']
82
+ 'EASYAI_SKIP_FORCE_UPDATE=1'
83
+ elsif first_subcommand == 'update'
84
+ '子命令为 update'
85
+ end
86
+
87
+ skip_check = !skip_reason.nil?
88
+
76
89
  if ENV['EASYAI_DEBUG']
77
90
  puts "📊 版本检查状态:".cyan
78
91
  puts " • 当前版本: v#{EasyAI::VERSION}".green
79
- puts " • 跳过检查: #{skip_check ? '是(--help/--version'.yellow : '否'.cyan}"
92
+ puts " • 跳过检查: #{skip_check ? "是(#{skip_reason}".yellow : '否'.cyan}"
80
93
  end
81
-
94
+
82
95
  return if skip_check
83
96
 
84
97
  # 强制更新检查(会阻塞执行)
@@ -97,24 +110,5 @@ module EasyAI
97
110
  puts e.backtrace.join("\n") if ENV['EASYAI_DEBUG']
98
111
  end
99
112
 
100
- # 设置清理处理器
101
- def setup_cleanup_handler
102
- # 注册信号处理器,确保 Ctrl+C 等信号时也能清理
103
- %w[INT TERM].each do |signal|
104
- Signal.trap(signal) do
105
- cleanup_temp_files
106
- exit(130) # 标准的 Ctrl+C 退出码
107
- end
108
- end
109
- end
110
-
111
- # 清理临时文件
112
- def cleanup_temp_files
113
- verbose = ENV['EASYAI_DEBUG'] || ENV['EASYAI_VERBOSE']
114
- EasyAIConfig.cleanup(verbose)
115
- rescue => e
116
- # 清理失败不影响退出
117
- puts "⚠️ 清理临时文件失败: #{e.message}" if ENV['EASYAI_DEBUG']
118
- end
119
113
  end
120
114
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: easyai
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wade
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-11-05 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: claide
@@ -38,39 +38,19 @@ dependencies:
38
38
  - !ruby/object:Gem::Version
39
39
  version: '3.1'
40
40
  - !ruby/object:Gem::Dependency
41
- name: webrick
41
+ name: base64
42
42
  requirement: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
- version: '1.9'
46
+ version: '0.2'
47
47
  type: :runtime
48
48
  prerelease: false
49
49
  version_requirements: !ruby/object:Gem::Requirement
50
50
  requirements:
51
51
  - - "~>"
52
52
  - !ruby/object:Gem::Version
53
- version: '1.9'
54
- - !ruby/object:Gem::Dependency
55
- name: jpsclient
56
- requirement: !ruby/object:Gem::Requirement
57
- requirements:
58
- - - "~>"
59
- - !ruby/object:Gem::Version
60
- version: '1.4'
61
- - - ">="
62
- - !ruby/object:Gem::Version
63
- version: 1.4.0
64
- type: :runtime
65
- prerelease: false
66
- version_requirements: !ruby/object:Gem::Requirement
67
- requirements:
68
- - - "~>"
69
- - !ruby/object:Gem::Version
70
- version: '1.4'
71
- - - ">="
72
- - !ruby/object:Gem::Version
73
- version: 1.4.0
53
+ version: '0.2'
74
54
  - !ruby/object:Gem::Dependency
75
55
  name: bundler
76
56
  requirement: !ruby/object:Gem::Requirement
@@ -113,8 +93,10 @@ dependencies:
113
93
  - - "~>"
114
94
  - !ruby/object:Gem::Version
115
95
  version: '3.0'
116
- description: A CLI tool that simplifies running AI tools like Claude, Gemini, and
117
- GPT with environment configuration
96
+ description: |
97
+ EasyAI 是一个 Ruby CLI 包装器,为 Anthropic Claude、Google Gemini、OpenAI Codex 三家命令行工具提供统一入口。
98
+ v2.0 起聚焦单机本地化:无远程下发链路,通过单一 ~/.easyai/config.json 集中管理多家 CLI 与多平台凭证、代理;
99
+ 运行时仅向子进程注入环境变量,不污染当前 shell。
118
100
  email:
119
101
  - wade@example.com
120
102
  executables:
@@ -128,27 +110,28 @@ files:
128
110
  - bin/easyai
129
111
  - easyai.gemspec
130
112
  - lib/easyai.rb
131
- - lib/easyai/auth/authclaude.rb
132
- - lib/easyai/auth/jpsloginhelper.rb
133
113
  - lib/easyai/base/cross_platform.rb
134
114
  - lib/easyai/base/file_crypto.rb
115
+ - lib/easyai/base/secret_masker.rb
135
116
  - lib/easyai/base/system_info.rb
136
- - lib/easyai/base/system_keychain.rb
137
117
  - lib/easyai/base/update_notifier.rb
138
118
  - lib/easyai/base/version_checker.rb
139
119
  - lib/easyai/command.rb
120
+ - lib/easyai/command/ai_tool_base.rb
121
+ - lib/easyai/command/backup.rb
122
+ - lib/easyai/command/backup/claude.rb
140
123
  - lib/easyai/command/claude.rb
141
124
  - lib/easyai/command/clean.rb
125
+ - lib/easyai/command/codex.rb
142
126
  - lib/easyai/command/gemini.rb
143
- - lib/easyai/command/gpt.rb
127
+ - lib/easyai/command/restore.rb
128
+ - lib/easyai/command/restore/claude.rb
144
129
  - lib/easyai/command/setup.rb
145
130
  - lib/easyai/command/update.rb
146
131
  - lib/easyai/command/utils.rb
147
132
  - lib/easyai/command/utils/decry.rb
148
133
  - lib/easyai/command/utils/encry.rb
149
- - lib/easyai/command/utils/export.rb
150
- - lib/easyai/config/config.rb
151
- - lib/easyai/config/easyai_config.rb
134
+ - lib/easyai/config/local_config.rb
152
135
  - lib/easyai/version.rb
153
136
  homepage: https://github.com/wade/easyai
154
137
  licenses:
@@ -161,14 +144,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
161
144
  requirements:
162
145
  - - ">="
163
146
  - !ruby/object:Gem::Version
164
- version: 2.7.0
147
+ version: 3.0.0
165
148
  required_rubygems_version: !ruby/object:Gem::Requirement
166
149
  requirements:
167
150
  - - ">="
168
151
  - !ruby/object:Gem::Version
169
152
  version: '0'
170
153
  requirements: []
171
- rubygems_version: 3.6.3
154
+ rubygems_version: 3.6.9
172
155
  specification_version: 4
173
- summary: Easy AI CLI tool wrapper
156
+ summary: Claude / Gemini / Codex 三家 AI CLI 的本地化统一入口
174
157
  test_files: []