No description
  • JavaScript 98.9%
  • Dockerfile 1.1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
w33ble 7ed7d80180 fix(bot-demo): emit NIP-10 root+reply tags so thread replies are accepted
A kind:9 reply tagged the immediate parent with a lone `reply` marker, which
NIP-10 resolves as a direct reply to the root. Inside a thread that claims the
parent is its own thread root, and the relay rejects the event at ingest with
`invalid: root tag does not match thread ancestry`. The bot logged a reply but
the relay stored nothing, so mentions inside threads looked ignored.

Add `replyTags()` to buzz-sdk: mirrors buzz-core::nip10 marker resolution (the
last valid root/reply marker wins; reply-only collapses to the root) and returns
a single `reply` tag for top-level parents or a `root` + `reply` pair for nested
ones. bot-demo builds reply tags through it.

Verified live against wss://buzz.w33ble.com: a reply-only tag to a thread
message is rejected with the ancestry error, the same reply with root+reply is
accepted, and after the change a thread @mention round-trips and is stored with
the correct root/reply markers. pnpm fmt:check and lint clean; pnpm test 12/12.
2026-09-12 20:36:38 -06:00
packages fix(bot-demo): emit NIP-10 root+reply tags so thread replies are accepted 2026-09-12 20:36:38 -06:00
.dockerignore refactor: extract buzz-sdk and bot-demo packages 2026-09-12 14:37:59 -06:00
.env.example docs: split README into root, buzz-sdk, and bot-demo 2026-09-12 15:38:34 -06:00
.gitignore feat: minimal Buzz relay bot with modular src/ 2026-09-12 12:16:11 -06:00
.oxfmtrc.json chore: add oxc lint/format toolchain 2026-09-12 14:34:25 -06:00
.oxlintignore chore: add oxc lint/format toolchain 2026-09-12 14:34:25 -06:00
.oxlintrc.json chore: add oxc lint/format toolchain 2026-09-12 14:34:25 -06:00
AGENTS.md chore: require Node 24 and base the image on node:24-alpine 2026-09-12 15:48:01 -06:00
docker-compose.yml refactor: extract buzz-sdk and bot-demo packages 2026-09-12 14:37:59 -06:00
Dockerfile chore: require Node 24 and base the image on node:24-alpine 2026-09-12 15:48:01 -06:00
mise.toml chore: add mise.toml pinning node 24 and pnpm 12 2026-09-12 15:46:35 -06:00
package.json chore: require Node 24 and base the image on node:24-alpine 2026-09-12 15:48:01 -06:00
pnpm-lock.yaml refactor: extract buzz-sdk and bot-demo packages 2026-09-12 14:37:59 -06:00
pnpm-workspace.yaml chore: migrate to pnpm 2026-09-12 14:34:07 -06:00
README.md chore: require Node 24 and base the image on node:24-alpine 2026-09-12 15:48:01 -06:00

buzz-example-agent

A minimal Buzz integration, organized as a pnpm monorepo. It ships two packages:

  • buzz-sdk — a reusable Buzz relay client: NIP-42 auth, subscriptions, presence, profile/agent-directory publishing, DM discovery, and NIP-AO agent observability.
  • bot-demo — a runnable "hello world" bot built on that SDK. It connects to a Buzz relay, subscribes to a channel plus its direct messages, and replies with a fixed string whenever someone else posts.

No LLM, no ACP harness, no Buzz changes. This is the "hello world" step before adding an agent brain — and the SDK that step builds on.

Packages

Package Path Role
buzz-sdk packages/buzz-sdk Reusable SDK: crypto, relay session, presence, profile, DM discovery, NIP-AO observability.
bot-demo packages/bot-demo Runnable bot entrypoint (index.mjs) that consumes buzz-sdk. The fixed-reply reference app.

Naming decision: buzz-sdk holds all reusable primitives (it is a client library, not a bot); bot-demo is the runnable app.

Quick start

Requires Node 24+ (uses the built-in global WebSocket) and pnpm.

pnpm install
pnpm gen-key      # prints nsec / npub / hex — put the nsec in .env
cp .env.example .env   # then set BUZZ_CHANNEL_ID and BUZZ_BOT_PRIVATE_KEY
pnpm start

See packages/bot-demo/README.md for the full configuration table, Docker usage, and verification steps, and packages/buzz-sdk/README.md for the SDK API.

Repository layout

.
├── packages/
│   ├── buzz-sdk/       # library (only package that depends on nostr-tools)
│   │   ├── src/        # crypto, relay session, presence, profile, dm, observer
│   │   └── test/
│   └── bot-demo/       # app
│       ├── index.mjs   # entrypoint (run + --gen-key)
│       └── src/        # config, handlers, bot lifecycle
├── pnpm-workspace.yaml
├── .oxlintrc.json / .oxfmtrc.json / .oxlintignore
├── Dockerfile
└── docker-compose.yml

Workspace tooling

This repo is a pnpm workspace. Node and pnpm versions are pinned in mise.toml; run mise install to provision them. Root scripts fan out to the packages:

pnpm install         # install all workspace deps
pnpm start           # run bot-demo (pnpm --filter bot-demo start)
pnpm gen-key         # generate a bot keypair
pnpm test            # run tests across packages (pnpm -r test)
pnpm lint            # oxlint
pnpm lint:fix        # oxlint --fix
pnpm fmt             # oxfmt
pnpm fmt:check       # oxfmt --check (CI-friendly)

Lint and format are provided by the oxc toolchain (oxlint + oxfmt), configured at the repo root and applied to all packages.

Docker

The image builds the whole workspace and runs bot-demo:

docker compose up --build        # foreground logs
docker compose up --build -d     # background
docker compose logs -f

docker-compose.yml reads .env via env_file. The image is node:24-alpine; docker buildx build --platform linux/amd64,linux/arm64 produces a multi-arch image for x86 Linux hosts.