npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

octoflow-react

v1.0.1

Published

Headless React bindings for OctoFlow: provider, chat/session/approval/provider hooks, and AI SDK UI / AG-UI adapters.

Downloads

273

Readme

@octoflow/react

Status: Preview. Transport compatibility tests are in progress. Pin versions before depending on it in production.

Headless React bindings for OctoFlow — browser-safe provider, hooks, and adapters. Not a UI component library.

Installation

npm install @octoflow/react react

# Optional adapters depending on your UI layer:
npm install @ag-ui/client
npm install @copilotkit/react-core @copilotkit/react-ui
npm install ai @ai-sdk/react

Quick Start

import {
  OctoFlowProvider,
  useOctoFlowChat,
  useOctoFlowApprovals,
  useOctoFlowProviders,
} from '@octoflow/react';

export function App() {
  return (
    <OctoFlowProvider baseUrl="/api/octoflow">
      <Chat />
    </OctoFlowProvider>
  );
}

function Chat() {
  const chat = useOctoFlowChat({ sessionId: 'support-thread-123' });
  const approvals = useOctoFlowApprovals({ sessionId: chat.sessionId });
  const providers = useOctoFlowProviders();

  // Render with your own components, assistant-ui, CopilotKit, or AI SDK UI.
}

Choose an Integration Path

| Path | Best for | Start with | | --- | --- | --- | | OctoFlowProvider + hooks | Custom product UI, custom approval surfaces, model/settings panels. | app-simple-chatbot | | @octoflow/react/ag-ui + @ag-ui/client | Protocol-first AG-UI testing or a custom AG-UI renderer. | react-ag-ui-chatbot | | CopilotKit + HttpAgent | Stock CopilotKit chat UI backed by OctoFlow. | react-copilotkit-ag-ui-chatbot | | AI SDK UI | Existing @ai-sdk/react useChat apps. | react-ai-sdk-ui-chatbot |

Security: Keep Secrets Server-Side

OctoFlowProvider accepts only display-safe headers (CSRF tokens, short-lived session tokens, tenant IDs). Provider API keys, filesystem grants, and backend secrets must live in server route handlers, never in client components.

// app/api/octoflow/agui/run/route.ts (Next.js App Router)
import { createOctoFlowRouteHandler } from '@octoflow/react/server';

export const POST = createOctoFlowRouteHandler({
  async authenticate(req) {
    // Validate session cookie, JWT, etc.
    return { userId: 'user-123' };
  },
  async runAgent(input, context) {
    // Use octoflow-core here — API keys stay on the server.
  },
});

Hooks

useOctoFlowChat(options?)

OctoFlow-backed streaming chat over the AG-UI gateway.

const {
  sessionId,
  messages,         // OctoFlowUIMessage[]
  status,           // 'ready' | 'submitted' | 'streaming' | 'error'
  error,
  sendMessage,      // (input: { content, metadata? }) => Promise<void>
  stop,             // () => void — abort the current stream
  regenerate,       // (messageId?) => Promise<void>
  resumeStream,     // () => Promise<void> — no-op on basic transport
  setMessages,
} = useOctoFlowChat({ sessionId?, initialMessages?, metadata?, resume? });

useOctoFlowApprovals(options)

Pending approvals for a session with approve/deny actions.

const { pending, isLoading, error, approve, deny } =
  useOctoFlowApprovals({ sessionId, pollIntervalMs?: 3000 });

useOctoFlowProviders()

Backend/provider readiness catalog for settings UIs and model pickers.

const { providers, isLoading, error, refresh } = useOctoFlowProviders();

useOctoFlowSessions()

Session list with delete support.

const { sessions, isLoading, error, refresh, deleteSession } =
  useOctoFlowSessions();

useOctoFlowClient()

Low-level access to the client context (baseUrl, resolveHeaders, fetchFn).

Subpath Exports

@octoflow/react/ai-sdk

AI SDK UI v4 helpers for @ai-sdk/react useChat and the ai package data stream protocol. Optional peer: ai.

import { createOctoFlowAiSdkUseChatOptions } from '@octoflow/react/ai-sdk';
import { useChat } from '@ai-sdk/react';

const chat = useChat(
  createOctoFlowAiSdkUseChatOptions({
    api: '/api/chat',
    sessionId,
  })
);

Server routes can use writeOctoFlowAiSdkText, writeOctoFlowAiSdkData, and writeOctoFlowAiSdkFinish to bridge OctoFlow session streams into AI SDK UI data streams.

@octoflow/react/ag-ui

AG-UI helpers for CopilotKit, assistant-ui, and direct @ag-ui/client usage. Optional peer: @ag-ui/client.

import { HttpAgent } from '@ag-ui/client';
import { createOctoFlowAguiConfig } from '@octoflow/react/ag-ui';

const { url, headers } = createOctoFlowAguiConfig({ baseUrl: '/api/octoflow' });
const agent = new HttpAgent({ url, headers });

For CopilotKit, pass that HttpAgent as the local agent behind <CopilotKit> and render <CopilotChat> from @copilotkit/react-ui. The full example is react-copilotkit-ag-ui-chatbot.

@octoflow/react/server

Server-only route handler factory. Node.js / Next.js / edge runtime safe.

import { createOctoFlowRouteHandler } from '@octoflow/react/server';

Building a Full UI

@octoflow/react is headless — it gives you the data, you supply the components. Here is the recommended component architecture:

<OctoFlowProvider>          ← one per app/layout; holds HTTP config
  <ChatPanel />             ← useOctoFlowChat (streaming, send, stop, regenerate)
  <ApprovalQueue />         ← useOctoFlowApprovals (poll + approve/deny)
  <BackendStatus />         ← useOctoFlowProviders (readiness badge)
  <SessionHistory />        ← useOctoFlowSessions (list + delete)
</OctoFlowProvider>

Performance pattern — useDeferredValue for the message list

Every streaming token triggers setMessages. Wrapping the message list in useDeferredValue lets React defer expensive re-renders while keeping the input and status badge responsive:

import { useDeferredValue } from 'react';

function ChatPanel() {
  const chat = useOctoFlowChat();

  // Defer the expensive message list — stays stale during fast streaming
  // but the textarea and status badge (chat.status) update immediately.
  const deferredMessages = useDeferredValue(chat.messages);
  const isUpdating = deferredMessages !== chat.messages;

  return (
    <>
      <StatusBadge status={chat.status} />     {/* always current */}
      <ul style={{ opacity: isUpdating ? 0.8 : 1 }}>
        {deferredMessages.map((m) => (
          <MessageRow key={m.id} message={m} />
        ))}
      </ul>
      <textarea onKeyDown={...} />             {/* always responsive */}
    </>
  );
}

useOctoFlowChat already wraps every streaming token update in startTransition, so message list re-renders are non-urgent by default. Pair with useDeferredValue for extra smoothness on long conversations.

Memo individual message rows

Because setMessages returns a new array on every token, wrap individual message components with React.memo to prevent full-list re-renders:

const MessageRow = React.memo(function MessageRow({ message }: { message: OctoFlowUIMessage }) {
  return <li className={`msg msg-${message.role}`}>{message.content}</li>;
});

Plugging in an existing UI library

| UI library | Integration path | | --- | --- | | assistant-ui | Use @octoflow/react/ag-ui to get the AG-UI config → pass to @assistant-ui/react-ag-ui | | CopilotKit | Use @octoflow/react/ag-uiHttpAgent<CopilotKit localRuntimeUrl={...}> | | AI SDK UI useChat | Use @octoflow/react/ai-sdkcreateOctoFlowAiSdkUseChatOptions | | Custom shadcn/ui | Use useOctoFlowChat directly — messages, status, and sendMessage map 1:1 |

Stream Transport Pluggability

@octoflow/react uses a fixed SSE transport (POST to /agui/run, read AG-UI events). To swap the transport or integrate with a different backend shape:

Option A — Custom fetch (same protocol, different auth/proxy):

<OctoFlowProvider
  baseUrl="/api/octoflow"
  customFetch={async (input, init) => {
    // Add auth headers, inject tenant id, route to a different host, etc.
    return fetch(input, { ...init, headers: { ...init?.headers, 'X-Tenant': 'acme' } });
  }}
>

Option B — Custom route handler (server-side: different agent, model, or tool set per tenant):

// app/api/octoflow/agui/run/route.ts
import { createOctoFlowRouteHandler } from '@octoflow/react/server';

export const POST = createOctoFlowRouteHandler({
  authenticate: (req) => verifyJwt(req),
  runAgent: async (input, ctx) => {
    // Swap agent, model, tool set, or execution environment per request.
    const agent = await pickAgent(ctx.auth);
    return agent.run(input);   // returns ReadableStream or AsyncIterable<string>
  },
});

Option C — AG-UI protocol adapter (different frontend UI library):

import { createOctoFlowAguiConfig } from '@octoflow/react/ag-ui';
import { HttpAgent } from '@ag-ui/client';

// Same server, different client library:
const config = createOctoFlowAguiConfig({ baseUrl: '/api/octoflow' });
const agent = new HttpAgent(config);   // works with any AG-UI-compatible UI

AG-UI and hooks — unified contract: Every integration path (hooks, AG-UI, AI SDK UI, CopilotKit) connects to the same OctoFlow server endpoint (/agui/run). The endpoint speaks the AG-UI SSE protocol — useOctoFlowChat parses it natively, while the @octoflow/react/ag-ui subpath exposes the raw config for third-party AG-UI clients. Choose the integration path based on your UI layer, not your backend.

Integration Examples

| Framework | Path | | --- | --- | | Headless React hooks (canonical) | packages/octoflow-examples/src/apps/app-react-hooks-chatbot/ | | Raw AG-UI client | packages/octoflow-examples/src/apps/app-react-ag-ui-chatbot/ | | CopilotKit / AG-UI | packages/octoflow-examples/src/apps/app-react-copilotkit-ag-ui-chatbot/ | | AI SDK UI | packages/octoflow-examples/src/apps/app-react-ai-sdk-ui-chatbot/ | | assistant-ui | Use @octoflow/react/ag-ui config → @assistant-ui/react-ag-ui |

Transport Capabilities

Current default capabilities (OCTOFLOW_REACT_DEFAULT_CAPABILITIES):

| Capability | Supported | | --- | --- | | Streaming text | ✅ | | Tool calls | ✅ | | Tool results | ✅ | | Approvals | ✅ | | Provider catalog | ✅ | | State sync (STATE_SNAPSHOT/DELTA) | ❌ (post-MVP) | | Interrupt/resume | ❌ (post-MVP) | | Reconnect/resume stream | ❌ (post-MVP) |

Validation

npm run -w octoflow-react lint
npm run -w octoflow-react typecheck
npm run -w octoflow-react test

Package Boundaries

  • @octoflow/react (root) — browser-safe; no octoflow-core import; React peer only.
  • @octoflow/react/ag-ui — browser-safe; optional @ag-ui/client peer.
  • @octoflow/react/server — server/node; may depend on octoflow-core via the runAgent callback.

Status

Marked Preview until:

  • Transport compatibility tests pass.
  • AI SDK UI / AG-UI examples are runnable.
  • Approval and session semantics are documented per transport.
  • Gateway beta/preview caveats are explicit in each hook's docs.

See docs/ag-ui.md and the package tests for the supported transport behavior.