Skip to main content

AgentProvider

Interface for implementing custom AI agent providers. Agent providers handle sending prompts to AI services and streaming responses.

Properties

send
(context: AgentContext<T>, signal: AbortSignal) => AsyncIterable<string>
required
Send a prompt to the agent and receive streaming response. Must return an async iterable that yields status message strings.
  • context - The agent context with content, prompt, and options
  • signal - AbortSignal for cancellation support
resume
(sessionId: string, signal: AbortSignal, storage: AgentSessionStorage) => AsyncIterable<string>
Resume a previously started session. Only required if supportsResume is true.
  • sessionId - ID of the session to resume
  • signal - AbortSignal for cancellation
  • storage - Storage interface for retrieving session data
abort
(sessionId: string) => Promise<void>
Abort a running session. Called when user cancels an active agent operation.
supportsResume
boolean
default:"false"
Whether this provider supports resuming sessions after page reload.
supportsFollowUp
boolean
default:"false"
Whether this provider supports follow-up prompts in the same session.
dismissButtonText
string
Custom text for the dismiss button in the agent UI. Defaults to “Dismiss”.
checkConnection
() => Promise<boolean>
Check if the agent service is available. Called before showing agent UI.
getCompletionMessage
() => string | undefined
Get a custom completion message to show when agent finishes successfully.
undo
() => Promise<void>
Undo the last agent action. Only required if canUndo returns true.
canUndo
() => boolean
Whether undo is currently available. Checked to show/hide undo button.
redo
() => Promise<void>
Redo a previously undone action. Only required if canRedo returns true.
canRedo
() => boolean
Whether redo is currently available. Checked to show/hide redo button.

AgentContext

Context object passed to agent providers containing the prompt and selected content.

Properties

content
string[]
required
Array of content strings from selected elements. Each string represents the code/content of one grabbed element.
prompt
string
required
The user’s prompt/instruction for the agent.
options
T
Custom options for the agent provider. Type parameter T allows providers to specify their own options interface.
sessionId
string
Unique session identifier. Useful for tracking and resuming sessions.

AgentSession

Represents an active or completed agent session with its state and metadata.

Properties

id
string
required
Unique session identifier.
context
AgentContext
required
The agent context (content, prompt, options) for this session.
lastStatus
string
required
The most recent status message from the agent.
isStreaming
boolean
required
Whether the agent is currently streaming responses.
isFading
boolean
Whether the session UI is fading out (dismissing).
createdAt
number
required
Timestamp (ms) when the session was created.
lastUpdatedAt
number
required
Timestamp (ms) of the last update to this session.
position
{ x: number; y: number }
required
Screen position where the agent UI should appear.
selectionBounds
OverlayBounds[]
required
Visual bounds of selected elements for highlighting.
tagName
string
HTML tag name of the primary selected element.
componentName
string
React component name of the primary selected element.
error
string
Error message if the session failed.

AgentSessionStorage

Storage interface for persisting agent session data. Used for session resumption.

Properties

getItem
(key: string) => string | null
required
Retrieve a stored value by key. Returns null if not found.
setItem
(key: string, value: string) => void
required
Store a value with the given key. Overwrites existing value.
removeItem
(key: string) => void
required
Remove a stored value by key.

AgentOptions

Configuration options for agent integration.

Properties

provider
AgentProvider<T>
The agent provider instance to use for this operation.
storage
AgentSessionStorage | null
Storage implementation for session persistence. Pass null to disable.
getOptions
() => T
Function that returns custom options to pass to the provider.
onStart
(session: AgentSession, elements: Element[]) => void
Called when an agent session starts.
onStatus
(status: string, session: AgentSession) => void
Called when agent sends a status update.
onComplete
(session: AgentSession, elements: Element[]) => AgentCompleteResult | void | Promise<AgentCompleteResult | void>
Called when agent completes successfully. Can return an error to show.
onError
(error: Error, session: AgentSession) => void
Called when agent encounters an error.
onResume
(session: AgentSession) => void
Called when a session is resumed.
onAbort
(session: AgentSession, elements: Element[]) => void
Called when user aborts a session.
onUndo
(session: AgentSession, elements: Element[]) => void
Called when user triggers undo.
onDismiss
(session: AgentSession, elements: Element[]) => void
Called when user dismisses the session UI.

Usage

Basic Agent Provider

import { AgentProvider, AgentContext } from 'react-grab';

const myAgent: AgentProvider = {
  async *send(context, signal) {
    yield 'Connecting to AI service...';
    
    const response = await fetch('/api/agent', {
      method: 'POST',
      body: JSON.stringify({
        prompt: context.prompt,
        content: context.content
      }),
      signal
    });
    
    yield 'Processing request...';
    
    const result = await response.json();
    
    yield 'Applying changes...';
    
    // Apply the changes
    await applyChanges(result);
    
    yield 'Complete!';
  },
  
  checkConnection: async () => {
    try {
      await fetch('/api/health');
      return true;
    } catch {
      return false;
    }
  }
};

Agent with Custom Options

interface MyAgentOptions {
  model: string;
  temperature: number;
}

const configurableAgent: AgentProvider<MyAgentOptions> = {
  async *send(context, signal) {
    const { model, temperature } = context.options || {};
    
    yield `Using model: ${model}...`;
    
    const response = await fetch('/api/chat', {
      method: 'POST',
      body: JSON.stringify({
        model,
        temperature,
        prompt: context.prompt,
        content: context.content
      }),
      signal
    });
    
    const reader = response.body?.getReader();
    const decoder = new TextDecoder();
    
    while (reader) {
      const { done, value } = await reader.read();
      if (done) break;
      yield decoder.decode(value);
    }
  },
  
  supportsFollowUp: true,
  dismissButtonText: 'Done'
};

Using Agent in Action

import { ContextMenuAction } from 'react-grab';

const refactorAction: ContextMenuAction = {
  id: 'refactor',
  label: 'Refactor with AI',
  onAction: async (context) => {
    context.enterPromptMode?.({
      provider: myAgent,
      getOptions: () => ({
        model: 'gpt-4',
        temperature: 0.7
      }),
      onComplete: (session, elements) => {
        console.log('Refactoring complete!');
      },
      onError: (error) => {
        console.error('Failed:', error);
      }
    });
  }
};

Agent with Session Storage

const persistentAgent: AgentProvider = {
  async *send(context, signal) {
    // Implementation...
    yield 'Processing...';
  },
  
  async *resume(sessionId, signal, storage) {
    const savedState = storage.getItem(`session-${sessionId}`);
    if (!savedState) {
      throw new Error('Session not found');
    }
    
    yield 'Resuming session...';
    
    const state = JSON.parse(savedState);
    // Continue from saved state
    
    yield 'Resumed!';
  },
  
  supportsResume: true
};

// Use with storage
const action: ContextMenuAction = {
  id: 'ai-assist',
  label: 'AI Assist',
  onAction: (context) => {
    context.enterPromptMode?.({
      provider: persistentAgent,
      storage: localStorage, // Use browser localStorage
      onStart: (session) => {
        localStorage.setItem(
          `session-${session.id}`,
          JSON.stringify(session.context)
        );
      }
    });
  }
};

Type Definitions

export interface AgentProvider<T = any> {
  send: (context: AgentContext<T>, signal: AbortSignal) => AsyncIterable<string>;
  resume?: (sessionId: string, signal: AbortSignal, storage: AgentSessionStorage) => AsyncIterable<string>;
  abort?: (sessionId: string) => Promise<void>;
  supportsResume?: boolean;
  supportsFollowUp?: boolean;
  dismissButtonText?: string;
  checkConnection?: () => Promise<boolean>;
  getCompletionMessage?: () => string | undefined;
  undo?: () => Promise<void>;
  canUndo?: () => boolean;
  redo?: () => Promise<void>;
  canRedo?: () => boolean;
}

export interface AgentContext<T = unknown> {
  content: string[];
  prompt: string;
  options?: T;
  sessionId?: string;
}

export interface AgentSession {
  id: string;
  context: AgentContext;
  lastStatus: string;
  isStreaming: boolean;
  isFading?: boolean;
  createdAt: number;
  lastUpdatedAt: number;
  position: { x: number; y: number };
  selectionBounds: OverlayBounds[];
  tagName?: string;
  componentName?: string;
  error?: string;
}

export interface AgentSessionStorage {
  getItem(key: string): string | null;
  setItem(key: string, value: string): void;
  removeItem(key: string): void;
}

export interface AgentOptions<T = any> {
  provider?: AgentProvider<T>;
  storage?: AgentSessionStorage | null;
  getOptions?: () => T;
  onStart?: (session: AgentSession, elements: Element[]) => void;
  onStatus?: (status: string, session: AgentSession) => void;
  onComplete?: (session: AgentSession, elements: Element[]) => AgentCompleteResult | void | Promise<AgentCompleteResult | void>;
  onError?: (error: Error, session: AgentSession) => void;
  onResume?: (session: AgentSession) => void;
  onAbort?: (session: AgentSession, elements: Element[]) => void;
  onUndo?: (session: AgentSession, elements: Element[]) => void;
  onDismiss?: (session: AgentSession, elements: Element[]) => void;
}

See Also

  • Actions - Use actions to trigger agent operations
  • Plugin - Register agents via plugins

Build docs developers (and LLMs) love