glove-react

Complete API reference for the React bindings package. Provides a declarative, hook-based interface for building agent-powered applications.

GloveClient

Central configuration object. Created once and passed to GloveProvider. Holds defaults for system prompt, tools, model/store factories, compaction, and subscribers.

typescript
import { GloveClient } from "glove-react";

const client = new GloveClient({
  endpoint: "/api/chat",
  systemPrompt: "You are a helpful assistant.",
  tools: [/* ... */],
  compaction: {
    compaction_instructions: "Summarize the conversation so far.",
    max_turns: 20,
  },
  subscribers: [],
});

Constructor

new GloveClient(config: GloveClientConfig)

GloveClientConfig

PropertyTypeDescription
endpoint?stringURL of the chat endpoint. Used by the default createEndpointModel factory. Mutually exclusive with createModel.
createModel?() => ModelAdapterFactory function that returns a ModelAdapter. Overrides endpoint when provided.
createStore?(sessionId: string) => StoreAdapterFactory function that returns a StoreAdapter for a given session. Defaults to in-memory MemoryStore.
systemPrompt?stringDefault system prompt sent with every model request.
tools?ToolConfig[]Array of tool definitions available to the agent.
compaction?CompactionConfigConfiguration for context window compaction. See CompactionConfig.
subscribers?SubscriberAdapter[]Array of subscriber adapters that receive streaming events.

Instance Properties

PropertyTypeDescription
systemPrompt?stringThe system prompt provided at construction.
tools?ToolConfig[]Tool definitions provided at construction.
compaction?CompactionConfigCompaction configuration provided at construction.
subscribers?SubscriberAdapter[]Subscriber adapters provided at construction.

Methods

MethodReturnsDescription
resolveModel()ModelAdapterReturns the model adapter. Uses createModel factory if provided, otherwise creates an endpoint model from endpoint. Marked @internal.
resolveStore(sessionId)StoreAdapterReturns a store adapter for the given session ID. Uses createStore factory if provided, otherwise creates a MemoryStore. Marked @internal.

GloveProvider

React context provider that makes a GloveClient available to all descendant components via useGloveClient() and useGlove().

tsx
import { GloveProvider } from "glove-react";

function App() {
  return (
    <GloveProvider client={client}>
      <ChatInterface />
    </GloveProvider>
  );
}
PropTypeDescription
clientGloveClientThe GloveClient instance to provide to the component tree.
childrenReactNodeChild components that can access the client via hooks.

useGlove

The primary hook for interacting with a Glove agent. Returns the full agent state and action methods. Can be called with no arguments to inherit everything from the nearest GloveProvider, or with a config object to override specific fields.

tsx
import { useGlove } from "glove-react";

function Chat() {
  const {
    timeline,
    streamingText,
    busy,
    slots,
    tasks,
    stats,
    sendMessage,
    abort,
    renderSlot,
    resolveSlot,
    rejectSlot,
  } = useGlove();

  return (
    <div>
      {timeline.map((entry, i) => (
        <div key={i}>
          {entry.kind === "user" && <p>{entry.text}</p>}
          {entry.kind === "agent_text" && <p>{entry.text}</p>}
          {entry.kind === "tool" && <p>Tool: {entry.name}</p>}
        </div>
      ))}
      {streamingText && <p>{streamingText}</p>}
      {slots.map(renderSlot)}
    </div>
  );
}

Signature

typescript
function useGlove(config?: UseGloveConfig): UseGloveReturn

UseGloveConfig

All fields are optional. When omitted, values are inherited from the nearest GloveClient via context.

PropertyTypeDescription
endpoint?stringOverride the chat endpoint URL for this hook instance.
sessionId?stringSession identifier. Different IDs produce independent conversation histories.
store?StoreAdapterOverride the store adapter for this hook instance.
model?ModelAdapterOverride the model adapter for this hook instance.
systemPrompt?stringOverride the system prompt for this hook instance.
tools?ToolConfig[]Override the tool definitions for this hook instance.
compaction?CompactionConfigOverride compaction configuration for this hook instance.
subscribers?SubscriberAdapter[]Override subscribers for this hook instance.

UseGloveReturn

Extends GloveState with action methods.

PropertyTypeDescription
busybooleanTrue while the agent is processing a request (prompting the model or executing tools).
timelineTimelineEntry[]Ordered list of conversation entries: user messages, agent text responses, and tool invocations.
streamingTextstringAccumulated text from the current streaming model response. Empty string when not streaming.
tasksTask[]Current task list managed by the agent via the built-in task tool.
slotsEnhancedSlot[]Active display stack slots with metadata (toolName, displayStrategy, status).
statsGloveStatsCumulative usage statistics for the current session.
sendMessage(text, images?)voidSend a user message to the agent. Optionally include images as Array<{ data: string; media_type: string }>. No-op if busy is true.
abort()voidAbort the current agent request. Triggers AbortError in the agent loop.
resolveSlot(slotId, value)voidResolve a pushAndWait slot with a value, unblocking the tool that created it.
rejectSlot(slotId, reason?)voidReject a pushAndWait slot with an optional reason string, causing the tool's pushAndWait call to throw.
renderSlot(slot)ReactNodeRender a slot using its associated renderer. Returns null if no renderer is registered for the slot's renderer key.
renderToolResult(entry)ReactNodeRender a completed tool result from the timeline using renderResult. Uses renderData to show a read-only view. Returns null if no renderResult is registered.

useGloveClient

Returns the nearest GloveClient from context, or null if no GloveProvider is present. This is an internal hook used by useGlove.

tsx
import { useGloveClient } from "glove-react";

function DebugPanel() {
  const client = useGloveClient();
  if (!client) return <p>No GloveProvider found.</p>;
  return <pre>{client.systemPrompt}</pre>;
}

Signature

typescript
function useGloveClient(): GloveClient | null

ToolConfig

Defines a tool that the agent can invoke. Combines the schema (for the model) with the implementation (for the runtime) and an optional React renderer (for the display stack).

PropertyTypeDescription
namestringUnique tool name. The model uses this to identify which tool to call.
descriptionstringHuman-readable description of what the tool does. The model reads this to decide when to use the tool.
inputSchemaz.ZodType<I>Zod schema defining the tool's input shape. Converted to JSON Schema for the model and used for runtime validation.
do(input: I, display: ToolDisplay) => Promise<ToolResultData>The tool's implementation. Receives validated input and a display adapter for pushing UI slots. Returns ToolResultData with { status, data, renderData? }. data is sent to the AI; renderData stays client-only.
render?(props: SlotRenderProps) => ReactNodeOptional React component for rendering this tool's display slots. When provided, the framework auto-registers a renderer keyed by the tool name.
renderResult?(props: ToolResultRenderProps) => ReactNodeSecondary renderer for showing tool results from history. Receives renderData from the tool result.
displayStrategy?SlotDisplayStrategyControls slot visibility lifecycle. See SlotDisplayStrategy.
requiresPermission?booleanWhen true, the agent will check the store for permission before executing this tool. Defaults to false.
unAbortable?booleanWhen true, the tool runs to completion even if the abort signal fires (e.g. from voice barge-in or manual interrupt). Use for mutation-critical tools like checkout forms. Defaults to false.
typescript
import { z } from "zod";
import type { ToolConfig } from "glove-react";

const weatherTool: ToolConfig<{ city: string }> = {
  name: "get_weather",
  description: "Get current weather for a city.",
  inputSchema: z.object({ city: z.string() }),
  async do(input) {
    const res = await fetch(`https://api.weather.example/v1?city=${input.city}`);
    return res.json();
  },
};

defineTool

Type-safe tool definition helper that provides typed props in render(), typed resolve in render(), and typed display.pushAndWait() / display.pushAndForget(). Preferred over raw ToolConfig for tools with display UI.

Signature

typescript
function defineTool<I extends z.ZodType, D extends z.ZodType, R extends z.ZodType = z.ZodVoid>(
  config: DefineToolConfig<I, D, R>
): ToolConfig<z.infer<I>>

DefineToolConfig

PropertyTypeDescription
namestringUnique tool name.
descriptionstringDescription for the AI.
inputSchemaz.ZodType<I>Zod schema for tool input.
displayPropsSchema?z.ZodType<D>Zod schema for display props passed to render. Optional, but recommended for tools with display UI.
resolveSchema?z.ZodType<R>Zod schema for the resolve value. Defaults to z.ZodVoid.
displayStrategy?SlotDisplayStrategyControls slot visibility lifecycle. See SlotDisplayStrategy.
requiresPermission?booleanWhen true, checks store for permission before executing.
unAbortable?booleanTool runs to completion even if the abort signal fires. Use for mutation-critical tools like checkout.
do(input: z.infer<I>, display: TypedDisplay<z.infer<D>, z.infer<R>>) => Promise<unknown>Tool implementation. Return value auto-wrapped into ToolResultData if raw.
render?(props: { props: z.infer<D>; resolve: (value: z.infer<R>) => void; reject: (reason?: string) => void }) => ReactNodeRenders display slots with typed props and resolve.
renderResult?(props: { data: unknown; output?: string; status: "success" | "error" }) => ReactNodeRenders completed tool results from history using renderData.

Example

tsx
import { defineTool } from "glove-react";
import { z } from "zod";

const askPreference = defineTool({
  name: "ask_preference",
  description: "Ask the user to pick a preference.",
  inputSchema: z.object({
    question: z.string(),
    options: z.array(z.string()),
  }),
  displayPropsSchema: z.object({
    question: z.string(),
    options: z.array(z.string()),
  }),
  resolveSchema: z.object({ choice: z.string() }),
  displayStrategy: "hide-on-complete",

  async do(input, display) {
    const result = await display.pushAndWait({
      question: input.question,
      options: input.options,
    });
    return { status: "success", data: `User chose: ${result.choice}` };
  },

  render({ props, resolve }) {
    return (
      <div>
        <p>{props.question}</p>
        {props.options.map((opt) => (
          <button key={opt} onClick={() => resolve({ choice: opt })}>
            {opt}
          </button>
        ))}
      </div>
    );
  },
});

Note: defineTool's displayPropsSchema is optional but recommended for tools with display UI. Tools without display should use raw ToolConfig instead.

ToolDisplay

The display adapter passed as the second argument to a tool's do function. Provides methods to push UI slots onto the display stack.

MethodReturnsDescription
pushAndWait<I, O>(slot)Promise<O>Push a slot onto the display stack and block until the user resolves or rejects it. The slot object has optional renderer (string) and required input (I). Returns the resolved value of type O.
pushAndForget<I>(slot)Promise<string>Push a slot onto the display stack without blocking. Returns the slot ID. The slot object has optional renderer (string) and required input (I).
tsx
const confirmTool: ToolConfig<{ message: string }> = {
  name: "confirm",
  description: "Ask the user to confirm an action.",
  inputSchema: z.object({ message: z.string() }),
  async do(input, display) {
    const confirmed = await display.pushAndWait<{ message: string }, boolean>({
      input,
    });
    return confirmed ? "User confirmed." : "User declined.";
  },
  render({ data, resolve }) {
    return (
      <div>
        <p>{data.message}</p>
        <button onClick={() => resolve(true)}>Yes</button>
        <button onClick={() => resolve(false)}>No</button>
      </div>
    );
  },
};

TypedDisplay

Typed display adapter provided to defineTool's do() function. Eliminates the renderer field and provides full type safety.

MethodReturnsDescription
pushAndWait(input: D)Promise<R>Push a slot and block until resolved. Input typed by displayPropsSchema, return typed by resolveSchema.
pushAndForget(input: D)Promise<string>Push a slot without blocking. Returns slot ID. Input typed by displayPropsSchema.

SlotRenderProps

Props passed to a tool's render function when rendering a display slot.

PropertyTypeDescription
dataTThe input data that was passed to pushAndWait or pushAndForget.
resolve(value: unknown) => voidCall this to resolve the slot. For pushAndWait slots, the value is returned to the tool. For pushAndForget slots, this removes the slot from the stack.
reject(reason?: string) => voidCall this to reject the slot. For pushAndWait slots, this causes the tool's await to throw.

ToolResultRenderProps

Props passed to a tool's renderResult function when rendering completed tool results from history.

PropertyTypeDescription
dataTThe renderData from the tool result's ToolResultData. Client-only, never sent to AI.
output?stringThe string output of the tool.
status"success" | "error"The tool execution status.

TimelineEntry

A discriminated union representing one entry in the conversation timeline. The kind field determines the shape.

typescript
type TimelineEntry =
  | { kind: "user"; text: string; images?: string[] }
  | { kind: "agent_text"; text: string }
  | { kind: "tool"; id: string; name: string; input: unknown; status: "running" | "success" | "error"; output?: string; renderData?: unknown };
KindFieldsDescription
"user"text, images?A user message. May include optional image data URLs (string[]).
"agent_text"textA text response from the agent (model output).
"tool"id, name, input, status, output?, renderData?A tool invocation. Shows the tool name, its input arguments, execution status, optional output, and optional client-only renderData.

ToolEntry

Convenience type that extracts the tool variant from TimelineEntry.

typescript
type ToolEntry = Extract<TimelineEntry, { kind: "tool" }>;

SlotDisplayStrategy

Controls how a tool's display slots behave over time. Set via displayStrategy on ToolConfig or defineTool.

typescript
type SlotDisplayStrategy = "stay" | "hide-on-complete" | "hide-on-new";
KindBehaviorUse
"stay"Slot always visible (default)Info cards, persistent results
"hide-on-complete"Hidden when slot is resolved/rejectedForms, confirmations, pickers
"hide-on-new"Hidden when newer slot from same tool appearsCart summaries, status panels

EnhancedSlot

Extended slot type with metadata. Returned by useGlove's slots array.

typescript
interface EnhancedSlot extends Slot<unknown> {
  toolName: string;
  toolCallId: string;
  createdAt: number;
  displayStrategy: SlotDisplayStrategy;
  status: "pending" | "resolved" | "rejected";
}
PropertyTypeDescription
toolNamestringName of the tool that created this slot.
toolCallIdstringID of the tool call that created this slot.
createdAtnumberTimestamp when the slot was created.
displayStrategySlotDisplayStrategyVisibility strategy for this slot.
status"pending" | "resolved" | "rejected"Current resolution status.

GloveState

The reactive state object that drives the UI. All properties in UseGloveReturn are inherited from this type plus the action methods.

PropertyTypeDescription
busybooleanWhether the agent is currently processing a request.
timelineTimelineEntry[]Full conversation timeline for rendering.
streamingTextstringCurrent streaming text buffer. Empty when idle.
tasksTask[]Current task list maintained by the agent.
slotsEnhancedSlot[]Active display stack slots with metadata (toolName, displayStrategy, status).
statsGloveStatsCumulative session statistics: turns, tokens in, tokens out.
isCompactingbooleanTrue while context compaction is in progress. Driven by compaction_start and compaction_end observer events.

GloveStats

PropertyTypeDescription
turnsnumberNumber of completed agent turns in this session.
tokens_innumberTotal input tokens consumed across all model calls.
tokens_outnumberTotal output tokens generated across all model calls.

CompactionConfig

Controls automatic context window compaction. When the conversation exceeds configured limits, the model generates a summary of the conversation so far. The full message history is preserved in the store — compaction does not delete any messages. Instead, the summary is appended as a new message marked with is_compaction: true, and token/turn counters are reset via resetCounters(). When the agent builds its next prompt, Context.getMessages() calls splitAtLastCompaction() to find the last compaction summary and returns only messages from that point onward. This means the model sees a compact context while the store retains the complete history for auditing, replay, or export.

PropertyTypeDescription
compaction_instructionsstringInstructions given to the model when summarizing the conversation. Required.
max_turns?numberMaximum number of turns before compaction is triggered.
compaction_context_limit?numberMaximum token count before compaction is triggered.

MemoryStore

An in-memory implementation of StoreAdapter. Data is lost when the page is refreshed. Useful for prototyping and ephemeral sessions.

typescript
import { MemoryStore } from "glove-react";

const store = new MemoryStore("session-1");
PropertyTypeDescription
identifierstringThe session identifier passed to the constructor.

Implements the full StoreAdapter interface: messages, token counts, turn counts, tasks, and permissions are all stored in memory. The resetCounters() method resets token and turn counts to zero without clearing messages, which is used during compaction to preserve the full conversation history.

createRemoteStore

Factory function that creates a StoreAdapter backed by remote async functions. Delegates every store operation to user-provided action functions, enabling persistence on any backend.

typescript
import { createRemoteStore } from "glove-react";

const store = createRemoteStore("session-123", {
  async getMessages(sessionId) {
    const res = await fetch(`/api/sessions/${sessionId}/messages`);
    return res.json();
  },
  async appendMessages(sessionId, messages) {
    await fetch(`/api/sessions/${sessionId}/messages`, {
      method: "POST",
      body: JSON.stringify(messages),
    });
  },
});

Signature

typescript
function createRemoteStore(
  sessionId: string,
  actions: RemoteStoreActions
): StoreAdapter

RemoteStoreActions

MethodTypeDescription
getMessages(sessionId: string) => Promise<Message[]>Fetch all messages for the session. Required.
appendMessages(sessionId: string, msgs: Message[]) => Promise<void>Append new messages to the session history. Required.
getTokenCount?(sessionId: string) => Promise<number>Get the current token count for the session.
addTokens?(sessionId: string, count: number) => Promise<void>Add to the cumulative token count.
getTurnCount?(sessionId: string) => Promise<number>Get the current turn count.
incrementTurn?(sessionId: string) => Promise<void>Increment the turn counter by one.
resetCounters?(sessionId: string) => Promise<void>Reset token and turn counters to zero without clearing messages. Called during compaction after the summary message is appended.
getTasks?(sessionId: string) => Promise<Task[]>Fetch all tasks for the session.
addTasks?(sessionId: string, tasks: Task[]) => Promise<void>Add new tasks to the session.
updateTask?(sessionId: string, taskId: string, updates: Partial<Task>) => Promise<void>Update a specific task by ID.
getPermission?(sessionId: string, toolName: string) => Promise<PermissionStatus>Check the permission status for a tool.
setPermission?(sessionId: string, toolName: string, status: PermissionStatus) => Promise<void>Set the permission status for a tool.

createRemoteModel

Factory function that creates a ModelAdapter backed by user-provided async functions. Enables calling any model backend, whether it is a custom server, a proxy, or a third-party API.

typescript
import { createRemoteModel } from "glove-react";

const model = createRemoteModel("my-model", {
  async prompt(request) {
    const res = await fetch("/api/custom-llm", {
      method: "POST",
      body: JSON.stringify(request),
    });
    return res.json();
  },
});

Signature

typescript
function createRemoteModel(
  name: string,
  actions: RemoteModelActions
): ModelAdapter

RemoteModelActions

MethodTypeDescription
prompt(request: RemotePromptRequest, signal?: AbortSignal) => Promise<RemotePromptResponse>Send a prompt to the model and receive a complete response. Required.
promptStream?(request: RemotePromptRequest, signal?: AbortSignal) => AsyncIterable<RemoteStreamEvent>Send a prompt and receive a stream of events. When provided, the adapter uses streaming for real-time text output.

RemotePromptRequest

PropertyTypeDescription
systemPromptstringThe system prompt for this request.
messagesMessage[]The conversation history to send to the model.
tools?SerializedTool[]Tool definitions serialized as JSON Schema objects.

RemotePromptResponse

PropertyTypeDescription
messageMessageThe model's response message, including any tool calls.
tokens_innumberNumber of input tokens consumed by this request.
tokens_outnumberNumber of output tokens generated by this request.

RemoteStreamEvent

A discriminated union of server-sent event types. The type field determines the payload shape.

typescript
type RemoteStreamEvent =
  | { type: "text_delta"; text: string }
  | { type: "tool_use"; id: string; name: string; input: unknown }
  | { type: "done"; message: Message; tokens_in: number; tokens_out: number };
TypeFieldsDescription
"text_delta"textA chunk of streaming text from the model.
"tool_use"id, name, inputThe model is invoking a tool with the given name and input arguments.
"done"message, tokens_in, tokens_outThe stream is complete. Includes the final Message object and token counts.

SerializedTool

PropertyTypeDescription
namestringThe tool name.
descriptionstringThe tool description.
parametersRecord<string, unknown>JSON Schema representation of the tool's input parameters.

createEndpointModel

Creates a ModelAdapter that communicates with a server endpoint via SSE (Server-Sent Events). This is the default model adapter when using GloveClient with an endpoint URL. Compatible with endpoints created by glove-next's createChatHandler.

typescript
import { createEndpointModel } from "glove-react";

const model = createEndpointModel("/api/chat");

Signature

typescript
function createEndpointModel(endpoint: string): ModelAdapter

parseSSEStream

Utility function that parses a Response object containing SSE data into an async iterable of RemoteStreamEvent objects. Used internally by createEndpointModel and available for custom streaming implementations.

typescript
import { parseSSEStream } from "glove-react";

const response = await fetch("/api/chat", { method: "POST", body: "..." });

for await (const event of parseSSEStream(response)) {
  if (event.type === "text_delta") {
    process.stdout.write(event.text);
  }
}

Signature

typescript
function parseSSEStream(response: Response): AsyncIterable<RemoteStreamEvent>

GloveHandle

The interface consumed by the <Render> component. This is a subset of UseGloveReturn that includes only the properties needed for rendering.

PropertyTypeDescription
timelineTimelineEntry[]Ordered conversation timeline entries.
streamingTextstringCurrent streaming text buffer. Empty when idle.
busybooleanWhether the agent is currently processing a request.
slotsEnhancedSlot[]Active display stack slots with metadata.
sendMessage(text, images?)voidSend a user message to the agent.
abort()voidAbort the current agent request.
renderSlot(slot)ReactNodeRender a slot using its associated renderer.
renderToolResult(entry)ReactNodeRender a completed tool result using renderResult.
resolveSlot(slotId, value)voidResolve a pushAndWait slot with a value.
rejectSlot(slotId, reason?)voidReject a pushAndWait slot with an optional reason.

Render

Headless render component that replaces manual timeline.map() / slots.map(renderSlot) rendering. Handles slot visibility filtering, renderResult rendering for completed tools, and slot interleaving.

typescript
import { Render } from "glove-react";

RenderProps

PropTypeDescription
gloveGloveHandleRequired. Return value of useGlove().
strategy?RenderStrategyWhere slots appear relative to conversation. Default: "interleaved".
renderMessage?(props: MessageRenderProps) => ReactNodeRender a user or agent_text entry.
renderToolStatus?(props: ToolStatusRenderProps) => ReactNodeRender a tool status indicator. Default: hidden.
renderStreaming?(props: StreamingRenderProps) => ReactNodeRender the streaming text buffer.
renderInput?(props: InputRenderProps) => ReactNodeRender the input area.
renderSlotContainer?(props: SlotContainerRenderProps) => ReactNodeOverride slot container for slots-before/slots-after. Default: vertical stack.
as?keyof JSX.IntrinsicElementsWrapper element. Default: "div".
className?stringclassName on wrapper.
style?CSSPropertiesstyle on wrapper.
voice?VoiceRenderHandleOptional voice state. When provided, <Render> auto-renders a transcript indicator and voice status below the messages. Works with both useGloveVoice() and useGlovePTT() returns.
renderTranscript?(props: TranscriptRenderProps) => ReactNodeCustom renderer for the voice transcript. Receives { transcript, mode }. Only used when voice prop is provided.
renderVoiceStatus?(props: VoiceStatusRenderProps) => ReactNodeCustom renderer for the voice status indicator. Receives { mode, recording? }. Only used when voice prop is provided.

RenderStrategy

typescript
type RenderStrategy = "interleaved" | "slots-before" | "slots-after" | "slots-only";

MessageRenderProps

PropertyTypeDescription
entryExtract<TimelineEntry, { kind: "user" | "agent_text" }>The timeline entry being rendered.
indexnumberIndex of this entry in the timeline.
isLastbooleanTrue when this is the last entry in the timeline and no streaming text is active.

ToolStatusRenderProps

PropertyTypeDescription
entryToolEntryThe tool timeline entry.
indexnumberIndex of this entry in the timeline.
hasSlotbooleanTrue when this tool call has an associated visible display slot.

StreamingRenderProps

PropertyTypeDescription
textstringThe accumulated streaming text buffer.

InputRenderProps

PropertyTypeDescription
send(text: string, images?: Array<{ data: string; media_type: string }>) => voidSend a user message. Mapped from useGlove's sendMessage.
busybooleanWhether the agent is currently processing.
abort() => voidAbort the current request.

SlotContainerRenderProps

PropertyTypeDescription
slotsEnhancedSlot[]The visible slots to render.
renderSlot(slot: EnhancedSlot) => ReactNodeRender a single slot.

Example

tsx
import { Render, useGlove } from "glove-react";

function Chat() {
  const glove = useGlove();

  return (
    <Render
      glove={glove}
      strategy="interleaved"
      renderMessage={({ entry }) => (
        <div className={entry.kind === "user" ? "user-msg" : "agent-msg"}>
          {entry.text}
        </div>
      )}
      renderToolStatus={({ entry, hasSlot }) => (
        <div className="tool-status">
          <span>{entry.name}: {entry.status}</span>
          {hasSlot && <span> (has UI)</span>}
        </div>
      )}
      renderStreaming={({ text }) => (
        <div className="streaming">{text}</div>
      )}
      renderInput={({ busy, send }) => (
        <form onSubmit={(e) => {
          e.preventDefault();
          const input = e.currentTarget.elements.namedItem("msg") as HTMLInputElement;
          send(input.value);
          input.value = "";
        }}>
          <input name="msg" disabled={busy} placeholder="Type a message..." />
          <button type="submit" disabled={busy}>Send</button>
        </form>
      )}
    />
  );
}

Re-exported Types

The following types are re-exported from glove-core for convenience. See the glove-core reference for full details.

TypeSourceDescription
Taskglove-coreA tracked task with id, content, activeForm, and status.
ContentPartglove-coreA multimodal content part (text, image, video, document).
Slotdisplay-managerA display stack slot with id, renderer key, and input data.
StoreAdapterglove-coreInterface for conversation persistence backends. Includes resetCounters() for compaction support.
ModelAdapterglove-coreInterface for language model providers.
SubscriberAdapterglove-coreInterface for event observers (logging, streaming, analytics).
ToolResultDataglove-coreReturn type for tool implementations with { status, data, renderData? }. data is sent to the AI; renderData stays client-only.
VoiceRenderHandleglove-reactInterface for the voice prop on <Render>. Requires mode, transcript, and optional recording.
TranscriptRenderPropsglove-reactProps for custom renderTranscript function: { transcript, mode }.
VoiceStatusRenderPropsglove-reactProps for custom renderVoiceStatus function: { mode, recording? }.