npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

x360airuntest

v0.0.9

Published

X360AIRunTest Web Agent

Readme

Overview

X360AIAgent is Playwright supercharged with AI. No more brittle scripts, just powerful natural language commands. Just looking for scalable headless browsers or scraping infra? Go to X360AICloudRunner to get started for free!

Features

  • 🤖 AI Commands: Simple APIs like page.ai(), page.extract() and executeTask() for any AI automation
  • Fallback to Regular Playwright: Use regular Playwright when AI isn't needed
  • 🥷 Stealth Mode – Avoid detection with built-in anti-bot patches
  • ☁️ Cloud Ready – Instantly scale to hundreds of sessions via X360AICloudRunner
  • 🔌 MCP Client – Connect to tools like Composio for full workflows (e.g. writing web data to Google Sheets)

Quick Start

Installation

# Using npm
npm install x360airuntest

# Using yarn
yarn add x360airuntest

CLI

$ npx x360airuntest -c "Find a route from Miami to New Orleans, and provide the detailed route information."

The CLI supports options for debugging or using X360AICloudRunner instead of a local browser

-d, --debug                       Enable debug mode
-c, --command <task description>  Command to run
--X360AICloudRunner                    Use X360AICloudRunner for the browser provider

Library

import { X360AIAgent } from "x360airuntest";
import { z } from "zod";

// Initialize the agent
const agent = new X360AIAgent({
  llm: {
    provider: "openai",
    model: "gpt-4o",
  },
});

// Execute a task
const result = await agent.executeTask(
  "Navigate to amazon.com, search for 'laptop', and extract the prices of the first 5 results"
);
console.log(result.output);

// Use page.ai and page.extract
const page = await agent.newPage();
await page.goto("https://flights.google.com", { waitUntil: "load" });
await page.ai("search for flights from Rio to LAX from July 16 to July 22");
const res = await page.extract(
  "give me the flight options",
  z.object({
    flights: z.array(
      z.object({
        price: z.number(),
        departure: z.string(),
        arrival: z.string(),
      })
    ),
  })
);
console.log(res);

// Clean up
await agent.closeAgent();

Two Modes of Operation

X360AIAgent provides two complementary APIs optimized for different use cases:

🎯 page.aiAction() - Single Granular Actions

Best for: Single, specific actions like "click login", "fill email with [email protected]"

Advantages:

  • Fast - Uses accessibility tree (no screenshots)
  • 💰 Cheap - Single LLM call per action
  • 🎯 Reliable - Direct element finding and execution
  • 📊 Efficient - Text-based DOM analysis with automatic ad-frame filtering

Example:

const page = await agent.newPage();
await page.goto("https://example.com/login");

// Fast, reliable single actions
await page.aiAction("fill email with [email protected]");
await page.aiAction("fill password with mypassword");
await page.aiAction("click the login button");

🧠 page.ai() - Complex Multi-Step Tasks

Best for: Complex workflows requiring multiple steps and visual context

Advantages:

  • 🖼️ Visual Understanding - Can use screenshots with element overlays
  • 🎭 Complex Tasks - Handles multi-step workflows automatically
  • 🧠 Context-Aware - Better at understanding page layout and relationships
  • 🔄 Adaptive - Can adjust strategy based on page state

Parameters:

  • useDomCache (boolean): Reuse DOM snapshots for speed
  • enableVisualMode (boolean): Enable screenshots and overlays (default: false)

Example:

const page = await agent.newPage();
await page.goto("https://flights.google.com");

// Complex task with multiple steps handled automatically
await page.ai("search for flights from Miami to New Orleans on July 16", {
  useDomCache: true,
});

🎨 Mix and Match

Combine both APIs for optimal performance:

// Use aiAction for fast, reliable individual actions
await page.aiAction("click the search button");
await page.aiAction("type laptop into search");

// Use ai() for complex, multi-step workflows
await page.ai("filter results by price under $1000 and sort by rating");

// Extract structured data
const products = await page.extract(
  "get the top 5 products",
  z.object({
    products: z.array(z.object({ name: z.string(), price: z.number() }))
  })
);

☁️ Cloud

You can scale X360AIAgent with cloud headless browsers using X360AICloudRunner

  1. Get a free api key from X360AICloudRunner
  2. Add it to your env as X360AICloudRunner_API_KEY
  3. Set your browserProvider to "X360AICloudRunner"
const agent = new X360AIAgent({
  browserProvider: "X360AICloudRunner",
});

const response = await agent.executeTask(
  "Go to hackernews, and list me the 5 most recent article titles"
);

console.log(response);
await agent.closeAgent();

Usage Guide

Multi-Page Management

// Create and manage multiple pages
const page1 = await agent.newPage();
const page2 = await agent.newPage();

// Execute tasks on specific pages
const page1Response = await page1.ai(
  "Go to google.com/travel/explore and set the starting location to New York. Then, return to me the first recommended destination that shows up. Return to me only the name of the location."
);
const page2Response = await page2.ai(
  `I want to plan a trip to ${page1Response.output}. Recommend me places to visit there.`
);

console.log(page2Response.output);

// Get all active pages
const pages = await agent.getPages();
await agent.closeAgent();

Customization

Output Schema Definition

X360AIAgent can extract data in a specified schema. The schema can be passed in at a per-task level

import { z } from "zod";

const agent = new X360AIAgent();
const agentResponse = await agent.executeTask(
  "Navigate to imdb.com, search for 'The Matrix', and extract the director, release year, and rating",
  {
    outputSchema: z.object({
      director: z.string().describe("The name of the movie director"),
      releaseYear: z.number().describe("The year the movie was released"),
      rating: z.string().describe("The IMDb rating of the movie"),
    }),
  }
);
console.log(agentResponse.output);
await agent.closeAgent();
{
  "director": "Lana Wachowski, Lilly Wachowski",
  "releaseYear": 1999,
  "rating": "8.7/10"
}

Using Different LLM Providers

X360AIAgent supports multiple LLM providers with native SDKs for better performance and reliability.

// Using OpenAI
const agent = new X360AIAgent({
  llm: {
    provider: "openai",
    model: "gpt-4o",
  },
});

// Using Anthropic's Claude
const agent = new X360AIAgent({
  llm: {
    provider: "anthropic",
    model: "claude-3-7-sonnet-latest",
  },
});

    // Using Google Gemini
    const agent = new X360AIAgent({
      llm: {
        provider: "gemini",
        model: "gemini-2.5-pro-preview-03-25",
      },
    });

    // Using DeepSeek
    const agent = new X360AIAgent({
      llm: {
        provider: "deepseek",
        model: "deepseek-chat",
      },
    });

MCP Support

X360AIAgent functions as a fully functional MCP client. For best results, we recommend using gpt-4o as your LLM.

Here is an example which reads from wikipedia, and inserts information into a google sheet using the composio Google Sheet MCP. For the full example, see here

const agent = new X360AIAgent({
  llm: llm,
  debug: true,
});

await agent.initializeMCPClient({
  servers: [
    {
      command: "npx",
      args: [
        "@composio/mcp@latest",
        "start",
        "--url",
        "https://mcp.composio.dev/googlesheets/...",
      ],
      env: {
        npm_config_yes: "true",
      },
    },
  ],
});

const response = await agent.executeTask(
  "Go to https://en.wikipedia.org/wiki/List_of_U.S._states_and_territories_by_population and get the data on the top 5 most populous states from the table. Then insert that data into a google sheet. You may need to first check if there is an active connection to google sheet, and if there isn't connect to it and present me with the link to sign in. "
);

console.log(response);
await agent.closeAgent();

Custom Actions

X360AIAgent's capabilities can be extended with custom actions. Custom actions require 3 things:

  • type: Name of the action. Should be something descriptive about the action.
  • actionParams: A zod object describing the parameters that the action may consume.
  • run: A function that takes in a context, and the params for the action and produces a result based on the params.

Here is an example that performs a search using Exa

const exaInstance = new Exa(process.env.EXA_API_KEY);

export const RunSearchActionDefinition: AgentActionDefinition = {
  type: "perform_search",
  actionParams: z.object({
    search: z
      .string()
      .describe(
        "The search query for something you want to search about. Keep the search query concise and to-the-point."
      ),
  }).describe("Search and return the results for a given query.");,
  run: async function (
    ctx: ActionContext,
    params: z.infer<typeof searchSchema>
  ): Promise<ActionOutput> {
    const results = (await exaInstance.search(params.search, {})).results
      .map(
        (res) =>
          `title: ${res.title} || url: ${res.url} || relevance: ${res.score}`
      )
      .join("\n");

    return {
      success: true,
      message: `Succesfully performed search for query ${params.search}. Got results: \n${results}`,
    };
  },
};

const agent = new X360AIAgent({
  "Search about the news for today in New York",
  customActions: [RunSearchActionDefinition],
});

CDP First

X360AIAgent speaks Chrome DevTools Protocol natively. Element lookup, scrolling, typing, frame management, and screenshots all go through CDP so every action has exact coordinates, execution contexts, and browser events. This allows for more custom commands and deep iframe tracking.

X360AIAgent integrates seamlessly with Playwright, so you can still use familiar commands, while the actions take full advantage of native CDP protocol with fast locators and advanced iframe tracking.

Key Features:

  • Auto-Ad Filtering: Automatically filters out ad and tracking iframes to keep context clean
  • Deep Iframe Support: Tracking across nested and cross-origin iframes (OOPIFs)
  • Exact Coordinates: Actions use precise CDP coordinates for reliability

Keep in mind that CDP is still experimental, and stability is not guaranteed. If you’d like the agent to use Playwright’s native locators/actions instead, set cdpActions: false when you create the agent and it will fall back automatically.

The CDP layer is still evolving—expect rapid polish (and the occasional sharp edge). If you hit something quirky you can toggle CDP off for that workflow and drop us a bug report.

Contributing

We welcome contributions to X360AIAgent! Here's how you can help:

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

Support