Skip to content

Commit e1fcbe7

Browse files
committed
Properly handle prompt exceptions
1 parent 44da21a commit e1fcbe7

23 files changed

Lines changed: 530 additions & 6 deletions

src/Prompts/AbstractPrompt.php

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
namespace Synapse\Prompts;
55

66
use Cake\Core\Configure;
7+
use Mcp\Exception\PromptGetException;
78

89
/**
910
* Abstract Prompt Base Class
@@ -30,4 +31,82 @@ public function __construct()
3031
$this->cakephpVersion = Configure::read('Synapse.prompts.cakephp_version', '5.x');
3132
$this->phpVersion = Configure::read('Synapse.prompts.php_version', '8.2');
3233
}
34+
35+
/**
36+
* Validate that a parameter value is one of the allowed values
37+
*
38+
* @param string $value The parameter value
39+
* @param array<string> $allowed Allowed values
40+
* @param string $paramName The parameter name (for error message)
41+
* @param string $promptName The prompt name (for error message)
42+
* @throws \Mcp\Exception\PromptGetException
43+
*/
44+
protected function validateEnumParameter(
45+
string $value,
46+
array $allowed,
47+
string $paramName,
48+
string $promptName,
49+
): void {
50+
if (!in_array($value, $allowed, true)) {
51+
$allowedStr = implode(', ', $allowed);
52+
throw new PromptGetException(
53+
sprintf("Invalid value for parameter '%s': '%s'. ", $paramName, $value) .
54+
sprintf('Expected one of: %s. ', $allowedStr) .
55+
'Prompt: ' . $promptName,
56+
);
57+
}
58+
}
59+
60+
/**
61+
* Validate that a parameter is not empty
62+
*
63+
* @param string $value The parameter value
64+
* @param string $paramName The parameter name (for error message)
65+
* @param string $promptName The prompt name (for error message)
66+
* @throws \Mcp\Exception\PromptGetException
67+
*/
68+
protected function validateNonEmptyParameter(
69+
string $value,
70+
string $paramName,
71+
string $promptName,
72+
): void {
73+
if ($value === '' || $value === '0') {
74+
throw new PromptGetException(
75+
sprintf("Parameter '%s' cannot be empty. Prompt: %s", $paramName, $promptName),
76+
);
77+
}
78+
}
79+
80+
/**
81+
* Validate comma-separated values against allowed list
82+
*
83+
* @param string $value Comma-separated values
84+
* @param array<string> $allowed Allowed values
85+
* @param string $paramName The parameter name (for error message)
86+
* @param string $promptName The prompt name (for error message)
87+
* @throws \Mcp\Exception\PromptGetException
88+
*/
89+
protected function validateCommaSeparatedParameter(
90+
string $value,
91+
array $allowed,
92+
string $paramName,
93+
string $promptName,
94+
): void {
95+
if ($value === '' || $value === '0') {
96+
return;
97+
}
98+
99+
$values = array_map('trim', explode(',', $value));
100+
$invalid = array_diff($values, $allowed);
101+
102+
if ($invalid !== []) {
103+
$invalidStr = implode(', ', $invalid);
104+
$allowedStr = implode(', ', $allowed);
105+
throw new PromptGetException(
106+
sprintf("Invalid values for parameter '%s': %s. ", $paramName, $invalidStr) .
107+
sprintf('Expected one of: %s. ', $allowedStr) .
108+
'Prompt: ' . $promptName,
109+
);
110+
}
111+
}
33112
}

src/Prompts/CodeReviewerPrompt.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ public function handle(
3030
string $code,
3131
string $focus = 'all',
3232
): array {
33+
$this->validateEnumParameter(
34+
$focus,
35+
['conventions', 'security', 'performance', 'testing', 'all'],
36+
'focus',
37+
'code-reviewer',
38+
);
39+
3340
return [
3441
new PromptMessage(
3542
role: Role::User,

src/Prompts/DatabaseExplorerPrompt.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@ public function handle(
3030
string $table,
3131
string $show = 'all',
3232
): array {
33+
$this->validateNonEmptyParameter($table, 'table', 'database-explorer');
34+
$this->validateEnumParameter(
35+
$show,
36+
['schema', 'data', 'relationships', 'all'],
37+
'show',
38+
'database-explorer',
39+
);
40+
3341
return [
3442
new PromptMessage(
3543
role: Role::User,

src/Prompts/DebugHelperPrompt.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,15 @@ public function handle(
3030
string $error,
3131
string $context = '',
3232
): array {
33+
if ($context !== '' && $context !== '0') {
34+
$this->validateEnumParameter(
35+
$context,
36+
['controller', 'model', 'database', 'view'],
37+
'context',
38+
'debug-helper',
39+
);
40+
}
41+
3342
$contextHint = $context !== '' && $context !== '0' ? sprintf(' in the %s layer', $context) : '';
3443

3544
return [

src/Prompts/DocumentationExpertPrompt.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ public function handle(
3030
string $topic,
3131
string $depth = 'intermediate',
3232
): array {
33+
$this->validateEnumParameter(
34+
$depth,
35+
['basic', 'intermediate', 'advanced'],
36+
'depth',
37+
'documentation-expert',
38+
);
39+
3340
return match ($depth) {
3441
'basic' => $this->getBasicDocumentationMessages($topic),
3542
'advanced' => $this->getAdvancedDocumentationMessages($topic),

src/Prompts/FeatureBuilderPrompt.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ public function handle(
3030
string $feature,
3131
string $component = 'full-stack',
3232
): array {
33+
$this->validateEnumParameter(
34+
$component,
35+
['controller', 'model', 'behavior', 'helper', 'middleware', 'command', 'full-stack'],
36+
'component',
37+
'feature-builder',
38+
);
39+
3340
return [
3441
new PromptMessage(
3542
role: Role::User,

src/Prompts/MigrationGuidePrompt.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ public function handle(
3232
string $toVersion,
3333
string $area = 'general',
3434
): array {
35+
$this->validateNonEmptyParameter($fromVersion, 'fromVersion', 'migration-guide');
36+
$this->validateNonEmptyParameter($toVersion, 'toVersion', 'migration-guide');
37+
3538
return [
3639
new PromptMessage(
3740
role: Role::User,

src/Prompts/OrmQueryHelperPrompt.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ public function handle(
3030
string $queryGoal,
3131
string $tables = '',
3232
): array {
33+
$this->validateNonEmptyParameter($queryGoal, 'queryGoal', 'orm-query-helper');
34+
3335
$tablesHint = $tables !== '' && $tables !== '0' ? '
3436
Tables involved: ' . $tables : '';
3537

src/Prompts/PerformanceAnalyzerPrompt.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ public function handle(
3030
string $concern,
3131
string $context = '',
3232
): array {
33+
$this->validateNonEmptyParameter($concern, 'concern', 'performance-analyzer');
34+
3335
$contextSection = $context !== '' && $context !== '0' ? '
3436
3537
Context:

src/Prompts/QualityAssurancePrompt.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,21 @@ public function handle(
5555
string $context = 'all',
5656
string $tools = 'all',
5757
): array {
58+
$this->validateEnumParameter(
59+
$context,
60+
['guidelines', 'integration', 'troubleshooting', 'all'],
61+
'context',
62+
'quality-assurance',
63+
);
64+
65+
$allowedTools = array_keys($this->qualityTools);
66+
$this->validateCommaSeparatedParameter(
67+
$tools,
68+
array_merge($allowedTools, ['all']),
69+
'tools',
70+
'quality-assurance',
71+
);
72+
5873
$enabledTools = $this->getEnabledTools($tools);
5974

6075
if ($enabledTools === []) {

0 commit comments

Comments
 (0)