easyai 1.0.2 → 1.0.4

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.
@@ -0,0 +1,210 @@
1
+ require 'fileutils'
2
+ require 'tmpdir'
3
+ require 'colored2'
4
+
5
+ module EasyAI
6
+ class Command
7
+ class Update < Command
8
+ self.summary = '从代码仓库安装最新开发版本(仅用于测试)'
9
+ self.description = <<-DESC
10
+ 从 Gitee 代码仓库下载并安装最新的开发版本。
11
+
12
+ 主要功能:
13
+
14
+ * 从远程仓库拉取最新代码
15
+
16
+ * 自动构建 gem 包
17
+
18
+ * 安装到本地系统
19
+
20
+ 使用示例:
21
+
22
+ $ easyai update # 安装 master 分支
23
+
24
+ $ easyai update --branch=dev # 安装指定分支
25
+
26
+ $ easyai update --keep-source # 保留源代码
27
+
28
+ $ easyai update --verbose # 显示详细输出
29
+ DESC
30
+
31
+ def self.options
32
+ [
33
+ ['--branch=BRANCH', '指定要安装的分支(默认: master)'],
34
+ ['--keep-source', '保留下载的源代码'],
35
+ ['--verbose', '显示详细输出']
36
+ ].concat(super)
37
+ end
38
+
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
+ 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
202
+ else
203
+ nil
204
+ end
205
+ rescue
206
+ nil
207
+ end
208
+ end
209
+ end
210
+ end
@@ -0,0 +1,102 @@
1
+ require_relative '../../base/file_crypto'
2
+
3
+ module EasyAI
4
+ class Command
5
+ class Utils
6
+ class Decry < Utils
7
+ self.summary = '解密指定文件或目录'
8
+ self.description = <<-DESC
9
+ 对指定的加密文件或目录进行解密处理。
10
+
11
+ 支持功能:
12
+
13
+ * 单个文件解密
14
+
15
+ * 目录批量解密
16
+
17
+ * 自动恢复原文件名
18
+
19
+ 使用示例:
20
+
21
+ $ easyai utils decry file.encrypted # 解密单个文件
22
+
23
+ $ easyai utils decry /path/to/dir # 解密整个目录
24
+
25
+ $ easyai utils decry file.enc out.txt # 指定输出文件
26
+
27
+ $ easyai utils decry --output=out.txt # 使用选项指定输出
28
+ DESC
29
+
30
+ def self.options
31
+ [
32
+ ['--output=PATH', '指定解密后文件的输出路径'],
33
+ ].concat(super)
34
+ end
35
+
36
+ def initialize(argv)
37
+ @file_path = argv.shift_argument
38
+ @output_path = argv.option('output') || argv.shift_argument
39
+ super
40
+ end
41
+
42
+ def validate!
43
+ super
44
+ help! '请指定要解密的文件或目录路径' if @file_path.nil? || @file_path.empty?
45
+ help! "路径不存在: #{@file_path}" unless File.exist?(@file_path)
46
+ end
47
+
48
+ def run
49
+ if File.file?(@file_path)
50
+ decrypt_file_mode
51
+ elsif File.directory?(@file_path)
52
+ decrypt_directory_mode
53
+ else
54
+ puts "❌ 指定路径既不是文件也不是目录: #{@file_path}"
55
+ exit 1
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ def decrypt_file_mode
62
+ puts "🔓 正在解密文件: #{@file_path}"
63
+
64
+ begin
65
+ # 获取解密密码
66
+ password = Base::FileCrypto.get_password("请输入解密密码: ")
67
+
68
+ # 解密文件
69
+ output_file = Base::FileCrypto.decrypt_file(@file_path, password, @output_path)
70
+
71
+ puts "✅ 文件解密完成"
72
+ puts "📁 解密文件保存位置: #{output_file}"
73
+
74
+ rescue => e
75
+ puts "❌ 解密失败: #{e.message}"
76
+ exit 1
77
+ end
78
+ end
79
+
80
+ def decrypt_directory_mode
81
+ puts "🔓 正在解密目录: #{@file_path}"
82
+
83
+ begin
84
+ # 获取解密密码
85
+ password = Base::FileCrypto.get_password("请输入解密密码: ")
86
+
87
+ # 解密目录
88
+ result = Base::FileCrypto.decrypt_directory(@file_path, password, @output_path)
89
+
90
+ puts "✅ 目录解密完成"
91
+ puts "📁 解密目录保存位置: #{result[:output_dir]}"
92
+ puts "📋 已解密 #{result[:decrypted_files].length} 个文件"
93
+
94
+ rescue => e
95
+ puts "❌ 解密失败: #{e.message}"
96
+ exit 1
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,102 @@
1
+ require_relative '../../base/file_crypto'
2
+
3
+ module EasyAI
4
+ class Command
5
+ class Utils
6
+ class Encry < Utils
7
+ self.summary = '加密指定文件或目录'
8
+ self.description = <<-DESC
9
+ 对指定文件或目录进行加密处理。
10
+
11
+ 支持功能:
12
+
13
+ * 单个文件加密
14
+
15
+ * 目录批量加密
16
+
17
+ * 自定义输出路径
18
+
19
+ 使用示例:
20
+
21
+ $ easyai utils encry file.txt # 加密单个文件
22
+
23
+ $ easyai utils encry /path/to/dir # 加密整个目录
24
+
25
+ $ easyai utils encry file.txt out.enc # 指定输出文件
26
+
27
+ $ easyai utils encry --output=out.enc # 使用选项指定输出
28
+ DESC
29
+
30
+ def self.options
31
+ [
32
+ ['--output=PATH', '指定加密后文件的输出路径'],
33
+ ].concat(super)
34
+ end
35
+
36
+ def initialize(argv)
37
+ @file_path = argv.shift_argument
38
+ @output_path = argv.option('output') || argv.shift_argument
39
+ super
40
+ end
41
+
42
+ def validate!
43
+ super
44
+ help! '请指定要加密的文件或目录路径' if @file_path.nil? || @file_path.empty?
45
+ help! "路径不存在: #{@file_path}" unless File.exist?(@file_path)
46
+ end
47
+
48
+ def run
49
+ if File.file?(@file_path)
50
+ encrypt_file_mode
51
+ elsif File.directory?(@file_path)
52
+ encrypt_directory_mode
53
+ else
54
+ puts "❌ 指定路径既不是文件也不是目录: #{@file_path}"
55
+ exit 1
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ def encrypt_file_mode
62
+ puts "🔐 正在加密文件: #{@file_path}"
63
+
64
+ begin
65
+ # 获取加密密码
66
+ password = Base::FileCrypto.get_password("请输入加密密码: ")
67
+
68
+ # 加密文件
69
+ output_file = Base::FileCrypto.encrypt_file(@file_path, password, @output_path)
70
+
71
+ puts "✅ 文件加密完成"
72
+ puts "📁 加密文件保存位置: #{output_file}"
73
+
74
+ rescue => e
75
+ puts "❌ 加密失败: #{e.message}"
76
+ exit 1
77
+ end
78
+ end
79
+
80
+ def encrypt_directory_mode
81
+ puts "🔐 正在加密目录: #{@file_path}"
82
+
83
+ begin
84
+ # 获取加密密码
85
+ password = Base::FileCrypto.get_password("请输入加密密码: ")
86
+
87
+ # 加密目录
88
+ result = Base::FileCrypto.encrypt_directory(@file_path, password, @output_path)
89
+
90
+ puts "✅ 目录加密完成"
91
+ puts "📁 加密目录保存位置: #{result[:output_dir]}"
92
+ puts "📋 已加密 #{result[:encrypted_files].length} 个文件"
93
+
94
+ rescue => e
95
+ puts "❌ 加密失败: #{e.message}"
96
+ exit 1
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,32 @@
1
+ module EasyAI
2
+ class Command
3
+ class Utils < Command
4
+ self.summary = '实用工具集合'
5
+ self.description = <<-DESC
6
+ 提供各种实用工具。
7
+
8
+ 可用命令:
9
+
10
+ * encry - 文件加密工具
11
+
12
+ * decry - 文件解密工具
13
+
14
+ 使用示例:
15
+
16
+ $ easyai utils encry file.txt # 加密文件
17
+
18
+ $ easyai utils decry file.encrypted # 解密文件
19
+ DESC
20
+
21
+ self.abstract_command = true
22
+
23
+ def self.options
24
+ [].concat(super)
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ # 加载子命令
31
+ require_relative 'utils/encry'
32
+ require_relative 'utils/decry'
@@ -0,0 +1,56 @@
1
+ require 'claide'
2
+ require 'yaml'
3
+ require 'fileutils'
4
+ require 'colored2'
5
+ require_relative 'base/system_keychain'
6
+ require_relative 'base/version_checker'
7
+
8
+ module EasyAI
9
+ class Command < CLAide::Command
10
+
11
+ self.abstract_command = true
12
+ self.command = 'easyai'
13
+ self.version = VERSION
14
+ self.description = '简化 AI 命令行工具的 CLI 包装器,支持 Claude、Gemini 和 GPT'
15
+ self.plugin_prefixes = %w(easyai)
16
+
17
+ # 定义帮助标志访问器(类似 pindo)
18
+ attr_accessor :args_help_flag
19
+ alias_method :args_help_flag?, :args_help_flag
20
+
21
+ # 根命令的选项
22
+ DEFAULT_ROOT_OPTIONS = [
23
+ ['--version', '显示版本信息']
24
+ ]
25
+
26
+ # 所有命令通用的选项
27
+ DEFAULT_OPTIONS = [
28
+ ['--help', '显示此帮助信息']
29
+ ]
30
+
31
+ def self.options
32
+ if self == Command # 根命令
33
+ DEFAULT_ROOT_OPTIONS + DEFAULT_OPTIONS
34
+ else # 子命令
35
+ DEFAULT_OPTIONS
36
+ end
37
+ end
38
+
39
+
40
+ def initialize(argv)
41
+ super
42
+ # 使用CLAide已经设置的help_arg,而不是重新获取
43
+ @args_help_flag = @help_arg
44
+ end
45
+
46
+ def validate!
47
+ super
48
+ help! if args_help_flag?
49
+ end
50
+
51
+ def self.run(argv)
52
+ super(argv)
53
+ end
54
+
55
+ end
56
+ end