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.
Files changed (117) hide show
  1. package/CLAUDE.md +230 -0
  2. package/LICENSE +21 -0
  3. package/README.md +309 -0
  4. package/SKILL.md +143 -0
  5. package/SNAPSHOT_IMPROVEMENTS.md +302 -0
  6. package/USAGE.md +146 -0
  7. package/dist/index.d.ts +34 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +35 -0
  10. package/dist/index.js.map +1 -0
  11. package/docs/browser-cli-design.md +500 -0
  12. package/examples/chrome-extension/CHANGELOG.md +210 -0
  13. package/examples/chrome-extension/DEBUG.md +231 -0
  14. package/examples/chrome-extension/ERROR_FIXED.md +147 -0
  15. package/examples/chrome-extension/QUICK_TEST.md +189 -0
  16. package/examples/chrome-extension/README.md +149 -0
  17. package/examples/chrome-extension/SESSION_ONLY_MODE.md +305 -0
  18. package/examples/chrome-extension/TEST_WITH_YOUR_TABS.md +97 -0
  19. package/examples/chrome-extension/build.js +43 -0
  20. package/examples/chrome-extension/manifest.json +37 -0
  21. package/examples/chrome-extension/package-lock.json +1063 -0
  22. package/examples/chrome-extension/package.json +21 -0
  23. package/examples/chrome-extension/popup.html +195 -0
  24. package/examples/chrome-extension/src/background.ts +12 -0
  25. package/examples/chrome-extension/src/content.ts +7 -0
  26. package/examples/chrome-extension/src/popup.ts +303 -0
  27. package/examples/chrome-extension/src/scenario-google-github.ts +389 -0
  28. package/examples/chrome-extension/test-page.html +127 -0
  29. package/examples/chrome-extension/tests/README.md +206 -0
  30. package/examples/chrome-extension/tests/scenario-google-to-github-star.ts +380 -0
  31. package/examples/chrome-extension/tsconfig.json +14 -0
  32. package/examples/snapshots/README.md +207 -0
  33. package/examples/snapshots/amazon-com-detail.html +9528 -0
  34. package/examples/snapshots/amazon-com-detail.snapshot.txt +997 -0
  35. package/examples/snapshots/convert-snapshots.ts +97 -0
  36. package/examples/snapshots/edition-cnn-com.html +13292 -0
  37. package/examples/snapshots/edition-cnn-com.snapshot.txt +562 -0
  38. package/examples/snapshots/github-com-microsoft-vscode.html +2916 -0
  39. package/examples/snapshots/github-com-microsoft-vscode.snapshot.txt +455 -0
  40. package/examples/snapshots/google-search.html +20012 -0
  41. package/examples/snapshots/google-search.snapshot.txt +195 -0
  42. package/examples/snapshots/metadata.json +86 -0
  43. package/examples/snapshots/npr-org-templates.html +2031 -0
  44. package/examples/snapshots/npr-org-templates.snapshot.txt +224 -0
  45. package/examples/snapshots/stackoverflow-com.html +5216 -0
  46. package/examples/snapshots/stackoverflow-com.snapshot.txt +2404 -0
  47. package/examples/snapshots/test-all-mode.html +46 -0
  48. package/examples/snapshots/test-all-mode.snapshot.txt +5 -0
  49. package/examples/snapshots/validate.test.ts +296 -0
  50. package/package.json +65 -0
  51. package/packages/cli/package.json +42 -0
  52. package/packages/cli/src/__tests__/cli.test.ts +434 -0
  53. package/packages/cli/src/__tests__/errors.test.ts +226 -0
  54. package/packages/cli/src/__tests__/executor.test.ts +275 -0
  55. package/packages/cli/src/__tests__/formatter.test.ts +260 -0
  56. package/packages/cli/src/__tests__/parser.test.ts +288 -0
  57. package/packages/cli/src/__tests__/suggestions.test.ts +255 -0
  58. package/packages/cli/src/commands/back.ts +22 -0
  59. package/packages/cli/src/commands/check.ts +33 -0
  60. package/packages/cli/src/commands/clear.ts +33 -0
  61. package/packages/cli/src/commands/click.ts +32 -0
  62. package/packages/cli/src/commands/closetab.ts +31 -0
  63. package/packages/cli/src/commands/eval.ts +41 -0
  64. package/packages/cli/src/commands/fill.ts +30 -0
  65. package/packages/cli/src/commands/focus.ts +33 -0
  66. package/packages/cli/src/commands/forward.ts +22 -0
  67. package/packages/cli/src/commands/goto.ts +34 -0
  68. package/packages/cli/src/commands/help.ts +162 -0
  69. package/packages/cli/src/commands/hover.ts +34 -0
  70. package/packages/cli/src/commands/index.ts +129 -0
  71. package/packages/cli/src/commands/newtab.ts +35 -0
  72. package/packages/cli/src/commands/press.ts +40 -0
  73. package/packages/cli/src/commands/reload.ts +25 -0
  74. package/packages/cli/src/commands/screenshot.ts +27 -0
  75. package/packages/cli/src/commands/scroll.ts +64 -0
  76. package/packages/cli/src/commands/select.ts +35 -0
  77. package/packages/cli/src/commands/snapshot.ts +21 -0
  78. package/packages/cli/src/commands/tab.ts +32 -0
  79. package/packages/cli/src/commands/tabs.ts +26 -0
  80. package/packages/cli/src/commands/text.ts +27 -0
  81. package/packages/cli/src/commands/title.ts +17 -0
  82. package/packages/cli/src/commands/type.ts +38 -0
  83. package/packages/cli/src/commands/uncheck.ts +33 -0
  84. package/packages/cli/src/commands/url.ts +17 -0
  85. package/packages/cli/src/commands/wait.ts +54 -0
  86. package/packages/cli/src/errors.ts +164 -0
  87. package/packages/cli/src/executor.ts +68 -0
  88. package/packages/cli/src/formatter.ts +215 -0
  89. package/packages/cli/src/index.ts +257 -0
  90. package/packages/cli/src/parser.ts +195 -0
  91. package/packages/cli/src/suggestions.ts +207 -0
  92. package/packages/cli/src/terminal/Terminal.ts +365 -0
  93. package/packages/cli/src/terminal/index.ts +5 -0
  94. package/packages/cli/src/types.ts +155 -0
  95. package/packages/cli/tsconfig.json +20 -0
  96. package/packages/core/package.json +35 -0
  97. package/packages/core/src/actions.ts +1210 -0
  98. package/packages/core/src/errors.ts +296 -0
  99. package/packages/core/src/index.test.ts +638 -0
  100. package/packages/core/src/index.ts +220 -0
  101. package/packages/core/src/ref-map.ts +107 -0
  102. package/packages/core/src/snapshot.ts +873 -0
  103. package/packages/core/src/types.ts +536 -0
  104. package/packages/core/tsconfig.json +23 -0
  105. package/packages/extension/README.md +129 -0
  106. package/packages/extension/package.json +43 -0
  107. package/packages/extension/src/background.ts +888 -0
  108. package/packages/extension/src/content.ts +172 -0
  109. package/packages/extension/src/index.ts +579 -0
  110. package/packages/extension/src/session-manager.ts +385 -0
  111. package/packages/extension/src/session-types.ts +144 -0
  112. package/packages/extension/src/types.ts +162 -0
  113. package/packages/extension/tsconfig.json +28 -0
  114. package/src/index.ts +64 -0
  115. package/tsconfig.build.json +12 -0
  116. package/tsconfig.json +26 -0
  117. package/vitest.config.ts +13 -0
@@ -0,0 +1,296 @@
1
+ /**
2
+ * Error handling utilities for BTCP Browser Agent
3
+ *
4
+ * Provides structured error types with machine-readable codes and
5
+ * actionable suggestions to help AI agents self-correct.
6
+ */
7
+
8
+ /**
9
+ * Machine-readable error codes for programmatic error handling
10
+ */
11
+ export enum ErrorCode {
12
+ /** Element not found with given selector */
13
+ ELEMENT_NOT_FOUND = 'ELEMENT_NOT_FOUND',
14
+
15
+ /** Element exists but doesn't support the requested action */
16
+ ELEMENT_NOT_COMPATIBLE = 'ELEMENT_NOT_COMPATIBLE',
17
+
18
+ /** Ref ID has expired (cleared by new snapshot) */
19
+ REF_EXPIRED = 'REF_EXPIRED',
20
+
21
+ /** Invalid selector syntax or format */
22
+ INVALID_SELECTOR = 'INVALID_SELECTOR',
23
+
24
+ /** Operation timed out waiting for condition */
25
+ TIMEOUT = 'TIMEOUT',
26
+
27
+ /** Element exists but is not visible */
28
+ ELEMENT_NOT_VISIBLE = 'ELEMENT_NOT_VISIBLE',
29
+
30
+ /** Element exists but is disabled */
31
+ ELEMENT_DISABLED = 'ELEMENT_DISABLED',
32
+
33
+ /** Conflicting parameters provided to command */
34
+ INVALID_PARAMETERS = 'INVALID_PARAMETERS',
35
+
36
+ /** Element is not in the expected state */
37
+ INVALID_STATE = 'INVALID_STATE',
38
+
39
+ /** Network or navigation error */
40
+ NAVIGATION_ERROR = 'NAVIGATION_ERROR',
41
+ }
42
+
43
+ /**
44
+ * Structured context information for errors
45
+ */
46
+ export interface ErrorContext {
47
+ /** The selector that was used */
48
+ selector?: string;
49
+
50
+ /** Expected element type or role */
51
+ expectedType?: string;
52
+
53
+ /** Actual element type or role found */
54
+ actualType?: string;
55
+
56
+ /** Current state of the element */
57
+ elementState?: {
58
+ attached: boolean;
59
+ visible: boolean;
60
+ enabled: boolean;
61
+ };
62
+
63
+ /** Actions available for this element */
64
+ availableActions?: string[];
65
+
66
+ /** Similar selectors that were found */
67
+ similarSelectors?: Array<{
68
+ selector: string;
69
+ role: string;
70
+ name: string;
71
+ similarity?: number;
72
+ }>;
73
+
74
+ /** Nearby interactive elements */
75
+ nearbyElements?: Array<{
76
+ ref: string;
77
+ role: string;
78
+ name: string;
79
+ }>;
80
+
81
+ /** Additional context-specific data */
82
+ [key: string]: any;
83
+ }
84
+
85
+ /**
86
+ * Detailed error with structured data for AI agents
87
+ *
88
+ * Provides both human-readable messages and machine-readable
89
+ * error codes, context, and recovery suggestions.
90
+ *
91
+ * @example
92
+ * ```typescript
93
+ * throw new DetailedError(
94
+ * ErrorCode.ELEMENT_NOT_FOUND,
95
+ * "Element not found: #submit-btn",
96
+ * {
97
+ * selector: "#submit-btn",
98
+ * similarSelectors: [
99
+ * { selector: "#submit-button", role: "button", name: "Submit" }
100
+ * ]
101
+ * },
102
+ * [
103
+ * "Try using selector: #submit-button",
104
+ * "Run snapshot({ interactive: true }) to see all clickable elements"
105
+ * ]
106
+ * );
107
+ * ```
108
+ */
109
+ export class DetailedError extends Error {
110
+ public readonly code: ErrorCode;
111
+ public readonly context: ErrorContext;
112
+ public readonly suggestions: string[];
113
+
114
+ constructor(
115
+ code: ErrorCode,
116
+ message: string,
117
+ context: ErrorContext = {},
118
+ suggestions: string[] = []
119
+ ) {
120
+ // Build enhanced message with suggestions
121
+ let fullMessage = message;
122
+
123
+ if (suggestions.length > 0) {
124
+ fullMessage += '\n\nSuggestions:';
125
+ suggestions.forEach(suggestion => {
126
+ fullMessage += `\n - ${suggestion}`;
127
+ });
128
+ }
129
+
130
+ super(fullMessage);
131
+ this.name = 'DetailedError';
132
+ this.code = code;
133
+ this.context = context;
134
+ this.suggestions = suggestions;
135
+ }
136
+
137
+ /**
138
+ * Convert to structured object for API responses
139
+ */
140
+ toJSON() {
141
+ return {
142
+ name: this.name,
143
+ message: this.message,
144
+ code: this.code,
145
+ context: this.context,
146
+ suggestions: this.suggestions,
147
+ };
148
+ }
149
+ }
150
+
151
+ /**
152
+ * Helper function to create element not found error with suggestions
153
+ */
154
+ export function createElementNotFoundError(
155
+ selector: string,
156
+ options: {
157
+ similarSelectors?: Array<{ selector: string; role: string; name: string }>;
158
+ nearbyElements?: Array<{ ref: string; role: string; name: string }>;
159
+ isRef?: boolean;
160
+ } = {}
161
+ ): DetailedError {
162
+ const { similarSelectors = [], nearbyElements = [], isRef = false } = options;
163
+
164
+ const suggestions: string[] = [];
165
+
166
+ if (isRef) {
167
+ suggestions.push(
168
+ 'Ref may have expired. Refs are cleared on snapshot() calls and page navigation.',
169
+ 'Call snapshot() again to get fresh refs.'
170
+ );
171
+ }
172
+
173
+ if (similarSelectors.length > 0) {
174
+ suggestions.push(
175
+ `Similar selectors found: ${similarSelectors.map(s => s.selector).join(', ')}`
176
+ );
177
+ }
178
+
179
+ if (nearbyElements.length > 0) {
180
+ suggestions.push(
181
+ 'Run snapshot({ interactive: true }) to see all clickable elements'
182
+ );
183
+ }
184
+
185
+ return new DetailedError(
186
+ isRef ? ErrorCode.REF_EXPIRED : ErrorCode.ELEMENT_NOT_FOUND,
187
+ `Element not found: ${selector}`,
188
+ {
189
+ selector,
190
+ similarSelectors,
191
+ nearbyElements,
192
+ },
193
+ suggestions
194
+ );
195
+ }
196
+
197
+ /**
198
+ * Helper function to create element not compatible error
199
+ */
200
+ export function createElementNotCompatibleError(
201
+ selector: string,
202
+ action: string,
203
+ actualType: string,
204
+ expectedTypes: string[],
205
+ availableActions: string[] = []
206
+ ): DetailedError {
207
+ const suggestions: string[] = [];
208
+
209
+ if (availableActions.length > 0) {
210
+ suggestions.push(
211
+ `Available actions for ${actualType}: ${availableActions.join(', ')}`
212
+ );
213
+ }
214
+
215
+ suggestions.push(
216
+ `Use snapshot() to verify element type before attempting action`
217
+ );
218
+
219
+ return new DetailedError(
220
+ ErrorCode.ELEMENT_NOT_COMPATIBLE,
221
+ `Element ${selector} is ${actualType}, cannot perform action: ${action}`,
222
+ {
223
+ selector,
224
+ actualType,
225
+ expectedType: expectedTypes.join(' or '),
226
+ availableActions,
227
+ },
228
+ suggestions
229
+ );
230
+ }
231
+
232
+ /**
233
+ * Helper function to create timeout error with state information
234
+ */
235
+ export function createTimeoutError(
236
+ selector: string | undefined,
237
+ expectedState: string,
238
+ currentState?: {
239
+ attached: boolean;
240
+ visible: boolean;
241
+ enabled: boolean;
242
+ }
243
+ ): DetailedError {
244
+ const suggestions: string[] = [];
245
+
246
+ if (currentState) {
247
+ if (currentState.attached && !currentState.visible && expectedState === 'visible') {
248
+ suggestions.push(
249
+ 'Element is attached but not visible. Check CSS display/visibility properties.',
250
+ 'Try state="attached" if you just need element to exist in DOM.'
251
+ );
252
+ }
253
+
254
+ if (currentState.attached && currentState.visible && !currentState.enabled && expectedState === 'enabled') {
255
+ suggestions.push(
256
+ 'Element is visible but disabled. Check disabled attribute or aria-disabled.',
257
+ 'Wait for the condition that enables the element, or use force option if available.'
258
+ );
259
+ }
260
+ }
261
+
262
+ suggestions.push('Increase timeout value if element appears slowly.');
263
+
264
+ const message = selector
265
+ ? `Timeout waiting for ${selector} to be ${expectedState}`
266
+ : `Timeout waiting for page to be ${expectedState}`;
267
+
268
+ return new DetailedError(
269
+ ErrorCode.TIMEOUT,
270
+ message,
271
+ {
272
+ selector,
273
+ expectedType: expectedState,
274
+ elementState: currentState,
275
+ },
276
+ suggestions
277
+ );
278
+ }
279
+
280
+ /**
281
+ * Helper function to create invalid parameters error
282
+ */
283
+ export function createInvalidParametersError(
284
+ message: string,
285
+ conflictingParams: string[],
286
+ suggestion: string
287
+ ): DetailedError {
288
+ return new DetailedError(
289
+ ErrorCode.INVALID_PARAMETERS,
290
+ message,
291
+ {
292
+ conflictingParams,
293
+ },
294
+ [suggestion]
295
+ );
296
+ }