feat(sdk): chat sessions, host event feed, and host workspaces again

Closed
HA
1mo ago
+1704-14

Summary

Re-adds host routing that #7564 removed. I could not find a reason for the removal in that PR, its commits or its reviews. The removed code used the same API-key-to-JWT exchange this PR uses.

The SDK can now start and drive agent chat sessions, and receive a host's live events. This lets an external client such as Roster create a session in a workspace, follow its status, send messages, answer approvals and read the transcript, without the desktop app.

New API

  • client.chat:
    • createSession({ workspaceId, harness, modeId?, modelId?, resumeHarnessSessionId? })
    • listSessions, retrieveSession, listItems
    • prompt (takes a plain string or content blocks)
    • cancelTurn, respondToApproval, setMode, setConfigOption, closeSession
    • subscribe({ sessionId, since?, deltas?, onEnvelope }): the session's live stream
  • client.events.subscribe({ onChatSessionChanged?, onEvent? }): the host's /events feed.
  • client.hosts: brings back what #7564 removed when it made the SDK cloud-only. It is a separate namespace, so the cloud workspaces API is unchanged.
    • hosts.list()
    • hosts.projects.list({ hostId? })
    • hosts.workspaces.list / create / createSession / update / delete, with tags on create and update. create generates a retry id when you omit it.
    • These call host-service's /trpc router (SuperJSON) through the relay.
    • hostId defaults to the client's.
    • hosts.list sends the user JWT, not the API key. The API forwards the caller's bearer token to the relay to check presence, so with the key alone every host would show online: false. It lists only the hosts the key's user is linked to.
  • All types are defined in the SDK. Nothing imports the private @superset/chat or @superset/chat-runtime packages, so the published bundle stays self-contained.

Where calls go

Every chat and events call takes hostId and workspaceId:

  • Host (machine running Superset): used when hostId is set on the call or on the client. The call goes to {relay}/hosts/{organizationId}:{hostId}. The relay URL comes from host.relayEndpoint, falling back to https://relay.superset.sh like the CLI.
  • Cloud workspace: used otherwise. The call goes to the workspace's sandbox through the existing gate ticket (cloudWorkspace.hostTicket / access).

Chat-v3 is a separate tRPC router at /chat-v3/trpc with no SuperJSON transformer, so these calls send and parse plain JSON ({ result: { data } }).

Auth

The relay accepts only a user JWT checked against /api/auth/jwks. With an sk_… API key, the SDK calls GET /api/auth/token once:

  • enableSessionForAPIKeys turns the x-api-key request into a session.
  • The jwt plugin issues the token.

The SDK caches the JWT until a minute before its exp, and drops it after a failed host call. Only the JWT goes to the relay. A credential that is not an sk_ key is already sent as a bearer token, so it goes to the relay as is.

WebSockets use the global WebSocket (Node 22+, Bun, Deno, browsers), or the new WebSocket client option. The token goes in ?token=, which both the relay and the gate accept.

Depends on

  • #8168 for chat:session-changed. ChatSessionChangedEvent.removed matches that PR's current shape. Hosts without it never send the event, so callers should keep listSessions as a fallback.

Test plan

  • bun test in packages/sdk: 10 pass, 7 of them new. The two hosts tests cover:

    • hosts.list sends the JWT, not the API key
    • hosts.workspaces.create reaches {relay}/hosts/{org}:{host}/trpc/workspaces.create with a retry id and tags

    The five chat and events tests cover:

    • host calls trade the key for one JWT and reach the relay as plain JSON
    • a bearer credential is passed through
    • cloud routing goes to /chat-v3/trpc on the gate
    • a call with no target is refused before any request
    • events.subscribe opens wss://…/hosts/{org}:{host}/events?token=… and routes chat:session-changed
  • bun run typecheck and bun run build in packages/sdk: clean.

  • bunx biome check (repo): clean. packages/sdk/src is excluded by config.

  • Not run against the live API and relay. The API key to JWT exchange is checked by reading better-auth 1.6.22 (@better-auth/api-key before-hook and jwt /token), not by a live call.

  • Not bumped: the SDK version, and apps/docs/content/docs/sdk/reference.mdx. That page already describes a different SDK surface than this package.


Summary by cubic

The SDK can now start and drive agent chat sessions and receive a host's live events, letting an external client like Roster work without the desktop app.

Adds client.chat (create, list, retrieve, prompt, cancel, approve, set mode and config, close, and live subscribe), client.events.subscribe for the host event feed, and client.hosts for listing host machines and managing their projects and workspaces. Calls target a host through the relay when hostId is set, otherwise the named cloud workspace's sandbox. The relay accepts only a user JWT, so API keys are traded once for a JWT at /api/auth/token and cached until near expiry.

Details

  • Chat calls use a new /chat-v3 tRPC router with plain JSON instead of SuperJSON.
  • WebSockets use the global WebSocket; older runtimes pass one via the WebSocket client option.
  • hosts.list sends the JWT instead of the API key so the API can check host presence at the relay.
  • Depends on #8168 for chat:session-changed; hosts without it never send the event, so keep listSessions as a fallback.

Summary by CodeRabbit

  • New Features
    • Added SDK support for listing hosts and projects, and creating, updating, listing, and deleting host workspaces.
    • Added support for creating and managing chat sessions, sending prompts, handling approvals, and receiving live chat updates.
    • Added event subscriptions for chat-session changes, with callbacks for messages, errors, and connection closures.
    • Added host-targeted and cloud-workspace routing, including relay authentication and configurable WebSocket connections.
  • Documentation
    • Expanded the SDK guides with host, workspace, chat, event subscription, authentication, routing, and WebSocket setup details.