chrome-devtools-mcp-for-extension 0.9.24 → 0.9.26
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.
|
@@ -222,14 +222,62 @@ export const askChatGPTWeb = defineTool({
|
|
|
222
222
|
});
|
|
223
223
|
if (deepResearchEnabled) {
|
|
224
224
|
response.appendResponseLine('✅ DeepResearchモード有効化完了');
|
|
225
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
225
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
226
|
+
// Verify mode was actually enabled (check for composer-pill button)
|
|
227
|
+
const verified = await page.evaluate(() => {
|
|
228
|
+
const DEEP_RESEARCH_PATTERN = /リサーチ|deep\s*research|ディープ\s*リサーチ|深度研究|深入研究/i;
|
|
229
|
+
const promptTextarea = document.querySelector('#prompt-textarea');
|
|
230
|
+
if (promptTextarea) {
|
|
231
|
+
const form = promptTextarea.closest('form');
|
|
232
|
+
if (form) {
|
|
233
|
+
const pillButton = Array.from(form.querySelectorAll('button')).find((btn) => {
|
|
234
|
+
const text = btn.textContent?.trim() || '';
|
|
235
|
+
const ariaLabel = btn.getAttribute('aria-label') || '';
|
|
236
|
+
return (btn.className.includes('composer-pill') &&
|
|
237
|
+
DEEP_RESEARCH_PATTERN.test(text + ' ' + ariaLabel));
|
|
238
|
+
});
|
|
239
|
+
return !!pillButton;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return false;
|
|
243
|
+
});
|
|
244
|
+
if (verified) {
|
|
245
|
+
response.appendResponseLine('✅ モード確認完了: DeepResearch有効(composer-pill検出)');
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
response.appendResponseLine('⚠️ DeepResearchモードの確認に失敗しました');
|
|
249
|
+
}
|
|
226
250
|
}
|
|
227
251
|
else {
|
|
228
252
|
response.appendResponseLine('⚠️ DeepResearchオプションが見つかりませんでした');
|
|
229
253
|
}
|
|
230
254
|
}
|
|
231
255
|
}
|
|
232
|
-
// Step 4: Send question
|
|
256
|
+
// Step 4: Send question (with final mode verification)
|
|
257
|
+
if (useDeepResearch) {
|
|
258
|
+
const finalCheck = await page.evaluate(() => {
|
|
259
|
+
const DEEP_RESEARCH_PATTERN = /リサーチ|deep\s*research|ディープ\s*リサーチ|深度研究|深入研究/i;
|
|
260
|
+
const promptTextarea = document.querySelector('#prompt-textarea');
|
|
261
|
+
if (promptTextarea) {
|
|
262
|
+
const form = promptTextarea.closest('form');
|
|
263
|
+
if (form) {
|
|
264
|
+
const pillButton = Array.from(form.querySelectorAll('button')).find((btn) => {
|
|
265
|
+
const text = btn.textContent?.trim() || '';
|
|
266
|
+
const ariaLabel = btn.getAttribute('aria-label') || '';
|
|
267
|
+
return (btn.className.includes('composer-pill') &&
|
|
268
|
+
DEEP_RESEARCH_PATTERN.test(text + ' ' + ariaLabel));
|
|
269
|
+
});
|
|
270
|
+
return !!pillButton;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return false;
|
|
274
|
+
});
|
|
275
|
+
if (!finalCheck) {
|
|
276
|
+
response.appendResponseLine('❌ エラー: DeepResearchモードが無効です(composer-pill未検出)。送信を中止します。');
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
response.appendResponseLine('✅ 送信前確認: DeepResearchモード有効(composer-pill検出)');
|
|
280
|
+
}
|
|
233
281
|
response.appendResponseLine('質問を送信中...');
|
|
234
282
|
const questionSent = await page.evaluate((questionText) => {
|
|
235
283
|
const prosemirror = document.querySelector('.ProseMirror[contenteditable="true"]');
|
|
@@ -129,33 +129,37 @@ function isCodeRelatedQuestion(question) {
|
|
|
129
129
|
async function detectDeepResearchMode(page) {
|
|
130
130
|
return await page.evaluate(() => {
|
|
131
131
|
// Multi-language patterns for DeepResearch
|
|
132
|
-
const DEEP_RESEARCH_PATTERN =
|
|
133
|
-
//
|
|
134
|
-
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
132
|
+
const DEEP_RESEARCH_PATTERN = /リサーチ|deep\s*research|ディープ\s*リサーチ|深度研究|深入研究/i;
|
|
133
|
+
// Step 1: Check for the "リサーチ" pill button near prompt (MOST RELIABLE)
|
|
134
|
+
// When DeepResearch is ON, a pill button appears in the composer form
|
|
135
|
+
const promptTextarea = document.querySelector('#prompt-textarea');
|
|
136
|
+
if (promptTextarea) {
|
|
137
|
+
const form = promptTextarea.closest('form');
|
|
138
|
+
if (form) {
|
|
139
|
+
const pillButton = Array.from(form.querySelectorAll('button')).find((btn) => {
|
|
140
|
+
const text = btn.textContent?.trim() || '';
|
|
141
|
+
const ariaLabel = btn.getAttribute('aria-label') || '';
|
|
142
|
+
// Check for pill button with research text
|
|
143
|
+
return (btn.className.includes('composer-pill') &&
|
|
144
|
+
DEEP_RESEARCH_PATTERN.test(text + ' ' + ariaLabel));
|
|
145
|
+
});
|
|
146
|
+
if (pillButton) {
|
|
147
|
+
const text = pillButton.textContent?.trim() || '';
|
|
148
|
+
return {
|
|
149
|
+
isEnabled: true,
|
|
150
|
+
indicator: `composer-pill: "${text}"`,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
}
|
|
150
154
|
}
|
|
151
|
-
// Step 2: Try data-testid selectors
|
|
155
|
+
// Step 2: Try data-testid selectors
|
|
152
156
|
const dataTestIdSelectors = [
|
|
153
157
|
'[data-testid*="deep-research"]',
|
|
154
158
|
'[data-testid*="deepresearch"]',
|
|
155
159
|
'[data-testid*="research-mode"]',
|
|
156
160
|
];
|
|
157
161
|
for (const selector of dataTestIdSelectors) {
|
|
158
|
-
const element =
|
|
162
|
+
const element = document.querySelector(selector);
|
|
159
163
|
if (element) {
|
|
160
164
|
return {
|
|
161
165
|
isEnabled: true,
|
|
@@ -170,7 +174,7 @@ async function detectDeepResearchMode(page) {
|
|
|
170
174
|
'[aria-checked="true"][role="menuitemradio"]',
|
|
171
175
|
];
|
|
172
176
|
for (const selector of ariaSelectors) {
|
|
173
|
-
const elements = Array.from(
|
|
177
|
+
const elements = Array.from(document.querySelectorAll(selector));
|
|
174
178
|
for (const element of elements) {
|
|
175
179
|
const ariaLabel = element.getAttribute('aria-label') || '';
|
|
176
180
|
const role = element.getAttribute('role') || '';
|
|
@@ -195,25 +199,13 @@ async function detectDeepResearchMode(page) {
|
|
|
195
199
|
}
|
|
196
200
|
}
|
|
197
201
|
// Step 4: Text matching as LAST resort (least reliable)
|
|
198
|
-
|
|
199
|
-
const now = Date.now();
|
|
200
|
-
if (cache.element && now - cache.timestamp < CACHE_TTL) {
|
|
201
|
-
return {
|
|
202
|
-
isEnabled: true,
|
|
203
|
-
indicator: 'cached indicator',
|
|
204
|
-
};
|
|
205
|
-
}
|
|
206
|
-
// Search within scoped root only, not entire document
|
|
207
|
-
const textElements = Array.from(scopedRoot.querySelectorAll('div, span, button'));
|
|
202
|
+
const textElements = Array.from(document.querySelectorAll('div, span, button'));
|
|
208
203
|
for (const element of textElements) {
|
|
209
204
|
const text = element.textContent || '';
|
|
210
205
|
if (DEEP_RESEARCH_PATTERN.test(text)) {
|
|
211
|
-
// Update cache
|
|
212
|
-
cache.element = element;
|
|
213
|
-
cache.timestamp = now;
|
|
214
206
|
return {
|
|
215
207
|
isEnabled: true,
|
|
216
|
-
indicator: text.substring(0, 50)
|
|
208
|
+
indicator: `text match: ${text.substring(0, 50).trim()}`,
|
|
217
209
|
};
|
|
218
210
|
}
|
|
219
211
|
}
|
|
@@ -226,32 +218,31 @@ async function detectDeepResearchMode(page) {
|
|
|
226
218
|
async function enableDeepResearchMode(page, response) {
|
|
227
219
|
try {
|
|
228
220
|
response.appendResponseLine('DeepResearchモードを有効化中...');
|
|
229
|
-
// Step 1: Click "+" button
|
|
221
|
+
// Step 1: Click "+" button (ファイルの追加など)
|
|
230
222
|
const plusClicked = await page.evaluate(() => {
|
|
231
223
|
const buttons = Array.from(document.querySelectorAll('button'));
|
|
232
224
|
const plusButton = buttons.find((btn) => {
|
|
233
225
|
const aria = btn.getAttribute('aria-label') || '';
|
|
234
|
-
|
|
235
|
-
return aria.includes('ファイルの追加') || desc.includes('ファイルの追加');
|
|
226
|
+
return aria.includes('ファイルの追加');
|
|
236
227
|
});
|
|
237
228
|
if (!plusButton)
|
|
238
|
-
return { success: false, error: '
|
|
229
|
+
return { success: false, error: '+ボタン(ファイルの追加など)が見つかりません' };
|
|
239
230
|
plusButton.click();
|
|
240
231
|
return { success: true };
|
|
241
232
|
});
|
|
242
233
|
if (!plusClicked.success) {
|
|
243
234
|
return { success: false, error: plusClicked.error };
|
|
244
235
|
}
|
|
245
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
246
|
-
// Step 2:
|
|
236
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
237
|
+
// Step 2: Click "Deep Research" menuitemradio
|
|
247
238
|
const deepResearchSelected = await page.evaluate(() => {
|
|
248
239
|
const menuItems = Array.from(document.querySelectorAll('[role="menuitemradio"]'));
|
|
249
240
|
const deepResearchItem = menuItems.find((item) => item.textContent?.includes('Deep Research') ||
|
|
250
|
-
item.textContent?.includes('
|
|
241
|
+
item.textContent?.includes('リサーチ'));
|
|
251
242
|
if (!deepResearchItem) {
|
|
252
243
|
return {
|
|
253
244
|
success: false,
|
|
254
|
-
error: 'DeepResearch
|
|
245
|
+
error: 'DeepResearch menuitemradio が見つかりません',
|
|
255
246
|
};
|
|
256
247
|
}
|
|
257
248
|
deepResearchItem.click();
|
|
@@ -260,8 +251,17 @@ async function enableDeepResearchMode(page, response) {
|
|
|
260
251
|
if (!deepResearchSelected.success) {
|
|
261
252
|
return { success: false, error: deepResearchSelected.error };
|
|
262
253
|
}
|
|
263
|
-
response.appendResponseLine('✅ DeepResearch
|
|
264
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
254
|
+
response.appendResponseLine('✅ DeepResearch menuitemradio をクリック');
|
|
255
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
256
|
+
// Step 3: Verify mode was actually enabled (composer-pill detection)
|
|
257
|
+
const verification = await detectDeepResearchMode(page);
|
|
258
|
+
if (!verification.isEnabled) {
|
|
259
|
+
return {
|
|
260
|
+
success: false,
|
|
261
|
+
error: 'DeepResearchモードの有効化に失敗しました(リサーチpillが検出されませんでした)',
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
response.appendResponseLine(`✅ モード確認完了: DeepResearch有効 (${verification.indicator})`);
|
|
265
265
|
return { success: true };
|
|
266
266
|
}
|
|
267
267
|
catch (error) {
|
|
@@ -323,6 +323,15 @@ async function configureSources(page, response, enableGitHub) {
|
|
|
323
323
|
* Send question text and click send button
|
|
324
324
|
*/
|
|
325
325
|
async function sendQuestion(page, response, question) {
|
|
326
|
+
// Final verification before sending
|
|
327
|
+
const finalCheck = await detectDeepResearchMode(page);
|
|
328
|
+
if (!finalCheck.isEnabled) {
|
|
329
|
+
return {
|
|
330
|
+
success: false,
|
|
331
|
+
error: 'DeepResearchモードが無効です。送信前の最終確認に失敗しました。',
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
response.appendResponseLine(`✅ 送信前確認: DeepResearchモード有効 (${finalCheck.indicator})`);
|
|
326
335
|
response.appendResponseLine('リサーチテーマを送信中...');
|
|
327
336
|
const questionSent = await page.evaluate((questionText) => {
|
|
328
337
|
const prosemirror = document.querySelector('.ProseMirror[contenteditable="true"]');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chrome-devtools-mcp-for-extension",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.26",
|
|
4
4
|
"description": "MCP server for Chrome extension development with Web Store automation. Fork of chrome-devtools-mcp with extension-specific tools.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": "./build/src/index.js",
|