PartyServer Documentation

repository·main·Indexed 22 days ago

https://github.com/cloudflare/partykit

A framework for building real-time, stateful applications using Cloudflare Durable Objects. It provides a room-based abstraction for managing WebSocket connections and broadcasting messages. The ecosystem includes hono-party for Hono integration, partyagent for autonomous agents, partybase for managed database capabilities, partyflow for stateful workflows, and partyfn for bidirectional typesafe RPC.

Tokens
32.6K
Snippets
50
Records
145
Agent score
79%

What's inside PartyServer

  1. Overview of partyagent

    main

    partyagent is a framework for building autonomous agents powered by Cloudflare Durable Objects. It extends PartySync to provide state synchronization for agentic workflows.

    Key capabilities include:

    • Natural Language Processing: Agents can process and respond to natural language inputs.
    • Customizable Personalities: You can define specific behaviors and characteristics for your agents.
    • Tool Usage: Agents can interact with external functions using defined input/output schemas.
    • Task Hand-off: Agents have the ability to delegate tasks to other specialized agents.
    • Observability: Provides mechanisms to monitor agent actions and decision-making processes.
  2. Overview of partytracks features and design

    main

    partytracks provides audio/video handling for realtime applications using Observables for WebRTC, powered by Cloudflare Realtime SFU.

    Key Features

    • Observable-based API: Uses Observables to manage WebRTC complexities more effectively than standard Promises.
    • Automatic Recovery: Automatically handles common WebRTC issues such as disconnects, hardware changes (e.g., unplugging a webcam), and network switches.
    • Abstracted Complexity: Shields your application code from the low-level details of WebRTC track management and connection repairs.
  3. Overview of partyfn

    main
    partyfn is an RPC (Remote Procedure Call) system designed for PartyServer. It enables typesafe function calls between the client and the server. A key feature is its support for bidirectional RPC, meaning you can make calls from the client to the server and also from the server to the client.
  4. How to use PartyServer with Durable Object Facets

    main

    When using Durable Object Facets to spawn child servers, you must provide an explicit id in the FacetStartupOptions.

    If you omit the id, the facet inherits the parent's ctx.id.name, causing this.name to return the parent's name instead of the child's. To ensure the child has its own identity and that this.name works correctly, construct the ID using the namespace's idFromName() method.

    Note: Do not use plain strings as IDs (e.g., id: "child-foo"). This causes the facet to behave like idFromString, which lacks a ctx.id.name and will cause this.name to throw.

    import { Server } from "partyserver";
    
    export class FacetChild extends Server {
      // `this.name` here will report `facetName` (NOT the parent's name)
      // because we passed an explicit `id` at spawn time below.
      onStart() {
        console.log("facet started:", this.name);
      }
    }
    
    export class ParentServer extends Server {
      async fetch(request: Request) {
        const facetName = "child-foo";
    
        // Recommended: construct the id via `ctx.exports[BoundDOClass]`,
        // which is also a `DurableObjectNamespace`. Any bound DO class
        // works — the id is opaque + a name; nothing routes through the
        // namespace at runtime for facets.
        const id = this.ctx.exports.ParentServer.idFromName(facetName);
    
        const facet = this.ctx.facets.get(facetName, () => ({
          class: this.ctx.exports.FacetChild,
          id // <-- the critical bit
        }));
    
        return facet.fetch(request);
      }
    }
  5. Why partytracks uses Observables instead of Promises

    main

    While a promise-based API (e.g., pushing a track and receiving a promise of metadata) may seem simpler, it acts as a leaky abstraction during failures. Events like unplugging a webcam or losing a peer connection during a network switch are difficult to model with single-resolution Promises.

    partytracks uses Observables to contain the logic for replacing and repairing tracks and connections internally. This allows your application code to remain focused on high-level logic without needing to manage the lifecycle of WebRTC repairs.

  6. How PartyServer works

    main

    PartyServer is a framework for building real-time applications using Cloudflare Durable Objects. It provides a "room"-based routing model, lifecycle hooks for managing connections and requests, and a unified API for handling both hibernated and non-hibernated Durable Objects. It also simplifies broadcasting messages to specific sets of connections.

    Key differences from PartyKit:

    • Decoupled Routing: Decouples the URL from the server name, allowing you to associate servers with identifiers like session IDs. You can still use routePartykitRequest() for PartyKit-style matching.
    • Manual Configuration: Unlike PartyKit, PartyServer does not auto-infer Durable Object bindings or migrations. You must manually specify these in your wrangler.jsonc file.
    • Leaner Bindings: It does not include built-in bindings for services like AI or static assets; instead, you use Wrangler's native support for those services.
  7. Configure the PartyTracks server proxy

    main

    In your server environment (e.g., a Cloudflare Worker using Hono), you must implement a proxy path that routes requests to the Cloudflare Realtime SFU API. This requires your SFU_APP_ID and SFU_APP_TOKEN.

    Use routePartyTracksRequest to handle these requests. This function acts as the bridge between your client's requests and the SFU service.

    import { Hono } from "hono";
    import { routePartyTracksRequest } from "partytracks/server";
    
    type Bindings = {
      SFU_APP_ID: string;
      SFU_APP_TOKEN: string;
      TURN_SERVER_APP_ID?: string;
      TURN_SERVER_APP_TOKEN?: string;
    };
    
    const app = new Hono<{ Bindings: Bindings }>();
    
    app.all("/partytracks/*", (c) =>
      routePartyTracksRequest({
        appId: c.env.SFU_APP_ID,
        token: c.env.SFU_APP_TOKEN,
        turnServerAppId: c.env.TURN_SERVER_APP_ID,
        turnServerAppToken: c.env.TURN_SERVER_APP_TOKEN,
        request: c.req.raw,
      })
    );
    
    export default app;