UNPKG

donobu

Version:

Create browser automations with an LLM agent and replay them as Playwright scripts.

138 lines 5.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.InputFakerTool = exports.InputFakerGptSchema = exports.InputFakerNonGptSchema = exports.InputFakerCoreSchema = exports.FAKER_DATA_TYPES = void 0; const faker_1 = require("@faker-js/faker"); const v4_1 = require("zod/v4"); const MiscUtils_1 = require("../utils/MiscUtils"); const TargetUtils_1 = require("../utils/TargetUtils"); const ReplayableInteraction_1 = require("./ReplayableInteraction"); exports.FAKER_DATA_TYPES = [ // Person 'person.fullName', 'person.firstName', 'person.lastName', 'person.jobTitle', 'person.jobArea', // Internet 'internet.email', 'internet.username', 'internet.password', 'internet.url', 'internet.domainName', 'internet.ipv4', // Phone 'phone.number', // Location 'location.streetAddress', 'location.city', 'location.state', 'location.country', 'location.zipCode', // Company 'company.name', 'company.catchPhrase', // Finance 'finance.accountNumber', 'finance.creditCardNumber', 'finance.currencyCode', // Date 'date.birthdate', 'date.past', 'date.future', // Lorem 'lorem.word', 'lorem.sentence', 'lorem.paragraph', // Number / string 'number.int', 'string.uuid', 'string.alphanumeric', 'color.human', ]; exports.InputFakerCoreSchema = v4_1.z.object({ dataType: v4_1.z .enum(exports.FAKER_DATA_TYPES) .describe('The type of realistic data to generate and input. Each value maps to a Faker.js data category.'), append: v4_1.z .boolean() .optional() .describe('If true, append the generated value to the existing contents of the input, rather than clearing it first. Defaults to false.'), finalizeWithSubmit: v4_1.z .boolean() .optional() .describe("Attempt to submit the data after inputting the generated value (i.e. hitting 'Enter' at the end). " + "This can be useful if doing something like using a webpage's search box, etc."), }); exports.InputFakerNonGptSchema = v4_1.z.object({ ...ReplayableInteraction_1.SelectorBasedSchema.shape, ...exports.InputFakerCoreSchema.shape, }); exports.InputFakerGptSchema = v4_1.z.object({ ...ReplayableInteraction_1.AnnotationBasedSchema.shape, ...exports.InputFakerCoreSchema.shape, }); class InputFakerTool extends ReplayableInteraction_1.ReplayableInteraction { constructor() { super(InputFakerTool.NAME, "Input a randomly generated, realistic value into a webpage's text input box. " + 'The generated value is drawn from a real-world data category (e.g. a person name, email address, ' + 'street address, company name, etc.) and will look plausible to a human. ' + 'A new value is generated on every invocation.', exports.InputFakerCoreSchema, exports.InputFakerNonGptSchema, exports.InputFakerGptSchema); } async invoke(context, parameters, handles) { const element = handles.target; const text = InputFakerTool.generate(parameters.dataType); if (!parameters.append) { await this.clearField(element); } // Focus the element, then type via the page keyboard rather than holding // a reference to a specific DOM node. This survives mid-sequence DOM // replacement: if a reactive widget (e.g. Wikipedia's CDX search) swaps // the <input> on the first keydown, the replacement receives focus and // subsequent keystrokes are delivered there automatically. await element.focus(); const page = (0, TargetUtils_1.webPage)(context); await context.interactionVisualizer.pointAt(page, element); for (const char of text) { await page.keyboard.press(char, { delay: MiscUtils_1.MiscUtils.generateHumanLikeKeyPressDurationInMs(char), }); } if (parameters.finalizeWithSubmit) { const enterKey = 'Enter'; await page.keyboard.press(enterKey, { delay: MiscUtils_1.MiscUtils.generateHumanLikeKeyPressDurationInMs(enterKey), }); } return `Inputted generated value '${text}' into: `; } /** * Generates a value for the given data type using Faker.js. * Exported as a static method so the Playwright helper and code generator * can call it directly without instantiating the tool. */ static generate(dataType) { const [module, method] = dataType.split('.'); const value = faker_1.faker[module][method](); return String(value instanceof Date ? value.toISOString().slice(0, 10) : value); } async clearField(element) { try { const value = await element.inputValue(); if (value !== '') { await element.selectText({ timeout: 3000 }); const backspaceKey = 'Backspace'; await element.press(backspaceKey, { delay: MiscUtils_1.MiscUtils.generateHumanLikeKeyPressDurationInMs(backspaceKey), timeout: 3000, }); } } catch (_e) { // This can happen if the element is not a text element, but still accepts text inputs. // Pass. } } } exports.InputFakerTool = InputFakerTool; InputFakerTool.NAME = 'inputFaker'; //# sourceMappingURL=InputFakerTool.js.map