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

@ergoblockchain/sage-widget

v0.3.0

Published

Embeddable Sage widgets for live activity and paid Accord Note chat on ergoblockchain.org. React, vanilla, typed API clients, and portable payment intents.

Readme

@ergoblockchain/sage-widget

npm license

Embeddable widgets for Sage — the agent-economy concierge on ergoblockchain.org. Use the read-only activity feed, or embed the paid Sage chat flow with quote, manual Note verification, streaming answer, receipt JSON, and public receipt link.

Why this matters: Sage settles real paid AI queries on Ergo testnet. The feed makes the "agent-economy" thesis visibly provable wherever you embed it — not a marketing claim, a list of public on-chain receipts that update live.

What v0.3 ships

  • <SagePaymentWidget /> React component.
  • mountSagePaymentWidget(target, opts) vanilla DOM mount.
  • Typed clients for quote, verify, chat stream, receipt bundle, and activity feed.
  • Tenant metadata and host-provided payment instructions.
  • Portable SagePaymentIntent JSON for host-owned wallet flows.
  • Optional walletLauncher(intent) callback so your app can open a reviewed wallet flow without letting the widget sign funds.
  • Payment lifecycle callbacks: quote, receipt, receipt bundle, tier, phase, status.
  • Public receipt links plus machine-readable /api/sage/receipt/<id> links.

The canonical Sage host is testnet live proof. It can produce full_receipt_bundle receipts with Agreement JSON, Verification Receipt JSON, and Settlement Receipt JSON. Mainnet readiness remains audit-gated.

Install

npm install @ergoblockchain/sage-widget
# or
pnpm add @ergoblockchain/sage-widget
# or
yarn add @ergoblockchain/sage-widget

react and react-dom are optional peer deps — only required if you import from /react.

Use it

React activity feed

import { SageActivityFeed } from "@ergoblockchain/sage-widget/react"

export function Footer() {
  return <SageActivityFeed limit={5} refreshMs={60_000} />
}

The component renders into your DOM (no iframe), styles itself with inline styles to avoid host-CSS conflicts, and polls /api/sage/activity on the host you point it at.

React paid chat

import { SagePaymentWidget } from "@ergoblockchain/sage-widget/react"

export function PaidSageBox() {
  return (
    <SagePaymentWidget
      tenant={{ id: "my-site", label: "My Ergo app" }}
      paymentInstructions={{
        helperText: "Issue the quoted Accord Note from your testnet wallet, then paste the Note box id.",
        walletUrl: "https://www.ergoblockchain.org/build/agent-payments",
        walletLauncherLabel: "Open my testnet wallet",
      }}
      onQuote={(quote) => console.log("Sage quote", quote)}
      onPaymentIntent={(intent) => console.log("Wallet intent", intent)}
      onReceipt={(receipt) => console.log("Sage receipt", receipt.receiptUrl)}
      onReceiptBundle={(bundle) => console.log("Receipt completeness", bundle.completeness)}
      walletLauncher={async (intent) => {
        // Your app owns wallet policy, ErgoPay/Fleet integration and signing.
        // Return a Note box id when the wallet creates the testnet Note.
        console.log("Create a Note for", intent.amountErg, intent.receiverAddress)
        return { ok: true, noteBoxId: "" }
      }}
    />
  )
}

The paid widget calls /api/sage/quote, shows the Accord Note payment fields, accepts a noteBoxId, calls /api/sage/verify-payment, streams /api/sage/chat, then surfaces the receipt link from /api/sage/receipt/<id>.

Vanilla / non-React activity feed

import { mountSageFeed } from "@ergoblockchain/sage-widget/vanilla"

const handle = mountSageFeed(document.getElementById("sage-feed")!, {
  limit: 5,
  refreshMs: 60_000,
})

// later, if you want to tear down:
handle.destroy()

Or use the canonical hosted CDN drop-in (no install needed):

<div id="sage-feed"></div>
<script src="https://www.ergoblockchain.org/agents.js"
        data-target="#sage-feed"
        data-height="320"
        async></script>

That last form is an iframe variant served straight from ergoblockchain.org — total style isolation, zero install. Use the npm package when you want the markup inline (themable, accessibility-friendly, tree-shakeable).

Vanilla / non-React paid chat

import { mountSagePaymentWidget } from "@ergoblockchain/sage-widget/vanilla"

const handle = mountSagePaymentWidget(document.getElementById("sage-chat")!, {
  tenant: { id: "docs-footer", label: "Docs footer" },
  onPaymentIntent: (intent) => console.log("[sage] payment intent", intent),
})

// You can also start a question programmatically:
await handle.send("/research explain Ergo Notes")

// Inspect embed state:
console.log(handle.status().receipt?.receiptUrl)

Just the types

If you want to render your own UI over Sage's API and skip the bundled components:

import {
  fetchSageActivity,
  fetchSageQuote,
  streamSageChat,
  verifySagePayment,
  type SageActivityEvent,
  type SageActivityResponse,
} from "@ergoblockchain/sage-widget"

const data: SageActivityResponse = await fetchSageActivity({ limit: 10 })
const settlements = data.events.filter((e) => e.type === "settlement")

Useful helpers:

import { fetchSageReceipt, isFullSageReceiptBundle } from "@ergoblockchain/sage-widget"

const receipt = await fetchSageReceipt("f8752d10a2ece92fbc88065c3b92b94da621ec65943098f43c9e084deb763d81")

if (isFullSageReceiptBundle(receipt)) {
  console.log("Agreement JSON is present", receipt.accord?.agreement_json)
}

Payment intent bridge

v0.3 adds a small but important contract between the widget and your wallet layer. The widget still does not sign transactions. Instead it emits a portable intent:

import {
  createSagePaymentIntent,
  serializeSagePaymentIntent,
} from "@ergoblockchain/sage-widget"

const intent = createSagePaymentIntent({
  question: "/deep explain Ergo Notes",
  quote,
  tenant: { id: "my-wallet", label: "My Wallet" },
})

console.log(serializeSagePaymentIntent(intent))

The intent includes network, receiver, amount, reserve box, task hash, expiry, verification endpoint, and receipt endpoint template. A wallet integration can turn it into an Ergo testnet Note, then hand the Note box id back to the widget for verification.

Render-prop / bring-your-own-design

<SageActivityFeed>
  {({ response, loading }) => (
    <MyOwnDesign events={response?.events ?? []} loading={loading} />
  )}
</SageActivityFeed>

Options

| Prop | Type | Default | Notes | | --------------- | --------------------------------- | ----------------------------------------- | ---------------------------------------------------------------------------------------------- | | apiBase | string | "https://www.ergoblockchain.org" | Override if you run your own Sage deployment behind a custom domain. | | limit | number | 5 | Max 25. | | refreshMs | number | 60000 | Poll interval. Set to 0 to fetch once on mount and never refresh. | | onUpdate | (r: SageActivityResponse) => void | — | Fired after every successful poll. | | onError | (err: unknown) => void | console.warn | Fired on fetch failure. | | className | string | — | Applied to the root container (React only). | | style | CSSProperties | — | Inline style merged onto the root container (React only). | | children | render-prop | — | Pass a function for full UI control; the component will skip the default markup. |

SagePaymentWidget also accepts:

| Prop | Type | Notes | | ------------------- | ----------------------------------------- | ----------------------------------------------------------- | | tenant | { id?: string; label?: string; headers?: Record<string,string> } | Stable embed metadata and optional request headers. | | initialMessages | SageChatMessage[] | Preloaded chat context. | | title | string | Widget heading. | | placeholder | string | Input placeholder. | | paymentInstructions | { helperText?: string; walletUrl?: string; noteBoxLabel?: string } | Host-specific payment copy and guide link. | | onMessage | (message, messages) => void | Fired when the widget appends a chat message. | | onQuote | (quote) => void | Fired after Sage returns a premium quote. | | onReceipt | (receipt) => void | Fired after payment verifies and a receipt URL exists. | | onReceiptBundle | (bundle) => void | Fired after the widget fetches /api/sage/receipt/<id>. | | onTier | ("free" \| "premium") => void | Fired when the stream reports model tier. | | onPhase | (phase) => void | Fired on widget phase changes: idle, quoting, payment_required, verifying, streaming, error. | | onPaymentIntent | (intent) => void | Fired when a premium quote becomes a structured wallet intent. | | walletLauncher | (intent) => Promise<{ ok; noteBoxId? }> | Optional host-owned wallet flow. The widget never signs itself. | | showPaymentIntent | boolean | Shows or hides the default payment-intent JSON panel. Default true. | | testnetWarning | string \| false | Default testnet safety copy. Set false to hide. | | onStatus | (status) => void | Fired with a compact snapshot of phase, tier, quote, payment intent, receipt, receipt bundle, and error. |

onStatus and the vanilla handle.status() also include paymentIntent, messages, and activeQuestion, so hosts can mirror widget state into their own telemetry or UI.

Payment model

v0.3 deliberately does not sign wallet transactions inside the widget. The widget shows the quote fields, emits a portable payment intent, accepts a Note box id, verifies it through Sage, then streams the answer and exposes the receipt. Hosts can pair it with their own wallet flow, Accord tooling, ErgoPay/Fleet integration, or a manual testnet Note issuer.

For the canonical site, a successful paid flow looks like:

question -> quote -> Ergo testnet Note -> verify-payment -> receipt bundle -> Sage answer

The public receipt API is the source of truth. Articles, dashboards, and registry entries should link to it instead of duplicating receipt fields.

Event shape

Each event in response.events is a typed object:

{
  txId: string                       // 64-char hex
  blockHeight: number
  timestamp: number                  // ms epoch
  type: "settlement" | "issuance" | "transfer"
  inflowNanoErg: number              // sum of outputs to Sage wallet
  paymentNanoErg?: number            // value of redeemed Note (settlements only)
  noteBoxId?: string                 // first Note-shape input
}

For settlements, use paymentNanoErg (the value of the consumed Note) for "amount paid" display. inflowNanoErg includes change boxes when buyer and seller share an address in test setups.

Related

Release checks

Before publishing:

npm run typecheck
npm run smoke
npm pack --dry-run

Roadmap

  • v0.1.x — read-only activity feed (React + vanilla + types).
  • v0.2<SagePaymentWidget /> paid chat with quote, manual Note verify, streaming answer, receipt link, tenant config.
  • v0.3 (current source) — payment-intent bridge, wallet launcher callback, stronger host telemetry, clearer testnet safety copy.
  • v0.4 — generic <AccordActivityFeed providerId="..." /> that works for any provider in the registry, not just Sage.

License

MIT