From c682dfaa3b2c7d297a8f681895937c3e5a5df22f Mon Sep 17 00:00:00 2001 From: mektpoy Date: Fri, 23 Oct 2026 15:09:32 +0800 Subject: [PATCH] refactor(liveshare-protocol): publish one entry point The root entry already re-exports the wire codecs, the identity contract, the viewer carrier, and the viewer-state vocabulary, so `./protocol` and `./identity` were aliases of subsets that every consumer had to mirror in the tsconfig path list. Keep `.` alone, keep the mock provider in its source module for tests, and bundle only the root. --- .../liveshare-protocol/README.i18n.yaml | 8 ++--- .../experimental/liveshare-protocol/README.md | 8 ++--- .../liveshare-protocol/README.zh.md | 8 ++--- .../liveshare-protocol/package.json | 16 --------- .../tests/entrypoints.spec.ts | 34 ++++++++----------- .../tests/identity-mock.spec.ts | 2 +- .../liveshare-protocol/tests/identity.spec.ts | 2 +- .../tests/protocol-frames.spec.ts | 2 +- .../tests/protocol-utilities.spec.ts | 2 +- .../liveshare-protocol/tsdown.config.ts | 3 -- tsconfig.base.json | 3 -- 11 files changed, 31 insertions(+), 57 deletions(-) diff --git a/packages/experimental/liveshare-protocol/README.i18n.yaml b/packages/experimental/liveshare-protocol/README.i18n.yaml index 19752ea66f..134ab1cb63 100644 --- a/packages/experimental/liveshare-protocol/README.i18n.yaml +++ b/packages/experimental/liveshare-protocol/README.i18n.yaml @@ -18,14 +18,14 @@ en: bbff250eba0f1b89 zh: 0a618f05cc88ee2b /deepseek-ai-dsh-experimental-liveshare-protocol/use-this-package/when-to-use-it: - en: fc94a4bd3119d40d - zh: e85f74bbacb4fd09 + en: d3f965cdd4635ef2 + zh: cca0198bc469ba1d /deepseek-ai-dsh-experimental-liveshare-protocol/use-this-package/entry-point: en: 452b98f914e90804 zh: 20c344a12a23f9c1 /deepseek-ai-dsh-experimental-liveshare-protocol/understand-the-implementation: - en: ae0264f375192b04 - zh: ba1d95ab72fc003c + en: 2b683ba1b31c8ce5 + zh: 94ad38d16e83f823 /deepseek-ai-dsh-experimental-liveshare-protocol/further-exploration: en: e773c21200a61a9d zh: 57108786433cf892 diff --git a/packages/experimental/liveshare-protocol/README.md b/packages/experimental/liveshare-protocol/README.md index dd03330bd4..13b9085f5d 100644 --- a/packages/experimental/liveshare-protocol/README.md +++ b/packages/experimental/liveshare-protocol/README.md @@ -26,13 +26,13 @@ English | [中文](README.zh.md) ### When to use it -Import `./protocol` and `./identity` from 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 viewer carrier and the viewer-state vocabulary are imported from the package root. This is a library — no profile mounts it and no `cordis.yml` row names 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 ```ts -import { parseGatewayFrame, rawText, sendFrame } from '@deepseek-ai/dsh-experimental-liveshare-protocol/protocol' -import { identityKeyOf, normalizeIdentity } from '@deepseek-ai/dsh-experimental-liveshare-protocol/identity' +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. @@ -56,7 +56,7 @@ Relay compatibility uses declared versions, capabilities, and explicit refusals, | [`src/index.ts`](src/index.ts) | Both faces re-exported for callers that want one import | | [`src/tunnel-protocol.ts`](src/tunnel-protocol.ts) | Owner/worker IPC frames, gateway frames, and their codecs | | [`src/viewer-carrier.ts`](src/viewer-carrier.ts) | Viewer-page carrier script and the owner page routes it forwards; reachable through the root entry | -| [`src/viewer-states.ts`](src/viewer-states.ts) | Viewer state vocabulary and its answers, re-exported by `./protocol` and the root entry | +| [`src/viewer-states.ts`](src/viewer-states.ts) | Viewer state vocabulary and its answers, re-exported by the root entry | | [`src/identity/types.ts`](src/identity/types.ts) | Provider-neutral identity triple and `IdentityProvider` contract | | [`src/identity/keys.ts`](src/identity/keys.ts) | Canonical ACL key codec and the tenant normalization adapters apply before storing an identity | | [`src/identity/mock.ts`](src/identity/mock.ts) | Loopback identity provider for local runs and tests | diff --git a/packages/experimental/liveshare-protocol/README.zh.md b/packages/experimental/liveshare-protocol/README.zh.md index fe60223423..1b26883f47 100644 --- a/packages/experimental/liveshare-protocol/README.zh.md +++ b/packages/experimental/liveshare-protocol/README.zh.md @@ -26,13 +26,13 @@ kind: "package-library" ### 何时使用 -凡是需要说 Liveshare 线路协议或解析某个 viewer 身份的代码,都从本包导入 `./protocol` 与 `./identity`:owner host 及其 gateway worker、Relay server 及其验收测试。查看页载体与查看页状态词汇从包根入口导入。这是一个库——没有 profile 会挂载它,也没有 `cordis.yml` 行引用它。 +凡是需要说 Liveshare 线路协议或解析某个 viewer 身份的代码,都导入本包:owner host 及其 gateway worker、Relay server 及其验收测试。包根入口同时携带帧编解码、身份契约、查看页载体与查看页状态词汇;mock provider 位于 `src/identity/mock.ts`,仅供测试使用,任何包入口都不导出它。这是一个库——没有 profile 会挂载它,也没有 `cordis.yml` 行引用它。 ### 入口 ```ts -import { parseGatewayFrame, rawText, sendFrame } from '@deepseek-ai/dsh-experimental-liveshare-protocol/protocol' -import { identityKeyOf, normalizeIdentity } from '@deepseek-ai/dsh-experimental-liveshare-protocol/identity' +import { parseGatewayFrame, rawText, sendFrame } from '@deepseek-ai/dsh-experimental-liveshare-protocol' +import { identityKeyOf, normalizeIdentity } from '@deepseek-ai/dsh-experimental-liveshare-protocol' ``` 查看页载体(`installViewerCarrier`)与查看页状态词汇通过根入口发布,而不是各自的子路径,因为 owner 页面的两个面会一起消费它们。 @@ -56,7 +56,7 @@ Relay 兼容性依靠声明版本、能力和明确拒绝,不提供逐发布 | [`src/index.ts`](src/index.ts) | 为只想一次导入的调用方复出两个面 | | [`src/tunnel-protocol.ts`](src/tunnel-protocol.ts) | owner/worker IPC 帧、gateway 帧及其编解码 | | [`src/viewer-carrier.ts`](src/viewer-carrier.ts) | 查看页载体脚本及其转发的 owner 页面路由;经根入口引入 | -| [`src/viewer-states.ts`](src/viewer-states.ts) | 查看页状态词汇及其应答,由 `./protocol` 与根入口复出 | +| [`src/viewer-states.ts`](src/viewer-states.ts) | 查看页状态词汇及其应答,由根入口复出 | | [`src/identity/types.ts`](src/identity/types.ts) | 与 provider 无关的身份三元组与 `IdentityProvider` 契约 | | [`src/identity/keys.ts`](src/identity/keys.ts) | 规范 ACL 身份键编解码,以及 adapter 存入身份前的 tenant 规范化 | | [`src/identity/mock.ts`](src/identity/mock.ts) | 供本地运行与测试使用的 loopback 身份 provider | diff --git a/packages/experimental/liveshare-protocol/package.json b/packages/experimental/liveshare-protocol/package.json index 462055d4f2..51dae6f760 100644 --- a/packages/experimental/liveshare-protocol/package.json +++ b/packages/experimental/liveshare-protocol/package.json @@ -15,26 +15,10 @@ "types": "./lib/types/index.d.ts", "default": "./lib/index.js" }, - "./identity": { - "types": "./lib/types/identity/index.d.ts", - "default": "./lib/identity/index.js" - }, - "./identity/mock": { - "types": "./lib/types/identity/mock.d.ts", - "default": "./lib/identity/mock.js" - }, - "./protocol": { - "types": "./lib/types/tunnel-protocol.d.ts", - "default": "./lib/tunnel-protocol.js" - }, - "./src/*": "./src/*", "./package.json": "./package.json" }, "files": [ "lib/index.js", - "lib/identity/index.js", - "lib/identity/mock.js", - "lib/tunnel-protocol.js", "lib/types/**/*.d.ts" ], "license": "MIT", diff --git a/packages/experimental/liveshare-protocol/tests/entrypoints.spec.ts b/packages/experimental/liveshare-protocol/tests/entrypoints.spec.ts index f068e91f33..6652118e8d 100644 --- a/packages/experimental/liveshare-protocol/tests/entrypoints.spec.ts +++ b/packages/experimental/liveshare-protocol/tests/entrypoints.spec.ts @@ -1,27 +1,23 @@ -/** The package's public entry points re-export the one shared contract. */ +/** The package's single public entry carries the whole shared contract. */ import { expect, it } from 'vitest' -import * as identity from '@deepseek-ai/dsh-experimental-liveshare-protocol/identity' -import * as protocol from '@deepseek-ai/dsh-experimental-liveshare-protocol/protocol' import * as root from '@deepseek-ai/dsh-experimental-liveshare-protocol' +import { MockIdentityProvider } from '../src/identity/mock.ts' -it('publishes the mock identity provider only on its test-scoped entry', async () => { - const mock = await import('@deepseek-ai/dsh-experimental-liveshare-protocol/identity/mock') - expect(mock.MockIdentityProvider).toBeTypeOf('function') - expect('MockIdentityProvider' in root).toBe(false) -}) - -it('re-exports the protocol and identity contracts from the package root', () => { - expect(root.LIVESHARE_PROTOCOL_VERSION).toBe(protocol.LIVESHARE_PROTOCOL_VERSION) - expect(root.parseShareAccessState).toBe(protocol.parseShareAccessState) - expect(root.identityKeyOf).toBe(identity.identityKeyOf) - expect('MockIdentityProvider' in identity).toBe(false) +it('publishes the wire, identity, carrier, and viewer-state contracts from the package root', () => { + expect(root.LIVESHARE_PROTOCOL_VERSION).toBeTypeOf('number') + expect(root.parseShareAccessState).toBeTypeOf('function') + expect(root.parseTunnelWorkerCommand).toBeTypeOf('function') + expect(root.identityKeyOf({ providerId: 'p', tenantId: 't', subjectId: 's' })).toBe('p:t:s') + expect(root.identityFromKey('p:t:s')).toEqual({ providerId: 'p', tenantId: 't', subjectId: 's' }) + expect(root.identityFromKey('p:t')).toBeUndefined() + expect(root.identityFromKey('p::s')).toBeUndefined() expect(root.viewerCarrierScript).toBeTypeOf('function') + expect(root.VIEWER_STATE_REACH).toBeTypeOf('object') }) -it('re-exports the identity contract from its own entry', () => { - expect(identity.identityKeyOf({ providerId: 'p', tenantId: 't', subjectId: 's' })).toBe('p:t:s') - expect(identity.identityFromKey('p:t:s')).toEqual({ providerId: 'p', tenantId: 't', subjectId: 's' }) - expect(identity.identityFromKey('p:t')).toBeUndefined() - expect(identity.identityFromKey('p::s')).toBeUndefined() +it('keeps the mock identity provider out of the published surface', () => { + // Tests import the mock from its source module; no package entry exposes it. + expect('MockIdentityProvider' in root).toBe(false) + expect(MockIdentityProvider).toBeTypeOf('function') }) diff --git a/packages/experimental/liveshare-protocol/tests/identity-mock.spec.ts b/packages/experimental/liveshare-protocol/tests/identity-mock.spec.ts index 84730c8ca0..d12cd71ebb 100644 --- a/packages/experimental/liveshare-protocol/tests/identity-mock.spec.ts +++ b/packages/experimental/liveshare-protocol/tests/identity-mock.spec.ts @@ -4,7 +4,7 @@ import { describe, expect, it } from 'vitest' import { MockIdentityProvider, type MockIdentityPersona, -} from '@deepseek-ai/dsh-experimental-liveshare-protocol/identity/mock' +} from '../src/identity/mock.ts' /** The personas one provider is built from; the array stays writable so a test can empty it. */ function personas(): MockIdentityPersona[] { diff --git a/packages/experimental/liveshare-protocol/tests/identity.spec.ts b/packages/experimental/liveshare-protocol/tests/identity.spec.ts index 757f8ac13a..6eab03801b 100644 --- a/packages/experimental/liveshare-protocol/tests/identity.spec.ts +++ b/packages/experimental/liveshare-protocol/tests/identity.spec.ts @@ -6,7 +6,7 @@ import { normalizeIdentity, requireIdentityTenant, type IdentityActor, -} from '@deepseek-ai/dsh-experimental-liveshare-protocol/identity' +} from '@deepseek-ai/dsh-experimental-liveshare-protocol' const actor: IdentityActor = { providerId: 'example', diff --git a/packages/experimental/liveshare-protocol/tests/protocol-frames.spec.ts b/packages/experimental/liveshare-protocol/tests/protocol-frames.spec.ts index 0fde0010fc..790c94b495 100644 --- a/packages/experimental/liveshare-protocol/tests/protocol-frames.spec.ts +++ b/packages/experimental/liveshare-protocol/tests/protocol-frames.spec.ts @@ -11,7 +11,7 @@ import { parseTunnelWorkerEvent, rejectedCommandShareId, unsupportedFrameRefusal, -} from '@deepseek-ai/dsh-experimental-liveshare-protocol/protocol' +} from '@deepseek-ai/dsh-experimental-liveshare-protocol' /** Which two endpoints exchanged a recorded frame, which also names the codec that reads it. */ type Direction = 'relay->gateway' | 'gateway->relay' | 'host->worker' | 'worker->host' diff --git a/packages/experimental/liveshare-protocol/tests/protocol-utilities.spec.ts b/packages/experimental/liveshare-protocol/tests/protocol-utilities.spec.ts index 42da4bd44d..c11501861c 100644 --- a/packages/experimental/liveshare-protocol/tests/protocol-utilities.spec.ts +++ b/packages/experimental/liveshare-protocol/tests/protocol-utilities.spec.ts @@ -11,7 +11,7 @@ import { sendFrame, unsupportedFrameRefusal, viewerRequestFields, -} from '@deepseek-ai/dsh-experimental-liveshare-protocol/protocol' +} from '@deepseek-ai/dsh-experimental-liveshare-protocol' /** One registration token; the parsers accept only this UUID-v4 shape. */ const REGISTRATION = '11111111-1111-4111-8111-111111111111' diff --git a/packages/experimental/liveshare-protocol/tsdown.config.ts b/packages/experimental/liveshare-protocol/tsdown.config.ts index a29b8cb984..329c670926 100644 --- a/packages/experimental/liveshare-protocol/tsdown.config.ts +++ b/packages/experimental/liveshare-protocol/tsdown.config.ts @@ -12,9 +12,6 @@ export default defineConfig(({ env }) => { return { entry: [ 'lib/types/index.js', - 'lib/types/identity/index.js', - 'lib/types/identity/mock.js', - 'lib/types/tunnel-protocol.js', ], outDir: 'lib', format: ['esm'], diff --git a/tsconfig.base.json b/tsconfig.base.json index b229c23a07..4a56dee404 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -375,9 +375,6 @@ "@deepseek-ai/dsh-experimental-session-inspector/client": ["./packages/experimental/session-inspector/src/client/index.ts"], "@deepseek-ai/dsh-experimental-inspector/client": ["./packages/experimental/inspector/src/client/index.ts"], "@deepseek-ai/dsh-experimental-liveshare-protocol": ["./packages/experimental/liveshare-protocol/src"], - "@deepseek-ai/dsh-experimental-liveshare-protocol/identity": ["./packages/experimental/liveshare-protocol/src/identity/index.ts"], - "@deepseek-ai/dsh-experimental-liveshare-protocol/identity/mock": ["./packages/experimental/liveshare-protocol/src/identity/mock.ts"], - "@deepseek-ai/dsh-experimental-liveshare-protocol/protocol": ["./packages/experimental/liveshare-protocol/src/tunnel-protocol.ts"], "@deepseek-ai/dsh-experimental-ptc-runtime-python": ["./packages/experimental/ptc-runtime-python/src"], "@deepseek-ai/dsh-util-crypto": ["./packages/util/crypto/src"], "@deepseek-ai/dsh-util-values": ["./packages/util/values/src"],