pindo 5.16.3 → 5.16.5

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: 422206b97d48082c23809fd79aabd82b7b3c37ce894fb59ea3356afe4f00f2ce
4
- data.tar.gz: 6d633e17089d40b280387b2203f7912bd44d09f6635aff383d454589e1b83433
3
+ metadata.gz: 061bf75ae3563da24c18d0d4204fdecac9d03011e1493dd4e89b53d9b112d617
4
+ data.tar.gz: a51d17f8a46a767527a34f970657c7cf164511902c28f46e7567b6264de3079f
5
5
  SHA512:
6
- metadata.gz: 2cc63d005cf7d980a24cfedc90909ec9417ca8e05fcd6a169502aa6e2684ea601fd6aabcf49ca7e275ab9da58e85348c5078819c99e7497a7edcf92b5728f5c4
7
- data.tar.gz: ecfabd23ce708f5f0e2e58b07bfbadf91181f4c604cf796a9851db7ac06e1bc4ce350b8e1f44036b82752705b7b887f7e925b4882c565b924caaec6ce0e5ddf2
6
+ metadata.gz: efc7584e50c172c78c3e53f45ff97b335f18c60565d02ef8892273c29c253199909c54f590673ab232dfe688a086270d7200097293d7a6c1e0320efd682d2dfb
7
+ data.tar.gz: d0d46c6e9bc600c526e7c3ef2cb4fce1fafd47d39d8e806161d3843cbd40098fac4fecc33fb1f2141cec6d7163ea1ca1ec1642e10f214c7f3beef220bce54e5c
@@ -105,7 +105,7 @@ module Pindo
105
105
  Funlog.current_output_sink.log_info(Funlog.current_task_id, message)
106
106
  else
107
107
  # 串行模式:保持原有行为
108
- puts "#{message}"
108
+ puts " #{message}"
109
109
  end
110
110
  end
111
111
 
@@ -0,0 +1,253 @@
1
+ require 'highline/import'
2
+ require 'fileutils'
3
+ require 'json'
4
+ require 'tmpdir'
5
+ require 'pindo/base/funlog'
6
+
7
+ module Pindo
8
+ class Command
9
+ class Utils < Command
10
+ class Installskills < Utils
11
+
12
+ self.summary = '安装 Claude Code 技能到本地项目'
13
+
14
+ self.description = <<-DESC
15
+ 安装 Claude Code 技能到本地项目。
16
+
17
+ 支持功能:
18
+ - 从技能仓库克隆指定技能
19
+ - 支持安装单个或多个技能
20
+
21
+ 使用示例:
22
+ pindo utils installskills # 交互式选择仓库安装
23
+ pindo utils installskills skill-name # 从默认仓库安装指定技能
24
+ pindo utils installskills skill1 skill2 # 安装多个技能
25
+ pindo utils installskills --source=https://gitee.com/your/skills.git # 从指定仓库安装
26
+ DESC
27
+
28
+ self.arguments = [
29
+ CLAide::Argument.new('skill_name', false),
30
+ ]
31
+
32
+ def self.options
33
+ [
34
+ ['--source=URL', '指定技能仓库地址,指定后跳过仓库选择'],
35
+ ].concat(super)
36
+ end
37
+
38
+ def initialize(argv)
39
+ @skill_names = argv.arguments! || []
40
+ @source = argv.option('source')
41
+
42
+ super
43
+ @additional_args = argv.remainder!
44
+ end
45
+
46
+ def run
47
+ # 确定使用的仓库
48
+ repo_info = determine_repo
49
+ return if repo_info.nil?
50
+
51
+ # 克隆仓库到临时目录
52
+ temp_dir = clone_repo_to_temp(repo_info)
53
+ return if temp_dir.nil?
54
+
55
+ begin
56
+ # 安装 command 和 skills
57
+ install_from_repo(temp_dir, repo_info['skills_repo_name'] || 'custom')
58
+ ensure
59
+ # 清理临时目录
60
+ FileUtils.rm_rf(temp_dir) if File.exist?(temp_dir)
61
+ end
62
+ end
63
+
64
+ private
65
+
66
+ def determine_repo
67
+ # 如果指定了 --source,直接使用
68
+ if @source
69
+ return {
70
+ 'skills_repo_name' => 'custom',
71
+ 'skills_repo_desc' => '自定义仓库',
72
+ 'git_url' => @source
73
+ }
74
+ end
75
+
76
+ # 从配置读取仓库列表
77
+ repos = skills_repo_array
78
+
79
+ if repos.empty?
80
+ Funlog.error("未配置技能仓库,请在 ~/.pindo/pindo_common_config/pindo_config.json 中配置 skills_repo_array")
81
+ return nil
82
+ end
83
+
84
+ if repos.length == 1
85
+ Funlog.info("使用默认仓库: #{repos.first['skills_repo_name']}")
86
+ return repos.first
87
+ end
88
+
89
+ # 交互式选择仓库
90
+ interactive_select_repo(repos)
91
+ end
92
+
93
+ def skills_repo_array
94
+ config = pindo_single_config.pindo_user_config_json
95
+ return [] unless config
96
+
97
+ repos = config['skills_repo_array']
98
+ return [] unless repos.is_a?(Array)
99
+
100
+ repos
101
+ end
102
+
103
+ def interactive_select_repo(repos)
104
+ Funlog.info("")
105
+ Funlog.info("=============================================================")
106
+ Funlog.info(" 请选择要安装的仓库")
107
+ Funlog.info("=============================================================")
108
+ Funlog.info("")
109
+
110
+ repos.each_with_index do |repo, index|
111
+ name = repo['skills_repo_name'] || "未命名#{index + 1}"
112
+ desc = repo['skills_repo_desc'] || ''
113
+
114
+ # 显示序号和名称
115
+ Funlog.info("[#{index + 1}] #{name}")
116
+
117
+ # 显示描述(如果有)
118
+ unless desc.empty?
119
+ desc.lines.each do |line|
120
+ Funlog.info(" #{line.chomp}")
121
+ end
122
+ end
123
+
124
+ # 显示仓库URL(调试模式)
125
+ if ENV['PINDO_DEBUG'] && repo['git_url']
126
+ Funlog.info(" URL: #{repo['git_url']}")
127
+ end
128
+
129
+ Funlog.info("")
130
+ end
131
+
132
+ # 使用 HighLine 获取用户输入
133
+ cli = HighLine.new
134
+ input = cli.ask("请输入序号 (1-#{repos.length}): ")
135
+
136
+ num = input.to_i
137
+ if num >= 1 && num <= repos.length
138
+ selected = repos[num - 1]
139
+ Funlog.info("已选择: #{selected['skills_repo_name']}")
140
+ selected
141
+ else
142
+ Funlog.error("无效选择,请输入 1-#{repos.length} 之间的数字")
143
+ nil
144
+ end
145
+ end
146
+
147
+ def clone_repo_to_temp(repo_info)
148
+ url = repo_info['git_url']
149
+ repo_name = repo_info['skills_repo_name'] || 'temp_repo'
150
+
151
+ unless url
152
+ Funlog.error("仓库配置错误,缺少 git_url")
153
+ return nil
154
+ end
155
+
156
+ # 创建系统临时目录
157
+ temp_dir = Dir.mktmpdir(['pindo_skills_', "_#{repo_name}"])
158
+
159
+ Funlog.fancyinfo_start("克隆仓库: #{url}...")
160
+ Funlog.info("仓库 URL: #{url}") if ENV['PINDO_DEBUG']
161
+
162
+ # 克隆仓库
163
+ success = system("git clone #{url} #{temp_dir} --quiet 2>/dev/null")
164
+
165
+ unless success && File.exist?(File.join(temp_dir, '.git'))
166
+ Funlog.fancyinfo_error("仓库克隆失败: #{url}")
167
+ FileUtils.rm_rf(temp_dir) if File.exist?(temp_dir)
168
+ return nil
169
+ end
170
+
171
+ Funlog.fancyinfo_success("仓库克隆完成")
172
+ temp_dir
173
+ end
174
+
175
+ def install_from_repo(repo_dir, repo_name)
176
+ installed = false
177
+
178
+ # 安装 commands 目录(合并式拷贝)
179
+ source_commands = File.join(repo_dir, 'commands')
180
+ target_commands = File.expand_path('~/.claude/commands')
181
+
182
+ if File.exist?(source_commands) && File.directory?(source_commands)
183
+ Funlog.info("安装 commands...")
184
+ FileUtils.mkdir_p(target_commands)
185
+
186
+ Dir.glob(File.join(source_commands, '*')).each do |item|
187
+ next if File.basename(item).start_with?('.')
188
+
189
+ target = File.join(target_commands, File.basename(item))
190
+
191
+ if File.directory?(item)
192
+ # 子目录:合并到目标对应子目录
193
+ FileUtils.mkdir_p(target)
194
+ Dir.glob(File.join(item, '*')).each do |sub_item|
195
+ next if File.basename(sub_item).start_with?('.')
196
+ target_sub = File.join(target, File.basename(sub_item))
197
+ FileUtils.rm_rf(target_sub) if File.exist?(target_sub)
198
+ FileUtils.cp_r(sub_item, target_sub)
199
+ end
200
+ else
201
+ # 直接文件:拷贝到目标目录
202
+ FileUtils.rm_f(target) if File.exist?(target)
203
+ FileUtils.cp(item, target)
204
+ end
205
+ Funlog.info(" ✓ #{File.basename(item)}")
206
+ end
207
+ installed = true
208
+ end
209
+
210
+ # 安装 skills 目录(合并式拷贝)
211
+ source_skills = File.join(repo_dir, 'skills')
212
+ target_skills = File.expand_path('~/.claude/skills')
213
+
214
+ if File.exist?(source_skills) && File.directory?(source_skills)
215
+ Funlog.info("安装 skills...")
216
+ FileUtils.mkdir_p(target_skills)
217
+
218
+ Dir.glob(File.join(source_skills, '*')).each do |item|
219
+ next if File.basename(item).start_with?('.')
220
+
221
+ target = File.join(target_skills, File.basename(item))
222
+
223
+ if File.directory?(item)
224
+ # 子目录:合并到目标对应子目录
225
+ FileUtils.mkdir_p(target)
226
+ Dir.glob(File.join(item, '*')).each do |sub_item|
227
+ next if File.basename(sub_item).start_with?('.')
228
+ target_sub = File.join(target, File.basename(sub_item))
229
+ FileUtils.rm_rf(target_sub) if File.exist?(target_sub)
230
+ FileUtils.cp_r(sub_item, target_sub)
231
+ end
232
+ else
233
+ # 直接文件:拷贝到目标目录
234
+ FileUtils.rm_f(target) if File.exist?(target)
235
+ FileUtils.cp(item, target)
236
+ end
237
+ Funlog.info(" ✓ #{File.basename(item)}")
238
+ end
239
+ installed = true
240
+ end
241
+
242
+ if installed
243
+ Funlog.fancyinfo_success("技能安装完成: #{repo_name}")
244
+ Funlog.info("安装位置: ~/.claude/")
245
+ else
246
+ Funlog.warning("仓库中未找到 commands 或 skills 目录")
247
+ end
248
+ end
249
+
250
+ end
251
+ end
252
+ end
253
+ end
@@ -13,6 +13,7 @@ require 'pindo/command/utils/updateconfig'
13
13
  require 'pindo/command/utils/fabric'
14
14
  require 'pindo/command/utils/encrypt'
15
15
  require 'pindo/command/utils/decrypt'
16
+ require 'pindo/command/utils/installskills'
16
17
 
17
18
 
18
19
  module Pindo
@@ -164,19 +164,47 @@ module Pindo
164
164
  # 4. 提交到 JPS 项目
165
165
  puts "📋 提交到 JPS 项目..."
166
166
 
167
+ # 构建请求参数
168
+ request_params = {
169
+ packageUrl: file_url,
170
+ attachFileUrls: []
171
+ }
172
+
173
+ if ENV['PINDO_DEBUG']
174
+ puts "[DEBUG] 提交参数:"
175
+ puts "[DEBUG] 项目ID: #{nuget_project['id']}"
176
+ puts "[DEBUG] 项目名称: #{nuget_project['projectName']}"
177
+ puts "[DEBUG] 包URL: #{file_url}"
178
+ puts "[DEBUG] 附件URLs: #{request_params[:attachFileUrls].inspect}"
179
+ end
180
+
181
+ puts "++++++ 1 upload_nuget_package" if ENV['PINDO_DEBUG']
167
182
  result = jps_client.upload_nuget_package(
168
183
  projectId: nuget_project['id'],
169
- params: {
170
- packageUrl: file_url,
171
- attachFileUrls: []
172
- }
184
+ params: request_params
173
185
  )
174
186
 
187
+ if ENV['PINDO_DEBUG']
188
+ puts "[DEBUG] API 响应:"
189
+ puts "[DEBUG] #{result.inspect}"
190
+ end
191
+
175
192
  if result && (result['code'] == 0 || result['code'] == 200)
176
193
  puts "✅ 提交成功"
177
194
  print_upload_result(result)
178
195
  else
179
196
  error_msg = result['message'] || result['msg'] || '未知错误'
197
+ error_code = result['code']
198
+
199
+ puts "[ERROR] 提交失败详情:"
200
+ puts "[ERROR] 错误代码: #{error_code}"
201
+ puts "[ERROR] 错误消息: #{error_msg}"
202
+
203
+ if ENV['PINDO_DEBUG']
204
+ puts "[DEBUG] 完整响应内容:"
205
+ puts "[DEBUG] #{JSON.pretty_generate(result)}" rescue puts "[DEBUG] #{result.inspect}"
206
+ end
207
+
180
208
  raise Informative, "提交失败: #{error_msg}"
181
209
  end
182
210
  end
data/lib/pindo/version.rb CHANGED
@@ -6,7 +6,7 @@ require 'time'
6
6
 
7
7
  module Pindo
8
8
 
9
- VERSION = "5.16.3"
9
+ VERSION = "5.16.5"
10
10
 
11
11
  class VersionCheck
12
12
  RUBYGEMS_API = 'https://rubygems.org/api/v1/gems/pindo.json'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pindo
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.16.3
4
+ version: 5.16.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - wade
@@ -112,7 +112,7 @@ dependencies:
112
112
  version: '2.0'
113
113
  - - ">="
114
114
  - !ruby/object:Gem::Version
115
- version: 2.0.0
115
+ version: 2.0.3
116
116
  type: :runtime
117
117
  prerelease: false
118
118
  version_requirements: !ruby/object:Gem::Requirement
@@ -122,7 +122,7 @@ dependencies:
122
122
  version: '2.0'
123
123
  - - ">="
124
124
  - !ruby/object:Gem::Version
125
- version: 2.0.0
125
+ version: 2.0.3
126
126
  - !ruby/object:Gem::Dependency
127
127
  name: rqrcode
128
128
  requirement: !ruby/object:Gem::Requirement
@@ -355,6 +355,7 @@ files:
355
355
  - lib/pindo/command/utils/encrypt.rb
356
356
  - lib/pindo/command/utils/fabric.rb
357
357
  - lib/pindo/command/utils/icon.rb
358
+ - lib/pindo/command/utils/installskills.rb
358
359
  - lib/pindo/command/utils/renewcert.rb
359
360
  - lib/pindo/command/utils/renewproj.rb
360
361
  - lib/pindo/command/utils/repoinit.rb