@crazx/dsh-client-test-runtime 0.1.6-alpha.2.zw.2 → 0.2.1-rc.2.zw.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.i18n.yaml +66 -5
- package/README.md +10 -4
- package/README.zh.md +10 -4
- package/lib/index.js +123 -33
- package/lib/types/access.d.ts +30 -0
- package/lib/types/assembly/bundle-roster.d.ts +4 -3
- package/lib/types/assembly/roster.d.ts +4 -4
- package/lib/types/assembly/test-client.d.ts +4 -2
- package/lib/types/config-form.d.ts +29 -0
- package/lib/types/index.d.ts +5 -6
- package/lib/types/invariant.d.ts +16 -0
- package/lib/types/sessions.d.ts +4 -10
- package/lib/types/settings-scope.d.ts +1 -3
- package/lib/types/workspaces.d.ts +18 -0
- package/package.json +56 -56
- package/LICENSE +0 -21
package/README.i18n.yaml
CHANGED
|
@@ -1,6 +1,67 @@
|
|
|
1
|
-
# Bilingual-pair consistency record (docs/i18n/README.md):
|
|
2
|
-
#
|
|
3
|
-
#
|
|
1
|
+
# Bilingual-pair consistency record for README.md (docs/i18n/README.md): per heading
|
|
2
|
+
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
|
|
3
|
+
# After editing either side, bring the other along and re-record with:
|
|
4
4
|
# pnpm run verify-translation-pairing --write packages/test-support/client-runtime/README.md
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
/:
|
|
6
|
+
en: 6fd77b7a27000bf1
|
|
7
|
+
zh: 4a9606aa75285111
|
|
8
|
+
/deepseek-ai-dsh-client-test-runtime:
|
|
9
|
+
en: edb01d7d9545062d
|
|
10
|
+
zh: de5e5ac8a9ff2f9b
|
|
11
|
+
/deepseek-ai-dsh-client-test-runtime/summary:
|
|
12
|
+
en: ff69de920b4ab273
|
|
13
|
+
zh: 225437473535326a
|
|
14
|
+
/deepseek-ai-dsh-client-test-runtime/table-of-contents:
|
|
15
|
+
en: d152484eb41ac6b4
|
|
16
|
+
zh: 09388d293f9be9cb
|
|
17
|
+
/deepseek-ai-dsh-client-test-runtime/use-this-package:
|
|
18
|
+
en: 12afbb217bc06678
|
|
19
|
+
zh: c07f001ed8bb3300
|
|
20
|
+
/deepseek-ai-dsh-client-test-runtime/use-this-package/setting-up-a-feature-spec:
|
|
21
|
+
en: 620906bcbaba405a
|
|
22
|
+
zh: b7c34920ba5873d1
|
|
23
|
+
/deepseek-ai-dsh-client-test-runtime/use-this-package/local-dom-snapshots:
|
|
24
|
+
en: 1abbbed6cc4cf57b
|
|
25
|
+
zh: ab3975178b589653
|
|
26
|
+
/deepseek-ai-dsh-client-test-runtime/use-this-package/scripting-remote-answers-and-failures:
|
|
27
|
+
en: cbcfc9a331783c98
|
|
28
|
+
zh: 1cc2f8e21a3d0dd4
|
|
29
|
+
/deepseek-ai-dsh-client-test-runtime/use-this-package/whole-client-tier:
|
|
30
|
+
en: 1442fc215c8128e8
|
|
31
|
+
zh: 8439861b08e46ea2
|
|
32
|
+
/deepseek-ai-dsh-client-test-runtime/use-this-package/roster-and-startup-behavior:
|
|
33
|
+
en: 95c5c2121547bd60
|
|
34
|
+
zh: 4dfb089ba7aac04d
|
|
35
|
+
/deepseek-ai-dsh-client-test-runtime/use-this-package/when-to-use-it:
|
|
36
|
+
en: eb2f9bc90acb7a62
|
|
37
|
+
zh: cb59a2134bc83106
|
|
38
|
+
/deepseek-ai-dsh-client-test-runtime/use-this-package/what-can-go-wrong:
|
|
39
|
+
en: c6bfe837a9221cf5
|
|
40
|
+
zh: 8d8fadea54f9e295
|
|
41
|
+
/deepseek-ai-dsh-client-test-runtime/understand-the-implementation:
|
|
42
|
+
en: 70d19a7761d06ac9
|
|
43
|
+
zh: 2a3e648ee3dc51c1
|
|
44
|
+
/deepseek-ai-dsh-client-test-runtime/understand-the-implementation/design:
|
|
45
|
+
en: 3264640018c1a0e8
|
|
46
|
+
zh: d777e0b8ad8b602f
|
|
47
|
+
/deepseek-ai-dsh-client-test-runtime/understand-the-implementation/source-map:
|
|
48
|
+
en: e3ef8397426d484b
|
|
49
|
+
zh: 23f735f4bda1534a
|
|
50
|
+
/deepseek-ai-dsh-client-test-runtime/understand-the-implementation/lifecycle:
|
|
51
|
+
en: b42779f364504719
|
|
52
|
+
zh: a10bad7ea1161388
|
|
53
|
+
/deepseek-ai-dsh-client-test-runtime/further-exploration:
|
|
54
|
+
en: 7da91d03f5e40b35
|
|
55
|
+
zh: c35021982fdde126
|
|
56
|
+
/deepseek-ai-dsh-client-test-runtime/model-experience:
|
|
57
|
+
en: 53b590e95981d312
|
|
58
|
+
zh: 326a89a5a4e15155
|
|
59
|
+
/deepseek-ai-dsh-client-test-runtime/model-experience/kv-cache-effect:
|
|
60
|
+
en: ca75c51c89c2c9b0
|
|
61
|
+
zh: f57cc48a1b5cbfa9
|
|
62
|
+
/deepseek-ai-dsh-client-test-runtime/known-limitations-and-deferred-work:
|
|
63
|
+
en: da5c7983453b2515
|
|
64
|
+
zh: 7f558354e84abff5
|
|
65
|
+
/deepseek-ai-dsh-client-test-runtime/known-limitations-and-deferred-work/dev-note:
|
|
66
|
+
en: e67f633dc6fe7773
|
|
67
|
+
zh: 3bb0c20c93f16f98
|
package/README.md
CHANGED
|
@@ -11,6 +11,8 @@ English | [中文](README.zh.md)
|
|
|
11
11
|
|
|
12
12
|
`SlotTestRuntime.create()` lets Vitest suites drive production slots, stores, typed Session and Workspace fixtures, and local DOM assertions in jsdom. For plugin activation, reload, reconnect, and cleanup tests, `createClientTest` starts the web profile's bundle roster with endpoint-named Remote mocks, without a business Host. Missing services and unstubbed calls fail explicitly. The whole-client fixture owns startup and disposal; the local runtime provides idempotent disposal. Use this package through `devDependencies` for client tests; it is not a product plugin.
|
|
13
13
|
|
|
14
|
+
Linked bundles resolve dependencies from their real package directories; dependencies next to any bundle take precedence over packages inherited from ancestor directories.
|
|
15
|
+
|
|
14
16
|
## Table of Contents
|
|
15
17
|
|
|
16
18
|
- [Use this package](#use-this-package)
|
|
@@ -42,8 +44,12 @@ await runtime.dispose()
|
|
|
42
44
|
|
|
43
45
|
`mount` prechecks required services and fails loud when one is missing — `provide(name, value)` supplies an extra service first. The runtime provides a `fileUpload` stub that rejects every call until a suite replaces `runtime.fileUpload.upload`. `storeOf(key, scopeKey)` returns the live store instance the renderer hands a slot's component for identity and action-driven-write assertions.
|
|
44
46
|
|
|
47
|
+
The runtime installs `allowAllAccessPlugin` before ui-session: its `remoteAccess` service answers true for every resource, so every access Hook allows every action. Hand-built component props spread `...allowAllAccess` to receive the same Hooks; a spec of a refused path overrides one Hook.
|
|
48
|
+
|
|
45
49
|
The optional render options select a keyed entry with `entryKey` or a list item with `only`; `view.update(owner)` retains that selection. `runtime.panelInfo` supplies the default `usePanelInfo` source with no global panel selected. Release it with `releasePanelInfoSource()` before mounting the production Layout owner. `dispose()` releases both default Workspace and panel-info root sources; early release is idempotent and does not remove replacement owners.
|
|
46
50
|
|
|
51
|
+
The Session fixture resolves subagent addresses from explicitly supplied addresses or loaded parent projections without retaining a Session generation. External catalog entries have no local browsing address.
|
|
52
|
+
|
|
47
53
|
### Local DOM snapshots
|
|
48
54
|
|
|
49
55
|
A registered snapshot serializer folds CSS-module class hashes (`_frame_a1b2c3` → `frame`) so `.snap` files stay structural, and collapses `<svg>` internals to a `data-content` fingerprint. Suites needing a custom page frame use `root.declare(children, Frame)` instead of the auto frame; `dispose()` tears down views, feature fibers, minted scopes, and persisted store state on one axis and is idempotent.
|
|
@@ -87,7 +93,7 @@ The [generic Remote proxy](../remote-mock/README.md#remote-proxy) supports every
|
|
|
87
93
|
|
|
88
94
|
### Roster and startup behavior
|
|
89
95
|
|
|
90
|
-
`webApp` is the `web` profile's browser roster, read when the assembly entry is first imported from its bundles (`dsh-base`, then `dsh-web-app`) as the launcher composes them, except that a patch matching nothing throws here where the launcher warns: each bundle's `dsh.bundle.patch` list is parsed with the include plugin's YAML dialect and composed by its `applyEntryPatches`, and every enabled row whose package declares `dsh.client.platform === 'web'` becomes a row carrying that declaration's `inject` and `immediately`; `bundleRoster(bundles)`
|
|
96
|
+
`webApp` is the `web` profile's browser roster, read when the assembly entry is first imported from its bundles (`dsh-base`, then `dsh-web-app`) as the launcher composes them, except that a patch matching nothing throws here where the launcher warns: each bundle's `dsh.bundle.patch` list is parsed with the include plugin's YAML dialect and composed by its `applyEntryPatches`, and every enabled row whose package declares `dsh.client.platform === 'web'` becomes a row carrying that declaration's `inject` and `immediately`; `bundleRoster(bundles, anchor, disabledContext)` accepts an explicit Loader evaluation scope for conditional `disabled` flags; without one, browser expressions are rejected. `webApp` supplies the Web profile name, not business Host services. Nothing is copied from the bundles, so a bundle change is visible at the next test run. `webApp.closure(names)` keeps the named rows plus everything they inject, transitively (the rows a spec needs to boot those plugins as the bundle composes them), `webApp.pick(names)` and `webApp.without(names)` cut it down by hand, all three throw on unknown names, and `ClientRoster.of(rows)` builds one inline. `remoteDefaultResponses` holds default responses for exactly the Remote endpoints the roster calls while booting with no sessions, no workspaces, and default settings; a spec layers its own `RemoteTable` on top with `mock.load(table)`, and any call without a rule fails the test at `dispose()` through `mock.assertNoUnmatched()`. `mount` requires a roster that provides `uiRenderer`; `start` fails loud otherwise instead of returning an empty container. `client.connection` is the roster's Connection service (no `Context` augmentation declares it), and `connectTimeoutMs` bounds the readiness wait, whose failure message lists the mock log. `reload(name)` rebuilds one Loader entry through the shared Client Modules helper (registry-first teardown, then `entry.refresh()`); each client retains its own module system and instance-bound Connection replacement, so starts and reloads can overlap without changing a page global. `unload(name)` removes an entry and waits for plugin cleanup; `flush()` settles React inside `act`. jsdom implements neither `EventSource` (client-hmr opens one at apply) nor `ResizeObserver` nor the `document.fonts` event target (layout components observe size and font loading at mount), so `start` reference-counts inert stubs for whichever global is absent and `dispose` removes exactly those — a jsdom gap, not a client identity channel. The `@deepseek-ai/dsh-api-remotes` row is dropped from every roster: its generated Remote clients exist only in built `lib/`, and `remote.<ns>` is what the tier replaces anyway. The `@deepseek-ai/dsh-api-remote-access` row, which mounts its own generated contribution, is dropped too, and `start` installs `allowAllAccessPlugin` in its place; a plan `provide` entry for either row is refused. `start` instead provides one contract-free proxy per `remote.<ns>` service the roster injects (plus the namespaces the mock has rules for at that point; a namespace first registered later has no proxy); `ctx.remote.<ns>.<method>(...args)` becomes a call on the endpoint `<ns>/<method>` carrying the positional args, a stream when the mock registered a `stream()` script and a unary call otherwise, with the generated client's outcome folding (`gateway/internal` for carrier throws, `gateway/cancelled` on abort). An endpoint without a rule is still dispatched, so the mock logs it and `dispose()` fails the test.
|
|
91
97
|
|
|
92
98
|
### When to use it
|
|
93
99
|
|
|
@@ -111,7 +117,7 @@ This section explains the design of the bench; the observable behavior is fully
|
|
|
111
117
|
|
|
112
118
|
### Design
|
|
113
119
|
|
|
114
|
-
The bench copies no production logic: it mounts the production `SlotRegistry`, production renderer, and `UiSession` adapter. `TestSessions` and `TestWorkspaces` implement the owner interfaces that features consume through Cordis, each fixture Session implements `SessionFace`, and `
|
|
120
|
+
The bench copies no production logic: it mounts the production `SlotRegistry`, production renderer, and `UiSession` adapter. `TestSessions` and `TestWorkspaces` implement the owner interfaces that features consume through Cordis, each fixture Session implements `SessionFace`, and `stubConfigForm` implements `ConfigForm`. `UiSession` derives standard renderer sources from those Controller bindings. Unstubbed `ISession` behavior fails with the missing method name.
|
|
115
121
|
|
|
116
122
|
### Source map
|
|
117
123
|
|
|
@@ -121,9 +127,10 @@ The bench copies no production logic: it mounts the production `SlotRegistry`, p
|
|
|
121
127
|
| [`src/sessions.ts`](src/sessions.ts) + [`src/workspaces.ts`](src/workspaces.ts) | `ISessions`/`IWorkspaces` test doubles and `FixtureSession` behavior stubs |
|
|
122
128
|
| [`src/fixtures.ts`](src/fixtures.ts) | Plain fixture builders: conversation snapshots, workspace list state |
|
|
123
129
|
| [`src/snapshot.ts`](src/snapshot.ts) | DOM snapshot serializer (class-hash folding, `<svg>` fingerprint) |
|
|
130
|
+
| [`src/access.ts`](src/access.ts) | `allowAllAccess` props and `allowAllAccessPlugin`, the allow-all stand-in for the remote-access Client row |
|
|
124
131
|
| [`src/remote.ts`](src/remote.ts) | `TestRemote` double for host RPC, `RemoteError` value re-export |
|
|
125
132
|
| [`src/translate.ts`](src/translate.ts) + [`src/locale-env.ts`](src/locale-env.ts) | Translation and pinned-browser-language test helpers |
|
|
126
|
-
| [`src/
|
|
133
|
+
| [`src/config-form.ts`](src/config-form.ts) | `stubConfigForm` with test-driven publications and write spies |
|
|
127
134
|
| [`src/assembly/roster.ts`](src/assembly/roster.ts) | `ClientRosterRow`, `ClientRoster` (`of`/`closure`/`pick`/`without`), the `AssemblyPlan` it annotates, and `graphFromRoster` |
|
|
128
135
|
| [`src/assembly/modules.ts`](src/assembly/modules.ts) | Source `/client` imports and replacements, registered through the production module facade's pending factory queue |
|
|
129
136
|
| [`src/assembly/test-client.ts`](src/assembly/test-client.ts) | `TestClient`: instance-bound Connection, shared jsdom shims, `bootClient`, mount, readiness wait, `reload`/`unload`/`dispose` |
|
|
@@ -131,7 +138,6 @@ The bench copies no production logic: it mounts the production `SlotRegistry`, p
|
|
|
131
138
|
| [`src/assembly/remote-default-responses.ts`](src/assembly/remote-default-responses.ts) | `remoteDefaultResponses`: default responses of the Remote endpoints the roster calls at boot |
|
|
132
139
|
| [`src/assembly/remote-proxies.ts`](src/assembly/remote-proxies.ts) | Contract-free `remote.<ns>` proxies over the Connection: `remoteNamespacesOf`, `remoteProxiesPlugin` |
|
|
133
140
|
| [`src/assembly/bundle-roster.ts`](src/assembly/bundle-roster.ts) | `bundleRoster` and `webApp`: the browser roster read from bundle patch files with the include plugin's own schema and patch application |
|
|
134
|
-
| — | No runtime invariant companion is published; this test-support package owns no production event stream or mutable data — it assembles the runtime SlotRegistry and renderer (whose packages own their invariants) around test doubles; its own behavior is exercised by its package tests. |
|
|
135
141
|
|
|
136
142
|
### Lifecycle
|
|
137
143
|
|
package/README.zh.md
CHANGED
|
@@ -11,6 +11,8 @@ kind: "package-library"
|
|
|
11
11
|
|
|
12
12
|
`SlotTestRuntime.create()` 让 Vitest 套件在 jsdom 中驱动生产 slot、store、带类型的 Session 与 Workspace fixture,并对局部 DOM 断言。面向插件激活、重载、重连与清理的测试,`createClientTest` 使用具名端点 Remote mock 启动 web profile 的 bundle roster,无需业务 Host。缺失服务与未打桩调用会明确失败。整机 fixture 拥有启动和销毁,局部 runtime 提供幂等销毁。通过 `devDependencies` 将本包用于客户端测试;它不是产品插件。
|
|
13
13
|
|
|
14
|
+
链接到工作区的 bundle 从实际包目录解析依赖;各 bundle 自身目录中的依赖优先于祖先目录中继承的包。
|
|
15
|
+
|
|
14
16
|
## 目录
|
|
15
17
|
|
|
16
18
|
- [使用本包](#use-this-package)
|
|
@@ -42,8 +44,12 @@ await runtime.dispose()
|
|
|
42
44
|
|
|
43
45
|
`mount` 会预检必需服务,缺失时自明报错——先用 `provide(name, value)` 提供额外服务。运行时提供的 `fileUpload` 替身会拒绝每次调用,直到测试套件替换 `runtime.fileUpload.upload`。`storeOf(key, scopeKey)` 返回渲染器交给 slot 组件的实时存储实例,用于身份与动作驱动写入断言。
|
|
44
46
|
|
|
47
|
+
运行时在 ui-session 之前安装 `allowAllAccessPlugin`:它的 `remoteAccess` 服务对每个资源都回答 true,因此每个访问 Hook 都允许每个 action。手工构造的组件 props 展开 `...allowAllAccess` 以获得同样的 Hook;测试被拒绝路径的 spec 覆盖其中一个 Hook。
|
|
48
|
+
|
|
45
49
|
可选渲染参数通过 `entryKey` 选择 keyed 条目,或通过 `only` 选择 list 条目;`view.update(owner)` 保留该选择。`runtime.panelInfo` 提供默认的 `usePanelInfo` 数据源,初始不选中全局面板。挂载生产 Layout 所有者之前,先调用 `releasePanelInfoSource()` 释放该数据源。`dispose()` 同时释放默认的工作区与面板信息根数据源;提前释放是幂等的,不会移除替代它们的所有者。
|
|
46
50
|
|
|
51
|
+
Session fixture 从显式提供的地址或已加载的父级投影解析子代理地址,不会保留 Session generation。外部目录项没有本地浏览地址。
|
|
52
|
+
|
|
47
53
|
### 局部 DOM 快照
|
|
48
54
|
|
|
49
55
|
注册的快照序列化器把 CSS-module 哈希类名折回语义名(`_frame_a1b2c3` → `frame`),使 `.snap` 文件只含结构,并把 `<svg>` 内部折叠为 `data-content` 指纹。需要自定义页面 frame 的套件改用 `root.declare(children, Frame)` 而非自动 frame;`dispose()` 沿单一轴拆除视图、功能 fiber、已铸 scope 与持久化存储状态,且幂等。
|
|
@@ -87,7 +93,7 @@ test('registers into the sidebar', async ({ remote, start }) => {
|
|
|
87
93
|
|
|
88
94
|
### Roster 与启动行为
|
|
89
95
|
|
|
90
|
-
`webApp` 是 `web` profile 的浏览器 roster,首次 import 装配入口时从它的 bundle(先 `dsh-base`、再 `dsh-web-app`)按启动器的方式现读,只是匹配不到任何行的补丁在这里抛错、启动器只警告:每个 bundle 的 `dsh.bundle.patch` 列表用 include 插件的 YAML 方言解析、用它的 `applyEntryPatches` 合成,每个未禁用且其包声明 `dsh.client.platform === 'web'` 的行成为一行,带上该声明的 `inject` 与 `immediately`;`bundleRoster(bundles)`
|
|
96
|
+
`webApp` 是 `web` profile 的浏览器 roster,首次 import 装配入口时从它的 bundle(先 `dsh-base`、再 `dsh-web-app`)按启动器的方式现读,只是匹配不到任何行的补丁在这里抛错、启动器只警告:每个 bundle 的 `dsh.bundle.patch` 列表用 include 插件的 YAML 方言解析、用它的 `applyEntryPatches` 合成,每个未禁用且其包声明 `dsh.client.platform === 'web'` 的行成为一行,带上该声明的 `inject` 与 `immediately`;`bundleRoster(bundles, anchor, disabledContext)` 接受显式 Loader 求值作用域来处理条件 `disabled` 标记;未提供作用域时拒绝浏览器表达式。`webApp` 仅提供 Web profile 名称,不提供业务 Host 服务。没有任何东西从 bundle 拷贝出来,bundle 一改下次跑测试就能看见。`webApp.closure(names)` 保留点名的行及其传递注入的全部行(即按 bundle 组合方式起这些插件所需的行),`webApp.pick(names)` 与 `webApp.without(names)` 手工裁剪,三者都对未知名字抛错,`ClientRoster.of(rows)` 内联构造一份。`remoteDefaultResponses` 是 roster 在没有 session、没有 workspace、默认设置下启动时恰好会打的那些 Remote 端点的默认响应;测试用 `mock.load(table)` 在其上叠加自己的 `RemoteTable`,任何没有规则的调用都会在 `dispose()` 时经 `mock.assertNoUnmatched()` 让测试失败。`mount` 要求 roster 提供 `uiRenderer`;否则 `start` 响亮失败而不是返回一个空容器。`client.connection` 是 roster 的 Connection 服务(没有任何 `Context` 增强声明它),`connectTimeoutMs` 限定等就绪的时长,超时消息列出 mock log。`reload(name)` 通过共享的 Client Modules 辅助函数重建一个 Loader entry(先拆 registry,再 `entry.refresh()`);每个客户端都保留自己的模块系统和绑定实例的 Connection 替换,因此启动与重载可以重叠而无需改写页面全局变量。`unload(name)` 移除 entry 并等待插件清理完成,`flush()` 在 `act` 内让 React 落定。jsdom 既没有 `EventSource`(client-hmr 在 apply 时打开一个)也没有 `ResizeObserver` 和 `document.fonts` 事件目标(布局组件挂载时观察尺寸与字体加载),所以 `start` 对缺失的全局惰性桩做引用计数,`dispose` 只移除它装的那些——这是 jsdom 的缺口,不是客户端身份通道。每个 roster 里的 `@deepseek-ai/dsh-api-remotes` 行都会被去掉:它生成的 Remote 客户端只存在于构建后的 `lib/`,而 `remote.<ns>` 正是本档要替掉的东西。自行挂载其生成 contribution 的 `@deepseek-ai/dsh-api-remote-access` 行同样会被去掉,`start` 改为安装 `allowAllAccessPlugin`;计划中为这两行之一提供的 `provide` 项会被拒绝。`start` 改为给 roster 注入的每个 `remote.<ns>` 服务(加上此刻 mock 登记过规则的命名空间;之后才首次登记的命名空间没有代理)提供一个无契约代理;`ctx.remote.<ns>.<method>(...args)` 变成对端点 `<ns>/<method>` 的调用,携带位置参数,mock 登记了 `stream()` 脚本的走流、否则走一元,并沿用生成客户端的结果折叠(载体抛错折成 `gateway/internal`,中止折成 `gateway/cancelled`)。没有规则的端点照样发出,所以 mock 会记下它、`dispose()` 让测试失败。
|
|
91
97
|
|
|
92
98
|
### 何时使用
|
|
93
99
|
|
|
@@ -111,7 +117,7 @@ test('registers into the sidebar', async ({ remote, start }) => {
|
|
|
111
117
|
|
|
112
118
|
### 设计
|
|
113
119
|
|
|
114
|
-
测试台不复制生产逻辑:它挂载生产 `SlotRegistry`、生产渲染器与 `UiSession` 适配器。`TestSessions` 与 `TestWorkspaces` 实现功能通过 Cordis 消费的 owner 接口,每个 fixture Session 实现 `SessionFace`,`
|
|
120
|
+
测试台不复制生产逻辑:它挂载生产 `SlotRegistry`、生产渲染器与 `UiSession` 适配器。`TestSessions` 与 `TestWorkspaces` 实现功能通过 Cordis 消费的 owner 接口,每个 fixture Session 实现 `SessionFace`,`stubConfigForm` 实现 `ConfigForm`。`UiSession` 从这些控制器绑定派生标准渲染器数据源。未 stub 的 `ISession` 行为会携缺失方法名失败。
|
|
115
121
|
|
|
116
122
|
### 源码地图
|
|
117
123
|
|
|
@@ -121,9 +127,10 @@ test('registers into the sidebar', async ({ remote, start }) => {
|
|
|
121
127
|
| [`src/sessions.ts`](src/sessions.ts) + [`src/workspaces.ts`](src/workspaces.ts) | `ISessions`/`IWorkspaces` 测试替身与 `FixtureSession` 行为桩 |
|
|
122
128
|
| [`src/fixtures.ts`](src/fixtures.ts) | 普通 fixture 构造器:会话快照、workspace 列表状态 |
|
|
123
129
|
| [`src/snapshot.ts`](src/snapshot.ts) | DOM 快照序列化器(类名哈希折叠、`<svg>` 指纹) |
|
|
130
|
+
| [`src/access.ts`](src/access.ts) | `allowAllAccess` props 与 `allowAllAccessPlugin`:remote-access Client 行的全允许替身 |
|
|
124
131
|
| [`src/remote.ts`](src/remote.ts) | 用于 host RPC 的 `TestRemote` 替身、`RemoteError` 值转出 |
|
|
125
132
|
| [`src/translate.ts`](src/translate.ts) + [`src/locale-env.ts`](src/locale-env.ts) | 翻译与固定浏览器语言测试辅助 |
|
|
126
|
-
| [`src/
|
|
133
|
+
| [`src/config-form.ts`](src/config-form.ts) | 带测试驱动发布与写入 spy 的 `stubConfigForm` |
|
|
127
134
|
| [`src/assembly/roster.ts`](src/assembly/roster.ts) | `ClientRosterRow`、`ClientRoster`(`of`/`closure`/`pick`/`without`)、它所标注的 `AssemblyPlan`,以及 `graphFromRoster` |
|
|
128
135
|
| [`src/assembly/modules.ts`](src/assembly/modules.ts) | 源码 `/client` 导入及替换,通过生产模块 facade 的待注册工厂队列登记 |
|
|
129
136
|
| [`src/assembly/test-client.ts`](src/assembly/test-client.ts) | `TestClient`:绑定实例的 Connection、共享 jsdom 桩、`bootClient`、挂载、等就绪、`reload`/`unload`/`dispose` |
|
|
@@ -131,7 +138,6 @@ test('registers into the sidebar', async ({ remote, start }) => {
|
|
|
131
138
|
| [`src/assembly/remote-default-responses.ts`](src/assembly/remote-default-responses.ts) | `remoteDefaultResponses`:roster 启动期 Remote 端点的默认响应 |
|
|
132
139
|
| [`src/assembly/remote-proxies.ts`](src/assembly/remote-proxies.ts) | 经 Connection 的无契约 `remote.<ns>` 代理:`remoteNamespacesOf`、`remoteProxiesPlugin` |
|
|
133
140
|
| [`src/assembly/bundle-roster.ts`](src/assembly/bundle-roster.ts) | `bundleRoster` 与 `webApp`:用 include 插件自己的 schema 与补丁应用从 bundle 补丁文件读出浏览器 roster |
|
|
134
|
-
| — | 不发布运行时不变式伴生入口;本测试支持包不拥有生产事件流或可变数据,而是围绕测试替身组装生产 SlotRegistry 与渲染器。所挂载的生产包拥有各自的不变式,本包行为由本包测试检验。 |
|
|
135
141
|
|
|
136
142
|
### 生命周期
|
|
137
143
|
|
package/lib/index.js
CHANGED
|
@@ -232,6 +232,7 @@ function workspaceSnapshot() {
|
|
|
232
232
|
return {
|
|
233
233
|
items: [],
|
|
234
234
|
archivedSessionIds: [],
|
|
235
|
+
pinnedSessionIds: [],
|
|
235
236
|
state: "idle",
|
|
236
237
|
phase: "ready",
|
|
237
238
|
error: null
|
|
@@ -482,8 +483,7 @@ var TestSessions = class {
|
|
|
482
483
|
ids: [],
|
|
483
484
|
byId: {},
|
|
484
485
|
phase: "ready",
|
|
485
|
-
|
|
486
|
-
jobsBySession: {}
|
|
486
|
+
projectionsBySession: {}
|
|
487
487
|
});
|
|
488
488
|
rootCtx.effect(() => async () => {
|
|
489
489
|
this.closed = true;
|
|
@@ -557,9 +557,20 @@ var TestSessions = class {
|
|
|
557
557
|
async setProjection(id, key, value) {
|
|
558
558
|
const record = this.require(id);
|
|
559
559
|
record.projections.set(key, value);
|
|
560
|
+
const values = {
|
|
561
|
+
...record.summary.projectionValues ?? {},
|
|
562
|
+
[key]: value
|
|
563
|
+
};
|
|
564
|
+
record.summary = {
|
|
565
|
+
...record.summary,
|
|
566
|
+
projectionValues: values
|
|
567
|
+
};
|
|
560
568
|
await this.stabilize(() => {
|
|
561
569
|
record.session.projections.set(key, value);
|
|
562
570
|
this.generations.get(id)?.session.projections.set(key, value);
|
|
571
|
+
this.list.update((draft) => {
|
|
572
|
+
draft.byId[id] = record.summary;
|
|
573
|
+
});
|
|
563
574
|
});
|
|
564
575
|
}
|
|
565
576
|
/**
|
|
@@ -743,27 +754,20 @@ var TestSessions = class {
|
|
|
743
754
|
subagentAddress(id) {
|
|
744
755
|
const retained = this.addresses.get(id);
|
|
745
756
|
if (retained !== void 0) return retained;
|
|
746
|
-
for (const [parentSessionId,
|
|
747
|
-
const child =
|
|
748
|
-
if (child
|
|
757
|
+
for (const [parentSessionId, projections] of Object.entries(this.list.getSnapshot().projectionsBySession)) {
|
|
758
|
+
const child = projections.values.subagentCatalog?.find((entry) => entry.id === id);
|
|
759
|
+
if (child !== void 0 && child.mode !== "external") return {
|
|
749
760
|
parentSessionId,
|
|
750
761
|
childSessionId: id,
|
|
751
762
|
mode: child.mode
|
|
752
763
|
};
|
|
753
764
|
}
|
|
754
765
|
}
|
|
755
|
-
/** Record
|
|
756
|
-
|
|
766
|
+
/** Record a projection refresh; fixture callers drive snapshots explicitly. */
|
|
767
|
+
refreshProjections(sessionId) {
|
|
757
768
|
this.calls.push({
|
|
758
|
-
method: "
|
|
759
|
-
args: [
|
|
760
|
-
});
|
|
761
|
-
}
|
|
762
|
-
/** Record a catalog refresh; fixture callers drive snapshots explicitly. */
|
|
763
|
-
refreshSubagents(parentSessionId) {
|
|
764
|
-
this.calls.push({
|
|
765
|
-
method: "refreshSubagents",
|
|
766
|
-
args: [parentSessionId]
|
|
769
|
+
method: "refreshProjections",
|
|
770
|
+
args: [sessionId]
|
|
767
771
|
});
|
|
768
772
|
return Promise.resolve();
|
|
769
773
|
}
|
|
@@ -1025,6 +1029,18 @@ var TestWorkspaces = class {
|
|
|
1025
1029
|
};
|
|
1026
1030
|
}
|
|
1027
1031
|
/**
|
|
1032
|
+
* Initialize the default Workspace through a test stub; defaults to an ineligible first use.
|
|
1033
|
+
* @param signal - caller lifetime.
|
|
1034
|
+
* @returns the stubbed Workspace, or undefined when initialization is ineligible.
|
|
1035
|
+
*/
|
|
1036
|
+
async initializeDefault(signal) {
|
|
1037
|
+
this.calls.push({
|
|
1038
|
+
method: "initializeDefault",
|
|
1039
|
+
args: [signal]
|
|
1040
|
+
});
|
|
1041
|
+
return await this.stubs.get("initializeDefault")?.(signal);
|
|
1042
|
+
}
|
|
1043
|
+
/**
|
|
1028
1044
|
* Rename a Workspace (recorded). The default echoes a minimal view.
|
|
1029
1045
|
* @param workspaceId - target workspace.
|
|
1030
1046
|
* @param title - new title.
|
|
@@ -1130,29 +1146,108 @@ var TestWorkspaces = class {
|
|
|
1130
1146
|
draft.archivedSessionIds = draft.archivedSessionIds.filter((id) => id !== sessionId);
|
|
1131
1147
|
});
|
|
1132
1148
|
}
|
|
1149
|
+
/**
|
|
1150
|
+
* Pin a session (recorded). The default mirrors the production face's
|
|
1151
|
+
* observable effect: the id leads the list state's pin set.
|
|
1152
|
+
* @param sessionId - session to pin.
|
|
1153
|
+
*/
|
|
1154
|
+
async pinSession(sessionId) {
|
|
1155
|
+
this.calls.push({
|
|
1156
|
+
method: "pinSession",
|
|
1157
|
+
args: [sessionId]
|
|
1158
|
+
});
|
|
1159
|
+
const stub = this.stubs.get("pinSession");
|
|
1160
|
+
if (stub !== void 0) {
|
|
1161
|
+
await stub(sessionId);
|
|
1162
|
+
return;
|
|
1163
|
+
}
|
|
1164
|
+
await this.update((draft) => {
|
|
1165
|
+
draft.pinnedSessionIds = [sessionId, ...draft.pinnedSessionIds.filter((id) => id !== sessionId)];
|
|
1166
|
+
});
|
|
1167
|
+
}
|
|
1168
|
+
/**
|
|
1169
|
+
* Unpin a session (recorded). The default mirrors the production face's
|
|
1170
|
+
* observable effect: the id leaves the list state's pin set.
|
|
1171
|
+
* @param sessionId - session to unpin.
|
|
1172
|
+
*/
|
|
1173
|
+
async unpinSession(sessionId) {
|
|
1174
|
+
this.calls.push({
|
|
1175
|
+
method: "unpinSession",
|
|
1176
|
+
args: [sessionId]
|
|
1177
|
+
});
|
|
1178
|
+
const stub = this.stubs.get("unpinSession");
|
|
1179
|
+
if (stub !== void 0) {
|
|
1180
|
+
await stub(sessionId);
|
|
1181
|
+
return;
|
|
1182
|
+
}
|
|
1183
|
+
await this.update((draft) => {
|
|
1184
|
+
draft.pinnedSessionIds = draft.pinnedSessionIds.filter((id) => id !== sessionId);
|
|
1185
|
+
});
|
|
1186
|
+
}
|
|
1187
|
+
};
|
|
1188
|
+
//#endregion
|
|
1189
|
+
//#region lib/types/access.js
|
|
1190
|
+
/**
|
|
1191
|
+
* Allow-all access for client specs. Production pages receive the
|
|
1192
|
+
* `remoteAccess` Client service and the global-resource `useRemoteAccess` Hook
|
|
1193
|
+
* from the remote-access Client plugin, and the Session and Workspace access
|
|
1194
|
+
* Hooks (Session-scope `useAccess`, `useSessionAccess`, `useWorkspaceAccess`)
|
|
1195
|
+
* from ui-session and ui-workspace over that service. The test runtimes
|
|
1196
|
+
* install an allow-all service and `useRemoteAccess` Hook instead, and
|
|
1197
|
+
* hand-built component props spread {@link allowAllAccess}; a spec of a
|
|
1198
|
+
* refused path overrides one Hook.
|
|
1199
|
+
* @module @deepseek-ai/dsh-client-test-runtime/src/access
|
|
1200
|
+
*/
|
|
1201
|
+
/** Access Hooks that allow every action on every resource, for hand-built component props. */
|
|
1202
|
+
const allowAllAccess = {
|
|
1203
|
+
useRemoteAccess: () => true,
|
|
1204
|
+
useAccess: () => true,
|
|
1205
|
+
useSessionAccess: () => true,
|
|
1206
|
+
useWorkspaceAccess: () => true
|
|
1207
|
+
};
|
|
1208
|
+
const ALLOWED = {
|
|
1209
|
+
getSnapshot: () => true,
|
|
1210
|
+
subscribe: () => () => {}
|
|
1211
|
+
};
|
|
1212
|
+
const allowed = () => ALLOWED;
|
|
1213
|
+
/** The `remoteAccess` Client service answering true for every resource. */
|
|
1214
|
+
const allowAllRemoteAccess = { source: allowed };
|
|
1215
|
+
/**
|
|
1216
|
+
* Plugin standing in for the remote-access Client row: it provides an
|
|
1217
|
+
* allow-all `remoteAccess` service, so ui-session and ui-workspace publish
|
|
1218
|
+
* their resource Hooks over it, and the allow-all `useRemoteAccess` Hook on
|
|
1219
|
+
* the global resource.
|
|
1220
|
+
*/
|
|
1221
|
+
const allowAllAccessPlugin = {
|
|
1222
|
+
name: "client-test-runtime:allow-all-access",
|
|
1223
|
+
inject: ["slots"],
|
|
1224
|
+
/** @param ctx - plugin Context with the Slot registry injected. */
|
|
1225
|
+
apply(ctx) {
|
|
1226
|
+
ctx.provide("remoteAccess", allowAllRemoteAccess);
|
|
1227
|
+
ctx.slots.provideRoot({ keyedHooks: { remoteAccess: allowed } });
|
|
1228
|
+
}
|
|
1133
1229
|
};
|
|
1134
1230
|
//#endregion
|
|
1135
|
-
//#region lib/types/
|
|
1136
|
-
/** Test
|
|
1231
|
+
//#region lib/types/config-form.js
|
|
1232
|
+
/** Test doubles for settings transport. */
|
|
1137
1233
|
/**
|
|
1138
|
-
* Build an in-memory settings scope for service specs: starts in the
|
|
1139
|
-
*
|
|
1234
|
+
* Build an in-memory settings scope for service specs: starts in the loading
|
|
1235
|
+
* state, records writes, and lets the test publish Host acceptances.
|
|
1140
1236
|
* @returns the stub handle.
|
|
1141
1237
|
*/
|
|
1142
|
-
function
|
|
1238
|
+
function stubConfigForm() {
|
|
1143
1239
|
let snapshot = {
|
|
1144
1240
|
status: "loading",
|
|
1145
1241
|
value: void 0,
|
|
1146
1242
|
base: void 0,
|
|
1147
1243
|
user: void 0,
|
|
1148
1244
|
revision: void 0,
|
|
1149
|
-
writable: false
|
|
1150
|
-
mode: "host"
|
|
1245
|
+
writable: false
|
|
1151
1246
|
};
|
|
1152
1247
|
const listeners = /* @__PURE__ */ new Set();
|
|
1153
|
-
const set = vi.fn(() => Promise.resolve());
|
|
1154
|
-
const mutate = vi.fn(() => Promise.resolve());
|
|
1155
|
-
const unset = vi.fn(() => Promise.resolve());
|
|
1248
|
+
const set = vi.fn(() => Promise.resolve(true));
|
|
1249
|
+
const mutate = vi.fn(() => Promise.resolve(true));
|
|
1250
|
+
const unset = vi.fn(() => Promise.resolve(true));
|
|
1156
1251
|
return {
|
|
1157
1252
|
scope: {
|
|
1158
1253
|
getSnapshot: () => snapshot,
|
|
@@ -1373,8 +1468,6 @@ var SlotTestRuntime = class SlotTestRuntime {
|
|
|
1373
1468
|
workspaces;
|
|
1374
1469
|
/** Test-owned panel selection used by the framework's usePanelInfo hook. */
|
|
1375
1470
|
panelInfo = createSnapshotStore({ activePanelId: null });
|
|
1376
|
-
/** Test-owned toolbar portal hosts used by the framework's useToolbarHosts hook (null = no toolbar). */
|
|
1377
|
-
toolbarHosts = createSnapshotStore(null);
|
|
1378
1471
|
/** Mutable file-upload stub; replace `upload` in suites that exercise the capability. */
|
|
1379
1472
|
fileUpload;
|
|
1380
1473
|
stabilizer = async (fn) => {
|
|
@@ -1392,7 +1485,6 @@ var SlotTestRuntime = class SlotTestRuntime {
|
|
|
1392
1485
|
autoRootView;
|
|
1393
1486
|
disposeWorkspaceSource;
|
|
1394
1487
|
disposePanelInfoSource;
|
|
1395
|
-
disposeToolbarHostsSource;
|
|
1396
1488
|
constructor(ctx, slots) {
|
|
1397
1489
|
this.ctx = ctx;
|
|
1398
1490
|
this.slots = slots;
|
|
@@ -1406,7 +1498,6 @@ var SlotTestRuntime = class SlotTestRuntime {
|
|
|
1406
1498
|
ctx.provide("fileUpload", this.fileUpload);
|
|
1407
1499
|
this.disposeWorkspaceSource = slots.provideRoot({ hooks: { workspaces: this.workspaces.list } });
|
|
1408
1500
|
this.disposePanelInfoSource = slots.provideRoot({ hooks: { panelInfo: this.panelInfo } });
|
|
1409
|
-
this.disposeToolbarHostsSource = slots.provideRoot({ hooks: { toolbarHosts: this.toolbarHosts } });
|
|
1410
1501
|
const renderer = createSlotRenderer();
|
|
1411
1502
|
slots.install({ renderRoot: (host, ownerProps) => {
|
|
1412
1503
|
this.host = host;
|
|
@@ -1423,6 +1514,7 @@ var SlotTestRuntime = class SlotTestRuntime {
|
|
|
1423
1514
|
const ctx = new Context();
|
|
1424
1515
|
await ctx.plugin(SlotRegistry).await();
|
|
1425
1516
|
const runtime = new SlotTestRuntime(ctx, ctx.get("slots"));
|
|
1517
|
+
await ctx.plugin(allowAllAccessPlugin).await();
|
|
1426
1518
|
await ctx.plugin({
|
|
1427
1519
|
inject: [...inject],
|
|
1428
1520
|
apply
|
|
@@ -1462,7 +1554,6 @@ var SlotTestRuntime = class SlotTestRuntime {
|
|
|
1462
1554
|
/** Release the default panel hook before mounting the production Layout owner. */
|
|
1463
1555
|
releasePanelInfoSource() {
|
|
1464
1556
|
this.disposePanelInfoSource();
|
|
1465
|
-
this.disposeToolbarHostsSource();
|
|
1466
1557
|
}
|
|
1467
1558
|
/**
|
|
1468
1559
|
* Render the root slot tree through the ctx-level entry (the shell's own
|
|
@@ -1588,11 +1679,10 @@ var SlotTestRuntime = class SlotTestRuntime {
|
|
|
1588
1679
|
this.root.release();
|
|
1589
1680
|
this.disposeWorkspaceSource();
|
|
1590
1681
|
this.disposePanelInfoSource();
|
|
1591
|
-
this.disposeToolbarHostsSource();
|
|
1592
1682
|
await this.sessions.disposeScopes();
|
|
1593
1683
|
await this.stabilizer(() => this.ctx.fiber.dispose());
|
|
1594
1684
|
localStorage.clear();
|
|
1595
1685
|
}
|
|
1596
1686
|
};
|
|
1597
1687
|
//#endregion
|
|
1598
|
-
export { FixtureSession, RemoteError, SlotTestRuntime, TestRemote, TestRoot, TestSessions, TestWorkspaces, bindSnapshotSelector, chatSnapshot, conversationSnapshot, createSlotRenderer, domSnapshotSerializer, makeTranslate, registerDomSnapshotSerializer, sessionSnapshot,
|
|
1688
|
+
export { FixtureSession, RemoteError, SlotTestRuntime, TestRemote, TestRoot, TestSessions, TestWorkspaces, allowAllAccess, allowAllAccessPlugin, bindSnapshotSelector, chatSnapshot, conversationSnapshot, createSlotRenderer, domSnapshotSerializer, makeTranslate, registerDomSnapshotSerializer, sessionSnapshot, stubConfigForm, usePinnedBrowserLanguages, workspaceSnapshot };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Allow-all access for client specs. Production pages receive the
|
|
3
|
+
* `remoteAccess` Client service and the global-resource `useRemoteAccess` Hook
|
|
4
|
+
* from the remote-access Client plugin, and the Session and Workspace access
|
|
5
|
+
* Hooks (Session-scope `useAccess`, `useSessionAccess`, `useWorkspaceAccess`)
|
|
6
|
+
* from ui-session and ui-workspace over that service. The test runtimes
|
|
7
|
+
* install an allow-all service and `useRemoteAccess` Hook instead, and
|
|
8
|
+
* hand-built component props spread {@link allowAllAccess}; a spec of a
|
|
9
|
+
* refused path overrides one Hook.
|
|
10
|
+
* @module @deepseek-ai/dsh-client-test-runtime/src/access
|
|
11
|
+
*/
|
|
12
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
13
|
+
import type { GlobalStandardProps, SessionStandardProps } from '@deepseek-ai/dsh-client-ui-slots';
|
|
14
|
+
/** The access Hooks every Slot component receives. */
|
|
15
|
+
export type AccessStandardProps = Pick<GlobalStandardProps, 'useRemoteAccess' | 'useSessionAccess' | 'useWorkspaceAccess'> & Pick<SessionStandardProps, 'useAccess'>;
|
|
16
|
+
/** Access Hooks that allow every action on every resource, for hand-built component props. */
|
|
17
|
+
export declare const allowAllAccess: AccessStandardProps;
|
|
18
|
+
/**
|
|
19
|
+
* Plugin standing in for the remote-access Client row: it provides an
|
|
20
|
+
* allow-all `remoteAccess` service, so ui-session and ui-workspace publish
|
|
21
|
+
* their resource Hooks over it, and the allow-all `useRemoteAccess` Hook on
|
|
22
|
+
* the global resource.
|
|
23
|
+
*/
|
|
24
|
+
export declare const allowAllAccessPlugin: {
|
|
25
|
+
name: string;
|
|
26
|
+
inject: string[];
|
|
27
|
+
/** @param ctx - plugin Context with the Slot registry injected. */
|
|
28
|
+
apply(ctx: Context): void;
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=access.d.ts.map
|
|
@@ -5,11 +5,12 @@ export declare const WEB_PROFILE_BUNDLES: readonly string[];
|
|
|
5
5
|
* Compose the browser roster of `bundles`, applied in order.
|
|
6
6
|
* @param bundles - bundle package names in application order.
|
|
7
7
|
* @param anchor - file whose package resolution locates the bundles; default this package.
|
|
8
|
+
* @param disabledContext - optional Loader evaluation scope for trusted `disabled` expressions.
|
|
8
9
|
* @returns the roster in composition order, one row per package.
|
|
9
10
|
* @throws {Error} when a bundle, its patch file, or an enabled row's package does not resolve, when the patch list
|
|
10
|
-
* is not a list or does not apply as written, or when a browser row
|
|
11
|
+
* is not a list or does not apply as written, or when a browser row has an unevaluated `disabled` expression.
|
|
11
12
|
*/
|
|
12
|
-
export declare function bundleRoster(bundles: readonly string[], anchor?: string): ClientRoster;
|
|
13
|
-
/** The `web` profile's browser roster, composed
|
|
13
|
+
export declare function bundleRoster(bundles: readonly string[], anchor?: string, disabledContext?: object): ClientRoster;
|
|
14
|
+
/** The `web` profile's browser roster, composed with its profile name and no business Host services. */
|
|
14
15
|
export declare const webApp: ClientRoster;
|
|
15
16
|
//# sourceMappingURL=bundle-roster.d.ts.map
|
|
@@ -18,10 +18,10 @@ export interface ClientRosterRow {
|
|
|
18
18
|
}
|
|
19
19
|
/**
|
|
20
20
|
* Synthesize the raw `WebBootGraph` for `rows`: one `application` batch
|
|
21
|
-
* holding every row, `rev: 'local'`, placeholder
|
|
22
|
-
*
|
|
23
|
-
* stays with the production `parseBootManifest` inside the module
|
|
24
|
-
* duplicate names and an empty roster are rejected there, not here.
|
|
21
|
+
* holding every row, `rev: 'local'`, placeholder `plugins/<name>/client.js`
|
|
22
|
+
* references, since every module is seeded in process and never fetched.
|
|
23
|
+
* Validation stays with the production `parseBootManifest` inside the module
|
|
24
|
+
* system: duplicate names and an empty roster are rejected there, not here.
|
|
25
25
|
* @param rows - roster rows in composition order.
|
|
26
26
|
* @returns the unparsed graph, as `createClientModuleSystem` consumes it.
|
|
27
27
|
*/
|
|
@@ -38,8 +38,10 @@ export declare class TestClient {
|
|
|
38
38
|
* dropped from the roster: its generated Remote clients exist only in built
|
|
39
39
|
* `lib/`, and the `remote.<ns>` services the roster injects (plus the
|
|
40
40
|
* namespaces the mock has rules for at this point) are provided as
|
|
41
|
-
* contract-free proxies over the same Connection instead
|
|
42
|
-
*
|
|
41
|
+
* contract-free proxies over the same Connection instead. The
|
|
42
|
+
* `@deepseek-ai/dsh-api-remote-access` row, which mounts its own generated
|
|
43
|
+
* contribution, is dropped too, and allow-all access Hooks replace it. A
|
|
44
|
+
* `provide` entry for either row is refused. On any failure the context is disposed, an owned
|
|
43
45
|
* mount removed, and this client's hold on the shims released before the
|
|
44
46
|
* original error is rethrown.
|
|
45
47
|
* @param plan - roster and annotations.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** Test doubles for settings transport. */
|
|
2
|
+
import { vi } from 'vitest';
|
|
3
|
+
import type { ConfigForm, ConfigFormSnapshot } from '@deepseek-ai/dsh-client-ui-settings/client';
|
|
4
|
+
/** Handle over one stubbed scope: the scope, its write spy, and publication controls. */
|
|
5
|
+
export interface StubConfigForm<T> {
|
|
6
|
+
/** The scope face handed to the service under test. */
|
|
7
|
+
scope: ConfigForm<T>;
|
|
8
|
+
/** Spy behind `scope.set`; resolves immediately. */
|
|
9
|
+
set: ReturnType<typeof vi.fn>;
|
|
10
|
+
/** Spy behind `scope.mutate`; resolves immediately. */
|
|
11
|
+
mutate: ReturnType<typeof vi.fn<ConfigForm<T>['mutate']>>;
|
|
12
|
+
/** Spy behind `scope.unset`; resolves immediately. */
|
|
13
|
+
unset: ReturnType<typeof vi.fn>;
|
|
14
|
+
/** @returns how many listeners are currently subscribed (disposal assertions). */
|
|
15
|
+
listenerCount(): number;
|
|
16
|
+
/**
|
|
17
|
+
* Replace part of the snapshot and notify subscribers, as a Host
|
|
18
|
+
* acceptance would.
|
|
19
|
+
* @param next - snapshot fields to replace.
|
|
20
|
+
*/
|
|
21
|
+
publish(next: Partial<ConfigFormSnapshot<T>>): void;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Build an in-memory settings scope for service specs: starts in the loading
|
|
25
|
+
* state, records writes, and lets the test publish Host acceptances.
|
|
26
|
+
* @returns the stub handle.
|
|
27
|
+
*/
|
|
28
|
+
export declare function stubConfigForm<T>(): StubConfigForm<T>;
|
|
29
|
+
//# sourceMappingURL=config-form.d.ts.map
|
package/lib/types/index.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ import type { BoundFunctions } from '@testing-library/dom';
|
|
|
18
18
|
import { SlotRegistry } from '@deepseek-ai/dsh-client-ui-renderer/client';
|
|
19
19
|
import type { SessionReference } from '@deepseek-ai/dsh-api-session-controller/client';
|
|
20
20
|
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
21
|
-
import type { PanelInfo
|
|
21
|
+
import type { PanelInfo } from '@deepseek-ai/dsh-client-ui-layout/client';
|
|
22
22
|
import type { ChildrenDecl, ComposedProps, HostObservable, OwnerOf, RenderOpts, SlotComponent, SlotMap, SlotRenderer, SlotFactoryMap, SnapshotSelectorHook, StoredFactory, StoreInstanceLike } from '@deepseek-ai/dsh-client-ui-slots';
|
|
23
23
|
import { TestRemote } from './remote.ts';
|
|
24
24
|
import { TestSessions } from './sessions.ts';
|
|
@@ -27,13 +27,15 @@ import type { Stabilizer } from './fixtures.ts';
|
|
|
27
27
|
export type { UseSession } from '@deepseek-ai/dsh-client-ui-session/client';
|
|
28
28
|
export { domSnapshotSerializer, registerDomSnapshotSerializer } from './snapshot.ts';
|
|
29
29
|
export { FixtureSession, TestSessions } from './sessions.ts';
|
|
30
|
-
export {
|
|
31
|
-
export type {
|
|
30
|
+
export { stubConfigForm } from './config-form.ts';
|
|
31
|
+
export type { StubConfigForm } from './config-form.ts';
|
|
32
32
|
export { TestWorkspaces } from './workspaces.ts';
|
|
33
33
|
export { RemoteError, TestRemote } from './remote.ts';
|
|
34
34
|
export { chatSnapshot, conversationSnapshot, sessionSnapshot, workspaceSnapshot, } from './fixtures.ts';
|
|
35
35
|
export type { FixtureSnapshot, SessionBehaviorOverrides, SessionFixture, SessionFixtureSnapshot, Stabilizer, } from './fixtures.ts';
|
|
36
36
|
export { makeTranslate } from './translate.ts';
|
|
37
|
+
export { allowAllAccess, allowAllAccessPlugin } from './access.ts';
|
|
38
|
+
export type { AccessStandardProps } from './access.ts';
|
|
37
39
|
export { usePinnedBrowserLanguages } from './locale-env.ts';
|
|
38
40
|
/**
|
|
39
41
|
* Bind an observable source to the production renderer's selector hook.
|
|
@@ -136,8 +138,6 @@ export declare class SlotTestRuntime {
|
|
|
136
138
|
readonly workspaces: TestWorkspaces;
|
|
137
139
|
/** Test-owned panel selection used by the framework's usePanelInfo hook. */
|
|
138
140
|
readonly panelInfo: import("@deepseek-ai/dsh-client-store").SnapshotStore<PanelInfo>;
|
|
139
|
-
/** Test-owned toolbar portal hosts used by the framework's useToolbarHosts hook (null = no toolbar). */
|
|
140
|
-
readonly toolbarHosts: import("@deepseek-ai/dsh-client-store").SnapshotStore<ToolbarHosts | null>;
|
|
141
141
|
/** Mutable file-upload stub; replace `upload` in suites that exercise the capability. */
|
|
142
142
|
readonly fileUpload: TestFileUpload;
|
|
143
143
|
private readonly stabilizer;
|
|
@@ -151,7 +151,6 @@ export declare class SlotTestRuntime {
|
|
|
151
151
|
private autoRootView;
|
|
152
152
|
private readonly disposeWorkspaceSource;
|
|
153
153
|
private readonly disposePanelInfoSource;
|
|
154
|
-
private readonly disposeToolbarHostsSource;
|
|
155
154
|
private constructor();
|
|
156
155
|
/**
|
|
157
156
|
* Assemble a runtime: real Context, mounted SlotRegistry, installed
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Package-owned invariant companion for `@deepseek-ai/dsh-client-test-runtime`.
|
|
3
|
+
* @module @deepseek-ai/dsh-client-test-runtime/invariant
|
|
4
|
+
*/
|
|
5
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
6
|
+
/** Cordis companion plugin name. */
|
|
7
|
+
export declare const name = "client-test-runtime-invariant";
|
|
8
|
+
/** Service required before the companion can reserve package ownership. */
|
|
9
|
+
export declare const inject: string[];
|
|
10
|
+
/**
|
|
11
|
+
* Register this package's invariant companion.
|
|
12
|
+
* @param ctx - Cordis context carrying the invariant service.
|
|
13
|
+
* @returns the installed registration's disposer after setup succeeds.
|
|
14
|
+
*/
|
|
15
|
+
export declare const apply: (ctx: Context) => Promise<() => void>;
|
|
16
|
+
//# sourceMappingURL=invariant.d.ts.map
|
package/lib/types/sessions.d.ts
CHANGED
|
@@ -120,7 +120,7 @@ export declare class TestSessions implements ISessions {
|
|
|
120
120
|
private closed;
|
|
121
121
|
/** Calls observed on the service-level face, newest last. */
|
|
122
122
|
readonly calls: {
|
|
123
|
-
method: 'create' | '
|
|
123
|
+
method: 'create' | 'refreshProjections' | 'refresh' | 'search' | 'fork';
|
|
124
124
|
args: unknown[];
|
|
125
125
|
}[];
|
|
126
126
|
/** The wire schema's `session.search` result bound (production parity). */
|
|
@@ -229,10 +229,8 @@ export declare class TestSessions implements ISessions {
|
|
|
229
229
|
create(opts?: Parameters<ISessions['create']>[0]): Promise<SessionId>;
|
|
230
230
|
/** Resolve a retained or catalog-derived address independently of a view. */
|
|
231
231
|
subagentAddress(id: SessionId): SubagentAddress | undefined;
|
|
232
|
-
/** Record
|
|
233
|
-
|
|
234
|
-
/** Record a catalog refresh; fixture callers drive snapshots explicitly. */
|
|
235
|
-
refreshSubagents(parentSessionId: SessionId): Promise<void>;
|
|
232
|
+
/** Record a projection refresh; fixture callers drive snapshots explicitly. */
|
|
233
|
+
refreshProjections(sessionId: SessionId): Promise<void>;
|
|
236
234
|
/** Record a list refresh; fixture callers publish list state explicitly. */
|
|
237
235
|
refresh(): Promise<void>;
|
|
238
236
|
/**
|
|
@@ -258,11 +256,7 @@ export declare class TestSessions implements ISessions {
|
|
|
258
256
|
* @param opts - source session id, optional cut anchor, and client title policy.
|
|
259
257
|
* @returns the source id (no child record is created).
|
|
260
258
|
*/
|
|
261
|
-
fork(opts:
|
|
262
|
-
sessionId: SessionId;
|
|
263
|
-
atSeq?: number;
|
|
264
|
-
increaseTitle?: boolean;
|
|
265
|
-
}): Promise<SessionId>;
|
|
259
|
+
fork(opts: Parameters<ISessions['fork']>[0]): Promise<SessionId>;
|
|
266
260
|
/**
|
|
267
261
|
* The session face of a fixture (typed view for assertions; fixture
|
|
268
262
|
* behavior methods are grafted onto it).
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
/** Test double for the client settings-scope seam. */
|
|
2
2
|
import { vi } from 'vitest';
|
|
3
|
-
import type { SettingsScope, SettingsScopeSnapshot } from '@deepseek-ai/dsh-client-
|
|
3
|
+
import type { SettingsScope, SettingsScopeSnapshot } from '@deepseek-ai/dsh-client-runtime/client';
|
|
4
4
|
/** Handle over one stubbed scope: the scope, its write spy, and publication controls. */
|
|
5
5
|
export interface StubSettingsScope<T> {
|
|
6
6
|
/** The scope face handed to the service under test. */
|
|
7
7
|
scope: SettingsScope<T>;
|
|
8
8
|
/** Spy behind `scope.set`; resolves immediately. */
|
|
9
9
|
set: ReturnType<typeof vi.fn>;
|
|
10
|
-
/** Spy behind `scope.mutate`; resolves immediately. */
|
|
11
|
-
mutate: ReturnType<typeof vi.fn>;
|
|
12
10
|
/** Spy behind `scope.unset`; resolves immediately. */
|
|
13
11
|
unset: ReturnType<typeof vi.fn>;
|
|
14
12
|
/** @returns how many listeners are currently subscribed (disposal assertions). */
|
|
@@ -52,6 +52,12 @@ export declare class TestWorkspaces implements IWorkspaces {
|
|
|
52
52
|
create(input: {
|
|
53
53
|
path: string;
|
|
54
54
|
}): Promise<WorkspaceView>;
|
|
55
|
+
/**
|
|
56
|
+
* Initialize the default Workspace through a test stub; defaults to an ineligible first use.
|
|
57
|
+
* @param signal - caller lifetime.
|
|
58
|
+
* @returns the stubbed Workspace, or undefined when initialization is ineligible.
|
|
59
|
+
*/
|
|
60
|
+
initializeDefault(signal?: AbortSignal): Promise<WorkspaceView | undefined>;
|
|
55
61
|
/**
|
|
56
62
|
* Rename a Workspace (recorded). The default echoes a minimal view.
|
|
57
63
|
* @param workspaceId - target workspace.
|
|
@@ -90,6 +96,18 @@ export declare class TestWorkspaces implements IWorkspaces {
|
|
|
90
96
|
* @param sessionId - session to unarchive.
|
|
91
97
|
*/
|
|
92
98
|
unarchiveSession(sessionId: SessionId): Promise<void>;
|
|
99
|
+
/**
|
|
100
|
+
* Pin a session (recorded). The default mirrors the production face's
|
|
101
|
+
* observable effect: the id leads the list state's pin set.
|
|
102
|
+
* @param sessionId - session to pin.
|
|
103
|
+
*/
|
|
104
|
+
pinSession(sessionId: SessionId): Promise<void>;
|
|
105
|
+
/**
|
|
106
|
+
* Unpin a session (recorded). The default mirrors the production face's
|
|
107
|
+
* observable effect: the id leaves the list state's pin set.
|
|
108
|
+
* @param sessionId - session to unpin.
|
|
109
|
+
*/
|
|
110
|
+
unpinSession(sessionId: SessionId): Promise<void>;
|
|
93
111
|
}
|
|
94
112
|
export {};
|
|
95
113
|
//# sourceMappingURL=workspaces.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crazx/dsh-client-test-runtime",
|
|
3
3
|
"description": "Browser test runtimes: a jsdom slot bench with test-owned Session and Workspace doubles, and a whole-client tier that boots the web roster through the production bootClient over an endpoint-named Remote mock",
|
|
4
|
-
"version": "0.1
|
|
4
|
+
"version": "0.2.1-rc.2.zw.8",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -24,68 +24,68 @@
|
|
|
24
24
|
"license": "MIT",
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@testing-library/dom": "^10.4.1",
|
|
27
|
-
"@testing-library/react": "^16.3.
|
|
28
|
-
"js-yaml": "^4.2
|
|
29
|
-
"vitest": "^4.1.
|
|
27
|
+
"@testing-library/react": "^16.3.3",
|
|
28
|
+
"js-yaml": "^4.3.2",
|
|
29
|
+
"vitest": "^4.1.11"
|
|
30
30
|
},
|
|
31
31
|
"peerDependencies": {
|
|
32
|
-
"@deepseek-ai/cordis": "
|
|
33
|
-
"@deepseek-ai/cordis-plugin-include": "
|
|
34
|
-
"@deepseek-ai/cordis-plugin-loader": "
|
|
35
|
-
"@deepseek-ai/dsh-api-gateway": "
|
|
36
|
-
"@deepseek-ai/dsh-api-session-controller": "0.1
|
|
37
|
-
"@deepseek-ai/dsh-api-workspace-controller": "
|
|
38
|
-
"@deepseek-ai/dsh-attachment": "
|
|
39
|
-
"@deepseek-ai/dsh-client-connection": "
|
|
40
|
-
"@deepseek-ai/dsh-client-hmr": "
|
|
41
|
-
"@deepseek-ai/dsh-client-modules": "0.1
|
|
42
|
-
"@deepseek-ai/dsh-client-store": "
|
|
43
|
-
"@deepseek-ai/dsh-client-ui-chat": "
|
|
44
|
-
"@deepseek-ai/dsh-client-ui-conversation": "0.1
|
|
45
|
-
"@deepseek-ai/dsh-client-ui-renderer": "
|
|
46
|
-
"@deepseek-ai/dsh-client-ui-session": "
|
|
47
|
-
"@deepseek-ai/dsh-client-ui-settings": "
|
|
48
|
-
"@deepseek-ai/dsh-client-ui-slots": "
|
|
49
|
-
"@deepseek-ai/dsh-client-web": "
|
|
50
|
-
"@deepseek-ai/dsh-remote-mock": "
|
|
51
|
-
"@deepseek-ai/dsh-session": "
|
|
52
|
-
"@deepseek-ai/dsh-subagent": "
|
|
53
|
-
"@deepseek-ai/dsh-typert-protocol": "
|
|
32
|
+
"@deepseek-ai/cordis": "~4.0.5",
|
|
33
|
+
"@deepseek-ai/cordis-plugin-include": "~1.0.10",
|
|
34
|
+
"@deepseek-ai/cordis-plugin-loader": "~1.0.6",
|
|
35
|
+
"@deepseek-ai/dsh-api-gateway": "0.2.1-rc.2",
|
|
36
|
+
"@deepseek-ai/dsh-api-session-controller": "0.2.1-rc.2",
|
|
37
|
+
"@deepseek-ai/dsh-api-workspace-controller": "0.2.1-rc.2",
|
|
38
|
+
"@deepseek-ai/dsh-attachment": "0.2.1-rc.2",
|
|
39
|
+
"@deepseek-ai/dsh-client-connection": "0.2.1-rc.2",
|
|
40
|
+
"@deepseek-ai/dsh-client-hmr": "0.2.1-rc.2",
|
|
41
|
+
"@deepseek-ai/dsh-client-modules": "0.2.1-rc.2",
|
|
42
|
+
"@deepseek-ai/dsh-client-store": "0.2.1-rc.2",
|
|
43
|
+
"@deepseek-ai/dsh-client-ui-chat": "0.2.1-rc.2",
|
|
44
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.2.1-rc.2",
|
|
45
|
+
"@deepseek-ai/dsh-client-ui-renderer": "0.2.1-rc.2",
|
|
46
|
+
"@deepseek-ai/dsh-client-ui-session": "0.2.1-rc.2",
|
|
47
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.2.1-rc.2",
|
|
48
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.2.1-rc.2",
|
|
49
|
+
"@deepseek-ai/dsh-client-web": "0.2.1-rc.2",
|
|
50
|
+
"@deepseek-ai/dsh-remote-mock": "0.2.1-rc.2",
|
|
51
|
+
"@deepseek-ai/dsh-session": "0.2.1-rc.2",
|
|
52
|
+
"@deepseek-ai/dsh-subagent": "0.2.1-rc.2",
|
|
53
|
+
"@deepseek-ai/dsh-typert-protocol": "0.2.1-rc.2",
|
|
54
54
|
"react": "^18.2.0",
|
|
55
55
|
"react-dom": "^18.2.0"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"@deepseek-ai/cordis": "
|
|
59
|
-
"@deepseek-ai/cordis-plugin-include": "
|
|
60
|
-
"@deepseek-ai/cordis-plugin-loader": "
|
|
61
|
-
"@deepseek-ai/dsh-api-gateway": "
|
|
62
|
-
"@deepseek-ai/dsh-api-
|
|
63
|
-
"@deepseek-ai/dsh-api-
|
|
64
|
-
"@deepseek-ai/dsh-api-
|
|
65
|
-
"@deepseek-ai/dsh-
|
|
66
|
-
"@deepseek-ai/dsh-
|
|
67
|
-
"@deepseek-ai/dsh-
|
|
68
|
-
"@deepseek-ai/dsh-client-
|
|
69
|
-
"@deepseek-ai/dsh-client-
|
|
70
|
-
"@deepseek-ai/dsh-client-
|
|
71
|
-
"@deepseek-ai/dsh-client-
|
|
72
|
-
"@deepseek-ai/dsh-client-
|
|
73
|
-
"@deepseek-ai/dsh-client-ui-
|
|
74
|
-
"@deepseek-ai/dsh-client-ui-
|
|
75
|
-
"@deepseek-ai/dsh-client-ui-
|
|
76
|
-
"@deepseek-ai/dsh-client-ui-
|
|
77
|
-
"@deepseek-ai/dsh-client-ui-
|
|
78
|
-
"@deepseek-ai/dsh-client-ui-
|
|
79
|
-
"@deepseek-ai/dsh-client-
|
|
80
|
-
"@deepseek-ai/dsh-
|
|
81
|
-
"@deepseek-ai/dsh-
|
|
82
|
-
"@deepseek-ai/dsh-
|
|
83
|
-
"@deepseek-ai/dsh-
|
|
84
|
-
"@deepseek-ai/dsh-
|
|
85
|
-
"@deepseek-ai/dsh-
|
|
58
|
+
"@deepseek-ai/cordis": "~4.0.5",
|
|
59
|
+
"@deepseek-ai/cordis-plugin-include": "~1.0.10",
|
|
60
|
+
"@deepseek-ai/cordis-plugin-loader": "~1.0.6",
|
|
61
|
+
"@deepseek-ai/dsh-api-gateway": "0.2.1-rc.2",
|
|
62
|
+
"@deepseek-ai/dsh-api-remote-access": "0.2.1-rc.2",
|
|
63
|
+
"@deepseek-ai/dsh-api-remotes": "0.2.1-rc.2",
|
|
64
|
+
"@deepseek-ai/dsh-api-session-controller": "npm:@crazx/dsh-api-session-controller@0.2.1-rc.2.zw.8",
|
|
65
|
+
"@deepseek-ai/dsh-api-workspace-controller": "0.2.1-rc.2",
|
|
66
|
+
"@deepseek-ai/dsh-attachment": "0.2.1-rc.2",
|
|
67
|
+
"@deepseek-ai/dsh-base": "0.2.1-rc.2",
|
|
68
|
+
"@deepseek-ai/dsh-client-connection": "0.2.1-rc.2",
|
|
69
|
+
"@deepseek-ai/dsh-client-hmr": "0.2.1-rc.2",
|
|
70
|
+
"@deepseek-ai/dsh-client-locale": "0.2.1-rc.2",
|
|
71
|
+
"@deepseek-ai/dsh-client-modules": "npm:@crazx/dsh-client-modules@0.2.1-rc.2.zw.8",
|
|
72
|
+
"@deepseek-ai/dsh-client-store": "0.2.1-rc.2",
|
|
73
|
+
"@deepseek-ai/dsh-client-ui-chat": "0.2.1-rc.2",
|
|
74
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.2.1-rc.2",
|
|
75
|
+
"@deepseek-ai/dsh-client-ui-layout": "0.2.1-rc.2",
|
|
76
|
+
"@deepseek-ai/dsh-client-ui-renderer": "0.2.1-rc.2",
|
|
77
|
+
"@deepseek-ai/dsh-client-ui-session": "0.2.1-rc.2",
|
|
78
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.2.1-rc.2",
|
|
79
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.2.1-rc.2",
|
|
80
|
+
"@deepseek-ai/dsh-client-ui-workspace": "npm:@crazx/dsh-client-ui-workspace@0.2.1-rc.2.zw.8",
|
|
81
|
+
"@deepseek-ai/dsh-client-web": "0.2.1-rc.2",
|
|
82
|
+
"@deepseek-ai/dsh-remote-mock": "0.2.1-rc.2",
|
|
83
|
+
"@deepseek-ai/dsh-session": "0.2.1-rc.2",
|
|
84
|
+
"@deepseek-ai/dsh-settings": "0.2.1-rc.2",
|
|
85
|
+
"@deepseek-ai/dsh-subagent": "0.2.1-rc.2",
|
|
86
|
+
"@deepseek-ai/dsh-typert-protocol": "0.2.1-rc.2",
|
|
87
|
+
"@deepseek-ai/dsh-web-app": "0.2.1-rc.2",
|
|
86
88
|
"@types/js-yaml": "^4.0.9",
|
|
87
|
-
"@types/react": "~18.3.1",
|
|
88
|
-
"@types/react-dom": "~18.3.0",
|
|
89
89
|
"react": "^18.2.0",
|
|
90
90
|
"react-dom": "^18.2.0"
|
|
91
91
|
},
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 DeepSeek
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|