@browser_use/pi 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +6 -0
- package/LICENSE +21 -0
- package/README.md +68 -0
- package/dist/agent.d.ts +15 -0
- package/dist/agent.js +381 -0
- package/dist/agent.js.map +1 -0
- package/dist/browser.d.ts +52 -0
- package/dist/browser.js +264 -0
- package/dist/browser.js.map +1 -0
- package/dist/cdp.d.ts +39 -0
- package/dist/cdp.js +291 -0
- package/dist/cdp.js.map +1 -0
- package/dist/context.d.ts +24 -0
- package/dist/context.js +143 -0
- package/dist/context.js.map +1 -0
- package/dist/control.d.ts +18 -0
- package/dist/control.js +84 -0
- package/dist/control.js.map +1 -0
- package/dist/events.d.ts +40 -0
- package/dist/events.js +79 -0
- package/dist/events.js.map +1 -0
- package/dist/highlight.d.ts +3 -0
- package/dist/highlight.js +102 -0
- package/dist/highlight.js.map +1 -0
- package/dist/history.d.ts +22 -0
- package/dist/history.js +126 -0
- package/dist/history.js.map +1 -0
- package/dist/images.d.ts +14 -0
- package/dist/images.js +104 -0
- package/dist/images.js.map +1 -0
- package/dist/index.d.ts +77 -0
- package/dist/index.js +422 -0
- package/dist/index.js.map +1 -0
- package/dist/model-stream.d.ts +3 -0
- package/dist/model-stream.js +78 -0
- package/dist/model-stream.js.map +1 -0
- package/dist/observer.d.ts +16 -0
- package/dist/observer.js +56 -0
- package/dist/observer.js.map +1 -0
- package/dist/page.d.ts +58 -0
- package/dist/page.js +189 -0
- package/dist/page.js.map +1 -0
- package/dist/policy.d.ts +18 -0
- package/dist/policy.js +195 -0
- package/dist/policy.js.map +1 -0
- package/dist/prompt.d.ts +1 -0
- package/dist/prompt.js +41 -0
- package/dist/prompt.js.map +1 -0
- package/dist/protocol.d.ts +70 -0
- package/dist/protocol.js +7 -0
- package/dist/protocol.js.map +1 -0
- package/dist/recording.d.ts +44 -0
- package/dist/recording.js +120 -0
- package/dist/recording.js.map +1 -0
- package/dist/research-tools.d.ts +3 -0
- package/dist/research-tools.js +67 -0
- package/dist/research-tools.js.map +1 -0
- package/dist/runtime.d.ts +39 -0
- package/dist/runtime.js +268 -0
- package/dist/runtime.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.js +251 -0
- package/dist/server.js.map +1 -0
- package/dist/telemetry.d.ts +3 -0
- package/dist/telemetry.js +41 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/types.d.ts +93 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/video.d.ts +18 -0
- package/dist/video.js +177 -0
- package/dist/video.js.map +1 -0
- package/dist/worker.d.ts +1 -0
- package/dist/worker.js +329 -0
- package/dist/worker.js.map +1 -0
- package/examples/README.md +58 -0
- package/examples/apply-to-job.ts +57 -0
- package/examples/ehr.ts +53 -0
- package/examples/extract.ts +50 -0
- package/examples/form.ts +36 -0
- package/examples/onepassword.ts +66 -0
- package/examples/qa.ts +72 -0
- package/examples/research.ts +35 -0
- package/examples/stripe-link.ts +166 -0
- package/package.json +66 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"highlight.js","sourceRoot":"","sources":["../src/highlight.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CDP } from './cdp.js';\n\n/** Browser Use's orange corner animation. Cosmetic, aria-hidden and pointer-transparent. */\nexport function actionHighlighter(browser: CDP) {\n let generation = 0;\n\n return async (method: string, raw: unknown, sessionId?: string) => {\n const params = raw as {\n type?: string;\n x?: number;\n y?: number;\n backendNodeId?: number;\n nodeId?: number;\n objectId?: string;\n };\n if (\n !sessionId ||\n !(\n (method === 'Input.dispatchMouseEvent' && params.type === 'mouseReleased') ||\n method === 'DOM.focus' ||\n method === 'Input.insertText'\n )\n )\n return;\n const current = ++generation;\n try {\n let node: { backendNodeId?: number; nodeId?: number; objectId?: string };\n if (method === 'Input.dispatchMouseEvent') {\n const hit = await browser.send(\n 'DOM.getNodeForLocation',\n {\n x: Math.round(params.x!),\n y: Math.round(params.y!),\n },\n sessionId,\n );\n node = { backendNodeId: hit.backendNodeId };\n } else if (method === 'DOM.focus') {\n node =\n params.backendNodeId !== undefined\n ? { backendNodeId: params.backendNodeId }\n : params.nodeId !== undefined\n ? { nodeId: params.nodeId }\n : params.objectId\n ? { objectId: params.objectId }\n : {};\n } else {\n const { result } = await browser.send(\n 'Runtime.evaluate',\n {\n expression: 'document.activeElement',\n objectGroup: `bu-pi-highlight-${current}`,\n },\n sessionId,\n );\n if (!result.objectId) return;\n node = { objectId: result.objectId };\n }\n if (current !== generation) return;\n const objectId =\n node.objectId ?? (await browser.send('DOM.resolveNode', node, sessionId)).object.objectId;\n if (!objectId) return;\n try {\n if (current !== generation) return;\n await browser.send(\n 'Runtime.callFunctionOn',\n {\n objectId,\n functionDeclaration: drawCorners.toString(),\n },\n sessionId,\n );\n } finally {\n if (!node.objectId)\n await browser.send('Runtime.releaseObject', { objectId }, sessionId).catch(() => {});\n }\n } catch {\n // Detached nodes, navigation and unsupported targets must not fail the action.\n } finally {\n if (method === 'Input.insertText')\n await browser\n .send(\n 'Runtime.releaseObjectGroup',\n { objectGroup: `bu-pi-highlight-${current}` },\n sessionId,\n )\n .catch(() => {});\n }\n };\n}\n\n// Geometry, color and timing follow browser_use/browser/session.py highlight_interaction_element.\nfunction drawCorners(this: Element) {\n const doc = this.ownerDocument;\n const rect = this.getBoundingClientRect();\n if (!this.isConnected || !rect.width || !rect.height) return;\n doc.querySelector('[data-browser-use-interaction-highlight]')?.remove();\n const host = doc.createElement('div');\n host.setAttribute('data-browser-use-interaction-highlight', 'true');\n host.setAttribute('aria-hidden', 'true');\n host.style.cssText = `all:initial;position:absolute;left:${rect.left + doc.defaultView!.scrollX}px;top:${rect.top + doc.defaultView!.scrollY}px;width:${rect.width}px;height:${rect.height}px;pointer-events:none;z-index:2147483647;opacity:1;transition:opacity .3s;`;\n const root = host.attachShadow({ mode: 'closed' });\n const size = Math.max(8, Math.min(20, Math.min(rect.width, rect.height) * 0.35));\n for (const [vertical, horizontal] of [\n ['top', 'left'],\n ['top', 'right'],\n ['bottom', 'left'],\n ['bottom', 'right'],\n ]) {\n const corner = doc.createElement('div');\n corner.style.cssText = `position:absolute;width:${size}px;height:${size}px;${vertical}:-10px;${horizontal}:-10px;border-${vertical}:3px solid rgb(255,127,39);border-${horizontal}:3px solid rgb(255,127,39);pointer-events:none;transition:all .15s ease-out;`;\n root.append(corner);\n setTimeout(() => {\n corner.style.setProperty(vertical!, '-3px');\n corner.style.setProperty(horizontal!, '-3px');\n }, 10);\n }\n doc.documentElement.append(host);\n setTimeout(() => {\n host.style.opacity = '0';\n setTimeout(() => host.remove(), 300);\n }, 1000);\n}\n"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { AgentMessage } from '@earendil-works/pi-agent-core';
|
|
2
|
+
import type { Usage } from '@earendil-works/pi-ai';
|
|
3
|
+
export interface SessionHistory {
|
|
4
|
+
version: 1;
|
|
5
|
+
model: string;
|
|
6
|
+
messages: AgentMessage[];
|
|
7
|
+
usage: Usage;
|
|
8
|
+
runs: number;
|
|
9
|
+
}
|
|
10
|
+
export interface WorkspaceFile {
|
|
11
|
+
path: string;
|
|
12
|
+
relativePath: string;
|
|
13
|
+
size: number;
|
|
14
|
+
modifiedAt: string;
|
|
15
|
+
}
|
|
16
|
+
/** JSON-safe observational copy. Non-JSON application metadata is labeled, never executed as code. */
|
|
17
|
+
export declare function redact<T>(value: T, secrets: readonly string[]): T;
|
|
18
|
+
/** Same-directory atomic replacement; mode 0600. Does not serialize the V8 heap or browser. */
|
|
19
|
+
export declare function saveHistory(path: string, history: SessionHistory, secrets?: readonly string[]): Promise<void>;
|
|
20
|
+
export declare function loadHistory(path: string, model: string): Promise<SessionHistory>;
|
|
21
|
+
/** Bounded inventory. Symlinks are excluded; files stay ordinary files owned by the caller. */
|
|
22
|
+
export declare function workspaceFiles(workspace: string): Promise<WorkspaceFile[]>;
|
package/dist/history.js
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { lstat, mkdir, open, readdir, readFile, rename, rm } from 'node:fs/promises';
|
|
2
|
+
import { dirname, join, relative } from 'node:path';
|
|
3
|
+
import { randomUUID } from 'node:crypto';
|
|
4
|
+
/** JSON-safe observational copy. Non-JSON application metadata is labeled, never executed as code. */
|
|
5
|
+
export function redact(value, secrets) {
|
|
6
|
+
const mask = (text) => secrets.reduce((text, secret) => (secret ? text.split(secret).join('[REDACTED]') : text), text);
|
|
7
|
+
const ancestors = [];
|
|
8
|
+
return JSON.parse(JSON.stringify(value, function (_key, item) {
|
|
9
|
+
if (_key === 'data' && this?.type === 'image')
|
|
10
|
+
return item;
|
|
11
|
+
if (typeof item === 'string')
|
|
12
|
+
return mask(item);
|
|
13
|
+
if (typeof item === 'bigint')
|
|
14
|
+
return `${item}n`;
|
|
15
|
+
if (typeof item === 'function' || typeof item === 'symbol')
|
|
16
|
+
return '[Non-JSON metadata]';
|
|
17
|
+
if (item && typeof item === 'object') {
|
|
18
|
+
while (ancestors.length && ancestors.at(-1) !== this)
|
|
19
|
+
ancestors.pop();
|
|
20
|
+
if (ancestors.includes(item))
|
|
21
|
+
return '[Circular metadata]';
|
|
22
|
+
ancestors.push(item);
|
|
23
|
+
}
|
|
24
|
+
return item;
|
|
25
|
+
}), (_key, item) => item && typeof item === 'object' && !Array.isArray(item)
|
|
26
|
+
? Object.fromEntries(Object.entries(item).map(([key, value]) => [mask(key), value]))
|
|
27
|
+
: item);
|
|
28
|
+
}
|
|
29
|
+
/** Same-directory atomic replacement; mode 0600. Does not serialize the V8 heap or browser. */
|
|
30
|
+
export async function saveHistory(path, history, secrets = []) {
|
|
31
|
+
await mkdir(dirname(path), { recursive: true, mode: 0o700 });
|
|
32
|
+
const temp = `${path}.${randomUUID()}.tmp`;
|
|
33
|
+
try {
|
|
34
|
+
const file = await open(temp, 'wx', 0o600);
|
|
35
|
+
try {
|
|
36
|
+
await file.writeFile(JSON.stringify(redact(history, secrets)));
|
|
37
|
+
await file.sync();
|
|
38
|
+
}
|
|
39
|
+
finally {
|
|
40
|
+
await file.close();
|
|
41
|
+
}
|
|
42
|
+
await rename(temp, path);
|
|
43
|
+
}
|
|
44
|
+
finally {
|
|
45
|
+
await rm(temp, { force: true });
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export async function loadHistory(path, model) {
|
|
49
|
+
const info = await lstat(path);
|
|
50
|
+
if (!info.isFile() || info.size > 64_000_000)
|
|
51
|
+
throw new Error('History must be a regular file no larger than 64 MB.');
|
|
52
|
+
const data = JSON.parse(await readFile(path, 'utf8'));
|
|
53
|
+
if (!data ||
|
|
54
|
+
typeof data !== 'object' ||
|
|
55
|
+
data.version !== 1 ||
|
|
56
|
+
data.model !== model ||
|
|
57
|
+
!Array.isArray(data.messages) ||
|
|
58
|
+
!Number.isSafeInteger(data.runs) ||
|
|
59
|
+
data.runs < 0)
|
|
60
|
+
throw new Error('Unsupported history version, model mismatch, or invalid history.');
|
|
61
|
+
for (const message of data.messages) {
|
|
62
|
+
if (!message ||
|
|
63
|
+
!['user', 'assistant', 'toolResult'].includes(message.role) ||
|
|
64
|
+
!('content' in message) ||
|
|
65
|
+
!(typeof message.content === 'string' || Array.isArray(message.content)))
|
|
66
|
+
throw new Error('Invalid history message.');
|
|
67
|
+
if (message.role === 'assistant' &&
|
|
68
|
+
(!message.usage || !message.model || !message.provider || !message.api))
|
|
69
|
+
throw new Error('Invalid assistant history message.');
|
|
70
|
+
if (message.role !== 'user' && !Array.isArray(message.content))
|
|
71
|
+
throw new Error('Invalid non-user message content.');
|
|
72
|
+
if (Array.isArray(message.content) &&
|
|
73
|
+
message.content.some((block) => !block || typeof block !== 'object' || typeof block.type !== 'string'))
|
|
74
|
+
throw new Error('Invalid message content block.');
|
|
75
|
+
if (message.role === 'toolResult' && (!message.toolCallId || !message.toolName))
|
|
76
|
+
throw new Error('Invalid tool history message.');
|
|
77
|
+
}
|
|
78
|
+
const validUsage = (value) => !!value &&
|
|
79
|
+
['input', 'output', 'cacheRead', 'cacheWrite', 'totalTokens'].every((k) => {
|
|
80
|
+
const n = value[k];
|
|
81
|
+
return typeof n === 'number' && Number.isFinite(n) && n >= 0;
|
|
82
|
+
}) &&
|
|
83
|
+
!!value.cost &&
|
|
84
|
+
['input', 'output', 'cacheRead', 'cacheWrite', 'total'].every((k) => {
|
|
85
|
+
const n = value.cost[k];
|
|
86
|
+
return typeof n === 'number' && Number.isFinite(n) && n >= 0;
|
|
87
|
+
});
|
|
88
|
+
if (!validUsage(data.usage) ||
|
|
89
|
+
data.messages.some((m) => m.role === 'assistant' && !validUsage(m.usage)))
|
|
90
|
+
throw new Error('Invalid history usage.');
|
|
91
|
+
return data;
|
|
92
|
+
}
|
|
93
|
+
/** Bounded inventory. Symlinks are excluded; files stay ordinary files owned by the caller. */
|
|
94
|
+
export async function workspaceFiles(workspace) {
|
|
95
|
+
const result = [];
|
|
96
|
+
const visit = async (directory, depth) => {
|
|
97
|
+
if (depth > 16)
|
|
98
|
+
throw new Error('Workspace inventory exceeds 16 directory levels.');
|
|
99
|
+
for (const entry of await readdir(directory, { withFileTypes: true })) {
|
|
100
|
+
if (entry.name === '.browser-use' ||
|
|
101
|
+
entry.name === 'node_modules' ||
|
|
102
|
+
entry.name === '.git' ||
|
|
103
|
+
entry.isSymbolicLink())
|
|
104
|
+
continue;
|
|
105
|
+
const path = join(directory, entry.name);
|
|
106
|
+
if (entry.isDirectory())
|
|
107
|
+
await visit(path, depth + 1);
|
|
108
|
+
else if (entry.isFile()) {
|
|
109
|
+
const info = await lstat(path);
|
|
110
|
+
if (!info.isFile())
|
|
111
|
+
continue;
|
|
112
|
+
result.push({
|
|
113
|
+
path,
|
|
114
|
+
relativePath: relative(workspace, path),
|
|
115
|
+
size: info.size,
|
|
116
|
+
modifiedAt: info.mtime.toISOString(),
|
|
117
|
+
});
|
|
118
|
+
if (result.length > 10_000)
|
|
119
|
+
throw new Error('Workspace inventory exceeds 10000 files.');
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
await visit(workspace, 0);
|
|
124
|
+
return result.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=history.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history.js","sourceRoot":"","sources":["../src/history.ts"],"names":[],"mappings":"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","sourcesContent":["import { lstat, mkdir, open, readdir, readFile, rename, rm } from 'node:fs/promises';\nimport { dirname, join, relative } from 'node:path';\nimport { randomUUID } from 'node:crypto';\nimport type { AgentMessage } from '@earendil-works/pi-agent-core';\nimport type { Usage } from '@earendil-works/pi-ai';\n\nexport interface SessionHistory {\n version: 1;\n model: string;\n messages: AgentMessage[];\n usage: Usage;\n runs: number;\n}\nexport interface WorkspaceFile {\n path: string;\n relativePath: string;\n size: number;\n modifiedAt: string;\n}\n\n/** JSON-safe observational copy. Non-JSON application metadata is labeled, never executed as code. */\nexport function redact<T>(value: T, secrets: readonly string[]): T {\n const mask = (text: string) =>\n secrets.reduce((text, secret) => (secret ? text.split(secret).join('[REDACTED]') : text), text);\n const ancestors: object[] = [];\n return JSON.parse(\n JSON.stringify(value, function (_key, item: unknown): unknown {\n if (_key === 'data' && this?.type === 'image') return item;\n if (typeof item === 'string') return mask(item);\n if (typeof item === 'bigint') return `${item}n`;\n if (typeof item === 'function' || typeof item === 'symbol') return '[Non-JSON metadata]';\n if (item && typeof item === 'object') {\n while (ancestors.length && ancestors.at(-1) !== this) ancestors.pop();\n if (ancestors.includes(item)) return '[Circular metadata]';\n ancestors.push(item);\n }\n return item;\n }),\n (_key, item: unknown) =>\n item && typeof item === 'object' && !Array.isArray(item)\n ? Object.fromEntries(Object.entries(item).map(([key, value]) => [mask(key), value]))\n : item,\n ) as T;\n}\n\n/** Same-directory atomic replacement; mode 0600. Does not serialize the V8 heap or browser. */\nexport async function saveHistory(\n path: string,\n history: SessionHistory,\n secrets: readonly string[] = [],\n) {\n await mkdir(dirname(path), { recursive: true, mode: 0o700 });\n const temp = `${path}.${randomUUID()}.tmp`;\n try {\n const file = await open(temp, 'wx', 0o600);\n try {\n await file.writeFile(JSON.stringify(redact(history, secrets)));\n await file.sync();\n } finally {\n await file.close();\n }\n await rename(temp, path);\n } finally {\n await rm(temp, { force: true });\n }\n}\n\nexport async function loadHistory(path: string, model: string): Promise<SessionHistory> {\n const info = await lstat(path);\n if (!info.isFile() || info.size > 64_000_000)\n throw new Error('History must be a regular file no larger than 64 MB.');\n const data = JSON.parse(await readFile(path, 'utf8')) as SessionHistory;\n if (\n !data ||\n typeof data !== 'object' ||\n data.version !== 1 ||\n data.model !== model ||\n !Array.isArray(data.messages) ||\n !Number.isSafeInteger(data.runs) ||\n data.runs < 0\n )\n throw new Error('Unsupported history version, model mismatch, or invalid history.');\n for (const message of data.messages) {\n if (\n !message ||\n !['user', 'assistant', 'toolResult'].includes(message.role) ||\n !('content' in message) ||\n !(typeof message.content === 'string' || Array.isArray(message.content))\n )\n throw new Error('Invalid history message.');\n if (\n message.role === 'assistant' &&\n (!message.usage || !message.model || !message.provider || !message.api)\n )\n throw new Error('Invalid assistant history message.');\n if (message.role !== 'user' && !Array.isArray(message.content))\n throw new Error('Invalid non-user message content.');\n if (\n Array.isArray(message.content) &&\n message.content.some(\n (block) => !block || typeof block !== 'object' || typeof block.type !== 'string',\n )\n )\n throw new Error('Invalid message content block.');\n if (message.role === 'toolResult' && (!message.toolCallId || !message.toolName))\n throw new Error('Invalid tool history message.');\n }\n const validUsage = (value: Usage): boolean =>\n !!value &&\n ['input', 'output', 'cacheRead', 'cacheWrite', 'totalTokens'].every((k) => {\n const n = value[k as keyof Usage];\n return typeof n === 'number' && Number.isFinite(n) && n >= 0;\n }) &&\n !!value.cost &&\n ['input', 'output', 'cacheRead', 'cacheWrite', 'total'].every((k) => {\n const n = value.cost[k as keyof Usage['cost']];\n return typeof n === 'number' && Number.isFinite(n) && n >= 0;\n });\n if (\n !validUsage(data.usage) ||\n data.messages.some((m) => m.role === 'assistant' && !validUsage(m.usage))\n )\n throw new Error('Invalid history usage.');\n return data;\n}\n\n/** Bounded inventory. Symlinks are excluded; files stay ordinary files owned by the caller. */\nexport async function workspaceFiles(workspace: string): Promise<WorkspaceFile[]> {\n const result: WorkspaceFile[] = [];\n const visit = async (directory: string, depth: number) => {\n if (depth > 16) throw new Error('Workspace inventory exceeds 16 directory levels.');\n for (const entry of await readdir(directory, { withFileTypes: true })) {\n if (\n entry.name === '.browser-use' ||\n entry.name === 'node_modules' ||\n entry.name === '.git' ||\n entry.isSymbolicLink()\n )\n continue;\n const path = join(directory, entry.name);\n if (entry.isDirectory()) await visit(path, depth + 1);\n else if (entry.isFile()) {\n const info = await lstat(path);\n if (!info.isFile()) continue;\n result.push({\n path,\n relativePath: relative(workspace, path),\n size: info.size,\n modifiedAt: info.mtime.toISOString(),\n });\n if (result.length > 10_000) throw new Error('Workspace inventory exceeds 10000 files.');\n }\n }\n };\n await visit(workspace, 0);\n return result.sort((a, b) => a.relativePath.localeCompare(b.relativePath));\n}\n"]}
|
package/dist/images.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ResizedImage } from '@earendil-works/pi-coding-agent';
|
|
2
|
+
import type { Image } from './protocol.js';
|
|
3
|
+
/** Read the dimensions of the three formats emitted by CDP, without decoding pixels. */
|
|
4
|
+
export declare function imageDimensions(bytes: Buffer): {
|
|
5
|
+
width: number;
|
|
6
|
+
height: number;
|
|
7
|
+
} | undefined;
|
|
8
|
+
type Resize = (bytes: Buffer, mimeType: string) => Promise<ResizedImage | null>;
|
|
9
|
+
/** Only the model preview changes. Original CDP bytes and saved artifacts stay untouched. */
|
|
10
|
+
export declare function prepareModelImages(captures: Image[], resizeImage?: Resize): Promise<{
|
|
11
|
+
images: Image[];
|
|
12
|
+
notes: string[];
|
|
13
|
+
}>;
|
|
14
|
+
export {};
|
package/dist/images.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/** Read the dimensions of the three formats emitted by CDP, without decoding pixels. */
|
|
2
|
+
export function imageDimensions(bytes) {
|
|
3
|
+
let width = 0;
|
|
4
|
+
let height = 0;
|
|
5
|
+
if (bytes.length >= 24 && bytes.subarray(0, 8).equals(Buffer.from('89504e470d0a1a0a', 'hex'))) {
|
|
6
|
+
if (bytes.toString('ascii', 12, 16) !== 'IHDR')
|
|
7
|
+
return;
|
|
8
|
+
width = bytes.readUInt32BE(16);
|
|
9
|
+
height = bytes.readUInt32BE(20);
|
|
10
|
+
}
|
|
11
|
+
else if (bytes.length >= 4 && bytes.readUInt16BE(0) === 0xffd8) {
|
|
12
|
+
let offset = 2;
|
|
13
|
+
while (offset + 1 < bytes.length && bytes[offset] === 0xff) {
|
|
14
|
+
while (bytes[offset] === 0xff)
|
|
15
|
+
offset++;
|
|
16
|
+
const marker = bytes[offset++];
|
|
17
|
+
if (marker === undefined || marker === 0xd9 || marker === 0xda)
|
|
18
|
+
return;
|
|
19
|
+
if (marker === 0x01 || (marker >= 0xd0 && marker <= 0xd8))
|
|
20
|
+
continue;
|
|
21
|
+
if (offset + 2 > bytes.length)
|
|
22
|
+
return;
|
|
23
|
+
const length = bytes.readUInt16BE(offset);
|
|
24
|
+
if (length < 2 || offset + length > bytes.length)
|
|
25
|
+
return;
|
|
26
|
+
if ([0xc0, 0xc1, 0xc2, 0xc3, 0xc5, 0xc6, 0xc7, 0xc9, 0xca, 0xcb, 0xcd, 0xce, 0xcf].includes(marker)) {
|
|
27
|
+
if (length < 8)
|
|
28
|
+
return;
|
|
29
|
+
height = bytes.readUInt16BE(offset + 3);
|
|
30
|
+
width = bytes.readUInt16BE(offset + 5);
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
offset += length;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
else if (bytes.length >= 30 &&
|
|
37
|
+
bytes.toString('ascii', 0, 4) === 'RIFF' &&
|
|
38
|
+
bytes.toString('ascii', 8, 12) === 'WEBP') {
|
|
39
|
+
const kind = bytes.toString('ascii', 12, 16);
|
|
40
|
+
if (kind === 'VP8X') {
|
|
41
|
+
width = bytes.readUIntLE(24, 3) + 1;
|
|
42
|
+
height = bytes.readUIntLE(27, 3) + 1;
|
|
43
|
+
}
|
|
44
|
+
else if (kind === 'VP8 ' && bytes.readUIntBE(23, 3) === 0x9d012a) {
|
|
45
|
+
width = bytes.readUInt16LE(26) & 0x3fff;
|
|
46
|
+
height = bytes.readUInt16LE(28) & 0x3fff;
|
|
47
|
+
}
|
|
48
|
+
else if (kind === 'VP8L' && bytes[20] === 0x2f) {
|
|
49
|
+
const packed = bytes.readUInt32LE(21);
|
|
50
|
+
width = (packed & 0x3fff) + 1;
|
|
51
|
+
height = ((packed >>> 14) & 0x3fff) + 1;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return width > 0 && height > 0 ? { width, height } : undefined;
|
|
55
|
+
}
|
|
56
|
+
const maxDimension = 2000;
|
|
57
|
+
const maxBase64Bytes = 4.5 * 1024 * 1024;
|
|
58
|
+
const resize = async (bytes, mimeType) => {
|
|
59
|
+
// Normal viewport captures never load the image backend or start a resize worker.
|
|
60
|
+
const { resizeImage } = await import('@earendil-works/pi-coding-agent');
|
|
61
|
+
return resizeImage(bytes, mimeType, {
|
|
62
|
+
maxWidth: maxDimension,
|
|
63
|
+
maxHeight: maxDimension,
|
|
64
|
+
maxBytes: maxBase64Bytes,
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
/** Only the model preview changes. Original CDP bytes and saved artifacts stay untouched. */
|
|
68
|
+
export async function prepareModelImages(captures, resizeImage = resize) {
|
|
69
|
+
const images = [];
|
|
70
|
+
const notes = [];
|
|
71
|
+
for (const [index, capture] of captures.entries()) {
|
|
72
|
+
const bytes = Buffer.from(capture.data, 'base64');
|
|
73
|
+
const dimensions = imageDimensions(bytes);
|
|
74
|
+
if (!dimensions || dimensions.width * dimensions.height > 50_000_000) {
|
|
75
|
+
notes.push(`[Screenshot ${index + 1} omitted from model vision: unsupported dimensions or over 50 megapixels. Capture a viewport or a bounded crop. Original CDP bytes are unchanged.]`);
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
if (dimensions.width <= maxDimension &&
|
|
79
|
+
dimensions.height <= maxDimension &&
|
|
80
|
+
capture.data.length < maxBase64Bytes) {
|
|
81
|
+
images.push(capture);
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
try {
|
|
85
|
+
const resized = await resizeImage(bytes, capture.mimeType);
|
|
86
|
+
const verified = resized && imageDimensions(Buffer.from(resized.data, 'base64'));
|
|
87
|
+
if (!resized ||
|
|
88
|
+
!verified ||
|
|
89
|
+
verified.width > maxDimension ||
|
|
90
|
+
verified.height > maxDimension ||
|
|
91
|
+
resized.data.length >= maxBase64Bytes) {
|
|
92
|
+
throw new Error('Preview exceeds inline limits');
|
|
93
|
+
}
|
|
94
|
+
images.push({ type: 'image', data: resized.data, mimeType: resized.mimeType });
|
|
95
|
+
notes.push(`[Screenshot ${index + 1}: original ${dimensions.width}x${dimensions.height}, model preview ${verified.width}x${verified.height}. Original CDP bytes are unchanged. A full-page preview may have unreadable text; capture a viewport or bounded crop for detail. Do not assume preview coordinates are viewport coordinates.]`);
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
// Do not poison the next provider request or fail/replay an otherwise completed browser cell.
|
|
99
|
+
notes.push(`[Screenshot ${index + 1} omitted from model vision: image resizing failed. Capture a viewport or bounded crop. Original CDP bytes are unchanged.]`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return { images, notes };
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=images.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"images.js","sourceRoot":"","sources":["../src/images.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ResizedImage } from '@earendil-works/pi-coding-agent';\nimport type { Image } from './protocol.js';\n\n/** Read the dimensions of the three formats emitted by CDP, without decoding pixels. */\nexport function imageDimensions(bytes: Buffer): { width: number; height: number } | undefined {\n let width = 0;\n let height = 0;\n if (bytes.length >= 24 && bytes.subarray(0, 8).equals(Buffer.from('89504e470d0a1a0a', 'hex'))) {\n if (bytes.toString('ascii', 12, 16) !== 'IHDR') return;\n width = bytes.readUInt32BE(16);\n height = bytes.readUInt32BE(20);\n } else if (bytes.length >= 4 && bytes.readUInt16BE(0) === 0xffd8) {\n let offset = 2;\n while (offset + 1 < bytes.length && bytes[offset] === 0xff) {\n while (bytes[offset] === 0xff) offset++;\n const marker = bytes[offset++];\n if (marker === undefined || marker === 0xd9 || marker === 0xda) return;\n if (marker === 0x01 || (marker >= 0xd0 && marker <= 0xd8)) continue;\n if (offset + 2 > bytes.length) return;\n const length = bytes.readUInt16BE(offset);\n if (length < 2 || offset + length > bytes.length) return;\n if (\n [0xc0, 0xc1, 0xc2, 0xc3, 0xc5, 0xc6, 0xc7, 0xc9, 0xca, 0xcb, 0xcd, 0xce, 0xcf].includes(\n marker,\n )\n ) {\n if (length < 8) return;\n height = bytes.readUInt16BE(offset + 3);\n width = bytes.readUInt16BE(offset + 5);\n break;\n }\n offset += length;\n }\n } else if (\n bytes.length >= 30 &&\n bytes.toString('ascii', 0, 4) === 'RIFF' &&\n bytes.toString('ascii', 8, 12) === 'WEBP'\n ) {\n const kind = bytes.toString('ascii', 12, 16);\n if (kind === 'VP8X') {\n width = bytes.readUIntLE(24, 3) + 1;\n height = bytes.readUIntLE(27, 3) + 1;\n } else if (kind === 'VP8 ' && bytes.readUIntBE(23, 3) === 0x9d012a) {\n width = bytes.readUInt16LE(26) & 0x3fff;\n height = bytes.readUInt16LE(28) & 0x3fff;\n } else if (kind === 'VP8L' && bytes[20] === 0x2f) {\n const packed = bytes.readUInt32LE(21);\n width = (packed & 0x3fff) + 1;\n height = ((packed >>> 14) & 0x3fff) + 1;\n }\n }\n return width > 0 && height > 0 ? { width, height } : undefined;\n}\n\nconst maxDimension = 2000;\nconst maxBase64Bytes = 4.5 * 1024 * 1024;\ntype Resize = (bytes: Buffer, mimeType: string) => Promise<ResizedImage | null>;\nconst resize: Resize = async (bytes, mimeType) => {\n // Normal viewport captures never load the image backend or start a resize worker.\n const { resizeImage } = await import('@earendil-works/pi-coding-agent');\n return resizeImage(bytes, mimeType, {\n maxWidth: maxDimension,\n maxHeight: maxDimension,\n maxBytes: maxBase64Bytes,\n });\n};\n\n/** Only the model preview changes. Original CDP bytes and saved artifacts stay untouched. */\nexport async function prepareModelImages(captures: Image[], resizeImage: Resize = resize) {\n const images: Image[] = [];\n const notes: string[] = [];\n for (const [index, capture] of captures.entries()) {\n const bytes = Buffer.from(capture.data, 'base64');\n const dimensions = imageDimensions(bytes);\n if (!dimensions || dimensions.width * dimensions.height > 50_000_000) {\n notes.push(\n `[Screenshot ${index + 1} omitted from model vision: unsupported dimensions or over 50 megapixels. Capture a viewport or a bounded crop. Original CDP bytes are unchanged.]`,\n );\n continue;\n }\n if (\n dimensions.width <= maxDimension &&\n dimensions.height <= maxDimension &&\n capture.data.length < maxBase64Bytes\n ) {\n images.push(capture);\n continue;\n }\n try {\n const resized = await resizeImage(bytes, capture.mimeType);\n const verified = resized && imageDimensions(Buffer.from(resized.data, 'base64'));\n if (\n !resized ||\n !verified ||\n verified.width > maxDimension ||\n verified.height > maxDimension ||\n resized.data.length >= maxBase64Bytes\n ) {\n throw new Error('Preview exceeds inline limits');\n }\n images.push({ type: 'image', data: resized.data, mimeType: resized.mimeType });\n notes.push(\n `[Screenshot ${index + 1}: original ${dimensions.width}x${dimensions.height}, model preview ${verified.width}x${verified.height}. Original CDP bytes are unchanged. A full-page preview may have unreadable text; capture a viewport or bounded crop for detail. Do not assume preview coordinates are viewport coordinates.]`,\n );\n } catch {\n // Do not poison the next provider request or fail/replay an otherwise completed browser cell.\n notes.push(\n `[Screenshot ${index + 1} omitted from model vision: image resizing failed. Capture a viewport or bounded crop. Original CDP bytes are unchanged.]`,\n );\n }\n }\n return { images, notes };\n}\n"]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { Usage } from '@earendil-works/pi-ai';
|
|
2
|
+
import { type Static, type TSchema } from 'typebox';
|
|
3
|
+
import { type SessionHistory } from './history.js';
|
|
4
|
+
import { EventStream } from './events.js';
|
|
5
|
+
import type { BrowserUseOptions, RunOptions, RunResult } from './types.js';
|
|
6
|
+
export type { BrowserUseOptions, RunOptions, RunResult, StopReason, RunMetrics } from './types.js';
|
|
7
|
+
export { Browser } from './browser.js';
|
|
8
|
+
export type { BrowserOptions, CloudBrowserOptions, ChromeBrowserOptions, LocalBrowserOptions, } from './browser.js';
|
|
9
|
+
export type { CellResult, Image } from './protocol.js';
|
|
10
|
+
export { CellError } from './runtime.js';
|
|
11
|
+
export type { AgentTool, AgentEvent, StreamFn } from '@earendil-works/pi-agent-core';
|
|
12
|
+
export { Type, type Static, type TSchema } from 'typebox';
|
|
13
|
+
export { builtinModels } from '@earendil-works/pi-ai/providers/all';
|
|
14
|
+
/** One browser, workspace and JavaScript namespace. run() resets context; followUp() retains it. */
|
|
15
|
+
export declare class BrowserUse {
|
|
16
|
+
private readonly config;
|
|
17
|
+
private readonly model;
|
|
18
|
+
private readonly runtime;
|
|
19
|
+
private readonly browser;
|
|
20
|
+
readonly workspace: string;
|
|
21
|
+
private readonly reportRun;
|
|
22
|
+
private active;
|
|
23
|
+
private closed;
|
|
24
|
+
private controller;
|
|
25
|
+
private closing;
|
|
26
|
+
private messages;
|
|
27
|
+
private totalUsage;
|
|
28
|
+
private runs;
|
|
29
|
+
private control;
|
|
30
|
+
private streams;
|
|
31
|
+
private sequence;
|
|
32
|
+
private activeRun;
|
|
33
|
+
private manualCell;
|
|
34
|
+
private runId;
|
|
35
|
+
private hasConversation;
|
|
36
|
+
private constructor();
|
|
37
|
+
static create(options: BrowserUseOptions): Promise<BrowserUse>;
|
|
38
|
+
run(task: string, options?: RunOptions): Promise<RunResult<string>>;
|
|
39
|
+
run<S extends TSchema>(task: string, options: RunOptions & {
|
|
40
|
+
schema: S;
|
|
41
|
+
}): Promise<RunResult<Static<S>>>;
|
|
42
|
+
followUp(task: string, options?: RunOptions): Promise<RunResult<string>>;
|
|
43
|
+
followUp<S extends TSchema>(task: string, options: RunOptions & {
|
|
44
|
+
schema: S;
|
|
45
|
+
}): Promise<RunResult<Static<S>>>;
|
|
46
|
+
private startRun;
|
|
47
|
+
private performRun;
|
|
48
|
+
private emit;
|
|
49
|
+
/** Subscribe before starting work. Iterators finish when the session closes. */
|
|
50
|
+
events(): EventStream;
|
|
51
|
+
get history(): SessionHistory;
|
|
52
|
+
get usage(): Usage;
|
|
53
|
+
get isPaused(): boolean;
|
|
54
|
+
files(): Promise<import("./history.js").WorkspaceFile[]>;
|
|
55
|
+
saveHistory(path?: string): Promise<string>;
|
|
56
|
+
pause(): Promise<void>;
|
|
57
|
+
resume(): Promise<void>;
|
|
58
|
+
steer(text: string): void;
|
|
59
|
+
cancel(): void;
|
|
60
|
+
/** Direct browser code. Use the same page and variables as the agent. */
|
|
61
|
+
execute(code: string, options?: {
|
|
62
|
+
timeoutMs?: number;
|
|
63
|
+
signal?: AbortSignal;
|
|
64
|
+
}): Promise<import("./protocol.js").CellResult>;
|
|
65
|
+
private assertIdle;
|
|
66
|
+
/** Idempotent. Cancels execution, closes our tab, and shuts down only browsers we launched. */
|
|
67
|
+
close(): Promise<void>;
|
|
68
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
69
|
+
}
|
|
70
|
+
export { CDP } from './cdp.js';
|
|
71
|
+
export { Page, Tabs, type AXNode } from './page.js';
|
|
72
|
+
export type { SessionHistory, WorkspaceFile } from './history.js';
|
|
73
|
+
export type { SessionEvent } from './events.js';
|
|
74
|
+
export { formatEvent } from './events.js';
|
|
75
|
+
export { exportRecording, type VideoOptions } from './video.js';
|
|
76
|
+
export type { RecordingOptions } from './recording.js';
|
|
77
|
+
export type { DomainOptions, SensitiveData } from './policy.js';
|