donobu
Version:
Create browser automations with an LLM agent and replay them as Playwright scripts.
127 lines • 5.99 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.RememberPageTextTool = exports.RememberPageTextToolGptSchema = exports.RememberPageTextNonGptSchema = void 0;
const v4_1 = require("zod/v4");
const ElementSelector_1 = require("../models/ElementSelector");
const ToolSchema_1 = require("../models/ToolSchema");
const Logger_1 = require("../utils/Logger");
const PlaywrightUtils_1 = require("../utils/PlaywrightUtils");
const TargetUtils_1 = require("../utils/TargetUtils");
const ReplayableInteraction_1 = require("./ReplayableInteraction");
const Tool_1 = require("./Tool");
exports.RememberPageTextNonGptSchema = v4_1.z.object({
name: v4_1.z.string(),
selector: ElementSelector_1.ElementSelectorSchema,
});
exports.RememberPageTextToolGptSchema = v4_1.z.object({
...ToolSchema_1.BaseGptArgsSchema.shape,
name: v4_1.z
.string()
.describe('The name for the text to save to the flow env data. The name should be in UPPER_SNAKE_CASE, like you would name an environment variable.'),
text: v4_1.z.string().describe('The raw text to save to the flow env data.'),
});
/**
* Persists text from the current page into the flow env data so subsequent tools can reference it.
* - `call` is driven by an explicit selector to extract text from the page.
* - `callFromGpt` is driven by provided text and attempts to infer selectors for replayability.
*/
class RememberPageTextTool extends Tool_1.Tool {
constructor() {
super(RememberPageTextTool.NAME, `Update the flow env data to remember text from the current webpage.`, exports.RememberPageTextNonGptSchema, exports.RememberPageTextToolGptSchema, false, undefined, ['web']);
}
async call(context, parameters) {
const page = (0, TargetUtils_1.webPage)(context);
let labelData = null;
const locators = await ReplayableInteraction_1.ReplayableInteraction.getLocatorsOrderedByMatchCount(page, parameters.selector);
for (const selectorLocator of locators) {
let count = 0;
try {
count = await selectorLocator.locator.count();
}
catch (locatorError) {
Logger_1.appLogger.error(`Failed to get selector count for '${selectorLocator.selector}'`, locatorError);
}
for (let i = 0; i < count && labelData === null; ++i) {
try {
const originalLocator = selectorLocator.locator.nth(i);
const element = (await ReplayableInteraction_1.ReplayableInteraction.getLocatorOrItsLabel(originalLocator)).first();
const text = await element.textContent();
if (text) {
labelData = {
name: parameters.name,
text: text,
element: parameters.selector.element,
frame: parameters.selector.frame,
};
}
}
catch (elementError) {
Logger_1.appLogger.error(`Failed to extract text for ${selectorLocator.selector}[${i}]`, elementError);
}
}
}
if (!labelData) {
return {
isSuccessful: false,
forLlm: `Unable to extract '${parameters.name}' from the page!`,
metadata: labelData,
};
}
else {
context.envData[parameters.name] = labelData.text;
const ref = `{{$.env.${parameters.name}}}`;
return {
isSuccessful: true,
forLlm: `Saved '${parameters.name}' to the flow context. Reference its value by: ${ref}`,
metadata: labelData,
};
}
}
async callFromGpt(context, parameters) {
const page = (0, TargetUtils_1.webPage)(context);
let elementSelector = null;
for (const frame of page.frames()) {
if (frame.isDetached()) {
continue;
}
let count = 0;
let locator;
try {
locator = frame.getByText(parameters.text);
count = await locator.count();
}
catch (locatorError) {
Logger_1.appLogger.error(`Failed to get locator count for text '${parameters.text}' in frame`, locatorError);
continue;
}
for (let i = 0; i < count && elementSelector === null; ++i) {
try {
const selectorCandidates = await PlaywrightUtils_1.PlaywrightUtils.generateSelectors(locator.nth(i));
const frameSelector = frame.parentFrame() === null
? null
: (await PlaywrightUtils_1.PlaywrightUtils.generateSelectors(await frame.frameElement()))[0];
elementSelector = {
element: selectorCandidates,
frame: frameSelector,
};
}
catch (error) {
Logger_1.appLogger.warn(`Failed to generate selectors for locator ${i + 1} of ${count} for the text '${parameters.text}', will try other locators if possible.`, error);
}
}
}
context.envData[parameters.name] = parameters.text;
if (!elementSelector) {
Logger_1.appLogger.error(`Unable to generate selectors for extracting the text '${parameters.text}'`);
}
const ref = `{{$.env.${parameters.name}}}`;
return {
isSuccessful: true,
forLlm: `Saved '${parameters.name}' to the flow context. Reference its value by: ${ref}`,
metadata: elementSelector,
};
}
}
exports.RememberPageTextTool = RememberPageTextTool;
RememberPageTextTool.NAME = 'rememberPageText';
//# sourceMappingURL=RememberPageTextTool.js.map