chrome-ai-bridge 1.0.14 → 1.0.16

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.
@@ -267,41 +267,31 @@ export const askGeminiWeb = defineTool({
267
267
  }
268
268
  response.appendResponseLine('✅ ログイン確認完了');
269
269
  response.appendResponseLine('質問を送信中...');
270
- // Input text using the textbox element
271
- // Gemini uses a textbox with role="textbox" or a div with contenteditable
272
- // NOTE: Gemini has Trusted Types CSP, so we cannot use innerHTML directly
273
- const questionSent = await page.evaluate(questionText => {
274
- // Helper to clear element content without innerHTML (CSP-safe)
275
- const clearElement = (el) => {
276
- while (el.firstChild) {
277
- el.removeChild(el.firstChild);
278
- }
279
- };
280
- // Try textbox first (Gemini's current implementation)
281
- const textbox = document.querySelector('[role="textbox"]');
282
- if (textbox) {
283
- textbox.focus();
284
- // Clear existing content (CSP-safe)
285
- clearElement(textbox);
286
- // Insert text using textContent (CSP-safe)
287
- textbox.textContent = questionText;
288
- textbox.dispatchEvent(new Event('input', { bubbles: true }));
289
- return true;
290
- }
291
- // Fallback to contenteditable
292
- const editor = document.querySelector('div[contenteditable="true"]');
293
- if (editor) {
294
- clearElement(editor);
295
- editor.textContent = questionText;
296
- editor.dispatchEvent(new Event('input', { bubbles: true }));
297
- return true;
298
- }
299
- return false;
300
- }, sanitizedQuestion);
301
- if (!questionSent) {
270
+ // Input text using Puppeteer's type() for proper Angular state updates
271
+ // Gemini uses Angular and requires real keyboard events to update internal state
272
+ const textboxSelector = '[role="textbox"]';
273
+ const textbox = await page.$(textboxSelector);
274
+ if (!textbox) {
302
275
  response.appendResponseLine('❌ 入力欄が見つかりません');
303
276
  return;
304
277
  }
278
+ // Click to focus and clear existing content
279
+ await textbox.click({ clickCount: 3 }); // Triple-click to select all
280
+ await page.keyboard.press('Backspace'); // Clear selection
281
+ // Type the question using real keyboard events (essential for Angular)
282
+ // IMPORTANT: Split by newlines and use Shift+Enter for line breaks
283
+ // (Enter alone triggers send in Gemini)
284
+ const lines = sanitizedQuestion.split('\n');
285
+ for (let i = 0; i < lines.length; i++) {
286
+ if (i > 0) {
287
+ // Shift+Enter for newline (Enter alone sends the message)
288
+ await page.keyboard.down('Shift');
289
+ await page.keyboard.press('Enter');
290
+ await page.keyboard.up('Shift');
291
+ }
292
+ await page.keyboard.type(lines[i], { delay: 2 });
293
+ }
294
+ // Wait for Angular to process the input and show send button
305
295
  await new Promise(resolve => setTimeout(resolve, 500));
306
296
  // 質問送信前に model-response 要素数を記録(ChatGPTと同じカウント方式)
307
297
  const initialModelResponseCount = await page.evaluate(() => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chrome-ai-bridge",
3
- "version": "1.0.14",
3
+ "version": "1.0.16",
4
4
  "description": "MCP server bridging Chrome browser and AI assistants (ChatGPT, Gemini). Browser automation + AI consultation.",
5
5
  "type": "module",
6
6
  "bin": "./scripts/cli.mjs",