Event Types Reference
Complete field-level documentation for all 10 Periscope event payload types
Each event payload includes a kind discriminator string, a data object with event-specific fields, and an optional context object with environmental metadata.
For an overview of how events flow through the system, see Event System Concepts.
text.selection
Fired when the user selects text on a web page.
Kind: "text.selection"
Data Fields
| Field | Type | Required | Description |
|---|---|---|---|
text | string | Yes | The selected text content |
range.start | number | Yes | Character offset where the selection begins |
range.end | number | Yes | Character offset where the selection ends |
surrounding | string | No | Surrounding paragraph or context around the selection |
Context Fields
| Field | Type | Required | Description |
|---|---|---|---|
documentTitle | string | No | Title of the document where text was selected |
filePath | string | No | File path if the selection is in a local file viewer |
url | string | No | URL of the page where text was selected |
language | string | No | Detected language of the selected text (ISO 639-1) |
isMultiline | boolean | No | Whether the selection spans multiple lines |
Example
{
"kind": "text.selection",
"data": {
"text": "Periscope captures browser context in real time",
"range": { "start": 42, "end": 89 },
"surrounding": "The extension works by... Periscope captures browser context in real time ...and syncs it to the cloud."
},
"context": {
"documentTitle": "Periscope Overview",
"url": "https://docs.uselovelace.com/periscope",
"language": "en",
"isMultiline": false
}
}
page.navigation
Fired when the user navigates to a new page or the page URL changes.
Kind: "page.navigation"
Data Fields
| Field | Type | Required | Description |
|---|---|---|---|
url | string | Yes | The URL the user navigated to |
title | string | No | Page title of the destination |
navigationType | enum | No | How the navigation was triggered |
previousUrl | string | No | URL of the page the user navigated from |
statusCode | number | No | HTTP status code of the navigation response |
navigationType values: initial, link_click, form_submit, back_forward, reload, redirect, history, script
Context Fields
| Field | Type | Required | Description |
|---|---|---|---|
sameSite | boolean | No | Whether the navigation stayed on the same origin |
referrer | string | No | The referring URL |
navigationTime | number | No | Time taken for the navigation in milliseconds |
Example
{
"kind": "page.navigation",
"data": {
"url": "https://github.com/lovelace-ai/lovelace/pulls",
"title": "Pull requests - lovelace-ai/lovelace",
"navigationType": "link_click",
"previousUrl": "https://github.com/lovelace-ai/lovelace",
"statusCode": 200
},
"context": {
"sameSite": true,
"referrer": "https://github.com/lovelace-ai/lovelace",
"navigationTime": 340
}
}
document.open
Fired when the user opens a document (PDF, spreadsheet, code file, etc.) in the browser.
Kind: "document.open"
Data Fields
| Field | Type | Required | Description |
|---|---|---|---|
documentType | enum | Yes | The type of document opened |
name | string | Yes | Document file name or title |
url | string | No | URL where the document is hosted |
mimeType | string | No | MIME type of the document |
fileSize | number | No | File size in bytes |
isNew | boolean | No | Whether this is a newly created document |
documentType values: pdf, word, google_docs, google_sheets, spreadsheet, presentation, code, text, markdown, image, video, audio, other
Context Fields
| Field | Type | Required | Description |
|---|---|---|---|
application | string | No | Application used to open the document (e.g. "Google Docs") |
owner | string | No | Document owner or creator |
isShared | boolean | No | Whether the document is shared with others |
isReadOnly | boolean | No | Whether the document is read-only for the current user |
openedAt | string | No | ISO 8601 timestamp when the document was opened |
Example
{
"kind": "document.open",
"data": {
"documentType": "google_docs",
"name": "Q4 Product Roadmap",
"url": "https://docs.google.com/document/d/abc123/edit",
"mimeType": "application/vnd.google-apps.document",
"isNew": false
},
"context": {
"application": "Google Docs",
"isShared": true,
"isReadOnly": false,
"openedAt": "2026-03-02T14:30:00Z"
}
}
code.selection
Fired when the user selects code in a browser-based editor or code viewer.
Kind: "code.selection"
Data Fields
| Field | Type | Required | Description |
|---|---|---|---|
code | string | Yes | The selected code content |
language | string | Yes | Programming language of the selected code |
lineRange.start | number | Yes | Starting line number of the selection |
lineRange.end | number | Yes | Ending line number of the selection |
charRange.start | number | Yes | Starting character offset within the start line |
charRange.end | number | Yes | Ending character offset within the end line |
syntaxType | string | No | AST node type of the selection (e.g. "function_declaration") |
Context Fields
| Field | Type | Required | Description |
|---|---|---|---|
filePath | string | Yes | Path of the file containing the selected code |
repositoryUrl | string | No | URL of the repository |
branch | string | No | Git branch name |
editor | string | No | Editor or viewer name (e.g. "GitHub", "GitLab") |
editorVersion | string | No | Version of the editor |
Example
{
"kind": "code.selection",
"data": {
"code": "export function createSyncClient(config: SyncConfig): SyncClient {",
"language": "typescript",
"lineRange": { "start": 15, "end": 15 },
"charRange": { "start": 0, "end": 67 },
"syntaxType": "function_declaration"
},
"context": {
"filePath": "src/sync/client.ts",
"repositoryUrl": "https://github.com/lovelace-ai/lovelace",
"branch": "main",
"editor": "GitHub"
}
}
media.playback
Fired when media playback state changes in the browser.
Kind: "media.playback"
Data Fields
| Field | Type | Required | Description |
|---|---|---|---|
mediaType | enum | Yes | Type of media being played |
state | enum | Yes | Current playback state |
currentTime | number | No | Current playback position in seconds |
duration | number | No | Total duration in seconds |
playbackRate | number | No | Playback speed multiplier (1.0 = normal) |
isMuted | boolean | No | Whether audio is muted |
volume | number | No | Volume level from 0.0 to 1.0 |
mediaType values: audio, video, podcast, stream
state values: playing, paused, stopped, buffering
Context Fields
| Field | Type | Required | Description |
|---|---|---|---|
title | string | No | Title of the media |
artist | string | No | Artist or creator name |
album | string | No | Album or collection name |
service | string | No | Streaming service (e.g. "YouTube", "Spotify") |
url | string | No | URL of the media page |
Example
{
"kind": "media.playback",
"data": {
"mediaType": "video",
"state": "playing",
"currentTime": 142.5,
"duration": 3600,
"playbackRate": 1.5,
"isMuted": false,
"volume": 0.8
},
"context": {
"title": "Building AI Agents with Lovelace",
"service": "YouTube",
"url": "https://youtube.com/watch?v=abc123"
}
}
image.capture
Fired when the user captures or extracts an image from the browser.
Kind: "image.capture"
Data Fields
| Field | Type | Required | Description |
|---|---|---|---|
captureType | enum | Yes | How the image was captured |
imageData | string | Yes | Base64-encoded image data or a reference URL |
format | string | No | Image format (e.g. "png", "jpeg", "webp") |
dimensions.width | number | No | Image width in pixels |
dimensions.height | number | No | Image height in pixels |
fileSize | number | No | Image file size in bytes |
captureType values: screenshot, photo, webcam, clipboard, extraction
Context Fields
| Field | Type | Required | Description |
|---|---|---|---|
reason | string | No | User-provided reason for capture |
capturedBy | string | No | Tool or method used for capture |
url | string | No | URL of the page where the image was captured |
selectedRegion.x | number | No | X coordinate of the capture region |
selectedRegion.y | number | No | Y coordinate of the capture region |
selectedRegion.width | number | No | Width of the capture region in pixels |
selectedRegion.height | number | No | Height of the capture region in pixels |
Example
{
"kind": "image.capture",
"data": {
"captureType": "screenshot",
"imageData": "data:image/png;base64,iVBORw0KGgo...",
"format": "png",
"dimensions": { "width": 1920, "height": 1080 },
"fileSize": 245760
},
"context": {
"capturedBy": "Periscope Extension",
"url": "https://dashboard.uselovelace.com/agents",
"selectedRegion": { "x": 100, "y": 200, "width": 800, "height": 600 }
}
}
focus.change
Fired when keyboard focus moves between interactive elements.
Kind: "focus.change"
Data Fields
| Field | Type | Required | Description |
|---|---|---|---|
elementType | enum | Yes | Type of element that received or lost focus |
elementId | string | No | DOM id attribute of the element |
tagName | string | No | HTML tag name (e.g. "INPUT", "BUTTON") |
action | enum | Yes | Whether focus was gained or lost |
previousElement | string | No | Descriptor of the previously focused element |
elementType values: input, button, link, select, checkbox, radio, contenteditable, searchbox, other
action values: focus, blur
Context Fields
| Field | Type | Required | Description |
|---|---|---|---|
label | string | No | Accessible label of the element |
url | string | No | URL of the page |
formId | string | No | DOM id of the parent form, if applicable |
Example
{
"kind": "focus.change",
"data": {
"elementType": "input",
"elementId": "search-bar",
"tagName": "INPUT",
"action": "focus",
"previousElement": "nav-link-docs"
},
"context": {
"label": "Search documentation",
"url": "https://docs.uselovelace.com",
"formId": "search-form"
}
}
scroll
Fired when the user scrolls a page or scrollable element.
Kind: "scroll"
Data Fields
| Field | Type | Required | Description |
|---|---|---|---|
x | number | Yes | Current horizontal scroll position in pixels |
y | number | Yes | Current vertical scroll position in pixels |
maxX | number | No | Maximum horizontal scroll position |
maxY | number | No | Maximum vertical scroll position |
direction | enum | No | Direction of the scroll |
velocity | number | No | Scroll velocity in pixels per second |
scrollPercentage | number | No | Vertical scroll progress from 0.0 to 1.0 |
direction values: up, down, left, right
Context Fields
| Field | Type | Required | Description |
|---|---|---|---|
url | string | No | URL of the page |
elementId | string | No | DOM id of the scrollable element (if not the page) |
isUserInitiated | boolean | No | Whether the scroll was triggered by the user (vs. script) |
scrollableElement | string | No | Descriptor of the scrollable container |
Example
{
"kind": "scroll",
"data": {
"x": 0,
"y": 2400,
"maxX": 0,
"maxY": 8500,
"direction": "down",
"velocity": 450,
"scrollPercentage": 0.28
},
"context": {
"url": "https://docs.uselovelace.com/periscope/reference/event-types",
"isUserInitiated": true
}
}
cursor.move
Fired on significant cursor movement events (throttled to reduce volume).
Kind: "cursor.move"
Data Fields
| Field | Type | Required | Description |
|---|---|---|---|
x | number | Yes | Cursor X coordinate in viewport pixels |
y | number | Yes | Cursor Y coordinate in viewport pixels |
distance | number | No | Distance moved since last event in pixels |
velocity | number | No | Cursor velocity in pixels per second |
hoveredElement | string | No | Descriptor of the element under the cursor |
Context Fields
| Field | Type | Required | Description |
|---|---|---|---|
url | string | No | URL of the page |
isDragging | boolean | No | Whether the user is currently dragging |
button | enum | No | Mouse button being held during drag |
modifiers.ctrl | boolean | No | Whether the Ctrl key is held |
modifiers.shift | boolean | No | Whether the Shift key is held |
modifiers.alt | boolean | No | Whether the Alt key is held |
modifiers.meta | boolean | No | Whether the Meta (Cmd/Win) key is held |
button values: left, middle, right
Example
{
"kind": "cursor.move",
"data": {
"x": 512,
"y": 340,
"distance": 85.2,
"velocity": 620,
"hoveredElement": "button#deploy-agent"
},
"context": {
"url": "https://dashboard.uselovelace.com/agents/new",
"isDragging": false,
"modifiers": { "ctrl": false, "shift": false, "alt": false, "meta": false }
}
}
form.input
Fired when the user interacts with a form field.
Kind: "form.input"
Data Fields
| Field | Type | Required | Description |
|---|---|---|---|
inputType | enum | Yes | Type of the form input |
fieldName | string | No | Name attribute of the input field |
value | string | No | Sanitized value (sensitive fields are redacted) |
interactionType | enum | Yes | Type of interaction with the field |
isRequired | boolean | No | Whether the field is marked as required |
validationError | string | No | Current validation error message, if any |
inputType values: text, email, password, number, checkbox, radio, select, textarea, date, time, file, search, other
interactionType values: focus, change, blur, submit
Context Fields
| Field | Type | Required | Description |
|---|---|---|---|
formId | string | No | DOM id of the parent form |
formAction | string | No | Action URL of the form |
url | string | No | URL of the page |
label | string | No | Accessible label of the field |
isSensitive | boolean | No | Whether the field contains sensitive data (password, SSN, etc.) |
Example
{
"kind": "form.input",
"data": {
"inputType": "email",
"fieldName": "user_email",
"value": "dev@example.com",
"interactionType": "change",
"isRequired": true,
"validationError": null
},
"context": {
"formId": "signup-form",
"formAction": "/api/auth/register",
"url": "https://accounts.uselovelace.com/register",
"label": "Email address",
"isSensitive": false
}
}
Note: When
isSensitiveistrue, thevaluefield is automatically redacted by the extension before transmission. Password fields are always treated as sensitive regardless of this flag.