@deepseek-ai/dsh-client-ui-plugin-manager 0.1.7-alpha.1 → 0.1.7-alpha.2
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 +2 -2
- package/README.md +11 -3
- package/README.zh.md +11 -3
- package/lib/client.js +70 -12
- package/lib/index.js +140 -4
- package/lib/typert.host.d.ts +3 -0
- package/lib/typert.host.js +53 -0
- package/lib/typert.remote-client.d.ts +21 -0
- package/lib/typert.remote-client.js +28 -0
- package/lib/types/client/manager-store.d.ts +2 -0
- package/lib/types/index.d.ts +35 -3
- package/package.json +36 -18
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# pnpm run verify-translation-pairing --write packages/client/ui-plugin-manager/README.md
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: a7e212adfc0b0ee03e4e8aa77fdf12cfa52205bf
|
|
6
|
+
README.zh.md: be30b1af3624e6c5fa40fa6caf98f6d3e5bee323
|
package/README.md
CHANGED
|
@@ -31,7 +31,11 @@ Installed bundles and their plugin rows display their own title and description
|
|
|
31
31
|
|
|
32
32
|
### Installing a bundle
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
On first use, when pnpm uses the unconfigured official npm registry and npmmirror is offered, the Host probes both registries in parallel. The first successful HTTPS ping response selects the initial source. The dialog preserves remembered choices, manual selections, explicit manager configuration, and custom or unknown pnpm registries. An install clicked during initial probing waits for that bounded operation; a late result cannot overwrite a manual choice or reopen a closed dialog.
|
|
35
|
+
|
|
36
|
+
The Host sends GET requests to `https://registry.npmjs.org/-/ping` and `https://registry.npmmirror.com/-/ping` through its normal fetch proxy. A 2xx response wins; redirects and failures do not. The remaining request is cancelled, both response bodies are discarded, and cleanup completes before the result returns. The default deadline is 1500 ms and results, including unavailable results, are cached for five minutes. Configure `registryProbeTimeoutMs` and `registryProbeCacheTtlMs` on `ui-plugin-manager`; `registryProbeEnabled: false` disables probing. If both requests fail or time out, the existing default remains selected. No IP-location service or Session content is involved.
|
|
37
|
+
|
|
38
|
+
**Add plugin** takes a package name with an optional version, a Git address, a tarball, or an absolute local path; the dialog says a package name is what follows `dsh plugin add` in a README. **Install guide and examples** under the field opens a guide that shows the three common forms with an example each; **Use example** drops one into the field. **Registry** beside it names the registry the install asks first and unfolds the choice: the default registry, pnpm's own, titled with the host the machine's pnpm configuration names; each mirror the Host configured (`pluginManager.registries`), npmmirror as the mainland China mirror; and a typed http(s) address. The options float over the dialog from the control, so unfolding them never lengthens the card, and the card's content scrolls when the guide makes it taller than the viewport. The initial choice follows the response comparison above; the choice is then remembered in this browser (`localStorage`) and starts the next dialog, and a remembered address the Host no longer offers stays as a typed one and remains the requested address when installation starts before the registry list returns. **Install** first asks the Host to read what the spec names (`pluginManager.inspect`) at the chosen registry: a name the list already shows, a name no registry has, a path without a package, a package without a bundle patch, or a spec pnpm would refuse comes back under the field as one sentence, with the spec kept for editing; when no registry could be reached, the sentence names every one asked. The install then starts at the registry that answered. An accepted spec opens the installing screen, which shows the package's name, one-liner, and version as the Host read them and folds pnpm's command and output behind **Show install details**. A finished install offers **Enable now**, which switches the new bundle on, closes the dialog, and scrolls the list to it; closing instead leaves it installed and off. While the Host moves on to another registry, the installing screen says which registry could not serve the package and which is asked now, and each pnpm run behind the details carries a badge naming its registry. A failed install says what went wrong in one line, as the Host attributed it — no registry could be reached, naming every one asked; the host a GitHub address or a tarball link is fetched from could not be reached, which no registry helps; the package was not found, the disk is full, the profile is not writable, pnpm blocked a build script — with pnpm's output behind the details and **Retry** at hand, and **Change registry** beside it when the Host laid the failure at the registry it asked, which returns to the spec with the registry options open; the Host has already put the profile files back. When pnpm blocked a dependency's install scripts, the failed screen lists the packages whose scripts wait for permission and offers **Allow these scripts and retry** in place of **Retry**; the Host saves the permission in the profile's `pnpm-workspace.yaml`, which a failed run leaves as pnpm wrote it, then runs pnpm again, and the installed screen names what was allowed. A successful installation does not certify that a module can activate.
|
|
35
39
|
|
|
36
40
|
During preparation and download, **Cancel install** asks the Host to stop the run and waits for confirmation. Loading the bundle cannot be cancelled. Closing with ×, Escape, or the backdrop hides the dialog immediately and requests cancellation when possible. **View installation** reopens the same task with its output; another installation cannot start while its outcome is pending or unconfirmed. Confirmed cancellation returns to the spec and shows a toast; the manifest and lockfile are restored, while downloaded files can remain. A lost installation response triggers a request to recover the result; **Check installation status** and reconnect retry that request. If the Host has no active request, **Installation result unavailable** allows returning to editing after checking the plugin list. A cancellation sent before acceptance waits and retries automatically; a failed cancellation can be retried manually. Hidden tasks report their outcome through toasts without reopening the dialog.
|
|
37
41
|
|
|
@@ -83,6 +87,8 @@ Package management uses the profile's dependency records: installed bundles can
|
|
|
83
87
|
|
|
84
88
|
### Registration
|
|
85
89
|
|
|
90
|
+
The Host entry exposes `pluginRegistryProbe.fastest()` through the generated Remote interface. It shares pending comparisons, expires cached results, and aborts and awaits outstanding probes on unload. Calls after unload return a rejected Promise.
|
|
91
|
+
|
|
86
92
|
The browser plugin registers the `plugins` sidebar entry and its `main` panel through `ctx.slots.inject()`, so both follow late slot declaration, locale changes and teardown. The page is global and belongs to no Session. Display text comes from package metadata and the page's dictionary.
|
|
87
93
|
|
|
88
94
|
### The store
|
|
@@ -124,6 +130,8 @@ None; this package neither assembles nor sends a provider request.
|
|
|
124
130
|
|
|
125
131
|
## Known Limitations and Deferred Work
|
|
126
132
|
|
|
133
|
+
- Ping response time does not measure package-download throughput. Probes use the Host fetch route, which pnpm-specific proxy settings can differ from; users can always choose the registry manually, and installation retains its existing fallback rules.
|
|
134
|
+
|
|
127
135
|
<a id="known-limitations-and-deferred-work"></a>
|
|
128
136
|
|
|
129
137
|
|
|
@@ -134,7 +142,7 @@ These limits define the reach of the management view; they are current package c
|
|
|
134
142
|
- **Rows show a phase, not a reason** — a failed row reads as failed without the Host's error text; the Host log has it.
|
|
135
143
|
- **One install at a time** — the dialog runs one pnpm command; a second spec waits for the first to finish.
|
|
136
144
|
- **No version picker** — the spec is typed as pnpm accepts it; the page neither lists registry versions nor offers upgrades.
|
|
137
|
-
- **The registry choice is this browser's** — it lives in `localStorage`, so another browser
|
|
145
|
+
- **The registry choice is this browser's** — it lives in `localStorage`, so another browser applies its own initial recommendation; the `dsh plugin` command and the agent tool use the Host's configured registry.
|
|
138
146
|
- **Every registry read runs pnpm** — opening the dialog, the check, and the install each ask pnpm what its own configuration names; a machine without pnpm reads it as unknown and is offered no fallback.
|
|
139
147
|
|
|
140
148
|
<a id="dev-note"></a>
|
|
@@ -147,4 +155,4 @@ None.
|
|
|
147
155
|
|
|
148
156
|
</details>
|
|
149
157
|
|
|
150
|
-
**Runtime invariant:** No companion is published.
|
|
158
|
+
**Runtime invariant:** No companion is published. The panel reads Host-owned facts, and the registry-probe cache stores one comparison result without an independently maintained projection.
|
package/README.zh.md
CHANGED
|
@@ -31,7 +31,11 @@ kind: "package-reference"
|
|
|
31
31
|
|
|
32
32
|
### 安装一个组合包
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
首次使用时,如果未显式配置安装源、pnpm 使用官方 npm 源,且列表提供 npmmirror,Host 会并发探测这两个源,选择最先成功响应 HTTPS ping 的源。已记住的选择、用户手选、管理器显式配置,以及自定义或未知的 pnpm 源均保留。在初次探测期间点击安装会等待这次有时限的操作;迟到结果不会覆盖手选或重新打开已关闭的对话框。
|
|
35
|
+
|
|
36
|
+
Host 通过普通 fetch 代理向 `https://registry.npmjs.org/-/ping` 和 `https://registry.npmmirror.com/-/ping` 发送 GET 请求,以最先返回 2xx 的源为结果;重定向和失败不参与选择。随后取消另一条请求、丢弃两个响应体,并在清理完成后返回。默认时限为 1500 毫秒,包括不可用结果在内的探测结果均缓存五分钟。在 `ui-plugin-manager` 上配置 `registryProbeTimeoutMs` 和 `registryProbeCacheTtlMs`;`registryProbeEnabled: false` 关闭探测。两条请求都失败或超时时保留现有默认源。不使用 IP 地区服务,也不发送 Session 内容。
|
|
37
|
+
|
|
38
|
+
**添加插件**接受包名(可带版本)、Git 地址、压缩包或本地绝对路径;对话框说明包名就是 README 里 `dsh plugin add` 后面的那一段。输入框下方的**插件安装引导和示例**展开一段引导,给出三种常见形式各一个示例;**填入示例**把示例填进输入框。旁边的**安装源**写着安装首先询问的注册表,展开后可选:默认安装源,即 pnpm 自身的注册表,标题带上本机 pnpm 配置指向的主机名;Host 配置的每个镜像(`pluginManager.registries`),npmmirror 显示为中国大陆镜像源;以及手动输入的 http(s) 地址。选项从控件上浮在对话框之上,展开不会拉长卡片;引导使卡片高过视口时,卡片内容可以滚动。初始选择遵循上文的响应比较规则;之后选择记在本浏览器(`localStorage`)里,下次打开对话框从它开始,Host 不再提供的已记住地址保留为手动输入的地址;在安装源列表返回前开始安装,也仍请求该地址。**安装**先让 Host 在所选注册表读出 spec 指向什么(`pluginManager.inspect`):列表中已有的名字、所有注册表都没有的名字、没有包的路径、没有组合包 patch 的包,或 pnpm 会拒绝的 spec,都以一句话回到输入框下方,spec 保留可继续编辑;所有注册表都连不上时,这句话列出问过的每一个。随后安装从作答的那个注册表开始。通过检查的 spec 打开安装中界面,展示 Host 读到的包名、一句话简介和版本,pnpm 的命令与输出折叠在**查看安装详情**之后。安装完成后提供**立即启用**:启用新组合包、关闭对话框并把列表滚动到它;直接关闭则让它保持已安装但关闭。Host 改问另一个注册表时,安装中界面会说明哪个源没能提供这个包、现在改问哪个,详情里每次 pnpm 运行都带一个写明所用源的标记。安装失败时按 Host 的归因用一行话说明原因——所有安装源都连不上,并列出问过的每一个;GitHub 地址或压缩包链接自身的主机连不上,换源无济于事;包不存在、磁盘已满、profile 不可写、pnpm 拦下了构建脚本——pnpm 输出在详情里,**重试**就在手边,Host 把失败归于所问注册表时还在旁边提供**更换安装源**,回到 spec 输入界面并展开安装源选项;Host 已经把 profile 文件放回原样。pnpm 拦下依赖的安装脚本时,失败界面列出等待允许的包,并以**允许这些脚本并重试**取代**重试**;Host 把授权写进 profile 的 `pnpm-workspace.yaml`(失败的运行保留 pnpm 写入的这个文件)再运行 pnpm,安装完成界面会说明允许了哪些脚本。安装成功不代表模块一定能够激活。
|
|
35
39
|
|
|
36
40
|
准备和下载期间,**取消安装**会请求 Host 停止运行并等待确认。加载组合包的阶段不可取消。点击 ×、按 Escape 或点击遮罩会立即隐藏对话框,并在可以取消时请求取消。**查看安装任务**会重新打开同一任务并保留输出;结果待定或尚未确认时不能发起另一项安装。确认取消后回到 spec 输入界面并显示 toast;manifest 与 lockfile 已恢复,已下载文件可能保留。安装响应丢失后会请求恢复结果;**核对安装状态**和重连会重试该请求。Host 已无活动请求时,**未能获取安装结果**允许检查插件列表后返回编辑。早于接收确认的取消请求会等待并自动重试;取消失败可手动重试。隐藏的任务通过 toast 通知结果,不会重新弹出对话框。
|
|
37
41
|
|
|
@@ -83,6 +87,8 @@ ctx.slots.inject('plugins.detail.section', () => ctx.slots.register({
|
|
|
83
87
|
|
|
84
88
|
### 注册
|
|
85
89
|
|
|
90
|
+
Host 入口通过生成的 Remote 接口暴露 `pluginRegistryProbe.fastest()`,共享进行中的比较、让缓存按时过期,并在卸载时中止和等待未完成探测。卸载后调用会返回拒绝的 Promise。
|
|
91
|
+
|
|
86
92
|
浏览器插件通过 `ctx.slots.inject()` 注册 `plugins` 侧栏入口与它的 `main` 面板,使两者跟随 slot 延迟声明、本地化变化与销毁。页面为全局页面,不属于任何 Session。显示文本来自包元信息与页面字典。
|
|
87
93
|
|
|
88
94
|
### store
|
|
@@ -124,6 +130,8 @@ ctx.slots.inject('plugins.detail.section', () => ctx.slots.register({
|
|
|
124
130
|
|
|
125
131
|
## 已知限制与延期工作
|
|
126
132
|
|
|
133
|
+
- Ping 响应时间不代表包下载吞吐量。探测使用 Host fetch 的网络路径,pnpm 专用代理设置可能使用不同路径;用户始终可以手动选择安装源,安装仍遵循现有回退规则。
|
|
134
|
+
|
|
127
135
|
<a id="known-limitations-and-deferred-work"></a>
|
|
128
136
|
|
|
129
137
|
|
|
@@ -134,7 +142,7 @@ ctx.slots.inject('plugins.detail.section', () => ctx.slots.register({
|
|
|
134
142
|
- **行只显示阶段,不显示原因**——失败的行只显示为失败,没有 Host 的错误文本;Host 日志里有。
|
|
135
143
|
- **一次只能安装一个**——对话框一次运行一个 pnpm 命令;第二个 spec 要等前一个完成。
|
|
136
144
|
- **没有版本选择器**——spec 按 pnpm 接受的写法输入;页面不列出注册表版本,也不提供升级。
|
|
137
|
-
- **安装源选择只属于本浏览器**——它存在 `localStorage`
|
|
145
|
+
- **安装源选择只属于本浏览器**——它存在 `localStorage` 里,所以另一个浏览器会独立计算初始推荐;`dsh plugin` 命令和 agent 工具使用 Host 配置的注册表。
|
|
138
146
|
- **每次读注册表都要运行 pnpm**——打开对话框、检查、安装各问一次 pnpm 自身配置指向哪里;没有 pnpm 的机器读作未知,不提供备选。
|
|
139
147
|
|
|
140
148
|
<a id="dev-note"></a>
|
|
@@ -147,4 +155,4 @@ ctx.slots.inject('plugins.detail.section', () => ctx.slots.register({
|
|
|
147
155
|
|
|
148
156
|
</details>
|
|
149
157
|
|
|
150
|
-
**运行时不变式:**
|
|
158
|
+
**运行时不变式:** 不发布伴生检查。面板读取 Host 事实,安装源探测缓存只保存一次比较结果,没有独立维护的投影。
|
package/lib/client.js
CHANGED
|
@@ -74,7 +74,7 @@ window.__ModuleLoader__.load({
|
|
|
74
74
|
};
|
|
75
75
|
}
|
|
76
76
|
//#endregion
|
|
77
|
-
//#region ../../util/crypto/
|
|
77
|
+
//#region ../../util/crypto/lib/index.js
|
|
78
78
|
/**
|
|
79
79
|
* Random v4 UUID, minted from `crypto.getRandomValues`.
|
|
80
80
|
* @returns the UUID string.
|
|
@@ -86,10 +86,25 @@ window.__ModuleLoader__.load({
|
|
|
86
86
|
}).join("");
|
|
87
87
|
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
88
88
|
}
|
|
89
|
-
|
|
90
|
-
|
|
89
|
+
/** Public npmmirror URL shared by the fallback configuration and public-registry comparison. */
|
|
90
|
+
const NPMMIRROR_REGISTRY = "https://registry.npmmirror.com/";
|
|
91
91
|
/** An http(s) URL, as pnpm's `--registry` takes it. */
|
|
92
92
|
const REGISTRY_URL = /^https?:\/\/\S+$/;
|
|
93
|
+
/**
|
|
94
|
+
* Parse a registry URL into the form pnpm compares registries in: lower-case host, trailing slash.
|
|
95
|
+
* @param url - the registry as configured or requested.
|
|
96
|
+
* @returns the normalized URL.
|
|
97
|
+
* @throws {Error} for anything but an http(s) URL.
|
|
98
|
+
*/
|
|
99
|
+
function normalizeRegistry(url) {
|
|
100
|
+
let parsed;
|
|
101
|
+
try {
|
|
102
|
+
parsed = new URL(url);
|
|
103
|
+
} catch {}
|
|
104
|
+
if (parsed === void 0 || parsed.protocol !== "http:" && parsed.protocol !== "https:") throw new Error(`a registry must be an http(s) URL: ${url}`);
|
|
105
|
+
if (!parsed.pathname.endsWith("/")) parsed.pathname += "/";
|
|
106
|
+
return parsed.href;
|
|
107
|
+
}
|
|
93
108
|
//#endregion
|
|
94
109
|
//#region lib/types/client/presentation.js
|
|
95
110
|
/** Display labels and toast sentences for global plugin management. */
|
|
@@ -382,6 +397,18 @@ window.__ModuleLoader__.load({
|
|
|
382
397
|
url: remembered.registry
|
|
383
398
|
} : remembered;
|
|
384
399
|
}
|
|
400
|
+
/** Only the shipped public mirror can replace an unconfigured official npm default. */
|
|
401
|
+
function eligibleMirror(registries) {
|
|
402
|
+
if (registries.registry !== null || registries.resolved === null) return void 0;
|
|
403
|
+
let resolved;
|
|
404
|
+
try {
|
|
405
|
+
resolved = normalizeRegistry(registries.resolved);
|
|
406
|
+
} catch (_error) {
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
if (resolved !== "https://registry.npmjs.org/") return void 0;
|
|
410
|
+
return registries.fallbackRegistries.find((registry) => registry === NPMMIRROR_REGISTRY);
|
|
411
|
+
}
|
|
385
412
|
/** Reads and mutates the profile's plugins through the `pluginManager` Remote. */
|
|
386
413
|
var PluginManagerController = class {
|
|
387
414
|
ctx;
|
|
@@ -395,6 +422,7 @@ window.__ModuleLoader__.load({
|
|
|
395
422
|
inspectAbort;
|
|
396
423
|
request;
|
|
397
424
|
noticeSeq = 0;
|
|
425
|
+
registryRead;
|
|
398
426
|
/** The registry last used from this browser, kept across dialogs and page loads; null until one was used. */
|
|
399
427
|
registryMemory = (0, _deepseek_ai_dsh_client_store.createSnapshotStore)(null, { persist: { name: "dsh.plugin-manager.install-registry" } });
|
|
400
428
|
/**
|
|
@@ -422,6 +450,7 @@ window.__ModuleLoader__.load({
|
|
|
422
450
|
/** Stop publishing and drop every late settlement. */
|
|
423
451
|
dispose() {
|
|
424
452
|
this.disposed = true;
|
|
453
|
+
this.registryRead = void 0;
|
|
425
454
|
this.request = void 0;
|
|
426
455
|
this.generation += 1;
|
|
427
456
|
}
|
|
@@ -453,7 +482,11 @@ window.__ModuleLoader__.load({
|
|
|
453
482
|
open: true,
|
|
454
483
|
registry: this.registryMemory.getSnapshot() ?? OFFICIAL_REGISTRY
|
|
455
484
|
} });
|
|
456
|
-
this.
|
|
485
|
+
const read = { choice: this.getSnapshot().install.registry };
|
|
486
|
+
this.registryRead = read;
|
|
487
|
+
read.done = this.readRegistries(read).finally(() => {
|
|
488
|
+
delete read.done;
|
|
489
|
+
});
|
|
457
490
|
} else this.patchInstall({ open: true });
|
|
458
491
|
this.reconcileInstall();
|
|
459
492
|
},
|
|
@@ -464,6 +497,7 @@ window.__ModuleLoader__.load({
|
|
|
464
497
|
return;
|
|
465
498
|
}
|
|
466
499
|
this.abortInspect();
|
|
500
|
+
this.registryRead = void 0;
|
|
467
501
|
this.patch({ install: IDLE_INSTALL });
|
|
468
502
|
},
|
|
469
503
|
editInstallSpec: (text) => {
|
|
@@ -578,15 +612,31 @@ window.__ModuleLoader__.load({
|
|
|
578
612
|
} }
|
|
579
613
|
});
|
|
580
614
|
}
|
|
615
|
+
currentRegistryRead(read) {
|
|
616
|
+
return !this.disposed && this.registryRead === read;
|
|
617
|
+
}
|
|
581
618
|
/** Read the registries the Host offers, for the dialog just opened; a refused read leaves pnpm's own and a typed one. */
|
|
582
|
-
async readRegistries() {
|
|
619
|
+
async readRegistries(read) {
|
|
583
620
|
const answer = await this.ctx.remote.pluginManager.registries();
|
|
584
621
|
const install = this.getSnapshot().install;
|
|
585
|
-
if (this.
|
|
622
|
+
if (!this.currentRegistryRead(read) || !install.open || !answer.ok) return;
|
|
623
|
+
const remembered = this.registryMemory.getSnapshot();
|
|
624
|
+
const untouched = install.registry === read.choice && (install.phase === "idle" || install.phase === "checking");
|
|
625
|
+
if (untouched) read.choice = reconciled(remembered, answer.value);
|
|
586
626
|
this.patchInstall({
|
|
587
627
|
registries: answer.value,
|
|
588
|
-
registry:
|
|
628
|
+
...untouched ? { registry: read.choice } : {}
|
|
589
629
|
});
|
|
630
|
+
const mirror = eligibleMirror(answer.value);
|
|
631
|
+
if (!untouched || remembered !== null || mirror === void 0) return;
|
|
632
|
+
const fastest = await this.ctx.remote.pluginRegistryProbe.fastest();
|
|
633
|
+
const current = this.getSnapshot().install;
|
|
634
|
+
if (!this.currentRegistryRead(read) || !current.open || current.phase !== "idle" && current.phase !== "checking" || current.registry !== read.choice || !fastest.ok || fastest.value !== mirror) return;
|
|
635
|
+
read.choice = {
|
|
636
|
+
kind: "offered",
|
|
637
|
+
registry: mirror
|
|
638
|
+
};
|
|
639
|
+
this.patchInstall({ registry: read.choice });
|
|
590
640
|
}
|
|
591
641
|
/**
|
|
592
642
|
* Fold a chunk belonging to this installation into its pnpm command.
|
|
@@ -713,11 +763,6 @@ window.__ModuleLoader__.load({
|
|
|
713
763
|
});
|
|
714
764
|
return;
|
|
715
765
|
}
|
|
716
|
-
const registry = typed ?? choice.registry;
|
|
717
|
-
this.registryMemory.set(typed === void 0 ? choice : {
|
|
718
|
-
kind: "custom",
|
|
719
|
-
url: typed
|
|
720
|
-
});
|
|
721
766
|
this.abortInspect();
|
|
722
767
|
const controller = new AbortController();
|
|
723
768
|
this.inspectAbort = controller;
|
|
@@ -734,6 +779,18 @@ window.__ModuleLoader__.load({
|
|
|
734
779
|
failure: null,
|
|
735
780
|
approvedBuilds: []
|
|
736
781
|
});
|
|
782
|
+
const read = this.registryRead;
|
|
783
|
+
if (read !== void 0 && choice === read.choice && read.done !== void 0) {
|
|
784
|
+
await read.done;
|
|
785
|
+
if (this.gone(controller.signal) || this.registryRead !== read) return;
|
|
786
|
+
}
|
|
787
|
+
const currentChoice = this.getSnapshot().install.registry;
|
|
788
|
+
const selected = currentChoice.kind === "custom" ? {
|
|
789
|
+
...currentChoice,
|
|
790
|
+
url: currentChoice.url.trim()
|
|
791
|
+
} : currentChoice;
|
|
792
|
+
const registry = selected.kind === "custom" ? selected.url : selected.registry;
|
|
793
|
+
this.registryMemory.set(selected);
|
|
737
794
|
const inspected = await this.ctx.remote.pluginManager.inspect(spec, { registry }, controller.signal);
|
|
738
795
|
if (this.gone(controller.signal)) return;
|
|
739
796
|
this.inspectAbort = void 0;
|
|
@@ -3172,6 +3229,7 @@ window.__ModuleLoader__.load({
|
|
|
3172
3229
|
"remote",
|
|
3173
3230
|
"remote.pluginManager",
|
|
3174
3231
|
"remote.pluginInventory",
|
|
3232
|
+
"remote.pluginRegistryProbe",
|
|
3175
3233
|
"configForms"
|
|
3176
3234
|
];
|
|
3177
3235
|
/**
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,142 @@
|
|
|
1
|
+
import z from "@deepseek-ai/schemastery";
|
|
2
|
+
import { MAX_TIMER_DELAY_MS } from "@deepseek-ai/dsh-timeout";
|
|
3
|
+
import { Remote, TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
|
|
1
4
|
//#region lib/types/index.js
|
|
2
|
-
/** Host
|
|
3
|
-
|
|
4
|
-
|
|
5
|
+
/** Host registry-response probing for the plugin installation dialog. */
|
|
6
|
+
var __runInitializers = function(thisArg, initializers, value) {
|
|
7
|
+
var useValue = arguments.length > 2;
|
|
8
|
+
for (var i = 0; i < initializers.length; i++) value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
9
|
+
return useValue ? value : void 0;
|
|
10
|
+
};
|
|
11
|
+
var __esDecorate = function(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
12
|
+
function accept(f) {
|
|
13
|
+
if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected");
|
|
14
|
+
return f;
|
|
15
|
+
}
|
|
16
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
17
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
18
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
19
|
+
var _, done = false;
|
|
20
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
21
|
+
var context = {};
|
|
22
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
23
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
24
|
+
context.addInitializer = function(f) {
|
|
25
|
+
if (done) throw new TypeError("Cannot add initializers after decoration has completed");
|
|
26
|
+
extraInitializers.push(accept(f || null));
|
|
27
|
+
};
|
|
28
|
+
var result = (0, decorators[i])(kind === "accessor" ? {
|
|
29
|
+
get: descriptor.get,
|
|
30
|
+
set: descriptor.set
|
|
31
|
+
} : descriptor[key], context);
|
|
32
|
+
if (kind === "accessor") {
|
|
33
|
+
if (result === void 0) continue;
|
|
34
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
35
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
36
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
37
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
38
|
+
} else if (_ = accept(result)) if (kind === "field") initializers.unshift(_);
|
|
39
|
+
else descriptor[key] = _;
|
|
40
|
+
}
|
|
41
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
42
|
+
done = true;
|
|
43
|
+
};
|
|
44
|
+
let PluginRegistryProbe = (() => {
|
|
45
|
+
let _classSuper = TypertRemoteService;
|
|
46
|
+
let _instanceExtraInitializers = [];
|
|
47
|
+
let _fastest_decorators;
|
|
48
|
+
return class PluginRegistryProbe extends _classSuper {
|
|
49
|
+
static {
|
|
50
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
51
|
+
_fastest_decorators = [Remote];
|
|
52
|
+
__esDecorate(this, null, _fastest_decorators, {
|
|
53
|
+
kind: "method",
|
|
54
|
+
name: "fastest",
|
|
55
|
+
static: false,
|
|
56
|
+
private: false,
|
|
57
|
+
access: {
|
|
58
|
+
has: (obj) => "fastest" in obj,
|
|
59
|
+
get: (obj) => obj.fastest
|
|
60
|
+
},
|
|
61
|
+
metadata: _metadata
|
|
62
|
+
}, null, _instanceExtraInitializers);
|
|
63
|
+
if (_metadata) Object.defineProperty(this, Symbol.metadata, {
|
|
64
|
+
enumerable: true,
|
|
65
|
+
configurable: true,
|
|
66
|
+
writable: true,
|
|
67
|
+
value: _metadata
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
config = __runInitializers(this, _instanceExtraInitializers);
|
|
71
|
+
static Config = z.object({
|
|
72
|
+
registryProbeEnabled: z.boolean().default(true),
|
|
73
|
+
registryProbeTimeoutMs: z.natural().min(1).max(MAX_TIMER_DELAY_MS).default(1500),
|
|
74
|
+
registryProbeCacheTtlMs: z.natural().default(3e5)
|
|
75
|
+
});
|
|
76
|
+
lifetime = new AbortController();
|
|
77
|
+
pending;
|
|
78
|
+
cached;
|
|
79
|
+
constructor(ctx, config) {
|
|
80
|
+
super(ctx, "pluginRegistryProbe");
|
|
81
|
+
this.config = config;
|
|
82
|
+
ctx.effect(() => async () => {
|
|
83
|
+
this.lifetime.abort();
|
|
84
|
+
await this.pending;
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Race npm and npmmirror HTTPS ping responses through the Host's fetch proxy.
|
|
89
|
+
* Concurrent readers share a probe; a winner cancels and awaits the other request.
|
|
90
|
+
* @returns the first registry with a successful response, or null when disabled or neither responds successfully; results are cached.
|
|
91
|
+
* @throws rejects when the service has been unloaded.
|
|
92
|
+
*/
|
|
93
|
+
async fastest() {
|
|
94
|
+
this.lifetime.signal.throwIfAborted();
|
|
95
|
+
if (!this.config.registryProbeEnabled) return null;
|
|
96
|
+
if (this.cached !== void 0 && this.cached.expiresAt > Date.now()) return this.cached.registry;
|
|
97
|
+
this.pending ??= this.probe().finally(() => {
|
|
98
|
+
this.pending = void 0;
|
|
99
|
+
});
|
|
100
|
+
return this.pending;
|
|
101
|
+
}
|
|
102
|
+
async probe() {
|
|
103
|
+
const finished = new AbortController();
|
|
104
|
+
const signal = AbortSignal.any([
|
|
105
|
+
this.lifetime.signal,
|
|
106
|
+
finished.signal,
|
|
107
|
+
AbortSignal.timeout(this.config.registryProbeTimeoutMs)
|
|
108
|
+
]);
|
|
109
|
+
const requests = ["https://registry.npmjs.org/-/ping", "https://registry.npmmirror.com/-/ping"].map(async (endpoint) => ({
|
|
110
|
+
registry: new URL("/", endpoint).href,
|
|
111
|
+
response: await fetch(endpoint, {
|
|
112
|
+
signal,
|
|
113
|
+
redirect: "error"
|
|
114
|
+
})
|
|
115
|
+
}));
|
|
116
|
+
const successful = requests.map(async (request) => {
|
|
117
|
+
const { registry, response } = await request;
|
|
118
|
+
if (!response.ok) throw new Error(`Registry ping returned HTTP ${response.status}`);
|
|
119
|
+
return registry;
|
|
120
|
+
});
|
|
121
|
+
let registry;
|
|
122
|
+
try {
|
|
123
|
+
registry = await Promise.any(successful);
|
|
124
|
+
} catch (_unavailableRegistries) {
|
|
125
|
+
registry = null;
|
|
126
|
+
} finally {
|
|
127
|
+
finished.abort();
|
|
128
|
+
const responses = await Promise.allSettled(requests);
|
|
129
|
+
await Promise.allSettled(responses.map(async (result) => {
|
|
130
|
+
if (result.status === "fulfilled") await result.value.response.body?.cancel();
|
|
131
|
+
}));
|
|
132
|
+
}
|
|
133
|
+
if (!this.lifetime.signal.aborted) this.cached = {
|
|
134
|
+
registry,
|
|
135
|
+
expiresAt: Date.now() + this.config.registryProbeCacheTtlMs
|
|
136
|
+
};
|
|
137
|
+
return registry;
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
})();
|
|
5
141
|
//#endregion
|
|
6
|
-
export {
|
|
142
|
+
export { PluginRegistryProbe as default };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/* Generated by @deepseek-ai/dsh-typert-generator from FaceModel — do not edit. */
|
|
2
|
+
import { z } from 'zod'
|
|
3
|
+
|
|
4
|
+
let _deepseek_ai_dsh_client_ui_plugin_manager_pluginRegistryProbe_fastest_result$schema$value
|
|
5
|
+
const _deepseek_ai_dsh_client_ui_plugin_manager_pluginRegistryProbe_fastest_result$schema = () => (_deepseek_ai_dsh_client_ui_plugin_manager_pluginRegistryProbe_fastest_result$schema$value ??= z.union([z.literal(null), z.string()]))
|
|
6
|
+
|
|
7
|
+
export const TYPERT = {
|
|
8
|
+
package: '@deepseek-ai/dsh-client-ui-plugin-manager',
|
|
9
|
+
face: 'host',
|
|
10
|
+
schemas: [
|
|
11
|
+
],
|
|
12
|
+
invocations: [
|
|
13
|
+
{
|
|
14
|
+
id: '@deepseek-ai/dsh-client-ui-plugin-manager#pluginRegistryProbe/fastest',
|
|
15
|
+
service: 'pluginRegistryProbe',
|
|
16
|
+
namespace: 'pluginRegistryProbe',
|
|
17
|
+
method: 'fastest',
|
|
18
|
+
invocation: { kind: 'direct' },
|
|
19
|
+
parameters: [
|
|
20
|
+
],
|
|
21
|
+
result: {
|
|
22
|
+
mode: 'strict',
|
|
23
|
+
typeSymbol: '@deepseek-ai/dsh-client-ui-plugin-manager#pluginRegistryProbe/fastest:result',
|
|
24
|
+
create: _deepseek_ai_dsh_client_ui_plugin_manager_pluginRegistryProbe_fastest_result$schema,
|
|
25
|
+
},
|
|
26
|
+
sourceLocation: {"file":"packages/client/ui-plugin-manager/src/index.ts","line":51,"column":9},
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
model: {
|
|
30
|
+
"services": [
|
|
31
|
+
{
|
|
32
|
+
"description": "Compares public registry responses on the Host; the Client owns the initial selection.",
|
|
33
|
+
"summary": "Compares public registry responses on the Host; the Client owns the initial selection.",
|
|
34
|
+
"tags": [],
|
|
35
|
+
"jsDoc": "/** Compares public registry responses on the Host; the Client owns the initial selection. */",
|
|
36
|
+
"key": "pluginRegistryProbe",
|
|
37
|
+
"exportName": "default",
|
|
38
|
+
"members": [
|
|
39
|
+
{
|
|
40
|
+
"kind": "method",
|
|
41
|
+
"name": "fastest",
|
|
42
|
+
"signature": "@Remote async fastest(): Promise<string | null>",
|
|
43
|
+
"summary": "Race npm and npmmirror HTTPS ping responses through the Host's fetch proxy.",
|
|
44
|
+
"jsDoc": "/**\n * Race npm and npmmirror HTTPS ping responses through the Host's fetch proxy.\n * Concurrent readers share a probe; a winner cancels and awaits the other request.\n * @returns the first registry with a successful response, or null when disabled or neither responds successfully; results are cached.\n * @throws rejects when the service has been unloaded.\n */"
|
|
45
|
+
}
|
|
46
|
+
],
|
|
47
|
+
"types": []
|
|
48
|
+
}
|
|
49
|
+
],
|
|
50
|
+
"events": [],
|
|
51
|
+
"objects": []
|
|
52
|
+
},
|
|
53
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/* Generated by @deepseek-ai/dsh-typert-generator from the Host FaceModel — do not edit. */
|
|
2
|
+
import type {
|
|
3
|
+
RemoteResult,
|
|
4
|
+
TypertRemoteContribution,
|
|
5
|
+
} from '@deepseek-ai/dsh-typert-protocol'
|
|
6
|
+
|
|
7
|
+
declare module '@deepseek-ai/dsh-typert-protocol' {
|
|
8
|
+
interface TypertRemoteNamespace$706c7567696e526567697374727950726f6265 {
|
|
9
|
+
fastest: () => Promise<RemoteResult<string | null>>
|
|
10
|
+
}
|
|
11
|
+
interface TypertRemoteMap {
|
|
12
|
+
'pluginRegistryProbe/fastest': () => Promise<RemoteResult<string | null>>
|
|
13
|
+
}
|
|
14
|
+
interface TypertRemoteNamespaceMap {
|
|
15
|
+
'pluginRegistryProbe': TypertRemoteNamespace$706c7567696e526567697374727950726f6265
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export declare const TYPERT_REMOTE: TypertRemoteContribution
|
|
20
|
+
export default TYPERT_REMOTE
|
|
21
|
+
//# sourceMappingURL=typert.remote-client.d.ts.map
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/* Generated by @deepseek-ai/dsh-typert-generator from the Host FaceModel — do not edit. */
|
|
2
|
+
import { z } from 'zod'
|
|
3
|
+
|
|
4
|
+
let _deepseek_ai_dsh_client_ui_plugin_manager_pluginRegistryProbe_fastest_result$schema$value
|
|
5
|
+
const _deepseek_ai_dsh_client_ui_plugin_manager_pluginRegistryProbe_fastest_result$schema = () => (_deepseek_ai_dsh_client_ui_plugin_manager_pluginRegistryProbe_fastest_result$schema$value ??= z.union([z.literal(null), z.string()]))
|
|
6
|
+
|
|
7
|
+
export const TYPERT_REMOTE = {
|
|
8
|
+
package: '@deepseek-ai/dsh-client-ui-plugin-manager',
|
|
9
|
+
descriptors: [
|
|
10
|
+
{
|
|
11
|
+
id: '@deepseek-ai/dsh-client-ui-plugin-manager#pluginRegistryProbe/fastest',
|
|
12
|
+
service: 'pluginRegistryProbe',
|
|
13
|
+
namespace: 'pluginRegistryProbe',
|
|
14
|
+
method: 'fastest',
|
|
15
|
+
invocation: { kind: 'direct' },
|
|
16
|
+
parameters: [
|
|
17
|
+
],
|
|
18
|
+
result: {
|
|
19
|
+
mode: 'strict',
|
|
20
|
+
typeSymbol: '@deepseek-ai/dsh-client-ui-plugin-manager#pluginRegistryProbe/fastest:result',
|
|
21
|
+
create: _deepseek_ai_dsh_client_ui_plugin_manager_pluginRegistryProbe_fastest_result$schema,
|
|
22
|
+
},
|
|
23
|
+
sourceLocation: {"file":"packages/client/ui-plugin-manager/src/index.ts","line":51,"column":9},
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export default TYPERT_REMOTE
|
|
@@ -285,6 +285,7 @@ export declare class PluginManagerController {
|
|
|
285
285
|
private inspectAbort;
|
|
286
286
|
private request;
|
|
287
287
|
private noticeSeq;
|
|
288
|
+
private registryRead;
|
|
288
289
|
/** The registry last used from this browser, kept across dialogs and page loads; null until one was used. */
|
|
289
290
|
private readonly registryMemory;
|
|
290
291
|
/**
|
|
@@ -310,6 +311,7 @@ export declare class PluginManagerController {
|
|
|
310
311
|
* @param progress - a request id and phase received from the Host.
|
|
311
312
|
*/
|
|
312
313
|
installProgress(progress: PluginInstallProgress): void;
|
|
314
|
+
private currentRegistryRead;
|
|
313
315
|
/** Read the registries the Host offers, for the dialog just opened; a refused read leaves pnpm's own and a typed one. */
|
|
314
316
|
private readRegistries;
|
|
315
317
|
/**
|
package/lib/types/index.d.ts
CHANGED
|
@@ -1,4 +1,36 @@
|
|
|
1
|
-
/** Host
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/** Host registry-response probing for the plugin installation dialog. */
|
|
2
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
3
|
+
import z from '@deepseek-ai/schemastery';
|
|
4
|
+
import { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
|
|
5
|
+
declare module '@deepseek-ai/cordis' {
|
|
6
|
+
interface Context {
|
|
7
|
+
pluginRegistryProbe: PluginRegistryProbe;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
/** Registry-probe deadline and process-local cache policy. */
|
|
11
|
+
export interface Config {
|
|
12
|
+
/** Whether the dialog can compare the public npm registries. */
|
|
13
|
+
registryProbeEnabled: boolean;
|
|
14
|
+
/** Deadline for the parallel HTTPS probes, including response cleanup. */
|
|
15
|
+
registryProbeTimeoutMs: number;
|
|
16
|
+
/** Lifetime of a winning registry or unavailable result. */
|
|
17
|
+
registryProbeCacheTtlMs: number;
|
|
18
|
+
}
|
|
19
|
+
/** Compares public registry responses on the Host; the Client owns the initial selection. */
|
|
20
|
+
export default class PluginRegistryProbe extends TypertRemoteService {
|
|
21
|
+
private readonly config;
|
|
22
|
+
static Config: z<Partial<Config>, Config>;
|
|
23
|
+
private readonly lifetime;
|
|
24
|
+
private pending;
|
|
25
|
+
private cached;
|
|
26
|
+
constructor(ctx: Context, config: Config);
|
|
27
|
+
/**
|
|
28
|
+
* Race npm and npmmirror HTTPS ping responses through the Host's fetch proxy.
|
|
29
|
+
* Concurrent readers share a probe; a winner cancels and awaits the other request.
|
|
30
|
+
* @returns the first registry with a successful response, or null when disabled or neither responds successfully; results are cached.
|
|
31
|
+
* @throws rejects when the service has been unloaded.
|
|
32
|
+
*/
|
|
33
|
+
fastest(): Promise<string | null>;
|
|
34
|
+
private probe;
|
|
35
|
+
}
|
|
4
36
|
//# sourceMappingURL=index.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-client-ui-plugin-manager",
|
|
3
3
|
"description": "Plugin management for the dsh web client: the sidebar Plugins panel installs, enables, disables, retries, and composes installed plugin packages",
|
|
4
|
-
"version": "0.1.7-alpha.
|
|
4
|
+
"version": "0.1.7-alpha.2",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -23,7 +23,15 @@
|
|
|
23
23
|
"default": "./lib/client.js"
|
|
24
24
|
},
|
|
25
25
|
"./src/*": "./src/*",
|
|
26
|
-
"./package.json": "./package.json"
|
|
26
|
+
"./package.json": "./package.json",
|
|
27
|
+
"./typert": {
|
|
28
|
+
"types": "./lib/typert.host.d.ts",
|
|
29
|
+
"default": "./lib/typert.host.js"
|
|
30
|
+
},
|
|
31
|
+
"./remote": {
|
|
32
|
+
"types": "./lib/typert.remote-client.d.ts",
|
|
33
|
+
"default": "./lib/typert.remote-client.js"
|
|
34
|
+
}
|
|
27
35
|
},
|
|
28
36
|
"dsh": {
|
|
29
37
|
"client": {
|
|
@@ -38,7 +46,7 @@
|
|
|
38
46
|
},
|
|
39
47
|
"license": "MIT",
|
|
40
48
|
"peerDependencies": {
|
|
41
|
-
"@deepseek-ai/cordis": "
|
|
49
|
+
"@deepseek-ai/cordis": "~4.0.4"
|
|
42
50
|
},
|
|
43
51
|
"devDependencies": {
|
|
44
52
|
"@testing-library/react": "^16.1.0",
|
|
@@ -47,26 +55,36 @@
|
|
|
47
55
|
"clsx": "^2.1.1",
|
|
48
56
|
"react": "^18.2.0",
|
|
49
57
|
"react-dom": "^18.2.0",
|
|
50
|
-
"@deepseek-ai/cordis": "
|
|
51
|
-
"@deepseek-ai/dsh-api-remotes": "
|
|
52
|
-
"@deepseek-ai/dsh-client-locale": "
|
|
53
|
-
"@deepseek-ai/dsh-client-store": "
|
|
54
|
-
"@deepseek-ai/dsh-client-test-runtime": "
|
|
55
|
-
"@deepseek-ai/dsh-client-ui-layout": "
|
|
56
|
-
"@deepseek-ai/dsh-client-ui-primitives": "
|
|
57
|
-
"@deepseek-ai/dsh-client-ui-renderer": "
|
|
58
|
-
"@deepseek-ai/dsh-client-ui-sidebar": "
|
|
59
|
-
"@deepseek-ai/dsh-
|
|
60
|
-
"@deepseek-ai/dsh-
|
|
61
|
-
"@deepseek-ai/dsh-
|
|
62
|
-
"@deepseek-ai/dsh-
|
|
63
|
-
"@deepseek-ai/dsh-client-ui-settings": "
|
|
58
|
+
"@deepseek-ai/cordis": "~4.0.4",
|
|
59
|
+
"@deepseek-ai/dsh-api-remotes": "0.1.7-alpha.2",
|
|
60
|
+
"@deepseek-ai/dsh-client-locale": "0.1.7-alpha.2",
|
|
61
|
+
"@deepseek-ai/dsh-client-store": "0.1.7-alpha.2",
|
|
62
|
+
"@deepseek-ai/dsh-client-test-runtime": "0.1.7-alpha.2",
|
|
63
|
+
"@deepseek-ai/dsh-client-ui-layout": "0.1.7-alpha.2",
|
|
64
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.1.7-alpha.2",
|
|
65
|
+
"@deepseek-ai/dsh-client-ui-renderer": "0.1.7-alpha.2",
|
|
66
|
+
"@deepseek-ai/dsh-client-ui-sidebar": "0.1.7-alpha.2",
|
|
67
|
+
"@deepseek-ai/dsh-package-manifest": "0.1.7-alpha.2",
|
|
68
|
+
"@deepseek-ai/dsh-util-crypto": "0.1.7-alpha.2",
|
|
69
|
+
"@deepseek-ai/dsh-plugin-manager": "0.1.7-alpha.2",
|
|
70
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.1.7-alpha.2",
|
|
71
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.1.7-alpha.2"
|
|
64
72
|
},
|
|
65
73
|
"files": [
|
|
66
74
|
"lib/index.js",
|
|
67
75
|
"lib/client.js",
|
|
68
|
-
"lib/types/**/*.d.ts"
|
|
76
|
+
"lib/types/**/*.d.ts",
|
|
77
|
+
"lib/typert.host.js",
|
|
78
|
+
"lib/typert.host.d.ts",
|
|
79
|
+
"lib/typert.remote-client.js",
|
|
80
|
+
"lib/typert.remote-client.d.ts"
|
|
69
81
|
],
|
|
82
|
+
"dependencies": {
|
|
83
|
+
"zod": "^4.4.3",
|
|
84
|
+
"@deepseek-ai/dsh-timeout": "0.1.7-alpha.2",
|
|
85
|
+
"@deepseek-ai/schemastery": "~3.18.4",
|
|
86
|
+
"@deepseek-ai/dsh-typert-protocol": "0.1.7-alpha.2"
|
|
87
|
+
},
|
|
70
88
|
"scripts": {
|
|
71
89
|
"bundle": "tsdown",
|
|
72
90
|
"watch": "tsdown --watch"
|