99use Illuminate \Support \Arr ;
1010use Illuminate \Support \Collection ;
1111use Illuminate \Support \Str ;
12+ use InvalidArgumentException ;
1213use Laravel \Boost \Contracts \Agent ;
1314use Laravel \Boost \Contracts \McpClient ;
1415use Laravel \Boost \Install \Cli \DisplayHelper ;
@@ -118,7 +119,7 @@ private function collectInstallationPreferences(): void
118119 {
119120 $ this ->selectedBoostFeatures = $ this ->selectBoostFeatures ();
120121 $ this ->enforceTests = $ this ->determineTestEnforcement (ask: false );
121- $ this ->selectedTargetMcpClient = $ this ->selectTargetIdes ();
122+ $ this ->selectedTargetMcpClient = $ this ->selectTargetMcpClients ();
122123 $ this ->selectedTargetAgents = $ this ->selectTargetAgents ();
123124 }
124125
@@ -143,9 +144,9 @@ private function discoverTools(): array
143144 ->name ('*.php ' );
144145
145146 foreach ($ finder as $ toolFile ) {
146- $ fqdn = 'Laravel \\Boost \\Mcp \\Tools \\' .$ toolFile ->getBasename ('.php ' );
147- if (class_exists ($ fqdn )) {
148- $ tools [$ fqdn ] = Str::headline ($ toolFile ->getBasename ('.php ' ));
147+ $ fullyClassifiedClassName = 'Laravel \\Boost \\Mcp \\Tools \\' .$ toolFile ->getBasename ('.php ' );
148+ if (class_exists ($ fullyClassifiedClassName )) {
149+ $ tools [$ fullyClassifiedClassName ] = Str::headline ($ toolFile ->getBasename ('.php ' ));
149150 }
150151 }
151152
@@ -260,14 +261,14 @@ protected function boostToolsToDisable(): array
260261 /**
261262 * @return Collection<int, CodeEnvironment>
262263 */
263- private function selectTargetIdes (): Collection
264+ private function selectTargetMcpClients (): Collection
264265 {
265266 if (! $ this ->shouldInstallMcp () && ! $ this ->shouldInstallHerdMcp ()) {
266267 return collect ();
267268 }
268269
269270 return $ this ->selectCodeEnvironments (
270- ' ide ' ,
271+ McpClient::class ,
271272 sprintf ('Which code editors do you use in %s? ' , $ this ->projectName )
272273 );
273274 }
@@ -282,29 +283,47 @@ private function selectTargetAgents(): Collection
282283 }
283284
284285 return $ this ->selectCodeEnvironments (
285- ' agent ' ,
286+ Agent::class ,
286287 sprintf ('Which agents need AI guidelines for %s? ' , $ this ->projectName )
287288 );
288289 }
289290
291+ /**
292+ * Get configuration settings for contract-specific selection behavior.
293+ *
294+ * @param string $contractClass
295+ * @return array{scroll: int, required: bool, displayMethod: string}
296+ */
297+ private function getSelectionConfig (string $ contractClass ): array
298+ {
299+ return match ($ contractClass ) {
300+ Agent::class => ['scroll ' => 4 , 'required ' => false , 'displayMethod ' => 'agentName ' ],
301+ McpClient::class => ['scroll ' => 5 , 'required ' => true , 'displayMethod ' => 'displayName ' ],
302+ default => throw new InvalidArgumentException ("Unsupported contract class: {$ contractClass }" ),
303+ };
304+ }
305+
290306 /**
291307 * @return Collection<int, CodeEnvironment>
292308 */
293- private function selectCodeEnvironments (string $ type , string $ label ): Collection
309+ private function selectCodeEnvironments (string $ contractClass , string $ label ): Collection
294310 {
295311 $ allEnvironments = $ this ->codeEnvironmentsDetector ->getCodeEnvironments ();
312+ $ config = $ this ->getSelectionConfig ($ contractClass );
296313
297- $ availableEnvironments = $ allEnvironments ->filter (function (CodeEnvironment $ environment ) use ($ type ) {
298- return ($ type === 'ide ' && $ environment ->isMcpClient ()) ||
299- ($ type === 'agent ' && $ environment ->IsAgent ());
314+ $ availableEnvironments = $ allEnvironments ->filter (function (CodeEnvironment $ environment ) use ($ contractClass ) {
315+ return $ environment instanceof $ contractClass ;
300316 });
301317
302318 if ($ availableEnvironments ->isEmpty ()) {
303319 return collect ();
304320 }
305321
306- $ options = $ availableEnvironments ->mapWithKeys (function (CodeEnvironment $ environment ) {
307- return [get_class ($ environment ) => $ environment ->displayName ()];
322+ $ options = $ availableEnvironments ->mapWithKeys (function (CodeEnvironment $ environment ) use ($ config ) {
323+ $ displayMethod = $ config ['displayMethod ' ];
324+ $ displayText = $ environment ->{$ displayMethod }();
325+
326+ return [get_class ($ environment ) => $ displayText ];
308327 })->sort ();
309328
310329 $ detectedClasses = [];
@@ -314,8 +333,7 @@ private function selectCodeEnvironments(string $type, string $label): Collection
314333 ));
315334
316335 foreach ($ installedEnvNames as $ envKey ) {
317- $ matchingEnv = $ availableEnvironments ->first (fn (CodeEnvironment $ env ) => strtolower ($ envKey ) === strtolower ($ env ->name ())
318- );
336+ $ matchingEnv = $ availableEnvironments ->first (fn (CodeEnvironment $ env ) => strtolower ($ envKey ) === strtolower ($ env ->name ()));
319337 if ($ matchingEnv ) {
320338 $ detectedClasses [] = get_class ($ matchingEnv );
321339 }
@@ -325,10 +343,15 @@ private function selectCodeEnvironments(string $type, string $label): Collection
325343 label: $ label ,
326344 options: $ options ->toArray (),
327345 default: array_unique ($ detectedClasses ),
328- scroll: $ type === ' ide ' ? 5 : 4 ,
329- required: $ type === ' ide ' ,
346+ scroll: $ config [ ' scroll ' ] ,
347+ required: $ config [ ' required ' ] ,
330348 hint: empty ($ detectedClasses ) ? null : sprintf ('Auto-detected %s for you ' ,
331- Arr::join (array_map (fn ($ className ) => $ availableEnvironments ->first (fn ($ env ) => get_class ($ env ) === $ className )->displayName (), $ detectedClasses ), ', ' , ' & ' )
349+ Arr::join (array_map (function ($ className ) use ($ availableEnvironments , $ config ) {
350+ $ env = $ availableEnvironments ->first (fn ($ env ) => get_class ($ env ) === $ className );
351+ $ displayMethod = $ config ['displayMethod ' ];
352+
353+ return $ env ->{$ displayMethod }();
354+ }, $ detectedClasses ), ', ' , ' & ' )
332355 )
333356 ))->sort ();
334357
0 commit comments