btcp-browser-agent 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
@@ -0,0 +1,138 @@
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
+ * Machine-readable error codes for programmatic error handling
9
+ */
10
+ export declare enum ErrorCode {
11
+ /** Element not found with given selector */
12
+ ELEMENT_NOT_FOUND = "ELEMENT_NOT_FOUND",
13
+ /** Element exists but doesn't support the requested action */
14
+ ELEMENT_NOT_COMPATIBLE = "ELEMENT_NOT_COMPATIBLE",
15
+ /** Ref ID has expired (cleared by new snapshot) */
16
+ REF_EXPIRED = "REF_EXPIRED",
17
+ /** Invalid selector syntax or format */
18
+ INVALID_SELECTOR = "INVALID_SELECTOR",
19
+ /** Operation timed out waiting for condition */
20
+ TIMEOUT = "TIMEOUT",
21
+ /** Element exists but is not visible */
22
+ ELEMENT_NOT_VISIBLE = "ELEMENT_NOT_VISIBLE",
23
+ /** Element exists but is disabled */
24
+ ELEMENT_DISABLED = "ELEMENT_DISABLED",
25
+ /** Conflicting parameters provided to command */
26
+ INVALID_PARAMETERS = "INVALID_PARAMETERS",
27
+ /** Element is not in the expected state */
28
+ INVALID_STATE = "INVALID_STATE",
29
+ /** Network or navigation error */
30
+ NAVIGATION_ERROR = "NAVIGATION_ERROR"
31
+ }
32
+ /**
33
+ * Structured context information for errors
34
+ */
35
+ export interface ErrorContext {
36
+ /** The selector that was used */
37
+ selector?: string;
38
+ /** Expected element type or role */
39
+ expectedType?: string;
40
+ /** Actual element type or role found */
41
+ actualType?: string;
42
+ /** Current state of the element */
43
+ elementState?: {
44
+ attached: boolean;
45
+ visible: boolean;
46
+ enabled: boolean;
47
+ };
48
+ /** Actions available for this element */
49
+ availableActions?: string[];
50
+ /** Similar selectors that were found */
51
+ similarSelectors?: Array<{
52
+ selector: string;
53
+ role: string;
54
+ name: string;
55
+ similarity?: number;
56
+ }>;
57
+ /** Nearby interactive elements */
58
+ nearbyElements?: Array<{
59
+ ref: string;
60
+ role: string;
61
+ name: string;
62
+ }>;
63
+ /** Additional context-specific data */
64
+ [key: string]: any;
65
+ }
66
+ /**
67
+ * Detailed error with structured data for AI agents
68
+ *
69
+ * Provides both human-readable messages and machine-readable
70
+ * error codes, context, and recovery suggestions.
71
+ *
72
+ * @example
73
+ * ```typescript
74
+ * throw new DetailedError(
75
+ * ErrorCode.ELEMENT_NOT_FOUND,
76
+ * "Element not found: #submit-btn",
77
+ * {
78
+ * selector: "#submit-btn",
79
+ * similarSelectors: [
80
+ * { selector: "#submit-button", role: "button", name: "Submit" }
81
+ * ]
82
+ * },
83
+ * [
84
+ * "Try using selector: #submit-button",
85
+ * "Run snapshot({ interactive: true }) to see all clickable elements"
86
+ * ]
87
+ * );
88
+ * ```
89
+ */
90
+ export declare class DetailedError extends Error {
91
+ readonly code: ErrorCode;
92
+ readonly context: ErrorContext;
93
+ readonly suggestions: string[];
94
+ constructor(code: ErrorCode, message: string, context?: ErrorContext, suggestions?: string[]);
95
+ /**
96
+ * Convert to structured object for API responses
97
+ */
98
+ toJSON(): {
99
+ name: string;
100
+ message: string;
101
+ code: ErrorCode;
102
+ context: ErrorContext;
103
+ suggestions: string[];
104
+ };
105
+ }
106
+ /**
107
+ * Helper function to create element not found error with suggestions
108
+ */
109
+ export declare function createElementNotFoundError(selector: string, options?: {
110
+ similarSelectors?: Array<{
111
+ selector: string;
112
+ role: string;
113
+ name: string;
114
+ }>;
115
+ nearbyElements?: Array<{
116
+ ref: string;
117
+ role: string;
118
+ name: string;
119
+ }>;
120
+ isRef?: boolean;
121
+ }): DetailedError;
122
+ /**
123
+ * Helper function to create element not compatible error
124
+ */
125
+ export declare function createElementNotCompatibleError(selector: string, action: string, actualType: string, expectedTypes: string[], availableActions?: string[]): DetailedError;
126
+ /**
127
+ * Helper function to create timeout error with state information
128
+ */
129
+ export declare function createTimeoutError(selector: string | undefined, expectedState: string, currentState?: {
130
+ attached: boolean;
131
+ visible: boolean;
132
+ enabled: boolean;
133
+ }): DetailedError;
134
+ /**
135
+ * Helper function to create invalid parameters error
136
+ */
137
+ export declare function createInvalidParametersError(message: string, conflictingParams: string[], suggestion: string): DetailedError;
138
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1,157 @@
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
+ * Machine-readable error codes for programmatic error handling
9
+ */
10
+ export var ErrorCode;
11
+ (function (ErrorCode) {
12
+ /** Element not found with given selector */
13
+ ErrorCode["ELEMENT_NOT_FOUND"] = "ELEMENT_NOT_FOUND";
14
+ /** Element exists but doesn't support the requested action */
15
+ ErrorCode["ELEMENT_NOT_COMPATIBLE"] = "ELEMENT_NOT_COMPATIBLE";
16
+ /** Ref ID has expired (cleared by new snapshot) */
17
+ ErrorCode["REF_EXPIRED"] = "REF_EXPIRED";
18
+ /** Invalid selector syntax or format */
19
+ ErrorCode["INVALID_SELECTOR"] = "INVALID_SELECTOR";
20
+ /** Operation timed out waiting for condition */
21
+ ErrorCode["TIMEOUT"] = "TIMEOUT";
22
+ /** Element exists but is not visible */
23
+ ErrorCode["ELEMENT_NOT_VISIBLE"] = "ELEMENT_NOT_VISIBLE";
24
+ /** Element exists but is disabled */
25
+ ErrorCode["ELEMENT_DISABLED"] = "ELEMENT_DISABLED";
26
+ /** Conflicting parameters provided to command */
27
+ ErrorCode["INVALID_PARAMETERS"] = "INVALID_PARAMETERS";
28
+ /** Element is not in the expected state */
29
+ ErrorCode["INVALID_STATE"] = "INVALID_STATE";
30
+ /** Network or navigation error */
31
+ ErrorCode["NAVIGATION_ERROR"] = "NAVIGATION_ERROR";
32
+ })(ErrorCode || (ErrorCode = {}));
33
+ /**
34
+ * Detailed error with structured data for AI agents
35
+ *
36
+ * Provides both human-readable messages and machine-readable
37
+ * error codes, context, and recovery suggestions.
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * throw new DetailedError(
42
+ * ErrorCode.ELEMENT_NOT_FOUND,
43
+ * "Element not found: #submit-btn",
44
+ * {
45
+ * selector: "#submit-btn",
46
+ * similarSelectors: [
47
+ * { selector: "#submit-button", role: "button", name: "Submit" }
48
+ * ]
49
+ * },
50
+ * [
51
+ * "Try using selector: #submit-button",
52
+ * "Run snapshot({ interactive: true }) to see all clickable elements"
53
+ * ]
54
+ * );
55
+ * ```
56
+ */
57
+ export class DetailedError extends Error {
58
+ code;
59
+ context;
60
+ suggestions;
61
+ constructor(code, message, context = {}, suggestions = []) {
62
+ // Build enhanced message with suggestions
63
+ let fullMessage = message;
64
+ if (suggestions.length > 0) {
65
+ fullMessage += '\n\nSuggestions:';
66
+ suggestions.forEach(suggestion => {
67
+ fullMessage += `\n - ${suggestion}`;
68
+ });
69
+ }
70
+ super(fullMessage);
71
+ this.name = 'DetailedError';
72
+ this.code = code;
73
+ this.context = context;
74
+ this.suggestions = suggestions;
75
+ }
76
+ /**
77
+ * Convert to structured object for API responses
78
+ */
79
+ toJSON() {
80
+ return {
81
+ name: this.name,
82
+ message: this.message,
83
+ code: this.code,
84
+ context: this.context,
85
+ suggestions: this.suggestions,
86
+ };
87
+ }
88
+ }
89
+ /**
90
+ * Helper function to create element not found error with suggestions
91
+ */
92
+ export function createElementNotFoundError(selector, options = {}) {
93
+ const { similarSelectors = [], nearbyElements = [], isRef = false } = options;
94
+ const suggestions = [];
95
+ if (isRef) {
96
+ suggestions.push('Ref may have expired. Refs are cleared on snapshot() calls and page navigation.', 'Call snapshot() again to get fresh refs.');
97
+ }
98
+ if (similarSelectors.length > 0) {
99
+ suggestions.push(`Similar selectors found: ${similarSelectors.map(s => s.selector).join(', ')}`);
100
+ }
101
+ if (nearbyElements.length > 0) {
102
+ suggestions.push('Run snapshot({ interactive: true }) to see all clickable elements');
103
+ }
104
+ return new DetailedError(isRef ? ErrorCode.REF_EXPIRED : ErrorCode.ELEMENT_NOT_FOUND, `Element not found: ${selector}`, {
105
+ selector,
106
+ similarSelectors,
107
+ nearbyElements,
108
+ }, suggestions);
109
+ }
110
+ /**
111
+ * Helper function to create element not compatible error
112
+ */
113
+ export function createElementNotCompatibleError(selector, action, actualType, expectedTypes, availableActions = []) {
114
+ const suggestions = [];
115
+ if (availableActions.length > 0) {
116
+ suggestions.push(`Available actions for ${actualType}: ${availableActions.join(', ')}`);
117
+ }
118
+ suggestions.push(`Use snapshot() to verify element type before attempting action`);
119
+ return new DetailedError(ErrorCode.ELEMENT_NOT_COMPATIBLE, `Element ${selector} is ${actualType}, cannot perform action: ${action}`, {
120
+ selector,
121
+ actualType,
122
+ expectedType: expectedTypes.join(' or '),
123
+ availableActions,
124
+ }, suggestions);
125
+ }
126
+ /**
127
+ * Helper function to create timeout error with state information
128
+ */
129
+ export function createTimeoutError(selector, expectedState, currentState) {
130
+ const suggestions = [];
131
+ if (currentState) {
132
+ if (currentState.attached && !currentState.visible && expectedState === 'visible') {
133
+ suggestions.push('Element is attached but not visible. Check CSS display/visibility properties.', 'Try state="attached" if you just need element to exist in DOM.');
134
+ }
135
+ if (currentState.attached && currentState.visible && !currentState.enabled && expectedState === 'enabled') {
136
+ suggestions.push('Element is visible but disabled. Check disabled attribute or aria-disabled.', 'Wait for the condition that enables the element, or use force option if available.');
137
+ }
138
+ }
139
+ suggestions.push('Increase timeout value if element appears slowly.');
140
+ const message = selector
141
+ ? `Timeout waiting for ${selector} to be ${expectedState}`
142
+ : `Timeout waiting for page to be ${expectedState}`;
143
+ return new DetailedError(ErrorCode.TIMEOUT, message, {
144
+ selector,
145
+ expectedType: expectedState,
146
+ elementState: currentState,
147
+ }, suggestions);
148
+ }
149
+ /**
150
+ * Helper function to create invalid parameters error
151
+ */
152
+ export function createInvalidParametersError(message, conflictingParams, suggestion) {
153
+ return new DetailedError(ErrorCode.INVALID_PARAMETERS, message, {
154
+ conflictingParams,
155
+ }, [suggestion]);
156
+ }
157
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1,120 @@
1
+ /**
2
+ * @btcp/core
3
+ *
4
+ * Core DOM actions for browser automation.
5
+ * Runs in content script context (web page, extension content script, iframe).
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { createContentAgent } from '@btcp/core';
10
+ *
11
+ * const agent = createContentAgent(document, window);
12
+ *
13
+ * // Take a snapshot
14
+ * const snapshot = await agent.execute({
15
+ * id: '1',
16
+ * action: 'snapshot'
17
+ * });
18
+ *
19
+ * // Click an element
20
+ * await agent.execute({
21
+ * id: '2',
22
+ * action: 'click',
23
+ * selector: '@ref:5' // From snapshot
24
+ * });
25
+ * ```
26
+ */
27
+ import type { Command, Response, RefMap } from './types.js';
28
+ export * from './types.js';
29
+ export * from './errors.js';
30
+ export { createSnapshot } from './snapshot.js';
31
+ export { createRefMap, createSimpleRefMap } from './ref-map.js';
32
+ export { DOMActions } from './actions.js';
33
+ /**
34
+ * ContentAgent - DOM automation agent that runs in content script context
35
+ *
36
+ * This agent handles all DOM-level operations:
37
+ * - Element interaction (click, type, fill, etc.)
38
+ * - DOM queries (snapshot, getText, getAttribute, etc.)
39
+ * - Keyboard/mouse events
40
+ *
41
+ * Use this in content scripts or directly in web pages.
42
+ * For browser-level operations (tabs, navigation, screenshots),
43
+ * use BrowserAgent from @btcp/extension.
44
+ */
45
+ export interface ContentAgent {
46
+ /**
47
+ * Execute a command and return a response
48
+ */
49
+ execute(command: Command): Promise<Response>;
50
+ /**
51
+ * Execute a command from JSON string
52
+ */
53
+ executeJson(json: string): Promise<string>;
54
+ /**
55
+ * Get the element reference map
56
+ */
57
+ getRefMap(): RefMap;
58
+ /**
59
+ * Clear all element references
60
+ */
61
+ clearRefs(): void;
62
+ /**
63
+ * Message handler for chrome.runtime.onMessage
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * const agent = createContentAgent();
68
+ * chrome.runtime.onMessage.addListener(agent.handleMessage);
69
+ * ```
70
+ */
71
+ handleMessage: (message: unknown, sender: unknown, sendResponse: (response: unknown) => void) => boolean;
72
+ }
73
+ /**
74
+ * Create a ContentAgent for DOM automation
75
+ *
76
+ * @param doc - The document to operate on (defaults to current document)
77
+ * @param win - The window context (defaults to current window)
78
+ * @returns A ContentAgent instance
79
+ *
80
+ * @example
81
+ * ```typescript
82
+ * // In content script
83
+ * const agent = createContentAgent();
84
+ *
85
+ * // Take a snapshot of the page
86
+ * const { data } = await agent.execute({ id: '1', action: 'snapshot' });
87
+ *
88
+ * // Click an element using ref from snapshot
89
+ * await agent.execute({ id: '2', action: 'click', selector: '@ref:5' });
90
+ * ```
91
+ */
92
+ export declare function createContentAgent(doc?: Document, win?: Window): ContentAgent;
93
+ /**
94
+ * @deprecated Use createContentAgent instead
95
+ */
96
+ export declare const createAgent: typeof createContentAgent;
97
+ /**
98
+ * @deprecated Use ContentAgent instead
99
+ */
100
+ export type Agent = ContentAgent;
101
+ /**
102
+ * Message types for extension communication
103
+ */
104
+ export interface AgentMessage {
105
+ type: 'aspect:command';
106
+ command: Command;
107
+ }
108
+ export interface AgentResponse {
109
+ type: 'aspect:response';
110
+ response: Response;
111
+ }
112
+ /**
113
+ * Install message listener for extension communication
114
+ * Call this in your content script to enable command execution via postMessage
115
+ *
116
+ * @param agent - The agent instance
117
+ * @returns Cleanup function to remove the listener
118
+ */
119
+ export declare function installMessageListener(agent: Agent): () => void;
120
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,134 @@
1
+ /**
2
+ * @btcp/core
3
+ *
4
+ * Core DOM actions for browser automation.
5
+ * Runs in content script context (web page, extension content script, iframe).
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { createContentAgent } from '@btcp/core';
10
+ *
11
+ * const agent = createContentAgent(document, window);
12
+ *
13
+ * // Take a snapshot
14
+ * const snapshot = await agent.execute({
15
+ * id: '1',
16
+ * action: 'snapshot'
17
+ * });
18
+ *
19
+ * // Click an element
20
+ * await agent.execute({
21
+ * id: '2',
22
+ * action: 'click',
23
+ * selector: '@ref:5' // From snapshot
24
+ * });
25
+ * ```
26
+ */
27
+ import { DOMActions } from './actions.js';
28
+ import { createRefMap, createSimpleRefMap } from './ref-map.js';
29
+ export * from './types.js';
30
+ export * from './errors.js';
31
+ export { createSnapshot } from './snapshot.js';
32
+ export { createRefMap, createSimpleRefMap } from './ref-map.js';
33
+ export { DOMActions } from './actions.js';
34
+ /**
35
+ * Create a ContentAgent for DOM automation
36
+ *
37
+ * @param doc - The document to operate on (defaults to current document)
38
+ * @param win - The window context (defaults to current window)
39
+ * @returns A ContentAgent instance
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * // In content script
44
+ * const agent = createContentAgent();
45
+ *
46
+ * // Take a snapshot of the page
47
+ * const { data } = await agent.execute({ id: '1', action: 'snapshot' });
48
+ *
49
+ * // Click an element using ref from snapshot
50
+ * await agent.execute({ id: '2', action: 'click', selector: '@ref:5' });
51
+ * ```
52
+ */
53
+ export function createContentAgent(doc = document, win = window) {
54
+ // Use WeakRef-based map if available for better memory management
55
+ const refMap = typeof WeakRef !== 'undefined'
56
+ ? createRefMap()
57
+ : createSimpleRefMap();
58
+ const actions = new DOMActions(doc, win, refMap);
59
+ const agent = {
60
+ async execute(command) {
61
+ return actions.execute(command);
62
+ },
63
+ async executeJson(json) {
64
+ try {
65
+ const command = JSON.parse(json);
66
+ const response = await actions.execute(command);
67
+ return JSON.stringify(response);
68
+ }
69
+ catch (error) {
70
+ const message = error instanceof Error ? error.message : String(error);
71
+ return JSON.stringify({
72
+ id: 'unknown',
73
+ success: false,
74
+ error: `Failed to parse command: ${message}`,
75
+ });
76
+ }
77
+ },
78
+ getRefMap() {
79
+ return refMap;
80
+ },
81
+ clearRefs() {
82
+ refMap.clear();
83
+ actions.invalidateSnapshot();
84
+ },
85
+ handleMessage(message, _sender, sendResponse) {
86
+ const msg = message;
87
+ if (msg?.type !== 'btcp:command')
88
+ return false;
89
+ agent.execute(msg.command).then(response => {
90
+ sendResponse({ type: 'btcp:response', response });
91
+ }).catch(error => {
92
+ sendResponse({
93
+ type: 'btcp:response',
94
+ response: {
95
+ id: msg.command?.id ?? 'unknown',
96
+ success: false,
97
+ error: error instanceof Error ? error.message : String(error),
98
+ },
99
+ });
100
+ });
101
+ return true; // Keep channel open for async response
102
+ },
103
+ };
104
+ return agent;
105
+ }
106
+ /**
107
+ * @deprecated Use createContentAgent instead
108
+ */
109
+ export const createAgent = createContentAgent;
110
+ /**
111
+ * Install message listener for extension communication
112
+ * Call this in your content script to enable command execution via postMessage
113
+ *
114
+ * @param agent - The agent instance
115
+ * @returns Cleanup function to remove the listener
116
+ */
117
+ export function installMessageListener(agent) {
118
+ const handler = async (event) => {
119
+ // Only accept messages from same window
120
+ if (event.source !== window)
121
+ return;
122
+ const data = event.data;
123
+ if (data?.type !== 'aspect:command')
124
+ return;
125
+ const response = await agent.execute(data.command);
126
+ window.postMessage({
127
+ type: 'aspect:response',
128
+ response,
129
+ }, '*');
130
+ };
131
+ window.addEventListener('message', handler);
132
+ return () => window.removeEventListener('message', handler);
133
+ }
134
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @btcp/core - Element Reference Map
3
+ *
4
+ * Maintains a mapping between string refs and DOM elements.
5
+ * Used by the snapshot system to enable @ref:xxx selectors.
6
+ */
7
+ import type { RefMap } from './types.js';
8
+ /**
9
+ * Create a new element reference map
10
+ */
11
+ export declare function createRefMap(): RefMap;
12
+ /**
13
+ * Simple ref map without WeakRef (for environments that don't support it)
14
+ */
15
+ export declare function createSimpleRefMap(): RefMap;
16
+ //# sourceMappingURL=ref-map.d.ts.map
@@ -0,0 +1,91 @@
1
+ /**
2
+ * @btcp/core - Element Reference Map
3
+ *
4
+ * Maintains a mapping between string refs and DOM elements.
5
+ * Used by the snapshot system to enable @ref:xxx selectors.
6
+ */
7
+ /**
8
+ * Create a new element reference map
9
+ */
10
+ export function createRefMap() {
11
+ const map = new Map();
12
+ let counter = 0;
13
+ return {
14
+ get(ref) {
15
+ const weakRef = map.get(ref);
16
+ if (!weakRef)
17
+ return null;
18
+ const element = weakRef.deref();
19
+ if (!element) {
20
+ // Element was garbage collected
21
+ map.delete(ref);
22
+ return null;
23
+ }
24
+ // Check if element is still in DOM
25
+ if (!element.isConnected) {
26
+ map.delete(ref);
27
+ return null;
28
+ }
29
+ return element;
30
+ },
31
+ set(ref, element) {
32
+ map.set(ref, new WeakRef(element));
33
+ },
34
+ clear() {
35
+ map.clear();
36
+ counter = 0;
37
+ },
38
+ generateRef(element) {
39
+ // Check if element already has a ref
40
+ for (const [ref, weakRef] of map.entries()) {
41
+ if (weakRef.deref() === element) {
42
+ return ref;
43
+ }
44
+ }
45
+ // Generate new ref
46
+ const ref = `@ref:${counter++}`;
47
+ map.set(ref, new WeakRef(element));
48
+ return ref;
49
+ },
50
+ };
51
+ }
52
+ /**
53
+ * Simple ref map without WeakRef (for environments that don't support it)
54
+ */
55
+ export function createSimpleRefMap() {
56
+ const map = new Map();
57
+ let counter = 0;
58
+ return {
59
+ get(ref) {
60
+ const element = map.get(ref);
61
+ if (!element)
62
+ return null;
63
+ // Check if element is still in DOM
64
+ if (!element.isConnected) {
65
+ map.delete(ref);
66
+ return null;
67
+ }
68
+ return element;
69
+ },
70
+ set(ref, element) {
71
+ map.set(ref, element);
72
+ },
73
+ clear() {
74
+ map.clear();
75
+ counter = 0;
76
+ },
77
+ generateRef(element) {
78
+ // Check if element already has a ref
79
+ for (const [ref, el] of map.entries()) {
80
+ if (el === element) {
81
+ return ref;
82
+ }
83
+ }
84
+ // Generate new ref
85
+ const ref = `@ref:${counter++}`;
86
+ map.set(ref, element);
87
+ return ref;
88
+ },
89
+ };
90
+ }
91
+ //# sourceMappingURL=ref-map.js.map
@@ -0,0 +1,37 @@
1
+ /**
2
+ * @btcp/core - DOM Snapshot
3
+ *
4
+ * Generates a flat accessibility snapshot of the DOM.
5
+ * Produces a compact, AI-friendly list of interactive elements.
6
+ */
7
+ import type { SnapshotData, RefMap } from './types.js';
8
+ /**
9
+ * Grep options (mirrors Unix grep flags)
10
+ */
11
+ interface GrepOptions {
12
+ /** Pattern to search for */
13
+ pattern: string;
14
+ /** Case-insensitive matching (grep -i) */
15
+ ignoreCase?: boolean;
16
+ /** Invert match - return non-matching lines (grep -v) */
17
+ invert?: boolean;
18
+ /** Treat pattern as fixed string, not regex (grep -F) */
19
+ fixedStrings?: boolean;
20
+ }
21
+ interface SnapshotOptions {
22
+ root?: Element;
23
+ maxDepth?: number;
24
+ includeHidden?: boolean;
25
+ interactive?: boolean;
26
+ compact?: boolean;
27
+ all?: boolean;
28
+ format?: 'tree' | 'html';
29
+ /** Grep filter - string pattern or options object */
30
+ grep?: string | GrepOptions;
31
+ }
32
+ /**
33
+ * Generate flat snapshot of the DOM
34
+ */
35
+ export declare function createSnapshot(document: Document, refMap: RefMap, options?: SnapshotOptions): SnapshotData;
36
+ export {};
37
+ //# sourceMappingURL=snapshot.d.ts.map