(host: SlashCommandHost, rawArgs: string)
| 45 | } |
| 46 | |
| 47 | export async function handlePluginsCommand(host: SlashCommandHost, rawArgs: string): Promise<void> { |
| 48 | const args = rawArgs.trim().split(/\s+/).filter((part) => part.length > 0); |
| 49 | const sub = args[0]; |
| 50 | const rest = args.slice(1); |
| 51 | const session = host.requireSession(); |
| 52 | |
| 53 | try { |
| 54 | if (sub === undefined) { |
| 55 | await showPluginsPicker(host); |
| 56 | return; |
| 57 | } |
| 58 | if (sub === 'list') { |
| 59 | await renderPluginsList(host); |
| 60 | return; |
| 61 | } |
| 62 | if (sub === 'install') { |
| 63 | const source = rest.join(' ').trim(); |
| 64 | if (source.length === 0) { |
| 65 | host.showError('Usage: /plugins install <local-path-or-zip-url>'); |
| 66 | return; |
| 67 | } |
| 68 | if (!(await confirmInstallTrust(host, source, isOfficialPluginSource(source)))) { |
| 69 | host.showStatus('Install cancelled.'); |
| 70 | return; |
| 71 | } |
| 72 | const spinner = host.showProgressSpinner(`Installing plugin from ${truncateForStatus(source)}…`); |
| 73 | try { |
| 74 | await installPluginFromSource(host, source); |
| 75 | spinner.stop({ ok: true, label: `Install finished — see details below.` }); |
| 76 | } catch (error) { |
| 77 | spinner.stop({ ok: false, label: `Install failed: ${formatErrorMessage(error)}` }); |
| 78 | throw error; |
| 79 | } |
| 80 | return; |
| 81 | } |
| 82 | if (sub === 'marketplace') { |
| 83 | const marketplaceSource = rest.join(' ').trim() || undefined; |
| 84 | await showPluginsPicker(host, { |
| 85 | // Custom marketplaces often omit `tier`, so their entries land on the |
| 86 | // Third-party tab (entry.tier !== 'official'). Open there when a custom |
| 87 | // source is supplied; otherwise the default catalog's official entries |
| 88 | // make Official the right landing tab. |
| 89 | initialTab: marketplaceSource === undefined ? 'official' : 'third-party', |
| 90 | marketplaceSource, |
| 91 | }); |
| 92 | return; |
| 93 | } |
| 94 | if (sub === 'info') { |
| 95 | const id = rest[0]; |
| 96 | if (id === undefined) { |
| 97 | await showPluginsPicker(host); |
| 98 | return; |
| 99 | } |
| 100 | await renderPluginInfo(host, id); |
| 101 | return; |
| 102 | } |
| 103 | if (sub === 'mcp') { |
| 104 | const action = rest[0]; |
no test coverage detected