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

@gea-ai/chat-ui

v0.1.260923-alpha.1

Published

Public React renderers for GEA Agent chat messages. The package owns standard message-part behavior, streaming Markdown, request `yaml-render`, and safe fallbacks while leaving visual identity under the Extension's control.

Readme

@gea-ai/chat-ui

Public React renderers for GEA Agent chat messages. The package owns standard message-part behavior, streaming Markdown, request yaml-render, and safe fallbacks while leaving visual identity under the Extension's control.

Usage

import {
  type AgentChatMessage,
  GeaChatUIProvider,
  GeaMessages,
} from "@gea-ai/chat-ui";
import "@gea-ai/chat-ui/styles.css";

export function Chat({
  addToolOutput,
  messages,
  resolveAssetUrl,
}: {
  addToolOutput: (input: {
    messageId?: string;
    tool: "request";
    toolCallId: string;
    output: unknown;
  }) => Promise<void>;
  messages: AgentChatMessage[];
  resolveAssetUrl: (url: string) => string | null;
}) {
  return (
    <GeaChatUIProvider
      actions={{
        addToolOutput,
        resolveAssetUrl,
      }}
      locale="zh-CN"
      theme={{ accent: "#e46161", radius: "16px" }}
    >
      <GeaMessages messages={messages} status="streaming" />
    </GeaChatUIProvider>
  );
}

The host owns transport and authorization. The renderer never starts chats or requests protected resources by itself.

GEA's own Web/Desktop app-ui uses the same GeaRequestPart and GeaYamlRender runtime, injecting host actions, locale, and thin shadcn visual components through yamlComponents. Request state binding, streaming previews, skipped/submitted states, and submission semantics therefore have one implementation across first-party and Extension hosts.

Custom YAML components receive normalized bindings, canonical button actions, and field-validation metadata. A visual adapter applies the supplied ARIA/data attributes, calls onFieldBlur, and renders the supplied errors; it does not parse YAML, run validation rules, own form state, infer request lifecycle, or implement submission transport.

Styling

Import the default stylesheet and override semantic variables or stable data-slot selectors. GeaChatUIProvider also accepts visual component slots for message frames, avatars, and part renderers. yamlComponents replaces the visual implementation of catalog components without changing their schema, state binding, or action semantics.

<GeaChatUIProvider
  components={{ AssistantAvatar: BrandAvatar }}
  theme={{ accent: "#c64141" }}
  yamlComponents={{ Card: BrandRequestCard }}
>
  {children}
</GeaChatUIProvider>

yaml-render

Interactive request UI is rendered directly from a request tool part. New Agents call request({ yaml: "root: ..." }); yaml contains the complete source without a Markdown fence and puts initial values in top-level YAML state. Invalid specs and legacy request-key inputs fail closed. Text yaml-render fences remain display-only and are never joined to a request. While an AI SDK part is input-streaming, the renderer shows a semantic loading placeholder until the partial YAML has a valid root, then renders the last valid spec as a locked preview. It remounts the final state once when the part becomes input-available, performs strict request validation, and immediately unlocks the active form even if adjacent assistant text continues streaming. Submission calls the host-provided addToolOutput({ messageId, tool: "request", toolCallId, output }) action. The renderer includes the persisted assistant messageId when it renders from a message, but it does not own persistence or continuation transport. An Extension host should submit the result through app.gea.chats.submitToolOutput(...), then update its local chat state and resume the stream. Without the action, an active request fails closed. When a newer message makes an unanswered request inactive, the form remains visible with locked controls and a Skipped/已跳过 submit label; it does not submit form state as a user message.

Fields bind checks to the same state path as their value (or checked for Checkbox). The runtime supports required, requiredIf, email, url, numeric, length/range, pattern, and cross-field comparison checks. Submit always validates every field before calling addToolOutput; validateOn controls earlier change/blur feedback. Empty optional fields skip other checks, while required Checkbox and Rating fields require an affirmative selection. Requiredness must be declared with a required or requiredIf check; words such as "required" in a label have no validation meaning.

name:
  type: Input
  props:
    label: Name
    value: { $bindState: /name }
    checks:
      - type: required
        message: Name is required
    validateOn: blur
  children: []

Completed request YAML with unsupported rules, invalid rule arguments, or unsafe state references fails closed. Validation messages are generated UI copy and should use the same language as the conversation.