@lyra-ai/toolkit 0.2.6 → 0.2.7
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.
- package/QUICKSTART.md +1 -4
- package/README.md +1 -2
- package/bin/toolkit.mjs +7 -18
- package/package.json +1 -1
- package/src/config-cmd.mjs +1 -1
- package/src/install.mjs +8 -7
- package/src/skillhub.mjs +2 -319
- package/src/status.mjs +1 -1
- package/src/zentao.mjs +57 -2
package/QUICKSTART.md
CHANGED
|
@@ -134,9 +134,6 @@ skillhub list --json
|
|
|
134
134
|
# 诊断问题
|
|
135
135
|
skillhub doctor
|
|
136
136
|
|
|
137
|
-
# 更新技能包
|
|
138
|
-
skillhub update --scope user
|
|
139
|
-
|
|
140
137
|
# 移除
|
|
141
138
|
skillhub remove code-review --scope user
|
|
142
139
|
```
|
|
@@ -150,7 +147,7 @@ skillhub publish ./my-skill
|
|
|
150
147
|
## skillhub 工作流
|
|
151
148
|
|
|
152
149
|
```
|
|
153
|
-
login(认证) → search(发现) → install(安装) → list/doctor(管理)
|
|
150
|
+
login(认证) → search(发现) → install(安装) → list/doctor(管理)
|
|
154
151
|
```
|
|
155
152
|
|
|
156
153
|
- **`login`** 存储 registry token
|
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
安装后,你的 AI 编码数据自动进入组织分析平台,生成专属的多维度效能看板。
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
toolkit install --
|
|
16
|
+
toolkit install --registry http://your-platform:38000
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
- 会话结束后自动同步,无需手动操作
|
|
@@ -117,7 +117,6 @@ AI 技能包管理器:搜索、安装、发布、管理 AI coding agent 技能
|
|
|
117
117
|
- `skillhub remove <slug> [--scope user|project] [--agent <profile>] [--json]` → 移除技能包
|
|
118
118
|
- `skillhub doctor [--fix] [--json]` → 诊断技能包安装状态
|
|
119
119
|
- `skillhub publish <path> [--json]` → 发布技能包到 registry
|
|
120
|
-
- `skillhub update [--scope user|project] [--agent <profile>] [--json]` → 更新已安装技能包
|
|
121
120
|
|
|
122
121
|
### Agent profiles(`--agent`)
|
|
123
122
|
|
package/bin/toolkit.mjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* toolkit — 研发工具集 CLI 入口
|
|
4
4
|
*
|
|
5
5
|
* 用法:
|
|
6
|
-
* toolkit install
|
|
6
|
+
* toolkit install --registry <url> 安装插件(自动检测 AI Coding Agent)
|
|
7
7
|
* toolkit status 查看状态
|
|
8
8
|
* toolkit flush 手动上传
|
|
9
9
|
* toolkit uninstall [--purge] 卸载
|
|
@@ -23,8 +23,8 @@ const cmd = args[0];
|
|
|
23
23
|
const HELP = `toolkit — 研发工具集
|
|
24
24
|
|
|
25
25
|
命令:
|
|
26
|
-
install --
|
|
27
|
-
|
|
26
|
+
install --registry <url> 安装插件(自动检测本机 AI Coding Agent)
|
|
27
|
+
当前支持: Claude Code (~/.claude)
|
|
28
28
|
status 查看安装状态 + 待同步会话
|
|
29
29
|
flush 手动触发一次同步
|
|
30
30
|
config 配置管理
|
|
@@ -44,29 +44,18 @@ async function main() {
|
|
|
44
44
|
return;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
// toolkit install --
|
|
47
|
+
// toolkit install --registry <url>(自动检测 AI Coding Agent)
|
|
48
48
|
if (cmd === 'install') {
|
|
49
|
-
const agentIdx = args.indexOf('--agent');
|
|
50
|
-
const agent = agentIdx >= 0 ? args[agentIdx + 1] : null;
|
|
51
|
-
if (!agent) {
|
|
52
|
-
console.error('ERROR: 缺少 --agent <name>');
|
|
53
|
-
console.error(' 用法: toolkit install --agent claudecode --registry <url>');
|
|
54
|
-
console.error(' 支持: claudecode');
|
|
55
|
-
process.exit(2);
|
|
56
|
-
}
|
|
57
|
-
if (agent !== 'claudecode') {
|
|
58
|
-
console.error(`ERROR: 暂不支持 agent "${agent}"。目前支持: claudecode`);
|
|
59
|
-
process.exit(2);
|
|
60
|
-
}
|
|
61
49
|
const regIdx = args.indexOf('--registry');
|
|
62
50
|
let registry = regIdx >= 0 ? args[regIdx + 1] : null;
|
|
63
51
|
if (!registry) {
|
|
64
52
|
console.error('ERROR: 缺少 --registry <url>');
|
|
65
|
-
console.error(' 用法: toolkit install --
|
|
53
|
+
console.error(' 用法: toolkit install --registry <url>');
|
|
54
|
+
console.error(' (自动检测本机 AI Coding Agent,当前支持: Claude Code)');
|
|
66
55
|
process.exit(2);
|
|
67
56
|
}
|
|
68
57
|
const { install } = await import(pathToFileURL(path.join(srcDir, 'install.mjs')).href);
|
|
69
|
-
await install(registry
|
|
58
|
+
await install(registry);
|
|
70
59
|
return;
|
|
71
60
|
}
|
|
72
61
|
|
package/package.json
CHANGED
package/src/config-cmd.mjs
CHANGED
|
@@ -27,7 +27,7 @@ export function configCmd(args) {
|
|
|
27
27
|
if (!sub || sub === 'list' || sub === 'help' || sub === '--help') {
|
|
28
28
|
const config = load();
|
|
29
29
|
if (!config.registry && !config.uid) {
|
|
30
|
-
console.error('配置文件不存在。先运行: toolkit install
|
|
30
|
+
console.error('配置文件不存在。先运行: toolkit install --registry <url>');
|
|
31
31
|
process.exit(1);
|
|
32
32
|
}
|
|
33
33
|
const pf = config['project-filter'];
|
package/src/install.mjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* install.mjs — `toolkit install --
|
|
3
|
+
* install.mjs — `toolkit install --registry <url>`
|
|
4
4
|
*
|
|
5
|
-
*
|
|
5
|
+
* 自动检测本机 AI Coding Agent:目前识别 Claude Code(~/.claude),
|
|
6
|
+
* 命中即用其官方「Skills 目录 plugin」机制(@skills-dir)注册:
|
|
6
7
|
* ~/.claude/skills/toolkit/ ← 含 .claude-plugin/plugin.json + hooks/hooks.json
|
|
7
8
|
* + hook.mjs + flush.mjs + shared/
|
|
8
9
|
*
|
|
@@ -75,13 +76,13 @@ function cleanupLegacy() {
|
|
|
75
76
|
return cleaned;
|
|
76
77
|
}
|
|
77
78
|
|
|
78
|
-
export async function install(registry
|
|
79
|
-
|
|
80
|
-
//
|
|
81
|
-
// (后续 --agent qoder 时,检测 ~/.qoder)
|
|
79
|
+
export async function install(registry) {
|
|
80
|
+
// 1. 自动检测本机 AI Coding Agent:目前仅识别 Claude Code(~/.claude)。
|
|
81
|
+
// 后续可扩展其它 agent(如 ~/.qoder)。
|
|
82
82
|
const claudeDir = path.join(HOME, '.claude');
|
|
83
83
|
if (!fs.existsSync(claudeDir)) {
|
|
84
|
-
console.error('ERROR:
|
|
84
|
+
console.error('ERROR: 未检测到任何已支持的 AI Coding Agent。');
|
|
85
|
+
console.error(' 当前支持: Claude Code (需存在 ~/.claude 目录)');
|
|
85
86
|
process.exit(1);
|
|
86
87
|
}
|
|
87
88
|
|
package/src/skillhub.mjs
CHANGED
|
@@ -3339,21 +3339,11 @@ export function unzipSync(data, opts) {
|
|
|
3339
3339
|
|
|
3340
3340
|
|
|
3341
3341
|
// ==================================================================
|
|
3342
|
-
// === Tools: self-implemented replacements (
|
|
3342
|
+
// === Tools: self-implemented replacements (readline prompts) ===
|
|
3343
3343
|
// ==================================================================
|
|
3344
3344
|
|
|
3345
3345
|
import readline from 'node:readline';
|
|
3346
3346
|
|
|
3347
|
-
function semverGt(a, b) {
|
|
3348
|
-
const pa = String(a).replace(/^v/, '').split('.').map(Number);
|
|
3349
|
-
const pb = String(b).replace(/^v/, '').split('.').map(Number);
|
|
3350
|
-
for (let i = 0; i < 3; i++) {
|
|
3351
|
-
if ((pa[i] ?? 0) > (pb[i] ?? 0)) return true;
|
|
3352
|
-
if ((pa[i] ?? 0) < (pb[i] ?? 0)) return false;
|
|
3353
|
-
}
|
|
3354
|
-
return false;
|
|
3355
|
-
}
|
|
3356
|
-
|
|
3357
3347
|
async function promptSelect(message, choices) {
|
|
3358
3348
|
const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
|
|
3359
3349
|
process.stderr.write(`${message}\n`);
|
|
@@ -3395,7 +3385,6 @@ async function promptMultiselect(message, choices) {
|
|
|
3395
3385
|
// === Version Info ===
|
|
3396
3386
|
// ==================================================================
|
|
3397
3387
|
|
|
3398
|
-
const PKG_NAME = "@astron-team/skillhub";
|
|
3399
3388
|
const PKG_VERSION = "0.1.8";
|
|
3400
3389
|
|
|
3401
3390
|
// ==================================================================
|
|
@@ -3417,7 +3406,6 @@ class CliError extends Error {
|
|
|
3417
3406
|
|
|
3418
3407
|
const DEFAULT_REGISTRY = '';
|
|
3419
3408
|
const CLI_VERSION = PKG_VERSION;
|
|
3420
|
-
const CLI_PACKAGE_NAME = PKG_NAME;
|
|
3421
3409
|
const EXIT = {
|
|
3422
3410
|
generic: 1,
|
|
3423
3411
|
auth: 2,
|
|
@@ -3614,79 +3602,6 @@ async function readBoundedResponseBody(response, maxBytes = MAX_PACKAGE_BYTES) {
|
|
|
3614
3602
|
return result.buffer;
|
|
3615
3603
|
}
|
|
3616
3604
|
|
|
3617
|
-
// ==================================================================
|
|
3618
|
-
// === Source: platform/updater ===
|
|
3619
|
-
// ==================================================================
|
|
3620
|
-
|
|
3621
|
-
import { spawn } from 'node:child_process';
|
|
3622
|
-
|
|
3623
|
-
async function runUpdateCommand(command) {
|
|
3624
|
-
try {
|
|
3625
|
-
const [program, ...args] = command;
|
|
3626
|
-
if (!program) {
|
|
3627
|
-
return { success: false, output: 'empty update command' };
|
|
3628
|
-
}
|
|
3629
|
-
|
|
3630
|
-
const spawnOptions = {
|
|
3631
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
3632
|
-
...(process.platform === 'win32' && { shell: true })
|
|
3633
|
-
};
|
|
3634
|
-
|
|
3635
|
-
return await new Promise((resolve) => {
|
|
3636
|
-
const proc = spawn(program, args, spawnOptions);
|
|
3637
|
-
const chunks = [];
|
|
3638
|
-
|
|
3639
|
-
proc.stdout?.on('data', (chunk) => chunks.push(Buffer.from(chunk)));
|
|
3640
|
-
proc.stderr?.on('data', (chunk) => chunks.push(Buffer.from(chunk)));
|
|
3641
|
-
proc.on('error', (error) => resolve({ success: false, output: error.message }));
|
|
3642
|
-
proc.on('close', (code) => resolve({
|
|
3643
|
-
success: code === 0,
|
|
3644
|
-
output: Buffer.concat(chunks).toString('utf-8')
|
|
3645
|
-
}));
|
|
3646
|
-
});
|
|
3647
|
-
} catch (error) {
|
|
3648
|
-
return {
|
|
3649
|
-
success: false,
|
|
3650
|
-
output: error instanceof Error ? error.message : String(error)
|
|
3651
|
-
};
|
|
3652
|
-
}
|
|
3653
|
-
}
|
|
3654
|
-
|
|
3655
|
-
// ==================================================================
|
|
3656
|
-
// === Source: platform/package-manager ===
|
|
3657
|
-
// ==================================================================
|
|
3658
|
-
|
|
3659
|
-
function detectInstallMode(argv = process.argv, env = process.env) {
|
|
3660
|
-
const execPath = argv[1] ?? '';
|
|
3661
|
-
|
|
3662
|
-
if (execPath.includes('_npx/') || execPath.includes('_npx\\')) {
|
|
3663
|
-
return 'npx';
|
|
3664
|
-
}
|
|
3665
|
-
|
|
3666
|
-
const npmExecPath = env.npm_execpath ?? '';
|
|
3667
|
-
if (npmExecPath.includes('npx')) {
|
|
3668
|
-
return 'npx';
|
|
3669
|
-
}
|
|
3670
|
-
|
|
3671
|
-
const bunInstall = env.BUN_INSTALL ?? '';
|
|
3672
|
-
if (bunInstall && execPath.startsWith(bunInstall)) {
|
|
3673
|
-
return 'bun-global';
|
|
3674
|
-
}
|
|
3675
|
-
if (execPath.includes('/.bun/') || execPath.includes('\\.bun\\')) {
|
|
3676
|
-
return 'bun-global';
|
|
3677
|
-
}
|
|
3678
|
-
|
|
3679
|
-
const npmGlobalPrefix = env.npm_config_prefix ?? '';
|
|
3680
|
-
if (npmGlobalPrefix && execPath.startsWith(npmGlobalPrefix)) {
|
|
3681
|
-
return 'npm-global';
|
|
3682
|
-
}
|
|
3683
|
-
if (execPath.includes('/lib/node_modules/') || execPath.includes('/node_modules/.bin/')) {
|
|
3684
|
-
return 'npm-global';
|
|
3685
|
-
}
|
|
3686
|
-
|
|
3687
|
-
return 'unknown';
|
|
3688
|
-
}
|
|
3689
|
-
|
|
3690
3605
|
// ==================================================================
|
|
3691
3606
|
// === Source: platform/archive ===
|
|
3692
3607
|
// ==================================================================
|
|
@@ -4192,97 +4107,6 @@ class SkillHubClient {
|
|
|
4192
4107
|
}
|
|
4193
4108
|
}
|
|
4194
4109
|
|
|
4195
|
-
// ==================================================================
|
|
4196
|
-
// === Source: clients/npm-registry-client ===
|
|
4197
|
-
// ==================================================================
|
|
4198
|
-
|
|
4199
|
-
const DEFAULT_NPM_REGISTRY = 'https://registry.npmjs.org';
|
|
4200
|
-
|
|
4201
|
-
function readEnv(env, name) {
|
|
4202
|
-
const exactValue = env[name]?.trim();
|
|
4203
|
-
if (exactValue) {
|
|
4204
|
-
return exactValue;
|
|
4205
|
-
}
|
|
4206
|
-
|
|
4207
|
-
const lowerName = name.toLowerCase();
|
|
4208
|
-
for (const [key, value] of Object.entries(env)) {
|
|
4209
|
-
const normalizedValue = value?.trim();
|
|
4210
|
-
if (key.toLowerCase() === lowerName && normalizedValue) {
|
|
4211
|
-
return normalizedValue;
|
|
4212
|
-
}
|
|
4213
|
-
}
|
|
4214
|
-
return undefined;
|
|
4215
|
-
}
|
|
4216
|
-
|
|
4217
|
-
function resolveNpmRegistry(env) {
|
|
4218
|
-
return readEnv(env, 'SKILLHUB_NPM_REGISTRY')
|
|
4219
|
-
?? readEnv(env, 'npm_config_registry')
|
|
4220
|
-
?? readEnv(env, 'NPM_CONFIG_REGISTRY')
|
|
4221
|
-
?? DEFAULT_NPM_REGISTRY;
|
|
4222
|
-
}
|
|
4223
|
-
|
|
4224
|
-
function buildLatestUrl(registry, packageName) {
|
|
4225
|
-
try {
|
|
4226
|
-
const base = registry.endsWith('/') ? registry : `${registry}/`;
|
|
4227
|
-
return new URL(`${encodeURIComponent(packageName)}/latest`, base).toString();
|
|
4228
|
-
} catch {
|
|
4229
|
-
throw new CliError('invalid npm registry URL', EXIT.usage, {
|
|
4230
|
-
registry,
|
|
4231
|
-
next: 'check npm registry configuration and retry'
|
|
4232
|
-
});
|
|
4233
|
-
}
|
|
4234
|
-
}
|
|
4235
|
-
|
|
4236
|
-
class NpmRegistryClient {
|
|
4237
|
-
constructor(fetchImpl = fetch, timeoutMs = 10000, env = process.env) {
|
|
4238
|
-
this.fetchImpl = fetchImpl;
|
|
4239
|
-
this.timeoutMs = timeoutMs;
|
|
4240
|
-
this.env = env;
|
|
4241
|
-
}
|
|
4242
|
-
|
|
4243
|
-
async latestVersion(packageName = CLI_PACKAGE_NAME) {
|
|
4244
|
-
const registry = resolveNpmRegistry(this.env);
|
|
4245
|
-
const url = buildLatestUrl(registry, packageName);
|
|
4246
|
-
const controller = new AbortController();
|
|
4247
|
-
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
4248
|
-
try {
|
|
4249
|
-
let response;
|
|
4250
|
-
try {
|
|
4251
|
-
response = await this.fetchImpl(url, {
|
|
4252
|
-
signal: controller.signal
|
|
4253
|
-
});
|
|
4254
|
-
} catch (error) {
|
|
4255
|
-
const isTimeout = error instanceof Error && error.name === 'AbortError';
|
|
4256
|
-
throw new CliError('npm registry unreachable', EXIT.network, {
|
|
4257
|
-
registry,
|
|
4258
|
-
cause: error instanceof Error ? error.message : String(error),
|
|
4259
|
-
next: isTimeout
|
|
4260
|
-
? 'check npm registry connectivity or proxy settings and retry'
|
|
4261
|
-
: 'check npm registry/proxy configuration and retry'
|
|
4262
|
-
});
|
|
4263
|
-
}
|
|
4264
|
-
if (!response.ok) {
|
|
4265
|
-
throw new CliError(`npm registry returned ${response.status}`, EXIT.network, { registry });
|
|
4266
|
-
}
|
|
4267
|
-
let body;
|
|
4268
|
-
try {
|
|
4269
|
-
body = await response.json();
|
|
4270
|
-
} catch (error) {
|
|
4271
|
-
throw new CliError('npm registry response invalid', EXIT.network, {
|
|
4272
|
-
registry,
|
|
4273
|
-
cause: error instanceof Error ? error.message : String(error)
|
|
4274
|
-
});
|
|
4275
|
-
}
|
|
4276
|
-
if (typeof body !== 'object' || body === null || !('version' in body) || typeof body.version !== 'string') {
|
|
4277
|
-
throw new CliError('npm registry response missing version', EXIT.network, { registry });
|
|
4278
|
-
}
|
|
4279
|
-
return body.version;
|
|
4280
|
-
} finally {
|
|
4281
|
-
clearTimeout(timer);
|
|
4282
|
-
}
|
|
4283
|
-
}
|
|
4284
|
-
}
|
|
4285
|
-
|
|
4286
4110
|
// ==================================================================
|
|
4287
4111
|
// === Source: services/registry-service ===
|
|
4288
4112
|
// ==================================================================
|
|
@@ -4340,7 +4164,7 @@ async function deleteToolkitToken() {
|
|
|
4340
4164
|
function requireRegistry(registry) {
|
|
4341
4165
|
if (!registry) {
|
|
4342
4166
|
throw new CliError(
|
|
4343
|
-
'未配置 registry。运行: toolkit install
|
|
4167
|
+
'未配置 registry。运行: toolkit install --registry <url>',
|
|
4344
4168
|
EXIT.config
|
|
4345
4169
|
);
|
|
4346
4170
|
}
|
|
@@ -4529,84 +4353,6 @@ async function removeLocalSkill(options) {
|
|
|
4529
4353
|
return { removed };
|
|
4530
4354
|
}
|
|
4531
4355
|
|
|
4532
|
-
// ==================================================================
|
|
4533
|
-
// === Source: services/update-service ===
|
|
4534
|
-
// ==================================================================
|
|
4535
|
-
|
|
4536
|
-
class UpdateService {
|
|
4537
|
-
constructor(deps) {
|
|
4538
|
-
this.deps = deps;
|
|
4539
|
-
}
|
|
4540
|
-
|
|
4541
|
-
async update(options) {
|
|
4542
|
-
const current = this.deps.currentVersion;
|
|
4543
|
-
const latest = await this.deps.latestVersion();
|
|
4544
|
-
|
|
4545
|
-
if (!semverGt(latest, current)) {
|
|
4546
|
-
return {
|
|
4547
|
-
updated: false,
|
|
4548
|
-
available: false,
|
|
4549
|
-
currentVersion: current,
|
|
4550
|
-
latestVersion: latest
|
|
4551
|
-
};
|
|
4552
|
-
}
|
|
4553
|
-
|
|
4554
|
-
if (options.checkOnly) {
|
|
4555
|
-
return {
|
|
4556
|
-
updated: false,
|
|
4557
|
-
available: true,
|
|
4558
|
-
currentVersion: current,
|
|
4559
|
-
latestVersion: latest
|
|
4560
|
-
};
|
|
4561
|
-
}
|
|
4562
|
-
|
|
4563
|
-
const mode = this.deps.detectInstallMode();
|
|
4564
|
-
|
|
4565
|
-
switch (mode) {
|
|
4566
|
-
case 'npx':
|
|
4567
|
-
return {
|
|
4568
|
-
updated: false,
|
|
4569
|
-
available: true,
|
|
4570
|
-
currentVersion: current,
|
|
4571
|
-
latestVersion: latest,
|
|
4572
|
-
next: `Run: npx ${CLI_PACKAGE_NAME}@latest <command> or install globally: npm install -g ${CLI_PACKAGE_NAME}`
|
|
4573
|
-
};
|
|
4574
|
-
|
|
4575
|
-
case 'npm-global': {
|
|
4576
|
-
const result = await this.deps.run(['npm', 'install', '-g', `${CLI_PACKAGE_NAME}@latest`]);
|
|
4577
|
-
return {
|
|
4578
|
-
updated: result.success,
|
|
4579
|
-
available: true,
|
|
4580
|
-
currentVersion: current,
|
|
4581
|
-
latestVersion: latest,
|
|
4582
|
-
error: result.success ? undefined : result.output
|
|
4583
|
-
};
|
|
4584
|
-
}
|
|
4585
|
-
|
|
4586
|
-
case 'bun-global': {
|
|
4587
|
-
const result = await this.deps.run(['bun', 'add', '-g', `${CLI_PACKAGE_NAME}@latest`]);
|
|
4588
|
-
return {
|
|
4589
|
-
updated: result.success,
|
|
4590
|
-
available: true,
|
|
4591
|
-
currentVersion: current,
|
|
4592
|
-
latestVersion: latest,
|
|
4593
|
-
error: result.success ? undefined : result.output
|
|
4594
|
-
};
|
|
4595
|
-
}
|
|
4596
|
-
|
|
4597
|
-
case 'unknown':
|
|
4598
|
-
default:
|
|
4599
|
-
return {
|
|
4600
|
-
updated: false,
|
|
4601
|
-
available: true,
|
|
4602
|
-
currentVersion: current,
|
|
4603
|
-
latestVersion: latest,
|
|
4604
|
-
next: `Update manually: npm install -g ${CLI_PACKAGE_NAME}@latest or bun add -g ${CLI_PACKAGE_NAME}@latest`
|
|
4605
|
-
};
|
|
4606
|
-
}
|
|
4607
|
-
}
|
|
4608
|
-
}
|
|
4609
|
-
|
|
4610
4356
|
// ==================================================================
|
|
4611
4357
|
// === Source: services/doctor-service ===
|
|
4612
4358
|
// ==================================================================
|
|
@@ -5044,11 +4790,6 @@ const commands = {
|
|
|
5044
4790
|
summary: 'Publish a local skill package',
|
|
5045
4791
|
usage: 'skillhub publish <path> [--namespace <slug>] [--visibility <public|namespace-only|private>] [--registry <url>] [--json]',
|
|
5046
4792
|
examples: ['skillhub publish ./my-skill', 'skillhub publish ./my-skill --namespace myspace']
|
|
5047
|
-
},
|
|
5048
|
-
update: {
|
|
5049
|
-
summary: 'Check or update CLI itself',
|
|
5050
|
-
usage: 'skillhub update [--check] [--json]',
|
|
5051
|
-
examples: ['skillhub update --check', 'skillhub update']
|
|
5052
4793
|
}
|
|
5053
4794
|
};
|
|
5054
4795
|
|
|
@@ -5483,58 +5224,6 @@ function toServerVisibility(visibility) {
|
|
|
5483
5224
|
return visibility.toUpperCase().replace(/-/g, '_');
|
|
5484
5225
|
}
|
|
5485
5226
|
|
|
5486
|
-
// ==================================================================
|
|
5487
|
-
// === Source: commands/update ===
|
|
5488
|
-
// ==================================================================
|
|
5489
|
-
|
|
5490
|
-
async function updateCommand(options) {
|
|
5491
|
-
const json = Boolean(options.json);
|
|
5492
|
-
const checkOnly = Boolean(options.check);
|
|
5493
|
-
|
|
5494
|
-
const service = new UpdateService({
|
|
5495
|
-
currentVersion: CLI_VERSION,
|
|
5496
|
-
latestVersion: () => new NpmRegistryClient().latestVersion(),
|
|
5497
|
-
detectInstallMode: () => detectInstallMode(),
|
|
5498
|
-
run: runUpdateCommand
|
|
5499
|
-
});
|
|
5500
|
-
|
|
5501
|
-
const result = await service.update({ checkOnly });
|
|
5502
|
-
|
|
5503
|
-
if (!result.available) {
|
|
5504
|
-
return printResult(
|
|
5505
|
-
json
|
|
5506
|
-
? { ok: true, upToDate: true, version: result.currentVersion }
|
|
5507
|
-
: `Already up to date (${result.currentVersion})`,
|
|
5508
|
-
json
|
|
5509
|
-
);
|
|
5510
|
-
}
|
|
5511
|
-
|
|
5512
|
-
if (result.updated) {
|
|
5513
|
-
return printResult(
|
|
5514
|
-
json
|
|
5515
|
-
? { ok: true, updated: true, from: result.currentVersion, to: result.latestVersion }
|
|
5516
|
-
: `Updated skillhub ${result.currentVersion} -> ${result.latestVersion}`,
|
|
5517
|
-
json
|
|
5518
|
-
);
|
|
5519
|
-
}
|
|
5520
|
-
|
|
5521
|
-
if (result.error) {
|
|
5522
|
-
throw new CliError(result.error, EXIT.generic, { from: result.currentVersion, to: result.latestVersion });
|
|
5523
|
-
}
|
|
5524
|
-
|
|
5525
|
-
const lines = [`Update available: ${result.currentVersion} -> ${result.latestVersion}`];
|
|
5526
|
-
if (result.next) {
|
|
5527
|
-
lines.push(result.next);
|
|
5528
|
-
}
|
|
5529
|
-
|
|
5530
|
-
return printResult(
|
|
5531
|
-
json
|
|
5532
|
-
? { ok: true, available: true, from: result.currentVersion, to: result.latestVersion, next: result.next }
|
|
5533
|
-
: lines.join('\n'),
|
|
5534
|
-
json
|
|
5535
|
-
);
|
|
5536
|
-
}
|
|
5537
|
-
|
|
5538
5227
|
// ==================================================================
|
|
5539
5228
|
// === Source: index (CLI entry point) ===
|
|
5540
5229
|
// ==================================================================
|
|
@@ -5685,10 +5374,6 @@ cli.command('help [command]', 'Show help')
|
|
|
5685
5374
|
cli.command('version', 'Show CLI version')
|
|
5686
5375
|
.option('--json', 'Output JSON');
|
|
5687
5376
|
|
|
5688
|
-
cli.command('update', 'Update CLI to latest version')
|
|
5689
|
-
.option('--check', 'Check for updates without installing')
|
|
5690
|
-
.option('--json', 'Output JSON');
|
|
5691
|
-
|
|
5692
5377
|
cli.command('login', 'Save registry and token')
|
|
5693
5378
|
.option('--registry <url>', 'Registry URL')
|
|
5694
5379
|
.option('--token <token>', 'API token')
|
|
@@ -5756,8 +5441,6 @@ async function dispatchCommand(commandName, args, options) {
|
|
|
5756
5441
|
return helpCommand([...args, ...(options.json ? ['--json'] : [])]);
|
|
5757
5442
|
case 'version':
|
|
5758
5443
|
return versionCommand(options.json ? ['--json'] : []);
|
|
5759
|
-
case 'update':
|
|
5760
|
-
return updateCommand(options);
|
|
5761
5444
|
case 'login':
|
|
5762
5445
|
return loginCommand(options);
|
|
5763
5446
|
case 'logout':
|
package/src/status.mjs
CHANGED
|
@@ -41,7 +41,7 @@ export function collectStatus() {
|
|
|
41
41
|
lines.push('════════════════════════════════════════');
|
|
42
42
|
|
|
43
43
|
if (!pluginExists && !configExists) {
|
|
44
|
-
lines.push(' ❌ 未安装。运行: toolkit install
|
|
44
|
+
lines.push(' ❌ 未安装。运行: toolkit install --registry <url>');
|
|
45
45
|
return lines.join('\n');
|
|
46
46
|
}
|
|
47
47
|
|
package/src/zentao.mjs
CHANGED
|
@@ -327,6 +327,48 @@ export function shapeBugListItem(b) {
|
|
|
327
327
|
};
|
|
328
328
|
}
|
|
329
329
|
|
|
330
|
+
// 去除 HTML 标签 + 折叠空白:action.comment/desc 可能含 <p>/<strong>/<br> 等
|
|
331
|
+
function stripHtml(s) {
|
|
332
|
+
if (!s) return '';
|
|
333
|
+
return String(s)
|
|
334
|
+
.replace(/<br\s*\/?\s*>/gi, '\n')
|
|
335
|
+
.replace(/<\/p>\s*<p[^>]*>/gi, '\n')
|
|
336
|
+
.replace(/<[^>]+>/g, '')
|
|
337
|
+
.replace(/ /g, ' ')
|
|
338
|
+
.replace(/</g, '<')
|
|
339
|
+
.replace(/>/g, '>')
|
|
340
|
+
.replace(/&/g, '&')
|
|
341
|
+
.replace(/[ \t]+\n/g, '\n')
|
|
342
|
+
.replace(/\n{3,}/g, '\n\n')
|
|
343
|
+
.trim();
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// 历史动作/评论轨迹:原始 actions[] 清洗为精简结构
|
|
347
|
+
// { actor, action, date, comment, extra, changes: [{ field, fieldName, old, new }] }
|
|
348
|
+
// comment/desc 去标签;history 取字段变更明细;空 comment / 无变更的动作仍保留(动作本身有意义)
|
|
349
|
+
export function shapeActions(actions) {
|
|
350
|
+
if (!Array.isArray(actions)) return [];
|
|
351
|
+
return actions
|
|
352
|
+
.filter((a) => a && typeof a === 'object')
|
|
353
|
+
.map((a) => ({
|
|
354
|
+
actor: a.actor ?? '',
|
|
355
|
+
action: a.action ?? '',
|
|
356
|
+
date: a.date ?? '',
|
|
357
|
+
comment: stripHtml(a.comment),
|
|
358
|
+
extra: a.extra ? stripHtml(String(a.extra)) : '',
|
|
359
|
+
changes: Array.isArray(a.history)
|
|
360
|
+
? a.history
|
|
361
|
+
.filter((h) => h && typeof h === 'object')
|
|
362
|
+
.map((h) => ({
|
|
363
|
+
field: h.field ?? '',
|
|
364
|
+
fieldName: h.fieldName ?? h.field ?? '',
|
|
365
|
+
old: h.old ?? '',
|
|
366
|
+
new: h.new ?? '',
|
|
367
|
+
}))
|
|
368
|
+
: [],
|
|
369
|
+
}));
|
|
370
|
+
}
|
|
371
|
+
|
|
330
372
|
export function shapeBugDetail(b) {
|
|
331
373
|
return {
|
|
332
374
|
...shapeBugListItem(b),
|
|
@@ -336,6 +378,7 @@ export function shapeBugDetail(b) {
|
|
|
336
378
|
resolvedDate: b.resolvedDate ?? '', resolvedBuild: b.resolvedBuild ?? '',
|
|
337
379
|
closedBy: userToAccount(b.closedBy), closedDate: b.closedDate ?? '',
|
|
338
380
|
lastEditedBy: userToAccount(b.lastEditedBy), lastEditedDate: b.lastEditedDate ?? '',
|
|
381
|
+
actions: shapeActions(b.actions),
|
|
339
382
|
};
|
|
340
383
|
}
|
|
341
384
|
|
|
@@ -377,14 +420,26 @@ export function bugListToMarkdown({ total, count, bugs }) {
|
|
|
377
420
|
|
|
378
421
|
export function bugDetailToMarkdown(b) {
|
|
379
422
|
const f = (k) => b[k] === '' || b[k] == null ? '-' : b[k];
|
|
380
|
-
|
|
423
|
+
const lines = [
|
|
381
424
|
`# Bug #${b.id}: ${b.title}`, '',
|
|
382
425
|
`- **Severity**: ${b.severity} | **Priority**: ${b.priority} | **Status**: ${b.status}`,
|
|
383
426
|
`- **Project**: ${b.projectId} | **Product**: ${b.productId}`,
|
|
384
427
|
`- **OpenedBy**: ${b.openedBy} ${b.openedDate} | **AssignedTo**: ${f('assignedTo')}`,
|
|
385
428
|
`- **Resolution**: ${f('resolution')} by ${f('resolvedBy')} ${f('resolvedDate')}`,
|
|
386
429
|
'', '## Steps', '', b.steps || '(empty)',
|
|
387
|
-
]
|
|
430
|
+
];
|
|
431
|
+
if (Array.isArray(b.actions) && b.actions.length) {
|
|
432
|
+
lines.push('', '## History', '');
|
|
433
|
+
for (const a of b.actions) {
|
|
434
|
+
const extra = a.extra ? ` → **${a.extra}**` : '';
|
|
435
|
+
lines.push(`- **${a.actor || '?'}** \`${a.action || '?'}\` _${a.date || '?'}_${extra}`);
|
|
436
|
+
if (a.comment) lines.push(` > ${a.comment.replace(/\n/g, '\n > ')}`);
|
|
437
|
+
for (const c of a.changes) {
|
|
438
|
+
lines.push(` - ${c.fieldName || c.field}: \`${c.old || '∅'}\` → \`${c.new || '∅'}\``);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
return lines.join('\n');
|
|
388
443
|
}
|
|
389
444
|
|
|
390
445
|
// HTTP 状态码 -> 统一错误 kind/message
|