btcp-browser-agent 0.1.0 → 0.1.2

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.
Files changed (136) hide show
  1. package/package.json +8 -9
  2. package/packages/core/dist/actions.d.ts +97 -0
  3. package/packages/core/dist/actions.js +940 -0
  4. package/packages/core/dist/errors.d.ts +138 -0
  5. package/packages/core/dist/errors.js +157 -0
  6. package/packages/core/dist/index.d.ts +120 -0
  7. package/packages/core/dist/index.js +134 -0
  8. package/packages/core/dist/ref-map.d.ts +16 -0
  9. package/packages/core/dist/ref-map.js +91 -0
  10. package/packages/core/dist/snapshot.d.ts +37 -0
  11. package/packages/core/dist/snapshot.js +751 -0
  12. package/packages/core/dist/types.d.ts +396 -0
  13. package/packages/core/dist/types.js +7 -0
  14. package/packages/extension/dist/background.d.ts +227 -0
  15. package/packages/extension/dist/background.js +737 -0
  16. package/packages/extension/dist/content.d.ts +18 -0
  17. package/packages/extension/dist/content.js +149 -0
  18. package/packages/extension/dist/index.d.ts +228 -0
  19. package/packages/extension/dist/index.js +350 -0
  20. package/packages/extension/dist/session-manager.d.ts +87 -0
  21. package/packages/extension/dist/session-manager.js +322 -0
  22. package/packages/extension/{src/session-types.ts → dist/session-types.d.ts} +113 -144
  23. package/packages/extension/dist/session-types.js +5 -0
  24. package/packages/extension/dist/types.d.ts +88 -0
  25. package/packages/extension/dist/types.js +7 -0
  26. package/CLAUDE.md +0 -230
  27. package/SKILL.md +0 -143
  28. package/SNAPSHOT_IMPROVEMENTS.md +0 -302
  29. package/USAGE.md +0 -146
  30. package/dist/index.d.ts.map +0 -1
  31. package/dist/index.js.map +0 -1
  32. package/docs/browser-cli-design.md +0 -500
  33. package/examples/chrome-extension/CHANGELOG.md +0 -210
  34. package/examples/chrome-extension/DEBUG.md +0 -231
  35. package/examples/chrome-extension/ERROR_FIXED.md +0 -147
  36. package/examples/chrome-extension/QUICK_TEST.md +0 -189
  37. package/examples/chrome-extension/README.md +0 -149
  38. package/examples/chrome-extension/SESSION_ONLY_MODE.md +0 -305
  39. package/examples/chrome-extension/TEST_WITH_YOUR_TABS.md +0 -97
  40. package/examples/chrome-extension/build.js +0 -43
  41. package/examples/chrome-extension/manifest.json +0 -37
  42. package/examples/chrome-extension/package-lock.json +0 -1063
  43. package/examples/chrome-extension/package.json +0 -21
  44. package/examples/chrome-extension/popup.html +0 -195
  45. package/examples/chrome-extension/src/background.ts +0 -12
  46. package/examples/chrome-extension/src/content.ts +0 -7
  47. package/examples/chrome-extension/src/popup.ts +0 -303
  48. package/examples/chrome-extension/src/scenario-google-github.ts +0 -389
  49. package/examples/chrome-extension/test-page.html +0 -127
  50. package/examples/chrome-extension/tests/README.md +0 -206
  51. package/examples/chrome-extension/tests/scenario-google-to-github-star.ts +0 -380
  52. package/examples/chrome-extension/tsconfig.json +0 -14
  53. package/examples/snapshots/README.md +0 -207
  54. package/examples/snapshots/amazon-com-detail.html +0 -9528
  55. package/examples/snapshots/amazon-com-detail.snapshot.txt +0 -997
  56. package/examples/snapshots/convert-snapshots.ts +0 -97
  57. package/examples/snapshots/edition-cnn-com.html +0 -13292
  58. package/examples/snapshots/edition-cnn-com.snapshot.txt +0 -562
  59. package/examples/snapshots/github-com-microsoft-vscode.html +0 -2916
  60. package/examples/snapshots/github-com-microsoft-vscode.snapshot.txt +0 -455
  61. package/examples/snapshots/google-search.html +0 -20012
  62. package/examples/snapshots/google-search.snapshot.txt +0 -195
  63. package/examples/snapshots/metadata.json +0 -86
  64. package/examples/snapshots/npr-org-templates.html +0 -2031
  65. package/examples/snapshots/npr-org-templates.snapshot.txt +0 -224
  66. package/examples/snapshots/stackoverflow-com.html +0 -5216
  67. package/examples/snapshots/stackoverflow-com.snapshot.txt +0 -2404
  68. package/examples/snapshots/test-all-mode.html +0 -46
  69. package/examples/snapshots/test-all-mode.snapshot.txt +0 -5
  70. package/examples/snapshots/validate.test.ts +0 -296
  71. package/packages/cli/package.json +0 -42
  72. package/packages/cli/src/__tests__/cli.test.ts +0 -434
  73. package/packages/cli/src/__tests__/errors.test.ts +0 -226
  74. package/packages/cli/src/__tests__/executor.test.ts +0 -275
  75. package/packages/cli/src/__tests__/formatter.test.ts +0 -260
  76. package/packages/cli/src/__tests__/parser.test.ts +0 -288
  77. package/packages/cli/src/__tests__/suggestions.test.ts +0 -255
  78. package/packages/cli/src/commands/back.ts +0 -22
  79. package/packages/cli/src/commands/check.ts +0 -33
  80. package/packages/cli/src/commands/clear.ts +0 -33
  81. package/packages/cli/src/commands/click.ts +0 -32
  82. package/packages/cli/src/commands/closetab.ts +0 -31
  83. package/packages/cli/src/commands/eval.ts +0 -41
  84. package/packages/cli/src/commands/fill.ts +0 -30
  85. package/packages/cli/src/commands/focus.ts +0 -33
  86. package/packages/cli/src/commands/forward.ts +0 -22
  87. package/packages/cli/src/commands/goto.ts +0 -34
  88. package/packages/cli/src/commands/help.ts +0 -162
  89. package/packages/cli/src/commands/hover.ts +0 -34
  90. package/packages/cli/src/commands/index.ts +0 -129
  91. package/packages/cli/src/commands/newtab.ts +0 -35
  92. package/packages/cli/src/commands/press.ts +0 -40
  93. package/packages/cli/src/commands/reload.ts +0 -25
  94. package/packages/cli/src/commands/screenshot.ts +0 -27
  95. package/packages/cli/src/commands/scroll.ts +0 -64
  96. package/packages/cli/src/commands/select.ts +0 -35
  97. package/packages/cli/src/commands/snapshot.ts +0 -21
  98. package/packages/cli/src/commands/tab.ts +0 -32
  99. package/packages/cli/src/commands/tabs.ts +0 -26
  100. package/packages/cli/src/commands/text.ts +0 -27
  101. package/packages/cli/src/commands/title.ts +0 -17
  102. package/packages/cli/src/commands/type.ts +0 -38
  103. package/packages/cli/src/commands/uncheck.ts +0 -33
  104. package/packages/cli/src/commands/url.ts +0 -17
  105. package/packages/cli/src/commands/wait.ts +0 -54
  106. package/packages/cli/src/errors.ts +0 -164
  107. package/packages/cli/src/executor.ts +0 -68
  108. package/packages/cli/src/formatter.ts +0 -215
  109. package/packages/cli/src/index.ts +0 -257
  110. package/packages/cli/src/parser.ts +0 -195
  111. package/packages/cli/src/suggestions.ts +0 -207
  112. package/packages/cli/src/terminal/Terminal.ts +0 -365
  113. package/packages/cli/src/terminal/index.ts +0 -5
  114. package/packages/cli/src/types.ts +0 -155
  115. package/packages/cli/tsconfig.json +0 -20
  116. package/packages/core/package.json +0 -35
  117. package/packages/core/src/actions.ts +0 -1210
  118. package/packages/core/src/errors.ts +0 -296
  119. package/packages/core/src/index.test.ts +0 -638
  120. package/packages/core/src/index.ts +0 -220
  121. package/packages/core/src/ref-map.ts +0 -107
  122. package/packages/core/src/snapshot.ts +0 -873
  123. package/packages/core/src/types.ts +0 -536
  124. package/packages/core/tsconfig.json +0 -23
  125. package/packages/extension/README.md +0 -129
  126. package/packages/extension/package.json +0 -43
  127. package/packages/extension/src/background.ts +0 -888
  128. package/packages/extension/src/content.ts +0 -172
  129. package/packages/extension/src/index.ts +0 -579
  130. package/packages/extension/src/session-manager.ts +0 -385
  131. package/packages/extension/src/types.ts +0 -162
  132. package/packages/extension/tsconfig.json +0 -28
  133. package/src/index.ts +0 -64
  134. package/tsconfig.build.json +0 -12
  135. package/tsconfig.json +0 -26
  136. package/vitest.config.ts +0 -13
@@ -1,389 +0,0 @@
1
- /**
2
- * Google → GitHub → Star Scenario
3
- * AI Agent workflow demonstration that can be run from the popup
4
- */
5
-
6
- import type { Client } from '../../../packages/extension/src/index.js';
7
-
8
- const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
9
-
10
- interface LogCallback {
11
- (message: string, type?: 'info' | 'success' | 'error' | 'warning'): void;
12
- }
13
-
14
- /**
15
- * Find an element in the snapshot tree based on criteria
16
- * Snapshot format: "- ROLE "label" [attributes] [@ref:N]"
17
- */
18
- function findElement(tree: string, criteria: {
19
- role?: string;
20
- name?: string;
21
- nameContains?: string;
22
- type?: string;
23
- }): string | null {
24
- const lines = tree.split('\n');
25
-
26
- for (const line of lines) {
27
- const refMatch = line.match(/@ref:(\d+)/);
28
- if (!refMatch) continue;
29
-
30
- const ref = `@ref:${refMatch[1]}`;
31
- let matches = true;
32
-
33
- // Match role (uppercase in snapshot: BUTTON, TEXTBOX, LINK, etc.)
34
- if (criteria.role) {
35
- const roleUpper = criteria.role.toUpperCase();
36
- if (!line.includes(roleUpper)) matches = false;
37
- }
38
-
39
- // Match exact name in quotes: "Search"
40
- if (criteria.name) {
41
- const namePattern = `"${criteria.name}"`;
42
- if (!line.includes(namePattern)) matches = false;
43
- }
44
-
45
- // Match name contains (case-insensitive)
46
- if (criteria.nameContains) {
47
- const quotedTextMatch = line.match(/"([^"]+)"/);
48
- if (!quotedTextMatch || !quotedTextMatch[1].toLowerCase().includes(criteria.nameContains.toLowerCase())) {
49
- matches = false;
50
- }
51
- }
52
-
53
- // Match type attribute: [type=search]
54
- if (criteria.type) {
55
- const typePattern = `type=${criteria.type}`;
56
- if (!line.includes(typePattern)) matches = false;
57
- }
58
-
59
- if (matches) return ref;
60
- }
61
-
62
- return null;
63
- }
64
-
65
- /**
66
- * Find first link containing specific domain
67
- * Looks for LINK role with domain in the line
68
- */
69
- function findLinkByDomain(tree: string, domain: string): string | null {
70
- const lines = tree.split('\n');
71
-
72
- for (const line of lines) {
73
- // Check for LINK role (uppercase in snapshot)
74
- if (!line.includes("LINK")) continue;
75
-
76
- const refMatch = line.match(/@ref:(\d+)/);
77
- if (!refMatch) continue;
78
-
79
- // Check if domain appears anywhere in the line (case-insensitive)
80
- if (line.toLowerCase().includes(domain.toLowerCase())) {
81
- return `@ref:${refMatch[1]}`;
82
- }
83
- }
84
-
85
- return null;
86
- }
87
-
88
- /**
89
- * Run the Google → GitHub → Star scenario
90
- */
91
- export async function runGoogleGithubScenario(client: Client, log: LogCallback): Promise<void> {
92
- const TOTAL_STEPS = 15;
93
- let currentStep = 0;
94
-
95
- try {
96
- // Step 1: Navigate to Google
97
- currentStep++;
98
- log(`[${currentStep}/${TOTAL_STEPS}] Navigating to Google...`, 'info');
99
- await client.navigate('https://www.google.com');
100
- log('✅ Loaded Google', 'success');
101
- await sleep(1500);
102
-
103
- // Step 2: Take snapshot
104
- currentStep++;
105
- log(`[${currentStep}/${TOTAL_STEPS}] 🤔 Taking snapshot to analyze page...`, 'info');
106
- const snapshot1 = await client.snapshot({ format: 'tree' });
107
- log(`✅ Found ${snapshot1.split('\n').length} elements`, 'success');
108
- log(`\n📸 SNAPSHOT (Google Homepage - first 30 lines):\n${snapshot1.split('\n').slice(0, 30).join('\n')}\n... (${snapshot1.split('\n').length - 30} more lines)`, 'info');
109
- await sleep(500);
110
-
111
- // Step 3: Find search input
112
- currentStep++;
113
- log(`[${currentStep}/${TOTAL_STEPS}] 🔍 Analyzing snapshot for search box...`, 'info');
114
- log(`💭 Thinking: Trying role=combobox first...`, 'info');
115
- let searchInput = findElement(snapshot1, { role: 'combobox' });
116
- if (!searchInput) {
117
- log(`💭 Thinking: Not found. Trying role=searchbox...`, 'info');
118
- searchInput = findElement(snapshot1, { role: 'searchbox' });
119
- }
120
- if (!searchInput) {
121
- log(`💭 Thinking: Not found. Trying textbox with "search" in name...`, 'info');
122
- searchInput = findElement(snapshot1, { role: 'textbox', nameContains: 'search' });
123
- }
124
-
125
- if (!searchInput) {
126
- throw new Error('Could not find search input');
127
- }
128
- log(`✅ Found search box: ${searchInput}`, 'success');
129
- await sleep(500);
130
-
131
- // Step 4: Type search query
132
- currentStep++;
133
- log(`[${currentStep}/${TOTAL_STEPS}] Typing "btcp-cowork"...`, 'info');
134
- await client.type(searchInput, 'btcp-cowork');
135
- log('✅ Query typed', 'success');
136
- await sleep(500);
137
-
138
- // Step 5: Submit search
139
- currentStep++;
140
- log(`[${currentStep}/${TOTAL_STEPS}] Submitting search...`, 'info');
141
- log(`💭 Thinking: Looking for Google Search button...`, 'info');
142
-
143
- // Look for the actual "Google Search" button
144
- const searchButton = findElement(snapshot1, { role: 'button', name: 'Google Search' });
145
-
146
- if (!searchButton) {
147
- log('⚠️ Google Search button not found, trying Enter key...', 'warning');
148
- // Click the search input first to ensure focus
149
- await client.click(searchInput);
150
- await sleep(300);
151
- await client.execute({
152
- id: crypto.randomUUID(),
153
- action: 'press',
154
- key: 'Enter',
155
- });
156
- } else {
157
- log(`💭 Thinking: Found button ${searchButton}, clicking it...`, 'info');
158
- await client.click(searchButton);
159
- }
160
- log('✅ Search submitted', 'success');
161
- await sleep(3000); // Increased wait time for results to load
162
-
163
- // Step 6: Wait and verify results loaded
164
- currentStep++;
165
- log(`[${currentStep}/${TOTAL_STEPS}] Checking results page...`, 'info');
166
- const currentUrl = await client.getUrl();
167
- if (!currentUrl.includes('google.com/search')) {
168
- log('⚠️ URL may not be results page', 'warning');
169
- } else {
170
- log('✅ On results page', 'success');
171
- }
172
- await sleep(1000);
173
-
174
- // Step 7: Take snapshot of results
175
- currentStep++;
176
- log(`[${currentStep}/${TOTAL_STEPS}] 🤔 Taking snapshot of search results...`, 'info');
177
- const snapshot2 = await client.snapshot({ format: 'tree' });
178
- log(`✅ Found ${snapshot2.split('\n').length} elements`, 'success');
179
-
180
- // Show links found in snapshot
181
- const linkLines = snapshot2.split('\n').filter(line => line.includes('LINK') && line.includes('@ref:'));
182
- log(`\n📸 SNAPSHOT (Links found - first 10):\n${linkLines.slice(0, 10).join('\n')}`, 'info');
183
- await sleep(500);
184
-
185
- // Step 8: Find GitHub/BTCP link
186
- currentStep++;
187
- log(`[${currentStep}/${TOTAL_STEPS}] 🔍 Searching for BTCP repository link...`, 'info');
188
- log(`💭 Thinking: Scanning ${linkLines.length} links...`, 'info');
189
-
190
- // Try to find browser-tool-calling-protocol link first
191
- let githubLink = findLinkByDomain(snapshot2, 'browser-tool-calling-protocol');
192
-
193
- if (!githubLink) {
194
- log(`💭 Thinking: No BTCP link found, trying github.com...`, 'info');
195
- githubLink = findLinkByDomain(snapshot2, 'github.com');
196
- }
197
-
198
- if (!githubLink) {
199
- // Fallback: try to find first search result (skip navigation links)
200
- log(`💭 Thinking: Trying first search result...`, 'info');
201
- const lines = snapshot2.split('\n');
202
- for (const line of lines) {
203
- // Skip navigation links (Images, Videos, News, etc.)
204
- if (line.includes('LINK') && !line.includes('Images') && !line.includes('Videos') &&
205
- !line.includes('News') && !line.includes('Shopping') && !line.includes('AI Mode')) {
206
- const refMatch = line.match(/@ref:(\d+)/);
207
- if (refMatch && parseInt(refMatch[1]) >= 18) { // Start from ref:18 which is first result
208
- githubLink = `@ref:${refMatch[1]}`;
209
- log(`💭 Thinking: Found first result: ${line.substring(0, 80)}...`, 'info');
210
- break;
211
- }
212
- }
213
- }
214
- }
215
-
216
- if (!githubLink) {
217
- throw new Error('No GitHub links found in results');
218
- }
219
- log(`✅ Found link: ${githubLink}`, 'success');
220
- await sleep(500);
221
-
222
- // Step 9: Click GitHub link
223
- currentStep++;
224
- log(`[${currentStep}/${TOTAL_STEPS}] Navigating to GitHub...`, 'info');
225
- await client.click(githubLink);
226
- log('✅ Clicked link', 'success');
227
- await sleep(3000);
228
-
229
- // Step 10: Verify on GitHub
230
- currentStep++;
231
- log(`[${currentStep}/${TOTAL_STEPS}] Verifying GitHub page...`, 'info');
232
- const githubUrl = await client.getUrl();
233
- if (!githubUrl.includes('github.com')) {
234
- log('⚠️ May not be on GitHub', 'warning');
235
- } else {
236
- log('✅ On GitHub repository page', 'success');
237
- }
238
- await sleep(1000);
239
-
240
- // Step 11: Initial encounter & assessment
241
- currentStep++;
242
- log(`[${currentStep}/${TOTAL_STEPS}] 🤔 Taking snapshot to understand page structure...`, 'info');
243
- const snapshot3 = await client.snapshot({ format: 'tree' });
244
- const totalLines = snapshot3.split('\n').length;
245
- const snapshotHeader = snapshot3.split('\n').find(line => line.startsWith('SNAPSHOT:')) || '';
246
- const refsMatch = snapshotHeader.match(/refs=(\d+)/);
247
- const totalRefs = refsMatch ? parseInt(refsMatch[1]) : 0;
248
-
249
- log(`📸 Snapshot captured: ${totalLines} lines, ${totalRefs} interactive elements`, 'success');
250
- log(`💭 Thinking: This is a large page - processing all ${totalRefs} elements would be inefficient`, 'info');
251
- log(`💭 Thinking: Strategy: Preview first 100 lines to understand page structure`, 'info');
252
-
253
- const preview = snapshot3.split('\n').slice(0, 100).join('\n');
254
- log(`\n📸 PREVIEW (first 100 lines):\n${preview}`, 'info');
255
- await sleep(1000);
256
-
257
- // Step 12: Strategic analysis
258
- currentStep++;
259
- log(`[${currentStep}/${TOTAL_STEPS}] 🧠 Analyzing preview for patterns...`, 'info');
260
- log(`💭 Thinking: I see BUTTON elements, LINK elements, navigation structure`, 'info');
261
- log(`💭 Thinking: My goal: Find star button`, 'info');
262
- log(`💭 Thinking: Question: Does "star" appear in the preview?`, 'info');
263
-
264
- const hasStarInPreview = preview.toLowerCase().includes('star');
265
- if (hasStarInPreview) {
266
- log(`💭 Thinking: Result: Yes, star references found in preview`, 'success');
267
- } else {
268
- log(`💭 Thinking: Result: No star in preview - need to search full page`, 'info');
269
- }
270
- await sleep(500);
271
-
272
- // Step 13: Formulate filtering strategy
273
- currentStep++;
274
- log(`[${currentStep}/${TOTAL_STEPS}] 🎯 Decision point - How to narrow down to star button?`, 'info');
275
- log(`💭 Thinking: Option A: Use grep filter for "star" keyword → Fast, targeted`, 'info');
276
- log(`💭 Thinking: Option B: Use role=button filter → Gets all buttons, still large`, 'info');
277
- log(`💭 Thinking: Option C: Combine filters: grep="star" + analyze results`, 'info');
278
- log(`💭 Thinking: Choosing Option A: grep filter is most efficient`, 'success');
279
- log(`💭 Thinking: Executing: snapshot({ grep: { pattern: 'star', ignoreCase: true } })`, 'info');
280
- await sleep(500);
281
-
282
- // Step 14: Execute filtered snapshot
283
- currentStep++;
284
- log(`[${currentStep}/${TOTAL_STEPS}] 🔍 Taking filtered snapshot with grep="star"...`, 'info');
285
- const filteredSnapshot = await client.snapshot({
286
- format: 'tree',
287
- grep: { pattern: 'star', ignoreCase: true }
288
- });
289
-
290
- const filteredLines = filteredSnapshot.split('\n').filter(line => line.includes('@ref:'));
291
- log(`✅ Filtered snapshot: ${filteredLines.length} matching elements (reduced from ${totalRefs} refs)`, 'success');
292
- log(`\n📸 FILTERED RESULTS:\n${filteredLines.join('\n')}`, 'info');
293
- await sleep(1000);
294
-
295
- // Step 15: Intelligent element selection
296
- currentStep++;
297
- log(`[${currentStep}/${TOTAL_STEPS}] 🧩 Analyzing filtered results...`, 'info');
298
- log(`💭 Thinking: The grep filter returned ${filteredLines.length} elements with "star"`, 'info');
299
- log(`💭 Thinking: Now I need to identify which one is the star action button`, 'info');
300
-
301
- // Analyze what grep returned - purely use the filtered snapshot
302
- log(`💭 Thinking: Examining each filtered element:`, 'info');
303
- for (const line of filteredLines.slice(0, 5)) {
304
- log(` ${line}`, 'info');
305
- }
306
- if (filteredLines.length > 5) {
307
- log(` ... and ${filteredLines.length - 5} more`, 'info');
308
- }
309
-
310
- // Use findElement helper on the already-filtered snapshot
311
- log(`💭 Thinking: Using findElement to locate button with "star" in name`, 'info');
312
- let starButton = findElement(filteredSnapshot, { role: 'button', nameContains: 'star' });
313
-
314
- // Check if we found "Unstar" instead (means already starred)
315
- const hasUnstar = filteredSnapshot.toLowerCase().includes('"unstar"');
316
-
317
- if (hasUnstar) {
318
- log(`💭 Thinking: Found "Unstar" button → repo already starred`, 'info');
319
- log(`⚠️ Repository already starred (Unstar button present)`, 'warning');
320
- log(`ℹ️ Scenario completed - repo is already starred`, 'info');
321
- starButton = findElement(filteredSnapshot, { role: 'button', nameContains: 'unstar' });
322
- } else if (starButton) {
323
- log(`💭 Thinking: Found "Star" button → need to click it to star`, 'success');
324
- log(`💭 Thinking: Decision: Click ${starButton} "Star" button`, 'success');
325
- }
326
-
327
- if (!starButton) {
328
- log('⚠️ Could not find star button (may need login)', 'warning');
329
- log('ℹ️ Scenario completed up to GitHub navigation', 'info');
330
- return;
331
- }
332
-
333
- log(`✅ Selected element: ${starButton}`, 'success');
334
- await sleep(500);
335
-
336
- // Step 16: Execute action (only if not already starred)
337
- if (!hasUnstar) {
338
- currentStep++;
339
- log(`[${currentStep}/${TOTAL_STEPS}] 🎯 Clicking star button...`, 'info');
340
- await client.click(starButton);
341
- log('✅ Star button clicked', 'success');
342
- log('⏳ Waiting for UI update...', 'info');
343
- await sleep(2000);
344
- } else {
345
- currentStep++;
346
- log(`[${currentStep}/${TOTAL_STEPS}] ⏭️ Skipping star action (already starred)`, 'info');
347
- }
348
-
349
- // Step 17: Verification
350
- currentStep++;
351
- log(`[${currentStep}/${TOTAL_STEPS}] 🔍 Verifying action succeeded...`, 'info');
352
- log(`💭 Thinking: Taking verification snapshot with grep="star"...`, 'info');
353
-
354
- const finalUrl = await client.getUrl();
355
- if (finalUrl.includes('login')) {
356
- log('⚠️ Redirected to login - authentication required', 'warning');
357
- log('ℹ️ In production, agent would handle OAuth flow', 'info');
358
- } else {
359
- const verifySnapshot = await client.snapshot({
360
- format: 'tree',
361
- grep: { pattern: 'star', ignoreCase: true }
362
- });
363
-
364
- const hasUnstar = verifySnapshot.toLowerCase().includes('"unstar"');
365
- log(`💭 Thinking: Checking if "Unstar" now appears (indicates starring succeeded)`, 'info');
366
-
367
- if (hasUnstar) {
368
- log('✅ Success! Button changed from "Star" to "Unstar"', 'success');
369
- log('🎉 Repository successfully starred!', 'success');
370
- } else {
371
- log('✅ Star action completed', 'success');
372
- }
373
- }
374
-
375
- currentStep++;
376
- log(`[${currentStep}/${TOTAL_STEPS}] ✨ Scenario complete!`, 'success');
377
- log('───────────────────────────', 'info');
378
- log('Summary:', 'info');
379
- log('• Searched Google for "btcp-cowork"', 'info');
380
- log('• Found and clicked GitHub link', 'info');
381
- log('• Navigated to repository', 'info');
382
- log('• Attempted to star repository', 'info');
383
- log('───────────────────────────', 'info');
384
-
385
- } catch (error) {
386
- log(`❌ Scenario failed: ${error instanceof Error ? error.message : String(error)}`, 'error');
387
- throw error;
388
- }
389
- }
@@ -1,127 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <meta charset="UTF-8">
5
- <title>BTCP Extension Test Page</title>
6
- <style>
7
- body {
8
- font-family: system-ui, -apple-system, sans-serif;
9
- max-width: 800px;
10
- margin: 50px auto;
11
- padding: 20px;
12
- line-height: 1.6;
13
- }
14
- .card {
15
- background: #f8f9fa;
16
- border: 2px solid #dee2e6;
17
- border-radius: 8px;
18
- padding: 20px;
19
- margin: 20px 0;
20
- }
21
- .success { border-color: #28a745; background: #d4edda; }
22
- .info { border-color: #17a2b8; background: #d1ecf1; }
23
- .warning { border-color: #ffc107; background: #fff3cd; }
24
- h1 { color: #2563eb; }
25
- h2 { margin-top: 0; }
26
- code {
27
- background: #e9ecef;
28
- padding: 2px 6px;
29
- border-radius: 3px;
30
- font-family: 'Courier New', monospace;
31
- }
32
- ol { padding-left: 20px; }
33
- li { margin: 10px 0; }
34
- </style>
35
- </head>
36
- <body>
37
- <h1>🧪 BTCP Extension Test Page</h1>
38
-
39
- <div class="card info">
40
- <h2>Purpose</h2>
41
- <p>This page helps you test the BTCP Browser Agent extension. Use this as your "active tab" when testing session creation.</p>
42
- </div>
43
-
44
- <div class="card success">
45
- <h2>✅ You're Ready to Test!</h2>
46
- <p>This page is loaded successfully. Now follow these steps:</p>
47
- <ol>
48
- <li>Make sure this tab is <strong>active</strong> (you're viewing it now)</li>
49
- <li>Click the <strong>BTCP Browser Agent extension icon</strong> in your Chrome toolbar</li>
50
- <li>In the popup, click <strong>"Start New Session"</strong></li>
51
- <li>You should see this tab get added to a <strong>blue tab group</strong> labeled "BTCP Session 1"</li>
52
- </ol>
53
- </div>
54
-
55
- <div class="card warning">
56
- <h2>⚠️ Troubleshooting</h2>
57
- <p><strong>If the button doesn't work:</strong></p>
58
- <ol>
59
- <li>Open Chrome DevTools on the popup (right-click popup → Inspect)</li>
60
- <li>Check the Console tab for error messages</li>
61
- <li>Also check the Background Service Worker console:
62
- <ul>
63
- <li>Go to <code>chrome://extensions</code></li>
64
- <li>Find "BTCP Browser Agent"</li>
65
- <li>Click "service worker" link</li>
66
- <li>Check console for errors</li>
67
- </ul>
68
- </li>
69
- </ol>
70
- </div>
71
-
72
- <div class="card info">
73
- <h2>📋 Expected Behavior</h2>
74
- <p><strong>When you start a session:</strong></p>
75
- <ul>
76
- <li>✅ This tab should be added to a blue tab group</li>
77
- <li>✅ The group should be labeled "BTCP Session 1"</li>
78
- <li>✅ The popup should show:
79
- <ul>
80
- <li>Blue session status box</li>
81
- <li>Session name: "BTCP Session 1"</li>
82
- <li>Tab count: "1 tab"</li>
83
- <li>"Close Session" button (red)</li>
84
- </ul>
85
- </li>
86
- </ul>
87
-
88
- <p><strong>When you click "New Tab" in the popup:</strong></p>
89
- <ul>
90
- <li>✅ A new tab should open</li>
91
- <li>✅ It should automatically join the "BTCP Session 1" group</li>
92
- <li>✅ Tab count should update to "2 tabs"</li>
93
- </ul>
94
-
95
- <p><strong>When you click "Close Session":</strong></p>
96
- <ul>
97
- <li>✅ All tabs in the group should close at once</li>
98
- <li>✅ This includes this test page!</li>
99
- </ul>
100
- </div>
101
-
102
- <div class="card">
103
- <h2>🔍 Quick Debug Check</h2>
104
- <p>Open the Console (F12 → Console tab) and run this:</p>
105
- <pre><code>chrome.tabGroups.query({}).then(groups =>
106
- console.log('Active groups:', groups.length, groups)
107
- );</code></pre>
108
- <p>This shows all active tab groups in your browser.</p>
109
- </div>
110
-
111
- <div class="card info">
112
- <h2>📚 More Help</h2>
113
- <p>For detailed debugging instructions, see:</p>
114
- <ul>
115
- <li><code>DEBUG.md</code> - Full debugging guide</li>
116
- <li><code>QUICK_TEST.md</code> - Quick console tests</li>
117
- </ul>
118
- <p>Both files are in the extension directory.</p>
119
- </div>
120
-
121
- <script>
122
- console.log('BTCP Test Page loaded');
123
- console.log('Tab ID:', chrome?.runtime?.id || 'N/A');
124
- console.log('Ready for testing!');
125
- </script>
126
- </body>
127
- </html>