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

my-africhat

v0.2.1

Published

Embeddable My AfriChat widget for websites.

Readme

my-africhat

Widget embeddable pour ajouter un assistant IA My AfriChat sur un site web.

Depuis 0.2.1, le widget transmet aussi la configuration publique du package (assistant, branding, knowledgeBase) au backend a chaque message. Le launcher reste compact comme la demo du site: un bouton rond discret, avec le libelle affiche au survol. Le mode par defaut est floating.

Fonctionnement

  1. Le visiteur ouvre le widget et envoie un message.
  2. Le widget appelle widget-chat avec la siteKey publique et la configuration publique du fichier africhat.config.ts/js/json.
  3. L'Edge Function valide la cle, le domaine d'origine, charge la configuration active du site, puis applique les champs publics transmis par le package.
  4. Si l'audio est actif, widget-chat demande une reponse audio directe avec la config (assistant, branding, knowledgeBase) et modalities: ["text", "audio"].
  5. Si l'audio direct n'est pas supporte par l'upstream, le backend retombe sur le chemin texte puis gpt-audio-1.5 via /audio/speech.
  6. Le widget affiche le transcript renvoye et joue l'audio correspondant.

La cle d'inference privee reste toujours cote serveur. La siteKey du widget est publique mais limitee par domaine.

Modeles

Modeles texte configurables dans la plateforme ou dans africhat.config.ts/js/json:

  • gpt-5.4-mini
  • gpt-5.4
  • kimi-k2.5
  • glm-5.1

Modeles audio automatiques:

  • Audio direct: chat/completions avec modalities: ["text", "audio"]
  • Fallback TTS: gpt-audio-1.5
  • Realtime: gpt-realtime-1.5

Les champs historiques comme audioModel, audio_model, ttsModel ou speechModel ne sont plus necessaires. L'audio est choisi automatiquement pour eviter qu'un modele texte soit utilise comme modele vocal.

Le fichier africhat.config.ts/js/json pilote le comportement du package: assistant.persona, assistant.tone, assistant.model, assistant.reasoning_effort, assistant.web_search, assistant.multilingual et knowledgeBase sont transmis au backend a chaque message avant la generation audio.

Voix supportees:

  • alloy
  • echo
  • fable
  • onyx
  • nova
  • shimmer

Installation

npm install my-africhat

Configuration rapide

Dans ton projet client, stocke la cle dans une variable d'environnement publique adaptee a ton bundler.

VITE_AFRICHAT_SITE_KEY=afc_live_xxxxxxxxxxxx.yyyyyyyyyyyyyyyy

Puis cree africhat.config.ts ou africhat.config.js:

export const afriChatConfig = {
  version: 1,
  branding: {
    name: "Assistant",
    welcomeMessage: "Bonjour, comment puis-je vous aider ?",
    accentColor: "#5B4BFF",
    launcherLabel: "Discuter avec l'assistant",
    iconPreset: "afri-duo",
    iconSize: "medium",
  },
  assistant: {
    persona: "Conseiller client de ma boutique",
    tone: "friendly",
    model: "gpt-5.4-mini",
    reasoning_effort: "medium",
    voice: "alloy",
    audioMode: "auto",
    audioEnabled: true,
    multilingual: true,
  },
  knowledgeBase: {
    homeSummary: "Resume public de l'entreprise, des produits et des services.",
    businessRules: [
      "Repondre uniquement a partir des informations fournies.",
      "Proposer un contact humain si la demande sort du perimetre.",
    ],
  },
  integration: {
    mode: "floating",
    position: "bottom-right",
    zIndex: 999999,
  },
  api: {
    chatEndpoint: "https://YOUR_PROJECT.supabase.co/functions/v1/widget-chat",
    ttsEndpoint: "https://YOUR_PROJECT.supabase.co/functions/v1/widget-tts",
    realtimeTokenEndpoint: "https://YOUR_PROJECT.supabase.co/functions/v1/widget-realtime-token",
    siteKey: import.meta.env.VITE_AFRICHAT_SITE_KEY,
  },
};

Monte le widget cote client:

import { createMyAfriChat } from "my-africhat";
import { afriChatConfig } from "./africhat.config";

const widget = createMyAfriChat(afriChatConfig).mount();

React / Vite

import { useEffect } from "react";
import { createMyAfriChat } from "my-africhat";
import { afriChatConfig } from "./africhat.config";

export function AfriChatBootstrap() {
  useEffect(() => {
    const widget = createMyAfriChat(afriChatConfig).mount();
    return () => widget.destroy();
  }, []);

  return null;
}

HTML statique

<script type="module">
  import { createMyAfriChat } from "https://esm.sh/[email protected]";

  createMyAfriChat({
    assistant: { audioEnabled: true, voice: "alloy" },
    integration: { mode: "floating", position: "bottom-right" },
    api: {
      chatEndpoint: "https://YOUR_PROJECT.supabase.co/functions/v1/widget-chat",
      ttsEndpoint: "https://YOUR_PROJECT.supabase.co/functions/v1/widget-tts",
      realtimeTokenEndpoint: "https://YOUR_PROJECT.supabase.co/functions/v1/widget-realtime-token",
      siteKey: window.__ENV__.VITE_AFRICHAT_SITE_KEY,
    },
  }).mount();
</script>

API

createMyAfriChat(config) retourne:

  • mount(target?)
  • unmount()
  • destroy()
  • open()
  • close()
  • send(message)
  • updateConfig(nextConfig)

Options utiles

  • integration.mode: "floating" par defaut, ou "fullscreen".
  • integration.position: "bottom-right" ou "bottom-left".
  • branding.launcherLabel: texte affiche au survol du launcher compact.
  • branding.iconPreset: icone du launcher.
  • branding.iconSize: "small", "medium", "large".
  • assistant.audioEnabled: active ou coupe la generation vocale.
  • assistant.audioMode: auto tente l'audio direct puis fallback TTS, direct teste uniquement l'audio direct, tts force texte puis synthese vocale.
  • assistant.voice: voix TTS parmi les voix supportees.

Icones disponibles

  • afri-duo
  • afri-link
  • afri-orbit
  • afri-spark
  • afri-classic
  • afri-classic-soft
  • afri-classic-outline
  • afri-benin-green
  • afri-benin-yellow
  • afri-benin-red
  • afri-pan-africa
  • afri-kente
  • afri-sankofa
  • afri-sahel
  • afri-nile
  • afri-bronze
  • afri-baobab

Validation

  1. Le bouton rond apparait en bas a droite ou a gauche.
  2. Le clic ouvre le panneau de chat.
  3. Un message utilisateur retourne une reponse texte.
  4. Si audioEnabled: true, le widget joue l'audio de cette meme reponse.
  5. Le bouton Replay relit le message assistant affiche.

Depannage

Origin <domain> not allowed

Ajoute le host exact du site dans la plateforme. N'ajoute pas https:// ni de chemin.

Origin required

La requete doit partir d'une vraie page web avec un header Origin.

Upstream AI audio error

La generation audio directe ou son fallback a echoue. Le backend My AfriChat peut retenter avec gpt-5.4-mini, puis tomber sur le TTS gpt-audio-1.5 si l'audio direct n'est pas supporte. Verifie aussi que AFRI_API_KEY et AFRI_BASE_URL sont definis dans Supabase.

Audio absent ou different du texte

Mets a jour vers [email protected] et redeploie les fonctions Supabase recentes. En mode direct, le transcript de l'audio devient le texte affiche (message.audio.response_mode = "direct"). Si le fallback TTS est utilise, message.audio.input_text indique le texte transmis a gpt-audio-1.5.

Si l'audio lit encore un message du type "Bonjour, comment puis-je vous aider ?", verifie que le navigateur ne charge pas une ancienne version du package et que le bouton de relecture n'est pas celui du message d'accueil. Les versions recentes ne rendent plus le message d'accueil relisible par defaut.