reskill 1.5.0 → 1.7.0

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.
@@ -1 +1 @@
1
- {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/login.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsFpC,eAAO,MAAM,YAAY,SAOH,CAAC;AAEvB,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/login.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA0FpC,eAAO,MAAM,YAAY,SAOH,CAAC;AAEvB,eAAe,YAAY,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"whoami.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/whoami.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmEpC,eAAO,MAAM,aAAa,SAMH,CAAC;AAExB,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"whoami.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/whoami.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoEpC,eAAO,MAAM,aAAa,SAMH,CAAC;AAExB,eAAe,aAAa,CAAC"}
package/dist/cli/index.js CHANGED
@@ -437,12 +437,39 @@ var external_node_fs_ = __webpack_require__("node:fs");
437
437
  * Hardcoded registry to scope mapping
438
438
  * TODO: Replace with dynamic fetching from /api/registry/info
439
439
  */ const REGISTRY_SCOPE_MAP = {
440
+ // rush-app (private registry, new)
441
+ 'https://rush-test.zhenguanyu.com': '@kanyun',
442
+ 'https://rush.zhenguanyu.com': '@kanyun',
443
+ // reskill-app (private registry, legacy)
440
444
  'https://reskill-test.zhenguanyu.com': '@kanyun',
441
- 'https://reskill-test.zhenguanyu.com/': '@kanyun',
442
445
  // Local development
443
- 'http://localhost:3000': '@kanyun',
444
- 'http://localhost:3000/': '@kanyun'
446
+ 'http://localhost:3000': '@kanyun'
445
447
  };
448
+ /**
449
+ * Registry API prefix mapping
450
+ *
451
+ * rush-app hosts reskill APIs under /api/reskill/ prefix.
452
+ * Default for unlisted registries: '/api'
453
+ */ const REGISTRY_API_PREFIX = {
454
+ 'https://rush-test.zhenguanyu.com': '/api/reskill',
455
+ 'https://rush.zhenguanyu.com': '/api/reskill',
456
+ 'http://localhost:3000': '/api/reskill'
457
+ };
458
+ /**
459
+ * Get the API path prefix for a given registry URL
460
+ *
461
+ * @param registryUrl - Registry URL
462
+ * @returns API prefix string (e.g., '/api' or '/api/reskill')
463
+ *
464
+ * @example
465
+ * getApiPrefix('https://rush-test.zhenguanyu.com') // '/api/reskill'
466
+ * getApiPrefix('https://reskill.info') // '/api'
467
+ * getApiPrefix('https://unknown.com') // '/api'
468
+ */ function getApiPrefix(registryUrl) {
469
+ if (!registryUrl) return '/api';
470
+ const normalized = registryUrl.endsWith('/') ? registryUrl.slice(0, -1) : registryUrl;
471
+ return REGISTRY_API_PREFIX[normalized] || '/api';
472
+ }
446
473
  /**
447
474
  * Get the scope for a given registry URL
448
475
  *
@@ -450,7 +477,7 @@ var external_node_fs_ = __webpack_require__("node:fs");
450
477
  * @returns Scope string (e.g., "@kanyun") or null if not found
451
478
  *
452
479
  * @example
453
- * getScopeForRegistry('https://reskill-test.zhenguanyu.com') // '@kanyun'
480
+ * getScopeForRegistry('https://rush-test.zhenguanyu.com') // '@kanyun'
454
481
  * getScopeForRegistry('https://unknown.com') // null
455
482
  */ function getScopeForRegistry(registry) {
456
483
  if (!registry) return null;
@@ -468,8 +495,8 @@ var external_node_fs_ = __webpack_require__("node:fs");
468
495
  * @returns Registry URL (with trailing slash) or null if not found
469
496
  *
470
497
  * @example
471
- * getRegistryForScope('@kanyun') // 'https://reskill-test.zhenguanyu.com/'
472
- * getRegistryForScope('kanyun') // 'https://reskill-test.zhenguanyu.com/'
498
+ * getRegistryForScope('@kanyun') // 'https://rush-test.zhenguanyu.com/'
499
+ * getRegistryForScope('kanyun') // 'https://rush-test.zhenguanyu.com/'
473
500
  * getRegistryForScope('@unknown') // null
474
501
  * getRegistryForScope('@mycompany', { '@mycompany': 'https://my.registry.com/' }) // 'https://my.registry.com/'
475
502
  */ function getRegistryForScope(scope, customRegistries) {
@@ -499,8 +526,8 @@ var external_node_fs_ = __webpack_require__("node:fs");
499
526
  * @throws Error if scope is provided but not found in the registry map
500
527
  *
501
528
  * @example
502
- * getRegistryUrl('@kanyun') // 'https://reskill-test.zhenguanyu.com/'
503
- * getRegistryUrl('kanyun') // 'https://reskill-test.zhenguanyu.com/'
529
+ * getRegistryUrl('@kanyun') // 'https://rush-test.zhenguanyu.com/'
530
+ * getRegistryUrl('kanyun') // 'https://rush-test.zhenguanyu.com/'
504
531
  * getRegistryUrl(null) // 'https://reskill.info/'
505
532
  * getRegistryUrl('') // 'https://reskill.info/'
506
533
  * getRegistryUrl('@unknown') // throws Error
@@ -2684,6 +2711,15 @@ class RegistryClient {
2684
2711
  this.config = config;
2685
2712
  }
2686
2713
  /**
2714
+ * Get API base URL (registry + apiPrefix)
2715
+ *
2716
+ * @returns Base URL for API calls, e.g., 'https://example.com/api' or 'https://rush.com/api/reskill'
2717
+ */ getApiBase() {
2718
+ const prefix = this.config.apiPrefix || '/api';
2719
+ const registry = this.config.registry.endsWith('/') ? this.config.registry.slice(0, -1) : this.config.registry;
2720
+ return `${registry}${prefix}`;
2721
+ }
2722
+ /**
2687
2723
  * Get authorization headers
2688
2724
  */ getAuthHeaders() {
2689
2725
  const headers = {
@@ -2696,7 +2732,7 @@ class RegistryClient {
2696
2732
  /**
2697
2733
  * Get current user info (whoami)
2698
2734
  */ async whoami() {
2699
- const url = `${this.config.registry}/api/auth/me`;
2735
+ const url = `${this.getApiBase()}/auth/me`;
2700
2736
  const response = await fetch(url, {
2701
2737
  method: 'GET',
2702
2738
  headers: this.getAuthHeaders()
@@ -2706,6 +2742,24 @@ class RegistryClient {
2706
2742
  return data;
2707
2743
  }
2708
2744
  /**
2745
+ * CLI login - verify token and get user info
2746
+ *
2747
+ * Calls POST /api/auth/login-cli to validate the token and retrieve user information.
2748
+ * This is the preferred method for CLI authentication.
2749
+ *
2750
+ * @returns User information if authentication succeeds
2751
+ * @throws RegistryError if authentication fails
2752
+ */ async loginCli() {
2753
+ const url = `${this.getApiBase()}/auth/login-cli`;
2754
+ const response = await fetch(url, {
2755
+ method: 'POST',
2756
+ headers: this.getAuthHeaders()
2757
+ });
2758
+ const data = await response.json();
2759
+ if (!response.ok) throw new RegistryError(data.error || `Login failed: ${response.status}`, response.status, data);
2760
+ return data;
2761
+ }
2762
+ /**
2709
2763
  * Create tarball from skill files
2710
2764
  *
2711
2765
  * @param skillPath - Path to the skill directory
@@ -2752,7 +2806,7 @@ class RegistryClient {
2752
2806
  * @returns Skill 基本信息
2753
2807
  * @throws RegistryError 如果 skill 不存在或请求失败
2754
2808
  */ async getSkillInfo(skillName) {
2755
- const url = `${this.config.registry}/api/skills/${encodeURIComponent(skillName)}`;
2809
+ const url = `${this.getApiBase()}/skills/${encodeURIComponent(skillName)}`;
2756
2810
  const response = await fetch(url, {
2757
2811
  method: 'GET',
2758
2812
  headers: this.getAuthHeaders()
@@ -2786,7 +2840,7 @@ class RegistryClient {
2786
2840
  // 如果是 semver 版本号,直接返回
2787
2841
  if (/^\d+\.\d+\.\d+/.test(version)) return version;
2788
2842
  // 否则视为 tag,需要查询 dist-tags
2789
- const url = `${this.config.registry}/api/skills/${encodeURIComponent(skillName)}`;
2843
+ const url = `${this.getApiBase()}/skills/${encodeURIComponent(skillName)}`;
2790
2844
  const response = await fetch(url, {
2791
2845
  method: 'GET',
2792
2846
  headers: this.getAuthHeaders()
@@ -2821,15 +2875,34 @@ class RegistryClient {
2821
2875
  * @example
2822
2876
  * const { tarball, integrity } = await client.downloadSkill('@kanyun/test-skill', '1.0.0');
2823
2877
  */ async downloadSkill(skillName, version) {
2824
- const url = `${this.config.registry}/api/skills/${encodeURIComponent(skillName)}/versions/${version}/download`;
2878
+ const url = `${this.getApiBase()}/skills/${encodeURIComponent(skillName)}/versions/${version}/download`;
2879
+ // Use redirect: 'manual' to capture x-integrity header from 302 responses.
2880
+ // The registry returns a 302 redirect to OSS with the integrity header,
2881
+ // which would be lost if fetch auto-follows the redirect.
2825
2882
  const response = await fetch(url, {
2826
2883
  method: 'GET',
2827
- headers: this.getAuthHeaders()
2884
+ headers: this.getAuthHeaders(),
2885
+ redirect: 'manual'
2828
2886
  });
2887
+ // Handle 302 redirect (registry → OSS signed URL)
2888
+ if (301 === response.status || 302 === response.status) {
2889
+ const integrity = response.headers.get('x-integrity') || '';
2890
+ const location = response.headers.get('location');
2891
+ if (!location) throw new RegistryError('Missing redirect location in download response', response.status);
2892
+ const downloadResponse = await fetch(location);
2893
+ if (!downloadResponse.ok) throw new RegistryError(`Download from storage failed: ${downloadResponse.status}`, downloadResponse.status);
2894
+ const arrayBuffer = await downloadResponse.arrayBuffer();
2895
+ const tarball = Buffer.from(arrayBuffer);
2896
+ return {
2897
+ tarball,
2898
+ integrity
2899
+ };
2900
+ }
2829
2901
  if (!response.ok) {
2830
2902
  const data = await response.json();
2831
2903
  throw new RegistryError(data.error || `Download failed: ${response.status}`, response.status, data);
2832
2904
  }
2905
+ // Direct response (no redirect) - read tarball and integrity directly
2833
2906
  const arrayBuffer = await response.arrayBuffer();
2834
2907
  const tarball = Buffer.from(arrayBuffer);
2835
2908
  const integrity = response.headers.get('x-integrity') || '';
@@ -2879,7 +2952,7 @@ class RegistryClient {
2879
2952
  /**
2880
2953
  * Publish a skill to the registry
2881
2954
  */ async publish(skillName, payload, skillPath, options = {}) {
2882
- const url = `${this.config.registry}/api/skills/publish`;
2955
+ const url = `${this.getApiBase()}/skills/publish`;
2883
2956
  // 提取短名称作为 tarball 顶层目录(不含 scope 前缀)
2884
2957
  const shortName = getShortName(skillName);
2885
2958
  // Create tarball with short name as top-level directory
@@ -3157,7 +3230,8 @@ class RegistryResolver {
3157
3230
  const registryUrl = getRegistryUrl(parsed.scope);
3158
3231
  // 3. 创建 client 并解析版本
3159
3232
  const client = new RegistryClient({
3160
- registry: registryUrl
3233
+ registry: registryUrl,
3234
+ apiPrefix: getApiPrefix(registryUrl)
3161
3235
  });
3162
3236
  const version = await client.resolveVersion(parsed.fullName, parsed.version);
3163
3237
  // 4. 下载 tarball
@@ -4022,7 +4096,8 @@ class RegistryResolver {
4022
4096
  const parsed = parseSkillIdentifier(ref);
4023
4097
  const registryUrl = getRegistryUrl(parsed.scope);
4024
4098
  const client = new RegistryClient({
4025
- registry: registryUrl
4099
+ registry: registryUrl,
4100
+ apiPrefix: getApiPrefix(registryUrl)
4026
4101
  });
4027
4102
  // 新增:先查询 skill 信息获取 source_type
4028
4103
  let skillInfo;
@@ -4163,7 +4238,8 @@ class RegistryResolver {
4163
4238
  /**
4164
4239
  * 安装 Local Folder 模式发布的 skill
4165
4240
  *
4166
- * 通过 Registry 的 /api/skills/:name/download API 下载 tarball
4241
+ * 通过 Registry 的 {apiPrefix}/skills/:name/download API 下载 tarball
4242
+ * (apiPrefix 根据 registry 不同而不同,如 /api 或 /api/reskill)
4167
4243
  */ async installFromRegistryLocal(_skillInfo, parsed, targetAgents, options = {}) {
4168
4244
  const registryUrl = getRegistryUrl(parsed.scope);
4169
4245
  // 构造下载 URL(通过 Registry API)
@@ -5987,23 +6063,25 @@ async function loginAction(options) {
5987
6063
  */ async function loginWithToken(token, registry, authManager) {
5988
6064
  logger_logger.log(`Verifying token with ${registry}...`);
5989
6065
  logger_logger.newline();
5990
- // Verify token by calling whoami
6066
+ // Verify token by calling login-cli endpoint
5991
6067
  const client = new RegistryClient({
5992
6068
  registry,
5993
- token
6069
+ token,
6070
+ apiPrefix: getApiPrefix(registry)
5994
6071
  });
5995
6072
  try {
5996
- const response = await client.whoami();
6073
+ const response = await client.loginCli();
5997
6074
  if (!response.success || !response.user) {
5998
6075
  logger_logger.error(response.error || 'Token verification failed');
5999
6076
  process.exit(1);
6000
6077
  }
6001
- // Save token with handle (use user.handle, not user.id)
6002
- authManager.setToken(token, registry, void 0, response.user.handle);
6078
+ // Save token with handle and email
6079
+ authManager.setToken(token, registry, response.user.email, response.user.handle);
6003
6080
  logger_logger.log('✓ Token verified and saved!');
6004
6081
  logger_logger.newline();
6005
6082
  logger_logger.log(` Handle: @${response.user.handle}`);
6006
6083
  logger_logger.log(` Username: ${response.user.id}`);
6084
+ if (response.user.email) logger_logger.log(` Email: ${response.user.email}`);
6007
6085
  logger_logger.log(` Registry: ${registry}`);
6008
6086
  logger_logger.newline();
6009
6087
  logger_logger.log(`Token saved to ${authManager.getConfigPath()}`);
@@ -7106,7 +7184,8 @@ async function publishAction(skillPath, options) {
7106
7184
  logger_logger.log(`Publishing to ${registry}...`);
7107
7185
  const client = new RegistryClient({
7108
7186
  registry,
7109
- token
7187
+ token,
7188
+ apiPrefix: getApiPrefix(registry)
7110
7189
  });
7111
7190
  try {
7112
7191
  // Get skill name from SKILL.md (primary source per agentskills.io spec)
@@ -7284,7 +7363,8 @@ async function whoamiAction(options) {
7284
7363
  // Verify with server
7285
7364
  const client = new RegistryClient({
7286
7365
  registry,
7287
- token
7366
+ token,
7367
+ apiPrefix: getApiPrefix(registry)
7288
7368
  });
7289
7369
  try {
7290
7370
  const response = await client.whoami();
@@ -8,6 +8,8 @@ import type { PublishPayload } from './publisher.js';
8
8
  export interface RegistryConfig {
9
9
  registry: string;
10
10
  token?: string;
11
+ /** API path prefix, e.g., '/api' (default) or '/api/reskill' for rush-app */
12
+ apiPrefix?: string;
11
13
  }
12
14
  export interface PublishRequest {
13
15
  name: string;
@@ -39,6 +41,15 @@ export interface WhoamiResponse {
39
41
  handle: string;
40
42
  };
41
43
  }
44
+ export interface LoginCliResponse {
45
+ success: boolean;
46
+ error?: string;
47
+ user?: {
48
+ id: string;
49
+ handle: string;
50
+ email?: string;
51
+ };
52
+ }
42
53
  export interface SkillMetadataResponse {
43
54
  name: string;
44
55
  'dist-tags': Record<string, string>;
@@ -57,6 +68,12 @@ export declare class RegistryError extends Error {
57
68
  export declare class RegistryClient {
58
69
  private config;
59
70
  constructor(config: RegistryConfig);
71
+ /**
72
+ * Get API base URL (registry + apiPrefix)
73
+ *
74
+ * @returns Base URL for API calls, e.g., 'https://example.com/api' or 'https://rush.com/api/reskill'
75
+ */
76
+ private getApiBase;
60
77
  /**
61
78
  * Get authorization headers
62
79
  */
@@ -65,6 +82,16 @@ export declare class RegistryClient {
65
82
  * Get current user info (whoami)
66
83
  */
67
84
  whoami(): Promise<WhoamiResponse>;
85
+ /**
86
+ * CLI login - verify token and get user info
87
+ *
88
+ * Calls POST /api/auth/login-cli to validate the token and retrieve user information.
89
+ * This is the preferred method for CLI authentication.
90
+ *
91
+ * @returns User information if authentication succeeds
92
+ * @throws RegistryError if authentication fails
93
+ */
94
+ loginCli(): Promise<LoginCliResponse>;
68
95
  /**
69
96
  * Create tarball from skill files
70
97
  *
@@ -1 +1 @@
1
- {"version":3,"file":"registry-client.d.ts","sourceRoot":"","sources":["../../src/core/registry-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"registry-client.d.ts","sourceRoot":"","sources":["../../src/core/registry-client.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"registry-resolver.d.ts","sourceRoot":"","sources":["../../src/core/registry-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAGL,KAAK,qBAAqB,EAE3B,MAAM,4BAA4B,CAAC;AAQpC,MAAM,WAAW,qBAAqB;IACpC,8BAA8B;IAC9B,MAAM,EAAE,qBAAqB,CAAC;IAC9B,uCAAuC;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,uBAAuB;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,mBAAmB;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,iCAAiC;IACjC,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD,qBAAa,gBAAgB;IAC3B;;;;;;;;;;;;;OAaG;IACH,MAAM,CAAC,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAwC1C;;;;;;;;;;OAUG;IACG,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;IA+B1D;;;;;;OAMG;IACG,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAWjE"}
1
+ {"version":3,"file":"registry-resolver.d.ts","sourceRoot":"","sources":["../../src/core/registry-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAIL,KAAK,qBAAqB,EAE3B,MAAM,4BAA4B,CAAC;AAQpC,MAAM,WAAW,qBAAqB;IACpC,8BAA8B;IAC9B,MAAM,EAAE,qBAAqB,CAAC;IAC9B,uCAAuC;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,uBAAuB;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,mBAAmB;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,iCAAiC;IACjC,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD,qBAAa,gBAAgB;IAC3B;;;;;;;;;;;;;OAaG;IACH,MAAM,CAAC,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAwC1C;;;;;;;;;;OAUG;IACG,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;IA+B1D;;;;;;OAMG;IACG,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAWjE"}
@@ -178,7 +178,8 @@ export declare class SkillManager {
178
178
  /**
179
179
  * 安装 Local Folder 模式发布的 skill
180
180
  *
181
- * 通过 Registry 的 /api/skills/:name/download API 下载 tarball
181
+ * 通过 Registry 的 {apiPrefix}/skills/:name/download API 下载 tarball
182
+ * (apiPrefix 根据 registry 不同而不同,如 /api 或 /api/reskill)
182
183
  */
183
184
  private installFromRegistryLocal;
184
185
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"skill-manager.d.ts","sourceRoot":"","sources":["../../src/core/skill-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"skill-manager.d.ts","sourceRoot":"","sources":["../../src/core/skill-manager.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -2398,12 +2398,39 @@ const installer_SKILLS_SUBDIR = 'skills';
2398
2398
  * Hardcoded registry to scope mapping
2399
2399
  * TODO: Replace with dynamic fetching from /api/registry/info
2400
2400
  */ const REGISTRY_SCOPE_MAP = {
2401
+ // rush-app (private registry, new)
2402
+ 'https://rush-test.zhenguanyu.com': '@kanyun',
2403
+ 'https://rush.zhenguanyu.com': '@kanyun',
2404
+ // reskill-app (private registry, legacy)
2401
2405
  'https://reskill-test.zhenguanyu.com': '@kanyun',
2402
- 'https://reskill-test.zhenguanyu.com/': '@kanyun',
2403
2406
  // Local development
2404
- 'http://localhost:3000': '@kanyun',
2405
- 'http://localhost:3000/': '@kanyun'
2407
+ 'http://localhost:3000': '@kanyun'
2406
2408
  };
2409
+ /**
2410
+ * Registry API prefix mapping
2411
+ *
2412
+ * rush-app hosts reskill APIs under /api/reskill/ prefix.
2413
+ * Default for unlisted registries: '/api'
2414
+ */ const REGISTRY_API_PREFIX = {
2415
+ 'https://rush-test.zhenguanyu.com': '/api/reskill',
2416
+ 'https://rush.zhenguanyu.com': '/api/reskill',
2417
+ 'http://localhost:3000': '/api/reskill'
2418
+ };
2419
+ /**
2420
+ * Get the API path prefix for a given registry URL
2421
+ *
2422
+ * @param registryUrl - Registry URL
2423
+ * @returns API prefix string (e.g., '/api' or '/api/reskill')
2424
+ *
2425
+ * @example
2426
+ * getApiPrefix('https://rush-test.zhenguanyu.com') // '/api/reskill'
2427
+ * getApiPrefix('https://reskill.info') // '/api'
2428
+ * getApiPrefix('https://unknown.com') // '/api'
2429
+ */ function getApiPrefix(registryUrl) {
2430
+ if (!registryUrl) return '/api';
2431
+ const normalized = registryUrl.endsWith('/') ? registryUrl.slice(0, -1) : registryUrl;
2432
+ return REGISTRY_API_PREFIX[normalized] || '/api';
2433
+ }
2407
2434
  /**
2408
2435
  * Get the registry URL for a given scope (reverse lookup)
2409
2436
  *
@@ -2412,8 +2439,8 @@ const installer_SKILLS_SUBDIR = 'skills';
2412
2439
  * @returns Registry URL (with trailing slash) or null if not found
2413
2440
  *
2414
2441
  * @example
2415
- * getRegistryForScope('@kanyun') // 'https://reskill-test.zhenguanyu.com/'
2416
- * getRegistryForScope('kanyun') // 'https://reskill-test.zhenguanyu.com/'
2442
+ * getRegistryForScope('@kanyun') // 'https://rush-test.zhenguanyu.com/'
2443
+ * getRegistryForScope('kanyun') // 'https://rush-test.zhenguanyu.com/'
2417
2444
  * getRegistryForScope('@unknown') // null
2418
2445
  * getRegistryForScope('@mycompany', { '@mycompany': 'https://my.registry.com/' }) // 'https://my.registry.com/'
2419
2446
  */ function getRegistryForScope(scope, customRegistries) {
@@ -2443,8 +2470,8 @@ const installer_SKILLS_SUBDIR = 'skills';
2443
2470
  * @throws Error if scope is provided but not found in the registry map
2444
2471
  *
2445
2472
  * @example
2446
- * getRegistryUrl('@kanyun') // 'https://reskill-test.zhenguanyu.com/'
2447
- * getRegistryUrl('kanyun') // 'https://reskill-test.zhenguanyu.com/'
2473
+ * getRegistryUrl('@kanyun') // 'https://rush-test.zhenguanyu.com/'
2474
+ * getRegistryUrl('kanyun') // 'https://rush-test.zhenguanyu.com/'
2448
2475
  * getRegistryUrl(null) // 'https://reskill.info/'
2449
2476
  * getRegistryUrl('') // 'https://reskill.info/'
2450
2477
  * getRegistryUrl('@unknown') // throws Error
@@ -2581,6 +2608,15 @@ class RegistryClient {
2581
2608
  this.config = config;
2582
2609
  }
2583
2610
  /**
2611
+ * Get API base URL (registry + apiPrefix)
2612
+ *
2613
+ * @returns Base URL for API calls, e.g., 'https://example.com/api' or 'https://rush.com/api/reskill'
2614
+ */ getApiBase() {
2615
+ const prefix = this.config.apiPrefix || '/api';
2616
+ const registry = this.config.registry.endsWith('/') ? this.config.registry.slice(0, -1) : this.config.registry;
2617
+ return `${registry}${prefix}`;
2618
+ }
2619
+ /**
2584
2620
  * Get authorization headers
2585
2621
  */ getAuthHeaders() {
2586
2622
  const headers = {
@@ -2593,7 +2629,7 @@ class RegistryClient {
2593
2629
  /**
2594
2630
  * Get current user info (whoami)
2595
2631
  */ async whoami() {
2596
- const url = `${this.config.registry}/api/auth/me`;
2632
+ const url = `${this.getApiBase()}/auth/me`;
2597
2633
  const response = await fetch(url, {
2598
2634
  method: 'GET',
2599
2635
  headers: this.getAuthHeaders()
@@ -2603,6 +2639,24 @@ class RegistryClient {
2603
2639
  return data;
2604
2640
  }
2605
2641
  /**
2642
+ * CLI login - verify token and get user info
2643
+ *
2644
+ * Calls POST /api/auth/login-cli to validate the token and retrieve user information.
2645
+ * This is the preferred method for CLI authentication.
2646
+ *
2647
+ * @returns User information if authentication succeeds
2648
+ * @throws RegistryError if authentication fails
2649
+ */ async loginCli() {
2650
+ const url = `${this.getApiBase()}/auth/login-cli`;
2651
+ const response = await fetch(url, {
2652
+ method: 'POST',
2653
+ headers: this.getAuthHeaders()
2654
+ });
2655
+ const data = await response.json();
2656
+ if (!response.ok) throw new RegistryError(data.error || `Login failed: ${response.status}`, response.status, data);
2657
+ return data;
2658
+ }
2659
+ /**
2606
2660
  * Create tarball from skill files
2607
2661
  *
2608
2662
  * @param skillPath - Path to the skill directory
@@ -2649,7 +2703,7 @@ class RegistryClient {
2649
2703
  * @returns Skill 基本信息
2650
2704
  * @throws RegistryError 如果 skill 不存在或请求失败
2651
2705
  */ async getSkillInfo(skillName) {
2652
- const url = `${this.config.registry}/api/skills/${encodeURIComponent(skillName)}`;
2706
+ const url = `${this.getApiBase()}/skills/${encodeURIComponent(skillName)}`;
2653
2707
  const response = await fetch(url, {
2654
2708
  method: 'GET',
2655
2709
  headers: this.getAuthHeaders()
@@ -2683,7 +2737,7 @@ class RegistryClient {
2683
2737
  // 如果是 semver 版本号,直接返回
2684
2738
  if (/^\d+\.\d+\.\d+/.test(version)) return version;
2685
2739
  // 否则视为 tag,需要查询 dist-tags
2686
- const url = `${this.config.registry}/api/skills/${encodeURIComponent(skillName)}`;
2740
+ const url = `${this.getApiBase()}/skills/${encodeURIComponent(skillName)}`;
2687
2741
  const response = await fetch(url, {
2688
2742
  method: 'GET',
2689
2743
  headers: this.getAuthHeaders()
@@ -2718,15 +2772,34 @@ class RegistryClient {
2718
2772
  * @example
2719
2773
  * const { tarball, integrity } = await client.downloadSkill('@kanyun/test-skill', '1.0.0');
2720
2774
  */ async downloadSkill(skillName, version) {
2721
- const url = `${this.config.registry}/api/skills/${encodeURIComponent(skillName)}/versions/${version}/download`;
2775
+ const url = `${this.getApiBase()}/skills/${encodeURIComponent(skillName)}/versions/${version}/download`;
2776
+ // Use redirect: 'manual' to capture x-integrity header from 302 responses.
2777
+ // The registry returns a 302 redirect to OSS with the integrity header,
2778
+ // which would be lost if fetch auto-follows the redirect.
2722
2779
  const response = await fetch(url, {
2723
2780
  method: 'GET',
2724
- headers: this.getAuthHeaders()
2781
+ headers: this.getAuthHeaders(),
2782
+ redirect: 'manual'
2725
2783
  });
2784
+ // Handle 302 redirect (registry → OSS signed URL)
2785
+ if (301 === response.status || 302 === response.status) {
2786
+ const integrity = response.headers.get('x-integrity') || '';
2787
+ const location = response.headers.get('location');
2788
+ if (!location) throw new RegistryError('Missing redirect location in download response', response.status);
2789
+ const downloadResponse = await fetch(location);
2790
+ if (!downloadResponse.ok) throw new RegistryError(`Download from storage failed: ${downloadResponse.status}`, downloadResponse.status);
2791
+ const arrayBuffer = await downloadResponse.arrayBuffer();
2792
+ const tarball = Buffer.from(arrayBuffer);
2793
+ return {
2794
+ tarball,
2795
+ integrity
2796
+ };
2797
+ }
2726
2798
  if (!response.ok) {
2727
2799
  const data = await response.json();
2728
2800
  throw new RegistryError(data.error || `Download failed: ${response.status}`, response.status, data);
2729
2801
  }
2802
+ // Direct response (no redirect) - read tarball and integrity directly
2730
2803
  const arrayBuffer = await response.arrayBuffer();
2731
2804
  const tarball = Buffer.from(arrayBuffer);
2732
2805
  const integrity = response.headers.get('x-integrity') || '';
@@ -2776,7 +2849,7 @@ class RegistryClient {
2776
2849
  /**
2777
2850
  * Publish a skill to the registry
2778
2851
  */ async publish(skillName, payload, skillPath, options = {}) {
2779
- const url = `${this.config.registry}/api/skills/publish`;
2852
+ const url = `${this.getApiBase()}/skills/publish`;
2780
2853
  // 提取短名称作为 tarball 顶层目录(不含 scope 前缀)
2781
2854
  const shortName = getShortName(skillName);
2782
2855
  // Create tarball with short name as top-level directory
@@ -3120,7 +3193,8 @@ class RegistryResolver {
3120
3193
  const registryUrl = getRegistryUrl(parsed.scope);
3121
3194
  // 3. 创建 client 并解析版本
3122
3195
  const client = new RegistryClient({
3123
- registry: registryUrl
3196
+ registry: registryUrl,
3197
+ apiPrefix: getApiPrefix(registryUrl)
3124
3198
  });
3125
3199
  const version = await client.resolveVersion(parsed.fullName, parsed.version);
3126
3200
  // 4. 下载 tarball
@@ -4012,7 +4086,8 @@ class RegistryResolver {
4012
4086
  const parsed = parseSkillIdentifier(ref);
4013
4087
  const registryUrl = getRegistryUrl(parsed.scope);
4014
4088
  const client = new RegistryClient({
4015
- registry: registryUrl
4089
+ registry: registryUrl,
4090
+ apiPrefix: getApiPrefix(registryUrl)
4016
4091
  });
4017
4092
  // 新增:先查询 skill 信息获取 source_type
4018
4093
  let skillInfo;
@@ -4153,7 +4228,8 @@ class RegistryResolver {
4153
4228
  /**
4154
4229
  * 安装 Local Folder 模式发布的 skill
4155
4230
  *
4156
- * 通过 Registry 的 /api/skills/:name/download API 下载 tarball
4231
+ * 通过 Registry 的 {apiPrefix}/skills/:name/download API 下载 tarball
4232
+ * (apiPrefix 根据 registry 不同而不同,如 /api 或 /api/reskill)
4157
4233
  */ async installFromRegistryLocal(_skillInfo, parsed, targetAgents, options = {}) {
4158
4234
  const registryUrl = getRegistryUrl(parsed.scope);
4159
4235
  // 构造下载 URL(通过 Registry API)
@@ -9,6 +9,18 @@
9
9
  * 用于无 scope 的 skill 安装
10
10
  */
11
11
  export declare const PUBLIC_REGISTRY = "https://reskill.info/";
12
+ /**
13
+ * Get the API path prefix for a given registry URL
14
+ *
15
+ * @param registryUrl - Registry URL
16
+ * @returns API prefix string (e.g., '/api' or '/api/reskill')
17
+ *
18
+ * @example
19
+ * getApiPrefix('https://rush-test.zhenguanyu.com') // '/api/reskill'
20
+ * getApiPrefix('https://reskill.info') // '/api'
21
+ * getApiPrefix('https://unknown.com') // '/api'
22
+ */
23
+ export declare function getApiPrefix(registryUrl: string): string;
12
24
  /**
13
25
  * Parsed skill name result
14
26
  */
@@ -41,7 +53,7 @@ export interface ParsedSkillIdentifier {
41
53
  * @returns Scope string (e.g., "@kanyun") or null if not found
42
54
  *
43
55
  * @example
44
- * getScopeForRegistry('https://reskill-test.zhenguanyu.com') // '@kanyun'
56
+ * getScopeForRegistry('https://rush-test.zhenguanyu.com') // '@kanyun'
45
57
  * getScopeForRegistry('https://unknown.com') // null
46
58
  */
47
59
  export declare function getScopeForRegistry(registry: string): string | null;
@@ -58,8 +70,8 @@ export type ScopeRegistries = Record<string, string>;
58
70
  * @returns Registry URL (with trailing slash) or null if not found
59
71
  *
60
72
  * @example
61
- * getRegistryForScope('@kanyun') // 'https://reskill-test.zhenguanyu.com/'
62
- * getRegistryForScope('kanyun') // 'https://reskill-test.zhenguanyu.com/'
73
+ * getRegistryForScope('@kanyun') // 'https://rush-test.zhenguanyu.com/'
74
+ * getRegistryForScope('kanyun') // 'https://rush-test.zhenguanyu.com/'
63
75
  * getRegistryForScope('@unknown') // null
64
76
  * getRegistryForScope('@mycompany', { '@mycompany': 'https://my.registry.com/' }) // 'https://my.registry.com/'
65
77
  */
@@ -76,8 +88,8 @@ export declare function getRegistryForScope(scope: string, customRegistries?: Sc
76
88
  * @throws Error if scope is provided but not found in the registry map
77
89
  *
78
90
  * @example
79
- * getRegistryUrl('@kanyun') // 'https://reskill-test.zhenguanyu.com/'
80
- * getRegistryUrl('kanyun') // 'https://reskill-test.zhenguanyu.com/'
91
+ * getRegistryUrl('@kanyun') // 'https://rush-test.zhenguanyu.com/'
92
+ * getRegistryUrl('kanyun') // 'https://rush-test.zhenguanyu.com/'
81
93
  * getRegistryUrl(null) // 'https://reskill.info/'
82
94
  * getRegistryUrl('') // 'https://reskill.info/'
83
95
  * getRegistryUrl('@unknown') // throws Error
@@ -1 +1 @@
1
- {"version":3,"file":"registry-scope.d.ts","sourceRoot":"","sources":["../../src/utils/registry-scope.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,eAAO,MAAM,eAAe,0BAA0B,CAAC;AAcvD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,gDAAgD;IAChD,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,oEAAoE;IACpE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,qEAAqE;IACrE,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAcnE;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAErD;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,gBAAgB,CAAC,EAAE,eAAe,GACjC,MAAM,GAAG,IAAI,CAwBf;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAChC,gBAAgB,CAAC,EAAE,eAAe,GACjC,MAAM,CAgBR;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,CAiBjE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAS7E;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,qBAAqB,CAwD9E"}
1
+ {"version":3,"file":"registry-scope.d.ts","sourceRoot":"","sources":["../../src/utils/registry-scope.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,eAAO,MAAM,eAAe,0BAA0B,CAAC;AA8BvD;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAMxD;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,gDAAgD;IAChD,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,oEAAoE;IACpE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,qEAAqE;IACrE,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAcnE;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAErD;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,gBAAgB,CAAC,EAAE,eAAe,GACjC,MAAM,GAAG,IAAI,CAwBf;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAChC,gBAAgB,CAAC,EAAE,eAAe,GACjC,MAAM,CAgBR;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,CAiBjE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAS7E;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,qBAAqB,CAwD9E"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reskill",
3
- "version": "1.5.0",
3
+ "version": "1.7.0",
4
4
  "description": "AI Skills Package Manager - Git-based skills management for AI agents",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",