00:00 / 00:00

LAPLACE Chat

LAPLACE Event Bridge

Monorepo 结构

本仓库包含多个包:

  • 服务端(Go)packages/server):WebSocket 桥接的独立 Go 实现(推荐)
  • 服务端(Bun,已弃用)packages/server-bun):最初的 Bun/Node.js 实现,仅作参考保留
  • SDKpackages/sdk):用于连接桥接服务的 TypeScript/JavaScript 客户端
  • 示例examples/):SDK 的使用示例

功能特性

  • 基于角色的连接系统(服务端/客户端)
  • 服务端向客户端广播消息
  • SDK 可作为客户端接收事件,或以服务端角色生产事件
  • 基于令牌的身份验证
  • 支持断线重连

环境要求

  • Bun v1.2.0 或更高版本(管理 monorepo 以及运行 SDK / Bun 服务端时必需)
  • Go 1.23.0 或更高版本(仅从源码构建或运行 Go 服务端时需要;项目会选择 Go 1.24.2 工具链)

安装

您可以通过以下几种方式运行服务端:

  • 预编译二进制文件(对非技术用户最简单)
  • Go 服务端(易于部署,推荐)
  • laplace-event-fetcher 桥接模式(追求稳定性时推荐)
  • Bun 服务端(已弃用,仅作参考)
  • 源码(面向高级用户与开发者)

预编译二进制文件

如果您不熟悉编程或命令行工具,运行 LAPLACE Event Bridge 服务端最简单的方式,是从我们的 GitHub Releases 下载预编译二进制文件:

  1. 下载服务端

    • 前往 GitHub Releases 页面
    • 找到名称中带有 @laplace.live/event-bridge-server 的最新版本
    • 下载与您操作系统对应的文件:
      • Windowsleb-server-windows-x64.exe
      • macOSleb-server-darwin-arm64
      • Linux(x64)leb-server-linux-x64
      • Linux(arm64)leb-server-linux-arm64
  2. 赋予可执行权限(仅 macOS/Linux):

    • 打开终端
    • 进入下载文件夹:cd ~/Downloads
    • 执行:chmod +x leb-server-*(将 * 替换为实际的文件名)
  3. 运行服务端:

    • Windows:双击 .exe 文件
    • macOS:在终端中执行 ./leb-server-darwin-arm64
    • Linux:在终端中执行 ./leb-server-linux-x64(根据需要将 x64 替换为 arm64

服务端会启动,并在可以接受连接时输出一条提示信息

桥接服务端(Go)

推荐的桥接服务端现在是位于 packages/server 的单二进制 Go 应用。构建或运行它需要 Bun,只需要 Go 工具链

完整文档见 packages/server/README.md,快速上手如下:

# Enter the Go module and run from source
cd packages/server
go run . --debug

# Or build a native binary
go build -o leb-server .
./leb-server --host 0.0.0.0 --auth "your-secure-token"

服务端默认监听 http://localhost:9696

Event Fetcher 桥接模式

在最新版 laplace-event-fetcher(v2.2.0 及以上)中,您可以启用 WebSocket 桥接模式,让 event fetcher 兼作桥接服务端,以获得更好的稳定性。使用该模式时无需保持 LAPLACE Chat 控制台运行,它会替您同时充当 event fetcher 与桥接服务端

桥接服务端(Bun,已弃用)

最初的 Bun/Node.js 实现位于 packages/server-bun。它与 Go 版功能等价,但出于性能与部署便利性已被 Go 版取代。我们仍会为依赖它的用户继续提供

# Start the Bun server
bun run --cwd packages/server-bun start --debug --auth "your-secure-token"

服务端对比

特性桥接服务端(Go)Event Fetcher 桥接模式
安装单二进制文件或 Go 工具链需要 LAPLACE Event Fetcher v2.2.0+
环境本地(独立二进制文件)容器
部署简单 - 单文件部署需要有服务器持续运行
事件来源LAPLACE Chat 控制台或 SDK 服务端角色Event Fetcher 内置
复用本地连接
配置命令行参数Event fetcher 配置
稳定性取决于您的本地网络更稳定
适用场景个人项目集成、小规模使用面向 MCN 机构的生产级大规模部署,或已在使用 event fetcher 的用户

LLM 提示词

把下面的提示词粘贴给你的 AI 助手,或者存进项目的 CLAUDE.mdAGENTS.md 这类规则文件,它就有了替你编写集成所需的全部背景。提示词以英文写成,方便各家模型理解;里面引用的文档地址都可以直接抓取

You are helping me build an integration on top of LAPLACE Event Bridge, the WebSocket
bridge that relays real-time Bilibili live events — chat messages, gifts, super chats,
guard purchases, stream state — from LAPLACE Chat (https://chat.laplace.live) to local
clients.

Before writing any code, fetch the reference documents listed at the end — they are
the single source of truth for event types, payload fields and the client API. Do
not rely on memory and do not invent names.

## Setup

- Install `@laplace.live/event-bridge-sdk`. It runs anywhere with `WebSocket` and
  `fetch` globals: Node.js 22+, Bun and browsers. Event payload interfaces live in
  its dependency `@laplace.live/event-types`.
- A bridge server must be running: either the `leb-server` binary fed by LAPLACE Chat
  or an SDK v1.2.0+ producer using `role: 'server'`, or LAPLACE Event Fetcher v2.2.0+
  in bridge mode (standalone). Default endpoint: `ws://localhost:9696`.
- Auth is optional: when the server was started with `--auth`, pass the same string
  as `token`.

## Client

```ts
import { LaplaceEventBridgeClient } from "@laplace.live/event-bridge-sdk";

const bridge = new LaplaceEventBridgeClient({
  url: "ws://localhost:9696", // default
  token: "your-auth-token", // only when the server enables auth
});

bridge.on("message", (event) => {
  console.log(`${event.username}: ${event.message}`); // typed as Message
});
const offAny = bridge.onAny((event) => console.log(event.type, event.origin));

await bridge.connect();
// later: offAny(); bridge.disconnect();
```

## Producer (Server Role)

SDK v1.2.0+ can instead occupy the event-producing server role. This connects to
a running standalone Event Bridge server; it does not start the bridge server itself.

```ts
const producer = new LaplaceEventBridgeClient({
  url: "ws://localhost:9696",
  token: "your-auth-token",
  role: "server",
});

await producer.connect();
producer.send(event); // event must be a LaplaceEvent
```

Only server-role messages are broadcast. A client-role `send()` is acknowledged by
the bridge but is not relayed to other connections.

The bridge is one-way — servers broadcast, clients listen — and reconnection is
automatic. Handlers are typed from the event name. Every event carries `type`, `id`
and `origin` (the canonical room id — filter on it when one bridge serves several
rooms). The exact event names, payload fields and the rest of the client API live in
the reference below — look them up instead of guessing.

## Reference

Fetch these before writing code:

- https://laplace.live/chat/event-bridge.en.mdx — this page as raw Markdown: server
  setup, SDK client and producer roles, connection state, room discovery
- https://chat.laplace.live/event-types/ — every event type and payload field
- https://github.com/laplace-live/event-bridge — server and SDK source with runnable
  examples

SDK

SDK 提供了用于连接 event bridge 的类型安全客户端;它既能接收事件,也能以服务端角色生产事件

安装

npm install @laplace.live/event-bridge-sdk

用法

import { LaplaceEventBridgeClient } from "@laplace.live/event-bridge-sdk";

const client = new LaplaceEventBridgeClient({
  url: "ws://localhost:9696",
  token: "your-auth-token", // If auth is enabled
});

// Connect to the bridge
await client.connect();

// Listen for specific events
client.on("message", (event) => {
  console.log("Received message:", event);
});

// Listen for all events
client.onAny((event) => {
  console.log("Received event:", event.type);
});

连接选项

LaplaceEventBridgeClient 接受以下连接选项,所有选项均可省略:

Prop

Type

服务端角色

SDK v1.2.0 起也可以作为事件生产者连接。设置 role: 'server' 后,send() 发送的 LaplaceEvent 会由桥接服务广播给所有客户端:

import { LaplaceEventBridgeClient } from "@laplace.live/event-bridge-sdk";

const producer = new LaplaceEventBridgeClient({
  url: "ws://localhost:9696",
  token: "your-auth-token",
  role: "server",
});

await producer.connect();

function broadcast(event: Parameters<typeof producer.send>[0]) {
  producer.send(event);
}

这里的服务端角色是连接到正在运行的独立 Event Bridge 服务端的事件生产端,并不会启动桥接服务本身。默认的 client 角色用于接收事件;它调用 send() 时,消息只会收到确认,不会转发给其他连接。Event Fetcher 桥接模式会在内部自行生产事件,并忽略心跳 pong 以外的传入消息,因此无法转发 SDK 生产端的消息

连接状态

onConnectionStateChange() 会在注册时立即以当前状态调用一次处理函数,此时 detail 可能为 undefined。后续状态变化会在可用时提供断开原因与当前重连次数:

client.onConnectionStateChange((state, detail) => {
  console.log(state, detail?.reconnectAttempts);

  if (detail?.closeEvent) {
    console.log(detail.closeEvent.code, detail.closeEvent.reason);
  }
});

console.log(client.getReconnectAttempts());

getReconnectAttempts() 返回当前中断期间已经进行的重连次数;连接正常或空闲时为 0

Prop

Type

直播间发现

当服务端是运行在桥接模式下的 LAPLACE Event Fetcher 时,它会暴露一个 /info HTTP 端点,列出已配置的直播间。SDK 无需建立 WebSocket 连接即可获取它——适合让用户自行选择要接收哪些直播间

使用 client.getInfo() 方法(复用客户端的 url / token):

const client = new LaplaceEventBridgeClient({
  url: "ws://localhost:9696",
  token,
});

const info = await client.getInfo();
if (info) {
  console.log(`Fetcher v${info.version} exposes ${info.rooms.length} room(s)`);
  for (const room of info.rooms) {
    console.log(`${room.roomId}: ${room.username ?? "unknown"}`);
  }
} else {
  // Plain Event Bridge server or an older fetcher — fall back to manual entry.
}

也可以使用独立的 fetchInfo() 函数,它不需要客户端对象:

import { fetchInfo } from "@laplace.live/event-bridge-sdk";

const info = await fetchInfo({ url: "ws://localhost:9696", token, signal });

/info 不可用时——旧版 fetcher、普通的 Event Bridge 服务端、请求被中止,或任何网络/解析错误——两者都会解析为 null(而不会抛出异常),因此调用方可以静默回退到手动输入直播间

返回的类型是 FetcherInfoFetcherRoom,二者均由 SDK 导出:

import type { FetcherInfo, FetcherRoom } from "@laplace.live/event-bridge-sdk";

interface FetcherRoom {
  status: number; // 0 when resolved, otherwise an error code (e.g. 404)
  uid: number;
  roomId: number; // Canonical room id; matches the `origin` field on incoming events
  shortRoomId: number;
  username: string | null;
}

interface FetcherInfo {
  version: string;
  uptime: string;
  connectedAt: number;
  websocketBridge: boolean;
  websocketClients: number;
  rooms: FetcherRoom[];
}

LaplaceEvent

LaplaceEvent 是 event bridge 系统的核心类型,表示 LAPLACE Chat 与已连接客户端之间交换的事件。每个事件都包含来自哔哩哔哩直播各类弹幕流的标准化数据

所有事件都有一个共同的 type 字段用于标识事件类别,以及各自事件类型特有的附加字段

事件类型的更多说明见 事件类型文档

使用场景

  • 与 Discord、OBS、VTube Studio 集成
  • 在您偏好的前端中创建自定义的弹幕布局
  • 接入 streamer.bot、SAMMI 等第三方服务
  • ……以及任何您能想到的其他场景

开发

SDK 发布流程

SDK(@laplace.live/event-bridge-sdk)遵循结构化的发布流程,并使用 changesets 管理版本

  1. packages/sdk/修改 SDK

  2. 创建 changeset 以记录本次改动:

    bunx @changesets/cli
    • 从包列表中选择 @laplace.live/event-bridge-sdk
    • 选择合适的版本递增方式(patch/minor/major)
    • 写清楚本次改动的说明
  3. 提交改动,包含生成的 changeset 文件:

    git add .
    git commit -m "feat(sdk): your change description"

许可证

AGPL 与 MIT

最后更新于 2026年9月19日

Tech otakus destroy the world