@youtyan/browser-pilot 0.7.1
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/LICENSE +21 -0
- package/README.ja.md +138 -0
- package/README.md +140 -0
- package/dist/cli.js +13919 -0
- package/extension/background.js +2332 -0
- package/extension/content.js +2107 -0
- package/extension/manifest.json +21 -0
- package/extension/popup.html +15 -0
- package/extension/popup.js +12 -0
- package/package.json +78 -0
- package/skills/bp-annotate-coords/SKILL.md +148 -0
- package/skills/bp-gemini-image/SKILL.md +107 -0
- package/skills/bp-generate-manual/SKILL.md +367 -0
- package/skills/bp-test-scripts/SKILL.md +296 -0
- package/skills/bp-testing/SKILL.md +193 -0
- package/skills/bp-usage/SKILL.md +219 -0
- package/skills/bp-x-operation/SKILL.md +545 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"manifest_version": 3,
|
|
3
|
+
"name": "Browser MCP Bridge",
|
|
4
|
+
"version": "0.6.0",
|
|
5
|
+
"description": "Bridge between Chrome browser and MCP server for browser automation",
|
|
6
|
+
"permissions": ["tabs", "alarms", "scripting", "downloads", "storage", "debugger", "clipboardRead", "clipboardWrite"],
|
|
7
|
+
"host_permissions": ["<all_urls>"],
|
|
8
|
+
"action": {
|
|
9
|
+
"default_popup": "popup.html",
|
|
10
|
+
"default_title": "Browser Pilot"
|
|
11
|
+
},
|
|
12
|
+
"background": {
|
|
13
|
+
"service_worker": "background.js"
|
|
14
|
+
},
|
|
15
|
+
"content_scripts": [
|
|
16
|
+
{
|
|
17
|
+
"matches": ["<all_urls>"],
|
|
18
|
+
"js": ["content.js"]
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html><head><style>
|
|
3
|
+
body { width: 300px; padding: 12px; font-family: system-ui; }
|
|
4
|
+
input { width: 100%; padding: 6px; margin: 8px 0; box-sizing: border-box; }
|
|
5
|
+
button { padding: 6px 16px; }
|
|
6
|
+
.status { color: green; margin-top: 8px; display: none; }
|
|
7
|
+
</style></head>
|
|
8
|
+
<body>
|
|
9
|
+
<h3>Browser Pilot</h3>
|
|
10
|
+
<label>MCP Token</label>
|
|
11
|
+
<input id="token" type="password" placeholder="Paste token from ~/.browser-pilot-token">
|
|
12
|
+
<button id="save">Save</button>
|
|
13
|
+
<div class="status" id="status">Saved!</div>
|
|
14
|
+
<script src="popup.js"></script>
|
|
15
|
+
</body></html>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
document.addEventListener("DOMContentLoaded", async () => {
|
|
2
|
+
const input = document.getElementById("token");
|
|
3
|
+
const btn = document.getElementById("save");
|
|
4
|
+
const status = document.getElementById("status");
|
|
5
|
+
const stored = await chrome.storage.local.get("mcpToken");
|
|
6
|
+
if (stored.mcpToken) input.value = stored.mcpToken;
|
|
7
|
+
btn.addEventListener("click", async () => {
|
|
8
|
+
await chrome.storage.local.set({ mcpToken: input.value.trim() });
|
|
9
|
+
status.style.display = "block";
|
|
10
|
+
setTimeout(() => status.style.display = "none", 2000);
|
|
11
|
+
});
|
|
12
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@youtyan/browser-pilot",
|
|
3
|
+
"version": "0.7.1",
|
|
4
|
+
"description": "Browser automation MCP server for Claude Code — control Chrome via natural language",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"private": false,
|
|
8
|
+
"bin": {
|
|
9
|
+
"browser-pilot": "dist/cli.js"
|
|
10
|
+
},
|
|
11
|
+
"exports": {
|
|
12
|
+
".": "./dist/cli.js"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist/",
|
|
16
|
+
"skills/",
|
|
17
|
+
"extension/"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"start": "bun --watch run apps/mcp/src/index.ts",
|
|
21
|
+
"build": "bun run build:mcp && bun run build:ext",
|
|
22
|
+
"build:mcp": "bun build apps/mcp/src/cli.ts --outdir dist --target node --packages external && node -e \"const f=require('fs');const c=f.readFileSync('dist/cli.js','utf8');f.writeFileSync('dist/cli.js','#!/usr/bin/env node\\n'+c)\"",
|
|
23
|
+
"build:ext": "bun build apps/extension/src/background.ts --outfile apps/extension/dist/background.js --target browser && bun build apps/extension/src/content.ts --outfile apps/extension/dist/content.js --target browser",
|
|
24
|
+
"build:tools": "bun build apps/mcp/src/tool-registry.ts --outfile /tmp/bp-tools-latest.js --target node --packages external",
|
|
25
|
+
"prepublishOnly": "bun run build && cp -r apps/extension/dist/ extension/",
|
|
26
|
+
"typecheck": "tsc --noEmit && tsc --noEmit -p apps/extension/tsconfig.json",
|
|
27
|
+
"test": "bun test apps/mcp/src/ apps/extension/src/",
|
|
28
|
+
"lint": "biome lint apps/mcp/src/ apps/extension/src/",
|
|
29
|
+
"format": "biome format --write apps/mcp/src/ apps/extension/src/",
|
|
30
|
+
"check": "biome check --write apps/mcp/src/ apps/extension/src/",
|
|
31
|
+
"test:e2e": "bun run apps/test-sandbox/smoke-test.ts",
|
|
32
|
+
"test:ci-e2e": "bun run apps/test-sandbox/ci-server-test.ts",
|
|
33
|
+
"install:skills": "bun run apps/mcp/src/cli.ts init",
|
|
34
|
+
"update:skills": "bun run apps/mcp/src/cli.ts update",
|
|
35
|
+
"link:skills": "for dir in skills/*/; do name=$(basename \"$dir\"); [ ! -e \".claude/skills/$name\" ] && ln -s \"../../skills/$name\" \".claude/skills/$name\" && echo \"linked: $name\" || echo \"exists: $name\"; done"
|
|
36
|
+
},
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"repository": {
|
|
41
|
+
"type": "git",
|
|
42
|
+
"url": "https://github.com/youtyan/browser-pilot.git"
|
|
43
|
+
},
|
|
44
|
+
"homepage": "https://github.com/youtyan/browser-pilot#readme",
|
|
45
|
+
"bugs": {
|
|
46
|
+
"url": "https://github.com/youtyan/browser-pilot/issues"
|
|
47
|
+
},
|
|
48
|
+
"keywords": [
|
|
49
|
+
"mcp",
|
|
50
|
+
"browser",
|
|
51
|
+
"automation",
|
|
52
|
+
"chrome",
|
|
53
|
+
"claude-code",
|
|
54
|
+
"model-context-protocol",
|
|
55
|
+
"agent-skills"
|
|
56
|
+
],
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"@biomejs/biome": "^2.4.6",
|
|
59
|
+
"@happy-dom/global-registrator": "^20.8.3",
|
|
60
|
+
"@types/bun": "^1.3.10",
|
|
61
|
+
"@types/chrome": "^0.1.37",
|
|
62
|
+
"@types/turndown": "^5.0.6",
|
|
63
|
+
"@types/ws": "^8.18.1",
|
|
64
|
+
"happy-dom": "^20.8.3"
|
|
65
|
+
},
|
|
66
|
+
"engines": {
|
|
67
|
+
"node": ">=18"
|
|
68
|
+
},
|
|
69
|
+
"dependencies": {
|
|
70
|
+
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
71
|
+
"@paulirish/trace_engine": "0.0.61",
|
|
72
|
+
"node-html-parser": "^7.1.0",
|
|
73
|
+
"source-map": "^0.7.6",
|
|
74
|
+
"turndown": "^7.2.2",
|
|
75
|
+
"ws": "^8.19.0",
|
|
76
|
+
"zod": "^4.0.0"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: bp-annotate-coords
|
|
3
|
+
description: Use when using browser_get_bounds and browser_annotate together for screenshots with annotations, mosaics, arrows, or labels. Triggers on "座標", "アノテーション", "モザイク", "枠", "矢印", "バッジ", "annotate", "bounds", "mosaic", "マニュアル作成のスクショ".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# browser_get_bounds + browser_annotate 座標活用ガイド
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
`browser_get_bounds` で取得した座標を `browser_annotate` に渡してアノテーション(枠・矢印・テキスト・モザイク・バッジ)を描画する。座標系の理解と検証ステップが品質を決める。
|
|
11
|
+
|
|
12
|
+
## 座標系の基本
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
browser_get_bounds の出力:
|
|
16
|
+
x, y = viewport座標(ブラウザ表示領域の左上が原点)
|
|
17
|
+
scrollX, scrollY = 現在のスクロール量
|
|
18
|
+
pageX, pageY = ページ絶対座標(x + scrollX, y + scrollY)
|
|
19
|
+
width, height = 要素の実際のDOM幅・高さ
|
|
20
|
+
|
|
21
|
+
browser_annotate の入力:
|
|
22
|
+
全座標 = ページ絶対座標(pageX/pageY と同じ系)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**pageX/pageY をそのまま annotate に渡す。変換不要。**
|
|
26
|
+
|
|
27
|
+
## 落とし穴: width がビューポートを超える
|
|
28
|
+
|
|
29
|
+
`getBoundingClientRect()` が返す width は**要素のレンダリング幅**であり、ビューポート幅とは無関係。
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
例: 横スクロールなしのリスト要素
|
|
33
|
+
get_bounds → width: 1996, x: 330
|
|
34
|
+
ビューポート幅: 1280
|
|
35
|
+
|
|
36
|
+
→ 実際に見えているのは 1280 - 330 = 950px 程度
|
|
37
|
+
→ width: 1996 でモザイクを描くと右に大幅にはみ出す
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**対処:** モザイクや枠の幅を決める時、`width` をそのまま使わず、用途に応じてビューポート幅で切る:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
# ビューポート幅は browser_execute_javascript で取得可能
|
|
44
|
+
browser_execute_javascript({ code: "window.innerWidth" })
|
|
45
|
+
|
|
46
|
+
# モザイク幅 = min(要素width, ビューポート幅 - 要素x)
|
|
47
|
+
effectiveWidth = min(bounds.width, viewportWidth - bounds.x)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## 個別モザイク vs 領域モザイク
|
|
51
|
+
|
|
52
|
+
| 状況 | 戦略 |
|
|
53
|
+
|------|------|
|
|
54
|
+
| 要素が散在 | 個別に mosaic を配置 |
|
|
55
|
+
| 同じ列に並ぶ(テーブル等) | 列全体を1つの mosaic でカバー |
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
# NG: 20行 × 2列 = 40個のモザイク
|
|
59
|
+
annotations: [
|
|
60
|
+
{ type: "mosaic", x: 200, y: 180, width: 120, height: 20 },
|
|
61
|
+
{ type: "mosaic", x: 200, y: 220, width: 120, height: 20 },
|
|
62
|
+
... # 40個
|
|
63
|
+
|
|
64
|
+
# OK: 列ごとに1つ(先頭と末尾の座標から算出)
|
|
65
|
+
first = bounds[0] # pageY: 180
|
|
66
|
+
last = bounds[19] # pageY: 940, height: 20
|
|
67
|
+
columnHeight = last.pageY + last.height - first.pageY # = 780
|
|
68
|
+
|
|
69
|
+
annotations: [
|
|
70
|
+
{ type: "mosaic", x: 200, y: 180, width: 120, height: 780 },
|
|
71
|
+
{ type: "mosaic", x: 400, y: 180, width: 200, height: 780 }
|
|
72
|
+
]
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## テキストアノテーションの配置
|
|
76
|
+
|
|
77
|
+
`text` の x, y は**テキストボックスの左上**。中央配置するには:
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
# ボタンの真上中央にラベルを置く場合
|
|
81
|
+
bounds = get_bounds("#submit-btn") # pageX:500, pageY:400, width:120
|
|
82
|
+
|
|
83
|
+
# テキスト幅を概算(1文字 ≈ fontSize px。日本語は fontSize × 文字数)
|
|
84
|
+
textWidth = fontSize * charCount
|
|
85
|
+
centerX = bounds.pageX + bounds.width / 2 - textWidth / 2
|
|
86
|
+
|
|
87
|
+
annotations: [
|
|
88
|
+
{ type: "text", x: centerX, y: bounds.pageY - 30, text: "ここをクリック" }
|
|
89
|
+
]
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## 矢印の配置パターン
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
# ボタンの左上から斜めに指す
|
|
96
|
+
arrow: {
|
|
97
|
+
fromX: bounds.pageX - 80,
|
|
98
|
+
fromY: bounds.pageY - 60,
|
|
99
|
+
toX: bounds.pageX,
|
|
100
|
+
toY: bounds.pageY
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
# ボタンの中央に水平に指す
|
|
104
|
+
arrow: {
|
|
105
|
+
fromX: bounds.pageX - 100,
|
|
106
|
+
fromY: bounds.pageY + bounds.height / 2,
|
|
107
|
+
toX: bounds.pageX,
|
|
108
|
+
toY: bounds.pageY + bounds.height / 2
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## 必須: 検証ステップ
|
|
113
|
+
|
|
114
|
+
アノテーション後、最終スクリーンショットの前に**必ず位置確認**する:
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
1. browser_get_bounds(selector, all: true) # 座標取得
|
|
118
|
+
2. browser_annotate(action: "add", ...) # 描画
|
|
119
|
+
3. browser_screenshot() # ← 位置確認(ずれていたら clear → 再描画)
|
|
120
|
+
4. browser_annotate(action: "clear") # 修正が必要なら消す
|
|
121
|
+
5. browser_annotate(action: "add", ...) # 修正版を描画
|
|
122
|
+
6. browser_screenshot() # 最終スクリーンショット
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
ずれていなければ 3 で完了。**3 を飛ばして一発勝負しない。**
|
|
126
|
+
|
|
127
|
+
## rect のパディング
|
|
128
|
+
|
|
129
|
+
要素ぴったりの枠は見づらい。4px程度のパディングを入れる:
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
{ type: "rect",
|
|
133
|
+
x: bounds.pageX - 4,
|
|
134
|
+
y: bounds.pageY - 4,
|
|
135
|
+
width: bounds.width + 8,
|
|
136
|
+
height: bounds.height + 8 }
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Common Mistakes
|
|
140
|
+
|
|
141
|
+
| 間違い | 正しい対応 |
|
|
142
|
+
|--------|-----------|
|
|
143
|
+
| width をそのまま mosaic に使う | ビューポート幅でクリップする |
|
|
144
|
+
| 座標を目視で推測する | 必ず get_bounds で取得する |
|
|
145
|
+
| 40個の個別モザイクを配置 | 列全体を1-2個のモザイクでカバー |
|
|
146
|
+
| text の x に中央X座標を指定 | テキスト幅を引いて左上原点に変換 |
|
|
147
|
+
| アノテーション後に確認せず最終スクショ | 必ず確認スクショを挟む |
|
|
148
|
+
| visible: false の要素にアノテーション → 通常スクショ | fullPage: true を使うか、先にスクロールする |
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: bp-gemini-image
|
|
3
|
+
description: Use when generating images via Gemini web UI using browser-pilot MCP tools. Triggers on requests to create images, generate illustrations, or produce visual content through Gemini.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Gemini Image Generation via Browser Tools
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Gemini Web UIで画像を生成する。まず`gemini_generate_image` MCPツールを使う。失敗時のみマニュアルフローにフォールバック。
|
|
11
|
+
|
|
12
|
+
## フロー判定
|
|
13
|
+
|
|
14
|
+
```dot
|
|
15
|
+
digraph flow {
|
|
16
|
+
rankdir=TB;
|
|
17
|
+
"画像生成リクエスト" [shape=doublecircle];
|
|
18
|
+
"Geminiタブ確認\n(Pre-flight)" [shape=box];
|
|
19
|
+
"gemini_generate_image\nMCPツール呼び出し" [shape=box];
|
|
20
|
+
"成功?" [shape=diamond];
|
|
21
|
+
"完了" [shape=doublecircle];
|
|
22
|
+
"マニュアルフロー" [shape=box];
|
|
23
|
+
|
|
24
|
+
"画像生成リクエスト" -> "Geminiタブ確認\n(Pre-flight)";
|
|
25
|
+
"Geminiタブ確認\n(Pre-flight)" -> "gemini_generate_image\nMCPツール呼び出し";
|
|
26
|
+
"gemini_generate_image\nMCPツール呼び出し" -> "成功?";
|
|
27
|
+
"成功?" -> "完了" [label="yes"];
|
|
28
|
+
"成功?" -> "マニュアルフロー" [label="no"];
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Pre-flight(MCPツール・マニュアル共通)
|
|
33
|
+
|
|
34
|
+
MCPツールを呼ぶ**前に**必ず実行:
|
|
35
|
+
|
|
36
|
+
1. `browser_tab(action: "list")` → Geminiタブが開いているか確認
|
|
37
|
+
2. Geminiタブがなければ `browser_tab(action: "create", url: "https://gemini.google.com/app")` で作成
|
|
38
|
+
3. Geminiタブに `browser_tab(action: "connect")` で接続
|
|
39
|
+
4. `browser_screenshot` で画面状態を確認(ログイン済み・新規チャット可能か)
|
|
40
|
+
|
|
41
|
+
## 方法1: MCPツール(推奨)
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
gemini_generate_image(
|
|
45
|
+
prompt: "画像生成プロンプト",
|
|
46
|
+
referenceImagePath: "/path/to/ref.png", # 任意
|
|
47
|
+
download: true # デフォルトtrue
|
|
48
|
+
)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
ツールが自動で以下を実行:
|
|
52
|
+
- Geminiタブ自動接続 + 新規チャット作成
|
|
53
|
+
- 「画像の作成」モード切替 + 切替確認
|
|
54
|
+
- 参照画像ペースト(指定時)
|
|
55
|
+
- プロンプト入力 + 送信
|
|
56
|
+
- 画像生成待機(最大180秒)
|
|
57
|
+
- hover → ダウンロードボタンクリック → ダウンロード完了確認
|
|
58
|
+
- ダウンロード先ファイルパスとサイズを返す
|
|
59
|
+
|
|
60
|
+
**成功時の出力例:**
|
|
61
|
+
```
|
|
62
|
+
Image generated successfully. Downloaded: /Users/.../Gemini_Generated_Image_xxx.jpeg (2708KB)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## 方法2: マニュアルフロー(フォールバック)
|
|
66
|
+
|
|
67
|
+
MCPツールが失敗した場合のみ使用。Pre-flightは共通セクションで実施済みの前提。
|
|
68
|
+
|
|
69
|
+
### 手順
|
|
70
|
+
|
|
71
|
+
1. **新規チャット** — `browser_click(text: "チャットを新規作成")`
|
|
72
|
+
2. **画像モード** — `browser_click(text: "画像の作成")` → 「画像の説明を入力」欄が表示されるまで待つ
|
|
73
|
+
3. **参照画像**(任意) — `browser_paste_file(filePath: "...", selector: 'div[data-placeholder="画像の説明を入力"]')`
|
|
74
|
+
4. **プロンプト** — `browser_set_values(selector: 'div[data-placeholder="画像の説明を入力"]', value: "...")`
|
|
75
|
+
5. **送信** — `browser_click(selector: 'button[aria-label="プロンプトを送信"]')`
|
|
76
|
+
6. **待機** — `browser_wait_for(selector: "model-response img", condition: "appear", timeout: 180000)`
|
|
77
|
+
7. **ダウンロード** — 以下の順序で実行:
|
|
78
|
+
1. `browser_click(selector: "model-response img")` — 画像をクリックして拡大表示
|
|
79
|
+
2. `browser_click(selector: 'button[aria-label="フルサイズの画像をダウンロード"]')` — ダウンロードボタンをクリック
|
|
80
|
+
3. `browser_screenshot` — 「フルサイズでダウンロードしています」の表示を確認
|
|
81
|
+
4. `ls -t ~/Downloads/Gemini_Generated_Image_* | head -1` — ダウンロードされたファイルパスを取得
|
|
82
|
+
|
|
83
|
+
### Quick Reference
|
|
84
|
+
|
|
85
|
+
| 操作 | セレクタ / パラメータ |
|
|
86
|
+
|------|----------------------|
|
|
87
|
+
| 入力欄(通常) | `div[aria-label="Gemini へのプロンプトを入力"]` |
|
|
88
|
+
| 入力欄(画像モード) | `div[data-placeholder="画像の説明を入力"]` |
|
|
89
|
+
| 送信ボタン | `button[aria-label="プロンプトを送信"]` |
|
|
90
|
+
| 画像生成チップ | `browser_click(text: "画像の作成")` |
|
|
91
|
+
| ダウンロード | 画像クリック(拡大) → `button[aria-label="フルサイズの画像をダウンロード"]` |
|
|
92
|
+
|
|
93
|
+
## Common Mistakes
|
|
94
|
+
|
|
95
|
+
| 間違い | 正しい対応 |
|
|
96
|
+
|--------|-----------|
|
|
97
|
+
| MCPツールを使わずマニュアルで始める | **必ず**`gemini_generate_image`を最初に試す |
|
|
98
|
+
| Pre-flightをスキップしてMCPツールを呼ぶ | Geminiタブの存在・接続確認が必須。未確認だと「Input area did not appear」エラーになる |
|
|
99
|
+
| 「画像の作成」を押さずに送信 | テキスト応答になる。画像モード必須 |
|
|
100
|
+
| hoverでダウンロードボタンを探す | hoverでは出ないことがある。**画像クリック→拡大表示→ダウンロードボタン**が確実 |
|
|
101
|
+
| ダウンロード完了を確認しない | MCPツールは自動確認。マニュアル時は`ls -t ~/Downloads/Gemini_Generated_Image_*`で確認 |
|
|
102
|
+
| Extension hot-reload後に操作 | `browser_tab(action: "list")` → `browser_tab(action: "connect")` で再接続 |
|
|
103
|
+
|
|
104
|
+
## Limitations
|
|
105
|
+
|
|
106
|
+
- **ファイル選択ダイアログ不可** — `browser_paste_file`で代替
|
|
107
|
+
- **Trusted Types制約** — `browser_execute_javascript`はGeminiでブロック(content.tsアクションは影響なし)
|