btcp-browser-agent 0.1.0
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/CLAUDE.md +230 -0
- package/LICENSE +21 -0
- package/README.md +309 -0
- package/SKILL.md +143 -0
- package/SNAPSHOT_IMPROVEMENTS.md +302 -0
- package/USAGE.md +146 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/docs/browser-cli-design.md +500 -0
- package/examples/chrome-extension/CHANGELOG.md +210 -0
- package/examples/chrome-extension/DEBUG.md +231 -0
- package/examples/chrome-extension/ERROR_FIXED.md +147 -0
- package/examples/chrome-extension/QUICK_TEST.md +189 -0
- package/examples/chrome-extension/README.md +149 -0
- package/examples/chrome-extension/SESSION_ONLY_MODE.md +305 -0
- package/examples/chrome-extension/TEST_WITH_YOUR_TABS.md +97 -0
- package/examples/chrome-extension/build.js +43 -0
- package/examples/chrome-extension/manifest.json +37 -0
- package/examples/chrome-extension/package-lock.json +1063 -0
- package/examples/chrome-extension/package.json +21 -0
- package/examples/chrome-extension/popup.html +195 -0
- package/examples/chrome-extension/src/background.ts +12 -0
- package/examples/chrome-extension/src/content.ts +7 -0
- package/examples/chrome-extension/src/popup.ts +303 -0
- package/examples/chrome-extension/src/scenario-google-github.ts +389 -0
- package/examples/chrome-extension/test-page.html +127 -0
- package/examples/chrome-extension/tests/README.md +206 -0
- package/examples/chrome-extension/tests/scenario-google-to-github-star.ts +380 -0
- package/examples/chrome-extension/tsconfig.json +14 -0
- package/examples/snapshots/README.md +207 -0
- package/examples/snapshots/amazon-com-detail.html +9528 -0
- package/examples/snapshots/amazon-com-detail.snapshot.txt +997 -0
- package/examples/snapshots/convert-snapshots.ts +97 -0
- package/examples/snapshots/edition-cnn-com.html +13292 -0
- package/examples/snapshots/edition-cnn-com.snapshot.txt +562 -0
- package/examples/snapshots/github-com-microsoft-vscode.html +2916 -0
- package/examples/snapshots/github-com-microsoft-vscode.snapshot.txt +455 -0
- package/examples/snapshots/google-search.html +20012 -0
- package/examples/snapshots/google-search.snapshot.txt +195 -0
- package/examples/snapshots/metadata.json +86 -0
- package/examples/snapshots/npr-org-templates.html +2031 -0
- package/examples/snapshots/npr-org-templates.snapshot.txt +224 -0
- package/examples/snapshots/stackoverflow-com.html +5216 -0
- package/examples/snapshots/stackoverflow-com.snapshot.txt +2404 -0
- package/examples/snapshots/test-all-mode.html +46 -0
- package/examples/snapshots/test-all-mode.snapshot.txt +5 -0
- package/examples/snapshots/validate.test.ts +296 -0
- package/package.json +65 -0
- package/packages/cli/package.json +42 -0
- package/packages/cli/src/__tests__/cli.test.ts +434 -0
- package/packages/cli/src/__tests__/errors.test.ts +226 -0
- package/packages/cli/src/__tests__/executor.test.ts +275 -0
- package/packages/cli/src/__tests__/formatter.test.ts +260 -0
- package/packages/cli/src/__tests__/parser.test.ts +288 -0
- package/packages/cli/src/__tests__/suggestions.test.ts +255 -0
- package/packages/cli/src/commands/back.ts +22 -0
- package/packages/cli/src/commands/check.ts +33 -0
- package/packages/cli/src/commands/clear.ts +33 -0
- package/packages/cli/src/commands/click.ts +32 -0
- package/packages/cli/src/commands/closetab.ts +31 -0
- package/packages/cli/src/commands/eval.ts +41 -0
- package/packages/cli/src/commands/fill.ts +30 -0
- package/packages/cli/src/commands/focus.ts +33 -0
- package/packages/cli/src/commands/forward.ts +22 -0
- package/packages/cli/src/commands/goto.ts +34 -0
- package/packages/cli/src/commands/help.ts +162 -0
- package/packages/cli/src/commands/hover.ts +34 -0
- package/packages/cli/src/commands/index.ts +129 -0
- package/packages/cli/src/commands/newtab.ts +35 -0
- package/packages/cli/src/commands/press.ts +40 -0
- package/packages/cli/src/commands/reload.ts +25 -0
- package/packages/cli/src/commands/screenshot.ts +27 -0
- package/packages/cli/src/commands/scroll.ts +64 -0
- package/packages/cli/src/commands/select.ts +35 -0
- package/packages/cli/src/commands/snapshot.ts +21 -0
- package/packages/cli/src/commands/tab.ts +32 -0
- package/packages/cli/src/commands/tabs.ts +26 -0
- package/packages/cli/src/commands/text.ts +27 -0
- package/packages/cli/src/commands/title.ts +17 -0
- package/packages/cli/src/commands/type.ts +38 -0
- package/packages/cli/src/commands/uncheck.ts +33 -0
- package/packages/cli/src/commands/url.ts +17 -0
- package/packages/cli/src/commands/wait.ts +54 -0
- package/packages/cli/src/errors.ts +164 -0
- package/packages/cli/src/executor.ts +68 -0
- package/packages/cli/src/formatter.ts +215 -0
- package/packages/cli/src/index.ts +257 -0
- package/packages/cli/src/parser.ts +195 -0
- package/packages/cli/src/suggestions.ts +207 -0
- package/packages/cli/src/terminal/Terminal.ts +365 -0
- package/packages/cli/src/terminal/index.ts +5 -0
- package/packages/cli/src/types.ts +155 -0
- package/packages/cli/tsconfig.json +20 -0
- package/packages/core/package.json +35 -0
- package/packages/core/src/actions.ts +1210 -0
- package/packages/core/src/errors.ts +296 -0
- package/packages/core/src/index.test.ts +638 -0
- package/packages/core/src/index.ts +220 -0
- package/packages/core/src/ref-map.ts +107 -0
- package/packages/core/src/snapshot.ts +873 -0
- package/packages/core/src/types.ts +536 -0
- package/packages/core/tsconfig.json +23 -0
- package/packages/extension/README.md +129 -0
- package/packages/extension/package.json +43 -0
- package/packages/extension/src/background.ts +888 -0
- package/packages/extension/src/content.ts +172 -0
- package/packages/extension/src/index.ts +579 -0
- package/packages/extension/src/session-manager.ts +385 -0
- package/packages/extension/src/session-types.ts +144 -0
- package/packages/extension/src/types.ts +162 -0
- package/packages/extension/tsconfig.json +28 -0
- package/src/index.ts +64 -0
- package/tsconfig.build.json +12 -0
- package/tsconfig.json +26 -0
- package/vitest.config.ts +13 -0
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# Debugging Guide: Start Session Not Working
|
|
2
|
+
|
|
3
|
+
## Step 1: Load the Extension
|
|
4
|
+
|
|
5
|
+
1. Open Chrome and go to `chrome://extensions`
|
|
6
|
+
2. Enable **Developer mode** (toggle in top right)
|
|
7
|
+
3. Click **Load unpacked**
|
|
8
|
+
4. Navigate to: `/Users/minh/Documents/btcp/btcp-browser-agent/examples/chrome-extension/dist/`
|
|
9
|
+
5. Select the `dist` folder and click **Select**
|
|
10
|
+
|
|
11
|
+
## Step 2: Check Extension Loaded
|
|
12
|
+
|
|
13
|
+
You should see:
|
|
14
|
+
- **BTCP Browser Agent** card in the extensions list
|
|
15
|
+
- No errors shown in the extension card
|
|
16
|
+
- Extension icon appears in the Chrome toolbar
|
|
17
|
+
|
|
18
|
+
If you see errors, note them and check Step 3.
|
|
19
|
+
|
|
20
|
+
## Step 3: Check for Permission Errors
|
|
21
|
+
|
|
22
|
+
### View Background Service Worker Logs:
|
|
23
|
+
1. On the extension card, click **service worker** link (under "Inspect views")
|
|
24
|
+
2. This opens DevTools for the background script
|
|
25
|
+
3. Check Console tab for errors
|
|
26
|
+
|
|
27
|
+
**Common errors:**
|
|
28
|
+
- `chrome.tabGroups is not defined` → Permission missing
|
|
29
|
+
- `SessionManager is not a constructor` → Build issue
|
|
30
|
+
- `Failed to execute 'group'` → Invalid tab IDs
|
|
31
|
+
|
|
32
|
+
### Check Console Output:
|
|
33
|
+
Look for these messages when extension loads:
|
|
34
|
+
- No errors = Good ✅
|
|
35
|
+
- Red errors = Problem ❌
|
|
36
|
+
|
|
37
|
+
## Step 4: Test the Popup
|
|
38
|
+
|
|
39
|
+
1. Click the extension icon in Chrome toolbar
|
|
40
|
+
2. Popup should open showing:
|
|
41
|
+
- **Session** section at top
|
|
42
|
+
- "No active session" (gray)
|
|
43
|
+
- "Start New Session" button (blue)
|
|
44
|
+
- Quick Actions section below
|
|
45
|
+
|
|
46
|
+
3. **Open popup DevTools:**
|
|
47
|
+
- Right-click anywhere in the popup
|
|
48
|
+
- Select **Inspect**
|
|
49
|
+
- Go to **Console** tab
|
|
50
|
+
|
|
51
|
+
## Step 5: Test Start Session Button
|
|
52
|
+
|
|
53
|
+
### Click "Start New Session" button and watch for:
|
|
54
|
+
|
|
55
|
+
**In Popup Console (DevTools):**
|
|
56
|
+
```
|
|
57
|
+
[timestamp]
|
|
58
|
+
Starting new session...
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Then either:
|
|
62
|
+
```javascript
|
|
63
|
+
// Success:
|
|
64
|
+
{
|
|
65
|
+
"created": "BTCP Session 1",
|
|
66
|
+
"groupId": 123
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Or Error:
|
|
70
|
+
Error: [error message here]
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**In Background Service Worker Console:**
|
|
74
|
+
Look for command execution logs or errors.
|
|
75
|
+
|
|
76
|
+
## Step 6: Common Issues & Solutions
|
|
77
|
+
|
|
78
|
+
### Issue 1: "chrome.tabGroups is undefined"
|
|
79
|
+
**Cause:** Permission not granted
|
|
80
|
+
**Fix:**
|
|
81
|
+
1. Open `manifest.json`
|
|
82
|
+
2. Verify `"tabGroups"` is in `"permissions"` array
|
|
83
|
+
3. Rebuild: `npm run build`
|
|
84
|
+
4. Reload extension in `chrome://extensions`
|
|
85
|
+
|
|
86
|
+
### Issue 2: "No active tab for DOM command"
|
|
87
|
+
**Cause:** Extension needs an active tab to create group
|
|
88
|
+
**Fix:**
|
|
89
|
+
1. Make sure you have at least one tab open
|
|
90
|
+
2. Click on a regular webpage tab (not chrome:// pages)
|
|
91
|
+
3. Then click extension icon and try again
|
|
92
|
+
|
|
93
|
+
### Issue 3: "Failed to execute 'group' on 'tabs'"
|
|
94
|
+
**Cause:** Invalid tab ID or tab already closed
|
|
95
|
+
**Fix:**
|
|
96
|
+
1. Open a new tab first
|
|
97
|
+
2. Navigate to a regular website (e.g., example.com)
|
|
98
|
+
3. Then try creating session
|
|
99
|
+
|
|
100
|
+
### Issue 4: Button click does nothing
|
|
101
|
+
**Cause:** JavaScript error in popup
|
|
102
|
+
**Fix:**
|
|
103
|
+
1. Check popup console for errors (see Step 4)
|
|
104
|
+
2. Common errors:
|
|
105
|
+
- `client.groupCreate is not a function` → Rebuild needed
|
|
106
|
+
- `btnStartSession is null` → HTML/JS mismatch
|
|
107
|
+
- `Cannot read property 'group'` → API response issue
|
|
108
|
+
|
|
109
|
+
### Issue 5: "SessionManager is not a constructor"
|
|
110
|
+
**Cause:** session-manager.js not properly built/imported
|
|
111
|
+
**Fix:**
|
|
112
|
+
```bash
|
|
113
|
+
# Rebuild the packages
|
|
114
|
+
cd /Users/minh/Documents/btcp/btcp-browser-agent
|
|
115
|
+
npm run build
|
|
116
|
+
cd examples/chrome-extension
|
|
117
|
+
npm run build
|
|
118
|
+
```
|
|
119
|
+
Then reload extension.
|
|
120
|
+
|
|
121
|
+
## Step 7: Manual Console Testing
|
|
122
|
+
|
|
123
|
+
### Test in Background Service Worker Console:
|
|
124
|
+
```javascript
|
|
125
|
+
// Get background agent
|
|
126
|
+
const agent = globalThis.__backgroundAgent;
|
|
127
|
+
|
|
128
|
+
// Test session manager
|
|
129
|
+
agent.sessionManager.createGroup({ title: "Test Session" })
|
|
130
|
+
.then(group => console.log("Created:", group))
|
|
131
|
+
.catch(err => console.error("Error:", err));
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Test in Popup Console:
|
|
135
|
+
```javascript
|
|
136
|
+
// Get client
|
|
137
|
+
const client = createClient();
|
|
138
|
+
|
|
139
|
+
// Test group creation
|
|
140
|
+
client.groupCreate({ title: "Test Session" })
|
|
141
|
+
.then(result => console.log("Result:", result))
|
|
142
|
+
.catch(err => console.error("Error:", err));
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Step 8: Check Tab Groups API
|
|
146
|
+
|
|
147
|
+
Test if Chrome supports tab groups:
|
|
148
|
+
```javascript
|
|
149
|
+
// In any console:
|
|
150
|
+
console.log(chrome.tabGroups);
|
|
151
|
+
// Should show: Object with methods like 'group', 'update', 'query'
|
|
152
|
+
// If undefined: Chrome version too old or API not available
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**Minimum Chrome version:** 89+ (tab groups API)
|
|
156
|
+
|
|
157
|
+
## Step 9: Verify Session Creation Manually
|
|
158
|
+
|
|
159
|
+
After clicking "Start New Session":
|
|
160
|
+
|
|
161
|
+
1. **Check tabs in browser:**
|
|
162
|
+
- Do you see a blue colored tab group?
|
|
163
|
+
- Is there a label like "BTCP Session 1"?
|
|
164
|
+
|
|
165
|
+
2. **If no group visible:**
|
|
166
|
+
- SessionManager may have created group but no tabs in it
|
|
167
|
+
- Try clicking "New Tab" button
|
|
168
|
+
- New tab should appear in a blue group
|
|
169
|
+
|
|
170
|
+
## Step 10: Full Debug Flow
|
|
171
|
+
|
|
172
|
+
Run this complete test in **Background Service Worker Console**:
|
|
173
|
+
|
|
174
|
+
```javascript
|
|
175
|
+
// 1. Check SessionManager exists
|
|
176
|
+
console.log("SessionManager:", globalThis.SessionManager);
|
|
177
|
+
|
|
178
|
+
// 2. Check background agent has session manager
|
|
179
|
+
const agent = globalThis.__backgroundAgent || getBackgroundAgent();
|
|
180
|
+
console.log("Agent has sessionManager:", !!agent.sessionManager);
|
|
181
|
+
|
|
182
|
+
// 3. Try creating a group directly
|
|
183
|
+
agent.sessionManager.createGroup({ title: "Debug Test" })
|
|
184
|
+
.then(group => {
|
|
185
|
+
console.log("✅ Group created:", group);
|
|
186
|
+
return chrome.tabs.query({ groupId: group.id });
|
|
187
|
+
})
|
|
188
|
+
.then(tabs => {
|
|
189
|
+
console.log("✅ Tabs in group:", tabs.length);
|
|
190
|
+
})
|
|
191
|
+
.catch(err => {
|
|
192
|
+
console.error("❌ Error:", err);
|
|
193
|
+
console.error("Stack:", err.stack);
|
|
194
|
+
});
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Step 11: Collect Debug Info
|
|
198
|
+
|
|
199
|
+
If still not working, collect this info:
|
|
200
|
+
|
|
201
|
+
```javascript
|
|
202
|
+
// Run in Background Service Worker Console:
|
|
203
|
+
{
|
|
204
|
+
chromeVersion: navigator.userAgent.match(/Chrome\/(\d+)/)?.[1],
|
|
205
|
+
tabGroupsAPI: typeof chrome.tabGroups,
|
|
206
|
+
sessionManagerLoaded: typeof SessionManager !== 'undefined',
|
|
207
|
+
backgroundAgent: typeof getBackgroundAgent !== 'undefined',
|
|
208
|
+
activeTabs: await chrome.tabs.query({ active: true }),
|
|
209
|
+
allGroups: await chrome.tabGroups.query({})
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Quick Fix Checklist
|
|
214
|
+
|
|
215
|
+
- [ ] Extension loaded without errors
|
|
216
|
+
- [ ] Developer mode enabled
|
|
217
|
+
- [ ] `tabGroups` permission in manifest
|
|
218
|
+
- [ ] At least one regular tab open (not chrome://)
|
|
219
|
+
- [ ] Background service worker console has no errors
|
|
220
|
+
- [ ] Popup console has no errors
|
|
221
|
+
- [ ] Chrome version 89 or higher
|
|
222
|
+
- [ ] Extension reloaded after rebuild
|
|
223
|
+
|
|
224
|
+
## Getting More Help
|
|
225
|
+
|
|
226
|
+
If still stuck, provide:
|
|
227
|
+
1. Chrome version
|
|
228
|
+
2. Console errors from both background and popup
|
|
229
|
+
3. Result of Step 10 debug flow
|
|
230
|
+
4. Screenshot of extension popup
|
|
231
|
+
5. Output of Step 11 debug info
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# ✅ Error Fixed: "Tabs can only be moved to and from normal windows"
|
|
2
|
+
|
|
3
|
+
## What Was the Problem?
|
|
4
|
+
|
|
5
|
+
The error occurred because:
|
|
6
|
+
1. The extension was trying to get the "current window" using `chrome.windows.getCurrent()`
|
|
7
|
+
2. When called from a popup, this returns the **popup window**, not the main browser window
|
|
8
|
+
3. Chrome only allows tab grouping in **normal windows**, not popup/devtools/app windows
|
|
9
|
+
|
|
10
|
+
## The Fix
|
|
11
|
+
|
|
12
|
+
Changed `session-manager.ts` to:
|
|
13
|
+
1. Find which window the target tab belongs to
|
|
14
|
+
2. Verify it's a "normal" window type
|
|
15
|
+
3. Use that window's ID for group creation
|
|
16
|
+
4. Provide clear error messages if window type is wrong
|
|
17
|
+
|
|
18
|
+
## How to Test Now
|
|
19
|
+
|
|
20
|
+
### Step 1: Reload Extension
|
|
21
|
+
```bash
|
|
22
|
+
# Go to: chrome://extensions
|
|
23
|
+
# Find: BTCP Browser Agent
|
|
24
|
+
# Click the refresh icon (or remove and re-add)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Step 2: Proper Test Setup
|
|
28
|
+
1. **Open a regular browser window** (if you don't have one)
|
|
29
|
+
2. **Open a regular website** in a tab (e.g., https://example.com)
|
|
30
|
+
- NOT chrome:// pages
|
|
31
|
+
- NOT extension pages
|
|
32
|
+
- NOT devtools
|
|
33
|
+
3. **Make sure that tab is active** (click on it to focus)
|
|
34
|
+
4. **Then click the extension icon** in the toolbar
|
|
35
|
+
5. **Click "Start New Session"**
|
|
36
|
+
|
|
37
|
+
### Step 3: Expected Result
|
|
38
|
+
|
|
39
|
+
✅ **Success looks like:**
|
|
40
|
+
```
|
|
41
|
+
[SessionManager] createGroup called with options: {}
|
|
42
|
+
[SessionManager] No tabIds provided, getting active tab...
|
|
43
|
+
[SessionManager] Active tab: {id: 123, url: "https://example.com", ...}
|
|
44
|
+
[SessionManager] Creating group with tabs: [123]
|
|
45
|
+
[SessionManager] Group created with ID: 456
|
|
46
|
+
[SessionManager] Group updated with title: BTCP Session 1
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
✅ **Visual confirmation:**
|
|
50
|
+
- Your active tab gets a **blue border/group indicator**
|
|
51
|
+
- The tab shows group label: **"BTCP Session 1"**
|
|
52
|
+
- Popup updates to show session info
|
|
53
|
+
|
|
54
|
+
## Common Mistakes to Avoid
|
|
55
|
+
|
|
56
|
+
### ❌ Wrong: Opening popup in a popup window
|
|
57
|
+
**Don't:** Open extension in its own window
|
|
58
|
+
|
|
59
|
+
**Do:** Use the extension icon in the main browser toolbar
|
|
60
|
+
|
|
61
|
+
### ❌ Wrong: Testing on chrome:// pages
|
|
62
|
+
**Don't:** Have chrome://extensions as active tab
|
|
63
|
+
|
|
64
|
+
**Do:** Have a real website (https://...) as active tab
|
|
65
|
+
|
|
66
|
+
### ❌ Wrong: Using DevTools window
|
|
67
|
+
**Don't:** Have DevTools undocked as separate window
|
|
68
|
+
|
|
69
|
+
**Do:** Keep DevTools docked or use regular browser window
|
|
70
|
+
|
|
71
|
+
## Verification Test
|
|
72
|
+
|
|
73
|
+
Run this in the **Background Service Worker Console**:
|
|
74
|
+
|
|
75
|
+
```javascript
|
|
76
|
+
// Check window types
|
|
77
|
+
chrome.windows.getAll({ populate: true }, (windows) => {
|
|
78
|
+
windows.forEach(w => {
|
|
79
|
+
console.log(`Window ${w.id}:`, {
|
|
80
|
+
type: w.type,
|
|
81
|
+
focused: w.focused,
|
|
82
|
+
tabs: w.tabs?.length || 0,
|
|
83
|
+
tabTitles: w.tabs?.map(t => t.title)
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// This should show at least one window with type: "normal"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Still Not Working?
|
|
92
|
+
|
|
93
|
+
If you still get errors, provide:
|
|
94
|
+
|
|
95
|
+
1. **Error message** (exact text from console)
|
|
96
|
+
2. **Window type** (from verification test above)
|
|
97
|
+
3. **Active tab URL** (what page are you on?)
|
|
98
|
+
4. **How you opened the extension** (toolbar icon? right-click?)
|
|
99
|
+
|
|
100
|
+
## Next Steps After Fix Works
|
|
101
|
+
|
|
102
|
+
Once "Start New Session" works:
|
|
103
|
+
|
|
104
|
+
1. ✅ **Test "New Tab" button** - should auto-join the session
|
|
105
|
+
2. ✅ **Test "Close Session" button** - should close all tabs in group
|
|
106
|
+
3. ✅ **Test multiple tabs** - create several tabs, verify they all join
|
|
107
|
+
4. ✅ **Test session persistence** - session should exist until you close it
|
|
108
|
+
|
|
109
|
+
## Technical Details
|
|
110
|
+
|
|
111
|
+
The key change in `session-manager.ts`:
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
// OLD (broken):
|
|
115
|
+
const groupId = await chrome.tabs.group({
|
|
116
|
+
tabIds: targetTabIds,
|
|
117
|
+
createProperties: {
|
|
118
|
+
windowId: (await chrome.windows.getCurrent()).id, // ❌ Returns popup window!
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// NEW (fixed):
|
|
123
|
+
const tabs = await chrome.tabs.query({ windowId: chrome.windows.WINDOW_ID_CURRENT });
|
|
124
|
+
const targetTab = tabs.find(t => targetTabIds.includes(t.id!));
|
|
125
|
+
const window = await chrome.windows.get(targetTab.windowId);
|
|
126
|
+
|
|
127
|
+
if (window.type !== 'normal') {
|
|
128
|
+
throw new Error(`Tabs can only be grouped in normal windows`);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const groupId = await chrome.tabs.group({
|
|
132
|
+
tabIds: targetTabIds,
|
|
133
|
+
createProperties: {
|
|
134
|
+
windowId: targetTab.windowId, // ✅ Uses tab's actual window!
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Build Version
|
|
140
|
+
|
|
141
|
+
This fix is included in the build dated: **2026-01-16**
|
|
142
|
+
|
|
143
|
+
Make sure you rebuild and reload:
|
|
144
|
+
```bash
|
|
145
|
+
npm run build
|
|
146
|
+
# Then reload extension in chrome://extensions
|
|
147
|
+
```
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# Quick Test: Session Debugging
|
|
2
|
+
|
|
3
|
+
## 1. Load Extension (Fresh Start)
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
# Location: chrome://extensions
|
|
7
|
+
# 1. Remove old version if exists
|
|
8
|
+
# 2. Click "Load unpacked"
|
|
9
|
+
# 3. Select: /Users/minh/Documents/btcp/btcp-browser-agent/examples/chrome-extension/dist
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## 2. Open Background Console
|
|
13
|
+
|
|
14
|
+
1. In `chrome://extensions`, find **BTCP Browser Agent**
|
|
15
|
+
2. Click **service worker** (under "Inspect views")
|
|
16
|
+
3. This opens the background script DevTools
|
|
17
|
+
|
|
18
|
+
## 3. Run This Test in Background Console
|
|
19
|
+
|
|
20
|
+
Copy and paste this entire block:
|
|
21
|
+
|
|
22
|
+
```javascript
|
|
23
|
+
console.log('=== BTCP Session Debug Test ===');
|
|
24
|
+
|
|
25
|
+
// Test 1: Check API availability
|
|
26
|
+
console.log('1. Chrome APIs:');
|
|
27
|
+
console.log(' - chrome.tabs:', typeof chrome.tabs);
|
|
28
|
+
console.log(' - chrome.tabGroups:', typeof chrome.tabGroups);
|
|
29
|
+
console.log(' - chrome.windows:', typeof chrome.windows);
|
|
30
|
+
|
|
31
|
+
// Test 2: Check SessionManager
|
|
32
|
+
console.log('\n2. SessionManager:');
|
|
33
|
+
console.log(' - SessionManager class:', typeof SessionManager);
|
|
34
|
+
|
|
35
|
+
// Test 3: Check BackgroundAgent
|
|
36
|
+
console.log('\n3. BackgroundAgent:');
|
|
37
|
+
const agent = getBackgroundAgent();
|
|
38
|
+
console.log(' - Agent exists:', !!agent);
|
|
39
|
+
console.log(' - Has sessionManager:', !!agent?.sessionManager);
|
|
40
|
+
|
|
41
|
+
// Test 4: Check tabs
|
|
42
|
+
console.log('\n4. Current tabs:');
|
|
43
|
+
chrome.tabs.query({}, (tabs) => {
|
|
44
|
+
console.log(' - Total tabs:', tabs.length);
|
|
45
|
+
console.log(' - Active tabs:', tabs.filter(t => t.active).length);
|
|
46
|
+
const activeTab = tabs.find(t => t.active);
|
|
47
|
+
if (activeTab) {
|
|
48
|
+
console.log(' - Active tab ID:', activeTab.id);
|
|
49
|
+
console.log(' - Active tab URL:', activeTab.url);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Test 5: Try creating session
|
|
54
|
+
console.log('\n5. Attempting to create session...');
|
|
55
|
+
if (agent?.sessionManager) {
|
|
56
|
+
agent.sessionManager.createGroup({ title: 'Test Session' })
|
|
57
|
+
.then(group => {
|
|
58
|
+
console.log('✅ SUCCESS! Group created:');
|
|
59
|
+
console.log(' - ID:', group.id);
|
|
60
|
+
console.log(' - Title:', group.title);
|
|
61
|
+
console.log(' - Color:', group.color);
|
|
62
|
+
return chrome.tabs.query({ groupId: group.id });
|
|
63
|
+
})
|
|
64
|
+
.then(tabs => {
|
|
65
|
+
console.log(' - Tabs in group:', tabs.length);
|
|
66
|
+
console.log('\n🎉 Session working! Check your tabs for a blue group.');
|
|
67
|
+
})
|
|
68
|
+
.catch(err => {
|
|
69
|
+
console.error('❌ FAILED! Error:', err.message);
|
|
70
|
+
console.error(' Stack:', err.stack);
|
|
71
|
+
});
|
|
72
|
+
} else {
|
|
73
|
+
console.error('❌ SessionManager not available!');
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## 4. What to Look For
|
|
78
|
+
|
|
79
|
+
### SUCCESS looks like:
|
|
80
|
+
```
|
|
81
|
+
=== BTCP Session Debug Test ===
|
|
82
|
+
1. Chrome APIs:
|
|
83
|
+
- chrome.tabs: object
|
|
84
|
+
- chrome.tabGroups: object
|
|
85
|
+
- chrome.windows: object
|
|
86
|
+
|
|
87
|
+
2. SessionManager:
|
|
88
|
+
- SessionManager class: function
|
|
89
|
+
|
|
90
|
+
3. BackgroundAgent:
|
|
91
|
+
- Agent exists: true
|
|
92
|
+
- Has sessionManager: true
|
|
93
|
+
|
|
94
|
+
4. Current tabs:
|
|
95
|
+
- Total tabs: 3
|
|
96
|
+
- Active tabs: 1
|
|
97
|
+
- Active tab ID: 123
|
|
98
|
+
- Active tab URL: https://example.com/
|
|
99
|
+
|
|
100
|
+
5. Attempting to create session...
|
|
101
|
+
[SessionManager] createGroup called with options: {title: "Test Session"}
|
|
102
|
+
[SessionManager] No tabIds provided, getting active tab...
|
|
103
|
+
[SessionManager] Active tab: {id: 123, ...}
|
|
104
|
+
[SessionManager] Creating group with tabs: [123]
|
|
105
|
+
[SessionManager] Group created with ID: 456
|
|
106
|
+
[SessionManager] Group updated with title: Test Session
|
|
107
|
+
[SessionManager] Group info: {id: 456, title: "Test Session", ...}
|
|
108
|
+
✅ SUCCESS! Group created:
|
|
109
|
+
- ID: 456
|
|
110
|
+
- Title: Test Session
|
|
111
|
+
- Color: blue
|
|
112
|
+
- Tabs in group: 1
|
|
113
|
+
|
|
114
|
+
🎉 Session working! Check your tabs for a blue group.
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### FAILURE might show:
|
|
118
|
+
```
|
|
119
|
+
❌ FAILED! Error: No active tab available to create session
|
|
120
|
+
```
|
|
121
|
+
**Fix:** Open a regular webpage (not chrome:// page)
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
- chrome.tabGroups: undefined
|
|
125
|
+
```
|
|
126
|
+
**Fix:** Update Chrome to version 89+
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
❌ SessionManager not available!
|
|
130
|
+
```
|
|
131
|
+
**Fix:** Extension not built correctly, run: `npm run build`
|
|
132
|
+
|
|
133
|
+
## 5. Test from Popup
|
|
134
|
+
|
|
135
|
+
If background test works, test the popup:
|
|
136
|
+
|
|
137
|
+
1. Click extension icon
|
|
138
|
+
2. Right-click in popup → Inspect
|
|
139
|
+
3. In popup console, run:
|
|
140
|
+
|
|
141
|
+
```javascript
|
|
142
|
+
// Quick popup test
|
|
143
|
+
const client = createClient();
|
|
144
|
+
client.groupCreate({ title: 'Popup Test' })
|
|
145
|
+
.then(result => console.log('✅ Popup works:', result))
|
|
146
|
+
.catch(err => console.error('❌ Popup failed:', err));
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## 6. Common Issues Found
|
|
150
|
+
|
|
151
|
+
### Issue: "Cannot group extension page tabs"
|
|
152
|
+
**Symptom:** Error when popup tries to group itself
|
|
153
|
+
**Solution:** Make sure the ACTIVE tab is a regular webpage, not the popup or chrome:// page
|
|
154
|
+
|
|
155
|
+
### Issue: "activeTab is undefined"
|
|
156
|
+
**Symptom:** No tab found to add to group
|
|
157
|
+
**Solution:**
|
|
158
|
+
1. Click on a regular webpage tab FIRST
|
|
159
|
+
2. THEN open the extension popup
|
|
160
|
+
3. Try creating session
|
|
161
|
+
|
|
162
|
+
### Issue: "chrome.tabGroups is not defined"
|
|
163
|
+
**Symptom:** API not available
|
|
164
|
+
**Solution:**
|
|
165
|
+
1. Check Chrome version: `chrome://version`
|
|
166
|
+
2. Needs Chrome 89 or higher
|
|
167
|
+
3. Update Chrome if needed
|
|
168
|
+
|
|
169
|
+
## 7. Next Steps Based on Results
|
|
170
|
+
|
|
171
|
+
**If Test 5 succeeds but popup fails:**
|
|
172
|
+
→ Check popup console for errors
|
|
173
|
+
→ Verify popup.js has client.groupCreate method
|
|
174
|
+
→ Check communication between popup and background
|
|
175
|
+
|
|
176
|
+
**If Test 5 fails with "No active tab":**
|
|
177
|
+
→ Open a website in a tab
|
|
178
|
+
→ Click on that tab (make it active)
|
|
179
|
+
→ Run test again
|
|
180
|
+
|
|
181
|
+
**If SessionManager not found:**
|
|
182
|
+
→ Rebuild: `npm run build` in project root
|
|
183
|
+
→ Rebuild: `npm run build` in examples/chrome-extension
|
|
184
|
+
→ Reload extension
|
|
185
|
+
|
|
186
|
+
**If everything works in test but not in UI:**
|
|
187
|
+
→ Check popup console for JavaScript errors
|
|
188
|
+
→ Verify button event listeners attached
|
|
189
|
+
→ Check if updateSessionUI() is being called
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# Chrome Extension Example
|
|
2
|
+
|
|
3
|
+
Production-ready TypeScript example using `@btcp/browser-agent`.
|
|
4
|
+
|
|
5
|
+
## Project Structure
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
examples/chrome-extension/
|
|
9
|
+
├── src/
|
|
10
|
+
│ ├── content.ts # DOM agent + message listener
|
|
11
|
+
│ ├── background.ts # routes messages
|
|
12
|
+
│ └── popup.ts # UI using createClient
|
|
13
|
+
├── dist/ # Built output (gitignored)
|
|
14
|
+
├── manifest.json # Chrome extension manifest
|
|
15
|
+
├── popup.html # Popup UI
|
|
16
|
+
├── package.json # Build dependencies
|
|
17
|
+
├── tsconfig.json # TypeScript config
|
|
18
|
+
└── build.js # esbuild script
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Source Files
|
|
22
|
+
|
|
23
|
+
**src/content.ts** - registers DOM agent and message listener
|
|
24
|
+
```typescript
|
|
25
|
+
import { createContentAgent } from '@btcp/browser-agent/extension';
|
|
26
|
+
|
|
27
|
+
const agent = createContentAgent();
|
|
28
|
+
chrome.runtime.onMessage.addListener(agent.handleMessage);
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**src/background.ts** - routes messages
|
|
32
|
+
```typescript
|
|
33
|
+
import { setupMessageListener } from '@btcp/browser-agent/extension';
|
|
34
|
+
setupMessageListener();
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**src/popup.ts** - sends commands
|
|
38
|
+
```typescript
|
|
39
|
+
import { createClient } from '@btcp/browser-agent/extension';
|
|
40
|
+
|
|
41
|
+
const client = createClient();
|
|
42
|
+
await client.navigate('https://example.com');
|
|
43
|
+
const { tree } = await client.snapshot();
|
|
44
|
+
await client.click('@ref:5');
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Setup
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Install dependencies
|
|
51
|
+
npm install
|
|
52
|
+
|
|
53
|
+
# Build the extension
|
|
54
|
+
npm run build
|
|
55
|
+
|
|
56
|
+
# Or watch for changes
|
|
57
|
+
npm run watch
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Load Extension
|
|
61
|
+
|
|
62
|
+
1. Open `chrome://extensions`
|
|
63
|
+
2. Enable "Developer mode"
|
|
64
|
+
3. Click "Load unpacked"
|
|
65
|
+
4. Select this directory
|
|
66
|
+
|
|
67
|
+
## Architecture
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
Popup ──chrome.runtime.sendMessage──► Background (setupMessageListener)
|
|
71
|
+
│
|
|
72
|
+
chrome.tabs.sendMessage
|
|
73
|
+
▼
|
|
74
|
+
Content Script (auto-registered)
|
|
75
|
+
│
|
|
76
|
+
ContentAgent → DOM
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## API Usage
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
import { createClient } from '@btcp/browser-agent/extension';
|
|
83
|
+
|
|
84
|
+
const client = createClient();
|
|
85
|
+
|
|
86
|
+
// Navigation
|
|
87
|
+
await client.navigate('https://example.com');
|
|
88
|
+
await client.back();
|
|
89
|
+
await client.forward();
|
|
90
|
+
await client.reload();
|
|
91
|
+
|
|
92
|
+
// DOM operations
|
|
93
|
+
const { tree } = await client.snapshot();
|
|
94
|
+
await client.click('@ref:5');
|
|
95
|
+
await client.fill('@ref:3', 'hello@example.com');
|
|
96
|
+
await client.type('@ref:3', 'typing slowly', { delay: 50 });
|
|
97
|
+
const text = await client.getText('@ref:5');
|
|
98
|
+
const visible = await client.isVisible('@ref:5');
|
|
99
|
+
|
|
100
|
+
// Tab management
|
|
101
|
+
const tabs = await client.tabList();
|
|
102
|
+
const newTab = await client.tabNew({ url: 'https://github.com' });
|
|
103
|
+
await client.tabSwitch(newTab.tabId);
|
|
104
|
+
await client.tabClose(newTab.tabId);
|
|
105
|
+
|
|
106
|
+
// Screenshot
|
|
107
|
+
const base64 = await client.screenshot();
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Command Reference
|
|
111
|
+
|
|
112
|
+
### Browser Operations (BackgroundAgent)
|
|
113
|
+
|
|
114
|
+
| Method | Description |
|
|
115
|
+
|--------|-------------|
|
|
116
|
+
| `navigate(url)` | Navigate to URL |
|
|
117
|
+
| `back()` / `forward()` | History navigation |
|
|
118
|
+
| `reload()` | Reload page |
|
|
119
|
+
| `screenshot()` | Capture visible tab |
|
|
120
|
+
| `tabNew()` / `tabClose()` | Tab management |
|
|
121
|
+
| `tabSwitch()` / `tabList()` | Tab switching |
|
|
122
|
+
| `getUrl()` / `getTitle()` | Get page info |
|
|
123
|
+
|
|
124
|
+
### DOM Operations (ContentAgent)
|
|
125
|
+
|
|
126
|
+
| Method | Description |
|
|
127
|
+
|--------|-------------|
|
|
128
|
+
| `snapshot()` | Get accessibility tree with refs |
|
|
129
|
+
| `click(selector)` | Click element |
|
|
130
|
+
| `fill(selector, value)` | Set input value |
|
|
131
|
+
| `type(selector, text)` | Type text with events |
|
|
132
|
+
| `getText(selector)` | Get element text |
|
|
133
|
+
| `isVisible(selector)` | Check visibility |
|
|
134
|
+
|
|
135
|
+
## Selectors
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
// Ref from snapshot (recommended)
|
|
139
|
+
await client.click('@ref:5');
|
|
140
|
+
|
|
141
|
+
// CSS selectors
|
|
142
|
+
await client.click('#submit');
|
|
143
|
+
await client.click('.btn-primary');
|
|
144
|
+
await client.click('[data-testid="login"]');
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## License
|
|
148
|
+
|
|
149
|
+
Apache-2.0
|