Merge pull request #2719 from QwenLM/feat/npm-extension-installation

feat(extension): Add npm registry support for extension installation
This commit is contained in:
tanzhenxin 2026-04-01 16:18:17 +08:00 committed by GitHub
commit 2eb2f4e319
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 924 additions and 12 deletions

View file

@ -27,6 +27,7 @@ interface InstallArgs {
autoUpdate?: boolean;
allowPreRelease?: boolean;
consent?: boolean;
registry?: string;
}
export async function handleInstall(args: InstallArgs) {
@ -35,7 +36,8 @@ export async function handleInstall(args: InstallArgs) {
if (
installMetadata.type !== 'git' &&
installMetadata.type !== 'github-release'
installMetadata.type !== 'github-release' &&
installMetadata.type !== 'npm'
) {
if (args.ref || args.autoUpdate) {
throw new Error(
@ -46,6 +48,22 @@ export async function handleInstall(args: InstallArgs) {
}
}
if (installMetadata.type === 'npm' && args.ref) {
throw new Error(
t(
'--ref is not applicable for npm extensions. Use @version suffix instead (e.g. @scope/package@1.2.0).',
),
);
}
if (installMetadata.type !== 'npm' && args.registry) {
throw new Error(t('--registry is only applicable for npm extensions.'));
}
if (installMetadata.type === 'npm' && args.registry) {
installMetadata.registryUrl = args.registry;
}
const requestConsent = args.consent
? () => Promise.resolve()
: requestConsentOrFail.bind(null, requestConsentNonInteractive);
@ -83,7 +101,7 @@ export async function handleInstall(args: InstallArgs) {
export const installCommand: CommandModule = {
command: 'install <source>',
describe: t(
'Installs an extension from a git repository URL, local path, or claude marketplace (marketplace-url:plugin-name).',
'Installs an extension from a git repository URL, local path, scoped npm package (@scope/name), or claude marketplace (marketplace-url:plugin-name).',
),
builder: (yargs) =>
yargs
@ -106,6 +124,10 @@ export const installCommand: CommandModule = {
describe: t('Enable pre-release versions for this extension.'),
type: 'boolean',
})
.option('registry', {
describe: t('Custom npm registry URL (only for npm extensions).'),
type: 'string',
})
.option('consent', {
describe: t(
'Acknowledge the security risks of installing an extension and skip the confirmation prompt.',
@ -126,6 +148,7 @@ export const installCommand: CommandModule = {
autoUpdate: argv['auto-update'] as boolean | undefined,
allowPreRelease: argv['pre-release'] as boolean | undefined,
consent: argv['consent'] as boolean | undefined,
registry: argv['registry'] as string | undefined,
});
},
};