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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 061bf75ae3563da24c18d0d4204fdecac9d03011e1493dd4e89b53d9b112d617
|
|
4
|
+
data.tar.gz: a51d17f8a46a767527a34f970657c7cf164511902c28f46e7567b6264de3079f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: efc7584e50c172c78c3e53f45ff97b335f18c60565d02ef8892273c29c253199909c54f590673ab232dfe688a086270d7200097293d7a6c1e0320efd682d2dfb
|
|
7
|
+
data.tar.gz: d0d46c6e9bc600c526e7c3ef2cb4fce1fafd47d39d8e806161d3843cbd40098fac4fecc33fb1f2141cec6d7163ea1ca1ec1642e10f214c7f3beef220bce54e5c
|
data/lib/pindo/base/funlog.rb
CHANGED
|
@@ -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
|
data/lib/pindo/command/utils.rb
CHANGED
|
@@ -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
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.
|
|
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.
|
|
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.
|
|
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
|