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,305 @@
|
|
|
1
|
+
# Session-Only Mode
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The BTCP Browser Agent **only manages tabs within its session/tab group**. No operations are allowed outside of a session.
|
|
6
|
+
|
|
7
|
+
## Key Principle
|
|
8
|
+
|
|
9
|
+
**Session is Required** - All operations require an active session:
|
|
10
|
+
|
|
11
|
+
- ❌ Cannot list tabs without a session
|
|
12
|
+
- ❌ Cannot create tabs without a session
|
|
13
|
+
- ❌ Cannot navigate without a session
|
|
14
|
+
- ❌ Cannot perform DOM operations without a session
|
|
15
|
+
- ✅ Must create session first, then all operations work within that session
|
|
16
|
+
|
|
17
|
+
## How It Works
|
|
18
|
+
|
|
19
|
+
### 1. Session Must Be Created First
|
|
20
|
+
|
|
21
|
+
```javascript
|
|
22
|
+
// Create a session to start working
|
|
23
|
+
await client.groupCreate({ title: "BTCP Session 1" });
|
|
24
|
+
|
|
25
|
+
// Now all operations work (scoped to session)
|
|
26
|
+
await client.tabNew({ url: "https://example.com" });
|
|
27
|
+
await client.listTabs(); // Only session tabs
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### 2. Without Session = Error
|
|
31
|
+
|
|
32
|
+
```javascript
|
|
33
|
+
// Try to list tabs without session
|
|
34
|
+
await client.listTabs();
|
|
35
|
+
// ❌ Error: "No active session. Create a session first to manage tabs."
|
|
36
|
+
|
|
37
|
+
// Try to create tab without session
|
|
38
|
+
await client.tabNew({ url: "https://example.com" });
|
|
39
|
+
// ❌ Error: "No active session. Create a session first to manage tabs."
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 3. Operations Are Session-Scoped
|
|
43
|
+
|
|
44
|
+
Once a session exists, all operations only affect tabs in that session:
|
|
45
|
+
|
|
46
|
+
```javascript
|
|
47
|
+
// Create session with tab A
|
|
48
|
+
await client.groupCreate(); // Tab A joins session
|
|
49
|
+
|
|
50
|
+
// Create new tabs (auto-added to session)
|
|
51
|
+
await client.tabNew({ url: "https://example.com" }); // Tab B
|
|
52
|
+
await client.tabNew({ url: "https://github.com" }); // Tab C
|
|
53
|
+
|
|
54
|
+
// List tabs (only shows A, B, C)
|
|
55
|
+
const tabs = await client.listTabs(); // [A, B, C]
|
|
56
|
+
|
|
57
|
+
// User manually opens Tab D outside session
|
|
58
|
+
|
|
59
|
+
// Try to list tabs (still only shows session tabs)
|
|
60
|
+
const tabs2 = await client.listTabs(); // [A, B, C] - no Tab D
|
|
61
|
+
|
|
62
|
+
// Try to access Tab D
|
|
63
|
+
await client.switchTab(tabD.id);
|
|
64
|
+
// ❌ Error: "Cannot switch to tab: tab is not in the active session"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Implementation Details
|
|
68
|
+
|
|
69
|
+
### Session Requirement Check
|
|
70
|
+
|
|
71
|
+
Every operation checks for active session:
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
async listTabs(): Promise<TabInfo[]> {
|
|
75
|
+
const sessionGroupId = this.sessionManager.getActiveSessionGroupId();
|
|
76
|
+
|
|
77
|
+
// Session is required
|
|
78
|
+
if (sessionGroupId === null) {
|
|
79
|
+
throw new Error('No active session. Create a session first.');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Only query tabs in the session group
|
|
83
|
+
const tabs = await chrome.tabs.query({ groupId: sessionGroupId });
|
|
84
|
+
return tabs.map(mapToTabInfo);
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Tab Validation
|
|
89
|
+
|
|
90
|
+
Operations validate tab membership:
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
private async isTabInSession(tabId: number): Promise<boolean> {
|
|
94
|
+
const sessionGroupId = this.sessionManager.getActiveSessionGroupId();
|
|
95
|
+
|
|
96
|
+
// Session required
|
|
97
|
+
if (sessionGroupId === null) {
|
|
98
|
+
throw new Error('No active session.');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Check if tab is in session
|
|
102
|
+
const tab = await chrome.tabs.get(tabId);
|
|
103
|
+
return tab.groupId === sessionGroupId;
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### New Tab Creation
|
|
108
|
+
|
|
109
|
+
New tabs are automatically added to session:
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
async newTab(options?: { url?: string }): Promise<TabInfo> {
|
|
113
|
+
// Check session exists
|
|
114
|
+
if (!this.sessionManager.getActiveSessionGroupId()) {
|
|
115
|
+
throw new Error('No active session.');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Create tab
|
|
119
|
+
const tab = await chrome.tabs.create({ url: options?.url });
|
|
120
|
+
|
|
121
|
+
// Add to session
|
|
122
|
+
const added = await this.sessionManager.addTabToActiveSession(tab.id);
|
|
123
|
+
if (!added) {
|
|
124
|
+
// Cleanup if failed
|
|
125
|
+
await chrome.tabs.remove(tab.id);
|
|
126
|
+
throw new Error('Failed to add tab to session');
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return mapToTabInfo(tab);
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Usage Example
|
|
134
|
+
|
|
135
|
+
### Complete Workflow
|
|
136
|
+
|
|
137
|
+
```javascript
|
|
138
|
+
// 1. Create session (required first step)
|
|
139
|
+
await client.groupCreate({ title: "Work Session" });
|
|
140
|
+
// Current tab joins blue group "Work Session"
|
|
141
|
+
|
|
142
|
+
// 2. Now can create tabs (auto-added to session)
|
|
143
|
+
await client.tabNew({ url: "https://example.com" });
|
|
144
|
+
await client.tabNew({ url: "https://github.com" });
|
|
145
|
+
|
|
146
|
+
// 3. List tabs (only shows session tabs)
|
|
147
|
+
const tabs = await client.listTabs();
|
|
148
|
+
console.log(tabs.length); // 3 tabs
|
|
149
|
+
|
|
150
|
+
// 4. Navigate, interact (only session tabs)
|
|
151
|
+
await client.navigate("https://newsite.com");
|
|
152
|
+
await client.click("#button");
|
|
153
|
+
await client.fill("#input", "value");
|
|
154
|
+
|
|
155
|
+
// 5. Close session (closes all tabs)
|
|
156
|
+
const session = await client.sessionGetCurrent();
|
|
157
|
+
await client.groupDelete(session.groupId);
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Error Handling
|
|
161
|
+
|
|
162
|
+
```javascript
|
|
163
|
+
try {
|
|
164
|
+
// Try operation without session
|
|
165
|
+
await client.listTabs();
|
|
166
|
+
} catch (err) {
|
|
167
|
+
if (err.message.includes('No active session')) {
|
|
168
|
+
// Create session first
|
|
169
|
+
await client.groupCreate();
|
|
170
|
+
|
|
171
|
+
// Now retry
|
|
172
|
+
const tabs = await client.listTabs();
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Benefits
|
|
178
|
+
|
|
179
|
+
### 1. Security & Isolation
|
|
180
|
+
- Extension cannot access tabs outside its scope
|
|
181
|
+
- User's personal tabs are protected
|
|
182
|
+
- Clear boundaries enforced by code
|
|
183
|
+
|
|
184
|
+
### 2. Explicit Consent
|
|
185
|
+
- User must explicitly create session
|
|
186
|
+
- Visual indicator (tab group color/label)
|
|
187
|
+
- No accidental access to unrelated tabs
|
|
188
|
+
|
|
189
|
+
### 3. Clean Separation
|
|
190
|
+
- Each session is independent
|
|
191
|
+
- Easy to manage multiple workflows
|
|
192
|
+
- Clear visual organization
|
|
193
|
+
|
|
194
|
+
### 4. Predictable Behavior
|
|
195
|
+
- All operations scoped to one group
|
|
196
|
+
- No ambiguity about which tabs are managed
|
|
197
|
+
- Consistent error messages
|
|
198
|
+
|
|
199
|
+
## Visual Indicators
|
|
200
|
+
|
|
201
|
+
### Chrome Tab Groups
|
|
202
|
+
- Session tabs have **colored border** (e.g., blue)
|
|
203
|
+
- Group label shows session name (e.g., "BTCP Session 1")
|
|
204
|
+
- Can collapse/expand the group
|
|
205
|
+
- Easy to see which tabs are in scope
|
|
206
|
+
|
|
207
|
+
### Extension Popup
|
|
208
|
+
- Shows session status (active/inactive)
|
|
209
|
+
- Displays session name and tab count
|
|
210
|
+
- Info: "Extension only manages tabs within the active session"
|
|
211
|
+
- Buttons disabled when no session
|
|
212
|
+
|
|
213
|
+
## Comparison
|
|
214
|
+
|
|
215
|
+
### Before (Universal Access)
|
|
216
|
+
```javascript
|
|
217
|
+
// Could access any tab
|
|
218
|
+
const allTabs = await client.listTabs(); // All tabs in window
|
|
219
|
+
|
|
220
|
+
// Could navigate any tab
|
|
221
|
+
await client.switchTab(anyTabId); // Works
|
|
222
|
+
|
|
223
|
+
// Could close any tab
|
|
224
|
+
await client.tabClose(anyTabId); // Works
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### After (Session-Only)
|
|
228
|
+
```javascript
|
|
229
|
+
// Must create session first
|
|
230
|
+
await client.groupCreate();
|
|
231
|
+
|
|
232
|
+
// Only session tabs
|
|
233
|
+
const sessionTabs = await client.listTabs(); // Only grouped tabs
|
|
234
|
+
|
|
235
|
+
// Only session tabs accessible
|
|
236
|
+
await client.switchTab(sessionTabId); // ✅ Works
|
|
237
|
+
await client.switchTab(outsideTabId); // ❌ Error
|
|
238
|
+
|
|
239
|
+
// Only session tabs closable
|
|
240
|
+
await client.tabClose(sessionTabId); // ✅ Works
|
|
241
|
+
await client.tabClose(outsideTabId); // ❌ Error
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## FAQ
|
|
245
|
+
|
|
246
|
+
**Q: Can I use the extension without creating a session?**
|
|
247
|
+
A: No. Session creation is required for all operations.
|
|
248
|
+
|
|
249
|
+
**Q: What if I manually move a tab out of the session group?**
|
|
250
|
+
A: The extension immediately loses access to that tab.
|
|
251
|
+
|
|
252
|
+
**Q: Can I manually add tabs to the session?**
|
|
253
|
+
A: Yes! Drag any tab into the session group, and it becomes accessible.
|
|
254
|
+
|
|
255
|
+
**Q: What happens if the session group is deleted?**
|
|
256
|
+
A: All operations will fail until a new session is created.
|
|
257
|
+
|
|
258
|
+
**Q: Can operations work across multiple sessions?**
|
|
259
|
+
A: No. Only one active session at a time, and operations are scoped to it.
|
|
260
|
+
|
|
261
|
+
**Q: Why is session required?**
|
|
262
|
+
A: Security, isolation, and explicit user consent. The extension should only manage what the user explicitly adds to the session.
|
|
263
|
+
|
|
264
|
+
## Testing
|
|
265
|
+
|
|
266
|
+
### Test Session Requirement
|
|
267
|
+
|
|
268
|
+
```javascript
|
|
269
|
+
// 1. Try without session (should fail)
|
|
270
|
+
try {
|
|
271
|
+
await client.listTabs();
|
|
272
|
+
console.error('❌ Should have failed');
|
|
273
|
+
} catch (err) {
|
|
274
|
+
console.log('✅ Correctly requires session:', err.message);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// 2. Create session
|
|
278
|
+
await client.groupCreate({ title: "Test" });
|
|
279
|
+
|
|
280
|
+
// 3. Operations now work
|
|
281
|
+
const tabs = await client.listTabs();
|
|
282
|
+
console.log('✅ Session allows operations:', tabs.length);
|
|
283
|
+
|
|
284
|
+
// 4. Try accessing outside tab (should fail)
|
|
285
|
+
// (manually open tab outside session first)
|
|
286
|
+
try {
|
|
287
|
+
await client.switchTab(outsideTabId);
|
|
288
|
+
console.error('❌ Should have blocked outside tab');
|
|
289
|
+
} catch (err) {
|
|
290
|
+
console.log('✅ Correctly blocks outside tab:', err.message);
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## Summary
|
|
295
|
+
|
|
296
|
+
**Core Principle**: Session-first, session-only
|
|
297
|
+
|
|
298
|
+
- ✅ Session required for all operations
|
|
299
|
+
- ✅ All operations scoped to session tabs only
|
|
300
|
+
- ✅ Clear errors when session missing
|
|
301
|
+
- ✅ Visual boundaries via tab groups
|
|
302
|
+
- ✅ Explicit user consent required
|
|
303
|
+
- ✅ Maximum security and isolation
|
|
304
|
+
|
|
305
|
+
The extension is now a **pure session manager** - it only works within the boundaries of its explicitly created session.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Test Session with Your Current Tabs
|
|
2
|
+
|
|
3
|
+
## ✅ Good News: Extension is Working!
|
|
4
|
+
|
|
5
|
+
Your tab list command worked perfectly. You have 5 tabs:
|
|
6
|
+
- GitHub BTCP repo
|
|
7
|
+
- Claude.ai session
|
|
8
|
+
- GitHub Pull Request
|
|
9
|
+
- **YouTube video (ACTIVE)** ← Perfect for testing!
|
|
10
|
+
- Chrome extensions page
|
|
11
|
+
|
|
12
|
+
## Test the Session Now
|
|
13
|
+
|
|
14
|
+
Since the YouTube tab (ID: 1892096437) is active, it's perfect for testing:
|
|
15
|
+
|
|
16
|
+
### Step 1: Create Session
|
|
17
|
+
1. **Click the extension icon** (should still be open)
|
|
18
|
+
2. **Click "Start New Session"** button
|
|
19
|
+
3. **Watch the YouTube tab** - it should get a blue group border
|
|
20
|
+
|
|
21
|
+
### Step 2: Verify Success
|
|
22
|
+
Check if you see:
|
|
23
|
+
- ✅ Blue/colored border around the YouTube tab
|
|
24
|
+
- ✅ Group label appears: "BTCP Session 1"
|
|
25
|
+
- ✅ Popup shows: "BTCP Session 1" with "1 tab"
|
|
26
|
+
|
|
27
|
+
### Step 3: Test Auto-Grouping
|
|
28
|
+
1. In the popup, click **"New Tab"** button
|
|
29
|
+
2. A new tab should open at example.com
|
|
30
|
+
3. **It should automatically join the "BTCP Session 1" group**
|
|
31
|
+
4. Popup should update to show "2 tabs"
|
|
32
|
+
|
|
33
|
+
### Step 4: Test Close Session
|
|
34
|
+
1. Click **"Close Session"** button (red button)
|
|
35
|
+
2. **Both tabs in the group should close** (YouTube + new tab)
|
|
36
|
+
|
|
37
|
+
## What to Look For
|
|
38
|
+
|
|
39
|
+
### Console Output (Background Service Worker)
|
|
40
|
+
When you click "Start New Session", you should see:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
[SessionManager] createGroup called with options: {}
|
|
44
|
+
[SessionManager] No tabIds provided, getting active tab...
|
|
45
|
+
[SessionManager] Active tab: {id: 1892096437, url: "https://www.youtube.com/...", ...}
|
|
46
|
+
[SessionManager] Creating group with tabs: [1892096437]
|
|
47
|
+
[SessionManager] Group created with ID: <some-number>
|
|
48
|
+
[SessionManager] Group updated with title: BTCP Session 1
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Visual Feedback
|
|
52
|
+
In your browser:
|
|
53
|
+
- YouTube tab gets colored border/background
|
|
54
|
+
- Tab shows group indicator
|
|
55
|
+
- Can collapse/expand the group by clicking the group label
|
|
56
|
+
|
|
57
|
+
## If It Works
|
|
58
|
+
|
|
59
|
+
Congratulations! 🎉 Your session management is fully functional!
|
|
60
|
+
|
|
61
|
+
You can now:
|
|
62
|
+
- ✅ Start sessions to organize tabs
|
|
63
|
+
- ✅ Auto-group new tabs created by the extension
|
|
64
|
+
- ✅ Close entire sessions at once
|
|
65
|
+
- ✅ Track how many tabs are in each session
|
|
66
|
+
|
|
67
|
+
## If It Doesn't Work
|
|
68
|
+
|
|
69
|
+
Check these:
|
|
70
|
+
|
|
71
|
+
1. **Error in popup console?**
|
|
72
|
+
- Right-click popup → Inspect → Console tab
|
|
73
|
+
- Share the error message
|
|
74
|
+
|
|
75
|
+
2. **Error in background console?**
|
|
76
|
+
- Go to chrome://extensions
|
|
77
|
+
- Click "service worker" under BTCP Browser Agent
|
|
78
|
+
- Check console for errors
|
|
79
|
+
|
|
80
|
+
3. **Nothing happens?**
|
|
81
|
+
- Make sure YouTube tab is actually active (click on it first)
|
|
82
|
+
- Try refreshing the extension
|
|
83
|
+
- Check if "Start New Session" button is enabled
|
|
84
|
+
|
|
85
|
+
## Next: Make Sessions Automatic
|
|
86
|
+
|
|
87
|
+
Based on your earlier comment about wanting `launch` to handle sessions, we can make this more automatic:
|
|
88
|
+
|
|
89
|
+
**Option 1:** First `tabNew` automatically creates a session
|
|
90
|
+
- User doesn't need to click "Start New Session"
|
|
91
|
+
- Just click "New Tab" and session auto-starts
|
|
92
|
+
|
|
93
|
+
**Option 2:** Session always exists
|
|
94
|
+
- Background script creates default session on startup
|
|
95
|
+
- All operations happen in that session
|
|
96
|
+
|
|
97
|
+
Would you like me to implement either of these?
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as esbuild from 'esbuild';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
|
|
5
|
+
const watch = process.argv.includes('--watch');
|
|
6
|
+
|
|
7
|
+
const config = {
|
|
8
|
+
entryPoints: [
|
|
9
|
+
'src/background.ts',
|
|
10
|
+
'src/content.ts',
|
|
11
|
+
'src/popup.ts',
|
|
12
|
+
],
|
|
13
|
+
bundle: true,
|
|
14
|
+
outdir: 'dist',
|
|
15
|
+
format: 'esm',
|
|
16
|
+
platform: 'browser',
|
|
17
|
+
target: 'chrome120',
|
|
18
|
+
sourcemap: true,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// Copy static files to dist
|
|
22
|
+
function copyStaticFiles() {
|
|
23
|
+
const filesToCopy = ['manifest.json', 'popup.html'];
|
|
24
|
+
|
|
25
|
+
if (!fs.existsSync('dist')) {
|
|
26
|
+
fs.mkdirSync('dist', { recursive: true });
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
for (const file of filesToCopy) {
|
|
30
|
+
fs.copyFileSync(file, path.join('dist', file));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (watch) {
|
|
35
|
+
const ctx = await esbuild.context(config);
|
|
36
|
+
await ctx.watch();
|
|
37
|
+
copyStaticFiles();
|
|
38
|
+
console.log('Watching for changes...');
|
|
39
|
+
} else {
|
|
40
|
+
await esbuild.build(config);
|
|
41
|
+
copyStaticFiles();
|
|
42
|
+
console.log('Build complete');
|
|
43
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"manifest_version": 3,
|
|
3
|
+
"name": "BTCP Browser Agent",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"description": "Browser automation with DOM actions and navigation",
|
|
6
|
+
|
|
7
|
+
"permissions": [
|
|
8
|
+
"activeTab",
|
|
9
|
+
"tabs",
|
|
10
|
+
"tabGroups",
|
|
11
|
+
"scripting",
|
|
12
|
+
"storage"
|
|
13
|
+
],
|
|
14
|
+
|
|
15
|
+
"host_permissions": [
|
|
16
|
+
"<all_urls>"
|
|
17
|
+
],
|
|
18
|
+
|
|
19
|
+
"background": {
|
|
20
|
+
"service_worker": "background.js",
|
|
21
|
+
"type": "module"
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
"content_scripts": [
|
|
25
|
+
{
|
|
26
|
+
"matches": ["<all_urls>"],
|
|
27
|
+
"js": ["content.js"],
|
|
28
|
+
"run_at": "document_idle",
|
|
29
|
+
"all_frames": true
|
|
30
|
+
}
|
|
31
|
+
],
|
|
32
|
+
|
|
33
|
+
"action": {
|
|
34
|
+
"default_popup": "popup.html",
|
|
35
|
+
"default_title": "BTCP Agent"
|
|
36
|
+
}
|
|
37
|
+
}
|