Files
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00
..

@tutti-os/event-stream-core

Catalog-agnostic transport core for the business event stream (daemon ↔ renderer over WebSocket). It owns the parts that have nothing to do with a concrete event catalog:

  • connection lifecycle (connect / dispose)
  • heartbeat (ping/pong) and exponential-backoff reconnect
  • frame encode/decode and the subscription registry
  • connectionState observability
  • topic + scope multiplexing over a single socket

Everything catalog-specific — the concrete topics, payload validators, protocol version/revision, and the scope axis — is injected via an EventStreamProtocol. The core never imports a concrete catalog, so multiple products can bind their own:

import { createEventStreamClient } from "@tutti-os/event-stream-core";

const client = createEventStreamClient<MyClientEvent, MyServerEvent, MyScope>({
  resolveUrl: () => "ws://127.0.0.1:7790/v1/events/ws",
  protocol: {
    protocolVersion,
    catalogRevision,
    assertValidClientFrame,
    assertValidServerFrame,
    createClientEvent,
    normalizeScope,
    scopeKey,
    eventMatchesScope
  }
});

The scope type S is generic: tutti binds it to { workspaceId }, other products (e.g. group chat) can bind it to { roomId }. The transport is identical.