easyai 1.0.6 → 1.0.9

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3322fb9e0f41de14e28a234acdbc96ec0c28ffb43594eb295467fde9ea77fd0e
4
- data.tar.gz: acc9600a405f462c80c5e87bec61b0dc379133d4e002fb00840f1c2d33470809
3
+ metadata.gz: e62a795c1d9f823731c5efa0fdd2ccccece744164374c222cf42039eeab1d394
4
+ data.tar.gz: 8a937a49e3b619094a9af1beae643b9ede84f82e0f5cd38777e74e9f369711ee
5
5
  SHA512:
6
- metadata.gz: e130c4d6ba6220ad3f9c75704ff807241168b023ea5c1a032c35774dc7963e56606053bf6bb7b0600299d3c8295049357dc5b29a1e3eb9ad8fb8f8a8d26efc61
7
- data.tar.gz: 912bc95c679bfebd6efcfbf00e002f224d74dc65673be378c1fd5a896c8e94b0354b037068639abd0445e49e9869a4af56ba326636c2c511edb260eb8826bebb
6
+ metadata.gz: 32ac98c88d9cf7ae7045a461d49d40f187c050f6d83c484c7a00c605b38ae94527f95ffc82229f70afd50e9ca3a8f6c79c6359eabad5173dbf0c2134d7e1a5c9
7
+ data.tar.gz: 2d0e460bdd981bd8b411557657b25ea7c2a62fb5f270be3af0fb20922245a4e063dff7afd8099bca1e9cf3ce6fbc440b1775081ac94b836254c52736b269ca06
@@ -1,10 +1,11 @@
1
1
  require 'yaml'
2
2
  require 'time'
3
+ require 'colored2'
3
4
 
4
5
  module EasyAI
5
6
  module Base
6
7
  class UpdateNotifier
7
- NOTIFICATION_FILE = File.expand_path('~/.easyai/update_notification.yml')
8
+ VERSION_INFO_FILE = File.expand_path('~/.easyai/version_info.yml')
8
9
 
9
10
  class << self
10
11
  # 智能决定是否显示更新通知
@@ -13,7 +14,7 @@ module EasyAI
13
14
  return unless should_show_notification?
14
15
 
15
16
  notification = load_notification
16
- return unless notification && notification['available']
17
+ return unless notification && notification['new_version_available']
17
18
 
18
19
  # 使用简洁的单行提醒
19
20
  show_brief_notification(notification)
@@ -25,7 +26,7 @@ module EasyAI
25
26
  return if ENV['EASYAI_NO_UPDATE_CHECK']
26
27
 
27
28
  notification = load_notification
28
- return unless notification && notification['available']
29
+ return unless notification && notification['new_version_available']
29
30
  return if notification['shown_today']
30
31
 
31
32
  # 退出时显示稍微详细的信息
@@ -39,76 +40,100 @@ module EasyAI
39
40
  notification = load_notification
40
41
  return false unless notification
41
42
 
42
- # 检查显示频率
43
- last_shown = notification['last_shown_at']
44
- if last_shown
45
- hours_since = (Time.now - Time.parse(last_shown)) / 3600
43
+ # 只要当前版本低于最新版本就提醒
44
+ current = EasyAI::VERSION # 始终使用实际运行的版本
45
+ latest = notification['latest_version']
46
+
47
+ # 使用版本比较逻辑
48
+ return newer_version?(latest, current) if latest && current
49
+
50
+ true
51
+ end
52
+
53
+ # 版本比较:检查 latest 是否比 current 新
54
+ def newer_version?(latest, current)
55
+ return false unless latest && current
56
+
57
+ # 解析版本号 (major.minor.patch)
58
+ latest_parts = latest.split('.').map(&:to_i)
59
+ current_parts = current.split('.').map(&:to_i)
60
+
61
+ # 比较版本号
62
+ (0..2).each do |i|
63
+ latest_part = latest_parts[i] || 0
64
+ current_part = current_parts[i] || 0
46
65
 
47
- # 根据版本差异决定提醒频率
48
- if major_update?(notification)
49
- return hours_since > 6 # 主版本更新:6小时提醒一次
50
- elsif minor_update?(notification)
51
- return hours_since > 24 # 次版本更新:24小时提醒一次
52
- else
53
- return hours_since > 72 # 补丁更新:72小时提醒一次
54
- end
66
+ return true if latest_part > current_part
67
+ return false if latest_part < current_part
55
68
  end
56
69
 
57
- true
70
+ false
58
71
  end
59
72
 
60
73
  def major_update?(notification)
61
- return false unless notification['latest_version'] && notification['current_version']
74
+ return false unless notification['latest_version']
62
75
 
63
76
  latest_major = notification['latest_version'].split('.')[0].to_i
64
- current_major = notification['current_version'].split('.')[0].to_i
77
+ current_major = EasyAI::VERSION.split('.')[0].to_i
65
78
 
66
79
  latest_major > current_major
67
80
  end
68
81
 
69
82
  def minor_update?(notification)
70
- return false unless notification['latest_version'] && notification['current_version']
83
+ return false unless notification['latest_version']
71
84
 
72
85
  latest_parts = notification['latest_version'].split('.').map(&:to_i)
73
- current_parts = notification['current_version'].split('.').map(&:to_i)
86
+ current_parts = EasyAI::VERSION.split('.').map(&:to_i)
74
87
 
75
88
  latest_parts[0] == current_parts[0] && latest_parts[1] > current_parts[1]
76
89
  end
77
90
 
78
91
  def show_brief_notification(notification)
79
92
  latest = notification['latest_version']
80
- current = notification['current_version']
93
+ current = EasyAI::VERSION
81
94
 
82
- # 单行简洁提醒
95
+ # 醒目的框形提醒
83
96
  if major_update?(notification)
84
- puts "💡 重要更新: EasyAI #{latest} 已发布 (当前: #{current})。运行 'gem update easyai' 更新。".yellow
97
+ # 主版本更新使用红色警告框
98
+ puts ""
99
+ puts "┌─────────────────────────────────────────────────────┐".red
100
+ puts "│ 🚨 重要更新: EasyAI #{current} → #{latest} │".red
101
+ puts "│ 更新命令: gem update easyai │".red
102
+ puts "└─────────────────────────────────────────────────────┘".red
85
103
  else
86
- puts "💡 新版本: EasyAI #{latest} 可用。运行 'easyai --check-update' 查看详情。".cyan
104
+ # 普通更新使用黄色提示框
105
+ puts ""
106
+ puts "┌─────────────────────────────────────────────────────┐".yellow
107
+ puts "│ 📦 新版本可用: EasyAI #{current} → #{latest} │".yellow
108
+ puts "│ 更新命令: gem update easyai │".yellow
109
+ puts "└─────────────────────────────────────────────────────┘".yellow
87
110
  end
111
+ puts ""
88
112
  end
89
113
 
90
114
  def show_exit_notification(notification)
91
115
  latest = notification['latest_version']
92
- current = notification['current_version']
116
+ current = EasyAI::VERSION
93
117
 
94
118
  puts "\n" + "─" * 50
95
119
  puts "📦 EasyAI 更新提醒".yellow
96
120
  puts " 当前版本: #{current}"
97
121
  puts " 最新版本: #{latest}".green
98
122
  puts " 更新命令: gem update easyai"
99
- puts " 查看详情: easyai --check-update"
123
+ puts " 安装命令: gem install easyai"
100
124
  puts "─" * 50
101
125
  end
102
126
 
103
127
  def load_notification
104
- return nil unless File.exist?(NOTIFICATION_FILE)
105
- YAML.load_file(NOTIFICATION_FILE) rescue nil
128
+ return nil unless File.exist?(VERSION_INFO_FILE)
129
+ YAML.load_file(VERSION_INFO_FILE) rescue nil
106
130
  end
107
131
 
108
132
  def update_shown_time
109
- notification = load_notification || {}
110
- notification['last_shown_at'] = Time.now.to_s
111
- save_notification(notification)
133
+ # 读取完整的版本信息,只更新显示时间
134
+ data = load_notification || {}
135
+ data['last_shown_at'] = Time.now.to_s
136
+ save_notification(data)
112
137
  end
113
138
 
114
139
  def mark_as_shown_today
@@ -118,8 +143,8 @@ module EasyAI
118
143
  end
119
144
 
120
145
  def save_notification(data)
121
- FileUtils.mkdir_p(File.dirname(NOTIFICATION_FILE))
122
- File.write(NOTIFICATION_FILE, data.to_yaml)
146
+ FileUtils.mkdir_p(File.dirname(VERSION_INFO_FILE))
147
+ File.write(VERSION_INFO_FILE, data.to_yaml)
123
148
  rescue
124
149
  nil
125
150
  end
@@ -9,11 +9,28 @@ module EasyAI
9
9
  module Base
10
10
  class VersionChecker
11
11
  RUBYGEMS_API = 'https://rubygems.org/api/v1/gems/easyai.json'
12
- CACHE_FILE = File.expand_path('~/.easyai/version_cache.yml')
13
- CHECK_INTERVAL = 24 * 60 * 60 # 24小时检查一次
12
+ VERSION_INFO_FILE = File.expand_path('~/.easyai/version_info.yml')
13
+ CHECK_INTERVAL = 5 * 60 * 60 # 5小时检查一次
14
14
 
15
15
  class << self
16
- # 异步检查版本(不阻塞主程序)
16
+ # 同步检查版本(在当前进程中执行)
17
+ def check_sync(cached_latest_version = nil)
18
+ puts " 🔄 执行同步版本检查...".cyan if ENV['EASYAI_DEBUG']
19
+
20
+ return unless should_check?
21
+
22
+ puts " 📡 当前进程中检查版本...".green if ENV['EASYAI_DEBUG']
23
+
24
+ # 如果已经有缓存的版本信息,直接使用,避免重复网络请求
25
+ if cached_latest_version
26
+ puts " ♻️ 复用已获取的版本: #{cached_latest_version}".green if ENV['EASYAI_DEBUG']
27
+ check_and_cache_with_version(cached_latest_version)
28
+ else
29
+ check_and_cache
30
+ end
31
+ end
32
+
33
+ # 异步检查版本(不阻塞主程序)- 保留备用
17
34
  def check_async
18
35
  puts " 🔮 启动异步版本检查...".cyan if ENV['EASYAI_DEBUG']
19
36
 
@@ -41,10 +58,10 @@ module EasyAI
41
58
  return false if ENV['EASYAI_SKIP_FORCE_UPDATE'] # 紧急跳过选项
42
59
 
43
60
  # 检查缓存
44
- if File.exist?(CACHE_FILE)
45
- cache = YAML.load_file(CACHE_FILE) rescue {}
61
+ if File.exist?(VERSION_INFO_FILE)
62
+ cache = YAML.load_file(VERSION_INFO_FILE) rescue {}
46
63
  latest = cache['latest_version']
47
- current = cache['current_version'] || EasyAI::VERSION
64
+ current = EasyAI::VERSION # 直接使用实际版本
48
65
 
49
66
  return needs_major_or_minor_update?(latest, current)
50
67
  end
@@ -54,13 +71,13 @@ module EasyAI
54
71
  false
55
72
  end
56
73
 
57
- # 强制更新检查(同步)
74
+ # 强制更新检查(同步),返回获取到的最新版本
58
75
  def check_force_update!
59
76
  puts " 📌 执行强制更新检查...".cyan if ENV['EASYAI_DEBUG']
60
77
 
61
78
  # 如果缓存中已有需要强制更新的信息,直接使用
62
79
  if require_force_update?
63
- cache = YAML.load_file(CACHE_FILE) rescue {}
80
+ cache = YAML.load_file(VERSION_INFO_FILE) rescue {}
64
81
  show_force_update_message(cache['latest_version'], EasyAI::VERSION)
65
82
  exit(1)
66
83
  end
@@ -75,9 +92,17 @@ module EasyAI
75
92
  show_force_update_message(latest, EasyAI::VERSION)
76
93
  exit(1)
77
94
  end
95
+ return latest # 返回获取到的版本,供后续使用
78
96
  else
79
97
  puts " 💾 使用缓存(未过期)".cyan if ENV['EASYAI_DEBUG']
98
+ # 从缓存中获取版本信息
99
+ if File.exist?(VERSION_INFO_FILE)
100
+ cache = YAML.load_file(VERSION_INFO_FILE) rescue {}
101
+ return cache['latest_version']
102
+ end
80
103
  end
104
+
105
+ nil
81
106
  end
82
107
 
83
108
  # 同步检查版本(用于 --check-update 命令)
@@ -99,9 +124,9 @@ module EasyAI
99
124
 
100
125
  # 显示缓存的更新提醒(如果有)
101
126
  def show_cached_reminder
102
- return unless File.exist?(CACHE_FILE)
127
+ return unless File.exist?(VERSION_INFO_FILE)
103
128
 
104
- cache = YAML.load_file(CACHE_FILE) rescue {}
129
+ cache = YAML.load_file(VERSION_INFO_FILE) rescue {}
105
130
  return unless cache['new_version_available']
106
131
  return if cache['reminder_shown_at'] &&
107
132
  Time.now - Time.parse(cache['reminder_shown_at']) < 3600 # 1小时内不重复提醒
@@ -124,8 +149,8 @@ module EasyAI
124
149
  return false if ENV['EASYAI_NO_UPDATE_CHECK'] # 允许用户禁用
125
150
 
126
151
  # 检查缓存文件
127
- if File.exist?(CACHE_FILE)
128
- cache = YAML.load_file(CACHE_FILE) rescue {}
152
+ if File.exist?(VERSION_INFO_FILE)
153
+ cache = YAML.load_file(VERSION_INFO_FILE) rescue {}
129
154
  last_check = cache['last_check_at']
130
155
  if last_check
131
156
  time_since_check = Time.now - Time.parse(last_check)
@@ -140,67 +165,66 @@ module EasyAI
140
165
  latest = fetch_latest_version
141
166
  return unless latest
142
167
 
168
+ check_and_cache_with_version(latest)
169
+ rescue => e
170
+ # 静默失败,不影响主程序
171
+ nil
172
+ end
173
+
174
+ # 使用已知的最新版本更新缓存
175
+ def check_and_cache_with_version(latest)
176
+ return unless latest
177
+
178
+ # 不记录 current_version,运行时直接使用 EasyAI::VERSION 比较
143
179
  current = EasyAI::VERSION
144
180
  is_new = newer_version?(latest, current)
145
181
 
182
+ # 读取现有文件以保留提醒显示时间
183
+ existing_data = {}
184
+ if File.exist?(VERSION_INFO_FILE)
185
+ existing_data = YAML.load_file(VERSION_INFO_FILE) rescue {}
186
+ end
187
+
146
188
  cache = {
147
189
  'last_check_at' => Time.now.to_s,
148
190
  'latest_version' => latest,
149
- 'current_version' => current,
150
- 'new_version_available' => is_new
191
+ 'new_version_available' => is_new,
192
+ 'last_shown_at' => existing_data['last_shown_at'], # 保留上次显示时间
193
+ 'shown_today' => existing_data['shown_today'] # 保留今日显示标记
151
194
  }
152
195
 
153
196
  save_cache(cache)
154
-
155
- # 同时更新通知文件
156
- if is_new
157
- update_notification(latest, current)
158
- end
159
197
  rescue => e
160
198
  # 静默失败,不影响主程序
161
199
  nil
162
200
  end
163
201
 
164
- def update_notification(latest, current)
165
- notification_file = File.expand_path('~/.easyai/update_notification.yml')
166
- notification = {
167
- 'available' => true,
168
- 'latest_version' => latest,
169
- 'current_version' => current,
170
- 'checked_at' => Time.now.to_s
171
- }
172
-
173
- # 保留上次显示时间
174
- if File.exist?(notification_file)
175
- old_data = YAML.load_file(notification_file) rescue {}
176
- notification['last_shown_at'] = old_data['last_shown_at']
177
- notification['shown_today'] = old_data['shown_today']
178
- end
179
-
180
- FileUtils.mkdir_p(File.dirname(notification_file))
181
- File.write(notification_file, notification.to_yaml)
182
- rescue
183
- nil
184
- end
185
202
 
186
203
  def fetch_latest_version
187
204
  uri = URI(RUBYGEMS_API)
188
205
 
189
- http = Net::HTTP.new(uri.host, uri.port)
206
+ # 创建 HTTP 连接,禁用代理
207
+ http = Net::HTTP.new(uri.host, uri.port, nil, nil) # 后两个参数为 proxy_addr, proxy_port,设为 nil 禁用代理
190
208
  http.use_ssl = true
191
- http.open_timeout = 2 # 快速超时
192
- http.read_timeout = 2
209
+ http.open_timeout = 3 # 快速超时
210
+ http.read_timeout = 3
211
+
212
+ puts " 🌐 直连 RubyGems API (跳过代理)...".cyan if ENV['EASYAI_DEBUG']
193
213
 
194
214
  request = Net::HTTP::Get.new(uri)
195
215
  response = http.request(request)
196
216
 
197
217
  if response.code == '200'
198
218
  data = JSON.parse(response.body)
199
- data['version']
219
+ version = data['version']
220
+ puts " ✅ 获取到最新版本: #{version}".green if ENV['EASYAI_DEBUG']
221
+ version
200
222
  else
223
+ puts " ❌ API 响应错误: #{response.code}".yellow if ENV['EASYAI_DEBUG']
201
224
  nil
202
225
  end
203
226
  rescue => e
227
+ puts " ⚠️ 版本获取失败: #{e.message}".yellow if ENV['EASYAI_DEBUG']
204
228
  nil # 网络错误时静默失败
205
229
  end
206
230
 
@@ -241,16 +265,16 @@ module EasyAI
241
265
 
242
266
  # 是否应该立即检查
243
267
  def should_check_immediately?
244
- return true unless File.exist?(CACHE_FILE)
268
+ return true unless File.exist?(VERSION_INFO_FILE)
245
269
 
246
- cache = YAML.load_file(CACHE_FILE) rescue {}
270
+ cache = YAML.load_file(VERSION_INFO_FILE) rescue {}
247
271
  last_check = cache['last_check_at']
248
272
 
249
- # 如果没有检查记录或缓存超过6小时,立即检查
273
+ # 如果没有检查记录或缓存超过指定时间间隔,立即检查
250
274
  return true unless last_check
251
275
 
252
276
  time_since_check = Time.now - Time.parse(last_check)
253
- time_since_check > 6 * 60 * 60 # 6小时
277
+ time_since_check > CHECK_INTERVAL
254
278
  end
255
279
 
256
280
  # 更新缓存(强制更新场景)
@@ -258,7 +282,6 @@ module EasyAI
258
282
  cache = {
259
283
  'last_check_at' => Time.now.to_s,
260
284
  'latest_version' => latest,
261
- 'current_version' => current,
262
285
  'new_version_available' => true,
263
286
  'force_update_required' => true
264
287
  }
@@ -266,8 +289,8 @@ module EasyAI
266
289
  end
267
290
 
268
291
  def save_cache(data)
269
- FileUtils.mkdir_p(File.dirname(CACHE_FILE))
270
- File.write(CACHE_FILE, data.to_yaml)
292
+ FileUtils.mkdir_p(File.dirname(VERSION_INFO_FILE))
293
+ File.write(VERSION_INFO_FILE, data.to_yaml)
271
294
  rescue => e
272
295
  # 静默失败
273
296
  nil
@@ -60,8 +60,6 @@ module EasyAI
60
60
 
61
61
  def run
62
62
  begin
63
- # 在非verbose模式下显示简洁的更新提醒
64
- Base::UpdateNotifier.maybe_show_notification unless @verbose_mode
65
63
 
66
64
  # 首先尝试从远程下载配置
67
65
  remote_config = nil
@@ -1,3 +1,3 @@
1
1
  module EasyAI
2
- VERSION = '1.0.6'
2
+ VERSION = '1.0.9'
3
3
  end
data/lib/easyai.rb CHANGED
@@ -8,6 +8,7 @@ require 'easyai/command/utils'
8
8
  require 'easyai/command/clean'
9
9
  require 'easyai/command/update'
10
10
  require 'easyai/base/version_checker'
11
+ require 'easyai/base/update_notifier'
11
12
 
12
13
  module EasyAI
13
14
  # EasyAI 应用程序主类
@@ -72,10 +73,13 @@ module EasyAI
72
73
  return if skip_check
73
74
 
74
75
  # 强制更新检查(会阻塞执行)
75
- Base::VersionChecker.check_force_update!
76
+ latest_version = Base::VersionChecker.check_force_update!
76
77
 
77
- # 异步更新检查(不阻塞执行)
78
- Base::VersionChecker.check_async
78
+ # 同步更新检查(在当前进程中执行,复用已获取的版本)
79
+ Base::VersionChecker.check_sync(latest_version)
80
+
81
+ # 显示更新提醒(如果有新版本)
82
+ Base::UpdateNotifier.maybe_show_notification
79
83
 
80
84
  puts "✅ #{'版本检查完成'.green}" if ENV['EASYAI_DEBUG']
81
85
  rescue => e
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: easyai
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.6
4
+ version: 1.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wade