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

@folotoy/folotoy-openclaw-plugin

v0.5.9

Published

Empower your FoloToy with OpenClaw AI capabilities.

Readme

@folotoy/folotoy-openclaw-plugin

Empower your FoloToy with OpenClaw AI capabilities.

An OpenClaw channel plugin that bridges FoloToy smart toys with OpenClaw via MQTT.

FoloToy Toy  <──MQTT──>  FoloToy MQTT Broker  <──MQTT──>  Plugin  <──>  OpenClaw

Installation

Interactive install (scan QR code to pair your toy):

npx @folotoy/folotoy-openclaw-plugin install

Or install manually:

openclaw plugins install @folotoy/folotoy-openclaw-plugin

The interactive installer will pair your toy, write the config, and automatically restart the OpenClaw gateway.

For local development:

openclaw plugins install -l .

Configuration

The plugin supports two authentication flows. All fields are configured as flat key-value pairs in openclaw.json under channels.folotoy.

Flow 2: Direct SN + Key (Default)

| Field | Description | |-------|-------------| | flow | "direct" | | toy_sn | Toy serial number | | toy_key | Toy key (used as MQTT password) | | mqtt_host | MQTT broker host (default: 198.19.249.25) | | mqtt_port | MQTT broker port (default: 1883) | | summary_enabled | Enable reply summarization (default: true) | | summary_max_chars | Character threshold for summarization (default: 200) |

Flow 1: HTTP API Login

Exchange an API key for MQTT credentials via the FoloToy API:

| Field | Description | |-------|-------------| | flow | "api" | | toy_sn | Toy serial number | | api_url | FoloToy API base URL (default: https://api.folotoy.cn) | | api_key | Bearer token | | mqtt_host | MQTT broker host | | mqtt_port | MQTT broker port (default: 1883) |

Example openclaw.json:

{
  "channels": {
    "folotoy": {
      "flow": "direct",
      "toy_sn": "your-toy-sn",
      "toy_key": "your-toy-key",
      "mqtt_host": "198.19.249.25",
      "summary_enabled": true,
      "summary_max_chars": 200
    }
  }
}

MQTT

Inbound and outbound use separate topics:

Inbound      (Toy → Plugin):  /openapi/folotoy/{sn}/thing/command/call
Outbound     (Plugin → Toy):  /openapi/folotoy/{sn}/thing/command/callAck
Notification (Plugin → Toy):  /openapi/folotoy/{sn}/thing/event/post

The plugin connects with an openapi: prefix on the clientId to distinguish itself from the toy's own connection:

clientId: openapi:{toy_sn}
username: {toy_sn}
password: {toy_key}

Connection failures trigger exponential backoff reconnection (1s → 2s → 4s → ... → 60s max), resetting on successful connect.

Message Format

Toy → Plugin (inbound)

{
  "msgId": 1,
  "identifier": "chat_input",
  "inputParams": {
    "text": "hello",
    "recording_id": 100
  }
}

Plugin → Toy (outbound)

Reply is buffered, then summarized if it exceeds summary_max_chars. Sent as a single message with auto-incrementing order, followed by a finish message:

{
  "msgId": 1,
  "identifier": "chat_output",
  "outParams": {
    "content": "hello",
    "recording_id": 100,
    "order": 1,
    "is_finished": false
  }
}

Finish message (is_finished: true, empty content):

{
  "msgId": 1,
  "identifier": "chat_output",
  "outParams": {
    "content": "",
    "recording_id": 100,
    "order": 2,
    "is_finished": true
  }
}

msgId starts at 1 per session and auto-increments. recording_id is passed through from the inbound message.

Plugin → Toy (notification)

Proactive messages (e.g., timer reminders) use the event/post topic with a different identifier and payload format:

{
  "msgId": 1,
  "identifier": "send_notification",
  "outParams": {
    "text": "Time to drink water!"
  }
}

Notifications are triggered via the OpenClaw --deliver mechanism (see Testing Notifications).

Environments

| Environment | MQTT Host | Port | |-------------|-----------|------| | Development | 198.19.249.25 | 1883 | | Testing | f.qrc92.cn | 1883 | | Production | f.folotoy.cn | 1883 |

Switch environments via the FOLOTOY_MQTT_HOST environment variable or mqtt_host config field.

Features

Reply Summarization

When AI reply exceeds summary_max_chars (default 200), the plugin uses the primary model to generate a concise summary before sending to the toy. This avoids excessively long voice playback. Falls back to truncation on failure. Disable with summary_enabled: false.

Soothing Acknowledgment

Immediately sends a transitional reply (e.g., "Let me think...") upon receiving a message, providing instant feedback while the AI processes.

Exponential Backoff Reconnection

MQTT connection failures trigger automatic reconnection with exponential backoff (1s → 60s cap), resetting on success.

Auto-restart Gateway

After interactive installation (npx @folotoy/folotoy-openclaw-plugin install), the plugin automatically restarts the OpenClaw gateway so changes take effect immediately.

Testing Notifications

To send a proactive notification to the toy via OpenClaw:

openclaw agent --agent main \
  --message "你的通知内容" \
  --deliver \
  --reply-channel folotoy \
  --reply-account default \
  --reply-to <toy_sn>

This triggers the outbound.sendText path, which publishes a send_notification message to the event/post MQTT topic. The toy will receive and play the notification.

Development

pnpm install
pnpm test
pnpm build

MQTT Integration Test

A manual integration test script simulates a FoloToy toy by connecting to the MQTT broker, sending a message, and verifying the response format.

Configure .env:

FOLOTOY_TOY_SN=your-toy-sn
FOLOTOY_TOY_KEY=your-toy-key
FOLOTOY_MQTT_HOST=192.168.10.100
FOLOTOY_MQTT_PORT=1883
FOLOTOY_TEST_MQTT_USERNAME=testuser      # optional, defaults to TOY_SN
FOLOTOY_TEST_MQTT_PASSWORD=testpassword  # optional, defaults to TOY_KEY

Run:

# Chat test — verify soothing ack, AI reply, finish message
node --env-file=.env src/__tests__/test-message.mjs chat "你好"

# Reminder test — verify reply + wait for notification on event/post topic
node --env-file=.env src/__tests__/test-message.mjs reminder

License

MIT