Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 117 additions & 0 deletions packages/core/examples/p2p-client-example.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/**
* Example: Connecting to a Remote Stagehand Server
*
* This example demonstrates how to connect to a remote Stagehand server
* and execute commands that run on the remote machine.
*
* Usage:
* 1. First, start the server in another terminal:
* npx tsx examples/p2p-server-example.ts
*
* 2. Then run this client:
* npx tsx examples/p2p-client-example.ts
*/

import { Stagehand } from "../dist/index.js";
import { z } from "zod/v3";

async function main() {
const SERVER_URL = process.env.STAGEHAND_SERVER_URL || "http://localhost:3000";

console.log("Stagehand P2P Client");
console.log("=".repeat(60));
console.log(`Connecting to server at ${SERVER_URL}...`);

// Create a Stagehand instance
const stagehand = new Stagehand({
env: "LOCAL", // Required but won't be used since we're connecting to remote
verbose: 1,
});

// Connect to the remote server and create a session
await stagehand.connectToRemoteServer(SERVER_URL);
console.log("✓ Connected to remote server\n");

// Navigate to a test page first
console.log("=".repeat(60));
console.log("Navigating to example.com");
console.log("=".repeat(60));
try {
// Navigate using the remote API
await stagehand.goto("https://example.com");
console.log("✓ Navigated to example.com\n");
} catch (error: any) {
console.error("✗ Navigation error:", error.message);
}

// All actions now execute on the remote machine
console.log("=".repeat(60));
console.log("Testing act()");
console.log("=".repeat(60));
try {
const actResult = await stagehand.act("scroll to the bottom");
console.log("✓ Act result:", {
success: actResult.success,
message: actResult.message,
actionsCount: actResult.actions.length,
});
} catch (error: any) {
console.error("✗ Act error:", error.message);
}

console.log("\n" + "=".repeat(60));
console.log("Testing extract()");
console.log("=".repeat(60));
try {
const extractResult = await stagehand.extract("extract the page title");
console.log("✓ Extract result:", extractResult);
} catch (error: any) {
console.error("✗ Extract error:", error.message);
}

console.log("\n" + "=".repeat(60));
console.log("Testing observe()");
console.log("=".repeat(60));
try {
const observeResult = await stagehand.observe("find all links on the page");
console.log(
`✓ Observe result: Found ${observeResult.length} actions`
);
if (observeResult.length > 0) {
console.log(" First action:", {
selector: observeResult[0].selector,
description: observeResult[0].description,
});
}
} catch (error: any) {
console.error("✗ Observe error:", error.message);
}

console.log("\n" + "=".repeat(60));
console.log("Testing extract with schema");
console.log("=".repeat(60));
try {
const schema = z.object({
title: z.string(),
heading: z.string().optional(),
});
const structuredData = await stagehand.extract(
"extract the page title and main heading",
schema
);
console.log("✓ Structured data:", structuredData);
} catch (error: any) {
console.error("✗ Structured extract error:", error.message);
}

console.log("\n" + "=".repeat(60));
console.log("All tests completed!");
console.log("=".repeat(60));
console.log("\nNote: The browser is running on the remote server.");
console.log(" All commands were executed via RPC over HTTP/SSE.\n");
}

main().catch((error) => {
console.error("\n❌ Fatal error:", error);
process.exit(1);
});
98 changes: 98 additions & 0 deletions packages/core/examples/p2p-server-example.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/**
* Example: Running Stagehand as a P2P Server
*
* This example demonstrates how to run Stagehand as an HTTP server
* that other Stagehand instances can connect to and execute commands remotely.
*
* Usage:
* npx tsx examples/p2p-server-example.ts
*/

import { Stagehand } from "../dist/index.js";

async function main() {
console.log("Starting Stagehand P2P Server...");

// Check if we should use BROWSERBASE or LOCAL
const useBrowserbase =
process.env.BROWSERBASE_API_KEY && process.env.BROWSERBASE_PROJECT_ID;

// Create a Stagehand instance
const stagehand = new Stagehand(
useBrowserbase
? {
env: "BROWSERBASE",
apiKey: process.env.BROWSERBASE_API_KEY,
projectId: process.env.BROWSERBASE_PROJECT_ID,
verbose: 1,
}
: {
env: "LOCAL",
verbose: 1,
localBrowserLaunchOptions: {
headless: false, // Set to false to see the browser
},
}
);

console.log(
`Initializing browser (${useBrowserbase ? "BROWSERBASE" : "LOCAL"})...`
);
await stagehand.init();
console.log("✓ Browser initialized");

// Create and start the server
console.log("Creating server...");
const server = stagehand.createServer({
port: 3000,
host: "127.0.0.1", // Use localhost for testing
});

await server.listen();
console.log(`✓ Server listening at ${server.getUrl()}`);
console.log(` Active sessions: ${server.getActiveSessionCount()}`);

// Navigate to a starting page
console.log("\nNavigating to google.com...");
const page = await stagehand.context.awaitActivePage();
await page.goto("https://google.com");
console.log("✓ Page loaded");

// The server can also use Stagehand locally while serving remote requests
console.log("\nTesting local execution...");
const result = await stagehand.act("scroll down");
console.log("✓ Local action completed:", result.success ? "success" : "failed");

// Keep the server running
console.log("\n" + "=".repeat(60));
console.log("Server is ready!");
console.log("=".repeat(60));
console.log("\nTo connect from another terminal, run:");
console.log(" npx tsx examples/p2p-client-example.ts");
console.log("\nOr from code:");
console.log(` stagehand.connectToRemoteServer('${server.getUrl()}')`);
console.log("\nPress Ctrl+C to stop the server");
console.log("=".repeat(60));

// Handle graceful shutdown
process.on("SIGINT", async () => {
console.log("\n\nShutting down gracefully...");
try {
await server.close();
await stagehand.close();
console.log("✓ Server closed");
process.exit(0);
} catch (error) {
console.error("Error during shutdown:", error);
process.exit(1);
}
});

// Keep the process alive
await new Promise(() => {});
}

main().catch((error) => {
console.error("\n❌ Fatal error:", error);
process.exit(1);
});
127 changes: 127 additions & 0 deletions packages/core/examples/python-client-example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#!/usr/bin/env python3
"""
Example: Using Stagehand Python SDK with Remote Server

This example demonstrates how to use the Python SDK to connect to a
Stagehand server and execute browser automation tasks.

Usage:
1. First, start the Node.js server in another terminal:
npx tsx examples/p2p-server-example.ts

2. Install the Python dependencies:
pip install httpx httpx-sse

3. Then run this Python client:
python examples/python-client-example.py
"""

import asyncio
import os
from stagehand import Stagehand


async def main():
server_url = os.getenv("STAGEHAND_SERVER_URL", "http://localhost:3000")

print("Stagehand Python Client")
print("=" * 60)
print(f"Connecting to server at {server_url}...")

# Create Stagehand instance
stagehand = Stagehand(
server_url=server_url,
verbose=1,
)

try:
# Connect to the remote server and create a session
await stagehand.init()
print("✓ Connected to remote server\n")

# Navigate to a test page
print("=" * 60)
print("Navigating to example.com")
print("=" * 60)
await stagehand.goto("https://example.com")
print("✓ Navigated to example.com\n")

# Test act()
print("=" * 60)
print("Testing act()")
print("=" * 60)
try:
act_result = await stagehand.act("scroll to the bottom")
print(f"✓ Act result: success={act_result.success}, "
f"message={act_result.message}, "
f"actions={len(act_result.actions)}")
except Exception as e:
print(f"✗ Act error: {e}")

# Test extract()
print("\n" + "=" * 60)
print("Testing extract()")
print("=" * 60)
try:
extract_result = await stagehand.extract("extract the page title")
print(f"✓ Extract result: {extract_result}")
except Exception as e:
print(f"✗ Extract error: {e}")

# Test observe()
print("\n" + "=" * 60)
print("Testing observe()")
print("=" * 60)
try:
observe_result = await stagehand.observe("find all links on the page")
print(f"✓ Observe result: Found {len(observe_result)} actions")
if observe_result:
first_action = observe_result[0]
print(f" First action: selector={first_action.selector}, "
f"description={first_action.description}")
except Exception as e:
print(f"✗ Observe error: {e}")

# Test extract with schema
print("\n" + "=" * 60)
print("Testing extract with schema")
print("=" * 60)
try:
schema = {
"type": "object",
"properties": {
"title": {"type": "string"},
"heading": {"type": "string"}
}
}
structured_data = await stagehand.extract(
instruction="extract the page title and main heading",
schema=schema
)
print(f"✓ Structured data: {structured_data}")
except Exception as e:
print(f"✗ Structured extract error: {e}")

print("\n" + "=" * 60)
print("All tests completed!")
print("=" * 60)
print("\nNote: The browser is running on the remote Node.js server.")
print(" All commands were executed via RPC over HTTP/SSE.\n")

finally:
await stagehand.close()


# Alternative example using context manager
async def context_manager_example():
"""Example using Python's async context manager"""
async with Stagehand(server_url="http://localhost:3000", verbose=1) as stagehand:
await stagehand.goto("https://example.com")
data = await stagehand.extract("extract the page title")
print(f"Page title: {data}")


if __name__ == "__main__":
asyncio.run(main())
# Or use the context manager version:
# asyncio.run(context_manager_example())
Loading
Loading