@agent-browser-io/browser 0.1.0 → 0.2.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 (77) hide show
  1. package/README.md +70 -0
  2. package/bin/agent-browser-cli.cjs +2 -0
  3. package/bin/agent-browser-mcp.cjs +2 -0
  4. package/bin/index.cjs +54 -0
  5. package/dist/cjs/ai-sdk/createBrowserTools.d.ts +58 -0
  6. package/dist/cjs/ai-sdk/createBrowserTools.d.ts.map +1 -0
  7. package/dist/cjs/ai-sdk/createBrowserTools.js +192 -0
  8. package/dist/cjs/ai-sdk/createBrowserTools.js.map +1 -0
  9. package/dist/cjs/cli/cli.d.ts +6 -0
  10. package/dist/cjs/cli/cli.d.ts.map +1 -0
  11. package/dist/cjs/cli/cli.js +149 -0
  12. package/dist/cjs/cli/cli.js.map +1 -0
  13. package/dist/cjs/core/agent-browser/agent-browser.d.ts +51 -0
  14. package/dist/cjs/core/agent-browser/agent-browser.d.ts.map +1 -0
  15. package/dist/cjs/core/agent-browser/agent-browser.js +80 -0
  16. package/dist/cjs/core/agent-browser/agent-browser.js.map +1 -0
  17. package/dist/cjs/core/agent-browser/normalize-script.d.ts +3 -0
  18. package/dist/cjs/core/agent-browser/normalize-script.d.ts.map +1 -0
  19. package/dist/cjs/core/agent-browser/normalize-script.js +531 -0
  20. package/dist/cjs/core/agent-browser/normalize-script.js.map +1 -0
  21. package/dist/cjs/core/browser-backend/browser-backend.d.ts +23 -0
  22. package/dist/cjs/core/browser-backend/browser-backend.d.ts.map +1 -0
  23. package/dist/cjs/core/browser-backend/browser-backend.js +6 -0
  24. package/dist/cjs/core/browser-backend/browser-backend.js.map +1 -0
  25. package/dist/cjs/core/browser-backend/index.d.ts +3 -0
  26. package/dist/cjs/core/browser-backend/index.d.ts.map +1 -0
  27. package/dist/cjs/core/browser-backend/index.js +6 -0
  28. package/dist/cjs/core/browser-backend/index.js.map +1 -0
  29. package/dist/cjs/core/browser-backend/playwright-browser-backend.d.ts +27 -0
  30. package/dist/cjs/core/browser-backend/playwright-browser-backend.d.ts.map +1 -0
  31. package/dist/cjs/core/browser-backend/playwright-browser-backend.js +86 -0
  32. package/dist/cjs/core/browser-backend/playwright-browser-backend.js.map +1 -0
  33. package/dist/cjs/index.d.ts +5 -0
  34. package/dist/cjs/index.d.ts.map +1 -1
  35. package/dist/cjs/index.js +8 -3
  36. package/dist/cjs/index.js.map +1 -1
  37. package/dist/cjs/mcp/server.d.ts +5 -0
  38. package/dist/cjs/mcp/server.d.ts.map +1 -0
  39. package/dist/cjs/mcp/server.js +284 -0
  40. package/dist/cjs/mcp/server.js.map +1 -0
  41. package/dist/esm/ai-sdk/createBrowserTools.d.ts +58 -0
  42. package/dist/esm/ai-sdk/createBrowserTools.d.ts.map +1 -0
  43. package/dist/esm/ai-sdk/createBrowserTools.js +189 -0
  44. package/dist/esm/ai-sdk/createBrowserTools.js.map +1 -0
  45. package/dist/esm/cli/cli.d.ts +6 -0
  46. package/dist/esm/cli/cli.d.ts.map +1 -0
  47. package/dist/esm/cli/cli.js +114 -0
  48. package/dist/esm/cli/cli.js.map +1 -0
  49. package/dist/esm/core/agent-browser/agent-browser.d.ts +51 -0
  50. package/dist/esm/core/agent-browser/agent-browser.d.ts.map +1 -0
  51. package/dist/esm/core/agent-browser/agent-browser.js +76 -0
  52. package/dist/esm/core/agent-browser/agent-browser.js.map +1 -0
  53. package/dist/esm/core/agent-browser/normalize-script.d.ts +3 -0
  54. package/dist/esm/core/agent-browser/normalize-script.d.ts.map +1 -0
  55. package/dist/esm/core/agent-browser/normalize-script.js +528 -0
  56. package/dist/esm/core/agent-browser/normalize-script.js.map +1 -0
  57. package/dist/esm/core/browser-backend/browser-backend.d.ts +23 -0
  58. package/dist/esm/core/browser-backend/browser-backend.d.ts.map +1 -0
  59. package/dist/esm/core/browser-backend/browser-backend.js +5 -0
  60. package/dist/esm/core/browser-backend/browser-backend.js.map +1 -0
  61. package/dist/esm/core/browser-backend/index.d.ts +3 -0
  62. package/dist/esm/core/browser-backend/index.d.ts.map +1 -0
  63. package/dist/esm/core/browser-backend/index.js +2 -0
  64. package/dist/esm/core/browser-backend/index.js.map +1 -0
  65. package/dist/esm/core/browser-backend/playwright-browser-backend.d.ts +27 -0
  66. package/dist/esm/core/browser-backend/playwright-browser-backend.d.ts.map +1 -0
  67. package/dist/esm/core/browser-backend/playwright-browser-backend.js +82 -0
  68. package/dist/esm/core/browser-backend/playwright-browser-backend.js.map +1 -0
  69. package/dist/esm/index.d.ts +5 -0
  70. package/dist/esm/index.d.ts.map +1 -1
  71. package/dist/esm/index.js +4 -2
  72. package/dist/esm/index.js.map +1 -1
  73. package/dist/esm/mcp/server.d.ts +5 -0
  74. package/dist/esm/mcp/server.d.ts.map +1 -0
  75. package/dist/esm/mcp/server.js +282 -0
  76. package/dist/esm/mcp/server.js.map +1 -0
  77. package/package.json +14 -5
@@ -0,0 +1,189 @@
1
+ /**
2
+ * Vercel AI SDK tools for agent-browser-io.
3
+ * Use with generateText({ tools: createBrowserTools(browser), ... }).
4
+ * Call the launch tool before other actions if the browser is not yet running.
5
+ */
6
+ import { tool } from "ai";
7
+ import { z } from "zod";
8
+ function wrapExecute(browser, fn) {
9
+ return async (args) => {
10
+ try {
11
+ return await fn(browser, args);
12
+ }
13
+ catch (err) {
14
+ const message = err instanceof Error ? err.message : String(err);
15
+ return `Error: ${message}`;
16
+ }
17
+ };
18
+ }
19
+ /**
20
+ * Creates a set of Vercel AI SDK–compatible tools that control the given browser instance.
21
+ * Pass the result to generateText({ tools: createBrowserTools(browser), ... }).
22
+ * The model should call the launch tool first before other actions.
23
+ */
24
+ export function createBrowserTools(browser) {
25
+ return {
26
+ launch: tool({
27
+ description: "Launch the browser (idempotent). Call before other actions if the browser is not yet running.",
28
+ inputSchema: z.object({}),
29
+ execute: wrapExecute(browser, async (b) => {
30
+ await b.launch();
31
+ return "Browser launched.";
32
+ }),
33
+ }),
34
+ navigate: tool({
35
+ description: "Navigate to a URL and apply the wireframe normalizer.",
36
+ inputSchema: z.object({
37
+ url: z.string().describe("URL to open"),
38
+ }),
39
+ execute: wrapExecute(browser, async (b, { url }) => {
40
+ await b.navigate(url);
41
+ return `Navigated to ${url}`;
42
+ }),
43
+ }),
44
+ getWireframe: tool({
45
+ description: "Return the ASCII wireframe of the current page. Use ref IDs from this output for click, type, fill, etc. Ref ids are positioned at the start of the element.",
46
+ inputSchema: z.object({}),
47
+ execute: wrapExecute(browser, async (b) => {
48
+ const wireframe = await b.getWireframe();
49
+ return wireframe || "(empty wireframe)";
50
+ }),
51
+ }),
52
+ click: tool({
53
+ description: "Click the element with the given ref ID (from the wireframe).",
54
+ inputSchema: z.object({
55
+ ref: z.string().describe("Element ref ID from wireframe"),
56
+ }),
57
+ execute: wrapExecute(browser, async (b, { ref }) => {
58
+ await b.click(ref);
59
+ return `Clicked ref ${ref}`;
60
+ }),
61
+ }),
62
+ type: tool({
63
+ description: "Type text into the element with the given ref ID.",
64
+ inputSchema: z.object({
65
+ ref: z.string().describe("Element ref ID from wireframe"),
66
+ text: z.string().describe("Text to type"),
67
+ }),
68
+ execute: wrapExecute(browser, async (b, { ref, text }) => {
69
+ await b.type(ref, text);
70
+ return `Typed into ref ${ref}`;
71
+ }),
72
+ }),
73
+ fill: tool({
74
+ description: "Clear and fill the element (by ref) with the given text.",
75
+ inputSchema: z.object({
76
+ ref: z.string().describe("Element ref ID from wireframe"),
77
+ text: z.string().describe("Text to fill"),
78
+ }),
79
+ execute: wrapExecute(browser, async (b, { ref, text }) => {
80
+ await b.fill(ref, text);
81
+ return `Filled ref ${ref}`;
82
+ }),
83
+ }),
84
+ dblclick: tool({
85
+ description: "Double-click the element with the given ref ID.",
86
+ inputSchema: z.object({
87
+ ref: z.string().describe("Element ref ID from wireframe"),
88
+ }),
89
+ execute: wrapExecute(browser, async (b, { ref }) => {
90
+ await b.dblclick(ref);
91
+ return `Double-clicked ref ${ref}`;
92
+ }),
93
+ }),
94
+ hover: tool({
95
+ description: "Hover over the element with the given ref ID.",
96
+ inputSchema: z.object({
97
+ ref: z.string().describe("Element ref ID from wireframe"),
98
+ }),
99
+ execute: wrapExecute(browser, async (b, { ref }) => {
100
+ await b.hover(ref);
101
+ return `Hovered ref ${ref}`;
102
+ }),
103
+ }),
104
+ press: tool({
105
+ description: "Press a keyboard key (e.g. Enter, Tab, ArrowDown).",
106
+ inputSchema: z.object({
107
+ key: z.string().describe("Key to press"),
108
+ }),
109
+ execute: wrapExecute(browser, async (b, { key }) => {
110
+ await b.press(key);
111
+ return `Pressed key ${key}`;
112
+ }),
113
+ }),
114
+ select: tool({
115
+ description: "Select an option in a dropdown by ref and value.",
116
+ inputSchema: z.object({
117
+ ref: z.string().describe("Element ref ID from wireframe"),
118
+ value: z.string().describe("Option value to select"),
119
+ }),
120
+ execute: wrapExecute(browser, async (b, { ref, value }) => {
121
+ await b.select(ref, value);
122
+ return `Selected value in ref ${ref}`;
123
+ }),
124
+ }),
125
+ check: tool({
126
+ description: "Check the checkbox/radio with the given ref ID.",
127
+ inputSchema: z.object({
128
+ ref: z.string().describe("Element ref ID from wireframe"),
129
+ }),
130
+ execute: wrapExecute(browser, async (b, { ref }) => {
131
+ await b.check(ref);
132
+ return `Checked ref ${ref}`;
133
+ }),
134
+ }),
135
+ uncheck: tool({
136
+ description: "Uncheck the checkbox with the given ref ID.",
137
+ inputSchema: z.object({
138
+ ref: z.string().describe("Element ref ID from wireframe"),
139
+ }),
140
+ execute: wrapExecute(browser, async (b, { ref }) => {
141
+ await b.uncheck(ref);
142
+ return `Unchecked ref ${ref}`;
143
+ }),
144
+ }),
145
+ scroll: tool({
146
+ description: "Scroll the page in the given direction.",
147
+ inputSchema: z.object({
148
+ direction: z
149
+ .enum(["up", "down", "left", "right"])
150
+ .describe("Scroll direction"),
151
+ pixels: z.number().optional().describe("Pixels to scroll (default 100)"),
152
+ }),
153
+ execute: wrapExecute(browser, async (b, { direction, pixels }) => {
154
+ await b.scroll(direction, pixels);
155
+ return `Scrolled ${direction}`;
156
+ }),
157
+ }),
158
+ screenshot: tool({
159
+ description: "Take a screenshot. Returns base64 PNG when path is omitted; otherwise saves to file.",
160
+ inputSchema: z.object({
161
+ path: z
162
+ .string()
163
+ .optional()
164
+ .describe("Optional file path to save screenshot"),
165
+ fullPage: z
166
+ .boolean()
167
+ .optional()
168
+ .describe("Capture full scrollable page"),
169
+ }),
170
+ execute: wrapExecute(browser, async (b, { path: filePath, fullPage }) => {
171
+ const result = await b.screenshot(filePath, { fullPage });
172
+ if (filePath) {
173
+ return `Screenshot saved to ${filePath}`;
174
+ }
175
+ const base64 = result instanceof Buffer ? result.toString("base64") : "";
176
+ return base64 ? `data:image/png;base64,${base64}` : "(no image)";
177
+ }),
178
+ }),
179
+ close: tool({
180
+ description: "Close the browser.",
181
+ inputSchema: z.object({}),
182
+ execute: wrapExecute(browser, async (b) => {
183
+ await b.close();
184
+ return "Browser closed.";
185
+ }),
186
+ }),
187
+ };
188
+ }
189
+ //# sourceMappingURL=createBrowserTools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createBrowserTools.js","sourceRoot":"","sources":["../../../src/ai-sdk/createBrowserTools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Interactive CLI for @agent-browser-io/browser
3
+ * Launches a browser and provides REPL-style commands.
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../../src/cli/cli.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Interactive CLI for @agent-browser-io/browser
3
+ * Launches a browser and provides REPL-style commands.
4
+ */
5
+ import * as readline from 'readline';
6
+ import { VERSION } from '../index';
7
+ import { AgentBrowser } from '../core/agent-browser/agent-browser.js';
8
+ import { DefaultBrowserBackend } from '../core/browser-backend/index.js';
9
+ const PROMPT = 'agent-browser> ';
10
+ function print(msg) {
11
+ console.log(msg);
12
+ }
13
+ async function main() {
14
+ print(`@agent-browser-io/browser v${VERSION}`);
15
+ print('Launching browser...');
16
+ const backend = new DefaultBrowserBackend();
17
+ const browser = new AgentBrowser(backend);
18
+ await browser.launch();
19
+ print('Browser ready. Type "help" for commands, "exit" or Ctrl+D to quit.\n');
20
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
21
+ const loop = () => {
22
+ rl.question(PROMPT, async (line) => {
23
+ const trimmed = line.trim();
24
+ const parts = trimmed.split(/\s+/).filter(Boolean);
25
+ const cmd = parts[0]?.toLowerCase() ?? '';
26
+ const rest = parts.slice(1);
27
+ if (cmd === 'exit' || cmd === 'quit' || cmd === 'q') {
28
+ rl.close();
29
+ process.exit(0);
30
+ }
31
+ if (cmd === 'help') {
32
+ print(' help Show this message');
33
+ print(' version Show version');
34
+ print(' navigate <url> Open URL and apply wireframe normalizer');
35
+ print(' wireframe Print ASCII wireframe of current page');
36
+ print(' click <ref> Click element by ref id (e.g. 1)');
37
+ print(' type <ref> <text> Type into element by ref id');
38
+ print(' exit Quit the CLI');
39
+ }
40
+ else if (cmd === 'version') {
41
+ print(` ${VERSION}`);
42
+ }
43
+ else if (cmd === 'navigate') {
44
+ const url = rest[0];
45
+ if (!url) {
46
+ print(' Usage: navigate <url>');
47
+ }
48
+ else {
49
+ try {
50
+ await browser.navigate(url);
51
+ print(` Navigated to ${url}`);
52
+ }
53
+ catch (e) {
54
+ print(` Error: ${e instanceof Error ? e.message : String(e)}`);
55
+ }
56
+ }
57
+ }
58
+ else if (cmd === 'wireframe') {
59
+ try {
60
+ const wf = await browser.getWireframe();
61
+ print(wf || ' (empty wireframe)');
62
+ }
63
+ catch (e) {
64
+ print(` Error: ${e instanceof Error ? e.message : String(e)}`);
65
+ }
66
+ }
67
+ else if (cmd === 'click') {
68
+ const ref = rest[0];
69
+ if (!ref) {
70
+ print(' Usage: click <ref>');
71
+ }
72
+ else {
73
+ try {
74
+ await browser.click(ref);
75
+ print(` Clicked ref ${ref}`);
76
+ }
77
+ catch (e) {
78
+ print(` Error: ${e instanceof Error ? e.message : String(e)}`);
79
+ }
80
+ }
81
+ }
82
+ else if (cmd === 'type') {
83
+ const ref = rest[0];
84
+ const text = rest.slice(1).join(' ');
85
+ if (!ref) {
86
+ print(' Usage: type <ref> <text>');
87
+ }
88
+ else {
89
+ try {
90
+ await browser.type(ref, text);
91
+ print(` Typed into ref ${ref}`);
92
+ }
93
+ catch (e) {
94
+ print(` Error: ${e instanceof Error ? e.message : String(e)}`);
95
+ }
96
+ }
97
+ }
98
+ else if (trimmed !== '') {
99
+ print(` Unknown command: ${cmd}. Type "help" for commands.`);
100
+ }
101
+ loop();
102
+ });
103
+ };
104
+ rl.on('close', () => {
105
+ print('\nBye.');
106
+ process.exit(0);
107
+ });
108
+ loop();
109
+ }
110
+ main().catch((e) => {
111
+ console.error('Fatal:', e);
112
+ process.exit(1);
113
+ });
114
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../../src/cli/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ import { IBrowserBackend } from "../browser-backend/browser-backend.js";
2
+ export interface IAgentBrowser {
3
+ launch(): Promise<void>;
4
+ navigate(url: string): Promise<void>;
5
+ click(ref: string): Promise<void>;
6
+ type(ref: string, text: string): Promise<void>;
7
+ dblclick(ref: string): Promise<void>;
8
+ fill(ref: string, text: string): Promise<void>;
9
+ press(key: string): Promise<void>;
10
+ hover(ref: string): Promise<void>;
11
+ select(ref: string, value: string): Promise<void>;
12
+ check(ref: string): Promise<void>;
13
+ uncheck(ref: string): Promise<void>;
14
+ scroll(direction: "up" | "down" | "left" | "right", pixels?: number): Promise<void>;
15
+ screenshot(path?: string, options?: {
16
+ fullPage?: boolean;
17
+ }): Promise<Buffer | void>;
18
+ close(): Promise<void>;
19
+ getWireframe(): Promise<string>;
20
+ }
21
+ export declare class AgentBrowser implements IAgentBrowser {
22
+ private readonly browserBackend;
23
+ constructor(browserBackend: IBrowserBackend);
24
+ private injectNormalizeScript;
25
+ launch(): Promise<void>;
26
+ navigate(url: string): Promise<void>;
27
+ /** Ref is the data-ref-id value from the wireframe (e.g. "1"). */
28
+ click(ref: string): Promise<void>;
29
+ /** Ref is the data-ref-id value from the wireframe (e.g. "1"). */
30
+ type(ref: string, text: string): Promise<void>;
31
+ /** Ref is the data-ref-id value from the wireframe (e.g. "1"). */
32
+ dblclick(ref: string): Promise<void>;
33
+ /** Ref is the data-ref-id value from the wireframe (e.g. "1"). */
34
+ fill(ref: string, text: string): Promise<void>;
35
+ press(key: string): Promise<void>;
36
+ /** Ref is the data-ref-id value from the wireframe (e.g. "1"). */
37
+ hover(ref: string): Promise<void>;
38
+ /** Ref is the data-ref-id value from the wireframe (e.g. "1"). */
39
+ select(ref: string, value: string): Promise<void>;
40
+ /** Ref is the data-ref-id value from the wireframe (e.g. "1"). */
41
+ check(ref: string): Promise<void>;
42
+ /** Ref is the data-ref-id value from the wireframe (e.g. "1"). */
43
+ uncheck(ref: string): Promise<void>;
44
+ scroll(direction: "up" | "down" | "left" | "right", pixels?: number): Promise<void>;
45
+ screenshot(path?: string, options?: {
46
+ fullPage?: boolean;
47
+ }): Promise<Buffer | void>;
48
+ close(): Promise<void>;
49
+ getWireframe(): Promise<string>;
50
+ }
51
+ //# sourceMappingURL=agent-browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-browser.d.ts","sourceRoot":"","sources":["../../../../src/core/agent-browser/agent-browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AAGxE,MAAM,WAAW,aAAa;IAC1B,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,CAAC,SAAS,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpF,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACpF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CACnC;AAED,qBAAa,YAAa,YAAW,aAAa;IAClC,OAAO,CAAC,QAAQ,CAAC,cAAc;gBAAd,cAAc,EAAE,eAAe;YAE9C,qBAAqB;IAI7B,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAIvB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK1C,kEAAkE;IAC5D,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKvC,kEAAkE;IAC5D,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKpD,kEAAkE;IAC5D,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK1C,kEAAkE;IAC5D,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK9C,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKvC,kEAAkE;IAC5D,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKvC,kEAAkE;IAC5D,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKvD,kEAAkE;IAC5D,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKvC,kEAAkE;IAC5D,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKnC,MAAM,CACR,SAAS,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,EAC3C,MAAM,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC;IAKV,UAAU,CACZ,IAAI,CAAC,EAAE,MAAM,EACb,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,GACjC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAInB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAItB,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;CAOxC"}
@@ -0,0 +1,76 @@
1
+ import { NORMALIZE_SCRIPT } from "./normalize-script.js";
2
+ export class AgentBrowser {
3
+ constructor(browserBackend) {
4
+ this.browserBackend = browserBackend;
5
+ }
6
+ async injectNormalizeScript() {
7
+ await this.browserBackend.evaluate(NORMALIZE_SCRIPT);
8
+ }
9
+ async launch() {
10
+ await this.browserBackend.launch();
11
+ }
12
+ async navigate(url) {
13
+ await this.browserBackend.navigate(url);
14
+ await this.injectNormalizeScript();
15
+ }
16
+ /** Ref is the data-ref-id value from the wireframe (e.g. "1"). */
17
+ async click(ref) {
18
+ await this.browserBackend.click(`[data-ref-id="${ref}"]`);
19
+ await this.injectNormalizeScript();
20
+ }
21
+ /** Ref is the data-ref-id value from the wireframe (e.g. "1"). */
22
+ async type(ref, text) {
23
+ await this.browserBackend.type(`[data-ref-id="${ref}"]`, text);
24
+ await this.injectNormalizeScript();
25
+ }
26
+ /** Ref is the data-ref-id value from the wireframe (e.g. "1"). */
27
+ async dblclick(ref) {
28
+ await this.browserBackend.dblclick(`[data-ref-id="${ref}"]`);
29
+ await this.injectNormalizeScript();
30
+ }
31
+ /** Ref is the data-ref-id value from the wireframe (e.g. "1"). */
32
+ async fill(ref, text) {
33
+ await this.browserBackend.fill(`[data-ref-id="${ref}"]`, text);
34
+ await this.injectNormalizeScript();
35
+ }
36
+ async press(key) {
37
+ await this.browserBackend.press(key);
38
+ await this.injectNormalizeScript();
39
+ }
40
+ /** Ref is the data-ref-id value from the wireframe (e.g. "1"). */
41
+ async hover(ref) {
42
+ await this.browserBackend.hover(`[data-ref-id="${ref}"]`);
43
+ await this.injectNormalizeScript();
44
+ }
45
+ /** Ref is the data-ref-id value from the wireframe (e.g. "1"). */
46
+ async select(ref, value) {
47
+ await this.browserBackend.select(`[data-ref-id="${ref}"]`, value);
48
+ await this.injectNormalizeScript();
49
+ }
50
+ /** Ref is the data-ref-id value from the wireframe (e.g. "1"). */
51
+ async check(ref) {
52
+ await this.browserBackend.check(`[data-ref-id="${ref}"]`);
53
+ await this.injectNormalizeScript();
54
+ }
55
+ /** Ref is the data-ref-id value from the wireframe (e.g. "1"). */
56
+ async uncheck(ref) {
57
+ await this.browserBackend.uncheck(`[data-ref-id="${ref}"]`);
58
+ await this.injectNormalizeScript();
59
+ }
60
+ async scroll(direction, pixels) {
61
+ await this.browserBackend.scroll(direction, pixels);
62
+ await this.injectNormalizeScript();
63
+ }
64
+ async screenshot(path, options) {
65
+ return this.browserBackend.screenshot(path, options);
66
+ }
67
+ async close() {
68
+ await this.browserBackend.close();
69
+ }
70
+ async getWireframe() {
71
+ await this.injectNormalizeScript();
72
+ const result = await this.browserBackend.evaluate("typeof window.generateWireframeString === 'function' ? window.generateWireframeString() : ''");
73
+ return typeof result === "string" ? result : "";
74
+ }
75
+ }
76
+ //# sourceMappingURL=agent-browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-browser.js","sourceRoot":"","sources":["../../../../src/core/agent-browser/agent-browser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ /** Injected browser script for wireframe normalization. Exported as string for evaluation in the page. */
2
+ export declare const NORMALIZE_SCRIPT = "\n// This script is intended to be used in the browser.\n// It is not intended to be used in node.\n(function applyWireframeMode() {\n // --- PART A: INJECT CSS STYLES (idempotent) ---\n if (!document.getElementById(\"wf-normalize\")) {\n const cssStyles = `\n /* FORCE GLOBAL MONOSPACE & METRICS */\n * {\n font-family: \"Courier New\", Courier, monospace !important;\n font-size: 12px !important;\n font-weight: normal !important;\n color: #000000 !important;\n line-height: 18px !important;\n letter-spacing: 0px !important;\n box-shadow: none !important;\n text-shadow: none !important;\n border-radius: 0 !important;\n transition: none !important;\n }\n\n /* HIGH CONTRAST THEME */\n body {\n background-color: #ffffff !important;\n color: #000000 !important;\n }\n\n /* STRUCTURAL OUTLINES */\n div, section, article, header, footer, nav, aside, main {\n border: 1px dotted #cccccc !important;\n }\n\n /* KILL PSEUDO-ELEMENT BACKGROUNDS */\n *::before, *::after {\n background-image: none !important;\n background-color: transparent !important;\n border: none !important;\n }\n\n /* INTERACTIVE ELEMENTS */\n a, button, input[type=\"submit\"], input[type=\"button\"], [role=\"button\"] {\n border: 2px solid #000000 !important;\n background-color: #ffffff !important;\n color: #000000 !important;\n text-transform: uppercase !important;\n text-decoration: none !important;\n font-weight: bold !important;\n }\n\n /* FORM INPUTS */\n input, textarea, select {\n border: 1px solid #000000 !important;\n background-color: #ffffff !important;\n color: #000000 !important;\n font-family: monospace !important;\n }\n\n /* HIDE DECORATIVE MEDIA */\n img, video, canvas, svg {\n opacity: 0.5 !important;\n filter: grayscale(100%) !important;\n border: 1px dashed #000 !important;\n }\n\n /* BACKGROUND IMAGE INDICATORS */\n [data-bg-image=\"true\"] {\n background-color: #f4f4f4 !important;\n border: 1px dashed #555555 !important;\n position: relative !important;\n }\n [data-bg-image=\"true\"]::before {\n content: \"[ BG IMAGE ]\";\n position: absolute;\n top: 0; right: 0;\n background: #000000; color: #ffffff;\n font-size: 10px !important;\n padding: 2px 4px;\n opacity: 0.8;\n z-index: 9999;\n pointer-events: none;\n font-weight: normal !important;\n }\n `;\n\n const styleSheet = document.createElement(\"style\");\n styleSheet.id = \"wf-normalize\";\n styleSheet.type = \"text/css\";\n styleSheet.innerText = cssStyles;\n document.head.appendChild(styleSheet);\n }\n\n // --- PART B: NORMALIZE DOM CONTENT (idempotent) ---\n if (!document.body) return; // page not ready\n\n // Helper: check if element is the top-most (not behind an overlay) at its center\n function isElementVisible(el) {\n var rect = el.getBoundingClientRect();\n var cx = rect.left + rect.width / 2;\n var cy = rect.top + rect.height / 2;\n if (cx < 0 || cy < 0 || cx >= window.innerWidth || cy >= window.innerHeight) return false;\n var topEl = document.elementFromPoint(cx, cy);\n if (!topEl) return false;\n return el.contains(topEl) || topEl.contains(el);\n }\n\n // Remove old ref IDs and reset counter\n document.querySelectorAll(\"[data-ref-id]\").forEach(function(el) {\n el.removeAttribute(\"data-ref-id\");\n });\n var refCounter = 1;\n\n // Only run DOM mutations (media replacement, accessibility labels, bg stripping) once\n if (!document.body.hasAttribute(\"data-wf-normalized\")) {\n document.body.setAttribute(\"data-wf-normalized\", \"true\");\n\n // 1. REVEAL ACCESSIBILITY LABELS (ICON BUTTONS)\n var interactives = document.querySelectorAll('a, button, [role=\"button\"]');\n interactives.forEach(function(el) {\n if (el.innerText.trim() === '') {\n var label = el.getAttribute('aria-label') || el.getAttribute('title');\n // Also check child elements for hints (e.g. HN vote arrows: <a><div title=\"upvote\"></a>)\n if (!label) {\n var hintEl = el.querySelector('[aria-label], [title]');\n if (hintEl) label = hintEl.getAttribute('aria-label') || hintEl.getAttribute('title');\n }\n if (label) {\n el.innerText = label;\n el.style.display = 'inline-block';\n el.style.width = 'auto';\n el.style.height = 'auto';\n }\n }\n });\n\n // 2. REPLACE MEDIA WITH INTELLIGENT PLACEHOLDERS\n var mediaElements = document.querySelectorAll('img, svg, video, canvas');\n mediaElements.forEach(function(el) {\n var rect = el.getBoundingClientRect();\n if (rect.width < 10 || rect.height < 10) return;\n\n var placeholder = document.createElement('div');\n placeholder.style.cssText =\n 'width:' + rect.width + 'px;' +\n 'height:' + rect.height + 'px;' +\n 'background:#f0f0f0;color:#000;font-family:monospace;font-weight:bold;' +\n 'display:flex;align-items:center;justify-content:center;text-align:center;' +\n 'overflow:hidden;box-sizing:border-box;';\n\n var altText = el.getAttribute('alt') ||\n el.getAttribute('title') ||\n el.getAttribute('aria-label');\n\n if (!altText && el.tagName.toLowerCase() === 'svg') {\n var titleEl = el.querySelector('title');\n if (titleEl) altText = titleEl.textContent;\n }\n\n if (rect.width <= 50 && rect.height <= 50) {\n placeholder.style.border = '1px solid #333';\n placeholder.style.fontSize = '8px';\n placeholder.style.padding = '0';\n // Use short label for tiny icons to avoid overflow\n if (rect.width <= 20 || rect.height <= 20) {\n placeholder.innerText = altText ? altText.substring(0, 1) : '*';\n } else {\n var iconLabel = altText ? altText.substring(0, 8) : \"ICON\";\n placeholder.innerText = '[' + iconLabel + ']';\n }\n } else {\n placeholder.style.border = '2px solid #000';\n placeholder.style.fontSize = '10px';\n placeholder.style.padding = '2px';\n placeholder.style.wordBreak = 'break-word';\n var imgLabel = altText ? altText : \"IMAGE\";\n placeholder.innerText = '[' + imgLabel + ']';\n }\n\n if (el.parentNode) {\n el.parentNode.replaceChild(placeholder, el);\n }\n });\n\n // 3. CONVERT BACKGROUND IMAGES & STRIP COLORS\n var allElements = document.querySelectorAll('*');\n allElements.forEach(function(el) {\n var style = window.getComputedStyle(el);\n var hasBgImage = style.backgroundImage !== 'none' && style.backgroundImage !== '';\n var hasBgColor = style.backgroundColor !== 'rgba(0, 0, 0, 0)' &&\n style.backgroundColor !== 'transparent' &&\n style.backgroundColor !== 'rgb(255, 255, 255)';\n\n if (hasBgImage) {\n el.style.backgroundImage = 'none';\n el.setAttribute('data-bg-image', 'true');\n }\n\n if (hasBgColor) {\n el.style.backgroundColor = '#ffffff';\n }\n });\n }\n\n // 4. REMOVE TRANSPARENT OVERLAY BACKDROPS (run every time \u2014 new overlays can appear)\n // Full-viewport high z-index divs with no meaningful text are just backdrop overlays\n // that block elementFromPoint for content behind them\n var overlayDivs = document.querySelectorAll('div');\n overlayDivs.forEach(function(el) {\n var style = window.getComputedStyle(el);\n var z = parseInt(style.zIndex) || 0;\n if (z < 100 || style.display === 'none') return;\n var rect = el.getBoundingClientRect();\n if (rect.width < window.innerWidth * 0.9 || rect.height < window.innerHeight * 0.9) return;\n var text = (el.innerText || '').trim();\n if (text.length < 5) {\n el.style.display = 'none';\n }\n });\n\n // Overflow buffer: capture high-z-index elements pushed below viewport by CSS normalization\n var OVERFLOW_BUFFER = 200;\n var captureHeight = window.innerHeight + OVERFLOW_BUFFER;\n\n // 5. TAG INTERACTIVE ELEMENTS (always re-run since we cleared ref IDs)\n // Only tag elements visible, in viewport (+ overflow buffer), and not behind overlays\n function tagIfVisible(el) {\n if (el.hasAttribute('data-ref-id')) return; // already tagged\n var rect = el.getBoundingClientRect();\n var style = window.getComputedStyle(el);\n if (rect.width === 0 || rect.height === 0 || style.display === 'none' || style.visibility === 'hidden') return;\n if (rect.bottom < 0 || rect.top >= captureHeight || rect.right < 0 || rect.left >= window.innerWidth) return;\n // Elements in overflow zone (below viewport): can't use elementFromPoint, just tag them\n if (rect.top >= window.innerHeight) {\n el.setAttribute('data-ref-id', String(refCounter++));\n return;\n }\n if (!isElementVisible(el)) return;\n el.setAttribute('data-ref-id', String(refCounter++));\n }\n\n // Pass 1: semantic interactive elements\n var allInteractives = document.querySelectorAll('a, button, input, textarea, select, [role=\"button\"], [onclick], [tabindex=\"0\"]');\n allInteractives.forEach(tagIfVisible);\n\n // Pass 2: non-semantic clickable elements (divs/spans with cursor:pointer and text)\n // This catches sites that use <div> as buttons without proper ARIA roles\n var potentialClickables = document.querySelectorAll('div, span');\n potentialClickables.forEach(function(el) {\n if (el.hasAttribute('data-ref-id')) return;\n // Skip if already inside a tagged interactive element\n if (el.closest && el.closest('[data-ref-id]')) return;\n var style = window.getComputedStyle(el);\n if (style.cursor !== 'pointer') return;\n // Must have direct text content (not just children with text)\n var hasDirectText = false;\n for (var i = 0; i < el.childNodes.length; i++) {\n if (el.childNodes[i].nodeType === 3 && el.childNodes[i].textContent.trim()) {\n hasDirectText = true;\n break;\n }\n }\n if (!hasDirectText) return;\n tagIfVisible(el);\n });\n\n console.log(\"Normalization Complete.\");\n\n // --- PART C: WIREFRAME STRING GENERATOR ---\n function generateWireframeString() {\n // 1. Measure CHAR_W dynamically\n var probe = document.createElement('span');\n probe.style.cssText = 'font-family:\"Courier New\",Courier,monospace;font-size:12px;line-height:18px;letter-spacing:0px;position:absolute;top:-9999px;left:-9999px;white-space:pre;visibility:hidden;';\n probe.textContent = 'MMMMMMMMMM';\n document.body.appendChild(probe);\n var CHAR_W = probe.getBoundingClientRect().width / 10;\n document.body.removeChild(probe);\n if (CHAR_W <= 0) CHAR_W = 7.2; // fallback\n\n var CHAR_H = 18;\n\n // 2. Create grid (includes overflow buffer for elements pushed below viewport)\n var OVERFLOW_BUFFER_C = 200;\n var captureHeightC = window.innerHeight + OVERFLOW_BUFFER_C;\n var gridWidth = Math.ceil(window.innerWidth / CHAR_W);\n var gridHeight = Math.ceil(captureHeightC / CHAR_H);\n var grid = [];\n for (var r = 0; r < gridHeight; r++) {\n var row = [];\n for (var c = 0; c < gridWidth; c++) {\n row.push(' ');\n }\n grid.push(row);\n }\n\n function writeToGrid(x, y, str) {\n if (y < 0 || y >= gridHeight) return;\n for (var i = 0; i < str.length; i++) {\n var curX = x + i;\n if (curX >= 0 && curX < gridWidth) {\n grid[y][curX] = str[i];\n }\n }\n }\n\n // 3. Draw borders only for block-level interactive elements (buttons, form controls)\n // Skip inline links \u2014 they just get ref labels.\n var refElements = document.querySelectorAll('[data-ref-id]');\n refElements.forEach(function(el) {\n var rect = el.getBoundingClientRect();\n var style = window.getComputedStyle(el);\n if (style.display === 'none' || style.visibility === 'hidden' || rect.width === 0 || rect.height === 0) return;\n // Skip elements outside capture area\n if (rect.bottom < 0 || rect.top >= captureHeightC || rect.right < 0 || rect.left >= window.innerWidth) return;\n\n // Only draw borders for buttons, form elements, and block-level role=button\n var tag = el.tagName;\n var isFormEl = (tag === 'BUTTON' || tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT');\n var isBlockButton = (el.getAttribute('role') === 'button' && style.display !== 'inline');\n if (!isFormEl && !isBlockButton) return;\n\n var x = Math.floor(rect.left / CHAR_W);\n var y = Math.floor(rect.top / CHAR_H);\n var w = Math.max(2, Math.ceil(rect.width / CHAR_W));\n var h = Math.max(2, Math.ceil(rect.height / CHAR_H));\n\n // Top border\n writeToGrid(x, y, '+' + repeat('-', Math.max(0, w - 2)) + '+');\n // Side borders\n for (var i = 1; i < h - 1; i++) {\n writeToGrid(x, y + i, '|');\n writeToGrid(x + w - 1, y + i, '|');\n }\n // Bottom border\n if (h > 1) {\n writeToGrid(x, y + h - 1, '+' + repeat('-', Math.max(0, w - 2)) + '+');\n }\n });\n\n // Helper: check if element is the top-most at a given point\n function isVisibleAt(el, px, py) {\n if (px < 0 || py < 0 || px >= window.innerWidth) return false;\n // Overflow zone: elementFromPoint doesn't work below viewport, assume visible\n if (py >= window.innerHeight) return py < captureHeightC;\n var topEl = document.elementFromPoint(px, py);\n if (!topEl) return false;\n return el.contains(topEl) || topEl.contains(el);\n }\n\n // 4. Render text via TreeWalker (text only, no labels yet)\n var labeledRefs = {}; // refId -> {row, col} where the element's first text starts\n var walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, null, false);\n var textNode;\n while ((textNode = walker.nextNode())) {\n var parent = textNode.parentElement;\n if (!parent) continue;\n\n // Skip script/style\n var tag = parent.tagName;\n if (tag === 'SCRIPT' || tag === 'STYLE' || tag === 'NOSCRIPT') continue;\n\n // Skip invisible parents\n var pStyle = window.getComputedStyle(parent);\n if (pStyle.display === 'none' || pStyle.visibility === 'hidden' || pStyle.opacity === '0') continue;\n\n // Skip empty text\n var rawText = textNode.textContent;\n if (!rawText || !rawText.trim()) continue;\n\n // Skip form elements (handled separately)\n if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || tag === 'OPTION') continue;\n\n // Collapse whitespace\n var collapsed = rawText.replace(/\\s+/g, ' ').trim();\n if (!collapsed) continue;\n\n // Track first text position for ref label insertion\n var refAncestor = parent.closest ? parent.closest('[data-ref-id]') : null;\n\n // Use Range + getClientRects for accurate per-line positioning\n var range = document.createRange();\n range.selectNodeContents(textNode);\n var rects = range.getClientRects();\n\n if (rects.length === 0) continue;\n\n var charOffset = 0;\n var firstWritten = false;\n for (var ri = 0; ri < rects.length; ri++) {\n var rr = rects[ri];\n if (rr.width < 1 || rr.height < 1) continue;\n\n // Skip rects outside capture area or covered by overlays\n if (rr.bottom < 0 || rr.top >= captureHeightC || rr.right < 0 || rr.left >= window.innerWidth) {\n charOffset += Math.max(1, Math.ceil(rr.width / CHAR_W));\n continue;\n }\n var rcx = rr.left + rr.width / 2;\n var rcy = rr.top + rr.height / 2;\n if (!isVisibleAt(parent, rcx, rcy)) {\n charOffset += Math.max(1, Math.ceil(rr.width / CHAR_W));\n continue;\n }\n\n var gx = Math.floor(rr.left / CHAR_W);\n var gy = Math.floor(rr.top / CHAR_H);\n var charsInLine = Math.max(1, Math.ceil(rr.width / CHAR_W));\n // Cap to actual remaining text length\n var remaining = collapsed.length - charOffset;\n if (charsInLine > remaining) charsInLine = remaining;\n var slice = collapsed.substring(charOffset, charOffset + charsInLine);\n if (slice) {\n writeToGrid(gx, gy, slice);\n\n // Record insertion point for this ref's label\n if (!firstWritten && refAncestor) {\n var rid = refAncestor.getAttribute('data-ref-id');\n if (!labeledRefs[rid]) {\n labeledRefs[rid] = {row: gy, col: gx};\n }\n firstWritten = true;\n }\n }\n charOffset += charsInLine;\n }\n }\n\n // 5. Handle form inputs\n var formEls = document.querySelectorAll('input, textarea, select');\n formEls.forEach(function(el) {\n var rect = el.getBoundingClientRect();\n var style = window.getComputedStyle(el);\n if (style.display === 'none' || style.visibility === 'hidden' || rect.width === 0 || rect.height === 0) return;\n\n var x = Math.floor(rect.left / CHAR_W);\n var y = Math.floor(rect.top / CHAR_H);\n var w = Math.max(2, Math.ceil(rect.width / CHAR_W));\n var h = Math.max(2, Math.ceil(rect.height / CHAR_H));\n var midY = y + Math.floor((h - 1) / 2);\n var refId = el.getAttribute('data-ref-id');\n\n if (el.tagName === 'SELECT') {\n var selectedText = el.options && el.selectedIndex >= 0 ? el.options[el.selectedIndex].text : '';\n var selectContent = selectedText.substring(0, Math.max(0, w - 4));\n if (selectContent) writeToGrid(x + 1, midY, selectContent);\n writeToGrid(x + w - 2, midY, 'v');\n } else {\n var val = el.value || el.getAttribute('placeholder') || '';\n if (val) writeToGrid(x + 1, midY, val);\n }\n\n // Track form element position for label insertion\n if (refId && !labeledRefs[refId]) {\n labeledRefs[refId] = {row: midY, col: x};\n }\n });\n\n // Also track ref elements with no text at all (empty buttons, icons)\n refElements.forEach(function(el) {\n var refId = el.getAttribute('data-ref-id');\n if (labeledRefs[refId]) return;\n var rect = el.getBoundingClientRect();\n var style = window.getComputedStyle(el);\n if (style.display === 'none' || style.visibility === 'hidden' || rect.width === 0 || rect.height === 0) return;\n labeledRefs[refId] = {row: Math.floor(rect.top / CHAR_H), col: Math.floor(rect.left / CHAR_W)};\n });\n\n // 6. Insert ref labels by splicing into rows (never overwrites text)\n // Collect all labels per row, sorted right-to-left so insertions don't shift later positions\n var rowInsertions = {}; // row -> [{col, label}]\n refElements.forEach(function(el) {\n var refId = el.getAttribute('data-ref-id');\n if (!refId) return;\n var pos = labeledRefs[refId];\n if (!pos) return;\n var label = '[' + refId + ']';\n if (!rowInsertions[pos.row]) rowInsertions[pos.row] = [];\n rowInsertions[pos.row].push({col: pos.col, label: label});\n });\n\n // For each row with insertions, splice labels into the row string\n for (var rowIdx in rowInsertions) {\n var r = parseInt(rowIdx, 10);\n if (r < 0 || r >= gridHeight) continue;\n var inserts = rowInsertions[r];\n // Sort by column descending so we insert right-to-left (preserves earlier positions)\n inserts.sort(function(a, b) { return b.col - a.col; });\n // Convert row to string, splice in labels, write back\n var rowStr = grid[r].join('');\n for (var ii = 0; ii < inserts.length; ii++) {\n var ins = inserts[ii];\n var c = Math.max(0, Math.min(ins.col, rowStr.length));\n // Avoid splitting inside a [...] bracket sequence \u2014 shift to before the '['\n var openBracket = rowStr.lastIndexOf('[', c);\n if (openBracket >= 0) {\n var closeBracket = rowStr.indexOf(']', openBracket);\n if (closeBracket >= c) {\n // Insertion point is inside [..], shift to before the [\n c = openBracket;\n }\n }\n rowStr = rowStr.substring(0, c) + ins.label + rowStr.substring(c);\n }\n // Write back to grid as variable-width row (will be joined as string in step 7)\n grid[r] = rowStr.split('');\n }\n\n // 7. Trim output\n var lines = [];\n for (var r = 0; r < gridHeight; r++) {\n lines.push(grid[r].join('').replace(/\\s+$/, ''));\n }\n // Drop trailing empty rows\n while (lines.length > 0 && lines[lines.length - 1] === '') {\n lines.pop();\n }\n return lines.join('\\n');\n }\n\n function repeat(ch, count) {\n var s = '';\n for (var i = 0; i < count; i++) s += ch;\n return s;\n }\n\n window.generateWireframeString = generateWireframeString;\n})();\n";
3
+ //# sourceMappingURL=normalize-script.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize-script.d.ts","sourceRoot":"","sources":["../../../../src/core/agent-browser/normalize-script.ts"],"names":[],"mappings":"AAAA,0GAA0G;AAC1G,eAAO,MAAM,gBAAgB,44uBA6gB5B,CAAC"}