Cleanup: Remove unnecessary Library folder and keep plug files at root
All checks were successful
Build SilverBullet Plug / build (push) Successful in 31s

This commit is contained in:
2026-02-17 13:45:09 -08:00
parent 62d4ba1006
commit a11c6bd906
947 changed files with 434513 additions and 10 deletions

View File

@@ -0,0 +1,335 @@
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var actionRunner_exports = {};
__export(actionRunner_exports, {
runAction: () => runAction,
traceParamsForAction: () => traceParamsForAction
});
module.exports = __toCommonJS(actionRunner_exports);
var import_expectUtils = require("../utils/expectUtils");
var import_urlMatch = require("../../utils/isomorphic/urlMatch");
var import_stringUtils = require("../../utils/isomorphic/stringUtils");
var import_time = require("../../utils/isomorphic/time");
var import_crypto = require("../utils/crypto");
var import_ariaSnapshot = require("../../utils/isomorphic/ariaSnapshot");
var import_locatorGenerators = require("../../utils/isomorphic/locatorGenerators");
var import_utilsBundle = require("../../utilsBundle");
var import_errors = require("../errors");
async function runAction(progress, mode, page, action, secrets) {
const parentMetadata = progress.metadata;
const frame = page.mainFrame();
const callMetadata = callMetadataForAction(progress, frame, action, mode);
callMetadata.log = parentMetadata.log;
progress.metadata = callMetadata;
await frame.instrumentation.onBeforeCall(frame, callMetadata, parentMetadata.id);
let error;
const result = await innerRunAction(progress, mode, page, action, secrets).catch((e) => error = e);
callMetadata.endTime = (0, import_time.monotonicTime)();
callMetadata.error = error ? (0, import_errors.serializeError)(error) : void 0;
callMetadata.result = error ? void 0 : result;
await frame.instrumentation.onAfterCall(frame, callMetadata);
if (error)
throw error;
return result;
}
async function innerRunAction(progress, mode, page, action, secrets) {
const frame = page.mainFrame();
const commonOptions = { strict: true, noAutoWaiting: mode === "generate" };
switch (action.method) {
case "navigate":
await frame.goto(progress, action.url);
break;
case "click":
await frame.click(progress, action.selector, {
button: action.button,
clickCount: action.clickCount,
modifiers: action.modifiers,
...commonOptions
});
break;
case "drag":
await frame.dragAndDrop(progress, action.sourceSelector, action.targetSelector, { ...commonOptions });
break;
case "hover":
await frame.hover(progress, action.selector, {
modifiers: action.modifiers,
...commonOptions
});
break;
case "selectOption":
await frame.selectOption(progress, action.selector, [], action.labels.map((a) => ({ label: a })), { ...commonOptions });
break;
case "pressKey":
await page.keyboard.press(progress, action.key);
break;
case "pressSequentially": {
const secret = secrets?.find((s) => s.name === action.text)?.value ?? action.text;
await frame.type(progress, action.selector, secret, { ...commonOptions });
if (action.submit)
await page.keyboard.press(progress, "Enter");
break;
}
case "fill": {
const secret = secrets?.find((s) => s.name === action.text)?.value ?? action.text;
await frame.fill(progress, action.selector, secret, { ...commonOptions });
if (action.submit)
await page.keyboard.press(progress, "Enter");
break;
}
case "setChecked":
if (action.checked)
await frame.check(progress, action.selector, { ...commonOptions });
else
await frame.uncheck(progress, action.selector, { ...commonOptions });
break;
case "expectVisible": {
await runExpect(frame, progress, mode, action.selector, { expression: "to.be.visible", isNot: !!action.isNot }, "visible", "toBeVisible", "");
break;
}
case "expectValue": {
if (action.type === "textbox" || action.type === "combobox" || action.type === "slider") {
const expectedText = (0, import_expectUtils.serializeExpectedTextValues)([action.value]);
await runExpect(frame, progress, mode, action.selector, { expression: "to.have.value", expectedText, isNot: !!action.isNot }, action.value, "toHaveValue", "expected");
} else if (action.type === "checkbox" || action.type === "radio") {
const expectedValue = { checked: action.value === "true" };
await runExpect(frame, progress, mode, action.selector, { selector: action.selector, expression: "to.be.checked", expectedValue, isNot: !!action.isNot }, action.value ? "checked" : "unchecked", "toBeChecked", "");
} else {
throw new Error(`Unsupported element type: ${action.type}`);
}
break;
}
case "expectAria": {
const expectedValue = (0, import_ariaSnapshot.parseAriaSnapshotUnsafe)(import_utilsBundle.yaml, action.template);
await runExpect(frame, progress, mode, "body", { expression: "to.match.aria", expectedValue, isNot: !!action.isNot }, "\n" + action.template, "toMatchAriaSnapshot", "expected");
break;
}
case "expectURL": {
if (!action.regex && !action.value)
throw new Error("Either url or regex must be provided");
if (action.regex && action.value)
throw new Error("Only one of url or regex can be provided");
const expected = action.regex ? (0, import_stringUtils.parseRegex)(action.regex) : (0, import_urlMatch.constructURLBasedOnBaseURL)(page.browserContext._options.baseURL, action.value);
const expectedText = (0, import_expectUtils.serializeExpectedTextValues)([expected]);
await runExpect(frame, progress, mode, void 0, { expression: "to.have.url", expectedText, isNot: !!action.isNot }, expected, "toHaveURL", "expected");
break;
}
case "expectTitle": {
const expectedText = (0, import_expectUtils.serializeExpectedTextValues)([action.value], { normalizeWhiteSpace: true });
await runExpect(frame, progress, mode, void 0, { expression: "to.have.title", expectedText, isNot: !!action.isNot }, action.value, "toHaveTitle", "expected");
break;
}
}
}
async function runExpect(frame, progress, mode, selector, options, expected, matcherName, expectation) {
const result = await frame.expect(progress, selector, {
...options,
// When generating, we want the expect to pass or fail immediately and give feedback to the model.
noAutoWaiting: mode === "generate",
timeoutForLogs: mode === "generate" ? void 0 : progress.timeout
});
if (!result.matches === !options.isNot) {
const received = matcherName === "toMatchAriaSnapshot" ? "\n" + result.received.raw : result.received;
const expectedSuffix = typeof expected === "string" ? "" : " pattern";
const expectedDisplay = typeof expected === "string" ? expected : expected.toString();
throw new Error((0, import_expectUtils.formatMatcherMessage)(import_expectUtils.simpleMatcherUtils, {
isNot: options.isNot,
matcherName,
expectation,
locator: selector ? (0, import_locatorGenerators.asLocatorDescription)("javascript", selector) : void 0,
timedOut: result.timedOut,
timeout: mode === "generate" ? void 0 : progress.timeout,
printedExpected: options.isNot ? `Expected${expectedSuffix}: not ${expectedDisplay}` : `Expected${expectedSuffix}: ${expectedDisplay}`,
printedReceived: result.errorMessage ? "" : `Received: ${received}`,
errorMessage: result.errorMessage
// Note: we are not passing call log, because it will be automatically appended on the client side,
// as a part of the agent.{perform,expect} call.
}));
}
}
function traceParamsForAction(progress, action, mode) {
const timeout = progress.timeout;
switch (action.method) {
case "navigate": {
const params = {
url: action.url,
timeout
};
return { type: "Frame", method: "goto", params };
}
case "click": {
const params = {
selector: action.selector,
strict: true,
modifiers: action.modifiers,
button: action.button,
clickCount: action.clickCount,
timeout
};
return { type: "Frame", method: "click", params };
}
case "drag": {
const params = {
source: action.sourceSelector,
target: action.targetSelector,
timeout
};
return { type: "Frame", method: "dragAndDrop", params };
}
case "hover": {
const params = {
selector: action.selector,
modifiers: action.modifiers,
timeout
};
return { type: "Frame", method: "hover", params };
}
case "pressKey": {
const params = {
key: action.key
};
return { type: "Page", method: "keyboardPress", params };
}
case "pressSequentially": {
const params = {
selector: action.selector,
text: action.text,
timeout
};
return { type: "Frame", method: "type", params };
}
case "fill": {
const params = {
selector: action.selector,
strict: true,
value: action.text,
timeout
};
return { type: "Frame", method: "fill", params };
}
case "setChecked": {
if (action.checked) {
const params = {
selector: action.selector,
strict: true,
timeout
};
return { type: "Frame", method: "check", params };
} else {
const params = {
selector: action.selector,
strict: true,
timeout
};
return { type: "Frame", method: "uncheck", params };
}
}
case "selectOption": {
const params = {
selector: action.selector,
strict: true,
options: action.labels.map((label) => ({ label })),
timeout
};
return { type: "Frame", method: "selectOption", params };
}
case "expectValue": {
if (action.type === "textbox" || action.type === "combobox" || action.type === "slider") {
const expectedText = (0, import_expectUtils.serializeExpectedTextValues)([action.value]);
const params = {
selector: action.selector,
expression: "to.have.value",
expectedText,
isNot: !!action.isNot,
timeout
};
return { type: "Frame", method: "expect", title: "Expect Value", params };
} else if (action.type === "checkbox" || action.type === "radio") {
const params = {
selector: action.selector,
expression: "to.be.checked",
isNot: !!action.isNot,
timeout
};
return { type: "Frame", method: "expect", title: "Expect Checked", params };
} else {
throw new Error(`Unsupported element type: ${action.type}`);
}
}
case "expectVisible": {
const params = {
selector: action.selector,
expression: "to.be.visible",
isNot: !!action.isNot,
timeout
};
return { type: "Frame", method: "expect", title: "Expect Visible", params };
}
case "expectAria": {
const params = {
selector: "body",
expression: "to.match.snapshot",
expectedText: [],
isNot: !!action.isNot,
timeout
};
return { type: "Frame", method: "expect", title: "Expect Aria Snapshot", params };
}
case "expectURL": {
const expected = action.regex ? (0, import_stringUtils.parseRegex)(action.regex) : action.value;
const expectedText = (0, import_expectUtils.serializeExpectedTextValues)([expected]);
const params = {
selector: void 0,
expression: "to.have.url",
expectedText,
isNot: !!action.isNot,
timeout
};
return { type: "Frame", method: "expect", title: "Expect URL", params };
}
case "expectTitle": {
const expectedText = (0, import_expectUtils.serializeExpectedTextValues)([action.value], { normalizeWhiteSpace: true });
const params = {
selector: void 0,
expression: "to.have.title",
expectedText,
isNot: !!action.isNot,
timeout
};
return { type: "Frame", method: "expect", title: "Expect Title", params };
}
}
}
function callMetadataForAction(progress, frame, action, mode) {
const callMetadata = {
id: `call@${(0, import_crypto.createGuid)()}`,
objectId: frame.guid,
pageId: frame._page.guid,
frameId: frame.guid,
startTime: (0, import_time.monotonicTime)(),
endTime: 0,
log: [],
...traceParamsForAction(progress, action, mode)
};
return callMetadata;
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
runAction,
traceParamsForAction
});

View File

@@ -0,0 +1,128 @@
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var actions_exports = {};
__export(actions_exports, {
cachedActionsSchema: () => cachedActionsSchema
});
module.exports = __toCommonJS(actions_exports);
var import_mcpBundle = require("../../mcpBundle");
const modifiersSchema = import_mcpBundle.z.array(
import_mcpBundle.z.enum(["Alt", "Control", "ControlOrMeta", "Meta", "Shift"])
);
const navigateActionSchema = import_mcpBundle.z.object({
method: import_mcpBundle.z.literal("navigate"),
url: import_mcpBundle.z.string()
});
const clickActionSchema = import_mcpBundle.z.object({
method: import_mcpBundle.z.literal("click"),
selector: import_mcpBundle.z.string(),
button: import_mcpBundle.z.enum(["left", "right", "middle"]).optional(),
clickCount: import_mcpBundle.z.number().optional(),
modifiers: modifiersSchema.optional()
});
const dragActionSchema = import_mcpBundle.z.object({
method: import_mcpBundle.z.literal("drag"),
sourceSelector: import_mcpBundle.z.string(),
targetSelector: import_mcpBundle.z.string()
});
const hoverActionSchema = import_mcpBundle.z.object({
method: import_mcpBundle.z.literal("hover"),
selector: import_mcpBundle.z.string(),
modifiers: modifiersSchema.optional()
});
const selectOptionActionSchema = import_mcpBundle.z.object({
method: import_mcpBundle.z.literal("selectOption"),
selector: import_mcpBundle.z.string(),
labels: import_mcpBundle.z.array(import_mcpBundle.z.string())
});
const pressActionSchema = import_mcpBundle.z.object({
method: import_mcpBundle.z.literal("pressKey"),
key: import_mcpBundle.z.string()
});
const pressSequentiallyActionSchema = import_mcpBundle.z.object({
method: import_mcpBundle.z.literal("pressSequentially"),
selector: import_mcpBundle.z.string(),
text: import_mcpBundle.z.string(),
submit: import_mcpBundle.z.boolean().optional()
});
const fillActionSchema = import_mcpBundle.z.object({
method: import_mcpBundle.z.literal("fill"),
selector: import_mcpBundle.z.string(),
text: import_mcpBundle.z.string(),
submit: import_mcpBundle.z.boolean().optional()
});
const setCheckedSchema = import_mcpBundle.z.object({
method: import_mcpBundle.z.literal("setChecked"),
selector: import_mcpBundle.z.string(),
checked: import_mcpBundle.z.boolean()
});
const expectVisibleSchema = import_mcpBundle.z.object({
method: import_mcpBundle.z.literal("expectVisible"),
selector: import_mcpBundle.z.string(),
isNot: import_mcpBundle.z.boolean().optional()
});
const expectValueSchema = import_mcpBundle.z.object({
method: import_mcpBundle.z.literal("expectValue"),
selector: import_mcpBundle.z.string(),
type: import_mcpBundle.z.enum(["textbox", "checkbox", "radio", "combobox", "slider"]),
value: import_mcpBundle.z.string(),
isNot: import_mcpBundle.z.boolean().optional()
});
const expectAriaSchema = import_mcpBundle.z.object({
method: import_mcpBundle.z.literal("expectAria"),
template: import_mcpBundle.z.string(),
isNot: import_mcpBundle.z.boolean().optional()
});
const expectURLSchema = import_mcpBundle.z.object({
method: import_mcpBundle.z.literal("expectURL"),
value: import_mcpBundle.z.string().optional(),
regex: import_mcpBundle.z.string().optional(),
isNot: import_mcpBundle.z.boolean().optional()
});
const expectTitleSchema = import_mcpBundle.z.object({
method: import_mcpBundle.z.literal("expectTitle"),
value: import_mcpBundle.z.string(),
isNot: import_mcpBundle.z.boolean().optional()
});
const actionSchema = import_mcpBundle.z.discriminatedUnion("method", [
navigateActionSchema,
clickActionSchema,
dragActionSchema,
hoverActionSchema,
selectOptionActionSchema,
pressActionSchema,
pressSequentiallyActionSchema,
fillActionSchema,
setCheckedSchema,
expectVisibleSchema,
expectValueSchema,
expectAriaSchema,
expectURLSchema,
expectTitleSchema
]);
const actionWithCodeSchema = actionSchema.and(import_mcpBundle.z.object({
code: import_mcpBundle.z.string()
}));
const cachedActionsSchema = import_mcpBundle.z.record(import_mcpBundle.z.string(), import_mcpBundle.z.object({
actions: import_mcpBundle.z.array(actionWithCodeSchema)
}));
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
cachedActionsSchema
});

View File

@@ -0,0 +1,111 @@
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var codegen_exports = {};
__export(codegen_exports, {
generateCode: () => generateCode
});
module.exports = __toCommonJS(codegen_exports);
var import_locatorGenerators = require("../../utils/isomorphic/locatorGenerators");
var import_stringUtils = require("../../utils/isomorphic/stringUtils");
async function generateCode(sdkLanguage, action) {
switch (action.method) {
case "navigate": {
return `await page.goto(${(0, import_stringUtils.escapeWithQuotes)(action.url)});`;
}
case "click": {
const locator = (0, import_locatorGenerators.asLocator)(sdkLanguage, action.selector);
return `await page.${locator}.click(${(0, import_stringUtils.formatObjectOrVoid)({
button: action.button,
clickCount: action.clickCount,
modifiers: action.modifiers
})});`;
}
case "drag": {
const sourceLocator = (0, import_locatorGenerators.asLocator)(sdkLanguage, action.sourceSelector);
const targetLocator = (0, import_locatorGenerators.asLocator)(sdkLanguage, action.targetSelector);
return `await page.${sourceLocator}.dragAndDrop(${targetLocator});`;
}
case "hover": {
const locator = (0, import_locatorGenerators.asLocator)(sdkLanguage, action.selector);
return `await page.${locator}.hover(${(0, import_stringUtils.formatObjectOrVoid)({
modifiers: action.modifiers
})});`;
}
case "pressKey": {
return `await page.keyboard.press(${(0, import_stringUtils.escapeWithQuotes)(action.key, "'")});`;
}
case "selectOption": {
const locator = (0, import_locatorGenerators.asLocator)(sdkLanguage, action.selector);
return `await page.${locator}.selectOption(${action.labels.length === 1 ? (0, import_stringUtils.escapeWithQuotes)(action.labels[0]) : "[" + action.labels.map((label) => (0, import_stringUtils.escapeWithQuotes)(label)).join(", ") + "]"});`;
}
case "pressSequentially": {
const locator = (0, import_locatorGenerators.asLocator)(sdkLanguage, action.selector);
const code = [`await page.${locator}.pressSequentially(${(0, import_stringUtils.escapeWithQuotes)(action.text)});`];
if (action.submit)
code.push(`await page.keyboard.press('Enter');`);
return code.join("\n");
}
case "fill": {
const locator = (0, import_locatorGenerators.asLocator)(sdkLanguage, action.selector);
const code = [`await page.${locator}.fill(${(0, import_stringUtils.escapeWithQuotes)(action.text)});`];
if (action.submit)
code.push(`await page.keyboard.press('Enter');`);
return code.join("\n");
}
case "setChecked": {
const locator = (0, import_locatorGenerators.asLocator)(sdkLanguage, action.selector);
if (action.checked)
return `await page.${locator}.check();`;
else
return `await page.${locator}.uncheck();`;
}
case "expectVisible": {
const locator = (0, import_locatorGenerators.asLocator)(sdkLanguage, action.selector);
const notInfix = action.isNot ? "not." : "";
return `await expect(page.${locator}).${notInfix}toBeVisible();`;
}
case "expectValue": {
const notInfix = action.isNot ? "not." : "";
const locator = (0, import_locatorGenerators.asLocator)(sdkLanguage, action.selector);
if (action.type === "checkbox" || action.type === "radio")
return `await expect(page.${locator}).${notInfix}toBeChecked({ checked: ${action.value === "true"} });`;
return `await expect(page.${locator}).${notInfix}toHaveValue(${(0, import_stringUtils.escapeWithQuotes)(action.value)});`;
}
case "expectAria": {
const notInfix = action.isNot ? "not." : "";
return `await expect(page.locator('body')).${notInfix}toMatchAria(\`
${(0, import_stringUtils.escapeTemplateString)(action.template)}
\`);`;
}
case "expectURL": {
const arg = action.regex ? (0, import_stringUtils.parseRegex)(action.regex).toString() : (0, import_stringUtils.escapeWithQuotes)(action.value);
const notInfix = action.isNot ? "not." : "";
return `await expect(page).${notInfix}toHaveURL(${arg});`;
}
case "expectTitle": {
const notInfix = action.isNot ? "not." : "";
return `await expect(page).${notInfix}toHaveTitle(${(0, import_stringUtils.escapeWithQuotes)(action.value)});`;
}
}
throw new Error("Unknown action " + action.method);
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
generateCode
});

View File

@@ -0,0 +1,150 @@
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var context_exports = {};
__export(context_exports, {
Context: () => Context
});
module.exports = __toCommonJS(context_exports);
var import_browserContext = require("../browserContext");
var import_actionRunner = require("./actionRunner");
var import_codegen = require("./codegen");
var import_stringUtils = require("../../utils/isomorphic/stringUtils");
class Context {
constructor(page, agentParams, events) {
this._actions = [];
this._history = [];
this.page = page;
this.agentParams = agentParams;
this.sdkLanguage = page.browserContext._browser.sdkLanguage();
this.events = events;
this._budget = { tokens: agentParams.maxTokens };
}
async runActionAndWait(progress, action) {
return await this.runActionsAndWait(progress, [action]);
}
async runActionsAndWait(progress, action, options) {
const error = await this.waitForCompletion(progress, async () => {
for (const a of action) {
await (0, import_actionRunner.runAction)(progress, "generate", this.page, a, this.agentParams?.secrets ?? []);
const code = await (0, import_codegen.generateCode)(this.sdkLanguage, a);
this._actions.push({ ...a, code });
}
return void 0;
}, options).catch((error2) => error2);
return await this.snapshotResult(progress, error);
}
async runActionNoWait(progress, action) {
return await this.runActionsAndWait(progress, [action], { noWait: true });
}
actions() {
return this._actions.slice();
}
history() {
return this._history;
}
pushHistory(item) {
this._history.push(item);
this._actions = [];
}
consumeTokens(tokens) {
if (this._budget.tokens === void 0)
return;
this._budget.tokens = Math.max(0, this._budget.tokens - tokens);
}
maxTokensRemaining() {
return this._budget.tokens;
}
async waitForCompletion(progress, callback, options) {
if (options?.noWait)
return await callback();
const requests = [];
const requestListener = (request) => requests.push(request);
const disposeListeners = () => {
this.page.browserContext.off(import_browserContext.BrowserContext.Events.Request, requestListener);
};
this.page.browserContext.on(import_browserContext.BrowserContext.Events.Request, requestListener);
let result;
try {
result = await callback();
await progress.wait(500);
} finally {
disposeListeners();
}
const requestedNavigation = requests.some((request) => request.isNavigationRequest());
if (requestedNavigation) {
await this.page.mainFrame().waitForLoadState(progress, "load");
return result;
}
const promises = [];
for (const request of requests) {
if (["document", "stylesheet", "script", "xhr", "fetch"].includes(request.resourceType()))
promises.push(request.response().then((r) => r?.finished()));
else
promises.push(request.response());
}
await progress.race([...promises, progress.wait(5e3)]);
if (!promises.length)
await progress.wait(500);
return result;
}
async takeSnapshot(progress) {
const { full } = await this.page.snapshotForAI(progress, { doNotRenderActive: this.agentParams.doNotRenderActive });
return full;
}
async snapshotResult(progress, error) {
const snapshot = this._redactText(await this.takeSnapshot(progress));
const text = [];
if (error)
text.push(`# Error
${(0, import_stringUtils.stripAnsiEscapes)(error.message)}`);
else
text.push(`# Success`);
text.push(`# Page snapshot
${snapshot}`);
return {
isError: !!error,
content: [{ type: "text", text: text.join("\n\n") }]
};
}
async refSelectors(progress, params) {
return Promise.all(params.map(async (param) => {
try {
const { resolvedSelector } = await this.page.mainFrame().resolveSelector(progress, `aria-ref=${param.ref}`);
return resolvedSelector;
} catch (e) {
throw new Error(`Ref ${param.ref} not found in the current page snapshot. Try capturing new snapshot.`);
}
}));
}
_redactText(text) {
const secrets = this.agentParams?.secrets;
if (!secrets)
return text;
const redactText = (text2) => {
for (const { name, value } of secrets)
text2 = text2.replaceAll(value, `<secret>${name}</secret>`);
return text2;
};
return redactText(text);
}
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
Context
});

View File

@@ -0,0 +1,156 @@
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var expectTools_exports = {};
__export(expectTools_exports, {
default: () => expectTools_default
});
module.exports = __toCommonJS(expectTools_exports);
var import_mcpBundle = require("../../mcpBundle");
var import_locatorUtils = require("../../utils/isomorphic/locatorUtils");
var import_yaml = require("../../utils/isomorphic/yaml");
var import_tool = require("./tool");
const expectVisible = (0, import_tool.defineTool)({
schema: {
name: "browser_expect_visible",
title: "Expect element visible",
description: "Expect element is visible on the page",
inputSchema: import_mcpBundle.z.object({
role: import_mcpBundle.z.string().describe('ROLE of the element. Can be found in the snapshot like this: `- {ROLE} "Accessible Name":`'),
accessibleName: import_mcpBundle.z.string().describe('ACCESSIBLE_NAME of the element. Can be found in the snapshot like this: `- role "{ACCESSIBLE_NAME}"`'),
isNot: import_mcpBundle.z.boolean().optional().describe("Expect the opposite")
})
},
handle: async (progress, context, params) => {
return await context.runActionAndWait(progress, {
method: "expectVisible",
selector: (0, import_locatorUtils.getByRoleSelector)(params.role, { name: params.accessibleName }),
isNot: params.isNot
});
}
});
const expectVisibleText = (0, import_tool.defineTool)({
schema: {
name: "browser_expect_visible_text",
title: "Expect text visible",
description: `Expect text is visible on the page. Prefer ${expectVisible.schema.name} if possible.`,
inputSchema: import_mcpBundle.z.object({
text: import_mcpBundle.z.string().describe('TEXT to expect. Can be found in the snapshot like this: `- role "Accessible Name": {TEXT}` or like this: `- text: {TEXT}`'),
isNot: import_mcpBundle.z.boolean().optional().describe("Expect the opposite")
})
},
handle: async (progress, context, params) => {
return await context.runActionAndWait(progress, {
method: "expectVisible",
selector: (0, import_locatorUtils.getByTextSelector)(params.text),
isNot: params.isNot
});
}
});
const expectValue = (0, import_tool.defineTool)({
schema: {
name: "browser_expect_value",
title: "Expect value",
description: "Expect element value",
inputSchema: import_mcpBundle.z.object({
type: import_mcpBundle.z.enum(["textbox", "checkbox", "radio", "combobox", "slider"]).describe("Type of the element"),
element: import_mcpBundle.z.string().describe("Human-readable element description"),
ref: import_mcpBundle.z.string().describe("Exact target element reference from the page snapshot"),
value: import_mcpBundle.z.string().describe('Value to expect. For checkbox, use "true" or "false".'),
isNot: import_mcpBundle.z.boolean().optional().describe("Expect the opposite")
})
},
handle: async (progress, context, params) => {
const [selector] = await context.refSelectors(progress, [{ ref: params.ref, element: params.element }]);
return await context.runActionAndWait(progress, {
method: "expectValue",
selector,
type: params.type,
value: params.value,
isNot: params.isNot
});
}
});
const expectList = (0, import_tool.defineTool)({
schema: {
name: "browser_expect_list_visible",
title: "Expect list visible",
description: "Expect list is visible on the page, ensures items are present in the element in the exact order",
inputSchema: import_mcpBundle.z.object({
listRole: import_mcpBundle.z.string().describe("Aria role of the list element as in the snapshot"),
listAccessibleName: import_mcpBundle.z.string().optional().describe("Accessible name of the list element as in the snapshot"),
itemRole: import_mcpBundle.z.string().describe("Aria role of the list items as in the snapshot, should all be the same"),
items: import_mcpBundle.z.array(import_mcpBundle.z.string().describe("Text to look for in the list item, can be either from accessible name of self / nested text content")),
isNot: import_mcpBundle.z.boolean().optional().describe("Expect the opposite")
})
},
handle: async (progress, context, params) => {
const template = `- ${params.listRole}:
${params.items.map((item) => ` - ${params.itemRole}: ${(0, import_yaml.yamlEscapeValueIfNeeded)(item)}`).join("\n")}`;
return await context.runActionAndWait(progress, {
method: "expectAria",
template
});
}
});
const expectURL = (0, import_tool.defineTool)({
schema: {
name: "browser_expect_url",
title: "Expect URL",
description: "Expect the page URL to match the expected value. Either provide a url string or a regex pattern.",
inputSchema: import_mcpBundle.z.object({
url: import_mcpBundle.z.string().optional().describe("Expected URL string. Relative URLs are resolved against the baseURL."),
regex: import_mcpBundle.z.string().optional().describe("Regular expression pattern to match the URL against, e.g. /foo.*/i."),
isNot: import_mcpBundle.z.boolean().optional().describe("Expect the opposite")
})
},
handle: async (progress, context, params) => {
return await context.runActionAndWait(progress, {
method: "expectURL",
value: params.url,
regex: params.regex,
isNot: params.isNot
});
}
});
const expectTitle = (0, import_tool.defineTool)({
schema: {
name: "browser_expect_title",
title: "Expect title",
description: "Expect the page title to match the expected value.",
inputSchema: import_mcpBundle.z.object({
title: import_mcpBundle.z.string().describe("Expected page title."),
isNot: import_mcpBundle.z.boolean().optional().describe("Expect the opposite")
})
},
handle: async (progress, context, params) => {
return await context.runActionAndWait(progress, {
method: "expectTitle",
value: params.title,
isNot: params.isNot
});
}
});
var expectTools_default = [
expectVisible,
expectVisibleText,
expectValue,
expectList,
expectURL,
expectTitle
];

View File

@@ -0,0 +1,204 @@
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var pageAgent_exports = {};
__export(pageAgent_exports, {
pageAgentExpect: () => pageAgentExpect,
pageAgentExtract: () => pageAgentExtract,
pageAgentPerform: () => pageAgentPerform
});
module.exports = __toCommonJS(pageAgent_exports);
var import_fs = __toESM(require("fs"));
var import_path = __toESM(require("path"));
var import_tool = require("./tool");
var import_utilsBundle = require("../../utilsBundle");
var import_mcpBundle = require("../../mcpBundle");
var import_actionRunner = require("./actionRunner");
var import_performTools = __toESM(require("./performTools"));
var import_expectTools = __toESM(require("./expectTools"));
var actions = __toESM(require("./actions"));
async function pageAgentPerform(progress, context, userTask, callParams) {
const cacheKey = (callParams.cacheKey ?? userTask).trim();
if (await cachedPerform(progress, context, cacheKey))
return;
const task = `
### Instructions
- Perform the following task on the page.
- Your reply should be a tool call that performs action the page".
### Task
${userTask}
`;
progress.disableTimeout();
await runLoop(progress, context, import_performTools.default, task, void 0, callParams);
await updateCache(context, cacheKey);
}
async function pageAgentExpect(progress, context, expectation, callParams) {
const cacheKey = (callParams.cacheKey ?? expectation).trim();
if (await cachedPerform(progress, context, cacheKey))
return;
const task = `
### Instructions
- Call one of the "browser_expect_*" tools to verify / assert the condition.
- You can call exactly one tool and it can't be report_results, must be one of the assertion tools.
### Expectation
${expectation}
`;
progress.disableTimeout();
await runLoop(progress, context, import_expectTools.default, task, void 0, callParams);
await updateCache(context, cacheKey);
}
async function pageAgentExtract(progress, context, query, schema, callParams) {
const task = `
### Instructions
Extract the following information from the page. Do not perform any actions, just extract the information.
### Query
${query}`;
const { result } = await runLoop(progress, context, [], task, schema, callParams);
return result;
}
async function runLoop(progress, context, toolDefinitions, userTask, resultSchema, params) {
if (!context.agentParams.api || !context.agentParams.model)
throw new Error(`This action requires the API and API key to be set on the page agent. Did you mean to --run-agents=missing?`);
if (!context.agentParams.apiKey)
throw new Error(`This action requires API key to be set on the page agent.`);
if (context.agentParams.apiEndpoint && !URL.canParse(context.agentParams.apiEndpoint))
throw new Error(`Agent API endpoint "${context.agentParams.apiEndpoint}" is not a valid URL.`);
const snapshot = await context.takeSnapshot(progress);
const { tools, callTool, reportedResult, refusedToPerformReason } = (0, import_tool.toolsForLoop)(progress, context, toolDefinitions, { resultSchema, refuseToPerform: "allow" });
const secrets = Object.fromEntries((context.agentParams.secrets || [])?.map((s) => [s.name, s.value]));
const apiCacheTextBefore = context.agentParams.apiCacheFile ? await import_fs.default.promises.readFile(context.agentParams.apiCacheFile, "utf-8").catch(() => "{}") : "{}";
const apiCacheBefore = JSON.parse(apiCacheTextBefore || "{}");
const loop = new import_mcpBundle.Loop({
api: context.agentParams.api,
apiEndpoint: context.agentParams.apiEndpoint,
apiKey: context.agentParams.apiKey,
apiTimeout: context.agentParams.apiTimeout ?? 0,
model: context.agentParams.model,
maxTokens: params.maxTokens ?? context.maxTokensRemaining(),
maxToolCalls: params.maxActions ?? context.agentParams.maxActions ?? 10,
maxToolCallRetries: params.maxActionRetries ?? context.agentParams.maxActionRetries ?? 3,
summarize: true,
debug: import_utilsBundle.debug,
callTool,
tools,
secrets,
cache: apiCacheBefore,
...context.events
});
const task = [];
if (context.agentParams.systemPrompt) {
task.push("### System");
task.push(context.agentParams.systemPrompt);
task.push("");
}
task.push("### Task");
task.push(userTask);
if (context.history().length) {
task.push("### Context history");
task.push(context.history().map((h) => `- ${h.type}: ${h.description}`).join("\n"));
task.push("");
}
task.push("### Page snapshot");
task.push(snapshot);
task.push("");
const { error, usage } = await loop.run(task.join("\n"), { signal: progress.signal });
context.consumeTokens(usage.input + usage.output);
if (context.agentParams.apiCacheFile) {
const apiCacheAfter = { ...apiCacheBefore, ...loop.cache() };
const sortedCache = Object.fromEntries(Object.entries(apiCacheAfter).sort(([a], [b]) => a.localeCompare(b)));
const apiCacheTextAfter = JSON.stringify(sortedCache, void 0, 2);
if (apiCacheTextAfter !== apiCacheTextBefore) {
await import_fs.default.promises.mkdir(import_path.default.dirname(context.agentParams.apiCacheFile), { recursive: true });
await import_fs.default.promises.writeFile(context.agentParams.apiCacheFile, apiCacheTextAfter);
}
}
if (refusedToPerformReason())
throw new Error(`Agent refused to perform action: ${refusedToPerformReason()}`);
if (error)
throw new Error(`Agentic loop failed: ${error}`);
return { result: reportedResult ? reportedResult() : void 0 };
}
async function cachedPerform(progress, context, cacheKey) {
if (!context.agentParams?.cacheFile)
return;
const cache = await cachedActions(context.agentParams?.cacheFile);
const entry = cache.actions[cacheKey];
if (!entry)
return;
for (const action of entry.actions)
await (0, import_actionRunner.runAction)(progress, "run", context.page, action, context.agentParams.secrets ?? []);
return entry.actions;
}
async function updateCache(context, cacheKey) {
const cacheFile = context.agentParams?.cacheFile;
const cacheOutFile = context.agentParams?.cacheOutFile;
const cacheFileKey = cacheFile ?? cacheOutFile;
const cache = cacheFileKey ? await cachedActions(cacheFileKey) : { actions: {}, newActions: {} };
const newEntry = { actions: context.actions() };
cache.actions[cacheKey] = newEntry;
cache.newActions[cacheKey] = newEntry;
if (cacheOutFile) {
const entries = Object.entries(cache.newActions);
entries.sort((e1, e2) => e1[0].localeCompare(e2[0]));
await import_fs.default.promises.writeFile(cacheOutFile, JSON.stringify(Object.fromEntries(entries), void 0, 2));
} else if (cacheFile) {
const entries = Object.entries(cache.actions);
entries.sort((e1, e2) => e1[0].localeCompare(e2[0]));
await import_fs.default.promises.writeFile(cacheFile, JSON.stringify(Object.fromEntries(entries), void 0, 2));
}
}
const allCaches = /* @__PURE__ */ new Map();
async function cachedActions(cacheFile) {
let cache = allCaches.get(cacheFile);
if (!cache) {
const content = await import_fs.default.promises.readFile(cacheFile, "utf-8").catch(() => "");
let json;
try {
json = JSON.parse(content.trim() || "{}");
} catch (error) {
throw new Error(`Failed to parse cache file ${cacheFile}:
${error.message}`);
}
const parsed = actions.cachedActionsSchema.safeParse(json);
if (parsed.error)
throw new Error(`Failed to parse cache file ${cacheFile}:
${import_mcpBundle.z.prettifyError(parsed.error)}`);
cache = { actions: parsed.data, newActions: {} };
allCaches.set(cacheFile, cache);
}
return cache;
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
pageAgentExpect,
pageAgentExtract,
pageAgentPerform
});

View File

@@ -0,0 +1,262 @@
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var performTools_exports = {};
__export(performTools_exports, {
default: () => performTools_default
});
module.exports = __toCommonJS(performTools_exports);
var import_mcpBundle = require("../../mcpBundle");
var import_tool = require("./tool");
const navigateSchema = import_mcpBundle.z.object({
url: import_mcpBundle.z.string().describe("URL to navigate to")
});
const navigate = (0, import_tool.defineTool)({
schema: {
name: "browser_navigate",
title: "Navigate to URL",
description: "Navigate to a URL",
inputSchema: navigateSchema
},
handle: async (progress, context, params) => {
return await context.runActionNoWait(progress, {
method: "navigate",
url: params.url
});
}
});
const snapshot = (0, import_tool.defineTool)({
schema: {
name: "browser_snapshot",
title: "Page snapshot",
description: "Capture accessibility snapshot of the current page, this is better than screenshot",
inputSchema: import_mcpBundle.z.object({})
},
handle: async (progress, context, params) => {
return await context.snapshotResult(progress);
}
});
const elementSchema = import_mcpBundle.z.object({
element: import_mcpBundle.z.string().describe("Human-readable element description used to obtain permission to interact with the element"),
ref: import_mcpBundle.z.string().describe("Exact target element reference from the page snapshot")
});
const clickSchema = elementSchema.extend({
doubleClick: import_mcpBundle.z.boolean().optional().describe("Whether to perform a double click instead of a single click"),
button: import_mcpBundle.z.enum(["left", "right", "middle"]).optional().describe("Button to click, defaults to left"),
modifiers: import_mcpBundle.z.array(import_mcpBundle.z.enum(["Alt", "Control", "ControlOrMeta", "Meta", "Shift"])).optional().describe("Modifier keys to press")
});
const click = (0, import_tool.defineTool)({
schema: {
name: "browser_click",
title: "Click",
description: "Perform click on a web page",
inputSchema: clickSchema
},
handle: async (progress, context, params) => {
const [selector] = await context.refSelectors(progress, [params]);
return await context.runActionAndWait(progress, {
method: "click",
selector,
button: params.button,
modifiers: params.modifiers,
clickCount: params.doubleClick ? 2 : void 0
});
}
});
const drag = (0, import_tool.defineTool)({
schema: {
name: "browser_drag",
title: "Drag mouse",
description: "Perform drag and drop between two elements",
inputSchema: import_mcpBundle.z.object({
startElement: import_mcpBundle.z.string().describe("Human-readable source element description used to obtain the permission to interact with the element"),
startRef: import_mcpBundle.z.string().describe("Exact source element reference from the page snapshot"),
endElement: import_mcpBundle.z.string().describe("Human-readable target element description used to obtain the permission to interact with the element"),
endRef: import_mcpBundle.z.string().describe("Exact target element reference from the page snapshot")
})
},
handle: async (progress, context, params) => {
const [sourceSelector, targetSelector] = await context.refSelectors(progress, [
{ ref: params.startRef, element: params.startElement },
{ ref: params.endRef, element: params.endElement }
]);
return await context.runActionAndWait(progress, {
method: "drag",
sourceSelector,
targetSelector
});
}
});
const hoverSchema = elementSchema.extend({
modifiers: import_mcpBundle.z.array(import_mcpBundle.z.enum(["Alt", "Control", "ControlOrMeta", "Meta", "Shift"])).optional().describe("Modifier keys to press")
});
const hover = (0, import_tool.defineTool)({
schema: {
name: "browser_hover",
title: "Hover mouse",
description: "Hover over element on page",
inputSchema: hoverSchema
},
handle: async (progress, context, params) => {
const [selector] = await context.refSelectors(progress, [params]);
return await context.runActionAndWait(progress, {
method: "hover",
selector,
modifiers: params.modifiers
});
}
});
const selectOptionSchema = elementSchema.extend({
values: import_mcpBundle.z.array(import_mcpBundle.z.string()).describe("Array of values to select in the dropdown. This can be a single value or multiple values.")
});
const selectOption = (0, import_tool.defineTool)({
schema: {
name: "browser_select_option",
title: "Select option",
description: "Select an option in a dropdown",
inputSchema: selectOptionSchema
},
handle: async (progress, context, params) => {
const [selector] = await context.refSelectors(progress, [params]);
return await context.runActionAndWait(progress, {
method: "selectOption",
selector,
labels: params.values
});
}
});
const pressKey = (0, import_tool.defineTool)({
schema: {
name: "browser_press_key",
title: "Press a key",
description: "Press a key on the keyboard",
inputSchema: import_mcpBundle.z.object({
key: import_mcpBundle.z.string().describe("Name of the key to press or a character to generate, such as `ArrowLeft` or `a`"),
modifiers: import_mcpBundle.z.array(import_mcpBundle.z.enum(["Alt", "Control", "ControlOrMeta", "Meta", "Shift"])).optional().describe("Modifier keys to press")
})
},
handle: async (progress, context, params) => {
return await context.runActionAndWait(progress, {
method: "pressKey",
key: params.modifiers ? [...params.modifiers, params.key].join("+") : params.key
});
}
});
const typeSchema = elementSchema.extend({
text: import_mcpBundle.z.string().describe("Text to type into the element"),
submit: import_mcpBundle.z.boolean().optional().describe("Whether to submit entered text (press Enter after)"),
slowly: import_mcpBundle.z.boolean().optional().describe("Whether to type one character at a time. Useful for triggering key handlers in the page. By default entire text is filled in at once.")
});
const type = (0, import_tool.defineTool)({
schema: {
name: "browser_type",
title: "Type text",
description: "Type text into editable element",
inputSchema: typeSchema
},
handle: async (progress, context, params) => {
const [selector] = await context.refSelectors(progress, [params]);
if (params.slowly) {
return await context.runActionAndWait(progress, {
method: "pressSequentially",
selector,
text: params.text,
submit: params.submit
});
} else {
return await context.runActionAndWait(progress, {
method: "fill",
selector,
text: params.text,
submit: params.submit
});
}
}
});
const fillForm = (0, import_tool.defineTool)({
schema: {
name: "browser_fill_form",
title: "Fill form",
description: "Fill multiple form fields. Always use this tool when you can fill more than one field at a time.",
inputSchema: import_mcpBundle.z.object({
fields: import_mcpBundle.z.array(import_mcpBundle.z.object({
name: import_mcpBundle.z.string().describe("Human-readable field name"),
type: import_mcpBundle.z.enum(["textbox", "checkbox", "radio", "combobox", "slider"]).describe("Type of the field"),
ref: import_mcpBundle.z.string().describe("Exact target field reference from the page snapshot"),
value: import_mcpBundle.z.string().describe("Value to fill in the field. If the field is a checkbox, the value should be `true` or `false`. If the field is a combobox, the value should be the text of the option.")
})).describe("Fields to fill in")
})
},
handle: async (progress, context, params) => {
const actions = [];
for (const field of params.fields) {
const [selector] = await context.refSelectors(progress, [{ ref: field.ref, element: field.name }]);
if (field.type === "textbox" || field.type === "slider") {
actions.push({
method: "fill",
selector,
text: field.value
});
} else if (field.type === "checkbox" || field.type === "radio") {
actions.push({
method: "setChecked",
selector,
checked: field.value === "true"
});
} else if (field.type === "combobox") {
actions.push({
method: "selectOption",
selector,
labels: [field.value]
});
}
}
return await context.runActionsAndWait(progress, actions);
}
});
const setCheckedSchema = elementSchema.extend({
checked: import_mcpBundle.z.boolean().describe("Whether to check the checkbox")
});
const setChecked = (0, import_tool.defineTool)({
schema: {
name: "browser_set_checked",
title: "Set checked",
description: "Set the checked state of a checkbox",
inputSchema: setCheckedSchema
},
handle: async (progress, context, params) => {
const [selector] = await context.refSelectors(progress, [params]);
return await context.runActionAndWait(progress, {
method: "setChecked",
selector,
checked: params.checked
});
}
});
var performTools_default = [
navigate,
snapshot,
click,
drag,
hover,
selectOption,
pressKey,
type,
fillForm,
setChecked
];

109
node_modules/playwright-core/lib/server/agent/tool.js generated vendored Normal file
View File

@@ -0,0 +1,109 @@
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var tool_exports = {};
__export(tool_exports, {
defineTool: () => defineTool,
toolsForLoop: () => toolsForLoop
});
module.exports = __toCommonJS(tool_exports);
var import_mcpBundle = require("../../mcpBundle");
var import_stringUtils = require("../../utils/isomorphic/stringUtils");
function defineTool(tool) {
return tool;
}
function toolsForLoop(progress, context, toolDefinitions, options = {}) {
const tools = toolDefinitions.map((tool) => {
const result = {
name: tool.schema.name,
description: tool.schema.description,
inputSchema: import_mcpBundle.z.toJSONSchema(tool.schema.inputSchema)
};
return result;
});
if (options.resultSchema) {
tools.push({
name: "report_result",
description: "Report the result of the task.",
inputSchema: options.resultSchema
});
}
if (options.refuseToPerform === "allow") {
tools.push({
name: "refuse_to_perform",
description: "Refuse to perform action.",
inputSchema: {
type: "object",
properties: {
reason: {
type: "string",
description: `Call this when you believe that you can't perform the action because something is wrong with the page. The reason will be reported to the user.`
}
},
required: ["reason"]
}
});
}
let reportedResult;
let refusedToPerformReason;
const callTool = async (params) => {
if (params.name === "report_result") {
reportedResult = params.arguments;
return {
content: [{ type: "text", text: "Done" }],
isError: false
};
}
if (params.name === "refuse_to_perform") {
refusedToPerformReason = params.arguments.reason;
return {
content: [{ type: "text", text: "Done" }],
isError: false
};
}
const tool = toolDefinitions.find((t) => t.schema.name === params.name);
if (!tool) {
return {
content: [{
type: "text",
text: `Tool ${params.name} not found. Available tools: ${toolDefinitions.map((t) => t.schema.name)}`
}],
isError: true
};
}
try {
return await tool.handle(progress, context, params.arguments);
} catch (error) {
return {
content: [{ type: "text", text: (0, import_stringUtils.stripAnsiEscapes)(error.message) }],
isError: true
};
}
};
return {
tools,
callTool,
reportedResult: options.resultSchema ? () => reportedResult : void 0,
refusedToPerformReason: () => refusedToPerformReason
};
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
defineTool,
toolsForLoop
});