({
plugin,
marketplace
}: {
plugin: LoadedPlugin;
marketplace: string;
})
| 192 | |
| 193 | // Component to display installed plugin components |
| 194 | function PluginComponentsDisplay({ |
| 195 | plugin, |
| 196 | marketplace |
| 197 | }: { |
| 198 | plugin: LoadedPlugin; |
| 199 | marketplace: string; |
| 200 | }): React.ReactNode { |
| 201 | const [components, setComponents] = useState<{ |
| 202 | commands?: string | string[] | Record<string, unknown> | null; |
| 203 | agents?: string | string[] | Record<string, unknown> | null; |
| 204 | skills?: string | string[] | Record<string, unknown> | null; |
| 205 | hooks?: unknown; |
| 206 | mcpServers?: unknown; |
| 207 | } | null>(null); |
| 208 | const [loading, setLoading] = useState(true); |
| 209 | const [error, setError] = useState<string | null>(null); |
| 210 | useEffect(() => { |
| 211 | async function loadComponents() { |
| 212 | try { |
| 213 | // Built-in plugins don't have a marketplace entry — read from the |
| 214 | // registered definition directly. |
| 215 | if (marketplace === 'builtin') { |
| 216 | const builtinDef = getBuiltinPluginDefinition(plugin.name); |
| 217 | if (builtinDef) { |
| 218 | const skillNames = builtinDef.skills?.map(s => s.name) ?? []; |
| 219 | const hookEvents = builtinDef.hooks ? Object.keys(builtinDef.hooks) : []; |
| 220 | const mcpServerNames = builtinDef.mcpServers ? Object.keys(builtinDef.mcpServers) : []; |
| 221 | setComponents({ |
| 222 | commands: null, |
| 223 | agents: null, |
| 224 | skills: skillNames.length > 0 ? skillNames : null, |
| 225 | hooks: hookEvents.length > 0 ? hookEvents : null, |
| 226 | mcpServers: mcpServerNames.length > 0 ? mcpServerNames : null |
| 227 | }); |
| 228 | } else { |
| 229 | setError(`Built-in plugin ${plugin.name} not found`); |
| 230 | } |
| 231 | setLoading(false); |
| 232 | return; |
| 233 | } |
| 234 | const marketplaceData = await getMarketplace(marketplace); |
| 235 | // Find the plugin entry in the array |
| 236 | const pluginEntry = marketplaceData.plugins.find(p => p.name === plugin.name); |
| 237 | if (pluginEntry) { |
| 238 | // Combine commands from both sources |
| 239 | const commandPathList = []; |
| 240 | if (plugin.commandsPath) { |
| 241 | commandPathList.push(plugin.commandsPath); |
| 242 | } |
| 243 | if (plugin.commandsPaths) { |
| 244 | commandPathList.push(...plugin.commandsPaths); |
| 245 | } |
| 246 | |
| 247 | // Get base file names from all command paths |
| 248 | const commandList: string[] = []; |
| 249 | for (const commandPath of commandPathList) { |
| 250 | if (typeof commandPath === 'string') { |
| 251 | // commandPath is already a full path |
nothing calls this directly
no test coverage detected