Files
page-agent/packages/extension/src/messaging/protocol.ts
T

188 lines
5.2 KiB
TypeScript
Raw Normal View History

/**
* Message Protocol for PageAgentExt
*
2026-01-24 19:29:27 +08:00
* NEW ARCHITECTURE (MV3 compliant):
* - SidePanel hosts the agent, all state lives there
* - Background (SW) is a stateless message relay
* - Content Script runs PageController
*
* Message flows:
* 1. RPC: SidePanel → SW → ContentScript → SW → SidePanel (PageController calls)
* 2. Query: ContentScript → SW → SidePanel → SW → ContentScript (mask state check)
* 3. Events: SW → SidePanel (tab events from chrome.tabs API)
*/
// ============================================================================
2026-01-24 19:29:27 +08:00
// Shared Types
// ============================================================================
/** Action result from PageController operations */
export interface ActionResult {
success: boolean
message: string
}
/** Browser state for LLM consumption */
export interface BrowserState {
url: string
title: string
header: string
content: string
footer: string
}
/** Scroll options */
export interface ScrollOptions {
down: boolean
numPages: number
pixels?: number
index?: number
}
/** Horizontal scroll options */
export interface ScrollHorizontallyOptions {
right: boolean
pixels: number
index?: number
}
// ============================================================================
2026-01-24 19:29:27 +08:00
// Message Types
// ============================================================================
2026-01-24 19:29:27 +08:00
/** Message type identifier */
type MessageType =
| 'rpc:call' // SidePanel → SW: RPC call to content script
| 'rpc:response' // SW → SidePanel: RPC response from content script
| 'cs:rpc' // SW → ContentScript: Forwarded RPC call
| 'cs:query' // ContentScript → SW: Query to sidepanel
| 'query:response' // SW → ContentScript: Query response
| 'tab:event' // SW → SidePanel: Tab event notification
/** Base message structure */
interface BaseMessage {
type: MessageType
id: string // Unique message ID for request-response matching
}
// ============================================================================
2026-01-24 19:29:27 +08:00
// RPC Messages (SidePanel ↔ SW ↔ ContentScript)
// ============================================================================
2026-01-24 19:29:27 +08:00
/** RPC method names matching PageController interface */
export type RPCMethod =
| 'getCurrentUrl'
| 'getLastUpdateTime'
| 'getBrowserState'
| 'updateTree'
| 'cleanUpHighlights'
| 'clickElement'
| 'inputText'
| 'selectOption'
| 'scroll'
| 'scrollHorizontally'
| 'executeJavascript'
| 'showMask'
| 'hideMask'
| 'dispose'
/** SidePanel → SW: Request to call PageController method */
export interface RPCCallMessage extends BaseMessage {
type: 'rpc:call'
tabId: number
method: RPCMethod
args: unknown[]
}
2026-01-24 19:29:27 +08:00
/** SW → SidePanel: Response from PageController */
export interface RPCResponseMessage extends BaseMessage {
type: 'rpc:response'
success: boolean
result?: unknown
error?: string
}
2026-01-24 19:29:27 +08:00
/** SW → ContentScript: Forwarded RPC call */
export interface CSRPCMessage extends BaseMessage {
type: 'cs:rpc'
method: RPCMethod
args: unknown[]
}
// ============================================================================
2026-01-24 19:29:27 +08:00
// Query Messages (ContentScript → SW → SidePanel)
// ============================================================================
2026-01-24 19:29:27 +08:00
/** Query types that content script can ask */
export type QueryType = 'shouldShowMask'
/** ContentScript → SW: Query to sidepanel */
export interface CSQueryMessage extends BaseMessage {
type: 'cs:query'
queryType: QueryType
tabId: number
}
/** SW → ContentScript: Query response */
export interface QueryResponseMessage extends BaseMessage {
type: 'query:response'
result: unknown
}
// ============================================================================
2026-01-24 19:29:27 +08:00
// Tab Event Messages (SW → SidePanel)
// ============================================================================
2026-01-24 19:29:27 +08:00
/** Tab event types */
2026-01-24 19:37:46 +08:00
export type TabEventType = 'removed' | 'updated' | 'activated' | 'windowFocusChanged'
2026-01-24 19:29:27 +08:00
/** SW → SidePanel: Tab event notification */
export interface TabEventMessage extends BaseMessage {
type: 'tab:event'
eventType: TabEventType
tabId: number
data?: {
// For 'updated' events
status?: string
url?: string
2026-01-24 19:37:46 +08:00
// For 'activated' events
windowId?: number
// For 'windowFocusChanged' events
focused?: boolean
2026-01-24 19:29:27 +08:00
}
}
// ============================================================================
2026-01-24 19:29:27 +08:00
// Union Types
// ============================================================================
2026-01-24 19:29:27 +08:00
/** All message types */
export type ExtensionMessage =
| RPCCallMessage
| RPCResponseMessage
| CSRPCMessage
| CSQueryMessage
| QueryResponseMessage
| TabEventMessage
2026-01-24 19:29:27 +08:00
// ============================================================================
// Utility Functions
// ============================================================================
2026-01-24 19:29:27 +08:00
/** Generate unique message ID */
export function generateMessageId(): string {
return `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`
}
2026-01-24 19:29:27 +08:00
/** Type guard for our messages */
export function isExtensionMessage(msg: unknown): msg is ExtensionMessage {
return (
typeof msg === 'object' &&
msg !== null &&
'type' in msg &&
'id' in msg &&
typeof (msg as ExtensionMessage).type === 'string' &&
typeof (msg as ExtensionMessage).id === 'string'
)
}