@keystrokehq/browserbase
v0.0.15
Published
Browserbase cloud-browser automation for Keystroke, powered by [Stagehand](https://github.com/browserbase/stagehand).
Readme
@keystrokehq/browserbase
Browserbase cloud-browser automation for Keystroke, powered by Stagehand.
What's in here
- Cross-step Stagehand ops (
navigate,act,observe,extract,screenshot) that thread an optionalsessionIdso multiple workflow steps can drive the same cloud session. withSession(creds, opts, handler)for running many actions against one session inside a single op.- Browserbase-specific extras: session lifecycle (
createSession,getLiveView), persistent contexts (createContext,getContext,deleteContext), and directfetchUrl. createBrowserLoginExchange— acredentials-exchangepreset for providers with no API-login endpoint.
createBrowserLoginExchange — browser-login preset
Use this preset when the only way to log into a provider is through a real browser (SSO portals, legacy admin consoles, sites with no API).
import {
createBrowserLoginExchange,
type BrowserbaseCredentials,
} from '@keystrokehq/browserbase';
import { CredentialSet } from '@keystrokehq/core';
import { z } from 'zod';
async function resolveBrowserbaseCredentials(): Promise<BrowserbaseCredentials> {
// Platform-owned Browserbase credentials. In production this comes from
// the Keystroke-internal provider-app credential set for Browserbase.
return { BROWSERBASE_API_KEY: process.env.BROWSERBASE_API_KEY ?? '' };
}
export const legacyPortal = new CredentialSet({
id: 'legacyPortal',
auth: z.object({ sessionCookie: z.string() }),
stored: z.object({
sessionCookie: z.string(),
cookieName: z.string(),
cookieDomain: z.string(),
browserbaseContextId: z.string(),
}),
resolve: async (stored) => ({ sessionCookie: stored.sessionCookie }),
connection: createBrowserLoginExchange({
input: z.object({
username: z.email(),
password: z.string().min(1),
}),
stored: z.object({
sessionCookie: z.string(),
cookieName: z.string(),
cookieDomain: z.string(),
browserbaseContextId: z.string(),
}),
loginUrl: 'https://portal.example.com/login',
fields: {
username: 'Type %username% into the email field',
password: 'Type %password% into the password field',
},
submit: 'Click the Sign in button',
successSignal: { waitForUrl: /\/dashboard/ },
cookie: { name: 'example_session', domain: 'portal.example.com' },
resolveBrowserbaseCredentials,
}),
});Security posture
- The LLM never sees plaintext credentials. Each field instruction
references its value via
%fieldName%; Stagehand substitutes the placeholder at Chromium level after the LLM generates the click/type plan. - The exchange and rotate hooks run host-side in the trusted
runtime. User step code never observes the raw input, the Stagehand
session, or the extracted cookie — only the resolved auth value
returned by
resolve. - Workspace-authored browser-login is out of scope in v1. The preset is intended for Keystroke-official integrations only. Adding a workspace-facing variant requires a trust-model extension beyond cluster 11.
Rotation
Rotate reconnects the persistent Browserbase context and probes a known
authenticated URL. A redirect back to the login URL signals the session
is dead and the preset returns 'needs-reinput'. Keep the rotate
tolerance conservative — every rotate spawns a Browserbase session, and
the scheduler runs ahead of expiresAt to give the new cookie time to
land before the old one expires in flight.
See
plans-reconciled/14-credentials-exchange-connection-kind/03-browser-preset-docs.md
for the full design and testing notes.
