@hyperbrowser/agent
Version:
Hyperbrowsers Web Agent
293 lines (292 loc) • 12.9 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
require("dotenv/config");
const node_fs_1 = __importDefault(require("node:fs"));
const commander_1 = require("commander");
const inquirer = __importStar(require("@inquirer/prompts"));
const ora_1 = __importDefault(require("ora"));
const boxen_1 = __importDefault(require("boxen"));
const chalk_1 = __importDefault(require("chalk"));
const readline_1 = __importDefault(require("readline"));
const agent_1 = require("../agent");
const custom_actions_1 = require("../custom-actions");
const types_1 = require("../types");
const error_1 = require("../agent/error");
const program = new commander_1.Command();
let currentSpinner = (0, ora_1.default)();
program
.name("hyperbrowser")
.description("CLI for Hyperbrowser - A powerful browser automation tool")
.version("1.0.2");
program
.command("run", { isDefault: true })
.description("Run the interactive CLI")
.option("-d, --debug", "Enable debug mode")
.option("-c, --command <task description>", "Command to run")
.option("-f, --file <file path>", "Path to a file containing a command")
.option("-m, --mcp <mcp config file>", "Path to a file containing mcp config")
.option("--hyperbrowser", "Use Hyperbrowser for the browser provider")
.action(async function () {
const options = this.opts();
const debug = options.debug || false;
const useHB = options.hyperbrowser || false;
let taskDescription = options.command || undefined;
const filePath = options.file || undefined;
const mcpPath = options.mcp || undefined;
console.log(chalk_1.default.blue("HyperAgent CLI"));
currentSpinner.info(`Pause using ${chalk_1.default.bold("ctrl + p")} and resume using ${chalk_1.default.bold("ctrl + r")}\n`);
try {
// Check for API key if using Hyperbrowser
if (useHB && !process.env.HYPERBROWSER_API_KEY) {
const apiKey = await inquirer.password({
message: "Hyperbrowser API key not found in environment variables. Please enter it here:",
mask: "*",
});
if (!apiKey) {
console.log(chalk_1.default.yellow("Hyperbrowser API key is required. Exiting."));
process.exit(0);
}
process.env.HYPERBROWSER_API_KEY = apiKey; // Set it for the current process
}
const agent = new agent_1.HyperAgent({
debug: debug,
browserProvider: useHB ? "Hyperbrowser" : "Local",
customActions: [
(0, custom_actions_1.UserInteractionAction)(async ({ message, kind, choices }) => {
const currentText = currentSpinner.text;
try {
currentSpinner.stop();
currentSpinner.clear();
if (kind === "text_input") {
const response = await inquirer.input({
message,
required: true,
});
return {
success: true,
message: `User responded with the text: "${response}"`,
};
}
else if (kind === "confirm") {
const response = await inquirer.confirm({
message,
});
return {
success: true,
message: `User responded with "${response}"`,
};
}
else if (kind === "password") {
console.warn(chalk_1.default.red("Providing passwords to LLMs can be dangerous. Passwords are passed in plain-text to the LLM and can be read by other people."));
const response = await inquirer.password({
message,
});
return {
success: true,
message: `User responded with password: ${response}`,
};
}
else {
if (!choices || choices.length === 0) {
return {
success: false,
message: "For 'select' kind of user interaction, an array of choices is required.",
};
}
else {
const response = await inquirer.select({
message,
choices: choices.map((option) => ({
value: option,
name: option,
})),
});
return {
success: true,
message: `User selected the choice: ${response}`,
};
}
}
}
finally {
currentSpinner.start(currentText);
}
}),
],
});
let task;
readline_1.default.emitKeypressEvents(process.stdin);
process.stdin.on("keypress", async (ch, key) => {
if (key && key.ctrl && key.name == "p") {
if (currentSpinner.isSpinning) {
currentSpinner.stopAndPersist({ symbol: "⏸" });
}
currentSpinner.start(chalk_1.default.blue("Hyperagent will pause after completing this operation. Press Ctrl+r again to resume."));
currentSpinner.stopAndPersist({ symbol: "⏸" });
currentSpinner = (0, ora_1.default)();
if (task.getStatus() == types_1.TaskStatus.RUNNING) {
task.pause();
}
}
else if (key && key.ctrl && key.name == "r") {
if (task.getStatus() == types_1.TaskStatus.PAUSED) {
currentSpinner.start(chalk_1.default.blue("Hyperagent will resume"));
currentSpinner.stopAndPersist({ symbol: "⏵" });
currentSpinner = (0, ora_1.default)();
task.resume();
}
}
else if (key && key.ctrl && key.name == "c") {
if (currentSpinner.isSpinning) {
currentSpinner.stopAndPersist();
}
console.log("\nShutting down HyperAgent");
try {
await agent.closeAgent();
process.exit(0);
}
catch (err) {
console.error("Error during shutdown:", err);
process.exit(1);
}
}
});
process.stdin.setRawMode(true);
const onStep = (params) => {
const action = params.agentOutput.action;
const output = params.actionOutput;
const actionDisplay = output.success
? ` └── [${chalk_1.default.yellow(action.type)}] ${agent.pprintAction(action)}`
: ` └── [${chalk_1.default.red(action.type)}] ${chalk_1.default.red(output.message)}`;
currentSpinner.succeed(`[${chalk_1.default.yellow("step")}]: ${params.agentOutput.thoughts}\n${actionDisplay}`);
currentSpinner = (0, ora_1.default)();
process.stdin.setRawMode(true);
process.stdin.resume();
};
const debugAgentOutput = (params) => {
const action = params.action;
const actionDisplay = ` └── [${chalk_1.default.yellow(action.type)}] ${agent.pprintAction(action)}`;
currentSpinner.start(`[${chalk_1.default.yellow("planning")}]: ${params.thoughts}\n${actionDisplay}`);
process.stdin.setRawMode(true);
process.stdin.resume();
};
const onComplete = async (params) => {
console.log((0, boxen_1.default)(params.output || "No Response", {
title: chalk_1.default.yellow("HyperAgent Response"),
titleAlignment: "center",
float: "center",
padding: 1,
margin: { top: 2, left: 0, right: 0, bottom: 0 },
}));
console.log("\n");
const continueTask = await inquirer.select({
message: "Would you like to continue ",
choices: [
{ name: "Yes", value: true },
{ name: "No", value: false },
],
});
if (continueTask) {
const taskDescription = await inquirer.input({
message: "What should HyperAgent do next for you?",
required: true,
});
process.stdin.setRawMode(true);
process.stdin.resume();
task = await agent.executeTaskAsync(taskDescription, {
onStep: onStep,
debugOnAgentOutput: debugAgentOutput,
onComplete: onComplete,
});
task.emitter.addListener("error", (error) => {
task.cancel();
throw error;
});
}
else {
process.exit(0);
}
};
if (!taskDescription) {
if (filePath) {
taskDescription = (await node_fs_1.default.promises.readFile(filePath)).toString();
}
else {
taskDescription = await inquirer.input({
message: "What should HyperAgent do for you today?",
required: true,
});
}
}
if (mcpPath) {
const mcpConfig = JSON.parse((await node_fs_1.default.promises.readFile(mcpPath)).toString());
await agent.initializeMCPClient({ servers: mcpConfig });
}
if (useHB && !debug) {
await agent.initBrowser();
const session = agent.getSession();
console.log(`Hyperbrowser Live URL: ${session.liveUrl}\n`);
}
task = await agent.executeTaskAsync(taskDescription, {
onStep: onStep,
onComplete: onComplete,
debugOnAgentOutput: debugAgentOutput,
});
task.emitter.addListener("error", (error) => {
task.cancel();
throw error;
});
}
catch (err) {
if (err instanceof error_1.HyperagentError || err instanceof Error) {
console.log(chalk_1.default.red(err.message));
if (debug) {
console.trace(err);
}
}
else {
console.log(chalk_1.default.red(err));
if (debug) {
console.trace(err);
}
}
}
});
program.parse();