@angelerator/uuics-core
Version:
Universal UI Context System - AI-powered web interface understanding and interaction
916 lines (900 loc) • 24 kB
text/typescript
/**
* Universal UI Context System (UUICS) - Core Types
*
* Framework-agnostic, Model-agnostic type definitions for UI context tracking
* and interaction automation.
*/
/**
* Supported interactive element types
*/
type ElementType = 'button' | 'input' | 'textarea' | 'select' | 'checkbox' | 'radio' | 'link' | 'form' | 'container' | 'text' | 'other';
/**
* Represents an option within a select element
*/
interface SelectOption {
/** Option value attribute */
value: string;
/** Display label/text */
label: string;
/** Whether this option is currently selected */
selected: boolean;
/** Whether this option is disabled */
disabled: boolean;
/** Full text content */
text: string;
/** Option index in the select */
index: number;
}
/**
* Metadata for select elements
*/
interface SelectMetadata {
/** All available options */
options: SelectOption[];
/** Whether multiple selection is allowed */
multiple: boolean;
/** Currently selected value(s) */
selectedValues: string[];
/** Number of visible options */
size?: number;
}
/**
* Represents a single UI element in the DOM
*/
interface UIElement {
/** Unique identifier for the element */
id: string;
/** Element type classification */
type: ElementType;
/** HTML tag name (e.g., 'button', 'input') */
tag: string;
/** CSS selector to uniquely identify this element */
selector: string;
/** Human-readable label or description */
label: string;
/** Relevant HTML attributes */
attributes: Record<string, string | boolean | number>;
/** Current value (for inputs) */
value?: string | number | boolean | string[];
/** Text content of the element */
text?: string;
/** Whether the element is currently visible */
visible: boolean;
/** Whether the element is enabled/disabled */
enabled: boolean;
/** Child elements (for containers) */
children?: UIElement[];
/** Options for select elements */
options?: SelectOption[];
/** Select-specific metadata (for select elements only) */
selectMetadata?: SelectMetadata;
/** Bounding rectangle information */
bounds?: {
x: number;
y: number;
width: number;
height: number;
};
/** Metadata for caching and change detection */
metadata?: {
/** Hash of element state for change detection */
hash?: string;
/** Last update timestamp */
lastUpdated?: number;
/** Additional metadata (e.g., options for select) */
[key: string]: unknown;
};
}
/**
* Represents the complete UI context of a page
*/
interface PageContext {
/** Unique identifier for this context snapshot */
id: string;
/** Timestamp of context capture */
timestamp: number;
/** Current page URL */
url: string;
/** Page title */
title: string;
/** All interactive elements found on the page */
elements: UIElement[];
/** Available actions that can be performed */
actions: Action[];
/** Current form states (if any) */
forms?: FormState[];
/** Page metadata */
metadata: {
/** Total number of elements scanned */
elementCount: number;
/** Scan depth used */
scanDepth: number;
/** Time taken to scan (ms) */
scanDuration: number;
/** Whether scan was partial/truncated */
partial: boolean;
};
/** Captured JavaScript state/variables (if state tracking enabled) */
state?: Record<string, any>;
}
/**
* Represents the state of a form
*/
interface FormState {
/** Form identifier */
id: string;
/** Form selector */
selector: string;
/** Form fields and their values */
fields: Record<string, unknown>;
/** Whether the form is valid */
valid: boolean;
/** Validation errors (if any) */
errors?: Record<string, string>;
}
/**
* Supported action types
*/
type ActionType = 'click' | 'setValue' | 'submit' | 'select' | 'check' | 'uncheck' | 'focus' | 'scroll' | 'hover' | 'custom';
/**
* Represents an available action on the page
*/
interface Action {
/** Unique action identifier */
id: string;
/** Action type */
type: ActionType;
/** Human-readable description */
description: string;
/** Target element selector */
target: string;
/** Parameter schema for this action */
parameters?: ActionParameters;
/** Whether this action is currently available */
available: boolean;
}
/**
* Parameter schema for an action
*/
interface ActionParameters {
[key: string]: {
type: 'string' | 'number' | 'boolean' | 'array';
description?: string;
required?: boolean;
default?: unknown;
enum?: unknown[];
};
}
/**
* Command to execute an action
*/
interface ActionCommand {
/** Action ID or type */
action: string;
/** Target element selector */
target: string;
/** Action parameters */
parameters?: Record<string, unknown>;
/** Optional custom script to execute */
script?: string;
}
/**
* Result of an action execution
*/
interface ActionResult {
/** Whether the action succeeded */
success: boolean;
/** Result message */
message: string;
/** Error details (if failed) */
error?: string;
/** Any return value from the action */
data?: unknown;
/** Updated context after action (optional) */
context?: PageContext;
}
/**
* Supported serialization formats
*/
type SerializationFormat = 'json' | 'natural' | 'openapi';
/**
* Serialized context in various formats
*/
interface SerializedContext {
/** Format of serialization */
format: SerializationFormat;
/** Serialized content */
content: string | object;
/** Timestamp of serialization */
timestamp: number;
/** Metadata about the serialization */
metadata?: Record<string, unknown>;
}
/**
* Configuration for UUICS Engine
*/
interface UUICSConfig {
/** Scanning configuration */
scan?: {
/** Auto-scan interval in milliseconds (0 = manual only) */
interval?: number;
/** Maximum DOM depth to scan */
depth?: number;
/** Include hidden elements */
includeHidden?: boolean;
/** Include disabled elements */
includeDisabled?: boolean;
/** Root CSS selectors to limit scanning scope (string or array) */
rootSelectors?: string | string[];
/** CSS selectors to exclude from scanning (string or array) */
excludeSelectors?: string | string[];
/** Regex patterns to match against selectors/IDs/classes for inclusion */
includePatterns?: RegExp | RegExp[];
/** Regex patterns to match against selectors/IDs/classes for exclusion */
excludePatterns?: RegExp | RegExp[];
/** HTML element types to include (e.g., ['input', 'button', 'select']) */
includeElements?: string | string[];
/** HTML element types to exclude (e.g., ['script', 'style', 'noscript']) */
excludeElements?: string | string[];
/** Custom element filter function */
filter?: (element: HTMLElement) => boolean;
/** Use idle callback for scanning */
useIdleCallback?: boolean;
};
/** Tracking configuration */
track?: {
/** Track DOM mutations */
mutations?: boolean;
/** Track click events */
clicks?: boolean;
/** Track input changes */
changes?: boolean;
/** Track form submissions */
submits?: boolean;
/** Debounce delay for events (ms) */
debounceDelay?: number;
};
/** Serialization configuration */
serialize?: {
/** Default format */
format?: SerializationFormat;
/** Include metadata in output */
includeMetadata?: boolean;
/** Pretty-print JSON */
pretty?: boolean;
/** Include element bounds */
includeBounds?: boolean;
};
/** Performance configuration */
performance?: {
/** Enable caching */
enableCache?: boolean;
/** Cache TTL in milliseconds */
cacheTTL?: number;
/** Maximum number of elements to scan */
maxElements?: number;
/** Use Web Worker for scanning */
useWorker?: boolean;
};
/** Debug configuration */
debug?: {
/** Enable debug logging */
enabled?: boolean;
/** Log level */
level?: 'error' | 'warn' | 'info' | 'debug';
};
/** State tracking configuration */
state?: {
/** Enable state tracking */
enabled?: boolean;
/** Custom state capture function */
capture?: () => Record<string, any>;
/** Objects to auto-track with proxies */
track?: Record<string, object>;
/** Patterns to exclude from state snapshots (e.g., 'password', 'token', '*.secret') */
exclude?: string[];
};
}
/**
* Event emitted when context changes
*/
interface ContextChangeEvent {
/** Event type */
type: 'context-change';
/** Updated context */
context: PageContext;
/** What triggered the change */
trigger: 'scan' | 'mutation' | 'action' | 'manual';
/** Timestamp */
timestamp: number;
}
/**
* Event emitted when an action is executed
*/
interface ActionExecutedEvent {
/** Event type */
type: 'action-executed';
/** Executed action */
action: ActionCommand;
/** Action result */
result: ActionResult;
/** Timestamp */
timestamp: number;
}
/**
* All event types
*/
type UUICSEvent = ContextChangeEvent | ActionExecutedEvent;
/**
* Event listener callback
*/
type EventListener<T extends UUICSEvent = UUICSEvent> = (event: T) => void;
/**
* Callback for context updates
*/
type ContextSubscriber = (context: PageContext) => void;
/**
* Debounced function type
*/
type DebouncedFunction<T extends (...args: any[]) => any> = {
(...args: Parameters<T>): void;
cancel: () => void;
flush: () => void;
};
/**
* UUICS Engine - Main class integrating all components
*/
/**
* UUICS Engine - Universal UI Context System
*/
declare class UUICSEngine {
private config;
private scanner;
private tracker;
private stateTracker?;
private aggregator;
private serializer;
private executor;
private currentContext;
private subscribers;
private scanInterval;
private isInitialized;
constructor(config?: UUICSConfig);
/**
* Initialize the engine
*/
initialize(): Promise<void>;
/**
* Scan the DOM and update context
*/
scan(root?: HTMLElement, configOverride?: Partial<UUICSConfig['scan']>): Promise<PageContext>;
/**
* Start mutation tracking
*/
private startTracking;
/**
* Get current context
*/
getContext(): PageContext | null;
/**
* Subscribe to context updates
*/
subscribe(callback: ContextSubscriber): () => void;
/**
* Notify all subscribers of context update
*/
private notifySubscribers;
/**
* Serialize current context
*/
serialize(format?: SerializationFormat): string;
/**
* Execute an action
*/
execute(command: ActionCommand): Promise<ActionResult>;
/**
* Execute multiple actions in sequence
*/
executeBatch(commands: ActionCommand[]): Promise<ActionResult[]>;
/**
* Find element by selector
*/
findElement(selector: string): UIElement | null;
/**
* Find elements by type
*/
findElements(type: string): UIElement[];
/**
* Track an object with proxy-based state tracking
*/
trackState<T extends object>(name: string, obj: T): T;
/**
* Register a state getter for manual state tracking
*/
registerState(name: string, getter: () => any): void;
/**
* Unregister a state getter
*/
unregisterState(name: string): void;
/**
* Remove a tracked object
*/
untrackState(name: string): void;
/**
* Get list of tracked state names
*/
getTrackedStateNames(): string[];
/**
* Update configuration
*/
updateConfig(config: Partial<UUICSConfig>): void;
/**
* Clear cache
*/
clearCache(): void;
/**
* Destroy the engine and cleanup
*/
destroy(): void;
/**
* Check if engine is initialized
*/
get initialized(): boolean;
/**
* Get configuration
*/
getConfig(): UUICSConfig;
/**
* Merge configurations
*/
private mergeConfig;
/**
* Logging helper
*/
private log;
}
/**
* DOM Scanner - Performance-optimized DOM traversal and element detection
*/
/**
* Scanner configuration
*/
interface ScannerConfig {
depth: number;
includeHidden: boolean;
includeDisabled: boolean;
includeBounds: boolean;
rootSelectors?: string[] | string;
excludeSelectors?: string[] | string;
includePatterns?: RegExp[];
excludePatterns?: RegExp[];
includeElements?: string[];
excludeElements?: string[];
filter?: (element: HTMLElement) => boolean;
maxElements?: number;
}
/**
* DOM Scanner class
*/
declare class DOMScanner {
private config;
private cache;
private elementCount;
constructor(config?: Partial<UUICSConfig>);
/**
* Parse selector input - accepts string (comma-separated) or array
*/
private parseSelectors;
/**
* Parse regex patterns - accepts single RegExp or array
*/
private parsePatterns;
/**
* Parse element types - accepts string (comma-separated) or array
*/
private parseElements;
/**
* Get element info string for regex matching
* Returns a string containing selector, id, and classes
*/
private getElementInfo;
/**
* Scan the DOM and return all interactive elements
*/
scan(root?: HTMLElement, configOverride?: Partial<ScannerConfig>): UIElement[];
/**
* Recursively scan DOM tree
*/
private scanRecursive;
/**
* Analyze a single element and determine if it's interactive
*/
private analyzeElement;
/**
* Build UIElement object from HTMLElement
*/
private buildUIElement;
/**
* Extract options from a select element
*/
private extractSelectOptions;
/**
* Extract metadata for a select element
*/
private extractSelectMetadata;
/**
* Create a UIElement for an option
*/
private createOptionElement;
/**
* Determine element type
*/
private getElementType;
/**
* Check if element is a container
*/
private isContainer;
/**
* Check if element has significant text content
*/
private hasSignificantText;
/**
* Get human-readable label for element
*/
private getElementLabel;
/**
* Get relevant HTML attributes
*/
private getRelevantAttributes;
/**
* Get element value
*/
private getElementValue;
/**
* Get element text content
*/
private getElementText;
/**
* Check if element is disabled
*/
private isDisabled;
/**
* Generate hash for element state (for change detection)
*/
private hashElement;
/**
* Clear the cache
*/
clearCache(): void;
/**
* Update configuration
*/
updateConfig(config: Partial<ScannerConfig>): void;
}
/**
* Mutation Tracker - Debounced mutation observer and event tracking
*/
/**
* Tracker configuration
*/
interface TrackerConfig {
mutations: boolean;
clicks: boolean;
changes: boolean;
submits: boolean;
debounceDelay: number;
}
/**
* Change callback type
*/
type ChangeCallback = (trigger: 'mutation' | 'click' | 'change' | 'submit', target?: HTMLElement) => void;
/**
* Mutation Tracker class
*/
declare class MutationTracker {
private config;
private observer;
private listeners;
private changeCallback;
private debouncedOnChange;
private isActive;
constructor(config?: Partial<UUICSConfig>);
/**
* Start tracking
*/
start(callback: ChangeCallback): void;
/**
* Stop tracking
*/
stop(): void;
/**
* Setup mutation observer for DOM changes
*/
private setupMutationObserver;
/**
* Setup click event listener
*/
private setupClickListener;
/**
* Setup change event listener
*/
private setupChangeListener;
/**
* Setup submit event listener
*/
private setupSubmitListener;
/**
* Check if element is interactive
*/
private isInteractiveElement;
/**
* Check if element is a form control
*/
private isFormControl;
/**
* Flush any pending changes immediately
*/
flush(): void;
/**
* Update configuration
*/
updateConfig(config: Partial<TrackerConfig>): void;
/**
* Check if tracker is active
*/
get active(): boolean;
}
/**
* Context Aggregator - Aggregates UI elements into structured context with actions
*/
/**
* Context Aggregator class
*/
declare class ContextAggregator {
/**
* Aggregate UI elements into a complete page context
*/
aggregate(elements: UIElement[], metadata: {
scanDuration: number;
scanDepth: number;
partial: boolean;
}): PageContext;
/**
* Generate available actions from elements
*/
private generateActions;
/**
* Get actions for a specific element
*/
private getActionsForElement;
/**
* Create an action object
*/
private createAction;
/**
* Extract form states from elements
*/
private extractForms;
/**
* Generate action registry (for documentation/introspection)
*/
generateActionRegistry(context: PageContext): Record<string, Action[]>;
/**
* Find actions by type
*/
findActionsByType(context: PageContext, type: ActionType): Action[];
/**
* Find action by target
*/
findActionByTarget(context: PageContext, target: string): Action | undefined;
/**
* Get suggested actions (most common/important actions)
*/
getSuggestedActions(context: PageContext, limit?: number): Action[];
}
/**
* Serializers - Convert PageContext to various formats
*/
/**
* Serializer class
*/
declare class Serializer {
/**
* Serialize context to specified format
*/
serialize(context: PageContext, format?: SerializationFormat, options?: {
pretty?: boolean;
includeMetadata?: boolean;
includeBounds?: boolean;
}): SerializedContext;
/**
* Serialize to JSON
*/
private toJSON;
/**
* Create a replacer function that handles circular references and limits depth
*/
private createCircularReplacer;
/**
* Serialize to natural language (LLM-friendly)
*/
private toNaturalLanguage;
/**
* Serialize to OpenAPI format (tool calling)
*/
private toOpenAPI;
/**
* Format element for natural language output
*/
private formatElementNatural;
/**
* Group elements by type
*/
private groupElementsByType;
/**
* Group actions by type
*/
private groupActionsByType;
/**
* Capitalize first letter
*/
private capitalizeFirst;
/**
* Deduplicate elements by selector
*/
private deduplicateElements;
/**
* Deduplicate actions by target selector
*/
private deduplicateActions;
}
/**
* Action Executor - Execute UI actions with validation and error handling
*/
/**
* Action Executor class
*/
declare class ActionExecutor {
/**
* Execute an action command
*/
execute(command: ActionCommand, _context?: PageContext): Promise<ActionResult>;
/**
* Validate action command
*/
private validateCommand;
/**
* Find element by selector (with automatic sanitization)
*/
private findElement;
/**
* Execute action on element
*/
private executeAction;
/**
* Execute click action
*/
private executeClick;
/**
* Execute setValue action
*/
private executeSetValue;
/**
* Execute submit action
*/
private executeSubmit;
/**
* Execute select action
*/
private executeSelect;
/**
* Execute check/uncheck action
*/
private executeCheck;
/**
* Execute focus action
*/
private executeFocus;
/**
* Execute scroll action
*/
private executeScroll;
/**
* Execute hover action
*/
private executeHover;
/**
* Execute custom script
*/
private executeCustomScript;
/**
* Batch execute multiple commands
*/
executeBatch(commands: ActionCommand[], _context?: PageContext): Promise<ActionResult[]>;
/**
* Delay helper
*/
private delay;
/**
* Wait for React/framework state changes to settle after an action
* Uses a combination of techniques to ensure state updates are processed:
* 1. requestAnimationFrame - waits for next paint
* 2. MutationObserver - detects DOM changes
* 3. setTimeout - fallback timeout
*/
private waitForStateSettle;
}
/**
* Utility functions for UUICS
*/
/**
* Creates a debounced function that delays invoking func until after wait milliseconds
* have elapsed since the last time the debounced function was invoked.
*/
declare function debounce<T extends (...args: any[]) => any>(func: T, wait: number): {
(...args: Parameters<T>): void;
cancel: () => void;
flush: () => void;
};
/**
* Generate a simple hash from a string
*/
declare function hash(str: string): string;
/**
* Generate a unique ID
*/
declare function generateId(prefix?: string): string;
/**
* Check if an element is visible
*/
declare function isElementVisible(element: HTMLElement): boolean;
/**
* Get a unique CSS selector for an element (optimized for brevity)
*/
declare function getElementSelector(element: HTMLElement): string;
/**
* Execute a function in the next idle period
*/
declare function runInIdle(callback: () => void): void;
/**
* Safely get element bounds
*/
declare function getElementBounds(element: HTMLElement): {
x: number;
y: number;
width: number;
height: number;
};
/**
* Selector Sanitizer - Clean and validate CSS selectors before use
*
* This utility helps UUICS handle malformed selectors from AI systems
* or other sources that may include formatting artifacts.
*/
interface SanitizationResult {
selector: string;
original: string;
modified: boolean;
warnings: string[];
}
/**
* Sanitize a CSS selector by removing common formatting issues
*/
declare function sanitizeSelector(selector: string): SanitizationResult;
/**
* Validate a CSS selector without attempting to query the DOM
*/
declare function validateSelector(selector: string): {
valid: boolean;
error?: string;
};
/**
* Sanitize and validate a selector, returning a clean version or error
*/
declare function cleanAndValidateSelector(selector: string): {
success: boolean;
selector?: string;
error?: string;
warnings?: string[];
};
export { type Action, type ActionCommand, type ActionExecutedEvent, ActionExecutor, type ActionParameters, type ActionResult, type ActionType, ContextAggregator, type ContextChangeEvent, type ContextSubscriber, DOMScanner, type DebouncedFunction, type ElementType, type EventListener, type FormState, MutationTracker, type PageContext, type SanitizationResult, type SerializationFormat, type SerializedContext, Serializer, type UIElement, type UUICSConfig, UUICSEngine, type UUICSEvent, cleanAndValidateSelector, debounce, generateId, getElementBounds, getElementSelector, hash, isElementVisible, runInIdle, sanitizeSelector, validateSelector };