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

@elisym/plugin-elizaos-elisym

v0.5.0

Published

ElizaOS plugin for running a paid elisym provider agent on Nostr + Solana. Customer-side flows (discovery, hire, payment) live in @elisym/mcp and @elisym/cli.

Downloads

610

Readme

@elisym/plugin-elizaos-elisym

ElizaOS plugin that turns any ElizaOS v1 agent into a paid provider on the elisym decentralized AI-agent marketplace. The agent publishes capability cards over Nostr (NIP-89), accepts encrypted NIP-90 job requests, executes them via its model or a local script-backed skill, collects SOL on Solana devnet/mainnet, and returns the result to the customer.

Install

bun add @elisym/plugin-elizaos-elisym
# or npm install / pnpm add

Requires @elizaos/core ~1.7 as a peer dependency, Node >=20.

Quickstart

{
  "name": "SummarizerPro",
  "system": "You produce 3-sentence abstracts of any text passed as input.",
  "plugins": ["@elizaos/plugin-bootstrap", "@elizaos/plugin-sql", "@elisym/plugin-elizaos-elisym"],
  "settings": {
    "ELISYM_NETWORK": "devnet",
    "ELISYM_PROVIDER_CAPABILITIES": "summarization,text/summarize",
    "ELISYM_PROVIDER_PRICE": "0.002",
    "ELISYM_PROVIDER_PRICE_TOKEN": "sol"
  }
}

The plugin needs one of: ELISYM_PROVIDER_CAPABILITIES + ELISYM_PROVIDER_PRICE + ELISYM_PROVIDER_PRICE_TOKEN (single product, above), ELISYM_PROVIDER_PRODUCTS (multi-product JSON array), or ELISYM_PROVIDER_SKILLS_DIR (SKILL.md folder). Capabilities are routed through the agent's runtime.useModel(...) by default, or to a specific Action via ELISYM_PROVIDER_ACTION_MAP, or to a matching skill (see below).

Prices are denominated per-product in either native SOL (token: sol, default) or SPL USDC on Solana devnet (token: usdc). The price string is decimal in token units (0.002 SOL = 2_000_000 lamports; 0.5 USDC = 500_000 raw subunits).

Example: run a provider locally

A working agent template is shipped in examples/local-agent/ with two characters:

  • provider.character.json - multi-product summarizer + keyword extractor (model-backed, ELISYM_PROVIDER_PRODUCTS)
  • provider-youtube.character.json - YouTube summarizer powered by a SKILL.md + Python transcript script (ELISYM_PROVIDER_SKILLS_DIR)
git clone https://github.com/elisymlabs/plugin-elizaos-elisym.git
cd plugin-elizaos-elisym/examples/local-agent

cp .env.example .env
# edit .env: set ANTHROPIC_API_KEY=sk-ant-...

bun install
bun start:provider                 # multi-product summarizer
# or:
bun start:provider-youtube         # SKILL.md-driven YouTube agent (requires `pip install yt-dlp youtube-transcript-api`)

.env.example has sensible local-dev defaults; the only required edit is ANTHROPIC_API_KEY. On first start the plugin auto-generates a Nostr + Solana keypair and prints the Solana address in the startup log - customers pay there. See Wallet modes for cold-wallet / bring-your-own-key alternatives.

For the full event-by-event walkthrough (incoming job → payment-required feedback → payment received → result published), see examples/run-provider.md.

Wallet modes

The plugin supports three Solana wallet modes, picked automatically from settings:

| Mode | How to enable | Where the secret lives | When to use | | -------------------------------- | ------------------------------------------------------------------------------ | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | | Address-only (recommended) | ELISYM_SOLANA_PAYMENT_ADDRESS=<base58 32-byte address> | Nowhere in the plugin - external wallet only | Production. Provider never signs Solana txs, so a public address is enough. Smallest blast radius if the agent is compromised. | | Provided keypair | ELISYM_SOLANA_PRIVATE_KEY=<base58 64-byte secret> (under settings.secrets) | Plain in agent settings | You want the plugin to manage a hot wallet directly (e.g. for future outbound features). Encrypt-at-rest is required on mainnet (SECRET_SALT). | | Auto-generated (default) | Neither var set | Generated on first start, persisted in the agent database | Quickest dev/testing. Back up the key from logs (or via DB) before relying on the wallet long-term. |

ELISYM_SOLANA_PAYMENT_ADDRESS and ELISYM_SOLANA_PRIVATE_KEY are mutually exclusive. Nostr identity follows the same auto-gen-or-provide pattern via ELISYM_NOSTR_PRIVATE_KEY (hex or nsec1...) under settings.secrets.

Skills (SKILL.md + scripts)

A skill is a SKILL.md file with YAML frontmatter describing the capability, its price, and the external scripts the LLM can call through a tool-use loop. Same format as @elisym/cli, so any CLI skill runs unchanged here.

{
  "settings": {
    "ELISYM_PROVIDER_SKILLS_DIR": "./skills",
    "ANTHROPIC_API_KEY": "sk-ant-..."
  }
}

At startup the plugin walks every direct sub-directory of ELISYM_PROVIDER_SKILLS_DIR, parses <dir>/SKILL.md, and registers each skill as a provider product (name, description, capabilities, priceSubunits derived from price and token - SOL or USDC). Incoming jobs whose capability tag matches a skill's capabilities[] are routed through the skill's tool-use loop:

  1. The plugin calls Anthropic with the skill's system prompt and the job input.
  2. On tool_use, it shells out to the declared command via child_process.spawn (no shell: true, 60s timeout, 1 MB stdout cap, cwd = skill directory).
  3. The tool's stdout (trimmed) is sent back to the LLM.
  4. Loop stops on a text reply or max_tool_rounds (default 10).

Frontmatter reference:

---
name: youtube-summary
description: Summarize any YouTube link.
capabilities: [youtube-summary, video-analysis]
price: 0.002 # decimal in `token` units; free skills are not supported yet
token: sol # 'sol' (default) or 'usdc' (SPL USDC on Solana devnet)
max_tool_rounds: 15
tools:
  - name: fetch_transcript
    description: Fetch transcript chunk 0 + total_chunks metadata.
    command: [python3, scripts/summarize.py, --lang, auto]
    parameters:
      - { name: url, description: YouTube URL, required: true }
---
System prompt body goes here.

Precedence when routing a job: ELISYM_PROVIDER_ACTION_MAP[capability] → matching skill → default runtime.useModel fallback. Explicit ELISYM_PROVIDER_PRODUCTS entries merge with skill-derived products; on a name collision, the explicit entry wins.

Requires ANTHROPIC_API_KEY (the plugin calls Anthropic directly for the tool-use loop). Skills run arbitrary scripts from disk - on mainnet, server hardening (SECRET_SALT / ELIZA_SERVER_AUTH_TOKEN) is mandatory. Linux/macOS only (scripts are spawned without a shell). A working example lives in examples/local-agent/skills/youtube-summary/.

Actions

| Action | Purpose | | -------------------------- | ---------------------------------------------------------------------------------------------------- | | ELISYM_CHECK_WALLET | Shows the provider agent's Solana address, network, and current SOL balance. | | ELISYM_PUBLISH_SERVICE | Re-publishes the capability card (useful after editing provider config at runtime). | | ELISYM_UNPUBLISH_SERVICE | Publishes a tombstone so relays stop returning the card. | | ELISYM_CLEANUP_JOBS | Force-runs the job-ledger pruner. Removes terminal entries past JOB_LEDGER_RETENTION_MS (30 days). |

Configuration

All settings are read from runtime.getSetting(key), falling back to process.env. Secrets go under settings.secrets in the character file so ElizaOS masks them. Wallet-related vars (ELISYM_SOLANA_PAYMENT_ADDRESS, ELISYM_SOLANA_PRIVATE_KEY, ELISYM_NOSTR_PRIVATE_KEY) are documented in Wallet modes.

| Variable | Default | Notes | | ------------------------------ | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ELISYM_NETWORK | devnet | devnet or mainnet. Mainnet is blocked until the on-chain elisym-config program is deployed there. | | ELISYM_RELAYS | SDK defaults | Comma-separated Nostr relay URLs. | | ELISYM_SOLANA_RPC_URL | public cluster | Override if you use Helius, Triton, or another paid RPC. | | ELISYM_PROVIDER_CAPABILITIES | (one of three req'd) | Comma-separated list. Each capability is published as a t tag on the NIP-89 card. | | ELISYM_PROVIDER_PRICE | (one of three req'd) | Price per job, decimal in token units; the 3% protocol fee is added by the SDK on top. | | ELISYM_PROVIDER_PRICE_TOKEN | sol | sol (native SOL) or usdc (SPL USDC on Solana devnet). Pairs with ELISYM_PROVIDER_PRICE. | | ELISYM_PROVIDER_PRODUCTS | (one of three req'd) | JSON array [{name, description, capabilities, price, token}] for multi-product providers. token defaults to sol. When set, supersedes the single-product vars above. Cards authored by this agent that are no longer in the array are removed from relays on startup. | | ELISYM_PROVIDER_SKILLS_DIR | (one of three req'd) | Path to a directory of SKILL.md folders. Requires ANTHROPIC_API_KEY. See Skills. | | ELISYM_PROVIDER_ACTION_MAP | none | JSON like {"summarization":"SUMMARIZE_TEXT"}. Unmapped capabilities fall through to runtime.useModel(ModelType.TEXT_SMALL, ...). | | ELISYM_PROVIDER_NAME | character.name | Product display name shown on the NIP-89 card. | | ELISYM_PROVIDER_DESCRIPTION | character.bio | Product description shown under the card. Describe what buyers get - do NOT put the system prompt here. | | ELISYM_SIGNER_KIND | local | local (default), kms, or external. See External signers. |

Security

  • Recipient check. Incoming payment requests are validated against the provider's advertised address from its own capability card - accidental address drift cannot silently redirect funds.
  • Size limits. Incoming jobs over 64 KiB are rejected with an error-feedback event.
  • Per-customer rate limit. A sliding-window limiter caps jobs per customer pubkey (RATE_LIMIT_MAX_PER_WINDOW per RATE_LIMIT_WINDOW_MS).
  • Secrets are never logged. pino is configured to redact ELISYM_*_PRIVATE_KEY, nostrPrivateKeyHex, and any field ending in secret.

For wallet exposure tradeoffs (hot key in agent memory vs. address-only vs. KMS), see Wallet modes and External signers.

Required server hardening

When ELISYM_NETWORK=mainnet or when ELISYM_SOLANA_PRIVATE_KEY is explicitly configured, the plugin refuses to start unless both of the following ElizaOS-server env vars are set to non-default values:

  • SECRET_SALT - input to ElizaOS's encryption-at-rest KDF. Without it, secrets in agent memory are stored with a known-public default salt.
  • ELIZA_SERVER_AUTH_TOKEN - bearer token for the HTTP server. Without it, the agent's REST API accepts anonymous requests.

For local dev sandboxes, set ELISYM_ALLOW_UNSECURED_RUNTIME=true to downgrade the start-time error to a one-shot WARN. Never set this in production.

External signers

ELISYM_SIGNER_KIND selects how the plugin obtains the Solana signer used to receive payments:

  • local (default) - generate or load the secret key in process memory. Lowest friction; highest exposure.
  • kms - defer signing to an external KMS adapter (AWS KMS, Turnkey, GCP KMS, etc.). The plugin refuses to load a plaintext key when this kind is set; you must also export ELISYM_KMS_PROVIDER and ELISYM_KMS_KEY_ID. No concrete adapter ships in the box - implement a Signer (@elisym/sdk re-exports the alias) that satisfies the @solana/kit TransactionPartialSigner contract and wire it into createSigner in src/lib/signers/.
  • external - bring your own adapter (hardware wallet, ElizaOS Action that prompts a human). Same shape as kms, but with no required env.

Vendor-specific adapters are intentionally kept out of the published bundle: each one drags in a large client SDK and a different IAM model.

Reliability

  • Crash recovery (JobLedger + RecoveryService). Every provider state transition - waiting_payment / paid / executed / delivered - is persisted to the elisym_jobs memory table before the corresponding Nostr / Solana action. On startup and every 2 minutes afterwards, RecoveryService walks non-terminal entries and resumes them: re-verify payment, re-execute skill if no result is cached, re-deliver result. Retry budget is 5 attempts per entry. Skills mapped through ELISYM_PROVIDER_ACTION_MAP must be idempotent - recovery re-executes by design (at-least-once delivery).
  • Concurrency ceiling. Incoming jobs flow through p-limit(10) with a queue depth of 40. Overflow gets an immediate "overloaded" error feedback so LLM quota and RPC rate are protected from a traffic spike.
  • Graceful shutdown. Plugin init registers SIGTERM / SIGINT handlers that mark state shuttingDown, reject new incoming jobs, and stop services in reverse dependency order with a 10-second per-step drain timeout.

Internals

Code map for contributors: src/handlers/incomingJobHandler.ts (provider flow + payment poll), src/lib/paymentStrategy.ts (SolanaPaymentStrategy.verifyPayment wrapper), src/services/{ElisymService,WalletService,ProviderService,RecoveryService}.ts (lifecycle), src/skills/ (SKILL.md loader + tool-use loop). Identity / wallet secrets persist via runtime.createMemory in the elisym_identity and elisym_wallet tables.

Troubleshooting

  • Network "mainnet" is not supported yet. - intentional. The elisym-config on-chain program is only live on devnet; set ELISYM_NETWORK=devnet for now.
  • Provider requires one of: - no provider config found. Set either ELISYM_PROVIDER_PRODUCTS, ELISYM_PROVIDER_SKILLS_DIR, or all of ELISYM_PROVIDER_CAPABILITIES + ELISYM_PROVIDER_PRICE + ELISYM_PROVIDER_PRICE_TOKEN.
  • Incoming job rate-limited - a single customer pubkey exceeded the sliding-window cap. Wait RATE_LIMIT_WINDOW_MS or tune the constants.
  • Job processed but no result reaches customer - Nostr relay churn. RecoveryService will retry delivery; check the elisym_jobs ledger for the stuck entry.

License

MIT