btcp-browser-agent 0.1.7 → 0.1.9

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.
@@ -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
- export type ExtensionCommand = NavigateCommand | BackCommand | ForwardCommand | ReloadCommand | GetUrlCommand | GetTitleCommand | ScreenshotCommand | TabNewCommand | TabCloseCommand | TabSwitchCommand | TabListCommand | PopupInitializeCommand | SessionCommand;
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