proxy

package
v0.13.34 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 10, 2026 License: Apache-2.0 Imports: 40 Imported by: 0

Documentation

Overview

Package proxy implements a reverse HTTP proxy with JavaScript injection, traffic logging, and chaos engineering support for browser debugging.

Key types:

  • ProxyServer: the core proxy, created via ProxyManager.Create()
  • ProxyManager: registry and lifecycle manager for all proxies
  • TrafficLogger: circular-buffer log of HTTP traffic and browser events
  • ChaosEngine: configurable fault injection (latency, errors, bandwidth)

Proxies inject a __devtool JavaScript API into HTML responses for browser-side diagnostics, error capture, and real-time metrics.

Index

Constants

View Source
const (
	MaxInteractionsPerSession = 200
	MaxMutationsPerSession    = 100
)

Limits for interaction and mutation history per session

View Source
const AuditDirName = "audit"

AuditDirName is the directory name for storing audit data within .agnt

View Source
const AuditSummaryFile = "SUMMARY.md"

AuditSummaryFile is the name of the summary file in the audit directory.

View Source
const LargeResultThreshold = 50 * 1024 // 50KB

LargeResultThreshold is the size in bytes above which results are saved to file.

View Source
const ReadinessRetryAfterMs = 500

ReadinessRetryAfterMs is the retry interval suggested to clients in the readiness 503 body. The browser will retry automatically; the value is informational only.

View Source
const ReadinessSentinel = "agnt_proxy_not_ready"

ReadinessSentinel is the stable error code in the 503 JSON body emitted by the readiness gate. `get_errors` matches this string to drop gate-generated responses from its error feed.

Variables

View Source
var (
	// ErrProxyExists is returned when trying to create a proxy with an existing ID.
	ErrProxyExists = errors.New("proxy already exists")
	// ErrProxyNotFound is returned when a proxy ID is not found.
	ErrProxyNotFound = errors.New("proxy not found")
	// ErrProxyAmbiguous is returned when a fuzzy lookup matches multiple proxies.
	ErrProxyAmbiguous = errors.New("proxy ID is ambiguous - multiple matches")
)
View Source
var ChaosPresets = map[string]*ChaosConfig{

	"mobile-3g": {
		Enabled: true,
		Rules: []*ChaosRule{
			{
				ID:           "mobile-3g-latency",
				Name:         "3G Network Latency",
				Type:         ChaosLatency,
				Enabled:      true,
				Probability:  1.0,
				MinLatencyMs: 200,
				MaxLatencyMs: 2000,
				JitterMs:     500,
			},
			{
				ID:          "mobile-3g-packet-loss",
				Name:        "3G Packet Loss",
				Type:        ChaosPacketLoss,
				Enabled:     true,
				Probability: 0.02,
			},
		},
		LoggingMode: LoggingModeTesting,
	},

	"mobile-4g": {
		Enabled: true,
		Rules: []*ChaosRule{
			{
				ID:           "mobile-4g-latency",
				Name:         "4G Network Latency",
				Type:         ChaosLatency,
				Enabled:      true,
				Probability:  1.0,
				MinLatencyMs: 50,
				MaxLatencyMs: 500,
				JitterMs:     100,
			},
			{
				ID:          "mobile-4g-packet-loss",
				Name:        "4G Packet Loss",
				Type:        ChaosPacketLoss,
				Enabled:     true,
				Probability: 0.005,
			},
		},
		LoggingMode: LoggingModeTesting,
	},

	"flaky-api": {
		Enabled: true,
		Rules: []*ChaosRule{
			{
				ID:          "flaky-http-errors",
				Name:        "Random HTTP Errors",
				Type:        ChaosHTTPError,
				Enabled:     true,
				Probability: 0.05,
				ErrorCodes:  []int{500, 502, 503, 504},
			},
			{
				ID:           "flaky-latency",
				Name:         "Variable Latency",
				Type:         ChaosLatency,
				Enabled:      true,
				Probability:  0.3,
				MinLatencyMs: 100,
				MaxLatencyMs: 5000,
				JitterMs:     1000,
			},
			{
				ID:          "flaky-timeout",
				Name:        "Occasional Timeouts",
				Type:        ChaosTimeout,
				Enabled:     true,
				Probability: 0.02,
			},
		},
		LoggingMode: LoggingModeTesting,
	},

	"race-condition": {
		Enabled: true,
		Rules: []*ChaosRule{
			{
				ID:                 "reorder-responses",
				Name:               "Out-of-Order Responses",
				Type:               ChaosOutOfOrder,
				Enabled:            true,
				Probability:        0.5,
				ReorderMinRequests: 2,
				ReorderMaxWaitMs:   500,
			},
			{
				ID:           "variable-latency",
				Name:         "High Variance Latency",
				Type:         ChaosLatency,
				Enabled:      true,
				Probability:  0.7,
				MinLatencyMs: 0,
				MaxLatencyMs: 3000,
				JitterMs:     1000,
			},
		},
		LoggingMode: LoggingModeTesting,
	},

	"stale-tab": {
		Enabled: true,
		Rules: []*ChaosRule{
			{
				ID:           "stale-delay",
				Name:         "Stale Tab Delay",
				Type:         ChaosStale,
				Enabled:      true,
				Probability:  1.0,
				StaleDelayMs: 10800000,
			},
		},
		LoggingMode: LoggingModeTesting,
	},

	"slow-connection": {
		Enabled: true,
		Rules: []*ChaosRule{
			{
				ID:         "slow-drip",
				Name:       "Slow Data Transfer",
				Type:       ChaosSlowDrip,
				Enabled:    true,
				BytesPerMs: 5,
				ChunkSize:  10,
			},
			{
				ID:           "connection-latency",
				Name:         "Connection Latency",
				Type:         ChaosLatency,
				Enabled:      true,
				Probability:  1.0,
				MinLatencyMs: 500,
				MaxLatencyMs: 1000,
			},
		},
		LoggingMode: LoggingModeTesting,
	},

	"connection-drops": {
		Enabled: true,
		Rules: []*ChaosRule{
			{
				ID:               "drop-mid-response",
				Name:             "Drop Connection Mid-Response",
				Type:             ChaosDisconnect,
				Enabled:          true,
				Probability:      0.1,
				DropAfterPercent: 0.5,
			},
		},
		LoggingMode: LoggingModeTesting,
	},

	"data-corruption": {
		Enabled: true,
		Rules: []*ChaosRule{
			{
				ID:              "truncate-response",
				Name:            "Truncate Responses",
				Type:            ChaosTruncate,
				Enabled:         true,
				Probability:     0.05,
				TruncatePercent: 0.8,
			},
		},
		LoggingMode: LoggingModeTesting,
	},

	"rate-limited": {
		Enabled: true,
		Rules: []*ChaosRule{
			{
				ID:           "rate-limit-429",
				Name:         "Rate Limit Errors",
				Type:         ChaosHTTPError,
				Enabled:      true,
				Probability:  0.2,
				ErrorCodes:   []int{429},
				ErrorMessage: `{"error": "Too Many Requests", "retry_after": 60}`,
			},
		},
		LoggingMode: LoggingModeTesting,
	},

	"auth-failures": {
		Enabled: true,
		Rules: []*ChaosRule{
			{
				ID:          "auth-error",
				Name:        "Authentication Failures",
				Type:        ChaosHTTPError,
				Enabled:     true,
				Probability: 0.1,
				ErrorCodes:  []int{401, 403},
			},
		},
		LoggingMode: LoggingModeTesting,
	},

	"service-degradation": {
		Enabled:    true,
		GlobalOdds: 0.3,
		Rules: []*ChaosRule{
			{
				ID:           "degraded-latency",
				Name:         "Degraded Response Times",
				Type:         ChaosLatency,
				Enabled:      true,
				Probability:  0.5,
				MinLatencyMs: 1000,
				MaxLatencyMs: 10000,
			},
			{
				ID:          "degraded-errors",
				Name:        "Intermittent Errors",
				Type:        ChaosHTTPError,
				Enabled:     true,
				Probability: 0.1,
				ErrorCodes:  []int{503},
			},
			{
				ID:              "degraded-truncation",
				Name:            "Partial Responses",
				Type:            ChaosTruncate,
				Enabled:         true,
				Probability:     0.05,
				TruncatePercent: 0.5,
			},
		},
		LoggingMode: LoggingModeTesting,
	},

	"pressure-test": {
		Enabled:    true,
		GlobalOdds: 0.5,
		Rules: []*ChaosRule{
			{
				ID:           "pressure-latency",
				Name:         "Random Latency",
				Type:         ChaosLatency,
				Enabled:      true,
				Probability:  0.4,
				MinLatencyMs: 100,
				MaxLatencyMs: 2000,
				JitterMs:     500,
			},
			{
				ID:          "pressure-errors",
				Name:        "Random Errors",
				Type:        ChaosHTTPError,
				Enabled:     true,
				Probability: 0.1,
				ErrorCodes:  []int{500, 502, 503, 504, 429},
			},
			{
				ID:                 "pressure-reorder",
				Name:               "Response Reordering",
				Type:               ChaosOutOfOrder,
				Enabled:            true,
				Probability:        0.3,
				ReorderMinRequests: 3,
				ReorderMaxWaitMs:   300,
			},
			{
				ID:          "pressure-drops",
				Name:        "Connection Drops",
				Type:        ChaosDisconnect,
				Enabled:     true,
				Probability: 0.02,
			},
		},
		LoggingMode: LoggingModeCoordinated,
	},
}

ChaosPresets contains built-in chaos configurations for common testing scenarios

Functions

func BuildShellDocument added in v0.13.22

func BuildShellDocument(proxyID, frameID, contentSrc, authCfgJS string) []byte

BuildShellDocument returns the outer chrome-shell HTML for a top-level navigation. The shell carries the proxy-id, the chrome role marker, and the instrumentation bundle, and embeds a single full-viewport content <iframe> whose src is the originally-requested resource with the frame marker appended — so the proxy serves the real page there, injected in content role. The proxy UI runtime (indicator/panels) therefore lives in the shell, isolated from page content. Role gating of the runtime lands in Slice 3; this slice only establishes the wrap + the browser-side role/registry primitive. authCfgJS is the (possibly empty) inline JS publishing the auth-breakout config (AuthBreakout.clientConfigJS); it precedes the bundle so scripts/authbreakout.js reads it at eval time.

func DefaultPortForURL

func DefaultPortForURL(targetURL string) int

DefaultPortForURL computes a stable default port based on the target URL. The port is derived from a hash of the URL, mapped to the range 10000-60000. This ensures the same URL always gets the same default port while avoiding conflicts with common ports and ephemeral port ranges.

func FormatAuditReference added in v0.10.0

func FormatAuditReference() string

FormatAuditReference formats a reference to the audit directory for AI agent messages.

func GetAuditDir added in v0.10.0

func GetAuditDir() (string, error)

GetAuditDir returns the audit directory path for a project. Creates the directory if it doesn't exist. Returns absolute path to .agnt/audit in the current working directory.

func InjectContentRuntime added in v0.13.22

func InjectContentRuntime(body []byte, proxyID, frameID, authCfgJS string) []byte

InjectContentRuntime injects the proxy-id, the content role marker, and the bundle tag into a content-frame (or unwrapped-fallback / fragment) HTML response. Mirrors InjectInstrumentationAndMeta but additionally declares window.__devtool_role="content" + the frame id so scripts/frames.js resolves the frame's role without re-deriving it from the URL. authCfgJS mirrors BuildShellDocument: the content frame needs the config too, for client-side navigation interception (Navigation API / anchors).

func InjectInstrumentation

func InjectInstrumentation(body []byte, wsPort int) []byte

InjectInstrumentation adds monitoring JavaScript to HTML responses by inserting a small external <script src> tag that loads the content-addressed instrumentation bundle (served by the proxy at instrumentationAssetPath). The wsPort parameter is deprecated and unused (kept for backward compatibility). The tag is a blocking, same-origin script so it executes, in order, before the page's own scripts run.

func InjectInstrumentationAndMeta added in v0.13.17

func InjectInstrumentationAndMeta(body []byte, proxyID string) []byte

InjectInstrumentationAndMeta injects, in a single body copy, the proxy-id inline (it varies per proxy, so it cannot be a shared external asset) followed by the external instrumentation bundle tag. Both are blocking same-origin scripts placed in document order, so window.__devtool_proxy_id is set, then the bundle loads, before any page script runs.

The bundle (~1.3MB) was previously inlined into every HTML response — copied per request and re-sent on every page load. Serving it as an external, immutably-cached asset shrinks the injected payload from ~1.3MB to ~150 bytes and lets the browser cache the bundle across page loads.

func InjectProxyMeta added in v0.12.0

func InjectProxyMeta(body []byte, proxyID string) []byte

InjectProxyMeta inserts a small script tag setting window.__devtool_proxy_id after the last </script> in the body. Retained for direct callers/tests; the proxy response path uses InjectInstrumentationAndMeta to avoid a second full-body copy.

func ListPresets

func ListPresets() []string

ListPresets returns the names of all available presets

func SaveAuditData added in v0.10.0

func SaveAuditData(auditType, label string, result json.RawMessage) (string, error)

SaveAuditData saves audit data as a JSON file in the .agnt/audit directory. Returns the file path and any error.

func ShouldInject

func ShouldInject(contentType string) bool

ShouldInject determines if JavaScript should be injected based on content type.

func UpdateAuditSummary added in v0.10.0

func UpdateAuditSummary() error

UpdateAuditSummary creates or updates the SUMMARY.md file in .agnt/audit/ with a listing of all files and their descriptions.

Types

type AttributeChange

type AttributeChange struct {
	Name     string `json:"name"`
	OldValue string `json:"old_value,omitempty"`
	NewValue string `json:"new_value,omitempty"`
}

AttributeChange describes a changed attribute.

type AuthBreakout added in v0.13.34

type AuthBreakout struct {
	// Mode is "popup" or "top" (validated at config parse time).
	Mode string `json:"mode"`
	// Patterns are case-insensitive wildcard fragments matched against the
	// full navigation URL: `*` matches any run of characters, plain text
	// matches as a substring.
	Patterns []string `json:"patterns"`
	// contains filtered or unexported fields
}

AuthBreakout is the runtime form of the .agnt.kdl auth-breakout block (config.AuthBreakoutConfig). When set on a proxy, content-frame navigations to matching URLs are carried out in a top-level window instead of the content iframe, and the OAuth callback is replayed into the iframe. See docs/configuration.md § Auth Breakout.

func (*AuthBreakout) MatchesURL added in v0.13.34

func (ab *AuthBreakout) MatchesURL(rawURL string) bool

MatchesURL reports whether rawURL matches any breakout pattern. Case-insensitive; patterns use substring-with-`*`-wildcard semantics.

type ChaosConfig

type ChaosConfig struct {
	Enabled     bool         `json:"enabled"`
	Rules       []*ChaosRule `json:"rules"`
	GlobalOdds  float64      `json:"global_odds,omitempty"` // 0.0-1.0, applies to all
	Seed        int64        `json:"seed,omitempty"`        // For reproducible chaos
	LoggingMode LoggingMode  `json:"logging_mode,omitempty"`
}

ChaosConfig defines chaos rules for a proxy

func GetPreset

func GetPreset(name string) *ChaosConfig

GetPreset returns a copy of the named preset configuration

type ChaosEngine

type ChaosEngine struct {
	// contains filtered or unexported fields
}

ChaosEngine manages chaos rules and injection

func NewChaosEngine

func NewChaosEngine(logger *TrafficLogger) *ChaosEngine

NewChaosEngine creates a new chaos engine

func (*ChaosEngine) AddRule

func (ce *ChaosEngine) AddRule(rule *ChaosRule) error

AddRule adds a single rule

func (*ChaosEngine) Clear

func (ce *ChaosEngine) Clear()

Clear clears all chaos rules

func (*ChaosEngine) Disable

func (ce *ChaosEngine) Disable()

Disable disables chaos injection

func (*ChaosEngine) DisableRule

func (ce *ChaosEngine) DisableRule(ruleID string) bool

DisableRule disables a specific rule

func (*ChaosEngine) Enable

func (ce *ChaosEngine) Enable()

Enable enables chaos injection

func (*ChaosEngine) EnableRule

func (ce *ChaosEngine) EnableRule(ruleID string) bool

EnableRule enables a specific rule

func (*ChaosEngine) GetConfig

func (ce *ChaosEngine) GetConfig() *ChaosConfig

GetConfig returns the current configuration

func (*ChaosEngine) GetDropConfig

func (ce *ChaosEngine) GetDropConfig(rules []*ChaosRule) (afterPercent float64, afterBytes int64)

GetDropConfig returns connection drop configuration

func (*ChaosEngine) GetHTTPError

func (ce *ChaosEngine) GetHTTPError(rules []*ChaosRule) (int, string)

GetHTTPError returns an HTTP error code to inject, or 0 if none

func (*ChaosEngine) GetLatencyDelay

func (ce *ChaosEngine) GetLatencyDelay(rules []*ChaosRule) time.Duration

GetLatencyDelay calculates latency delay for matching rules

func (*ChaosEngine) GetLoggingMode

func (ce *ChaosEngine) GetLoggingMode() LoggingMode

GetLoggingMode returns the current logging mode

func (*ChaosEngine) GetReorderConfig

func (ce *ChaosEngine) GetReorderConfig(rules []*ChaosRule) (minRequests int, maxWait time.Duration)

GetReorderConfig returns out-of-order configuration

func (*ChaosEngine) GetSlowDripConfig

func (ce *ChaosEngine) GetSlowDripConfig(rules []*ChaosRule) (bytesPerMs, chunkSize int)

GetSlowDripConfig returns slow-drip configuration

func (*ChaosEngine) GetStaleDelay

func (ce *ChaosEngine) GetStaleDelay(rules []*ChaosRule) time.Duration

GetStaleDelay returns stale response delay

func (*ChaosEngine) GetStats

func (ce *ChaosEngine) GetStats() ChaosStats

GetStats returns current statistics

func (*ChaosEngine) GetTruncateConfig

func (ce *ChaosEngine) GetTruncateConfig(rules []*ChaosRule) float64

GetTruncateConfig returns truncation configuration

func (*ChaosEngine) HasRuleType

func (ce *ChaosEngine) HasRuleType(rules []*ChaosRule, ruleType ChaosType) bool

HasRuleType checks if any matching rule has the specified type

func (*ChaosEngine) IncrementReordered

func (ce *ChaosEngine) IncrementReordered()

IncrementReordered increments the reordered counter

func (*ChaosEngine) IsEnabled

func (ce *ChaosEngine) IsEnabled() bool

IsEnabled returns whether chaos is enabled

func (*ChaosEngine) MatchingRules

func (ce *ChaosEngine) MatchingRules(req *http.Request) []*ChaosRule

MatchingRules returns all rules that match the request

func (*ChaosEngine) RemoveRule

func (ce *ChaosEngine) RemoveRule(ruleID string) bool

RemoveRule removes a rule by ID

func (*ChaosEngine) ResetStats

func (ce *ChaosEngine) ResetStats()

ResetStats resets all statistics

func (*ChaosEngine) SetConfig

func (ce *ChaosEngine) SetConfig(config *ChaosConfig) error

SetConfig sets the chaos configuration

func (*ChaosEngine) SetLoggingMode

func (ce *ChaosEngine) SetLoggingMode(mode LoggingMode)

SetLoggingMode sets the logging mode

func (*ChaosEngine) SetOnChange added in v0.13.20

func (ce *ChaosEngine) SetOnChange(fn func())

SetOnChange registers a callback fired after any chaos mutation.

func (*ChaosEngine) SetSwallowDetect added in v0.13.20

func (ce *ChaosEngine) SetSwallowDetect(on bool)

SetSwallowDetect toggles the swallowed-error heuristic for this proxy and notifies listeners so the panel reflects the new state.

func (*ChaosEngine) ShouldDrop

func (ce *ChaosEngine) ShouldDrop(rules []*ChaosRule) bool

ShouldDrop returns true if the connection should be dropped

func (*ChaosEngine) ShouldReorder

func (ce *ChaosEngine) ShouldReorder(rules []*ChaosRule) bool

ShouldReorder returns true if responses should be reordered

func (*ChaosEngine) Snapshot added in v0.13.20

func (ce *ChaosEngine) Snapshot() *ChaosSnapshot

Snapshot returns the live engine state: master enabled flag, config-level knobs, and every rule with its current enabled state and applied count.

func (*ChaosEngine) Stop added in v0.12.51

func (ce *ChaosEngine) Stop()

Stop stops the chaos engine and drains its background goroutines. Must be called when the owning ProxyServer shuts down.

func (*ChaosEngine) SwallowDetectEnabled added in v0.13.20

func (ce *ChaosEngine) SwallowDetectEnabled() bool

SwallowDetectEnabled reports whether swallowed-error detection is active.

type ChaosRule

type ChaosRule struct {
	ID      string    `json:"id"`
	Name    string    `json:"name"`
	Type    ChaosType `json:"type"`
	Enabled bool      `json:"enabled"`

	// Matching criteria
	URLPattern  string   `json:"url_pattern,omitempty"` // Regex pattern for URL
	Methods     []string `json:"methods,omitempty"`     // HTTP methods (empty = all)
	Probability float64  `json:"probability,omitempty"` // 0.0-1.0, default 1.0

	// Latency config
	MinLatencyMs int `json:"min_latency_ms,omitempty"`
	MaxLatencyMs int `json:"max_latency_ms,omitempty"`
	JitterMs     int `json:"jitter_ms,omitempty"`

	// Slow-drip config
	BytesPerMs int `json:"bytes_per_ms,omitempty"` // Bytes to write per millisecond
	ChunkSize  int `json:"chunk_size,omitempty"`   // Size of each write chunk

	// Connection drop config
	DropAfterPercent float64 `json:"drop_after_percent,omitempty"` // Drop after % of body
	DropAfterBytes   int64   `json:"drop_after_bytes,omitempty"`   // Drop after N bytes

	// Error injection config
	ErrorCodes   []int  `json:"error_codes,omitempty"` // HTTP status codes
	ErrorMessage string `json:"error_message,omitempty"`

	// Truncation config
	TruncatePercent float64 `json:"truncate_percent,omitempty"` // Keep this % of response

	// Out-of-order config
	ReorderMinRequests int `json:"reorder_min_requests,omitempty"` // Min concurrent to reorder
	ReorderMaxWaitMs   int `json:"reorder_max_wait_ms,omitempty"`  // Max wait for batch

	// Stale config
	StaleDelayMs int64 `json:"stale_delay_ms,omitempty"` // Delay in milliseconds
	// contains filtered or unexported fields
}

ChaosRule defines a single chaos behavior

type ChaosRuleSnapshot added in v0.13.20

type ChaosRuleSnapshot struct {
	*ChaosRule
	Enabled bool  `json:"enabled"`
	Applied int64 `json:"applied"`
}

ChaosRuleSnapshot is a point-in-time view of a rule with its live enabled state and applied count. Rules added via AddRule never sync back into config.Rules, and per-rule toggles live in chaosRuleState — so UI surfaces must read this snapshot, not GetConfig.

type ChaosSnapshot added in v0.13.20

type ChaosSnapshot struct {
	Enabled    bool                 `json:"enabled"`
	GlobalOdds float64              `json:"global_odds,omitempty"`
	Seed       int64                `json:"seed,omitempty"`
	Rules      []*ChaosRuleSnapshot `json:"rules"`
	Stats      ChaosStats           `json:"stats"`
	// SwallowDetect mirrors the runtime swallowed-error toggle so the panel
	// renders the switch in the right position.
	SwallowDetect bool `json:"swallow_detect"`
}

ChaosSnapshot is the full live state of the engine for UI consumption.

type ChaosStats

type ChaosStats struct {
	TotalRequests   int64            `json:"total_requests"`
	AffectedCount   int64            `json:"affected_count"`
	LatencyInjected int64            `json:"latency_injected_ms"`
	ErrorsInjected  int64            `json:"errors_injected"`
	DropsInjected   int64            `json:"drops_injected"`
	TruncatedCount  int64            `json:"truncated_count"`
	ReorderedCount  int64            `json:"reordered_count"`
	RuleStats       map[string]int64 `json:"rule_stats"` // Rule ID -> times applied
}

ChaosStats tracks chaos injection statistics

type ChaosTransport

type ChaosTransport struct {
	// contains filtered or unexported fields
}

ChaosTransport wraps http.RoundTripper to inject chaos at the transport level. This enables latency injection, request reordering, and full request/response control.

func NewChaosTransport

func NewChaosTransport(underlying http.RoundTripper, engine *ChaosEngine) *ChaosTransport

NewChaosTransport creates a new chaos transport wrapping the given transport

func (*ChaosTransport) RoundTrip

func (ct *ChaosTransport) RoundTrip(req *http.Request) (*http.Response, error)

RoundTrip implements http.RoundTripper with chaos injection

type ChaosType

type ChaosType string

ChaosType defines the type of chaos to inject

const (
	// Network chaos
	ChaosLatency    ChaosType = "latency"     // Add delays to responses
	ChaosBandwidth  ChaosType = "bandwidth"   // Limit data transfer rate
	ChaosPacketLoss ChaosType = "packet_loss" // Drop random requests
	ChaosDisconnect ChaosType = "disconnect"  // Drop connection mid-response
	ChaosSlowClose  ChaosType = "slow_close"  // Delay TCP close

	// Response timing
	ChaosSlowDrip   ChaosType = "slow_drip"    // Trickle bytes slowly
	ChaosTimeout    ChaosType = "timeout"      // Never respond (simulate timeout)
	ChaosStale      ChaosType = "stale"        // Very long delays (hours)
	ChaosOutOfOrder ChaosType = "out_of_order" // Reorder responses

	// HTTP errors
	ChaosHTTPError ChaosType = "http_error" // Inject HTTP error codes
	ChaosRateLimit ChaosType = "rate_limit" // Simulate rate limiting (429)

	// Data corruption
	ChaosBitFlip     ChaosType = "bit_flip"     // Random byte changes
	ChaosTruncate    ChaosType = "truncate"     // Cut off response body
	ChaosCorruptJSON ChaosType = "corrupt_json" // Malform JSON responses

	// Protocol edge cases
	ChaosChunkedAbort ChaosType = "chunked_abort" // No terminal chunk
	ChaosPartialBody  ChaosType = "partial_body"  // Incomplete body
	ChaosHeaderBomb   ChaosType = "header_bomb"   // Many headers
)

type ConnAttempt added in v0.12.31

type ConnAttempt struct {
	Timestamp time.Time
	Event     string // "connection_refused", "timeout", "reset", etc.
	Message   string
}

ConnAttempt records a failed connection attempt for the loading page.

type ConnectionDropWriter

type ConnectionDropWriter struct {
	// contains filtered or unexported fields
}

ConnectionDropWriter wraps http.ResponseWriter to drop connection mid-response. This simulates network failures, connection resets, or abrupt disconnections.

func NewConnectionDropWriter

func NewConnectionDropWriter(w http.ResponseWriter, dropAfterPercent float64, dropAfterBytes int64, expectedSize int64) *ConnectionDropWriter

NewConnectionDropWriter creates a new connection drop writer

func (*ConnectionDropWriter) BytesWritten

func (cdw *ConnectionDropWriter) BytesWritten() int64

BytesWritten returns total bytes written

func (*ConnectionDropWriter) Flush

func (cdw *ConnectionDropWriter) Flush()

Flush implements http.Flusher

func (*ConnectionDropWriter) Header

func (cdw *ConnectionDropWriter) Header() http.Header

Header returns the header map

func (*ConnectionDropWriter) Hijack

func (cdw *ConnectionDropWriter) Hijack() (net.Conn, *bufio.ReadWriter, error)

Hijack implements http.Hijacker

func (*ConnectionDropWriter) IsDropped

func (cdw *ConnectionDropWriter) IsDropped() bool

IsDropped returns whether the connection has been dropped

func (*ConnectionDropWriter) Write

func (cdw *ConnectionDropWriter) Write(p []byte) (int, error)

Write writes data and may drop the connection mid-write

func (*ConnectionDropWriter) WriteHeader

func (cdw *ConnectionDropWriter) WriteHeader(statusCode int)

WriteHeader sends the HTTP response header

type CustomLog

type CustomLog struct {
	ID        string                 `json:"id"`
	Timestamp time.Time              `json:"timestamp"`
	Level     string                 `json:"level"` // debug, info, warn, error
	Message   string                 `json:"message"`
	Data      map[string]interface{} `json:"data,omitempty"`
	URL       string                 `json:"url"`
}

CustomLog represents a custom log message from the frontend.

type DeepgramConfig

type DeepgramConfig struct {
	Model          string
	Language       string
	Punctuate      bool
	SmartFormat    bool
	InterimResults bool
	Encoding       string
	SampleRate     int
	Channels       int
}

DeepgramConfig holds configuration for Deepgram connection.

func DefaultDeepgramConfig

func DefaultDeepgramConfig() DeepgramConfig

DefaultDeepgramConfig returns sensible defaults for voice transcription.

type DeepgramMessage

type DeepgramMessage struct {
	Type    string `json:"type"`
	Channel struct {
		Alternatives []struct {
			Transcript string  `json:"transcript"`
			Confidence float64 `json:"confidence"`
			Words      []struct {
				Word       string  `json:"word"`
				Start      float64 `json:"start"`
				End        float64 `json:"end"`
				Confidence float64 `json:"confidence"`
			} `json:"words"`
		} `json:"alternatives"`
	} `json:"channel"`
	IsFinal     bool    `json:"is_final"`
	SpeechFinal bool    `json:"speech_final"`
	Start       float64 `json:"start"`
	Duration    float64 `json:"duration"`
}

DeepgramMessage represents a message from Deepgram.

type DesignChat

type DesignChat struct {
	ID             string                `json:"id"`
	Timestamp      time.Time             `json:"timestamp"`
	Message        string                `json:"message"` // User's chat message
	Selector       string                `json:"selector"`
	XPath          string                `json:"xpath"`
	CurrentHTML    string                `json:"current_html"`
	OriginalHTML   string                `json:"original_html"`
	ContextHTML    string                `json:"context_html"`
	Metadata       DesignElementMetadata `json:"metadata"`
	ChatHistory    []DesignChatMessage   `json:"chat_history,omitempty"`
	URL            string                `json:"url"`
	ScreenshotPath string                `json:"screenshot_path,omitempty"` // saved PNG of the live segment
}

DesignChat represents a chat message about the selected element.

type DesignChatMessage

type DesignChatMessage struct {
	Timestamp int64  `json:"timestamp"`
	Message   string `json:"message"`
	Role      string `json:"role"` // user or assistant
}

DesignChatMessage represents a chat message in the design iteration history.

type DesignEdit added in v0.13.20

type DesignEdit struct {
	ID             string                `json:"id"`
	Timestamp      time.Time             `json:"timestamp"`
	Selector       string                `json:"selector"`
	XPath          string                `json:"xpath"`
	OID            string                `json:"oid"`             // data-devtool-oid value
	Deltas         map[string]string     `json:"deltas"`          // property → final value
	ComputedBefore map[string]string     `json:"computed_before"` // measured before the drag
	ComputedAfter  map[string]string     `json:"computed_after"`  // measured after the drag
	Metadata       DesignElementMetadata `json:"metadata"`
	URL            string                `json:"url"`
}

DesignEdit represents a direct-manipulation geometry edit committed on an existing element through the design-mode transform handles. The payload contract is selector + computed delta (plus OID so the agent can locate an element whose selector is weak); the browser never resolves source files.

type DesignElementMetadata

type DesignElementMetadata struct {
	Tag        string            `json:"tag"`
	ID         string            `json:"id,omitempty"`
	Classes    []string          `json:"classes,omitempty"`
	Attributes map[string]string `json:"attributes,omitempty"`
	Text       string            `json:"text,omitempty"` // Truncated text content
	Rect       struct {
		Width  int `json:"width"`
		Height int `json:"height"`
	} `json:"rect,omitempty"`
}

DesignElementMetadata describes metadata about a selected element for design iteration.

type DesignRequest

type DesignRequest struct {
	ID                string                `json:"id"`
	Timestamp         time.Time             `json:"timestamp"`
	Selector          string                `json:"selector"`
	XPath             string                `json:"xpath"`
	CurrentHTML       string                `json:"current_html"`  // Current HTML being displayed
	OriginalHTML      string                `json:"original_html"` // Original HTML before any changes
	ContextHTML       string                `json:"context_html"`  // Parent context
	Metadata          DesignElementMetadata `json:"metadata"`
	AlternativesCount int                   `json:"alternatives_count"` // How many alternatives already exist
	ChatHistory       []DesignChatMessage   `json:"chat_history,omitempty"`
	Scheme            *DesignScheme         `json:"scheme,omitempty"` // live-extracted design tokens of the proxied app
	URL               string                `json:"url"`
	ScreenshotPath    string                `json:"screenshot_path,omitempty"` // saved PNG of the live segment (dataURL stripped after save)
}

DesignRequest represents a request for new design alternatives.

type DesignScheme added in v0.13.24

type DesignScheme struct {
	Palette      []string          `json:"palette,omitempty"`       // frequency-ranked colors (hex/rgb)
	FontFamilies []string          `json:"font_families,omitempty"` // distinct font-family stacks
	FontSizes    []string          `json:"font_sizes,omitempty"`    // observed font-size ladder
	FontWeights  []string          `json:"font_weights,omitempty"`  // observed font weights
	Spacing      []string          `json:"spacing,omitempty"`       // observed margin/padding/gap steps
	Radius       []string          `json:"radius,omitempty"`        // observed border-radius values
	Shadows      []string          `json:"shadows,omitempty"`       // observed box-shadow samples
	CSSVars      map[string]string `json:"css_vars,omitempty"`      // declared --* custom properties
}

DesignScheme captures design tokens extracted live from the proxied target app so generated alternatives stay on-scheme (matching the app's palette, typography, spacing, and declared CSS variables). All fields are best-effort and omitted when extraction yields nothing.

type DesignState

type DesignState struct {
	ID           string                `json:"id"`
	Timestamp    time.Time             `json:"timestamp"`
	Selector     string                `json:"selector"` // CSS selector
	XPath        string                `json:"xpath"`    // XPath for robustness
	OriginalHTML string                `json:"original_html"`
	ContextHTML  string                `json:"context_html"` // Parent element with siblings for context
	Metadata     DesignElementMetadata `json:"metadata"`
	Scheme       *DesignScheme         `json:"scheme,omitempty"` // live-extracted design tokens of the proxied app
	URL          string                `json:"url"`
}

DesignState represents the initial state when an element is selected for design iteration.

type ElementCapture

type ElementCapture struct {
	ID        string    `json:"id"` // Reference ID for use in messages
	Timestamp time.Time `json:"timestamp"`
	URL       string    `json:"url"`
	Summary   string    `json:"summary"`  // Human-readable summary
	Selector  string    `json:"selector"` // CSS selector
	Tag       string    `json:"tag"`
	ElementID string    `json:"element_id,omitempty"` // DOM element id attribute
	Classes   []string  `json:"classes,omitempty"`
	Text      string    `json:"text,omitempty"` // Truncated text content
	Rect      struct {
		X      float64 `json:"x"`
		Y      float64 `json:"y"`
		Width  float64 `json:"width"`
		Height float64 `json:"height"`
	} `json:"rect,omitempty"`
}

ElementCapture represents an element capture from the panel with a reference ID.

type ErrorInjectionWriter

type ErrorInjectionWriter struct {
	// contains filtered or unexported fields
}

ErrorInjectionWriter wraps http.ResponseWriter to inject HTTP errors. Instead of proxying the actual response, it returns an error response.

func NewErrorInjectionWriter

func NewErrorInjectionWriter(w http.ResponseWriter, statusCode int, message string) *ErrorInjectionWriter

NewErrorInjectionWriter creates a new error injection writer

func (*ErrorInjectionWriter) Flush

func (ew *ErrorInjectionWriter) Flush()

Flush implements http.Flusher

func (*ErrorInjectionWriter) Header

func (ew *ErrorInjectionWriter) Header() http.Header

Header returns the header map

func (*ErrorInjectionWriter) Hijack

func (ew *ErrorInjectionWriter) Hijack() (net.Conn, *bufio.ReadWriter, error)

Hijack implements http.Hijacker

func (*ErrorInjectionWriter) StatusCode

func (ew *ErrorInjectionWriter) StatusCode() int

StatusCode returns the injected status code

func (*ErrorInjectionWriter) Write

func (ew *ErrorInjectionWriter) Write(p []byte) (int, error)

Write discards the actual response and writes the error message

func (*ErrorInjectionWriter) WriteHeader

func (ew *ErrorInjectionWriter) WriteHeader(statusCode int)

WriteHeader ignores the status code and writes the error status

type ExecutionResponse

type ExecutionResponse struct {
	ID        string        `json:"id"`
	Timestamp time.Time     `json:"timestamp"`
	ExecID    string        `json:"exec_id"` // Original execution ID
	Success   bool          `json:"success"`
	Result    string        `json:"result,omitempty"`
	Error     string        `json:"error,omitempty"`
	Duration  time.Duration `json:"duration"`
}

ExecutionResponse represents a response sent back to MCP client.

type ExecutionResult

type ExecutionResult struct {
	ID        string                 `json:"id"`
	Timestamp time.Time              `json:"timestamp"`
	Code      string                 `json:"code"`   // The code that was executed
	Result    string                 `json:"result"` // String representation of result
	Error     string                 `json:"error,omitempty"`
	Duration  time.Duration          `json:"duration"`
	URL       string                 `json:"url"`
	Data      map[string]interface{} `json:"data,omitempty"`
	FilePath  string                 `json:"file_path,omitempty"` // Path to file if result was too large
}

ExecutionResult represents the result of executing JavaScript.

type FrontendError

type FrontendError struct {
	ID        string    `json:"id"`
	Timestamp time.Time `json:"timestamp"`
	Message   string    `json:"message"`
	Source    string    `json:"source,omitempty"`
	LineNo    int       `json:"lineno,omitempty"`
	ColNo     int       `json:"colno,omitempty"`
	Error     string    `json:"error,omitempty"`
	Stack     string    `json:"stack,omitempty"`
	URL       string    `json:"url"` // Page URL where error occurred
}

FrontendError represents a JavaScript error from the frontend.

type HTTPLogEntry

type HTTPLogEntry struct {
	ID              string            `json:"id"`
	Timestamp       time.Time         `json:"timestamp"`
	Method          string            `json:"method"`
	URL             string            `json:"url"`
	RequestHeaders  map[string]string `json:"request_headers"`
	RequestBody     string            `json:"request_body,omitempty"`
	StatusCode      int               `json:"status_code"`
	ResponseHeaders map[string]string `json:"response_headers"`
	ResponseBody    string            `json:"response_body,omitempty"`
	Duration        time.Duration     `json:"duration"`
	Error           string            `json:"error,omitempty"`
	// Chaos marks a response the chaos engine synthesised (injected error
	// status / corruption) rather than one the backend actually produced.
	// Synthetic faults stay in the traffic log (proxylog query still surfaces
	// them) but are suppressed from the agent incident inbox so an injected
	// 500 is not mistaken for a real backend error. The swallow detector also
	// keys off this flag.
	Chaos bool `json:"chaos,omitempty"`
	// ChaosSwallowWatch is set when this injected fault should be watched by
	// the swallowed-error heuristic — i.e. chaos injected it AND the proxy's
	// runtime swallow-detect toggle (browser panel) was on. The daemon records
	// it as a pending fault; if no app-side error follows in the window it is
	// raised as a swallowed-error incident.
	ChaosSwallowWatch bool `json:"chaos_swallow_watch,omitempty"`
}

HTTPLogEntry represents a logged HTTP request/response pair.

type HookLogEntry added in v0.12.44

type HookLogEntry struct {
	Event       string          `json:"event"`
	Payload     json.RawMessage `json:"payload,omitempty"`
	SessionID   string          `json:"session_id,omitempty"`
	ProjectPath string          `json:"project_path,omitempty"`
	Agent       string          `json:"agent,omitempty"`
	ReceivedAt  time.Time       `json:"received_at"`
}

HookLogEntry is the proxy-package representation of a daemon HookEvent after it has been fanned out through BroadcastLogEntry as a unified LogEntry. The proxy package cannot import daemon (the import graph is daemon → proxy), so this struct mirrors the wire shape of HookEvent without introducing a cycle. Fields are flat by design — StreamSink consumers (monitor, get_errors) need direct access to event/payload/ session_id without unwrapping a nested map.

type InteractionEvent

type InteractionEvent struct {
	ID        string                 `json:"id"`
	Timestamp time.Time              `json:"timestamp"`
	EventType string                 `json:"event_type"` // click, dblclick, keydown, input, scroll, focus, blur, submit, contextmenu, mousemove
	Target    InteractionTarget      `json:"target"`
	Position  *InteractionPosition   `json:"position,omitempty"` // For mouse events
	Key       *KeyboardInfo          `json:"key,omitempty"`      // For keyboard events
	Value     string                 `json:"value,omitempty"`    // For input events (sanitized, no passwords)
	URL       string                 `json:"url"`
	Data      map[string]interface{} `json:"data,omitempty"` // Extra data (scroll_position, etc.)
}

InteractionEvent represents a user interaction (click, keyboard, etc.).

type InteractionPosition

type InteractionPosition struct {
	ClientX int `json:"client_x"`
	ClientY int `json:"client_y"`
	PageX   int `json:"page_x"`
	PageY   int `json:"page_y"`
}

InteractionPosition describes the mouse position during an interaction.

type InteractionTarget

type InteractionTarget struct {
	Selector   string            `json:"selector"`
	Tag        string            `json:"tag"`
	ID         string            `json:"id,omitempty"`
	Classes    []string          `json:"classes,omitempty"`
	Text       string            `json:"text,omitempty"`       // Truncated innerText
	Attributes map[string]string `json:"attributes,omitempty"` // Relevant attrs only (href, src, type, etc.)
}

InteractionTarget describes the DOM element that was interacted with.

type KeyboardInfo

type KeyboardInfo struct {
	Key   string `json:"key"`
	Code  string `json:"code"`
	Ctrl  bool   `json:"ctrl,omitempty"`
	Alt   bool   `json:"alt,omitempty"`
	Shift bool   `json:"shift,omitempty"`
	Meta  bool   `json:"meta,omitempty"`
}

KeyboardInfo describes keyboard event details.

type LogEntry

type LogEntry struct {
	Type LogEntryType `json:"type"`
	// FrameID attributes a browser-sourced entry to the content frame that
	// emitted it (the always-wrap model — docs/responsive-canonical-target.md
	// §5.2). Empty for server-sourced entries (HTTP) and for unframed/legacy
	// pages. Carried once on the envelope rather than on each typed payload.
	FrameID           string              `json:"frame_id,omitempty"`
	HTTP              *HTTPLogEntry       `json:"http,omitempty"`
	Error             *FrontendError      `json:"error,omitempty"`
	Performance       *PerformanceMetric  `json:"performance,omitempty"`
	Custom            *CustomLog          `json:"custom,omitempty"`
	Screenshot        *Screenshot         `json:"screenshot,omitempty"`
	Execution         *ExecutionResult    `json:"execution,omitempty"`
	Response          *ExecutionResponse  `json:"response,omitempty"`
	Interaction       *InteractionEvent   `json:"interaction,omitempty"`
	Mutation          *MutationEvent      `json:"mutation,omitempty"`
	PanelMessage      *PanelMessage       `json:"panel_message,omitempty"`
	Sketch            *SketchEntry        `json:"sketch,omitempty"`
	ScreenshotCapture *ScreenshotCapture  `json:"screenshot_capture,omitempty"`
	ElementCapture    *ElementCapture     `json:"element_capture,omitempty"`
	SketchCapture     *SketchCapture      `json:"sketch_capture,omitempty"`
	DesignState       *DesignState        `json:"design_state,omitempty"`
	DesignRequest     *DesignRequest      `json:"design_request,omitempty"`
	DesignChat        *DesignChat         `json:"design_chat,omitempty"`
	DesignEdit        *DesignEdit         `json:"design_edit,omitempty"`
	Walkthrough       *WalkthroughEntry   `json:"walkthrough,omitempty"`
	ResponsiveRequest *ResponsiveRequest  `json:"responsive_request,omitempty"`
	ResponsiveState   *ResponsiveState    `json:"responsive_state,omitempty"`
	Diagnostic        *ProxyDiagnostic    `json:"diagnostic,omitempty"`
	ProcessOutput     *ProcessOutputEvent `json:"process,omitempty"`
	Hook              *HookLogEntry       `json:"hook,omitempty"`
}

LogEntry is a union type for all log entry types.

type LogEntryType

type LogEntryType string

LogEntryType categorizes different types of log entries.

const (
	// LogTypeHTTP represents an HTTP request/response.
	LogTypeHTTP LogEntryType = "http"
	// LogTypeError represents a frontend JavaScript error.
	LogTypeError LogEntryType = "error"
	// LogTypePerformance represents frontend performance metrics.
	LogTypePerformance LogEntryType = "performance"
	// LogTypeCustom represents a custom log message from frontend.
	LogTypeCustom LogEntryType = "custom"
	// LogTypeScreenshot represents a screenshot capture.
	LogTypeScreenshot LogEntryType = "screenshot"
	// LogTypeExecution represents JavaScript execution result.
	LogTypeExecution LogEntryType = "execution"
	// LogTypeResponse represents JavaScript execution responses returned to MCP client.
	LogTypeResponse LogEntryType = "response"
	// LogTypeInteraction represents a user interaction event (click, keyboard, etc.).
	LogTypeInteraction LogEntryType = "interaction"
	// LogTypeMutation represents a DOM mutation event.
	LogTypeMutation LogEntryType = "mutation"
	// LogTypePanelMessage represents a message from the floating indicator panel.
	LogTypePanelMessage LogEntryType = "panel_message"
	// LogTypeSketch represents a sketch/wireframe from the sketch mode.
	LogTypeSketch LogEntryType = "sketch"
	// LogTypeScreenshotCapture represents an area capture with a reference ID.
	LogTypeScreenshotCapture LogEntryType = "screenshot_capture"
	// LogTypeElementCapture represents an element capture with a reference ID.
	LogTypeElementCapture LogEntryType = "element_capture"
	// LogTypeSketchCapture represents a sketch capture with a reference ID.
	LogTypeSketchCapture LogEntryType = "sketch_capture"
	// LogTypeDesignState represents the initial state when an element is selected for design iteration.
	LogTypeDesignState LogEntryType = "design_state"
	// LogTypeDesignRequest represents a request for new design alternatives.
	LogTypeDesignRequest LogEntryType = "design_request"
	// LogTypeDesignChat represents a chat message about the selected element.
	LogTypeDesignChat LogEntryType = "design_chat"
	// LogTypeDesignEdit represents a direct-manipulation geometry edit committed
	// on an existing element via the design-mode transform handles. Carries the
	// CSS selector plus the computed before→after delta for the agent to write
	// as a real source diff.
	LogTypeDesignEdit LogEntryType = "design_edit"
	// LogTypeWalkthrough represents a live-demo walkthrough lifecycle event
	// (start, step advance, manual nav, finish, stop) emitted by the chrome-frame
	// walkthrough panel. Lets the agent narrate live and react to where the user
	// is in the demo.
	LogTypeWalkthrough LogEntryType = "walkthrough"
	// LogTypeResponsiveRequest represents a handoff from responsive mode requesting agent fixes for layout shifts at a width.
	LogTypeResponsiveRequest LogEntryType = "responsive_request"
	// LogTypeResponsiveState represents the responsive mode panel state (current width + shift count).
	LogTypeResponsiveState LogEntryType = "responsive_state"
	// LogTypeDiagnostic represents a server-side diagnostic event (proxy errors, connection issues, etc.).
	LogTypeDiagnostic LogEntryType = "diagnostic"
	// LogTypeProcessOutput represents a line of process stdout/stderr output.
	LogTypeProcessOutput LogEntryType = "process"
	// LogTypeHook represents a Claude Code (or other agent) hook event
	// drained from the daemon's hook ring buffer. The payload carries the
	// raw hook JSON plus daemon-side provenance so StreamSink subscribers
	// can filter and display it via `agnt monitor --types hook`.
	LogTypeHook LogEntryType = "hook"
	// LogTypeIncidentDigest carries a periodic incident-inbox digest as a
	// synthetic stream entry. It is the cross-process transport for the
	// unified agent-inbound queue: the daemon broadcasts it over STREAM-EVENTS
	// and consumer processes (agnt mcp, agnt run) render it to the agent. The
	// compact digest text rides in Custom.Message; Custom.Level is the severity.
	LogTypeIncidentDigest LogEntryType = "incident_digest"
)

type LogFilter

type LogFilter struct {
	Types            []LogEntryType `json:"types,omitempty"`       // Filter by entry type
	Methods          []string       `json:"methods,omitempty"`     // HTTP methods
	URLPattern       string         `json:"url_pattern,omitempty"` // URL substring match
	StatusCodes      []int          `json:"status_codes,omitempty"`
	Since            *time.Time     `json:"since,omitempty"`
	Until            *time.Time     `json:"until,omitempty"`
	Limit            int            `json:"limit,omitempty"`             // Max results (0 = all)
	InteractionTypes []string       `json:"interaction_types,omitempty"` // click, keydown, scroll, etc.
	MutationTypes    []string       `json:"mutation_types,omitempty"`    // added, removed, attributes
	DiagnosticLevels []string       `json:"diagnostic_levels,omitempty"` // info, warning, error
	ErrorsOnly       bool           `json:"errors_only,omitempty"`       // Filter to errors from all sources
	Frames           []string       `json:"frames,omitempty"`            // Filter to entries from these content frame ids
}

LogFilter specifies criteria for querying logs.

func (LogFilter) Matches

func (f LogFilter) Matches(entry LogEntry) bool

Matches returns true if the entry matches the filter.

type LoggerStats

type LoggerStats struct {
	TotalEntries     int64 `json:"total_entries"`
	AvailableEntries int64 `json:"available_entries"`
	MaxSize          int64 `json:"max_size"`
	Dropped          int64 `json:"dropped"`
}

LoggerStats holds logger statistics.

type LoggingMode

type LoggingMode int32

LoggingMode defines how chaos events are logged

const (
	LoggingModeSilent      LoggingMode = 0 // No chaos-specific logging
	LoggingModeTesting     LoggingMode = 1 // Log session start/stop + stats
	LoggingModeCoordinated LoggingMode = 2 // Minimal logging
)

type MutationEvent

type MutationEvent struct {
	ID           string           `json:"id"`
	Timestamp    time.Time        `json:"timestamp"`
	MutationType string           `json:"mutation_type"` // added, removed, attributes, characterData
	Target       MutationTarget   `json:"target"`
	Added        []MutationNode   `json:"added,omitempty"`
	Removed      []MutationNode   `json:"removed,omitempty"`
	Attribute    *AttributeChange `json:"attribute,omitempty"`
	URL          string           `json:"url"`
	// TriggeredBy correlates this mutation to the user interaction that likely
	// caused it (the browser walks recent interaction history within a 500ms
	// window). Nil when no interaction preceded the mutation.
	TriggeredBy *MutationTrigger `json:"triggered_by,omitempty"`
}

MutationEvent represents a DOM mutation.

type MutationNode

type MutationNode struct {
	Selector string `json:"selector,omitempty"`
	Tag      string `json:"tag"`
	ID       string `json:"id,omitempty"`
	HTML     string `json:"html,omitempty"` // Truncated outerHTML
}

MutationNode describes a node that was added or removed.

type MutationTarget

type MutationTarget struct {
	Selector string `json:"selector"`
	Tag      string `json:"tag"`
	ID       string `json:"id,omitempty"`
}

MutationTarget describes the parent element where a mutation occurred.

type MutationTrigger added in v0.13.27

type MutationTrigger struct {
	Type      string `json:"type,omitempty"`      // interaction event type (click, keydown, ...)
	Timestamp int64  `json:"timestamp,omitempty"` // interaction time (ms epoch, browser clock)
	Latency   int64  `json:"latency,omitempty"`   // ms between interaction and mutation
	Target    string `json:"target,omitempty"`    // selector of the interaction target
}

MutationTrigger describes the user interaction the browser correlated to a DOM mutation (cause → effect), captured from the interaction history.

type OverlayEvent

type OverlayEvent struct {
	Type      string      `json:"type"`
	ProxyID   string      `json:"proxy_id"`
	Timestamp time.Time   `json:"timestamp"`
	Data      interface{} `json:"data"`
}

OverlayEvent represents an event to send to the overlay.

type OverlayNotifier

type OverlayNotifier struct {
	// contains filtered or unexported fields
}

OverlayNotifier sends events to the agent overlay server via Unix socket.

func NewOverlayNotifier

func NewOverlayNotifier() *OverlayNotifier

NewOverlayNotifier creates a new overlay notifier.

func (*OverlayNotifier) GetEndpoint

func (n *OverlayNotifier) GetEndpoint() string

GetEndpoint returns the current socket path.

func (*OverlayNotifier) IsEnabled

func (n *OverlayNotifier) IsEnabled() bool

IsEnabled returns whether the notifier is enabled.

func (*OverlayNotifier) NotifyBrowserError added in v0.12.36

func (n *OverlayNotifier) NotifyBrowserError(proxyID string, err FrontendError) error

NotifyBrowserError sends a browser JS error to the overlay for auto-forwarding.

func (*OverlayNotifier) NotifyCustom

func (n *OverlayNotifier) NotifyCustom(proxyID, eventType string, data interface{}) error

NotifyCustom sends a custom event to the overlay.

func (*OverlayNotifier) NotifyDesignChat

func (n *OverlayNotifier) NotifyDesignChat(proxyID string, chat *DesignChat) error

NotifyDesignChat sends a design chat message to the overlay.

func (*OverlayNotifier) NotifyDesignEdit added in v0.13.20

func (n *OverlayNotifier) NotifyDesignEdit(proxyID string, edit *DesignEdit) error

NotifyDesignEdit sends a committed design geometry edit to the overlay.

func (*OverlayNotifier) NotifyDesignRequest

func (n *OverlayNotifier) NotifyDesignRequest(proxyID string, request *DesignRequest) error

NotifyDesignRequest sends a design request to the overlay.

func (*OverlayNotifier) NotifyDesignState

func (n *OverlayNotifier) NotifyDesignState(proxyID string, state *DesignState) error

NotifyDesignState sends design state to the overlay.

func (*OverlayNotifier) NotifyHTTPError added in v0.12.36

func (n *OverlayNotifier) NotifyHTTPError(proxyID string, entry HTTPLogEntry) error

NotifyHTTPError sends an HTTP error (4xx/5xx) to the overlay for auto-forwarding.

func (*OverlayNotifier) NotifyInteraction

func (n *OverlayNotifier) NotifyInteraction(proxyID string, interaction *InteractionEvent) error

NotifyInteraction sends an interaction event to the overlay.

func (*OverlayNotifier) NotifyPanelMessage

func (n *OverlayNotifier) NotifyPanelMessage(proxyID string, msg *PanelMessage) error

NotifyPanelMessage sends a panel message to the overlay.

func (*OverlayNotifier) NotifyResponsiveRequest added in v0.13.20

func (n *OverlayNotifier) NotifyResponsiveRequest(proxyID string, request *ResponsiveRequest) error

NotifyResponsiveRequest sends a responsive mode handoff request to the overlay.

func (*OverlayNotifier) NotifyResponsiveState added in v0.13.20

func (n *OverlayNotifier) NotifyResponsiveState(proxyID string, state *ResponsiveState) error

NotifyResponsiveState sends responsive mode panel state to the overlay.

func (*OverlayNotifier) NotifySketch

func (n *OverlayNotifier) NotifySketch(proxyID string, sketch *SketchEntry) error

NotifySketch sends a sketch to the overlay.

func (*OverlayNotifier) SendKeyToOverlay

func (n *OverlayNotifier) SendKeyToOverlay(key string, ctrl, alt, shift bool) error

SendKeyToOverlay sends a key to the overlay.

func (*OverlayNotifier) SetEndpoint

func (n *OverlayNotifier) SetEndpoint(socketPath string)

SetEndpoint sets the overlay socket path. Example: "/run/user/1000/devtool-overlay.sock" or "\\.\pipe\devtool-overlay-user"

func (*OverlayNotifier) TypeToOverlay

func (n *OverlayNotifier) TypeToOverlay(text string, enter bool) error

TypeToOverlay sends a type command to the overlay. The overlay will inject this text into the PTY.

type PageSession

type PageSession struct {
	ID             string    `json:"id"`
	URL            string    `json:"url"`                       // Current/most recent URL
	BrowserSession string    `json:"browser_session,omitempty"` // Browser tab session ID (from cookie)
	PageTitle      string    `json:"page_title,omitempty"`
	StartTime      time.Time `json:"start_time"`
	LastActivity   time.Time `json:"last_activity"`
	Active         bool      `json:"active"`

	// Navigation history - all document requests in this tab session
	Navigations     []HTTPLogEntry     `json:"navigations,omitempty"`
	DocumentRequest *HTTPLogEntry      `json:"document_request,omitempty"` // Most recent document request (for backwards compat)
	Resources       []HTTPLogEntry     `json:"resources"`
	Errors          []FrontendError    `json:"errors,omitempty"`
	Performance     *PerformanceMetric `json:"performance,omitempty"`

	// User interaction tracking
	Interactions     []InteractionEvent `json:"interactions,omitempty"`
	InteractionCount int                `json:"interaction_count"` // Total count (may exceed slice length)

	// DOM mutation tracking
	Mutations     []MutationEvent `json:"mutations,omitempty"`
	MutationCount int             `json:"mutation_count"` // Total count (may exceed slice length)
}

PageSession represents a browser tab session and its navigation history. All navigations within the same browser tab are grouped together.

type PageSessionSummary added in v0.10.0

type PageSessionSummary struct {
	ID             string    `json:"id"`
	URL            string    `json:"url"`
	PageTitle      string    `json:"page_title,omitempty"`
	StartTime      time.Time `json:"start_time"`
	LastActivity   time.Time `json:"last_activity"`
	Active         bool      `json:"active"`
	ResourceCount  int       `json:"resource_count"`
	ErrorCount     int       `json:"error_count"`
	HasPerformance bool      `json:"has_performance"`
	LoadTimeMs     int64     `json:"load_time_ms,omitempty"`
	// Counts only, no detailed arrays
	InteractionCount int `json:"interaction_count"`
	MutationCount    int `json:"mutation_count"`
}

PageSessionSummary is a lightweight representation of a page session for list views. It omits detailed arrays (interactions, mutations, errors, resources) to reduce token usage.

type PageTracker

type PageTracker struct {
	// contains filtered or unexported fields
}

PageTracker tracks page sessions and groups requests by page.

Concurrency model: actor. One owner goroutine (run) has exclusive access to the state fields below — no mutex, no sync.Map. Public methods send closures over the ops channel; track methods are fire-and-forget with backpressure (blocking send, lossless), query methods wait for a reply. The single FIFO channel gives each caller read-your-writes ordering: a query enqueued after a track op observes its effect. Stop terminates the owner goroutine; after Stop, track ops are no-ops and queries return zero values.

func NewPageTracker

func NewPageTracker(maxSessions int, sessionTimeout time.Duration) *PageTracker

NewPageTracker creates a new page tracker and starts its owner goroutine. Call Stop when the tracker is no longer needed.

func (*PageTracker) Clear

func (pt *PageTracker) Clear()

Clear removes all page sessions.

func (*PageTracker) GetActiveSessionSummaries added in v0.10.0

func (pt *PageTracker) GetActiveSessionSummaries() []PageSessionSummary

GetActiveSessionSummaries returns lightweight summaries of active sessions. Use this for list views to avoid sending massive arrays of interactions/mutations.

func (*PageTracker) GetActiveSessions

func (pt *PageTracker) GetActiveSessions() []*PageSession

GetActiveSessions returns snapshot copies of all currently active page sessions, safe to read concurrently with tracking.

func (*PageTracker) GetSession

func (pt *PageTracker) GetSession(sessionID string) (*PageSession, bool)

GetSession returns a snapshot of a specific page session by ID.

func (*PageTracker) ResolveSession added in v0.8.0

func (pt *PageTracker) ResolveSession(browserSessionID, url string, frameID ...string) string

ResolveSession finds a session by browser session ID with URL fallback. An optional content-frame id is preferred when present (always-wrap model). Returns empty string if no session found.

func (*PageTracker) Stop added in v0.13.20

func (pt *PageTracker) Stop()

Stop terminates the owner goroutine. Idempotent. Pending and subsequent track ops are discarded; subsequent queries return zero values.

func (*PageTracker) TrackError

func (pt *PageTracker) TrackError(err FrontendError, browserSessionID string, frameID ...string)

TrackError associates a frontend error with a page session. browserSessionID is the unique ID from the browser tab's sessionStorage.

func (*PageTracker) TrackHTTPRequest

func (pt *PageTracker) TrackHTTPRequest(entry HTTPLogEntry)

TrackHTTPRequest processes an HTTP request and associates it with a page session.

func (*PageTracker) TrackInteraction

func (pt *PageTracker) TrackInteraction(interaction InteractionEvent, browserSessionID string, frameID ...string)

TrackInteraction associates a user interaction event with a page session. browserSessionID is the unique ID from the browser tab's sessionStorage.

func (*PageTracker) TrackMutation

func (pt *PageTracker) TrackMutation(mutation MutationEvent, browserSessionID string, frameID ...string)

TrackMutation associates a DOM mutation event with a page session. browserSessionID is the unique ID from the browser tab's sessionStorage.

func (*PageTracker) TrackPerformance

func (pt *PageTracker) TrackPerformance(perf PerformanceMetric, browserSessionID string, frameID ...string)

TrackPerformance associates performance metrics with a page session. browserSessionID is the unique ID from the browser tab's sessionStorage.

type PanelAttachment

type PanelAttachment struct {
	Type     string                 `json:"type"` // element, screenshot_area
	Selector string                 `json:"selector,omitempty"`
	Tag      string                 `json:"tag,omitempty"`
	ID       string                 `json:"id,omitempty"`
	Classes  []string               `json:"classes,omitempty"`
	Text     string                 `json:"text,omitempty"`
	Summary  string                 `json:"summary,omitempty"`
	FilePath string                 `json:"filePath,omitempty"` // Browser-side file path from capture_ack
	Area     *ScreenshotArea        `json:"area,omitempty"`
	Data     map[string]interface{} `json:"data,omitempty"`
}

PanelAttachment represents an attachment to a panel message.

type PanelMessage

type PanelMessage struct {
	ID                  string            `json:"id"`
	Timestamp           time.Time         `json:"timestamp"`
	Message             string            `json:"message"`
	Attachments         []PanelAttachment `json:"attachments,omitempty"`
	URL                 string            `json:"url"`
	RequestNotification bool              `json:"request_notification,omitempty"`
}

PanelMessage represents a message from the floating indicator panel.

type PerformanceMetric

type PerformanceMetric struct {
	ID                   string                 `json:"id"`
	Timestamp            time.Time              `json:"timestamp"`
	URL                  string                 `json:"url"` // Page URL
	NavigationStart      int64                  `json:"navigation_start,omitempty"`
	LoadEventEnd         int64                  `json:"load_event_end,omitempty"`
	DOMContentLoaded     int64                  `json:"dom_content_loaded,omitempty"`
	FirstPaint           int64                  `json:"first_paint,omitempty"`
	FirstContentfulPaint int64                  `json:"first_contentful_paint,omitempty"`
	Resources            []ResourceTiming       `json:"resources,omitempty"`
	Custom               map[string]interface{} `json:"custom,omitempty"`

	// Page context captured alongside the performance sample. PageTitle is the
	// document title (also copied onto the owning PageSession); the dimensions
	// are surfaced by the currentpage summary.
	PageTitle      string `json:"page_title,omitempty"`
	PageWidth      int    `json:"page_width,omitempty"`
	PageHeight     int    `json:"page_height,omitempty"`
	ViewportWidth  int    `json:"viewport_width,omitempty"`
	ViewportHeight int    `json:"viewport_height,omitempty"`
}

PerformanceMetric represents frontend performance data.

type ProcessOutputEvent added in v0.12.36

type ProcessOutputEvent struct {
	ProcessID string    `json:"process_id"`
	Stream    string    `json:"stream"`    // "stdout" or "stderr"
	Line      string    `json:"line"`      // Output line content (without trailing newline)
	Timestamp time.Time `json:"timestamp"` // When the line was received
}

ProcessOutputEvent represents a line of output from a managed process.

type ProxyConfig

type ProxyConfig struct {
	ID            string
	TargetURL     string
	ListenPort    int
	MaxLogSize    int
	AutoRestart   bool   // Enable automatic restart on crash (default: true)
	Path          string // Working directory where proxy was created
	BindAddress   string // Bind address: "127.0.0.1" (default, localhost only) or "0.0.0.0" (all interfaces)
	PublicURL     string // Optional public URL for tunnel services (e.g., "https://abc123.trycloudflare.com")
	AllowExternal bool   // Allow binding to non-localhost addresses (0.0.0.0, ::). Requires explicit opt-in for security.
	SkipTLSVerify bool   // Skip TLS certificate verification (default: false, verifies certs). Set true for self-signed/expired certs in dev.
	// StrictListenPort disables the silent :0 auto-assign fallback when
	// ListenPort is already in use. When true, a bind conflict surfaces
	// as a hard error from Start(). Used by autostart when a user
	// explicitly declares `listen-port` in .agnt.kdl — an explicit port
	// means "this port or nothing", not "this port or a random one".
	StrictListenPort bool
	Tunnel           *protocol.TunnelConfig

	// HealthCheckInterval controls how often the backend is probed.
	// Zero disables health checks. Default: 30s.
	HealthCheckInterval time.Duration
	// HealthFailThreshold is the number of consecutive failures before
	// marking the backend unhealthy and emitting a diagnostic event.
	// Default: 3.
	HealthFailThreshold int

	// AuthBreakout enables OAuth-flow breakout from the content iframe
	// (nil = off). Populated from the project's .agnt.kdl auth-breakout
	// block; may also be set post-create via SetAuthBreakout.
	AuthBreakout *AuthBreakout
}

ProxyConfig holds configuration for creating a proxy server.

type ProxyDiagnostic added in v0.11.3

type ProxyDiagnostic struct {
	Timestamp time.Time            `json:"timestamp"`
	Level     ProxyDiagnosticLevel `json:"level"`
	Category  string               `json:"category"` // "proxy", "connection", "request"
	Event     string               `json:"event"`    // "error", "timeout", "refused", etc.
	Message   string               `json:"message"`
	RequestID string               `json:"request_id,omitempty"`
	Method    string               `json:"method,omitempty"`
	URL       string               `json:"url,omitempty"`
	Target    string               `json:"target,omitempty"`
	Data      map[string]any       `json:"data,omitempty"`
}

ProxyDiagnostic represents a diagnostic event from the proxy server.

type ProxyDiagnosticLevel added in v0.11.3

type ProxyDiagnosticLevel string

ProxyDiagnosticLevel indicates the severity of a diagnostic event.

const (
	DiagnosticInfo    ProxyDiagnosticLevel = "info"
	DiagnosticWarning ProxyDiagnosticLevel = "warning"
	DiagnosticError   ProxyDiagnosticLevel = "error"
)

type ProxyManager

type ProxyManager struct {
	// contains filtered or unexported fields
}

ProxyManager manages multiple reverse proxy servers with lock-free access.

func NewProxyManager

func NewProxyManager() *ProxyManager

NewProxyManager creates a new proxy manager.

func (*ProxyManager) ActiveCount

func (pm *ProxyManager) ActiveCount() int64

ActiveCount returns the number of running proxies.

func (*ProxyManager) Create

func (pm *ProxyManager) Create(ctx context.Context, config ProxyConfig) (*ProxyServer, error)

Create creates and starts a new proxy server.

func (*ProxyManager) Get

func (pm *ProxyManager) Get(id string) (*ProxyServer, error)

Get retrieves a proxy by ID with fuzzy matching support. First tries exact match, then looks for proxies where the ID contains the search string as a component (for compound IDs like "project:name:host-port").

func (*ProxyManager) GetWithPathFilter added in v0.8.0

func (pm *ProxyManager) GetWithPathFilter(id, pathFilter string) (*ProxyServer, error)

GetWithPathFilter retrieves a proxy by ID with fuzzy matching, filtered by path. If pathFilter is non-empty, only proxies with matching Path are considered for fuzzy lookup. Exact matches are always returned regardless of path filter.

func (*ProxyManager) ListScoped added in v0.13.20

func (pm *ProxyManager) ListScoped(s scope.Scope) []*ProxyServer

ListScoped returns the managed proxy servers visible to the given scope. A project scope returns only that project's proxies; an unscoped scope returns all of them. The zero scope returns nothing — callers must build a scope explicitly, which keeps cross-project access deliberate rather than the silent default. This replaces the old unscoped List().

func (*ProxyManager) Shutdown

func (pm *ProxyManager) Shutdown(ctx context.Context) error

Shutdown stops all managed proxies.

func (*ProxyManager) Stop

func (pm *ProxyManager) Stop(ctx context.Context, id string) error

Stop stops a proxy server and removes it from the registry.

func (*ProxyManager) StopAll added in v0.7.6

func (pm *ProxyManager) StopAll(ctx context.Context) ([]string, error)

StopAll stops all running proxies and removes them from the registry. Unlike Shutdown, this does NOT set shuttingDown flag, allowing new proxies to be started afterward. This is used for cleanup when the last client disconnects. Returns the list of stopped proxy IDs for state persistence cleanup.

func (*ProxyManager) StopByProjectPath added in v0.7.8

func (pm *ProxyManager) StopByProjectPath(ctx context.Context, projectPath string) ([]string, error)

StopByProjectPath stops all running proxies for a specific project path and removes them. This is used for session-scoped cleanup when a client disconnects. Returns the list of stopped proxy IDs.

func (*ProxyManager) TotalStarted

func (pm *ProxyManager) TotalStarted() int64

TotalStarted returns the total number of proxies ever started.

type ProxyServer

type ProxyServer struct {
	ID            string
	TargetURL     *url.URL
	ListenAddr    string
	Path          string
	BindAddress   string // Bind address used (127.0.0.1 or 0.0.0.0)
	AllowExternal bool   // Whether external binding was explicitly allowed
	// StrictListenPort, when true, disables the silent :0 auto-assign
	// fallback in Start(). A bind failure on the requested listen port
	// becomes a hard error instead of being papered over with a random
	// port. Set by callers that hand us an explicit listen port (e.g.
	// autostart with .agnt.kdl `listen-port`).
	StrictListenPort bool
	PublicURL        string // Optional public URL for tunnel services
	// contains filtered or unexported fields
}

ProxyServer is a reverse proxy that logs traffic and injects instrumentation.

func NewProxyServer

func NewProxyServer(config ProxyConfig) (*ProxyServer, error)

NewProxyServer creates a new reverse proxy server.

func (*ProxyServer) ActiveFrame added in v0.13.22

func (ps *ProxyServer) ActiveFrame() string

ActiveFrame returns the last content frame reported active, or "" if none.

func (*ProxyServer) AuthBreakoutRules added in v0.13.34

func (ps *ProxyServer) AuthBreakoutRules() *AuthBreakout

AuthBreakoutRules returns the active OAuth-breakout rules, or nil.

func (*ProxyServer) BoundPort added in v0.13.26

func (ps *ProxyServer) BoundPort() int

BoundPort returns the TCP port the proxy is actually listening on, parsed from ListenAddr (which Start updates to the real bound address, including the OS-assigned port when ListenPort was 0). Returns 0 if the address has no parseable port. Callers restarting a proxy use this to rebind the same port rather than letting it drift to a fresh auto-assignment.

func (*ProxyServer) BroadcastActivityState

func (ps *ProxyServer) BroadcastActivityState(active bool) int

BroadcastActivityState sends an activity state update to all connected browser clients. Returns the number of clients that received the update.

func (*ProxyServer) BroadcastChaosState added in v0.13.20

func (ps *ProxyServer) BroadcastChaosState() int

BroadcastChaosState pushes the current chaos engine state to all connected browser clients. Wired to ChaosEngine.onChange so MCP/hub-driven changes reach the indicator UI too. Returns the number of clients reached.

func (*ProxyServer) BroadcastOutputPreview added in v0.8.0

func (ps *ProxyServer) BroadcastOutputPreview(lines []string) int

BroadcastOutputPreview sends output preview lines to all connected browser clients. Returns the number of clients that received the preview.

func (*ProxyServer) BroadcastProxyDiagnostic added in v0.11.3

func (ps *ProxyServer) BroadcastProxyDiagnostic(diag *ProxyDiagnostic) int

BroadcastProxyDiagnostic sends a diagnostic event to all connected browser clients. This allows the browser to receive server-side proxy errors for debugging. Returns the number of clients that received the diagnostic.

func (*ProxyServer) BroadcastToast

func (ps *ProxyServer) BroadcastToast(toastType, title, message string, duration int) (int, error)

BroadcastToast sends a toast notification to all connected browser clients. Returns the number of clients that received the toast.

func (*ProxyServer) CancelExecution added in v0.13.28

func (ps *ProxyServer) CancelExecution(execID string)

CancelExecution drops a pending execution whose caller has given up waiting (e.g. a hub-side timeout). Without it the pendingExecs entry and its result channel leak forever when the browser never replies — common when the target page navigates or reloads mid-exec. Safe against the ws_handler delivery race: LoadAndDelete is atomic, so exactly one of cancel/deliver wins.

func (*ProxyServer) ChaosEngine

func (ps *ProxyServer) ChaosEngine() *ChaosEngine

ChaosEngine returns the chaos engine for this proxy server.

func (*ProxyServer) ExecuteJavaScript

func (ps *ProxyServer) ExecuteJavaScript(code string, frameID ...string) (string, <-chan *ExecutionResult, error)

ExecuteJavaScript sends JavaScript code to connected clients for execution. Returns the execution ID and a channel that will receive the result. An optional frameID targets a specific content frame; when empty it defaults to the active content frame (always-wrap model — docs/responsive-canonical- target.md §5.3). When both are empty the exec is untargeted and every connected (content) frame runs it (legacy behaviour).

func (*ProxyServer) FlushConnections added in v0.12.8

func (ps *ProxyServer) FlushConnections()

FlushConnections replaces the transport to kill both idle and in-flight connections to the backend. Call this when the backend restarts so requests don't hang on half-open TCP connections waiting for the OS timeout.

func (*ProxyServer) HasOverlayEndpoint added in v0.12.36

func (ps *ProxyServer) HasOverlayEndpoint() bool

HasOverlayEndpoint returns true if this proxy has an overlay endpoint bound.

func (*ProxyServer) HasTunnel

func (ps *ProxyServer) HasTunnel() bool

HasTunnel returns true if a tunnel is configured.

func (*ProxyServer) IsReadyForForwarding added in v0.12.43

func (ps *ProxyServer) IsReadyForForwarding() bool

IsReadyForForwarding returns true when the readiness gate is open (no pending dependencies). This is separate from IsRunning, which only reports whether the underlying HTTP server is serving connections — a running proxy may still be gated.

func (*ProxyServer) IsRunning

func (ps *ProxyServer) IsRunning() bool

IsRunning returns true if the proxy is running.

func (*ProxyServer) IsTunnelRunning

func (ps *ProxyServer) IsTunnelRunning() bool

IsTunnelRunning returns true if the tunnel is currently running.

func (*ProxyServer) Logger

func (ps *ProxyServer) Logger() *TrafficLogger

Logger returns the traffic logger.

func (*ProxyServer) LookupCapture added in v0.11.4

func (ps *ProxyServer) LookupCapture(name string) string

LookupCapture returns the file path for a named screenshot, or empty string if not found. Entries are deleted after lookup — consumed once by the MCP tool handler.

func (*ProxyServer) MarkDependencyReady added in v0.12.43

func (ps *ProxyServer) MarkDependencyReady(dep string) (openedNow bool)

MarkDependencyReady removes dep from the pending set. Returns true when the call transitions the gate from closed to open, so the caller can fire a one-shot proxy_ready event.

func (*ProxyServer) OverlayNotifier

func (ps *ProxyServer) OverlayNotifier() *OverlayNotifier

OverlayNotifier returns the overlay notifier for direct access.

func (*ProxyServer) PageTracker

func (ps *ProxyServer) PageTracker() *PageTracker

PageTracker returns the page tracker for this proxy server.

func (*ProxyServer) PendingDependencies added in v0.12.43

func (ps *ProxyServer) PendingDependencies() []string

PendingDependencies returns the sorted list of dependencies the proxy is still waiting on. Returns an empty slice when the gate is open. Callers may modify the returned slice safely.

func (*ProxyServer) Ready

func (ps *ProxyServer) Ready() <-chan struct{}

Ready returns a channel that is closed when the server is ready to accept connections. Use this to wait for server readiness instead of polling or sleeping.

func (*ProxyServer) SetActiveFrame added in v0.13.22

func (ps *ProxyServer) SetActiveFrame(frameID string)

SetActiveFrame records the content frame the page reported as active. Empty frameID is ignored (a report must name a frame).

func (*ProxyServer) SetAuthBreakout added in v0.13.34

func (ps *ProxyServer) SetAuthBreakout(ab *AuthBreakout)

SetAuthBreakout installs (or clears, with nil) the OAuth-breakout rules. Safe to call while the proxy is serving.

func (*ProxyServer) SetDependencies added in v0.12.43

func (ps *ProxyServer) SetDependencies(deps []string)

SetDependencies registers the set of dependency names the proxy must wait on before it begins forwarding requests. Passing an empty or nil slice opens the gate immediately. See readiness.go for the full contract.

func (*ProxyServer) SetOverlayEndpoint

func (ps *ProxyServer) SetOverlayEndpoint(endpoint string)

SetOverlayEndpoint configures the overlay endpoint for forwarding events. Example: "http://127.0.0.1:19191"

func (*ProxyServer) SetPublicURL

func (ps *ProxyServer) SetPublicURL(publicURL string)

SetPublicURL sets the public URL for tunnel services. This URL is used for URL rewriting when behind a tunnel. Example: "https://abc123.trycloudflare.com"

func (*ProxyServer) SetSessionClientFactory added in v0.7.0

func (ps *ProxyServer) SetSessionClientFactory(factory SessionClientFactory)

SetSessionClientFactory sets the factory for creating session clients. This is used by the browser session API to communicate with the daemon.

func (*ProxyServer) Start

func (ps *ProxyServer) Start(ctx context.Context) error

Start begins the proxy server.

func (*ProxyServer) Stats

func (ps *ProxyServer) Stats() ProxyStats

Stats returns proxy statistics.

func (*ProxyServer) Stop

func (ps *ProxyServer) Stop(ctx context.Context) error

Stop gracefully stops the proxy server.

func (*ProxyServer) StopChaos added in v0.12.51

func (ps *ProxyServer) StopChaos()

StopChaos stops the chaos engine's background goroutines. Called by runServer's defer for started servers. Tests that create a ProxyServer without calling Start must call this directly in their cleanup.

func (*ProxyServer) TunnelURL

func (ps *ProxyServer) TunnelURL() string

TunnelURL returns the public tunnel URL if a tunnel is running.

type ProxyStats

type ProxyStats struct {
	ID            string        `json:"id"`
	TargetURL     string        `json:"target_url"`
	ListenAddr    string        `json:"listen_addr"`
	Path          string        `json:"path,omitempty"`         // Working directory where proxy was created
	BindAddress   string        `json:"bind_address,omitempty"` // Bind address (127.0.0.1 or 0.0.0.0)
	PublicURL     string        `json:"public_url,omitempty"`   // Public URL for tunnels
	Running       bool          `json:"running"`
	Uptime        time.Duration `json:"uptime"`
	TotalRequests int64         `json:"total_requests"`
	LoggerStats   LoggerStats   `json:"logger_stats"`
	LastError     string        `json:"last_error,omitempty"` // Set if server crashed
	RestartCount  int           `json:"restart_count"`        // Number of restarts in current window
	AutoRestart   bool          `json:"auto_restart"`         // Whether auto-restart is enabled

	// Backend health probe state
	BackendHealthy      bool      `json:"backend_healthy"`                // false after consecutive probe failures
	LastHealthCheck     time.Time `json:"last_health_check,omitempty"`    // time of last probe
	ConsecutiveFailures int32     `json:"consecutive_failures,omitempty"` // current consecutive failure count

	// Restart backoff
	BackoffDelay time.Duration `json:"backoff_delay,omitempty"` // current backoff base duration (0 = no backoff active)

	// Readiness gate (wait-for dependencies). ReadyForForwarding is
	// false while the proxy is gating on declared script dependencies;
	// WaitingFor holds the sorted list of pending dep names. An empty
	// WaitingFor with ReadyForForwarding=true is the normal running case.
	ReadyForForwarding bool     `json:"ready_for_forwarding"`
	WaitingFor         []string `json:"waiting_for,omitempty"`
}

ProxyStats holds proxy statistics.

type ReadinessBody added in v0.12.43

type ReadinessBody struct {
	Error        string   `json:"error"`
	Message      string   `json:"message"`
	Pending      []string `json:"pending"`
	RetryAfterMs int      `json:"retry_after_ms"`
}

ReadinessBody is the JSON payload returned when the gate is closed. Kept as a struct so the shape is self-documenting and so tests can unmarshal it without resorting to map[string]interface{}.

type ReorderQueue

type ReorderQueue struct {
	// contains filtered or unexported fields
}

ReorderQueue holds requests and releases them in shuffled order to simulate out-of-order response delivery

func NewReorderQueue

func NewReorderQueue(engine *ChaosEngine) *ReorderQueue

NewReorderQueue creates a new reorder queue

func (*ReorderQueue) PendingCount

func (rq *ReorderQueue) PendingCount() int

PendingCount returns the number of pending requests

func (*ReorderQueue) Stop

func (rq *ReorderQueue) Stop()

Stop stops the reorder queue and releases any pending requests

func (*ReorderQueue) Submit

func (rq *ReorderQueue) Submit(req *http.Request, transport http.RoundTripper, rules []*ChaosRule) (*http.Response, error)

Submit adds a request to the reorder queue and waits for its response

type ResourceTiming

type ResourceTiming struct {
	Name     string `json:"name"`
	Duration int64  `json:"duration"`
	Size     int64  `json:"size,omitempty"`
}

ResourceTiming represents timing for a single resource.

type ResponsiveRequest added in v0.13.20

type ResponsiveRequest struct {
	ID        string                   `json:"id"`
	Timestamp time.Time                `json:"timestamp"`
	URL       string                   `json:"url"`
	Width     int                      `json:"width"`
	Shifts    []map[string]interface{} `json:"shifts,omitempty"`    // layout-shift findings (id/type/severity/selector/message/width/isNew)
	Selectors []map[string]interface{} `json:"selectors,omitempty"` // flat {id, selector} list for quick targeting
}

ResponsiveRequest represents a handoff from responsive mode asking the agent to fix the layout shifts detected at a particular viewport width.

type ResponsiveState added in v0.13.20

type ResponsiveState struct {
	ID         string    `json:"id"`
	Timestamp  time.Time `json:"timestamp"`
	URL        string    `json:"url"`
	Width      int       `json:"width"`
	ShiftCount int       `json:"shift_count"`
}

ResponsiveState represents the responsive mode panel state at a settled width.

type Screenshot

type Screenshot struct {
	ID        string    `json:"id"`
	Timestamp time.Time `json:"timestamp"`
	Name      string    `json:"name"`
	FilePath  string    `json:"file_path"` // Path to saved screenshot file
	URL       string    `json:"url"`       // Page URL where screenshot was taken
	Width     int       `json:"width"`
	Height    int       `json:"height"`
	Format    string    `json:"format"`   // png, jpeg
	Selector  string    `json:"selector"` // CSS selector for element (or "body" for full page)
	Error     string    `json:"error,omitempty"`
}

Screenshot represents a captured screenshot.

type ScreenshotArea

type ScreenshotArea struct {
	X      int    `json:"x"`
	Y      int    `json:"y"`
	Width  int    `json:"width"`
	Height int    `json:"height"`
	Data   string `json:"data,omitempty"` // Base64 image data
}

ScreenshotArea represents a selected area for screenshot.

type ScreenshotCapture

type ScreenshotCapture struct {
	ID        string    `json:"id"` // Reference ID for use in messages
	Timestamp time.Time `json:"timestamp"`
	URL       string    `json:"url"`
	Summary   string    `json:"summary"`    // Human-readable summary
	ImageData string    `json:"image_data"` // Base64 PNG data (cleared after save)
	FilePath  string    `json:"file_path"`  // Path to saved image file
	Area      struct {
		X      int `json:"x"`
		Y      int `json:"y"`
		Width  int `json:"width"`
		Height int `json:"height"`
	} `json:"area"`
}

ScreenshotCapture represents an area capture from the panel with a reference ID.

type SessionClient added in v0.7.0

type SessionClient interface {
	SessionList(dirFilter protocol.DirectoryFilter) (map[string]interface{}, error)
	SessionGet(code string) (map[string]interface{}, error)
	SessionSend(code string, message string) (map[string]interface{}, error)
	SessionSchedule(code string, duration string, message string) (map[string]interface{}, error)
	SessionTasks(dirFilter protocol.DirectoryFilter) (map[string]interface{}, error)
	SessionCancel(taskID string) error
	StoreGet(req protocol.StoreGetRequest) (map[string]interface{}, error)
	StoreSet(req protocol.StoreSetRequest) error
	StoreDelete(req protocol.StoreDeleteRequest) error
	StoreList(req protocol.StoreListRequest) (map[string]interface{}, error)
	StoreClear(req protocol.StoreClearRequest) error
	StoreGetAll(req protocol.StoreGetAllRequest) (map[string]interface{}, error)
	Close() error
}

SessionClient defines the interface for session operations. This interface is implemented by daemon.Client to avoid import cycles.

type SessionClientFactory added in v0.7.0

type SessionClientFactory func() (SessionClient, error)

SessionClientFactory is a function that creates a new SessionClient. This is used to avoid import cycles by having the daemon package provide the factory.

type SketchCapture

type SketchCapture struct {
	ID           string                 `json:"id"` // Reference ID for use in messages
	Timestamp    time.Time              `json:"timestamp"`
	URL          string                 `json:"url"`
	Summary      string                 `json:"summary"` // Human-readable summary
	ElementCount int                    `json:"element_count"`
	Sketch       map[string]interface{} `json:"sketch,omitempty"` // Sketch data
	ImageData    string                 `json:"image_data,omitempty"`
	FilePath     string                 `json:"file_path,omitempty"`
}

SketchCapture represents a sketch capture from the panel with a reference ID.

type SketchEntry

type SketchEntry struct {
	ID           string                 `json:"id"`
	Timestamp    time.Time              `json:"timestamp"`
	URL          string                 `json:"url"`
	Description  string                 `json:"description"`   // User description of the wireframe
	Sketch       map[string]interface{} `json:"sketch"`        // JSON-serialized sketch data
	ImageData    string                 `json:"image_data"`    // Base64 PNG of the sketch
	FilePath     string                 `json:"file_path"`     // Path to saved image file
	ElementCount int                    `json:"element_count"` // Number of elements in sketch
}

SketchEntry represents a sketch/wireframe from sketch mode.

type SlowDripWriter

type SlowDripWriter struct {
	// contains filtered or unexported fields
}

SlowDripWriter wraps http.ResponseWriter to stream bytes with delays. This simulates slow network connections or bandwidth throttling.

func NewSlowDripWriter

func NewSlowDripWriter(w http.ResponseWriter, bytesPerMs, chunkSize int, ctx context.Context) *SlowDripWriter

NewSlowDripWriter creates a new slow-drip writer

func (*SlowDripWriter) BytesWritten

func (sdw *SlowDripWriter) BytesWritten() int64

BytesWritten returns the total bytes written

func (*SlowDripWriter) Flush

func (sdw *SlowDripWriter) Flush()

Flush implements http.Flusher

func (*SlowDripWriter) Header

func (sdw *SlowDripWriter) Header() http.Header

Header returns the header map

func (*SlowDripWriter) Hijack

func (sdw *SlowDripWriter) Hijack() (net.Conn, *bufio.ReadWriter, error)

Hijack implements http.Hijacker

func (*SlowDripWriter) Write

func (sdw *SlowDripWriter) Write(p []byte) (int, error)

Write writes data with delays between chunks

func (*SlowDripWriter) WriteHeader

func (sdw *SlowDripWriter) WriteHeader(statusCode int)

WriteHeader sends the HTTP response header with the provided status code

type TLSFallbackTransport added in v0.12.47

type TLSFallbackTransport struct {
	// contains filtered or unexported fields
}

TLSFallbackTransport wraps an http.RoundTripper. On the first request that fails with a TLS certificate verification error (self-signed, unknown CA, hostname mismatch), it upgrades to an insecure transport, calls onCertSkipped once, and retries. Subsequent requests use the insecure transport directly.

This allows the proxy to transparently handle dev servers with self-signed certs without requiring skip-tls-verify in config, while still surfacing a visible warning via the onCertSkipped callback.

func NewTLSFallbackTransport added in v0.12.47

func NewTLSFallbackTransport(base *http.Transport, onSkipped func(certErr error)) *TLSFallbackTransport

NewTLSFallbackTransport creates a TLSFallbackTransport. base must be an *http.Transport (cloned from http.DefaultTransport); onSkipped is called exactly once when TLS verification is first bypassed.

func (*TLSFallbackTransport) RoundTrip added in v0.12.47

func (t *TLSFallbackTransport) RoundTrip(req *http.Request) (*http.Response, error)

RoundTrip implements http.RoundTripper. When TLS cert verification fails and the target looks like a dev server (any HTTPS), it retries without verification and fires onSkipped.

type TrafficLogger

type TrafficLogger struct {
	// contains filtered or unexported fields
}

TrafficLogger stores proxy traffic logs with bounded memory.

func NewTrafficLogger

func NewTrafficLogger(maxSize int) *TrafficLogger

NewTrafficLogger creates a new logger with specified max entries.

func (*TrafficLogger) Clear

func (tl *TrafficLogger) Clear()

Clear removes all log entries.

func (*TrafficLogger) LogCustom

func (tl *TrafficLogger) LogCustom(entry CustomLog, frameID ...string)

LogCustom adds a custom log message.

func (*TrafficLogger) LogDesignChat

func (tl *TrafficLogger) LogDesignChat(entry DesignChat)

LogDesignChat adds a design chat entry.

func (*TrafficLogger) LogDesignEdit added in v0.13.20

func (tl *TrafficLogger) LogDesignEdit(entry DesignEdit)

LogDesignEdit adds a design geometry-edit entry.

func (*TrafficLogger) LogDesignRequest

func (tl *TrafficLogger) LogDesignRequest(entry DesignRequest)

LogDesignRequest adds a design request entry.

func (*TrafficLogger) LogDesignState

func (tl *TrafficLogger) LogDesignState(entry DesignState)

LogDesignState adds a design state entry.

func (*TrafficLogger) LogDiagnostic added in v0.11.3

func (tl *TrafficLogger) LogDiagnostic(entry ProxyDiagnostic)

LogDiagnostic adds a server-side diagnostic event.

func (*TrafficLogger) LogElementCapture

func (tl *TrafficLogger) LogElementCapture(entry ElementCapture)

LogElementCapture adds an element capture entry.

func (*TrafficLogger) LogError

func (tl *TrafficLogger) LogError(entry FrontendError, frameID ...string)

LogError adds a frontend error log entry. Optional frameID attributes it to the emitting content frame.

func (*TrafficLogger) LogExecution

func (tl *TrafficLogger) LogExecution(entry ExecutionResult)

LogExecution adds a JavaScript execution result.

func (*TrafficLogger) LogHTTP

func (tl *TrafficLogger) LogHTTP(entry HTTPLogEntry)

LogHTTP adds an HTTP request/response log entry.

func (*TrafficLogger) LogInteraction

func (tl *TrafficLogger) LogInteraction(entry InteractionEvent, frameID ...string)

LogInteraction adds a user interaction event.

func (*TrafficLogger) LogMutation

func (tl *TrafficLogger) LogMutation(entry MutationEvent, frameID ...string)

LogMutation adds a DOM mutation event.

func (*TrafficLogger) LogPanelMessage

func (tl *TrafficLogger) LogPanelMessage(entry PanelMessage)

LogPanelMessage adds a panel message entry.

func (*TrafficLogger) LogPerformance

func (tl *TrafficLogger) LogPerformance(entry PerformanceMetric, frameID ...string)

LogPerformance adds a frontend performance log entry.

func (*TrafficLogger) LogResponse

func (tl *TrafficLogger) LogResponse(entry ExecutionResponse)

LogResponse adds an execution response sent to MCP client.

func (*TrafficLogger) LogResponsiveRequest added in v0.13.20

func (tl *TrafficLogger) LogResponsiveRequest(entry ResponsiveRequest)

LogResponsiveRequest adds a responsive mode handoff request entry.

func (*TrafficLogger) LogResponsiveState added in v0.13.20

func (tl *TrafficLogger) LogResponsiveState(entry ResponsiveState)

LogResponsiveState adds a responsive mode state entry.

func (*TrafficLogger) LogScreenshot

func (tl *TrafficLogger) LogScreenshot(entry Screenshot)

LogScreenshot adds a screenshot log entry.

func (*TrafficLogger) LogScreenshotCapture

func (tl *TrafficLogger) LogScreenshotCapture(entry ScreenshotCapture)

LogScreenshotCapture adds a screenshot capture entry.

func (*TrafficLogger) LogSketch

func (tl *TrafficLogger) LogSketch(entry SketchEntry)

LogSketch adds a sketch entry.

func (*TrafficLogger) LogSketchCapture

func (tl *TrafficLogger) LogSketchCapture(entry SketchCapture)

LogSketchCapture adds a sketch capture entry.

func (*TrafficLogger) LogWalkthrough added in v0.13.24

func (tl *TrafficLogger) LogWalkthrough(entry WalkthroughEntry)

LogWalkthrough adds a walkthrough (live-demo) lifecycle entry.

func (*TrafficLogger) Query

func (tl *TrafficLogger) Query(filter LogFilter) []LogEntry

Query retrieves log entries matching the filter in chronological order.

func (*TrafficLogger) SetOnLogEntry added in v0.12.36

func (tl *TrafficLogger) SetOnLogEntry(fn func(LogEntry))

SetOnLogEntry sets a callback fired after each log entry. The callback must not block — use a buffered channel if forwarding.

func (*TrafficLogger) Stats

func (tl *TrafficLogger) Stats() LoggerStats

Stats returns logger statistics.

type TruncationWriter

type TruncationWriter struct {
	// contains filtered or unexported fields
}

TruncationWriter wraps http.ResponseWriter to truncate response body. This simulates partial responses, incomplete downloads, or data loss.

func NewTruncationWriter

func NewTruncationWriter(w http.ResponseWriter, truncatePercent float64, expectedSize int64) *TruncationWriter

NewTruncationWriter creates a new truncation writer

func (*TruncationWriter) BytesWritten

func (tw *TruncationWriter) BytesWritten() int64

BytesWritten returns total bytes written

func (*TruncationWriter) Flush

func (tw *TruncationWriter) Flush()

Flush implements http.Flusher

func (*TruncationWriter) Header

func (tw *TruncationWriter) Header() http.Header

Header returns the header map

func (*TruncationWriter) Hijack

func (tw *TruncationWriter) Hijack() (net.Conn, *bufio.ReadWriter, error)

Hijack implements http.Hijacker

func (*TruncationWriter) IsTruncated

func (tw *TruncationWriter) IsTruncated() bool

IsTruncated returns whether the response was truncated

func (*TruncationWriter) MaxBytes

func (tw *TruncationWriter) MaxBytes() int64

MaxBytes returns the maximum bytes limit

func (*TruncationWriter) Write

func (tw *TruncationWriter) Write(p []byte) (int, error)

Write writes data up to the truncation limit

func (*TruncationWriter) WriteHeader

func (tw *TruncationWriter) WriteHeader(statusCode int)

WriteHeader sends the HTTP response header

type TunnelManager

type TunnelManager struct {
	// contains filtered or unexported fields
}

TunnelManager manages a tunnel process alongside a proxy.

func NewTunnelManager

func NewTunnelManager(config *protocol.TunnelConfig, proxyPort int) *TunnelManager

NewTunnelManager creates a new tunnel manager.

func (*TunnelManager) IsRunning

func (tm *TunnelManager) IsRunning() bool

IsRunning returns whether the tunnel is running.

func (*TunnelManager) PublicURL

func (tm *TunnelManager) PublicURL() string

PublicURL returns the detected public URL.

func (*TunnelManager) RecentOutput

func (tm *TunnelManager) RecentOutput() []string

RecentOutput returns recent output lines for debugging.

func (*TunnelManager) Start

func (tm *TunnelManager) Start(ctx context.Context) error

Start starts the tunnel process.

func (*TunnelManager) Stop

func (tm *TunnelManager) Stop() error

Stop stops the tunnel process.

func (*TunnelManager) WaitForURL

func (tm *TunnelManager) WaitForURL(timeout time.Duration) (string, error)

WaitForURL waits for the public URL to be detected with a timeout.

type VoiceSession

type VoiceSession struct {
	// contains filtered or unexported fields
}

VoiceSession manages a single voice transcription session between browser and Deepgram.

func NewVoiceSession

func NewVoiceSession(id string, browserConn wsJSONWriter, config DeepgramConfig) (*VoiceSession, error)

NewVoiceSession creates a new voice session and connects to Deepgram.

func (*VoiceSession) Close

func (vs *VoiceSession) Close()

Close terminates the voice session.

func (*VoiceSession) SendAudio

func (vs *VoiceSession) SendAudio(data []byte) error

SendAudio forwards audio data to Deepgram.

type VoiceTranscript

type VoiceTranscript struct {
	Type       string  `json:"type"`
	Transcript string  `json:"transcript"`
	IsFinal    bool    `json:"is_final"`
	Confidence float64 `json:"confidence"`
	Start      float64 `json:"start"`
	Duration   float64 `json:"duration"`
}

VoiceTranscript is sent back to the browser.

type WalkthroughEntry added in v0.13.24

type WalkthroughEntry struct {
	ID        string    `json:"id"`
	Timestamp time.Time `json:"timestamp"`
	URL       string    `json:"url"`
	Event     string    `json:"event"`
	ScriptID  string    `json:"script_id,omitempty"`
	Title     string    `json:"title,omitempty"`
	StepIndex int       `json:"step_index"`
	Total     int       `json:"total,omitempty"`
	StepTitle string    `json:"step_title,omitempty"`
	Advance   string    `json:"advance,omitempty"` // auto | click-target | wait
	How       string    `json:"how,omitempty"`     // timer | click | wait | manual | start | goto
	Mode      string    `json:"mode,omitempty"`    // auto | manual
	Message   string    `json:"message,omitempty"`
}

WalkthroughEntry represents a walkthrough (live-demo) lifecycle event emitted from the chrome-frame panel. Event is one of: start, step, manual, warning, play, pause, finish, stop. Fields are populated as relevant to the event.

Directories

Path Synopsis
Package scripts provides embedded JavaScript for the DevTool proxy instrumentation.
Package scripts provides embedded JavaScript for the DevTool proxy instrumentation.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL