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

@charivo/core

v0.0.1

Published

Core functionality for Charivo character system

Readme

@charivo/core

Core types, interfaces, and event bus for the Charivo framework.

Features

  • 🎯 Core Types - Shared types for messages, characters, and configuration
  • 🔌 Interface Definitions - Standard interfaces for LLM, TTS, and Renderer
  • 📡 Event Bus - Type-safe event system for component communication
  • 🎨 Extensible - Build custom clients, players, and providers

Installation

pnpm add @charivo/core

Usage

Basic Setup

import { Charivo } from "@charivo/core";
import { createLLMManager } from "@charivo/llm-core";
import { createTTSManager } from "@charivo/tts-core";
import { createRenderManager } from "@charivo/render-core";
import { OpenAILLMClient } from "@charivo/llm-client-openai";
import { OpenAITTSPlayer } from "@charivo/tts-player-openai";
import { Live2DRenderer } from "@charivo/render-live2d";

// Initialize Charivo
const charivo = new Charivo();

// Setup LLM
const llmClient = new OpenAILLMClient({ apiKey: "your-api-key" });
const llmManager = createLLMManager(llmClient);
charivo.attachLLM(llmManager);

// Setup TTS
const ttsPlayer = new OpenAITTSPlayer({ apiKey: "your-api-key" });
const ttsManager = createTTSManager(ttsPlayer);
charivo.attachTTS(ttsManager);

// Disable TTS (optional)
// charivo.detachTTS();

// Setup Renderer
const renderer = new Live2DRenderer({ canvas });
await renderer.initialize();
await renderer.loadModel("/live2d/model.model3.json");
const renderManager = createRenderManager(renderer);
charivo.attachRenderer(renderManager);

// Set character
charivo.setCharacter({
  id: "hiyori",
  name: "Hiyori",
  personality: "Cheerful and helpful AI assistant"
});

// Start chatting
await charivo.userSay("Hello!");

API Reference

Charivo Methods

  • attachLLM(manager: LLMManager): void - Attach an LLM manager for conversation
  • attachTTS(manager: TTSManager): void - Attach a TTS manager for voice synthesis
  • detachTTS(): void - Detach the TTS manager to disable voice synthesis
  • attachRenderer(manager: RenderManager): void - Attach a renderer for visual output
  • setCharacter(character: Character): void - Set the character configuration
  • userSay(message: string): Promise<void> - Send a user message and get a response

Event Bus

import { EventBus } from "@charivo/core";

const eventBus = new EventBus();

// Subscribe to events
eventBus.on("tts:audio:start", (data) => {
  console.log("TTS started", data.audioElement);
});

eventBus.on("tts:audio:end", () => {
  console.log("TTS ended");
});

// Emit events
eventBus.emit("tts:audio:start", { audioElement });
eventBus.emit("tts:audio:end", {});

Core Types

Character

interface Character {
  id: string;
  name: string;
  personality: string;
  traits?: string[];
  background?: string;
  instructions?: string[];
}

Message

interface Message {
  id: string;
  content: string;
  timestamp: Date;
  type: "user" | "character" | "system";
}

MotionType

type MotionType = "greeting" | "happy" | "thinking" | "talk";

Core Interfaces

LLMManager

interface LLMManager {
  setCharacter(character: Character): void;
  getCharacter(): Character | null;
  clearHistory(): void;
  getHistory(): Message[];
  generateResponse(message: Message): Promise<string>;
}

TTSManager

interface TTSManager {
  speak(text: string, options?: TTSOptions): Promise<void>;
  stop(): Promise<void>;
  setVoice(voice: string): void;
  isSupported(): boolean;
  setEventEmitter?(eventEmitter: {
    emit: (event: string, data: any) => void;
  }): void;
}

RenderManager

interface RenderManager {
  initialize(): Promise<void>;
  render(message: Message, character?: Character): Promise<void>;
  setCharacter(character: Character): void;
  destroy(): Promise<void>;
  loadModel?(modelPath: string): Promise<void>;
  setMessageCallback?(callback: MessageCallback): void;
}

Renderer

interface Renderer {
  initialize(): Promise<void>;
  render(message: Message, character?: Character): Promise<void>;
  destroy(): Promise<void>;
  loadModel?(modelPath: string): Promise<void>;
  playMotion?(motionType: MotionType): void;
  animateExpression?(motionType: MotionType): void;
  setRealtimeLipSync?(enabled: boolean): void;
  updateRealtimeLipSyncRms?(rms: number): void;
}

Architecture

The Charivo framework follows a modular architecture:

Charivo (orchestrator)
├─ LLMManager (stateful)
│  └─ LLMClient (stateless)
│
├─ TTSManager (stateful)
│  └─ TTSPlayer (stateless)
│
└─ RenderManager (stateful)
   └─ Renderer (stateless)

Manager Pattern

  • Managers: Stateful components that handle business logic, state management, and coordination
  • Clients/Players/Renderers: Stateless components that handle pure operations (API calls, audio playback, rendering)

This separation allows:

  • Easy testing (mock the stateless components)
  • Flexibility (swap implementations without changing business logic)
  • Reusability (use clients independently or with managers)

Creating Custom Implementations

Custom LLM Client

import { LLMClient } from "@charivo/core";

class MyLLMClient implements LLMClient {
  async call(messages: Array<{role: string, content: string}>): Promise<string> {
    // Call your LLM API
    return "Response from my LLM";
  }
}

Custom TTS Player

import { TTSPlayer, TTSOptions } from "@charivo/core";

class MyTTSPlayer implements TTSPlayer {
  async speak(text: string, options?: TTSOptions): Promise<void> {
    // Play audio
  }

  async stop(): Promise<void> {
    // Stop playback
  }

  setVoice(voice: string): void {
    // Set voice
  }

  isSupported(): boolean {
    return true;
  }
}

Custom Renderer

import { Renderer, Message, Character, MotionType } from "@charivo/core";

class MyRenderer implements Renderer {
  async initialize(): Promise<void> {
    // Setup renderer
  }

  async render(message: Message, character?: Character): Promise<void> {
    // Render the message
  }

  async destroy(): Promise<void> {
    // Cleanup
  }

  // Optional methods
  playMotion?(motionType: MotionType): void {
    // Play motion
  }
}

Events

TTS Events

  • tts:audio:start - Emitted when TTS starts playing

    { audioElement: HTMLAudioElement }
  • tts:audio:end - Emitted when TTS stops playing

    {}

License

MIT