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

@svadmin/ai-elements

v0.8.0

Published

Composable Svelte 5 AI interaction components for SVAdmin

Readme

@svadmin/ai-elements

Composable AI interaction components for Svelte 5 and SVAdmin. The package uses runes, snippets, and structured message parts instead of a single string-only chat component.

Install

bun add @svadmin/ai-elements @svadmin/core @sinclair/typebox @tanstack/svelte-query svelte

Import the package stylesheet once in your application CSS:

@import '@svadmin/ai-elements/ai.css';

The legacy ai.theme.css path is a plain-CSS alias of ai.css, not compiler metadata. Consumers need no Tailwind or Panda compiler plugin. Finite utility styles are generated from design/migrated-utilities by the repository build. Native conditional class composition preserves unknown host classes; it does not interpret arbitrary new utility-language strings.

Vite SSR

Vite SSR consumers must bundle the Svelte and ESM dependency boundary used by the complete package entry, including the explicitly vendored Markdown renderer:

import { defineConfig } from 'vite';

export default defineConfig({
  ssr: {
    noExternal: [
      '@svadmin/ai-elements',
      '@tanstack/svelte-query',
      '@xyflow/svelte',
      '@xyflow/system',
      'katex',
    ],
  },
});

The package's SSR verification loads the root entry through vite.ssrLoadModule and renders representative components with svelte/server.

Core Components

  • Conversation, Message, Response, and PromptInput
  • Reasoning, Tool, Sources, and InlineCitation
  • ChatDialog, CopilotPanel, AICommandBar, InsightCard, SmartSuggest, and VoiceInput

Agent Components

  • Chat and workflow: ChainOfThought, Checkpoint, Confirmation, Plan, Question, Queue, Shimmer, Suggestion, and Task
  • Context and output: Attachments, ModelSelector, Context, Artifact, Image, OpenIn, and WebPreview
  • Developer output: Agent, CodeBlock, Commit, EnvironmentVariables, FileTree, JSXPreview, PackageInfo, Sandbox, SchemaDisplay, Snippet, StackTrace, Terminal, and TestResults
  • Voice: AudioPlayer, MicSelector, Persona, SpeechInput, Transcription, and VoiceSelector
  • Utilities: CopyButton, Loader, ContextIcon, TokensWithCost, ToolStatusBadge, and PromptInputSpeechButton
  • Workflow canvas: Canvas, Connection, Controls, Edge, Node, Panel, and Toolbar

Example

<script lang="ts">
  import {
    Conversation,
    Message,
    MessageContent,
    MessageResponse,
    messageText,
    PromptInput,
  } from '@svadmin/ai-elements';

  let prompt = $state('');
  const message = {
    id: 'welcome',
    role: 'assistant' as const,
    parts: [{ type: 'text' as const, text: 'How can I help?' }],
    status: 'complete' as const,
    createdAt: Date.now(),
  };
</script>

<Conversation>
  <Message from={message.role} data-message-id={message.id}>
    <MessageContent>
      <MessageResponse content={messageText(message)} />
    </MessageContent>
  </Message>
</Conversation>

<PromptInput bind:value={prompt} />

Messages use the ChatMessagePart contract from @svadmin/core, including text, reasoning, tool calls/results, sources, images, files, approvals, and generated components.

Generated components use TypeBox as their runtime boundary. The schema also drives the Svelte component prop type. Root object schemas are strict by default, so undeclared model-provided props are rejected even when the caller does not set additionalProperties: false:

import { Type } from '@sinclair/typebox';
import { defineGeneratedComponent } from '@svadmin/ai-elements';
import InventorySummary from './InventorySummary.svelte';

export const componentRegistry = {
  InventorySummary: defineGeneratedComponent({
    component: InventorySummary,
    schema: Type.Object({
      warehouse: Type.String(),
      count: Type.Number(),
      limit: Type.Optional(Type.Integer({ minimum: 1, maximum: 100 })),
    }),
  }),
};

Admin tools use the same TypeBox boundary. Call tools through executeAdminTool so untrusted model arguments are decoded before the tool implementation runs:

import { Type } from '@sinclair/typebox';
import { defineAdminTool, executeAdminTool } from '@svadmin/core';

const searchInventory = defineAdminTool({
  name: 'searchInventory',
  description: 'Search inventory by warehouse',
  parameters: Type.Object({
    warehouse: Type.String(),
    limit: Type.Optional(Type.Integer({ minimum: 1, maximum: 100 })),
  }),
  readOnly: true,
  execute: async ({ warehouse, limit }) => inventory.search({ warehouse, limit }),
});

await executeAdminTool(searchInventory, modelArguments);

Upstream parity and Markdown ownership

AI_ELEMENT_PARITY pins the audited vercel/ai-elements commit and verifies the 49-family, 398-export package surface. Export presence, behavior, and visual fidelity are tracked independently: an exact export name is not proof of interaction or pixel parity. JSXPreview intentionally uses a restricted, TypeBox-validated parser instead of executing arbitrary JSX. Tool.getStatusBadge returns Svelte-renderable status metadata instead of a React element.

Response uses the locked Apache-2.0 Streamdown 3.0.6 distribution under vendor/streamdown. Only its two theme class-composition calls are modified to remove the transitive class engine. Parser, streaming repair, URL policies and sanitizers are protected by original source hashes. LICENSE, modification notes and provenance are shipped. This copy requires explicit upstream maintenance; it does not automatically receive updates of the wrapper package. See THIRD_PARTY_NOTICES.md and vendor/streamdown/README.svadmin.md.

AdminApp Integration

Pass providers through the owning Svelte tree and render the assistant through the AdminApp snippet:

<AdminApp {dataProvider} {resources} {chatProvider}>
  {#snippet aiAssistant({ docked, scope, ownerScope })}
    <ChatDialog
      {docked}
      {scope}
      {ownerScope}
      persistKey={`user:${currentUser.id}:assistant`}
    />
  {/snippet}
</AdminApp>

History is in-memory by default. A non-empty persistKey enables localStorage; include a stable, non-secret user identity in the key. Use onPersist and onRestore for host-managed persistence. If restoration fails, the dialog blocks writes for that history scope instead of overwriting remote history; use onPersistenceError to report the failed operation.