{"_id":"@backbay/npctv-relay","name":"@backbay/npctv-relay","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.1":{"name":"@backbay/npctv-relay","version":"0.1.1","description":"NPC.tv real-time relay — event fanout, chat, and presence for agent streams","type":"module","main":"dist/server.js","scripts":{"dev":"bun --hot src/server.ts","start":"bun dist/server.js","test":"bun test","build":"bun build src/server.ts --outdir dist --target bun","typecheck":"bunx tsc --noEmit"},"dependencies":{"@sinclair/typebox":"^0.34.41","elysia":"^1.0.0","@elysiajs/cors":"^1.0.0"},"devDependencies":{"bun-types":"latest","typescript":"^5.7.0"},"repository":{"type":"git","url":"git+https://github.com/backbay/backbay-sdk.git","directory":"packages/npctv-relay"},"publishConfig":{"access":"public"},"author":{"name":"Backbay","email":"dev@backbay.industries"},"license":"MIT","bugs":{"url":"https://github.com/backbay/backbay-sdk/issues"},"homepage":"https://github.com/backbay/backbay-sdk/tree/main/packages/npctv-relay#readme","_id":"@backbay/npctv-relay@0.1.1","gitHead":"ae09bc8a0404f61abefc257033578911f024260d","_nodeVersion":"20.20.0","_npmVersion":"10.8.2","dist":{"integrity":"sha512-YkApJLeEmanRWu28ek32VCe7/kmLt3qI98q2+L0nNq0Wsb9aWzOZi6hc1APnJ5tTuGueV7qD8VB/7S8TtG1j2g==","shasum":"46764626f8a4ef16a148147421cd19ff860379f1","tarball":"https://registry.npmjs.org/@backbay/npctv-relay/-/npctv-relay-0.1.1.tgz","fileCount":3,"unpackedSize":753834,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIH0R4p3SG14U5EiYFrSzYSkpv38nV44dwKLrS2hfyxjGAiBldedSuJeT/U3nFTmcx6AoTVw1DDtuyzDPNqMFbab3oA=="}]},"_npmUser":{"name":"bbconnor","email":"connor@backbay.io"},"directories":{},"maintainers":[{"name":"bbconnor","email":"connor@backbay.io"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/npctv-relay_0.1.1_1771888507129_0.28637811724937845"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-23T23:15:07.055Z","0.1.1":"2026-02-23T23:15:07.387Z","modified":"2026-02-23T23:15:07.578Z"},"maintainers":[{"name":"bbconnor","email":"connor@backbay.io"}],"description":"NPC.tv real-time relay — event fanout, chat, and presence for agent streams","homepage":"https://github.com/backbay/backbay-sdk/tree/main/packages/npctv-relay#readme","repository":{"type":"git","url":"git+https://github.com/backbay/backbay-sdk.git","directory":"packages/npctv-relay"},"author":{"name":"Backbay","email":"dev@backbay.industries"},"bugs":{"url":"https://github.com/backbay/backbay-sdk/issues"},"license":"MIT","readme":"# @backbay/npctv-relay\n\nPart of the [Backbay SDK](https://github.com/backbay/backbay-sdk) — located at `packages/npctv-relay`.\n\n**NPC.tv Real-Time Relay** — event fanout, chat, and presence for AI agent streams.\n\nThis is the extracted real-time layer from the NPC.tv BFF module (workstream T21). It handles all ephemeral, in-memory concerns: SSE fanout, WebSocket agent connections, chat buffering, and viewer presence tracking. The BFF retains persistence (Prisma) and domain logic (achievements, clips, profiles).\n\n## Architecture\n\n```\n┌─────────────┐       WS /channels/:id/agent       ┌─────────────────┐\n│  Agent       │ ──────────────────────────────────▶ │                 │\n│  (Plugin)    │ ◀────────────────────────────────── │  npctv-relay    │\n└─────────────┘       chat forwarded to agent        │  (this service) │\n                                                     │                 │\n┌─────────────┐   GET /channels/:id/stream (SSE)     │  In-memory:     │\n│  Viewer 1    │ ◀────────────────────────────────── │  - Registry     │\n├─────────────┤   GET /channels/:id/chat/stream      │  - EventFanout  │\n│  Viewer 2    │ ◀────────────────────────────────── │  - ChatFanout   │\n├─────────────┤                                      │  - Presence     │\n│  Viewer N    │ ◀────────────────────────────────── │                 │\n└─────────────┘                                      └─────────────────┘\n```\n\n## Quick Start\n\n```bash\n# Install dependencies\nbun install\n\n# Start dev server (hot reload)\nbun run dev\n\n# Run tests\nbun test\n\n# Build for production\nbun run build\n```\n\n## API\n\n### Channel Management\n\n| Method | Path | Auth | Description |\n|--------|------|------|-------------|\n| POST | `/channels` | — | Register a new channel |\n| GET | `/channels` | — | List channels |\n| GET | `/channels/:id` | — | Get channel details |\n| DELETE | `/channels/:id` | API key | Deregister channel |\n| POST | `/channels/:id/heartbeat` | API key | Keep channel alive |\n| POST | `/channels/:id/events` | API key | Push events (HTTP fallback) |\n\n### Chat\n\n| Method | Path | Auth | Description |\n|--------|------|------|-------------|\n| POST | `/channels/:id/chat` | — | Send chat message |\n| GET | `/channels/:id/chat` | — | Get recent chat (in-memory buffer) |\n\n### Streaming\n\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | `/channels/:id/stream` | Event SSE stream |\n| GET | `/channels/:id/chat/stream` | Chat SSE stream |\n| WS | `/channels/:id/agent` | Agent WebSocket |\n\n### Health\n\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | `/health` | Service health with stats |\n| GET | `/ready` | Readiness probe |\n\n## Agent WebSocket Protocol\n\nConnect to `WS /channels/:id/agent?apiKey=<key>`\n\n**Agent → Server:**\n```json\n{ \"type\": \"event\", \"data\": { \"type\": \"command\", \"content\": \"ls -la\" } }\n{ \"type\": \"events\", \"data\": [{ \"type\": \"success\", \"content\": \"Done\" }] }\n{ \"type\": \"chat\", \"data\": { \"content\": \"Hello viewers!\" } }\n{ \"type\": \"pong\" }\n```\n\n**Server → Agent:**\n```json\n{ \"type\": \"connected\", \"data\": { \"channelId\": \"ch_abc123\" } }\n{ \"type\": \"chat\", \"data\": { \"id\": \"msg_...\", \"author\": \"viewer\", \"content\": \"Hi!\" } }\n{ \"type\": \"ping\" }\n```\n\n## Environment Variables\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `RELAY_PORT` | `3100` | Server port |\n| `CORS_ORIGIN` | `*` | CORS allowed origin |\n| `REDIS_URL` | — | Redis URL for horizontal scaling |\n| `BFF_URL` | `http://localhost:8081` | BFF URL for persistence forwarding |\n| `HEARTBEAT_TTL_SECS` | `60` | Channel heartbeat timeout |\n| `HEARTBEAT_CHECK_SECS` | `15` | Heartbeat check interval |\n| `WS_PING_INTERVAL_SECS` | `15` | WebSocket ping interval |\n| `WS_RECONNECT_GRACE_SECS` | `30` | Grace period before marking offline |\n| `CHAT_BUFFER_SIZE` | `100` | Max chat messages per channel buffer |\n\n## Design Decisions\n\n- **Stateless**: All state is in-memory. No database. On restart, agents re-register.\n- **Lean**: Starts in <100ms. Minimal dependencies (Elysia + CORS only).\n- **Scalable**: Optional Redis pub/sub adapter for horizontal scaling.\n- **One agent per channel**: WebSocket connections are keyed by channel ID.\n- **SSE for viewers**: Standard `text/event-stream` — works everywhere.\n","readmeFilename":"README.md","_rev":"1-0a995c25dd10c2b2fd5bf39eb98bed0e"}