easyai 1.1.1 → 1.1.3

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: 60e6aec7d6d0d2475a75e26f61f21f1f5354b75ba828006293cdcdd3a6961f8a
4
- data.tar.gz: bd0c31dccfcb0918707972a72415382b6ca778015ae67932626e4ad40933b747
3
+ metadata.gz: 92482873797bd9a6936d1b493799244501b94440c155fe49e15b5aa889291ada
4
+ data.tar.gz: e3e619b6bd230d469dbb21fc2372e714813a504162e392680907f8fb3eec39aa
5
5
  SHA512:
6
- metadata.gz: 31725ddd0f5c1ce5e3acda536b8c502addefc67271abb0b719521349fd3f3d840f2c41151982fbaca3044d34e6e110ef5e663155ee5c71ff636a6eb5af6b749a
7
- data.tar.gz: 3045e64aa95c96a0ca58934f080dc6e82512121348290db4b4d8859b0af016f343893a8208f281f6be33af75afd4e2160fbc04451adf8f89ff9d62a21b202719
6
+ metadata.gz: 1bb5fef07b98087e297e3db2a37f29abe34966771a58fca4c6297f7c29cb2e0136ef97cd7467d2bf8eff730bb2e693334776eeb241d7148ea94b12fdaa7f148e
7
+ data.tar.gz: 5a46f13a20d253320c6a039802cbd4caf93780bd5e1570680b51442722c8a42f9eb1b8fa607d4f8eb11ccb2fcf936764d2ad8ba70653a97af9eec2d010bd4b90
@@ -14,7 +14,7 @@ module EasyAI
14
14
  class JPSLogin
15
15
  attr_reader :access_token, :username, :expires_at
16
16
 
17
- def initialize
17
+ def initialize(options = {})
18
18
  @client_id = "cli_a7bc7fe9b3d1d00b"
19
19
  @server_port = 8898
20
20
  @state = "client_login"
@@ -32,7 +32,10 @@ module EasyAI
32
32
  @access_token = nil
33
33
  @username = nil
34
34
  @expires_at = nil
35
-
35
+
36
+ # 从选项中获取 verbose 标志
37
+ @verbose = options[:verbose] || false
38
+
36
39
  # token 存储路径
37
40
  @token_dir = File.expand_path('~/.easyai')
38
41
  @token_file = File.join(@token_dir, '.jpstoken')
@@ -44,9 +47,14 @@ module EasyAI
44
47
  if load_stored_token && validate_token
45
48
  return true
46
49
  end
47
-
50
+
48
51
  puts "🔐 需要登录 JPS..."
49
- return authorize_and_login
52
+ result = authorize_and_login
53
+
54
+ # 如果用户主动取消,返回特殊标识
55
+ return :user_cancelled if result == :user_cancelled
56
+
57
+ return result
50
58
  end
51
59
 
52
60
  # 获取用户名(登录后可用)
@@ -93,8 +101,12 @@ module EasyAI
93
101
  # 构建授权 URL
94
102
  authorization_uri = build_authorization_uri
95
103
  puts "正在打开浏览器进行飞书 OAuth 授权..."
96
- puts "授权 URL: #{authorization_uri}"
97
-
104
+ puts "\n授权 URL(如自动打开失败,请手动复制下面的链接到浏览器):"
105
+ puts "=" * 80
106
+ puts authorization_uri
107
+ puts "=" * 80
108
+ puts ""
109
+
98
110
  # 在浏览器中打开授权 URL
99
111
  open_browser(authorization_uri)
100
112
 
@@ -103,33 +115,88 @@ module EasyAI
103
115
 
104
116
  # 如果自动获取失败,提示用户手动输入
105
117
  if code.nil?
106
- puts "自动获取授权码失败,您可以手动输入:"
107
- puts "1. 授权码 (直接复制 'code=' 后面的内容)"
108
- puts "2. 完整回调 URL"
109
- print "> "
110
- input = STDIN.gets.chomp
111
-
112
- if input.start_with?("http")
113
- # 尝试从 URL 中提取 code
118
+ loop do
119
+ puts "\n自动获取授权码失败,请选择:"
120
+ puts "1. 输入授权码 (直接复制 'code=' 后面的内容)"
121
+ puts "2. 输入完整回调 URL"
122
+ puts "3. 重新打开授权网页"
123
+ puts "4. 退出"
124
+ print "> "
125
+
114
126
  begin
115
- uri = URI(input)
116
- query_params = URI.decode_www_form(uri.query || '').to_h
117
- code = query_params['code']
118
- puts "从 URL 中成功提取授权码" if code
119
- rescue => e
120
- puts "无法从 URL 中提取授权码: #{e.message}"
127
+ choice = STDIN.gets&.chomp
128
+
129
+ # 处理 Ctrl+C 中断
130
+ if choice.nil?
131
+ puts "\n用户中断操作"
132
+ return :user_cancelled
133
+ end
134
+
135
+ case choice
136
+ when "1"
137
+ puts "请输入授权码:"
138
+ print "> "
139
+ code_input = STDIN.gets&.chomp
140
+ if code_input.nil?
141
+ puts "用户中断操作"
142
+ return :user_cancelled
143
+ elsif !code_input.empty?
144
+ code = code_input
145
+ break
146
+ else
147
+ puts "授权码不能为空,请重新选择"
148
+ end
149
+ when "2"
150
+ puts "请输入完整回调 URL:"
151
+ print "> "
152
+ url_input = STDIN.gets&.chomp
153
+ if url_input.nil?
154
+ puts "用户中断操作"
155
+ return :user_cancelled
156
+ elsif url_input.start_with?("http")
157
+ # 尝试从 URL 中提取 code
158
+ begin
159
+ uri = URI(url_input)
160
+ query_params = URI.decode_www_form(uri.query || '').to_h
161
+ code = query_params['code']
162
+ if code
163
+ puts "✓ 从 URL 中成功提取授权码"
164
+ break
165
+ else
166
+ puts "✗ URL 中没有找到授权码,请重新选择"
167
+ end
168
+ rescue => e
169
+ puts "✗ 无法从 URL 中提取授权码: #{e.message}"
170
+ end
171
+ else
172
+ puts "✗ 无效的 URL 格式,请重新选择"
173
+ end
174
+ when "3"
175
+ # 重新打开授权网页
176
+ puts "正在重新打开授权网页..."
177
+ open_browser(authorization_uri)
178
+ # 重新启动服务器尝试获取授权码
179
+ code = start_callback_server
180
+ if code
181
+ break
182
+ end
183
+ # 如果还是失败,继续循环让用户选择
184
+ when "4"
185
+ puts "已退出授权流程"
186
+ return :user_cancelled
187
+ else
188
+ puts "无效的选择,请输入 1-4 之间的数字"
189
+ end
190
+ rescue Interrupt
191
+ puts "\n\n用户中断操作"
192
+ return :user_cancelled
121
193
  end
122
- else
123
- # 将输入直接作为 code
124
- code = input unless input.empty?
125
194
  end
126
195
  end
127
196
 
128
197
  if code
129
- puts "成功获取授权码!正在使用飞书身份登录 JPS..."
130
198
  if exchange_code_for_token(code)
131
- puts "✓ JPS 登录成功!"
132
- puts " 用户名: #{@username}"
199
+ puts "✓ JPS 登录成功!用户名: #{@username}"
133
200
  store_token
134
201
  return true
135
202
  end
@@ -181,8 +248,10 @@ module EasyAI
181
248
  return nil
182
249
  end
183
250
 
184
- puts "启动本地服务器,监听端口 #{@server_port}..."
185
-
251
+ puts "启动本地服务器,监听端口 #{@server_port}..." if @verbose
252
+ puts "提示:按 Ctrl+C 可以中断并获得更多选择"
253
+ puts "🔄 正在使用飞书身份登录 JPS..."
254
+
186
255
  begin
187
256
  server = WEBrick::HTTPServer.new(
188
257
  Port: @server_port,
@@ -209,19 +278,19 @@ module EasyAI
209
278
  begin
210
279
  # 解析请求参数
211
280
  query_params = URI.decode_www_form(req.query_string || '').to_h
212
- puts "接收到回调请求,参数: #{query_params.inspect}"
281
+ puts "接收到回调请求,参数: #{query_params.inspect}" if @verbose
213
282
 
214
283
  if query_params['error']
215
- puts "授权错误: #{query_params['error']}"
284
+ puts "授权错误: #{query_params['error']}" if @verbose
216
285
  res.content_type = "text/html; charset=UTF-8"
217
286
  res.body = build_error_page(query_params['error'])
218
287
  elsif query_params['code']
219
288
  code = query_params['code']
220
- puts "成功获取授权码"
289
+ puts "成功获取授权码" if @verbose
221
290
  res.content_type = "text/html; charset=UTF-8"
222
291
  res.body = build_success_page
223
292
  else
224
- puts "未获取到授权码"
293
+ puts "未获取到授权码" if @verbose
225
294
  res.content_type = "text/html; charset=UTF-8"
226
295
  res.body = build_error_page("未获取到授权码")
227
296
  end
@@ -275,14 +344,14 @@ module EasyAI
275
344
  request['Content-Type'] = 'application/json'
276
345
  request.body = request_data.to_json
277
346
 
278
- puts "正在请求 JPS API: #{@api_endpoint}"
347
+ puts "正在请求 JPS API: #{@api_endpoint}" if @verbose
279
348
  response = http.request(request)
280
-
281
- puts "API 响应状态码: #{response.code}"
349
+
350
+ puts "API 响应状态码: #{response.code}" if @verbose
282
351
 
283
352
  if response.body
284
353
  result = JSON.parse(response.body)
285
- puts "API 响应: #{result.inspect}"
354
+ puts "API 响应: #{result.inspect}" if @verbose
286
355
 
287
356
  if result['meta'] && result['meta']['code'] == 200 && result['data']
288
357
  data = result['data']
@@ -322,7 +391,7 @@ module EasyAI
322
391
  }
323
392
 
324
393
  File.write(@token_file, token_data.to_json)
325
- puts "✓ JPS Token 和用户名已存储到 #{@token_file}"
394
+ puts "✓ JPS Token 和用户名已存储到 #{@token_file}" if @verbose
326
395
  rescue => e
327
396
  puts "⚠ 存储 JPS Token 失败: #{e.message}"
328
397
  end
@@ -72,8 +72,15 @@ module EasyAI
72
72
  else
73
73
  # 从远程下载配置,传递选项
74
74
  print_status("🔄 获取远程配置", "默认用户")
75
- options = { no_keychain: @no_keychain }
75
+ options = { no_keychain: @no_keychain, verbose: @verbose_mode }
76
76
  remote_config = ConfigManager.download_user_config(nil, options)
77
+
78
+ # 处理用户取消授权的情况
79
+ if remote_config == :user_cancelled
80
+ print_error("用户取消了授权登录")
81
+ exit 0
82
+ end
83
+
77
84
  print_success("配置加载成功") if remote_config
78
85
  end
79
86
 
@@ -81,7 +88,7 @@ module EasyAI
81
88
  if remote_config.nil?
82
89
  print_warning("使用本地配置")
83
90
  remote_config = load_local_yaml_config
84
-
91
+
85
92
  # 如果本地配置也为空,提示用户先进行设置
86
93
  if remote_config.empty?
87
94
  print_error("未找到有效配置")
@@ -14,6 +14,7 @@ module EasyAI
14
14
 
15
15
  # 类变量初始化
16
16
  @@no_keychain = false
17
+ @@verbose = false
17
18
 
18
19
  # 管理配置仓库:如果存在则更新,不存在则下载
19
20
  def self.manage_config_repo
@@ -65,7 +66,7 @@ module EasyAI
65
66
 
66
67
  # 下载配置仓库到固定位置
67
68
  def self.download_config_repo
68
- puts "正在下载配置仓库到 #{CONFIG_REPO_DIR}..."
69
+ puts "正在下载配置仓库到 #{CONFIG_REPO_DIR}..." if @@verbose
69
70
 
70
71
  begin
71
72
  # 克隆仓库到固定位置,捕获错误信息
@@ -94,8 +95,9 @@ module EasyAI
94
95
 
95
96
  # 设置全局选项
96
97
  @@no_keychain = options[:no_keychain] || false
98
+ @@verbose = options[:verbose] || false
97
99
 
98
- puts "正在从本地配置仓库加载配置..."
100
+ puts "正在从本地配置仓库加载配置..." if @@verbose
99
101
 
100
102
  begin
101
103
  # 检查 index.json 文件,支持加密版本
@@ -134,8 +136,13 @@ module EasyAI
134
136
  selected_user = user_name
135
137
  else
136
138
  # 统一使用 JPS 登录获取用户名
137
- selected_user = get_username_from_jps
138
- if selected_user.nil? || selected_user.strip.empty?
139
+ selected_user = get_username_from_jps(@@verbose)
140
+
141
+ # 处理用户取消的情况
142
+ if selected_user == :user_cancelled
143
+ puts "✗ 用户取消了授权登录"
144
+ return :user_cancelled
145
+ elsif selected_user.nil? || selected_user.strip.empty?
139
146
  puts "✗ JPS 登录失败,无法获取用户名"
140
147
  return nil
141
148
  end
@@ -176,8 +183,14 @@ module EasyAI
176
183
  def self.download_user_config(user_name = nil, options = {})
177
184
  # 优先尝试使用本地配置仓库
178
185
  config = load_from_local_repo(user_name, options)
186
+
187
+ # 如果用户取消了授权,返回特殊标识
188
+ if config == :user_cancelled
189
+ return :user_cancelled
190
+ end
191
+
179
192
  return config if config
180
-
193
+
181
194
  # 如果本地仓库失败,回退到临时下载方式
182
195
  puts "本地配置仓库不可用,使用临时下载..."
183
196
  download_user_config_temp(user_name, options)
@@ -189,6 +202,7 @@ module EasyAI
189
202
 
190
203
  # 设置全局选项
191
204
  @@no_keychain = options[:no_keychain] || false
205
+ @@verbose = options[:verbose] || false
192
206
 
193
207
  begin
194
208
  # 创建临时目录
@@ -248,8 +262,14 @@ module EasyAI
248
262
  selected_user = user_name
249
263
  else
250
264
  # 统一使用 JPS 登录获取用户名
251
- selected_user = get_username_from_jps
252
- if selected_user.nil? || selected_user.strip.empty?
265
+ selected_user = get_username_from_jps(@@verbose)
266
+
267
+ # 处理用户取消的情况
268
+ if selected_user == :user_cancelled
269
+ puts "✗ 用户取消了授权登录"
270
+ cleanup_temp_dir(temp_dir)
271
+ return nil
272
+ elsif selected_user.nil? || selected_user.strip.empty?
253
273
  puts "✗ JPS 登录失败,无法获取用户名"
254
274
  cleanup_temp_dir(temp_dir)
255
275
  return nil
@@ -315,11 +335,17 @@ module EasyAI
315
335
  end
316
336
 
317
337
  # 通过 JPS 登录获取用户名
318
- def self.get_username_from_jps
338
+ def self.get_username_from_jps(verbose = false)
319
339
  begin
320
- jps_login = Auth::JPSLogin.new
321
-
322
- if jps_login.login
340
+ jps_login = Auth::JPSLogin.new(verbose: verbose)
341
+ login_result = jps_login.login
342
+
343
+ # 处理用户主动取消的情况
344
+ if login_result == :user_cancelled
345
+ return :user_cancelled
346
+ end
347
+
348
+ if login_result
323
349
  username = jps_login.get_username
324
350
  if username && !username.empty?
325
351
  puts "👤 用户: #{username}"
@@ -329,7 +355,7 @@ module EasyAI
329
355
  rescue => e
330
356
  puts "❌ JPS 登录失败: #{e.message}"
331
357
  end
332
-
358
+
333
359
  return nil
334
360
  end
335
361
 
@@ -356,7 +382,7 @@ module EasyAI
356
382
  end
357
383
 
358
384
  def self.load_encrypted_config_file(encrypted_config_file)
359
- puts "正在解密配置文件..."
385
+ puts "正在解密配置文件..." if @@verbose
360
386
 
361
387
  # 使用新的密码验证机制
362
388
  result = get_and_validate_password(encrypted_config_file, "请输入解密密码: ")
@@ -373,7 +399,7 @@ module EasyAI
373
399
  end
374
400
 
375
401
  def self.parse_encrypted_index_file(encrypted_index_file)
376
- puts "正在解密 index.json..."
402
+ puts "正在解密 index.json..." if @@verbose
377
403
 
378
404
  # 使用新的密码验证机制
379
405
  result = get_and_validate_password(encrypted_index_file, "请输入解密密码: ")
@@ -472,7 +498,7 @@ module EasyAI
472
498
  stored_password = Base::SystemKeychain.get_stored_password
473
499
 
474
500
  if stored_password && !stored_password.empty?
475
- puts "使用系统存储的密码进行解密..."
501
+ puts "使用系统存储的密码进行解密..." if @@verbose
476
502
  return { password: stored_password, from_system: true }
477
503
  end
478
504
 
@@ -1,3 +1,3 @@
1
1
  module EasyAI
2
- VERSION = '1.1.1'
2
+ VERSION = '1.1.3'
3
3
  end
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.1.1
4
+ version: 1.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wade