what-devtools-mcp 0.11.6 → 0.11.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/tools-agent.js +46 -2
package/package.json
CHANGED
package/src/tools-agent.js
CHANGED
|
@@ -119,6 +119,34 @@ effect(() => {
|
|
|
119
119
|
|
|
120
120
|
// Good — stable key:
|
|
121
121
|
<For each={items()}>{item => <li key={item.id}>{item.name}</li>}</For>`,
|
|
122
|
+
},
|
|
123
|
+
ERR_UNSAFE_REDIRECT: {
|
|
124
|
+
code: 'ERR_UNSAFE_REDIRECT',
|
|
125
|
+
severity: 'error',
|
|
126
|
+
diagnosis: 'redirect() was given a target that can leave your origin: a protocol-relative ("//host"), backslash-smuggled ("/\\host") or javascript:/data: URL. Reaching it from user input is an open redirect.',
|
|
127
|
+
suggestedFix: 'redirect() accepts same-origin paths and http:, https:, mailto: or tel: URLs only. Check a user-supplied target against an allowlist before passing it.',
|
|
128
|
+
codeExample: `// Bad - a user-controlled target can leave your origin:
|
|
129
|
+
redirect(query.next);
|
|
130
|
+
|
|
131
|
+
// Fix - allowlist the target first:
|
|
132
|
+
redirect(ALLOWED.has(query.next) ? query.next : '/');`,
|
|
133
|
+
},
|
|
134
|
+
ERR_REDIRECT_NOT_CAUGHT: {
|
|
135
|
+
code: 'ERR_REDIRECT_NOT_CAUGHT',
|
|
136
|
+
severity: 'error',
|
|
137
|
+
diagnosis: 'A redirect() navigation signal surfaced as an uncaught error, so nothing performed the navigation. redirect() is caught in two places only: route middleware, and a component body. An event handler, a promise callback or a timer runs long after both, and a try/catch around the call swallows the signal.',
|
|
138
|
+
suggestedFix: 'From an event handler, a promise callback or a timer, call navigate(to) instead. If the call is inside a try/catch, rethrow anything whose name is RouterRedirect.',
|
|
139
|
+
codeExample: `// Bad - an event handler runs after the render the Router caught:
|
|
140
|
+
<button onclick={() => redirect('/login')}>Sign in</button>
|
|
141
|
+
|
|
142
|
+
// Fix - navigate() from a handler:
|
|
143
|
+
<button onclick={() => navigate('/login')}>Sign in</button>
|
|
144
|
+
|
|
145
|
+
// Fix - redirect() from a component body, which the Router catches:
|
|
146
|
+
function Private() {
|
|
147
|
+
if (!user()) redirect('/login');
|
|
148
|
+
return <Secret />;
|
|
149
|
+
}`,
|
|
122
150
|
},
|
|
123
151
|
HINT_PREFER_COMPUTED: {
|
|
124
152
|
code: 'HINT_PREFER_COMPUTED',
|
|
@@ -1063,9 +1091,25 @@ export function registerAgentTools(server, bridge) {
|
|
|
1063
1091
|
'what_fix',
|
|
1064
1092
|
'Given a What Framework error code, get diagnosis, suggested fix, and code example. Works offline — no browser needed.',
|
|
1065
1093
|
{
|
|
1066
|
-
error: z.string().describe('Error code (e.g., "ERR_INFINITE_EFFECT") or error message text'),
|
|
1094
|
+
error: z.string().optional().describe('Error code (e.g., "ERR_INFINITE_EFFECT") or error message text'),
|
|
1095
|
+
// `errorCode` is an accepted alias, not a second parameter. Every CLAUDE.md
|
|
1096
|
+
// this project has ever scaffolded documents `what_fix {errorCode}` while
|
|
1097
|
+
// the schema only accepted `error`, so the tool the guide calls a "hidden
|
|
1098
|
+
// gem" and tells agents to reach for FIRST returned a hard validation
|
|
1099
|
+
// error. The docs are fixed, but those CLAUDE.md files are already sitting
|
|
1100
|
+
// in users' repos, so the alias stays permanently.
|
|
1101
|
+
errorCode: z.string().optional().describe('Alias for `error`, accepted for compatibility with older scaffolded CLAUDE.md files'),
|
|
1067
1102
|
},
|
|
1068
|
-
async ({ error
|
|
1103
|
+
async ({ error, errorCode }) => {
|
|
1104
|
+
const errorInput = error ?? errorCode;
|
|
1105
|
+
if (!errorInput) {
|
|
1106
|
+
return {
|
|
1107
|
+
content: [{
|
|
1108
|
+
type: 'text',
|
|
1109
|
+
text: 'what_fix needs an error code or message. Example: what_fix({ error: "ERR_INFINITE_EFFECT" }).',
|
|
1110
|
+
}],
|
|
1111
|
+
};
|
|
1112
|
+
}
|
|
1069
1113
|
// Try exact code match first
|
|
1070
1114
|
let entry = ERROR_DATABASE[errorInput];
|
|
1071
1115
|
|