btcp-browser-agent 0.1.7 → 0.1.8
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/LICENSE +21 -21
- package/README.md +338 -306
- package/package.json +69 -69
- package/packages/core/dist/actions.js +98 -67
- package/packages/core/dist/assertions.d.ts +118 -0
- package/packages/core/dist/assertions.js +230 -0
- package/packages/core/dist/errors.d.ts +23 -1
- package/packages/core/dist/errors.js +49 -0
- package/packages/core/dist/index.d.ts +1 -0
- package/packages/core/dist/index.js +1 -0
- package/packages/extension/dist/background.d.ts +8 -1
- package/packages/extension/dist/background.js +73 -14
- package/packages/extension/dist/content.js +114 -0
- package/packages/extension/dist/index.d.ts +43 -0
- package/packages/extension/dist/index.js +26 -0
- package/packages/extension/dist/remote.d.ts +133 -0
- package/packages/extension/dist/remote.js +668 -0
- package/packages/extension/dist/script-messenger.d.ts +132 -0
- package/packages/extension/dist/script-messenger.js +86 -0
- package/packages/extension/dist/types.d.ts +76 -2
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @btcp/extension - Script Messenger
|
|
3
|
+
*
|
|
4
|
+
* Type-safe message passing to injected scripts.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* // Define message types
|
|
9
|
+
* type HelperMessages = {
|
|
10
|
+
* getCount: { payload: { selector: string }; result: number };
|
|
11
|
+
* getData: { payload: { id: string }; result: { name: string; value: number } };
|
|
12
|
+
* };
|
|
13
|
+
*
|
|
14
|
+
* // Create typed messenger
|
|
15
|
+
* const helper = createScriptMessenger<HelperMessages>(client, { scriptId: 'helper' });
|
|
16
|
+
*
|
|
17
|
+
* // Use with full type safety
|
|
18
|
+
* const count = await helper.send('getCount', { selector: '.item' });
|
|
19
|
+
* // ^? number
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Message definition: maps action names to payload and result types
|
|
24
|
+
*/
|
|
25
|
+
export type MessageDefinitions = {
|
|
26
|
+
[action: string]: {
|
|
27
|
+
payload: unknown;
|
|
28
|
+
result: unknown;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Extract payload type for a specific action
|
|
33
|
+
*/
|
|
34
|
+
export type PayloadOf<T extends MessageDefinitions, K extends keyof T> = T[K]['payload'];
|
|
35
|
+
/**
|
|
36
|
+
* Extract result type for a specific action
|
|
37
|
+
*/
|
|
38
|
+
export type ResultOf<T extends MessageDefinitions, K extends keyof T> = T[K]['result'];
|
|
39
|
+
/**
|
|
40
|
+
* Options for creating a script messenger
|
|
41
|
+
*/
|
|
42
|
+
export interface ScriptMessengerOptions {
|
|
43
|
+
/** Target script ID (default: 'default') */
|
|
44
|
+
scriptId?: string;
|
|
45
|
+
/** Timeout in milliseconds for each message (default: 30000) */
|
|
46
|
+
timeout?: number;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Script messenger for type-safe communication with injected scripts
|
|
50
|
+
*/
|
|
51
|
+
export interface ScriptMessenger<T extends MessageDefinitions> {
|
|
52
|
+
/**
|
|
53
|
+
* Send a message to the injected script
|
|
54
|
+
*
|
|
55
|
+
* @param action - The action name
|
|
56
|
+
* @param payload - The payload to send
|
|
57
|
+
* @returns The result from the script
|
|
58
|
+
*/
|
|
59
|
+
send<K extends keyof T & string>(action: K, payload: PayloadOf<T, K>): Promise<ResultOf<T, K>>;
|
|
60
|
+
/**
|
|
61
|
+
* The script ID this messenger communicates with
|
|
62
|
+
*/
|
|
63
|
+
readonly scriptId: string;
|
|
64
|
+
/**
|
|
65
|
+
* The default timeout for messages
|
|
66
|
+
*/
|
|
67
|
+
readonly timeout: number;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Client interface required by ScriptMessenger
|
|
71
|
+
*/
|
|
72
|
+
export interface MessengerClient {
|
|
73
|
+
scriptSend(payload: unknown, options?: {
|
|
74
|
+
scriptId?: string;
|
|
75
|
+
timeout?: number;
|
|
76
|
+
}): Promise<unknown>;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Create a type-safe messenger for communicating with injected scripts
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```typescript
|
|
83
|
+
* type Messages = {
|
|
84
|
+
* getCount: { payload: { selector: string }; result: number };
|
|
85
|
+
* fetchItems: { payload: { category: string }; result: Item[] };
|
|
86
|
+
* };
|
|
87
|
+
*
|
|
88
|
+
* const messenger = createScriptMessenger<Messages>(client, {
|
|
89
|
+
* scriptId: 'helper',
|
|
90
|
+
* });
|
|
91
|
+
*
|
|
92
|
+
* const count = await messenger.send('getCount', { selector: '.item' });
|
|
93
|
+
* const items = await messenger.send('fetchItems', { category: 'books' });
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
export declare function createScriptMessenger<T extends MessageDefinitions>(client: MessengerClient, options?: ScriptMessengerOptions): ScriptMessenger<T>;
|
|
97
|
+
/**
|
|
98
|
+
* A messenger where each action is a method on the object
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```typescript
|
|
102
|
+
* const helper = createMethodMessenger<{
|
|
103
|
+
* getCount: { payload: { selector: string }; result: number };
|
|
104
|
+
* }>(client, { scriptId: 'helper' });
|
|
105
|
+
*
|
|
106
|
+
* const count = await helper.getCount({ selector: '.item' });
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
export type MethodMessenger<T extends MessageDefinitions> = {
|
|
110
|
+
[K in keyof T & string]: (payload: PayloadOf<T, K>) => Promise<ResultOf<T, K>>;
|
|
111
|
+
} & {
|
|
112
|
+
readonly scriptId: string;
|
|
113
|
+
readonly timeout: number;
|
|
114
|
+
};
|
|
115
|
+
/**
|
|
116
|
+
* Create a method-based messenger where each action is a method
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```typescript
|
|
120
|
+
* type Messages = {
|
|
121
|
+
* getCount: { payload: { selector: string }; result: number };
|
|
122
|
+
* click: { payload: { ref: number }; result: void };
|
|
123
|
+
* };
|
|
124
|
+
*
|
|
125
|
+
* const helper = createMethodMessenger<Messages>(client, { scriptId: 'helper' });
|
|
126
|
+
*
|
|
127
|
+
* const count = await helper.getCount({ selector: '.item' });
|
|
128
|
+
* await helper.click({ ref: 5 });
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
export declare function createMethodMessenger<T extends MessageDefinitions>(client: MessengerClient, options?: ScriptMessengerOptions): MethodMessenger<T>;
|
|
132
|
+
//# sourceMappingURL=script-messenger.d.ts.map
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @btcp/extension - Script Messenger
|
|
3
|
+
*
|
|
4
|
+
* Type-safe message passing to injected scripts.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* // Define message types
|
|
9
|
+
* type HelperMessages = {
|
|
10
|
+
* getCount: { payload: { selector: string }; result: number };
|
|
11
|
+
* getData: { payload: { id: string }; result: { name: string; value: number } };
|
|
12
|
+
* };
|
|
13
|
+
*
|
|
14
|
+
* // Create typed messenger
|
|
15
|
+
* const helper = createScriptMessenger<HelperMessages>(client, { scriptId: 'helper' });
|
|
16
|
+
*
|
|
17
|
+
* // Use with full type safety
|
|
18
|
+
* const count = await helper.send('getCount', { selector: '.item' });
|
|
19
|
+
* // ^? number
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Create a type-safe messenger for communicating with injected scripts
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* type Messages = {
|
|
28
|
+
* getCount: { payload: { selector: string }; result: number };
|
|
29
|
+
* fetchItems: { payload: { category: string }; result: Item[] };
|
|
30
|
+
* };
|
|
31
|
+
*
|
|
32
|
+
* const messenger = createScriptMessenger<Messages>(client, {
|
|
33
|
+
* scriptId: 'helper',
|
|
34
|
+
* });
|
|
35
|
+
*
|
|
36
|
+
* const count = await messenger.send('getCount', { selector: '.item' });
|
|
37
|
+
* const items = await messenger.send('fetchItems', { category: 'books' });
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export function createScriptMessenger(client, options = {}) {
|
|
41
|
+
const scriptId = options.scriptId ?? 'default';
|
|
42
|
+
const timeout = options.timeout ?? 30000;
|
|
43
|
+
return {
|
|
44
|
+
scriptId,
|
|
45
|
+
timeout,
|
|
46
|
+
async send(action, payload) {
|
|
47
|
+
const messagePayload = { action, ...payload };
|
|
48
|
+
const result = await client.scriptSend(messagePayload, { scriptId, timeout });
|
|
49
|
+
return result;
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Create a method-based messenger where each action is a method
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* type Messages = {
|
|
59
|
+
* getCount: { payload: { selector: string }; result: number };
|
|
60
|
+
* click: { payload: { ref: number }; result: void };
|
|
61
|
+
* };
|
|
62
|
+
*
|
|
63
|
+
* const helper = createMethodMessenger<Messages>(client, { scriptId: 'helper' });
|
|
64
|
+
*
|
|
65
|
+
* const count = await helper.getCount({ selector: '.item' });
|
|
66
|
+
* await helper.click({ ref: 5 });
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
export function createMethodMessenger(client, options = {}) {
|
|
70
|
+
const messenger = createScriptMessenger(client, options);
|
|
71
|
+
return new Proxy({
|
|
72
|
+
scriptId: messenger.scriptId,
|
|
73
|
+
timeout: messenger.timeout,
|
|
74
|
+
}, {
|
|
75
|
+
get(target, prop) {
|
|
76
|
+
if (prop === 'scriptId' || prop === 'timeout') {
|
|
77
|
+
return target[prop];
|
|
78
|
+
}
|
|
79
|
+
if (typeof prop === 'string') {
|
|
80
|
+
return (payload) => messenger.send(prop, payload);
|
|
81
|
+
}
|
|
82
|
+
return undefined;
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=script-messenger.js.map
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import type { Command as CoreCommand, Response } from '../../core/dist/index.js';
|
|
7
7
|
import type { SessionCommand } from './session-types.js';
|
|
8
|
-
export type ExtensionAction = 'navigate' | 'back' | 'forward' | 'reload' | 'getUrl' | 'getTitle' | 'screenshot' | 'tabNew' | 'tabClose' | 'tabSwitch' | 'tabList' | 'groupCreate' | 'groupUpdate' | 'groupDelete' | 'groupList' | 'groupAddTabs' | 'groupRemoveTabs' | 'groupGet' | 'sessionGetCurrent' | 'popupInitialize';
|
|
8
|
+
export type ExtensionAction = 'navigate' | 'back' | 'forward' | 'reload' | 'getUrl' | 'getTitle' | 'screenshot' | 'tabNew' | 'tabClose' | 'tabSwitch' | 'tabList' | 'groupCreate' | 'groupUpdate' | 'groupDelete' | 'groupList' | 'groupAddTabs' | 'groupRemoveTabs' | 'groupGet' | 'sessionGetCurrent' | 'popupInitialize' | 'scriptInject' | 'scriptSend';
|
|
9
9
|
export interface ExtensionBaseCommand {
|
|
10
10
|
/** Optional command ID. Auto-generated if not provided. */
|
|
11
11
|
id?: string;
|
|
@@ -56,7 +56,63 @@ export interface TabListCommand extends ExtensionBaseCommand {
|
|
|
56
56
|
export interface PopupInitializeCommand extends ExtensionBaseCommand {
|
|
57
57
|
action: 'popupInitialize';
|
|
58
58
|
}
|
|
59
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Inject a script into the page's main world
|
|
61
|
+
*
|
|
62
|
+
* The script runs in the page context (not the content script isolated world),
|
|
63
|
+
* allowing access to page-level APIs like window, fetch interceptors, etc.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* await client.execute({
|
|
68
|
+
* action: 'scriptInject',
|
|
69
|
+
* code: `
|
|
70
|
+
* window.addEventListener('message', (event) => {
|
|
71
|
+
* if (event.data?.type !== 'btcp:script-command') return;
|
|
72
|
+
* if (event.data.scriptId !== 'helper') return;
|
|
73
|
+
* const { commandId, payload } = event.data;
|
|
74
|
+
* // Handle command and send ack
|
|
75
|
+
* window.postMessage({ type: 'btcp:script-ack', commandId, result: { ok: true } }, '*');
|
|
76
|
+
* });
|
|
77
|
+
* `,
|
|
78
|
+
* scriptId: 'helper'
|
|
79
|
+
* });
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
export interface ScriptInjectCommand extends ExtensionBaseCommand {
|
|
83
|
+
action: 'scriptInject';
|
|
84
|
+
/** JavaScript code to inject into the page's main world */
|
|
85
|
+
code: string;
|
|
86
|
+
/** Unique identifier for this script (default: 'default') */
|
|
87
|
+
scriptId?: string;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Send a command to an injected script and wait for acknowledgment
|
|
91
|
+
*
|
|
92
|
+
* The content script posts a message to the page, and waits for the
|
|
93
|
+
* injected script to respond with an ack.
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* const result = await client.execute({
|
|
98
|
+
* action: 'scriptSend',
|
|
99
|
+
* scriptId: 'helper',
|
|
100
|
+
* payload: { action: 'getData', selector: '.items' },
|
|
101
|
+
* timeout: 5000
|
|
102
|
+
* });
|
|
103
|
+
* // result.data = { result: { items: [...] } }
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
export interface ScriptSendCommand extends ExtensionBaseCommand {
|
|
107
|
+
action: 'scriptSend';
|
|
108
|
+
/** Payload to send to the injected script */
|
|
109
|
+
payload: unknown;
|
|
110
|
+
/** Target script ID (default: 'default') */
|
|
111
|
+
scriptId?: string;
|
|
112
|
+
/** Timeout in milliseconds (default: 30000) */
|
|
113
|
+
timeout?: number;
|
|
114
|
+
}
|
|
115
|
+
export type ExtensionCommand = NavigateCommand | BackCommand | ForwardCommand | ReloadCommand | GetUrlCommand | GetTitleCommand | ScreenshotCommand | TabNewCommand | TabCloseCommand | TabSwitchCommand | TabListCommand | PopupInitializeCommand | SessionCommand | ScriptInjectCommand | ScriptSendCommand;
|
|
60
116
|
export type Command = CoreCommand | ExtensionCommand;
|
|
61
117
|
export type { Response };
|
|
62
118
|
export type { SessionCommand, GroupInfo, SessionInfo, GroupCreateOptions, GroupUpdateOptions, } from './session-types.js';
|
|
@@ -86,4 +142,22 @@ export interface TabInfo {
|
|
|
86
142
|
index: number;
|
|
87
143
|
}
|
|
88
144
|
export type ChromeTab = chrome.tabs.Tab;
|
|
145
|
+
/**
|
|
146
|
+
* Command sent from content script to injected page script
|
|
147
|
+
*/
|
|
148
|
+
export interface ScriptCommandMessage {
|
|
149
|
+
type: 'btcp:script-command';
|
|
150
|
+
commandId: string;
|
|
151
|
+
scriptId: string;
|
|
152
|
+
payload: unknown;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Acknowledgment sent from injected page script to content script
|
|
156
|
+
*/
|
|
157
|
+
export interface ScriptAckMessage {
|
|
158
|
+
type: 'btcp:script-ack';
|
|
159
|
+
commandId: string;
|
|
160
|
+
result?: unknown;
|
|
161
|
+
error?: string;
|
|
162
|
+
}
|
|
89
163
|
//# sourceMappingURL=types.d.ts.map
|