Documentation
¶
Overview ¶
Package browser implements the Browser Use capability: a CDP-driven browser the agent can see (text a11y snapshots + screenshots) and operate (click, fill, navigate) behind tiered approvals. Two backends share one TabConn abstraction: a managed Chrome launched by jcode, and the user's own Chrome reached through the jcode extension bridge. See internal-doc/browser-use-design.md.
Index ¶
- Constants
- Variables
- func ChromeVersion(ctx context.Context, path string) string
- func FindChrome(configPath string) string
- func InstallNativeHost(binPath string) error
- func IsLocalOrigin(origin string) bool
- func MaybeRunNativeHost(args []string) bool
- func OriginOf(raw string) string
- func WriteEndpoint(ws, token string) error
- type ActRequest
- type Backend
- type Bridge
- type Config
- type Endpoint
- type EventHandler
- type ExtensionInstallState
- type LaunchOptions
- type Manager
- func (m *Manager) Bridge() *Bridge
- func (m *Manager) Close() error
- func (m *Manager) DevMode() bool
- func (m *Manager) GetConfig() Config
- func (m *Manager) OpenSession(ctx context.Context) (*Session, error)
- func (m *Manager) SaveScreenshot(png []byte) (string, error)
- func (m *Manager) ScreenshotPath(id string) string
- func (m *Manager) SetConfig(cfg Config)
- func (m *Manager) Status(ctx context.Context) Status
- type Session
- func (s *Session) Act(ctx context.Context, req ActRequest) (string, error)
- func (s *Session) BackendKind() string
- func (s *Session) ClaimTab(ctx context.Context, tabID string) error
- func (s *Session) Close() error
- func (s *Session) CloseTab(ctx context.Context, tabID string) error
- func (s *Session) CurrentOrigin() string
- func (s *Session) Eval(ctx context.Context, expr string) (string, error)
- func (s *Session) ListTabs(ctx context.Context) ([]TabInfo, error)
- func (s *Session) NewTab(ctx context.Context) (string, error)
- func (s *Session) Open(ctx context.Context, url string, newTab bool) (string, error)
- func (s *Session) PageText(ctx context.Context, limit int) (string, error)
- func (s *Session) Reload(ctx context.Context) (string, error)
- func (s *Session) Screenshot(ctx context.Context, fullPage bool) ([]byte, error)
- func (s *Session) SelectTab(ctx context.Context, tabID string) error
- func (s *Session) Snapshot(ctx context.Context, filter string, maxLines int) (string, error)
- type Snapshot
- type Status
- type TabConn
- type TabInfo
Constants ¶
const ExtensionID = "ekcnniaefmnhnemnpphikhgfoofnojnd"
ExtensionID is the unpacked/dev extension id, derived from the committed public key ("key" field) in extension/manifest.json — stable across loads.
const NativeHostName = "com.jcode.bridge"
NativeHostName is the Chrome Native Messaging host id the extension connects to via chrome.runtime.connectNative. Must match the extension's usage.
Variables ¶
var AllowedExtensionIDs = []string{ ExtensionID, "olkapiiikpfhaccmjphakolinkcggcbd", }
AllowedExtensionIDs is every id the Browser Bridge extension can have: the unpacked dev build (above) plus the published store builds, which the stores re-sign under their own ids. All of these must appear in the native-host manifest's allowed_origins, or a store-installed extension can't open the native host (the browser enforces the origin before launching it).
var ErrControlInterrupted = fmt.Errorf("browser control interrupted")
ErrControlInterrupted is returned when the user (or the extension) takes back control of a tab mid-action. Tools surface this so the model stops and reports naturally rather than retrying.
Functions ¶
func ChromeVersion ¶
ChromeVersion returns the version string reported by the executable.
func FindChrome ¶
FindChrome returns the path to a Chromium-based browser executable, or "" when none is found. Explicit configPath (config.browser.chrome_path) wins.
func InstallNativeHost ¶
InstallNativeHost writes/refreshes the native-messaging host manifest so the extension can reach this jcode binary. Best-effort: it targets every browser dir it can and returns the first hard error (a missing browser dir is skipped, not an error). binPath should be os.Executable().
func IsLocalOrigin ¶
IsLocalOrigin reports whether an origin points at the local machine — the primary browser-use case (localhost dev-loop). Local targets get lighter treatment in some UIs but still follow the same approval tiers.
func MaybeRunNativeHost ¶
MaybeRunNativeHost checks argv for the native-messaging launch signature and, if present, runs the host loop and returns true (the caller should exit).
func OriginOf ¶
OriginOf returns the scheme://host[:port] origin of a raw URL, or "" when it cannot be parsed (e.g. about:blank).
func WriteEndpoint ¶
WriteEndpoint persists the current server WS URL + a valid bridge token so a freshly-spawned native host process (a separate process from the server) can read it and hand it to the extension. 0600 — it grants browser control.
Types ¶
type ActRequest ¶
type ActRequest struct {
Action string // click|dblclick|fill|press|hover|scroll|select|upload|dialog
UID string // element uid from the latest snapshot (most actions)
X, Y float64 // coordinate fallback for scroll/click
Value string // fill text, select value, dialog decision (accept|dismiss)
Key string // for action=press (e.g. "Enter")
Files []string
}
ActRequest describes a single browser_act call.
type Backend ¶
type Backend interface {
Kind() string // "managed" | "extension"
NewTab(ctx context.Context, url string) (TabConn, error)
ListTabs(ctx context.Context) ([]TabInfo, error)
// AttachTab takes control of an existing tab (claim). Managed backend
// attaches to its own targets; extension backend claims a user tab.
AttachTab(ctx context.Context, id string) (TabConn, error)
Close() error
}
Backend abstracts a browser jcode can drive.
type Bridge ¶
type Bridge struct {
// contains filtered or unexported fields
}
Bridge is the server side of the jcode Chrome extension channel. The extension's service worker connects over a websocket, presents a long-lived token (obtained via native-messaging Auto-connect), and then relays CDP commands to the user's Chrome via chrome.debugger. See §5.3 of the design.
func NewBridge ¶
func NewBridge() *Bridge
NewBridge creates a bridge. tokens are persisted to ~/.jcode/browser/ext-tokens.json.
func (*Bridge) HandleWS ¶
func (b *Bridge) HandleWS(w http.ResponseWriter, r *http.Request)
HandleWS upgrades an extension connection and runs its read loop.
func (*Bridge) IssueToken ¶
IssueToken mints and persists a token without a pairing code. Used by the native-messaging path, where the running server hands the extension a token directly (the OS-level native host launch is the trust anchor).
func (*Bridge) StableToken ¶
StableToken returns one long-lived token, reused across restarts — the "key" the extension stores once and re-presents forever. Combined with a stable server port, the extension reconnects silently with no re-auth. Persisted to ~/.jcode/browser/server-token (0600) and kept in the valid-token set. Preferred over IssueToken for the native/auto-connect path so tokens don't accumulate a fresh entry on every launch.
type Config ¶
type Config struct {
Enabled bool
Backend string // auto | managed | extension
ChromePath string
Headless bool
Viewport string
DevMode bool
}
Config mirrors config.BrowserConfig, decoupled so internal/browser does not import a specific config layout beyond what it needs.
type Endpoint ¶
Endpoint is what the native host hands back to the extension so it can dial the running jcode server without the user typing anything.
func ReadEndpoint ¶
ReadEndpoint loads the endpoint written by the running server.
type EventHandler ¶
type EventHandler func(method string, params json.RawMessage)
EventHandler receives CDP events for one tab.
type ExtensionInstallState ¶
type ExtensionInstallState struct {
Installed bool `json:"installed"`
Enabled bool `json:"enabled"`
Profile string `json:"profile,omitempty"`
Path string `json:"path,omitempty"` // unpacked path when known
}
ExtensionInstallState reports whether a jcode extension is present in the user's Chrome profiles by scanning Preferences JSON — the same technique as Codex's check-extension-installed.js.
func CheckExtensionInstalled ¶
func CheckExtensionInstalled(profileRoots []string, extDir string) ExtensionInstallState
CheckExtensionInstalled scans profileRoots (or the default Chrome dirs when nil) for an extension whose unpacked path points at extDir, or whose id equals ExtensionID when set.
type LaunchOptions ¶
type LaunchOptions struct {
ChromePath string // empty → FindChrome
Headless bool
ProfileDir string // empty → ~/.jcode/browser/profile
Viewport string // "1280x720"
}
LaunchOptions controls the managed Chrome launch.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager is the process-wide owner of browser-use infrastructure: the extension bridge, managed-Chrome lifecycle, screenshot store, and the resolved config. Tasks obtain a per-task Session from it. One per server.
func NewManager ¶
NewManager creates the manager. shotDir defaults to ~/.jcode/browser/shots.
func (*Manager) OpenSession ¶
OpenSession creates a per-task Session, choosing a backend per config: "extension" requires the bridge; "managed" launches Chrome; "auto" prefers a connected extension, else managed.
func (*Manager) SaveScreenshot ¶
SaveScreenshot writes PNG bytes to the shot store and returns its id.
func (*Manager) ScreenshotPath ¶
ScreenshotPath returns the file path for a shot id (for the HTTP endpoint).
type Session ¶
type Session struct {
// contains filtered or unexported fields
}
Session is the per-task browser state: one backend, a set of controlled tabs, the active tab, and the latest snapshot generation for stale-uid detection. It is safe for concurrent use by the tool layer.
func NewSession ¶
NewSession wraps a backend into a per-task session.
func (*Session) Act ¶
Act performs an interaction and returns a short "what changed" summary so the model usually does not need a follow-up snapshot.
func (*Session) BackendKind ¶
Backend returns the underlying backend kind ("managed"/"extension").
func (*Session) ClaimTab ¶
ClaimTab takes control of a pre-existing (user) tab without closing it later.
func (*Session) Close ¶
Close releases this task's tabs. It deliberately does NOT close the backend: the managed Chrome and the extension bridge are owned by the Manager and reused across tasks, so tearing the backend down here would kill the browser out from under every other (and future) task and leave the Manager caching a dead backend. Backend teardown belongs to Manager.Close.
func (*Session) CurrentOrigin ¶
CurrentOrigin returns the scheme://host of the active tab's last known URL, or "" when there is no active tab or its URL has no real origin (e.g. about:blank). It reads cached state — refreshed on every snapshot, which the model takes before acting — so the approval layer can scope per-site permissions for actions whose args carry no URL (clicks, fills) without a blocking CDP call.
func (*Session) Eval ¶
Eval runs a read-only expression and returns its JSON value (dev mode gate is enforced by the tool/approval layer, not here).
func (*Session) ListTabs ¶
ListTabs returns the tabs known to the backend, marking which are controlled.
func (*Session) Open ¶
Open navigates the active tab (or a new tab) to url and returns a fresh snapshot header.
func (*Session) Screenshot ¶
Screenshot captures the active tab as PNG bytes.
type Snapshot ¶
Snapshot is one serialized page state. UIDs are only valid for the generation they were minted in; actions verify this to reject stale refs.
type Status ¶
type Status struct {
Enabled bool `json:"enabled"`
Backend string `json:"backend"`
ChromeFound bool `json:"chrome_found"`
ChromePath string `json:"chrome_path,omitempty"`
ChromeVersion string `json:"chrome_version,omitempty"`
ExtensionOnline bool `json:"extension_online"`
DevMode bool `json:"dev_mode"`
}
Status describes browser-use availability for the settings UI.
type TabConn ¶
type TabConn interface {
// ID is the backend-scoped tab identifier (targetId or extension tab id).
ID() string
// Send issues a CDP command against this tab and returns its raw result.
Send(ctx context.Context, method string, params any) (json.RawMessage, error)
// SetEventHandler registers the sink for CDP events from this tab.
// Only one handler is active at a time; nil clears it.
SetEventHandler(h EventHandler)
// Close closes the underlying page/tab.
Close(ctx context.Context) error
// Detach releases control of the tab without closing it (extension backend
// leaves the page to the user; managed backend is equivalent to a no-op
// because nobody else is driving that Chrome).
Detach(ctx context.Context) error
}
TabConn is a single controllable tab, regardless of backend.