New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

glove-react

Package Overview
Dependencies
Maintainers
1
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

glove-react

React bindings for Glove agent framework

latest
Source
npmnpm
Version
2.2.4
Version published
Maintainers
1
Created
Source

glove-react

React bindings for the Glove agent framework — hooks, components, and tools with colocated renderers.

Install

npm install glove-react glove-next

Requires react >= 18.0.0 as a peer dependency.

Quick start

1. Server route (Next.js)

// app/api/chat/route.ts
import { createChatHandler } from "glove-next";

export const POST = createChatHandler({
  provider: "anthropic",
  model: "claude-sonnet-4-20250514",
});

2. Define tools

// lib/glove.tsx
import { GloveClient, defineTool } from "glove-react";
import type { ToolConfig } from "glove-react";
import { z } from "zod";

const inputSchema = z.object({
  question: z.string().describe("The question to display"),
  options: z.array(z.object({
    label: z.string().describe("Display text"),
    value: z.string().describe("Value returned when selected"),
  })),
});

const askPreferenceTool = defineTool({
  name: "ask_preference",
  description: "Present options for the user to choose from.",
  inputSchema,
  displayPropsSchema: inputSchema,     // optional, recommended for tools with UI
  resolveSchema: z.string(),
  displayStrategy: "hide-on-complete",
  async do(input, display) {
    const selected = await display.pushAndWait(input);
    return {
      status: "success" as const,
      data: `User selected: ${selected}`,
      renderData: { question: input.question, selected }, // client-only, not sent to AI
    };
  },
  render({ props, resolve }) {
    return (
      <div>
        <p>{props.question}</p>
        {props.options.map(opt => (
          <button key={opt.value} onClick={() => resolve(opt.value)}>
            {opt.label}
          </button>
        ))}
      </div>
    );
  },
  renderResult({ data }) {
    const { question, selected } = data as { question: string; selected: string };
    return <div><p>{question}</p><span>Selected: {selected}</span></div>;
  },
});

// Tools without display stay as raw ToolConfig
const getDateTool: ToolConfig = {
  name: "get_date",
  description: "Get today's date",
  inputSchema: z.object({}),
  async do() { return { status: "success", data: new Date().toLocaleDateString() }; },
};

export const gloveClient = new GloveClient({
  endpoint: "/api/chat",
  systemPrompt: "You are a helpful assistant.",
  tools: [askPreferenceTool, getDateTool],
  // Optional: resolve session ID asynchronously (e.g. from your backend)
  // getSessionId: () => fetch("/api/session").then(r => r.json()).then(d => d.sessionId),
});

3. Provider + UI

// app/providers.tsx
"use client";
import { GloveProvider } from "glove-react";
import { gloveClient } from "@/lib/glove";

export function Providers({ children }: { children: React.ReactNode }) {
  return <GloveProvider client={gloveClient}>{children}</GloveProvider>;
}
// app/page.tsx
"use client";
import { useGlove, Render } from "glove-react";

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

  return (
    <Render
      glove={glove}
      strategy="interleaved"
      renderMessage={({ entry }) => (
        <div><strong>{entry.kind === "user" ? "You" : "AI"}:</strong> {entry.text}</div>
      )}
      renderStreaming={({ text }) => <div style={{ opacity: 0.7 }}>{text}</div>}
    />
  );
}

Key exports

Components & hooks

  • GloveProvider — Context provider wrapping your app
  • useGlove(config?) — Main hook returning timeline, streamingText, busy, slots, tasks, stats, sessionReady, sessionId, sendMessage, abort, renderSlot, renderToolResult, resolveSlot, rejectSlot. Accepts an optional getSessionId async function to resolve the session ID at runtime (overrides the client-level one if set).
  • Render — Headless render component with automatic slot visibility, interleaving, and renderResult rendering

Tool helpers

  • defineTool(config) — Type-safe tool builder with colocated render and renderResult. Provides typed display props and resolve values.
  • ToolConfig — Raw tool interface for tools without display UI

Client

  • GloveClient — Configuration container. Pass endpoint (for server-side models via glove-next) or createModel (for client-side models). Optionally pass getSessionId to resolve the session ID asynchronously instead of providing one directly.

Adapters

  • MemoryStore — In-memory store for prototyping
  • createRemoteStore — Delegates store operations to your API endpoints
  • createRemoteModel — Custom model adapter with prompt and optional promptStream
  • createEndpointModel — SSE-based model compatible with glove-next handlers
  • parseSSEStream — Parse an SSE response stream into RemoteStreamEvent objects

Voice bindings

Voice hooks and components are exported from glove-react/voice:

  • useGloveVoice — Core voice hook (mode, transcript, start/stop/interrupt)
  • useGlovePTT — Push-to-talk with click-vs-hold detection, hotkey, min-duration
  • VoicePTTButton — Headless PTT button with render prop and ARIA attributes

Requires glove-voice as a peer dependency.

Async session ID

When your session ID comes from a backend (auth tokens, server-assigned IDs, etc.), use getSessionId instead of a static sessionId:

// At the client level — applies to all useGlove consumers
const client = new GloveClient({
  endpoint: "/api/chat",
  systemPrompt: "You are a helpful assistant.",
  getSessionId: async () => {
    const res = await fetch("/api/session");
    const { sessionId } = await res.json();
    return sessionId;
  },
});
// Or at the hook level — overrides the client-level getSessionId
function Chat() {
  const glove = useGlove({
    getSessionId: async () => {
      const res = await fetch("/api/session");
      const { sessionId } = await res.json();
      return sessionId;
    },
  });

  // sessionReady is false while the async ID is resolving
  if (!glove.sessionReady) return <div>Loading session...</div>;

  // sessionId contains the resolved value
  console.log("Session:", glove.sessionId);

  return <Render glove={glove} />;
}

When getSessionId is configured, the store is null until the ID resolves. The hook guards the build, hydration, and sendMessage flows against the null store, so consumers only need to check sessionReady before rendering. When no getSessionId is provided, behavior is unchanged -- sessionReady is always true and the session ID is either the provided sessionId or an auto-generated UUID.

Display strategies

StrategyBehavior
"stay" (default)Slot always visible
"hide-on-complete"Hidden when slot is resolved/rejected
"hide-on-new"Hidden when a newer slot from the same tool appears

Documentation

License

MIT

FAQs

Package last updated on 03 Apr 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts