Files
deepseek-harness/packages/experimental/liveshare-protocol
Turtle 38c7a9fbf4 feat(release): publish package source, declaration maps, and documentation (#5884)
* feat(release): publish package source, declaration maps, and documentation

Every release member publishes its TypeScript source and the declaration
maps that resolve into it, and @deepseek-ai/dsh publishes the repository
Markdown documentation staged from docs/ at prepack time.

The ./src/* export most members already declared now resolves for an
installed consumer, and a consumer editor follows a declaration to the
implementation. Bundled JavaScript maps stay unpublished; the vendored
family and the Desktop runtime file policy are unchanged.

Rationale: .agents/notes/implemented/process/2026-10-08-published-source-and-docs.md

* feat(release): publish JavaScript maps and compress bundles

Every emitted JavaScript map ships beside the bundle it describes, and the
workspace build and the client preset compress bundles without mangling
identifiers.

The documentation payload now mirrors the website publication manifest and
is removed again by `postpack`; Desktop and the Python executable exclude
the published source, documentation, and maps; `clean` removes a staged
copy. Typert's publication contract gains the Remote declaration map.

* fix(release): keep node bundles readable for the worker image

The browser worker image lowers `yield*` only as a whole statement and
rewrites `for await` loops by their source layout, so compressed node-side
entries either fail that lowering or lower to unparseable code. Only the
browser bundles keep compression, which removes about a third of their text.

The bundle-purity assertion now matches the module-loader call regardless of
the quote style compression picks, and the release-pack fixture exercises
the installed package's new documentation requirement.

* feat(release): publish the whole documentation tree

`@deepseek-ai/dsh` copies `docs/` in full instead of the website's page
set: the maintainer documents, the generated migration records, the
translation guidelines, and the `*.i18n.yaml` consistency records ship
with the installed package, so the documentation's own links resolve
without a checkout.

* feat(release): publish the upgrade guides with the documentation

The staged documentation keeps the website's page set and adds every
`docs/upgrade-guide/` document, which is what an installed reader consults
when a released change breaks something. The rest of the maintainer tree
stays out.

* test(release): expect source and maps in master's new payload cases

* feat(release): keep installed docs and source readable in Desktop

Desktop keeps the published src/ and docs/ trees inside app.asar, and
every model shell call receives DSH_INSTALL_DIR and DSH_NODE_EXECUTABLE
so an agent can read them through Electron's Node mode. Staging also
generates docs/upgrade-guide/README.md, an index of the upgrade guides
grouped by the release they upgrade from.

Minified client bundles print string literals with backticks: the
worker image packer now recognizes those chunk requests, client license
banners are prepended after minification so their text survives, and
the affected artifact tests accept either quote.

* test(desktop): read archived docs through the Windows PowerShell form

Regenerate the config catalog for the shifted shell-env source line.

* test(desktop): wait for the GUI-subsystem Electron process from PowerShell

* build(release): publish source and maps from the message-quotes package

* build(release): publish source and maps from packages new on master

* build(release): publish source and maps from the tool-office package
2026-11-05 00:22:36 +08:00
..

description, kind
description kind
Liveshare gateway frame codecs and the provider-neutral identity contract shared by the owner bundle and the Relay. package-library

@deepseek-ai/dsh-experimental-liveshare-protocol

English | 中文

Summary

dsh-experimental-liveshare-protocol gives the Liveshare owner bundle and the Relay one copy of what they must agree on: the owner/worker IPC frames, the gateway frames the Relay forwards without interpreting, the viewer carrier script the Relay places in the served page, and the provider-neutral identity contract with its loopback mock implementation. It exists so the owner bundle and the Relay share these definitions without either importing the other; the Relay never loads owner code. It depends on the stateless dsh-brand type library and declares cordis as a peer.

Table of Contents


Use this package

When to use it

Import this package whenever code must speak the Liveshare wire or resolve one viewer identity: the owner host and its gateway worker, the Relay server and its acceptance tests. The root entry carries the wire codecs, the identity contract, the viewer carrier, and the viewer-state vocabulary; the mock provider lives in src/identity/mock.ts for tests only and no package entry exposes it. This is a library — no profile mounts it and no cordis.yml row names it.

Entry point

import { parseGatewayFrame, rawText, sendFrame } from '@deepseek-ai/dsh-experimental-liveshare-protocol'
import { identityKeyOf, normalizeIdentity } from '@deepseek-ai/dsh-experimental-liveshare-protocol'

The viewer carrier (installViewerCarrier) and the viewer-state vocabulary are published through the root entry, not through their own subpaths, because both faces of the owner page consume them together.

parseGatewayFrame returns one validated frame and answers undefined for malformed or unknown input, so a gateway this build does not understand cannot fail the connection. A caller that needs to answer the peer instead of leaving it waiting calls unsupportedFrameRefusal, which turns a frame this build cannot serve into the refusal to send back. identityKeyOf renders one actor as the providerId:tenantId:subjectId key every ACL comparison uses, and normalizeIdentity fills the documented default tenant for a provider that issues none.

Relay compatibility uses declared versions, capabilities, and explicit refusals, not per-release frame translation or common-subset negotiation. Independently deployed peers have no agreed historical support window, so version-specific shims would add an unbounded set of behaviors to maintain. Published optional Relay fields remain optional; capability names are added only for implemented behavior and are never renamed or reinterpreted.


Understand the implementation

Implementation internals — click to expand

tunnel-protocol.ts defines the frames and nothing else: sendFrame takes any socket exposing readyState and send, so the package needs no socket dependency and both the owner gateway and the Relay pass their own ws instance. identity/ holds the provider contract, the canonical ACL key codec, and the loopback mock provider. Neither half imports owner code, so the Relay can depend on this package without depending on the owner bundle.

File Role
src/index.ts Both faces re-exported for callers that want one import
src/tunnel-protocol.ts Owner/worker IPC frames, gateway frames, and their codecs
src/viewer-carrier.ts Viewer-page carrier script and the owner page routes it forwards; reachable through the root entry
src/viewer-states.ts Viewer state vocabulary and its answers, re-exported by the root entry
src/identity/types.ts Provider-neutral identity triple and IdentityProvider contract
src/identity/keys.ts Canonical ACL key codec and the tenant normalization adapters apply before storing an identity
src/identity/mock.ts Loopback identity provider for local runs and tests
— No runtime invariant companion is published because this package holds no mutable state and no registrations; this package's own specs exercise these codecs.

Further Exploration

  • Experimental packages — experimental package status.
  • The Liveshare owner bundle and the Relay consume these frames and ship separately.

Known Limitations and Deferred Work

  • Gateway requests require the Relay's authenticated actor outside the opaque body; frames without that actor are refused.
  • The Owner Host and worker ship together. The supervisor mints a branded UUID registrationToken per logical add, invalidates it on removal, and replays it only for the same retained registration after process restart. Lifecycle, requests, and cancellations echo that token with the share id; per-request TunnelRequestToken remains independent. IPC decoders refuse missing identities, and neither token enters Relay URLs or wire frames. Same-package IPC does not negotiate versions; Relay wire frames retain numeric ids and protocol version 1. Compatibility capabilities include actor-credential and direct-connection. An actor may also carry an optional displayName (presentation data only, used for attribution; authorization keeps using the identity triple), and an optional owner-verifiable credential (the protocol validates its type only; an owner verifies it before trusting the asserted identity, and absence keeps today's Relay-asserted semantics). A share spec may carry connection; absence reads as { mode: 'relay' }, and a Relay that still owns the data path refuses a direct registration.
  • Owners declaring share-access-state receive committed, id-less ACL/mode/expiry snapshots with a durable monotonic version. The worker forwards snapshots only from its current socket; the Host clears authority on socket loss and refreshes the authenticated requests snapshot before external execution admission. An unavailable snapshot fails closed instead of borrowing persisted ACLs.
  • Historical release support is not verified — tests/frames/v1 records concrete frames and refusal obligations, but does not identify a published Owner release. The gateway declares LIVESHARE_PROTOCOL_VERSION and implemented capabilities; the Relay rejects a declared mismatch and sends optional lifecycle frames only to declared consumers. These checks preserve recorded fields and explicit refusals, not a per-release translation or an unbounded support window.

Dev Note

Working context for maintainers — click to expand

None.