reskill 1.10.0 → 1.11.1
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/dist/cli/commands/list.d.ts.map +1 -1
- package/dist/cli/index.js +434 -263
- package/dist/core/config-loader.d.ts +4 -0
- package/dist/core/config-loader.d.ts.map +1 -1
- package/dist/core/lock-manager.d.ts +1 -0
- package/dist/core/lock-manager.d.ts.map +1 -1
- package/dist/core/skill-manager.d.ts +55 -4
- package/dist/core/skill-manager.d.ts.map +1 -1
- package/dist/index.js +236 -50
- package/dist/types/index.d.ts +33 -2
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -97,6 +97,10 @@ export declare class ConfigLoader {
|
|
|
97
97
|
* @param updates - Partial defaults to merge
|
|
98
98
|
*/
|
|
99
99
|
updateDefaults(updates: Partial<SkillsDefaults>): void;
|
|
100
|
+
/**
|
|
101
|
+
* Get all configured registries (custom + default).
|
|
102
|
+
*/
|
|
103
|
+
getRegistries(): Record<string, string>;
|
|
100
104
|
/**
|
|
101
105
|
* Get registry URL by name
|
|
102
106
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/core/config-loader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAiCpE;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAGrD,CAAC;AAMF;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,MAAM,CAA2B;gBAE7B,WAAW,CAAC,EAAE,MAAM;IAShC;;OAEG;IACH,cAAc,IAAI,MAAM;IAIxB;;OAEG;IACH,aAAa,IAAI,MAAM;IAIvB;;OAEG;IACH,aAAa,IAAI,MAAM;IASvB;;OAEG;IACH,MAAM,IAAI,OAAO;IAIjB;;;;OAIG;IACH,IAAI,IAAI,UAAU;IAiBlB;;OAEG;IACH,MAAM,IAAI,UAAU;IAKpB;;;;;OAKG;IACH,IAAI,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,IAAI;IAS/B;;;;OAIG;IACH,YAAY,IAAI,OAAO;IAQvB;;;;OAIG;IACH,MAAM,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,UAAU;IAwBjD;;;;;;OAMG;IACH,WAAW,IAAI,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,iBAAiB,CAAC,GAAG;QACjE,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;KACrC;IAYD;;;;;;OAMG;IACH,kBAAkB,IAAI,MAAM,GAAG,SAAS;IAKxC;;;;;;OAMG;IACH,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI;IAgBtD;;;;;;;OAOG;IACH,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAiB5C;;;;;;;;OAQG;IACH,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IA2BnD;;;;;;;;;OASG;IACH,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAoBtC;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAuCzB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA8B1B;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAgBzC;;;;;;;;;;OAUG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAiB5C;;;;;;;OAOG;IACH,OAAO,CAAC,sBAAsB;IAa9B;;;;OAIG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAWlC;;OAEG;IACH,SAAS,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAUnC;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAK/B;;OAEG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAS7C;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAU1B;;OAEG;IACH,OAAO,CAAC,kBAAkB;CAK3B;AAED,eAAe,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/core/config-loader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAiCpE;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAGrD,CAAC;AAMF;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,MAAM,CAA2B;gBAE7B,WAAW,CAAC,EAAE,MAAM;IAShC;;OAEG;IACH,cAAc,IAAI,MAAM;IAIxB;;OAEG;IACH,aAAa,IAAI,MAAM;IAIvB;;OAEG;IACH,aAAa,IAAI,MAAM;IASvB;;OAEG;IACH,MAAM,IAAI,OAAO;IAIjB;;;;OAIG;IACH,IAAI,IAAI,UAAU;IAiBlB;;OAEG;IACH,MAAM,IAAI,UAAU;IAKpB;;;;;OAKG;IACH,IAAI,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,IAAI;IAS/B;;;;OAIG;IACH,YAAY,IAAI,OAAO;IAQvB;;;;OAIG;IACH,MAAM,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,UAAU;IAwBjD;;;;;;OAMG;IACH,WAAW,IAAI,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,iBAAiB,CAAC,GAAG;QACjE,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;KACrC;IAYD;;;;;;OAMG;IACH,kBAAkB,IAAI,MAAM,GAAG,SAAS;IAKxC;;;;;;OAMG;IACH,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI;IAgBtD;;OAEG;IACH,aAAa,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAQvC;;;;;;;OAOG;IACH,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAiB5C;;;;;;;;OAQG;IACH,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IA2BnD;;;;;;;;;OASG;IACH,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAoBtC;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAuCzB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA8B1B;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAgBzC;;;;;;;;;;OAUG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAiB5C;;;;;;;OAOG;IACH,OAAO,CAAC,sBAAsB;IAa9B;;;;OAIG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAWlC;;OAEG;IACH,SAAS,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAUnC;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAK/B;;OAEG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAS7C;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAU1B;;OAEG;IACH,OAAO,CAAC,kBAAkB;CAK3B;AAED,eAAe,YAAY,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lock-manager.d.ts","sourceRoot":"","sources":["../../src/core/lock-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAQjE;;;;GAIG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAA2B;gBAE/B,WAAW,CAAC,EAAE,MAAM;IAKhC;;OAEG;IACH,WAAW,IAAI,MAAM;IAIrB;;OAEG;IACH,MAAM,IAAI,OAAO;IAIjB;;OAEG;IACH,IAAI,IAAI,UAAU;IAsBlB;;OAEG;IACH,MAAM,IAAI,UAAU;IAKpB;;OAEG;IACH,IAAI,CAAC,UAAU,CAAC,EAAE,UAAU,GAAG,IAAI;IASnC;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAK1C;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI;IAM3C;;OAEG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAU7B;;OAEG;IACH,SAAS,CACP,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE;QACP,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,GAAG,EAAE,MAAM,CAAC;QACZ,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"lock-manager.d.ts","sourceRoot":"","sources":["../../src/core/lock-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAQjE;;;;GAIG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAA2B;gBAE/B,WAAW,CAAC,EAAE,MAAM;IAKhC;;OAEG;IACH,WAAW,IAAI,MAAM;IAIrB;;OAEG;IACH,MAAM,IAAI,OAAO;IAIjB;;OAEG;IACH,IAAI,IAAI,UAAU;IAsBlB;;OAEG;IACH,MAAM,IAAI,UAAU;IAKpB;;OAEG;IACH,IAAI,CAAC,UAAU,CAAC,EAAE,UAAU,GAAG,IAAI;IASnC;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAK1C;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI;IAM3C;;OAEG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAU7B;;OAEG;IACH,SAAS,CACP,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE;QACP,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,GAAG,EAAE,MAAM,CAAC;QACZ,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,GACA,WAAW;IAmBd;;OAEG;IACH,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC;IAKrC;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAK1B;;OAEG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO;IAQtD;;OAEG;IACH,KAAK,IAAI,IAAI;IAQb;;OAEG;IACH,MAAM,IAAI,IAAI;CAOf;AAED,eAAe,WAAW,CAAC"}
|
|
@@ -7,7 +7,7 @@ import { type ParsedSkillWithPath } from './skill-parser.js';
|
|
|
7
7
|
* SkillManager configuration options
|
|
8
8
|
*/
|
|
9
9
|
export interface SkillManagerOptions {
|
|
10
|
-
/** Global mode, install to ~/.
|
|
10
|
+
/** Global mode, install to ~/.agents/skills/ */
|
|
11
11
|
global?: boolean;
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
@@ -17,8 +17,8 @@ export interface SkillManagerOptions {
|
|
|
17
17
|
* Provides complete skill installation, update, and uninstall functionality
|
|
18
18
|
*
|
|
19
19
|
* Installation directories:
|
|
20
|
-
* - Project mode (default): .skills/ or
|
|
21
|
-
* - Global mode (-g): ~/.
|
|
20
|
+
* - Project mode (default): .agents/skills/ (canonical) or .skills/ (legacy)
|
|
21
|
+
* - Global mode (-g): ~/.agents/skills/
|
|
22
22
|
*/
|
|
23
23
|
export declare class SkillManager {
|
|
24
24
|
private projectRoot;
|
|
@@ -41,7 +41,7 @@ export declare class SkillManager {
|
|
|
41
41
|
/**
|
|
42
42
|
* Get legacy installation directory (for backward compatibility)
|
|
43
43
|
*
|
|
44
|
-
* - Global mode: ~/.
|
|
44
|
+
* - Global mode: ~/.agents/skills/ (canonical)
|
|
45
45
|
* - Project mode: .skills/ or directory configured in skills.json
|
|
46
46
|
*/
|
|
47
47
|
getInstallDir(): string;
|
|
@@ -113,12 +113,46 @@ export declare class SkillManager {
|
|
|
113
113
|
* Update skill
|
|
114
114
|
*/
|
|
115
115
|
update(name?: string): Promise<InstalledSkill[]>;
|
|
116
|
+
/**
|
|
117
|
+
* Resolve registry URL for a skill reference.
|
|
118
|
+
*
|
|
119
|
+
* Resolution order:
|
|
120
|
+
* 1. Explicit CLI override (options.registry)
|
|
121
|
+
* 2. Scoped skills → getRegistryUrl(scope)
|
|
122
|
+
* 3. Unscoped skills → lock file registry (O(1), no network)
|
|
123
|
+
* 4. Unscoped skills → probe skills.json registries (non-git-host, network)
|
|
124
|
+
* 5. Default → PUBLIC_REGISTRY
|
|
125
|
+
*/
|
|
126
|
+
private resolveRegistryUrl;
|
|
127
|
+
/**
|
|
128
|
+
* Check if a registry entry is a git host (github, gitlab, etc.)
|
|
129
|
+
* Git hosts are not skill registries and should be skipped during probe.
|
|
130
|
+
*/
|
|
131
|
+
private isGitHostRegistry;
|
|
132
|
+
/**
|
|
133
|
+
* Derive a registry name from a URL for storing in skills.json.registries.
|
|
134
|
+
* Returns null for git hosts (already in DEFAULT_REGISTRIES).
|
|
135
|
+
*/
|
|
136
|
+
private deriveRegistryName;
|
|
137
|
+
/**
|
|
138
|
+
* Install skill for update flow. Uses installToAgents so registry refs are
|
|
139
|
+
* routed correctly (Registry > HTTP > Git).
|
|
140
|
+
*/
|
|
141
|
+
private installForUpdate;
|
|
116
142
|
/**
|
|
117
143
|
* List installed skills
|
|
118
144
|
*
|
|
119
145
|
* Checks both canonical (.agents/skills/) and legacy (.skills/) locations.
|
|
120
146
|
*/
|
|
121
147
|
list(): InstalledSkill[];
|
|
148
|
+
/**
|
|
149
|
+
* Detect which agents have a skill installed (symlink or copy)
|
|
150
|
+
*
|
|
151
|
+
* Scans all known agent directories to check if the skill exists there.
|
|
152
|
+
* Excludes the canonical directory (.agents/skills/) to avoid false positives
|
|
153
|
+
* from agents whose skillsDir overlaps with the canonical path (e.g. amp).
|
|
154
|
+
*/
|
|
155
|
+
private detectSkillAgents;
|
|
122
156
|
/**
|
|
123
157
|
* Get installed skill information from a specific path
|
|
124
158
|
*/
|
|
@@ -209,6 +243,23 @@ export declare class SkillManager {
|
|
|
209
243
|
* - local: downloads tarball via Registry API
|
|
210
244
|
*/
|
|
211
245
|
private installFromWebPublished;
|
|
246
|
+
/**
|
|
247
|
+
* Build a Git ref for web-published github/gitlab skills.
|
|
248
|
+
*
|
|
249
|
+
* When `skillPath` is provided (multi-skill repo), constructs a shorthand ref
|
|
250
|
+
* like `github:owner/repo/skills/my-skill` so that only the sub-directory is
|
|
251
|
+
* cached and installed.
|
|
252
|
+
*
|
|
253
|
+
* Fallback: if `parseGitUrl` fails (non-standard URL), appends `#shortName`
|
|
254
|
+
* as a skill-name selector. The `#` fragment is extracted by
|
|
255
|
+
* `GitResolver.parseRef()` as `parsed.skillName`, then matched against
|
|
256
|
+
* SKILL.md `name` fields via `resolveSourcePath` / `discoverSkillsInDir`.
|
|
257
|
+
* This differs from the subPath approach (directory-based) but works because
|
|
258
|
+
* skill names typically match their directory basenames.
|
|
259
|
+
*
|
|
260
|
+
* Returns the raw `sourceUrl` when no `skillPath` is available.
|
|
261
|
+
*/
|
|
262
|
+
private buildGitRefForWebPublished;
|
|
212
263
|
/**
|
|
213
264
|
* Install a skill published via "local folder" mode.
|
|
214
265
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-manager.d.ts","sourceRoot":"","sources":["../../src/core/skill-manager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,cAAc,EACd,cAAc,
|
|
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
|
@@ -297,13 +297,6 @@ var external_node_fs_ = __webpack_require__("node:fs");
|
|
|
297
297
|
*/ function getHomeDir() {
|
|
298
298
|
return process.env.HOME || process.env.USERPROFILE || '';
|
|
299
299
|
}
|
|
300
|
-
/**
|
|
301
|
-
* Get global skills installation directory (~/.claude/skills)
|
|
302
|
-
* @deprecated Use getAgentGlobalSkillsDir from agent-registry instead
|
|
303
|
-
*/ function getGlobalSkillsDir() {
|
|
304
|
-
const home = getHomeDir();
|
|
305
|
-
return __WEBPACK_EXTERNAL_MODULE_node_path__.join(home, '.claude', 'skills');
|
|
306
|
-
}
|
|
307
300
|
// ============================================================================
|
|
308
301
|
// Multi-Agent path utilities
|
|
309
302
|
// ============================================================================
|
|
@@ -1994,6 +1987,15 @@ ${CURSOR_BRIDGE_MARKER}
|
|
|
1994
1987
|
// Registry Management
|
|
1995
1988
|
// ==========================================================================
|
|
1996
1989
|
/**
|
|
1990
|
+
* Get all configured registries (custom + default).
|
|
1991
|
+
*/ getRegistries() {
|
|
1992
|
+
const config = this.getConfigOrDefault();
|
|
1993
|
+
return {
|
|
1994
|
+
...DEFAULT_REGISTRIES,
|
|
1995
|
+
...config.registries
|
|
1996
|
+
};
|
|
1997
|
+
}
|
|
1998
|
+
/**
|
|
1997
1999
|
* Get registry URL by name
|
|
1998
2000
|
*
|
|
1999
2001
|
* Resolution order:
|
|
@@ -2835,6 +2837,8 @@ ${CURSOR_BRIDGE_MARKER}
|
|
|
2835
2837
|
commit: options.commit,
|
|
2836
2838
|
installedAt: new Date().toISOString()
|
|
2837
2839
|
};
|
|
2840
|
+
// Only persist registry URL for registry-sourced skills
|
|
2841
|
+
if (options.registry) lockedSkill.registry = options.registry;
|
|
2838
2842
|
this.set(name, lockedSkill);
|
|
2839
2843
|
return lockedSkill;
|
|
2840
2844
|
}
|
|
@@ -2899,6 +2903,23 @@ ${CURSOR_BRIDGE_MARKER}
|
|
|
2899
2903
|
// Local development
|
|
2900
2904
|
'http://localhost:3000': '@kanyun-test'
|
|
2901
2905
|
};
|
|
2906
|
+
/**
|
|
2907
|
+
* Get the scope for a given registry URL
|
|
2908
|
+
*
|
|
2909
|
+
* @param registry - Registry URL
|
|
2910
|
+
* @returns Scope string (e.g., "@kanyun") or null if not found
|
|
2911
|
+
*
|
|
2912
|
+
* @example
|
|
2913
|
+
* getScopeForRegistry('https://rush-test.zhenguanyu.com') // '@kanyun'
|
|
2914
|
+
* getScopeForRegistry('https://unknown.com') // null
|
|
2915
|
+
*/ function getScopeForRegistry(registry) {
|
|
2916
|
+
if (!registry) return null;
|
|
2917
|
+
// Try exact match first
|
|
2918
|
+
if (REGISTRY_SCOPE_MAP[registry]) return REGISTRY_SCOPE_MAP[registry];
|
|
2919
|
+
// Try with/without trailing slash
|
|
2920
|
+
const normalized = registry.endsWith('/') ? registry.slice(0, -1) : `${registry}/`;
|
|
2921
|
+
return REGISTRY_SCOPE_MAP[normalized] || null;
|
|
2922
|
+
}
|
|
2902
2923
|
/**
|
|
2903
2924
|
* Get the registry URL for a given scope (reverse lookup)
|
|
2904
2925
|
*
|
|
@@ -3736,8 +3757,8 @@ class RegistryResolver {
|
|
|
3736
3757
|
* Provides complete skill installation, update, and uninstall functionality
|
|
3737
3758
|
*
|
|
3738
3759
|
* Installation directories:
|
|
3739
|
-
* - Project mode (default): .skills/ or
|
|
3740
|
-
* - Global mode (-g): ~/.
|
|
3760
|
+
* - Project mode (default): .agents/skills/ (canonical) or .skills/ (legacy)
|
|
3761
|
+
* - Global mode (-g): ~/.agents/skills/
|
|
3741
3762
|
*/ class SkillManager {
|
|
3742
3763
|
projectRoot;
|
|
3743
3764
|
resolver;
|
|
@@ -3771,10 +3792,10 @@ class RegistryResolver {
|
|
|
3771
3792
|
/**
|
|
3772
3793
|
* Get legacy installation directory (for backward compatibility)
|
|
3773
3794
|
*
|
|
3774
|
-
* - Global mode: ~/.
|
|
3795
|
+
* - Global mode: ~/.agents/skills/ (canonical)
|
|
3775
3796
|
* - Project mode: .skills/ or directory configured in skills.json
|
|
3776
3797
|
*/ getInstallDir() {
|
|
3777
|
-
if (this.isGlobal) return
|
|
3798
|
+
if (this.isGlobal) return this.getCanonicalSkillsDir();
|
|
3778
3799
|
return this.config.getInstallDir();
|
|
3779
3800
|
}
|
|
3780
3801
|
/**
|
|
@@ -3990,8 +4011,11 @@ class RegistryResolver {
|
|
|
3990
4011
|
*/ async installAll(options = {}) {
|
|
3991
4012
|
const skills = this.config.getSkills();
|
|
3992
4013
|
const installed = [];
|
|
4014
|
+
const targetAgents = await detectInstalledAgents();
|
|
3993
4015
|
for (const [name, ref] of Object.entries(skills))try {
|
|
3994
|
-
|
|
4016
|
+
// Use installToAgents (not install) to correctly route registry refs
|
|
4017
|
+
// resolveRegistryUrl inside handles lock file / registries probe fallback
|
|
4018
|
+
const { skill } = await this.installToAgents(ref, targetAgents, {
|
|
3995
4019
|
...options,
|
|
3996
4020
|
save: false
|
|
3997
4021
|
});
|
|
@@ -4037,6 +4061,7 @@ class RegistryResolver {
|
|
|
4037
4061
|
* Update skill
|
|
4038
4062
|
*/ async update(name) {
|
|
4039
4063
|
const updated = [];
|
|
4064
|
+
const targetAgents = await detectInstalledAgents();
|
|
4040
4065
|
if (name) {
|
|
4041
4066
|
// Update single skill
|
|
4042
4067
|
const ref = this.config.getSkillRef(name);
|
|
@@ -4044,9 +4069,10 @@ class RegistryResolver {
|
|
|
4044
4069
|
logger_logger.error(`Skill ${name} not found in skills.json`);
|
|
4045
4070
|
return [];
|
|
4046
4071
|
}
|
|
4047
|
-
// Check if update is needed (skip
|
|
4048
|
-
|
|
4049
|
-
logger_logger.info(`${name} is from
|
|
4072
|
+
// Check if update is needed (skip for HTTP and Registry - always re-download/reinstall)
|
|
4073
|
+
const isRegistry = this.isRegistrySource(ref);
|
|
4074
|
+
if (isRegistry) logger_logger.info(`${name} is from registry, re-installing...`);
|
|
4075
|
+
else if (this.isHttpSource(ref)) logger_logger.info(`${name} is from HTTP source, re-downloading...`);
|
|
4050
4076
|
else {
|
|
4051
4077
|
const resolved = await this.resolver.resolve(ref);
|
|
4052
4078
|
const remoteCommit = await this.cache.getRemoteCommit(resolved.repoUrl, resolved.ref);
|
|
@@ -4055,7 +4081,7 @@ class RegistryResolver {
|
|
|
4055
4081
|
return [];
|
|
4056
4082
|
}
|
|
4057
4083
|
}
|
|
4058
|
-
const skill = await this.
|
|
4084
|
+
const skill = await this.installForUpdate(ref, targetAgents, {
|
|
4059
4085
|
force: true,
|
|
4060
4086
|
save: false
|
|
4061
4087
|
});
|
|
@@ -4064,8 +4090,9 @@ class RegistryResolver {
|
|
|
4064
4090
|
// Update all
|
|
4065
4091
|
const skills = this.config.getSkills();
|
|
4066
4092
|
for (const [skillName, ref] of Object.entries(skills))try {
|
|
4067
|
-
// Check if update is needed (skip
|
|
4068
|
-
if (this.
|
|
4093
|
+
// Check if update is needed (skip for HTTP and Registry)
|
|
4094
|
+
if (this.isRegistrySource(ref)) logger_logger.info(`${skillName} is from registry, re-installing...`);
|
|
4095
|
+
else if (this.isHttpSource(ref)) logger_logger.info(`${skillName} is from HTTP source, re-downloading...`);
|
|
4069
4096
|
else {
|
|
4070
4097
|
const resolved = await this.resolver.resolve(ref);
|
|
4071
4098
|
const remoteCommit = await this.cache.getRemoteCommit(resolved.repoUrl, resolved.ref);
|
|
@@ -4074,7 +4101,7 @@ class RegistryResolver {
|
|
|
4074
4101
|
continue;
|
|
4075
4102
|
}
|
|
4076
4103
|
}
|
|
4077
|
-
const skill = await this.
|
|
4104
|
+
const skill = await this.installForUpdate(ref, targetAgents, {
|
|
4078
4105
|
force: true,
|
|
4079
4106
|
save: false
|
|
4080
4107
|
});
|
|
@@ -4086,6 +4113,70 @@ class RegistryResolver {
|
|
|
4086
4113
|
return updated;
|
|
4087
4114
|
}
|
|
4088
4115
|
/**
|
|
4116
|
+
* Resolve registry URL for a skill reference.
|
|
4117
|
+
*
|
|
4118
|
+
* Resolution order:
|
|
4119
|
+
* 1. Explicit CLI override (options.registry)
|
|
4120
|
+
* 2. Scoped skills → getRegistryUrl(scope)
|
|
4121
|
+
* 3. Unscoped skills → lock file registry (O(1), no network)
|
|
4122
|
+
* 4. Unscoped skills → probe skills.json registries (non-git-host, network)
|
|
4123
|
+
* 5. Default → PUBLIC_REGISTRY
|
|
4124
|
+
*/ async resolveRegistryUrl(ref, explicitRegistry) {
|
|
4125
|
+
if (explicitRegistry) return explicitRegistry;
|
|
4126
|
+
const parsed = parseSkillIdentifier(ref);
|
|
4127
|
+
if (parsed.scope) return getRegistryUrl(parsed.scope);
|
|
4128
|
+
// Fast path: lock file has registry URL
|
|
4129
|
+
const locked = this.lockManager.get(parsed.name);
|
|
4130
|
+
if (locked?.registry) return locked.registry;
|
|
4131
|
+
// Slow path: probe configured registries (skip git hosts)
|
|
4132
|
+
const registries = this.config.getRegistries();
|
|
4133
|
+
for (const [name, url] of Object.entries(registries))if (!this.isGitHostRegistry(name, url)) try {
|
|
4134
|
+
const client = new RegistryClient({
|
|
4135
|
+
registry: url
|
|
4136
|
+
});
|
|
4137
|
+
await client.getSkillInfo(parsed.fullName);
|
|
4138
|
+
return url; // Found it
|
|
4139
|
+
} catch {}
|
|
4140
|
+
return getRegistryUrl(null); // PUBLIC_REGISTRY
|
|
4141
|
+
}
|
|
4142
|
+
/**
|
|
4143
|
+
* Check if a registry entry is a git host (github, gitlab, etc.)
|
|
4144
|
+
* Git hosts are not skill registries and should be skipped during probe.
|
|
4145
|
+
*/ isGitHostRegistry(name, url) {
|
|
4146
|
+
const gitHostNames = new Set(Object.keys(DEFAULT_REGISTRIES));
|
|
4147
|
+
if (gitHostNames.has(name)) return true;
|
|
4148
|
+
const gitHostPatterns = [
|
|
4149
|
+
'github.com',
|
|
4150
|
+
'gitlab.com'
|
|
4151
|
+
];
|
|
4152
|
+
const normalizedUrl = url.toLowerCase();
|
|
4153
|
+
return gitHostPatterns.some((pattern)=>normalizedUrl.includes(pattern));
|
|
4154
|
+
}
|
|
4155
|
+
/**
|
|
4156
|
+
* Derive a registry name from a URL for storing in skills.json.registries.
|
|
4157
|
+
* Returns null for git hosts (already in DEFAULT_REGISTRIES).
|
|
4158
|
+
*/ deriveRegistryName(registryUrl) {
|
|
4159
|
+
// Skip git hosts
|
|
4160
|
+
if (this.isGitHostRegistry('', registryUrl)) return null;
|
|
4161
|
+
// Try known scope mapping first (e.g., kanyun registries)
|
|
4162
|
+
const scope = getScopeForRegistry(registryUrl);
|
|
4163
|
+
if (scope) return scope;
|
|
4164
|
+
// Use hostname as registry name
|
|
4165
|
+
try {
|
|
4166
|
+
const url = new URL(registryUrl);
|
|
4167
|
+
return url.hostname;
|
|
4168
|
+
} catch {
|
|
4169
|
+
return null;
|
|
4170
|
+
}
|
|
4171
|
+
}
|
|
4172
|
+
/**
|
|
4173
|
+
* Install skill for update flow. Uses installToAgents so registry refs are
|
|
4174
|
+
* routed correctly (Registry > HTTP > Git).
|
|
4175
|
+
*/ async installForUpdate(ref, targetAgents, options) {
|
|
4176
|
+
const { skill } = await this.installToAgents(ref, targetAgents, options);
|
|
4177
|
+
return skill;
|
|
4178
|
+
}
|
|
4179
|
+
/**
|
|
4089
4180
|
* List installed skills
|
|
4090
4181
|
*
|
|
4091
4182
|
* Checks both canonical (.agents/skills/) and legacy (.skills/) locations.
|
|
@@ -4126,6 +4217,24 @@ class RegistryResolver {
|
|
|
4126
4217
|
return skills;
|
|
4127
4218
|
}
|
|
4128
4219
|
/**
|
|
4220
|
+
* Detect which agents have a skill installed (symlink or copy)
|
|
4221
|
+
*
|
|
4222
|
+
* Scans all known agent directories to check if the skill exists there.
|
|
4223
|
+
* Excludes the canonical directory (.agents/skills/) to avoid false positives
|
|
4224
|
+
* from agents whose skillsDir overlaps with the canonical path (e.g. amp).
|
|
4225
|
+
*/ detectSkillAgents(skillName) {
|
|
4226
|
+
const canonicalDir = this.getCanonicalSkillsDir();
|
|
4227
|
+
const installed = [];
|
|
4228
|
+
for (const [type, config] of Object.entries(agents)){
|
|
4229
|
+
const agentBase = this.isGlobal ? config.globalSkillsDir : __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.projectRoot, config.skillsDir);
|
|
4230
|
+
// Skip agents whose skillsDir is the canonical directory itself
|
|
4231
|
+
if (__WEBPACK_EXTERNAL_MODULE_node_path__.resolve(agentBase) === __WEBPACK_EXTERNAL_MODULE_node_path__.resolve(canonicalDir)) continue;
|
|
4232
|
+
const agentSkillDir = __WEBPACK_EXTERNAL_MODULE_node_path__.join(agentBase, skillName);
|
|
4233
|
+
if (exists(agentSkillDir)) installed.push(type);
|
|
4234
|
+
}
|
|
4235
|
+
return installed;
|
|
4236
|
+
}
|
|
4237
|
+
/**
|
|
4129
4238
|
* Get installed skill information from a specific path
|
|
4130
4239
|
*/ getInstalledSkillFromPath(name, skillPath) {
|
|
4131
4240
|
if (!exists(skillPath)) return null;
|
|
@@ -4140,7 +4249,8 @@ class RegistryResolver {
|
|
|
4140
4249
|
path: skillPath,
|
|
4141
4250
|
version,
|
|
4142
4251
|
source: isLinked ? getRealPath(skillPath) : locked?.source || '',
|
|
4143
|
-
isLinked
|
|
4252
|
+
isLinked,
|
|
4253
|
+
agents: this.detectSkillAgents(name)
|
|
4144
4254
|
};
|
|
4145
4255
|
}
|
|
4146
4256
|
/**
|
|
@@ -4333,7 +4443,7 @@ class RegistryResolver {
|
|
|
4333
4443
|
/**
|
|
4334
4444
|
* Install skill from Git to multiple agents
|
|
4335
4445
|
*/ async installToAgentsFromGit(ref, targetAgents, options = {}) {
|
|
4336
|
-
const { save = true, mode = 'symlink' } = options;
|
|
4446
|
+
const { save = true, mode = 'symlink', registryContext } = options;
|
|
4337
4447
|
// Parse reference
|
|
4338
4448
|
const resolved = await this.resolver.resolve(ref);
|
|
4339
4449
|
const { parsed, repoUrl } = resolved;
|
|
@@ -4351,7 +4461,8 @@ class RegistryResolver {
|
|
|
4351
4461
|
const sourcePath = this.resolveSourcePath(cachePath, parsed);
|
|
4352
4462
|
// Get the real skill name from SKILL.md in cache
|
|
4353
4463
|
const metadata = this.getSkillMetadataFromDir(sourcePath);
|
|
4354
|
-
|
|
4464
|
+
// Priority: registryContext name > SKILL.md name > fallback from Git URL
|
|
4465
|
+
const skillName = registryContext?.skillName ?? metadata?.name ?? fallbackName;
|
|
4355
4466
|
const semanticVersion = metadata?.version ?? gitRef;
|
|
4356
4467
|
logger_logger["package"](`Installing ${skillName}@${gitRef} to ${targetAgents.length} agent(s)...`);
|
|
4357
4468
|
// Create Installer with custom installDir from config
|
|
@@ -4366,19 +4477,22 @@ class RegistryResolver {
|
|
|
4366
4477
|
mode: mode
|
|
4367
4478
|
});
|
|
4368
4479
|
// Update lock file (project mode only)
|
|
4369
|
-
if (!this.isGlobal)
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
|
|
4480
|
+
if (!this.isGlobal) {
|
|
4481
|
+
const lockSource = registryContext?.lockSource ?? `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? `/${parsed.subPath}` : ''}`;
|
|
4482
|
+
this.lockManager.lockSkill(skillName, {
|
|
4483
|
+
source: lockSource,
|
|
4484
|
+
version: semanticVersion,
|
|
4485
|
+
ref: gitRef,
|
|
4486
|
+
resolved: repoUrl,
|
|
4487
|
+
commit: cacheResult.commit,
|
|
4488
|
+
registry: registryContext?.registryUrl
|
|
4489
|
+
});
|
|
4490
|
+
}
|
|
4376
4491
|
// Update skills.json (project mode only)
|
|
4377
4492
|
if (!this.isGlobal && save) {
|
|
4378
4493
|
this.config.ensureExists();
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
this.config.addSkill(skillName, normalizedRef);
|
|
4494
|
+
const configRef = registryContext?.configRef ?? this.config.normalizeSkillRef(ref);
|
|
4495
|
+
this.config.addSkill(skillName, configRef);
|
|
4382
4496
|
}
|
|
4383
4497
|
// Count results
|
|
4384
4498
|
const successCount = Array.from(results.values()).filter((r)=>r.success).length;
|
|
@@ -4401,7 +4515,7 @@ class RegistryResolver {
|
|
|
4401
4515
|
/**
|
|
4402
4516
|
* Install skill from HTTP/OSS to multiple agents
|
|
4403
4517
|
*/ async installToAgentsFromHttp(ref, targetAgents, options = {}) {
|
|
4404
|
-
const { save = true, mode = 'symlink' } = options;
|
|
4518
|
+
const { save = true, mode = 'symlink', registryContext } = options;
|
|
4405
4519
|
// Parse HTTP reference
|
|
4406
4520
|
const resolved = await this.httpResolver.resolve(ref);
|
|
4407
4521
|
const { parsed, repoUrl, httpInfo } = resolved;
|
|
@@ -4418,7 +4532,8 @@ class RegistryResolver {
|
|
|
4418
4532
|
const sourcePath = this.cache.getCachePath(parsed, version);
|
|
4419
4533
|
// Get the real skill name from SKILL.md in cache
|
|
4420
4534
|
const metadata = this.getSkillMetadataFromDir(sourcePath);
|
|
4421
|
-
|
|
4535
|
+
// Priority: registryContext name > SKILL.md name > fallback from URL
|
|
4536
|
+
const skillName = registryContext?.skillName ?? metadata?.name ?? fallbackName;
|
|
4422
4537
|
const semanticVersion = metadata?.version ?? version;
|
|
4423
4538
|
logger_logger["package"](`Installing ${skillName}@${version} from ${httpInfo.host} to ${targetAgents.length} agent(s)...`);
|
|
4424
4539
|
// Create Installer with custom installDir from config
|
|
@@ -4433,17 +4548,22 @@ class RegistryResolver {
|
|
|
4433
4548
|
mode: mode
|
|
4434
4549
|
});
|
|
4435
4550
|
// Update lock file (project mode only)
|
|
4436
|
-
if (!this.isGlobal)
|
|
4437
|
-
|
|
4438
|
-
|
|
4439
|
-
|
|
4440
|
-
|
|
4441
|
-
|
|
4442
|
-
|
|
4551
|
+
if (!this.isGlobal) {
|
|
4552
|
+
const lockSource = registryContext?.lockSource ?? `http:${httpInfo.host}/${skillName}`;
|
|
4553
|
+
this.lockManager.lockSkill(skillName, {
|
|
4554
|
+
source: lockSource,
|
|
4555
|
+
version: semanticVersion,
|
|
4556
|
+
ref: version,
|
|
4557
|
+
resolved: repoUrl,
|
|
4558
|
+
commit: cacheResult.commit,
|
|
4559
|
+
registry: registryContext?.registryUrl
|
|
4560
|
+
});
|
|
4561
|
+
}
|
|
4443
4562
|
// Update skills.json (project mode only)
|
|
4444
4563
|
if (!this.isGlobal && save) {
|
|
4445
4564
|
this.config.ensureExists();
|
|
4446
|
-
|
|
4565
|
+
const configRef = registryContext?.configRef ?? ref;
|
|
4566
|
+
this.config.addSkill(skillName, configRef);
|
|
4447
4567
|
}
|
|
4448
4568
|
// Count results
|
|
4449
4569
|
const successCount = Array.from(results.values()).filter((r)=>r.success).length;
|
|
@@ -4474,7 +4594,7 @@ class RegistryResolver {
|
|
|
4474
4594
|
const { force = false, save = true, mode = 'symlink' } = options;
|
|
4475
4595
|
// Parse skill identifier and resolve registry URL once (single source of truth)
|
|
4476
4596
|
const parsed = parseSkillIdentifier(ref);
|
|
4477
|
-
const registryUrl = options.registry
|
|
4597
|
+
const registryUrl = await this.resolveRegistryUrl(ref, options.registry);
|
|
4478
4598
|
const client = new RegistryClient({
|
|
4479
4599
|
registry: registryUrl
|
|
4480
4600
|
});
|
|
@@ -4561,13 +4681,22 @@ class RegistryResolver {
|
|
|
4561
4681
|
version,
|
|
4562
4682
|
ref: version,
|
|
4563
4683
|
resolved: resolvedRegistryUrl,
|
|
4564
|
-
commit: resolved.integrity
|
|
4684
|
+
commit: resolved.integrity,
|
|
4685
|
+
registry: resolvedRegistryUrl
|
|
4565
4686
|
});
|
|
4566
4687
|
// 8. Update skills.json (project mode only)
|
|
4567
4688
|
if (!this.isGlobal && save) {
|
|
4568
4689
|
this.config.ensureExists();
|
|
4569
4690
|
// Save with full name for registry skills
|
|
4570
4691
|
this.config.addSkill(shortName, ref);
|
|
4692
|
+
// Save custom registry to skills.json.registries (for reinstall without lock file)
|
|
4693
|
+
if (options.registry) {
|
|
4694
|
+
const registryName = this.deriveRegistryName(options.registry);
|
|
4695
|
+
if (registryName) {
|
|
4696
|
+
this.config.addRegistry(registryName, options.registry);
|
|
4697
|
+
this.config.save();
|
|
4698
|
+
}
|
|
4699
|
+
}
|
|
4571
4700
|
}
|
|
4572
4701
|
// 9. Count results and log
|
|
4573
4702
|
const successCount = Array.from(results.values()).filter((r)=>r.success).length;
|
|
@@ -4607,16 +4736,41 @@ class RegistryResolver {
|
|
|
4607
4736
|
if (parsed.version && 'latest' !== parsed.version) throw new Error(`Version specifier not supported for web-published skills.\n'${parsed.fullName}' was published via web and does not support versioning.\nUse: reskill install ${parsed.fullName}`);
|
|
4608
4737
|
if (!source_url) throw new Error(`Missing source_url for web-published skill: ${parsed.fullName}`);
|
|
4609
4738
|
logger_logger["package"](`Installing ${parsed.fullName} from ${source_type} source...`);
|
|
4739
|
+
// Build registry context so downstream methods use the registry name
|
|
4740
|
+
// instead of deriving from the source URL (e.g., Git repo name)
|
|
4741
|
+
const shortName = getShortName(parsed.fullName);
|
|
4742
|
+
const registryUrl = await this.resolveRegistryUrl(parsed.fullName, options.registry);
|
|
4743
|
+
const registryContext = {
|
|
4744
|
+
skillName: shortName,
|
|
4745
|
+
configRef: parsed.fullName,
|
|
4746
|
+
lockSource: `registry:${parsed.fullName}`,
|
|
4747
|
+
registryUrl
|
|
4748
|
+
};
|
|
4749
|
+
const optionsWithContext = {
|
|
4750
|
+
...options,
|
|
4751
|
+
registryContext
|
|
4752
|
+
};
|
|
4753
|
+
// Save custom registry to skills.json.registries (for reinstall without lock file)
|
|
4754
|
+
if (!this.isGlobal && options.registry) {
|
|
4755
|
+
const registryName = this.deriveRegistryName(options.registry);
|
|
4756
|
+
if (registryName) {
|
|
4757
|
+
this.config.ensureExists();
|
|
4758
|
+
this.config.load();
|
|
4759
|
+
this.config.addRegistry(registryName, options.registry);
|
|
4760
|
+
this.config.save();
|
|
4761
|
+
}
|
|
4762
|
+
}
|
|
4610
4763
|
switch(source_type){
|
|
4611
4764
|
case 'github':
|
|
4612
4765
|
case 'gitlab':
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4766
|
+
{
|
|
4767
|
+
const gitRef = this.buildGitRefForWebPublished(source_type, source_url, skillInfo.skill_path, parsed);
|
|
4768
|
+
return this.installToAgentsFromGit(gitRef, targetAgents, optionsWithContext);
|
|
4769
|
+
}
|
|
4616
4770
|
case 'oss_url':
|
|
4617
4771
|
case 'custom_url':
|
|
4618
4772
|
// Direct download URL
|
|
4619
|
-
return this.installToAgentsFromHttp(source_url, targetAgents,
|
|
4773
|
+
return this.installToAgentsFromHttp(source_url, targetAgents, optionsWithContext);
|
|
4620
4774
|
case 'local':
|
|
4621
4775
|
// Download tarball via Registry API
|
|
4622
4776
|
return this.installFromRegistryLocal(parsed, targetAgents, options);
|
|
@@ -4625,13 +4779,36 @@ class RegistryResolver {
|
|
|
4625
4779
|
}
|
|
4626
4780
|
}
|
|
4627
4781
|
/**
|
|
4782
|
+
* Build a Git ref for web-published github/gitlab skills.
|
|
4783
|
+
*
|
|
4784
|
+
* When `skillPath` is provided (multi-skill repo), constructs a shorthand ref
|
|
4785
|
+
* like `github:owner/repo/skills/my-skill` so that only the sub-directory is
|
|
4786
|
+
* cached and installed.
|
|
4787
|
+
*
|
|
4788
|
+
* Fallback: if `parseGitUrl` fails (non-standard URL), appends `#shortName`
|
|
4789
|
+
* as a skill-name selector. The `#` fragment is extracted by
|
|
4790
|
+
* `GitResolver.parseRef()` as `parsed.skillName`, then matched against
|
|
4791
|
+
* SKILL.md `name` fields via `resolveSourcePath` / `discoverSkillsInDir`.
|
|
4792
|
+
* This differs from the subPath approach (directory-based) but works because
|
|
4793
|
+
* skill names typically match their directory basenames.
|
|
4794
|
+
*
|
|
4795
|
+
* Returns the raw `sourceUrl` when no `skillPath` is available.
|
|
4796
|
+
*/ buildGitRefForWebPublished(sourceType, sourceUrl, skillPath, parsed) {
|
|
4797
|
+
if (!skillPath) return sourceUrl;
|
|
4798
|
+
const urlParsed = parseGitUrl(sourceUrl);
|
|
4799
|
+
if (urlParsed) return `${sourceType}:${urlParsed.owner}/${urlParsed.repo}/${skillPath}`;
|
|
4800
|
+
const shortName = getShortName(parsed.fullName);
|
|
4801
|
+
if (shortName) return `${sourceUrl}#${shortName}`;
|
|
4802
|
+
return sourceUrl;
|
|
4803
|
+
}
|
|
4804
|
+
/**
|
|
4628
4805
|
* Install a skill published via "local folder" mode.
|
|
4629
4806
|
*
|
|
4630
4807
|
* Downloads tarball via RegistryClient (handles 302 redirects to signed OSS URLs),
|
|
4631
4808
|
* then extracts and installs using the same flow as registry source_type.
|
|
4632
4809
|
*/ async installFromRegistryLocal(parsed, targetAgents, options = {}) {
|
|
4633
4810
|
const { save = true, mode = 'symlink' } = options;
|
|
4634
|
-
const registryUrl =
|
|
4811
|
+
const registryUrl = await this.resolveRegistryUrl(parsed.fullName, options.registry);
|
|
4635
4812
|
const shortName = getShortName(parsed.fullName);
|
|
4636
4813
|
const version = 'latest';
|
|
4637
4814
|
// Download tarball via RegistryClient (handles auth + 302 redirect to signed URL)
|
|
@@ -4667,12 +4844,21 @@ class RegistryResolver {
|
|
|
4667
4844
|
version: semanticVersion,
|
|
4668
4845
|
ref: version,
|
|
4669
4846
|
resolved: registryUrl,
|
|
4670
|
-
commit: ''
|
|
4847
|
+
commit: '',
|
|
4848
|
+
registry: registryUrl
|
|
4671
4849
|
});
|
|
4672
4850
|
// Update skills.json (project mode only)
|
|
4673
4851
|
if (!this.isGlobal && save) {
|
|
4674
4852
|
this.config.ensureExists();
|
|
4675
4853
|
this.config.addSkill(skillName, parsed.fullName);
|
|
4854
|
+
// Save custom registry to skills.json.registries (for reinstall without lock file)
|
|
4855
|
+
if (options.registry) {
|
|
4856
|
+
const registryName = this.deriveRegistryName(options.registry);
|
|
4857
|
+
if (registryName) {
|
|
4858
|
+
this.config.addRegistry(registryName, options.registry);
|
|
4859
|
+
this.config.save();
|
|
4860
|
+
}
|
|
4861
|
+
}
|
|
4676
4862
|
}
|
|
4677
4863
|
return {
|
|
4678
4864
|
skill: {
|