relay-dsh-plugin-manager 0.1.0-rc.4 → 0.1.0
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/CHANGELOG.md +24 -0
- package/README.md +25 -18
- package/README.zh.md +24 -16
- package/SPEC.md +8 -5
- package/docs/acceptance.md +1 -1
- package/docs/technical-design.md +4 -2
- package/lib/client.js +197 -120
- package/lib/client.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project are documented here.
|
|
4
4
|
|
|
5
|
+
## [0.1.0] - 2026-08-31
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- The Settings > Plugins tab now gives each recommended plugin a self-contained
|
|
10
|
+
card headed by its npm package name, carrying its purpose, prerequisite, the
|
|
11
|
+
complete Chat message that installs it, and its post-install check.
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- The Settings > Plugins help tab is now named "Recommended plugins" and sorts
|
|
16
|
+
ahead of the built-in tabs, so it is the tab Settings > Plugins opens on.
|
|
17
|
+
- The tab's copy is condensed and rescoped. Tab-level text claims nothing about
|
|
18
|
+
a specific plugin; anything true of one plugin lives on that plugin's card.
|
|
19
|
+
The former heading, introduction, standalone confirmation notice, and
|
|
20
|
+
search/remove/list example table are gone.
|
|
21
|
+
- The discovery example no longer names a specific third-party integration.
|
|
22
|
+
|
|
23
|
+
### Compatibility
|
|
24
|
+
|
|
25
|
+
- This release retains the verified DSH `0.1.1-rc.2` baseline. It does not include
|
|
26
|
+
migration to the client APIs introduced in DSH `0.1.2-alpha.2`.
|
|
27
|
+
|
|
5
28
|
## [0.1.0-rc.4] - 2026-08-28
|
|
6
29
|
|
|
7
30
|
### Added
|
|
@@ -55,3 +78,4 @@ All notable changes to this project are documented here.
|
|
|
55
78
|
[0.1.0-rc.2]: https://github.com/yangbobo2021/relay-dsh-plugin-manager/releases/tag/v0.1.0-rc.2
|
|
56
79
|
[0.1.0-rc.3]: https://github.com/yangbobo2021/relay-dsh-plugin-manager/compare/v0.1.0-rc.2...v0.1.0-rc.3
|
|
57
80
|
[0.1.0-rc.4]: https://github.com/yangbobo2021/relay-dsh-plugin-manager/compare/v0.1.0-rc.3...v0.1.0-rc.4
|
|
81
|
+
[0.1.0]: https://github.com/yangbobo2021/relay-dsh-plugin-manager/compare/v0.1.0-rc.4...v0.1.0
|
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Manage DeepSeek Harness Plugins from Chat
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/relay-dsh-plugin-manager)
|
|
4
4
|
[](https://github.com/yangbobo2021/relay-dsh-plugin-manager/actions/workflows/ci.yml)
|
|
@@ -13,10 +13,24 @@ English | [中文](README.zh.md)
|
|
|
13
13
|
**npm package:** [`relay-dsh-plugin-manager`](https://www.npmjs.com/package/relay-dsh-plugin-manager)
|
|
14
14
|
· [Relay DSH plugin catalog](https://github.com/yangbobo2021/Relay/blob/codex/relay-foundation/docs/dsh-plugins.md)
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
**Find and manage DSH plugins by describing what you need, without leaving the
|
|
17
|
+
conversation or editing Profile files by hand.**
|
|
18
|
+
|
|
19
|
+
`relay-dsh-plugin-manager` lets DeepSeek Harness Chat discover, install, update,
|
|
20
|
+
enable, disable, and remove plugins. Search and inspection are read-only. Before
|
|
21
|
+
any change, DSH shows the plan and waits for a separate confirmation.
|
|
22
|
+
|
|
23
|
+
[](https://github.com/yangbobo2021/Relay/blob/codex/relay-foundation/docs/media/dsh-plugin-manager-codex-install-demo.en.mp4?raw=1)
|
|
24
|
+
|
|
25
|
+
*Watch the [40-second real DSH run](https://github.com/yangbobo2021/Relay/blob/codex/relay-foundation/docs/media/dsh-plugin-manager-codex-install-demo.en.mp4?raw=1):
|
|
26
|
+
search, review a no-change plan, confirm separately, and finish with the Codex
|
|
27
|
+
plugin installed. Recorded on official DSH commit
|
|
28
|
+
[`b150a551`](https://github.com/deepseek-ai/deepseek-harness/commit/b150a551b8d465e31e418e1b2eaf5e79bbb7d28e)
|
|
29
|
+
with Plugin Manager `0.1.0-rc.3` and Codex plugin `0.1.2`.*
|
|
30
|
+
|
|
31
|
+
If conversation-first plugin management is useful to you,
|
|
32
|
+
[star this plugin](https://github.com/yangbobo2021/relay-dsh-plugin-manager) and
|
|
33
|
+
[share your install result or missing plugin use case](https://github.com/yangbobo2021/relay-dsh-plugin-manager/issues).
|
|
20
34
|
|
|
21
35
|
## Install
|
|
22
36
|
|
|
@@ -33,8 +47,12 @@ Then start or restart DSH Web:
|
|
|
33
47
|
dsh web
|
|
34
48
|
```
|
|
35
49
|
|
|
36
|
-
|
|
37
|
-
|
|
50
|
+
If `dsh` is not on `PATH`, replace it with
|
|
51
|
+
`pnpm dlx @deepseek-ai/dsh@0.1.1-rc.2` in both commands.
|
|
52
|
+
|
|
53
|
+
The plugin appears under **Settings > Plugins > Recommended plugins**, the tab
|
|
54
|
+
that Settings > Plugins opens on. It presents the recommended conversation-backend
|
|
55
|
+
plugins and a short help view; plugin management itself happens in Chat.
|
|
38
56
|
|
|
39
57
|
### Installed by KeySync
|
|
40
58
|
|
|
@@ -73,17 +91,6 @@ missing companion peers, waits for one confirmation, and runs the installs in
|
|
|
73
91
|
sequence. Completed changes that still need restart are reported explicitly as
|
|
74
92
|
restart-required or waiting for a manual restart.
|
|
75
93
|
|
|
76
|
-
## Real Install Demo
|
|
77
|
-
|
|
78
|
-
[](https://github.com/yangbobo2021/Relay/blob/codex/relay-foundation/docs/media/dsh-plugin-manager-codex-install-demo.en.mp4?raw=1)
|
|
79
|
-
|
|
80
|
-
Watch the [40-second real DSH run](https://github.com/yangbobo2021/Relay/blob/codex/relay-foundation/docs/media/dsh-plugin-manager-codex-install-demo.en.mp4?raw=1):
|
|
81
|
-
search, planning without changes, separate confirmation, installation, and the
|
|
82
|
-
final `succeeded` status. It was recorded against official DSH commit
|
|
83
|
-
[`b150a551`](https://github.com/deepseek-ai/deepseek-harness/commit/b150a551b8d465e31e418e1b2eaf5e79bbb7d28e)
|
|
84
|
-
with Plugin Manager `0.1.0-rc.3` and Codex plugin `0.1.2`. DSH reports when a
|
|
85
|
-
restart is required after installation.
|
|
86
|
-
|
|
87
94
|
## Part of Relay
|
|
88
95
|
|
|
89
96
|
This plugin is developed in the
|
package/README.zh.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# DeepSeek Harness
|
|
1
|
+
# 在 DeepSeek Harness 对话中管理插件
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/relay-dsh-plugin-manager)
|
|
4
4
|
[](https://github.com/yangbobo2021/relay-dsh-plugin-manager/actions/workflows/ci.yml)
|
|
@@ -13,9 +13,24 @@
|
|
|
13
13
|
**npm 包名:** [`relay-dsh-plugin-manager`](https://www.npmjs.com/package/relay-dsh-plugin-manager)
|
|
14
14
|
· [Relay DSH 插件目录](https://github.com/yangbobo2021/Relay/blob/codex/relay-foundation/docs/dsh-plugins.zh.md)
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
**只需描述需要的能力,就能查找和管理 DSH 插件;不必离开对话,也不必手工
|
|
17
|
+
编辑 Profile 文件。**
|
|
18
|
+
|
|
19
|
+
`relay-dsh-plugin-manager` 让 DeepSeek Harness Chat 可以查找、安装、更新、
|
|
20
|
+
启用、停用和卸载插件。搜索和查看只读;任何变更执行前,DSH 都会先展示计划,
|
|
21
|
+
并等待单独确认。
|
|
22
|
+
|
|
23
|
+
[](https://github.com/yangbobo2021/Relay/blob/codex/relay-foundation/docs/media/dsh-plugin-manager-codex-install-demo.zh.mp4?raw=1)
|
|
24
|
+
|
|
25
|
+
*查看 [38 秒真实 DSH 运行录像](https://github.com/yangbobo2021/Relay/blob/codex/relay-foundation/docs/media/dsh-plugin-manager-codex-install-demo.zh.mp4?raw=1):
|
|
26
|
+
从搜索、查看不产生变更的计划、单独确认,到 Codex 插件安装完成。录像基于官方
|
|
27
|
+
DSH 提交
|
|
28
|
+
[`b150a551`](https://github.com/deepseek-ai/deepseek-harness/commit/b150a551b8d465e31e418e1b2eaf5e79bbb7d28e),
|
|
29
|
+
使用 Plugin Manager `0.1.0-rc.2` 和 Codex 插件 `0.1.2`。*
|
|
30
|
+
|
|
31
|
+
如果这种对话式插件管理对你有用,欢迎
|
|
32
|
+
[Star 本插件](https://github.com/yangbobo2021/relay-dsh-plugin-manager),并
|
|
33
|
+
[反馈安装结果或缺少的插件场景](https://github.com/yangbobo2021/relay-dsh-plugin-manager/issues)。
|
|
19
34
|
|
|
20
35
|
## 安装
|
|
21
36
|
|
|
@@ -31,8 +46,11 @@ dsh plugin --profile web add relay-dsh-plugin-manager@latest
|
|
|
31
46
|
dsh web
|
|
32
47
|
```
|
|
33
48
|
|
|
34
|
-
|
|
35
|
-
|
|
49
|
+
如果 `PATH` 中没有 `dsh`,请在两条命令中将它替换为
|
|
50
|
+
`pnpm dlx @deepseek-ai/dsh@0.1.1-rc.2`。
|
|
51
|
+
|
|
52
|
+
安装后,**设置 > 插件** 会默认打开 **推荐插件** 标签页,在这里介绍推荐的
|
|
53
|
+
对话后端插件,并附一份简短帮助。实际的插件管理仍在 Chat 对话中完成。
|
|
36
54
|
|
|
37
55
|
### KeySync 已内置安装
|
|
38
56
|
|
|
@@ -68,16 +86,6 @@ Chat 对话中完成。
|
|
|
68
86
|
一次确认后依次安装。修改完成但仍需重启时,状态会明确区分“需要另行重启”和
|
|
69
87
|
“等待人工重启”。
|
|
70
88
|
|
|
71
|
-
## 真实安装演示
|
|
72
|
-
|
|
73
|
-
[](https://github.com/yangbobo2021/Relay/blob/codex/relay-foundation/docs/media/dsh-plugin-manager-codex-install-demo.mp4?raw=1)
|
|
74
|
-
|
|
75
|
-
查看 [38 秒真实 DSH 运行录像](https://github.com/yangbobo2021/Relay/blob/codex/relay-foundation/docs/media/dsh-plugin-manager-codex-install-demo.mp4?raw=1):
|
|
76
|
-
从搜索、只生成计划、单独确认,到安装完成并显示 `succeeded`。录像基于官方 DSH
|
|
77
|
-
提交 [`b150a551`](https://github.com/deepseek-ai/deepseek-harness/commit/b150a551b8d465e31e418e1b2eaf5e79bbb7d28e),
|
|
78
|
-
使用 Plugin Manager `0.1.0-rc.2` 和 Codex 插件 `0.1.2`;安装后如需重启,
|
|
79
|
-
DSH 会明确提示。
|
|
80
|
-
|
|
81
89
|
## 与 Relay 的关系
|
|
82
90
|
|
|
83
91
|
本插件在 [Relay](https://github.com/yangbobo2021/Relay) 的 integration 工作区中
|
package/SPEC.md
CHANGED
|
@@ -10,9 +10,12 @@ Relay DSH Plugin Manager is a conversation-first, independently installable
|
|
|
10
10
|
DeepSeek Harness bundle. It discovers and manages DSH profile plugins through
|
|
11
11
|
conversation, without management controls or public management HTTP routes.
|
|
12
12
|
|
|
13
|
-
The package contributes a read-only
|
|
14
|
-
Settings > Plugins. That tab
|
|
15
|
-
|
|
13
|
+
The package contributes a read-only recommended-plugins tab under
|
|
14
|
+
Settings > Plugins. That tab gives each recommended plugin one self-contained
|
|
15
|
+
card headed by its npm package name, carrying its purpose, prerequisite, the
|
|
16
|
+
complete Chat message that installs it, and the check that confirms it worked.
|
|
17
|
+
It then points at Chat for installing, reviewing, or removing any other plugin;
|
|
18
|
+
it does not call the Host or mutate plugin state.
|
|
16
19
|
|
|
17
20
|
The user may enter `/plugins <request>` or describe the same request in ordinary
|
|
18
21
|
conversation. Both paths use the same model-facing tools and Host management
|
|
@@ -42,7 +45,7 @@ service.
|
|
|
42
45
|
| PM-018 | Reject unsafe source tokens, flags, whitespace/control characters, shell metacharacters, unsupported URL hosts, ambiguous package names, and mutable execution sources. Build scripts remain governed by pnpm/DSH and are never silently authorized. |
|
|
43
46
|
| PM-019 | Expose no public plugin-management HTTP routes and impose no client-address, Origin, CORS, or loopback policy. The callable surface is the in-process DSH command/tool plane. |
|
|
44
47
|
| PM-020 | Remain independently installable. Do not import Relay parent implementation code or KeySync implementation code. Runtime interactions use DSH/Cordis public services and the official CLI. |
|
|
45
|
-
| PM-021 | Contribute one localized, read-only `marketplace` tab to `settings.plugins.tab
|
|
48
|
+
| PM-021 | Contribute one localized, read-only `marketplace` tab to `settings.plugins.tab`, sorted ahead of the Host's own tabs so Settings > Plugins opens on it. Each recommended plugin owns one self-contained card: its exact npm package name as the heading, its purpose, its prerequisite, one complete Chat message that installs it by that exact package name, and its post-install check. Tab-level copy claims nothing about a specific plugin and points at Chat for installing, reviewing, or removing any other plugin. It exposes no management control, Remote call, or additional Host service. |
|
|
46
49
|
| PM-022 | Preserve required manifest peer-dependency metadata during source inspection while respecting `peerDependenciesMeta.optional`. A multi-install plan reports required peers absent from both the current profile and the requested set, deduplicated with their ranges, dependents, and suggested npm source. Planning never silently adds an unrequested companion plugin. |
|
|
47
50
|
| PM-023 | `plugin_manage confirm` owns its DSH question: it validates the token, expiry, and exact Session before asking; supplies a stable plan-specific id, visible plan detail, exact approve/decline options, and `plan-review` intent; and executes in that same tool call only for the exact single approve answer. Declines, malformed or unrelated answers, provider failure/cancellation, and cross-session attempts do not execute or consume a still-valid plan. Generic model-authored question results are never mutation authority. |
|
|
48
51
|
| PM-024 | GitHub owner discovery recognizes `owner:<name>`, owner-only GitHub identities, `<name> DSH plugins`, and conservative bare identifiers containing digits. It sends a typed owner intent to providers, uses GitHub's exact owner qualifier, case-insensitively verifies returned ownership, and ranks verified owner matches first. Owner-only `inspect` fails with an actionable error directing callers to search. Every emitted repository identity is accepted by `inspect`; every recommended immutable source is accepted by `plan`. |
|
|
@@ -93,7 +96,7 @@ one provider before deterministic cross-provider ordering.
|
|
|
93
96
|
## Explicit Non-Goals
|
|
94
97
|
|
|
95
98
|
- Settings controls, dashboard, or any other second management workflow. The
|
|
96
|
-
read-only
|
|
99
|
+
read-only recommended-plugins help tab is explicitly in scope.
|
|
97
100
|
- Public management REST/HTTP endpoints.
|
|
98
101
|
- Provider-defined installers, shell commands, or arbitrary pnpm arguments.
|
|
99
102
|
- Arbitrary tarball, filesystem, SSH Git, or non-GitHub Git installation in the
|
package/docs/acceptance.md
CHANGED
|
@@ -28,7 +28,7 @@ This matrix is the release contract. Tests name the relevant `PM-*` ids.
|
|
|
28
28
|
| A-020 packed tarball installs through official DSH CLI into a clean profile and contributes both Host rows without modifying DSH | PM-020 | local checkout E2E + CI against the locked published DSH runtime fixture |
|
|
29
29
|
| A-021 optional live-network acceptance discovers the real Codex plugin through npm/GitHub, installs npm and immutable GitHub sources in isolated DSH homes, boots the npm-installed Web profile, exercises enable/disable/update, and removes both | PM-003-PM-017 | `npm run acceptance:live:codex` |
|
|
30
30
|
| A-022 a real DSH Web Session exposes both tools, serves slash-command and natural-language search, rejects same-turn confirmation, executes later confirmation, and observes Loader HMR without restarting DSH | PM-001, PM-002, PM-009, PM-012, PM-014 | release-candidate walkthrough with real Codex backend |
|
|
31
|
-
| A-023 Settings > Plugins
|
|
31
|
+
| A-023 Settings > Plugins opens on one localized recommended-plugins tab that gives each recommended plugin a self-contained card headed by its exact npm package name, carrying its purpose, prerequisite, a complete install message repeating that package name, and its post-install check, with tab-level copy claiming nothing about a specific plugin; the page has no action control, Host call, or Remote dependency | PM-019, PM-021 | client registration + server-rendered component unit tests + packed client-bundle E2E |
|
|
32
32
|
| A-024 three immutable plugin sources produce one deeply immutable plan and token, execute serially after one confirmation, expose per-child outcomes, stop/skip after failure, cancel without starting later children, and reject duplicates, invalid bounds, or aggregate stale state before mutation | PM-009, PM-010, PM-015, PM-017, PM-018 | plan/operation unit + conversation tool + fake-CLI manager integration |
|
|
33
33
|
| A-025 multi-install planning deduplicates missing peer dependencies, excludes optional peers and peers already installed or requested, suggests but never silently installs companions, and successful operations terminate as `succeeded`, `succeeded_restart_required`, or `waiting_for_manual_restart` according to activation and restart availability | PM-013, PM-015, PM-016, PM-022 | source/plan unit + manager integration + opt-in real Codex/Files/Terminal DSH CLI lifecycle |
|
|
34
34
|
| A-026 a valid Session-bound plan opens one plugin-owned DSH `plan-review` question; no mutation starts before an answer, and the exact single approve answer executes once without a typed chat message | PM-009, PM-023 | conversation state-machine unit + real UserQuestionService integration |
|
package/docs/technical-design.md
CHANGED
|
@@ -9,7 +9,7 @@ The bundle mounts two Host entries:
|
|
|
9
9
|
model tools, and `/plugins`.
|
|
10
10
|
|
|
11
11
|
It also ships one browser client entry that registers a static, read-only
|
|
12
|
-
|
|
12
|
+
recommended-plugins help tab in `settings.plugins.tab`. The client has no Remote
|
|
13
13
|
dependency and exposes no management action. There is no management HTTP route.
|
|
14
14
|
|
|
15
15
|
## Request Flow
|
|
@@ -31,8 +31,10 @@ natural language --------------------------+
|
|
|
31
31
|
|
|
|
32
32
|
restart fallback
|
|
33
33
|
|
|
34
|
-
Settings > Plugins >
|
|
34
|
+
Settings > Plugins > Recommended plugins (first tab, opened by default)
|
|
35
35
|
|
|
|
36
|
+
+-- one card per recommended plugin: package name + purpose
|
|
37
|
+
| + requires / install message / check
|
|
36
38
|
+-- localized Chat examples only (no Host call or mutation control)
|
|
37
39
|
```
|
|
38
40
|
|
package/lib/client.js
CHANGED
|
@@ -10,174 +10,251 @@ window.__ModuleLoader__.load({
|
|
|
10
10
|
section: {
|
|
11
11
|
display: "flex",
|
|
12
12
|
flexDirection: "column",
|
|
13
|
-
gap:
|
|
13
|
+
gap: 14,
|
|
14
14
|
width: "100%",
|
|
15
|
-
maxWidth:
|
|
15
|
+
maxWidth: 640,
|
|
16
16
|
color: "var(--dsw-alias-label-primary)"
|
|
17
17
|
},
|
|
18
|
-
|
|
18
|
+
plugins: {
|
|
19
19
|
display: "flex",
|
|
20
20
|
flexDirection: "column",
|
|
21
|
-
gap:
|
|
21
|
+
gap: 12
|
|
22
22
|
},
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
plugin: {
|
|
24
|
+
display: "flex",
|
|
25
|
+
flexDirection: "column",
|
|
26
|
+
gap: 14,
|
|
27
|
+
border: "1px solid var(--dsw-alias-border-l2)",
|
|
28
|
+
borderRadius: 8,
|
|
29
|
+
padding: "16px 18px"
|
|
30
|
+
},
|
|
31
|
+
pluginHeader: {
|
|
32
|
+
display: "flex",
|
|
33
|
+
flexDirection: "column",
|
|
34
|
+
gap: 4
|
|
28
35
|
},
|
|
29
|
-
|
|
30
|
-
maxWidth: 620,
|
|
36
|
+
packageName: {
|
|
31
37
|
margin: 0,
|
|
32
|
-
|
|
33
|
-
fontSize:
|
|
34
|
-
lineHeight: "22px"
|
|
38
|
+
fontFamily: "ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, monospace",
|
|
39
|
+
fontSize: 15,
|
|
40
|
+
lineHeight: "22px",
|
|
41
|
+
fontWeight: 600
|
|
35
42
|
},
|
|
36
|
-
|
|
43
|
+
purpose: {
|
|
37
44
|
margin: 0,
|
|
38
|
-
borderLeft: "3px solid var(--dsw-alias-state-business-primary)",
|
|
39
|
-
borderRadius: 6,
|
|
40
|
-
padding: "10px 12px",
|
|
41
|
-
background: "var(--dsw-alias-bg-layer-1)",
|
|
42
45
|
color: "var(--dsw-alias-label-secondary)",
|
|
43
46
|
fontSize: 13,
|
|
44
47
|
lineHeight: "20px"
|
|
45
48
|
},
|
|
46
|
-
|
|
49
|
+
facts: {
|
|
47
50
|
display: "flex",
|
|
48
51
|
flexDirection: "column",
|
|
49
|
-
gap:
|
|
50
|
-
},
|
|
51
|
-
examplesTitle: {
|
|
52
|
-
margin: 0,
|
|
53
|
-
fontSize: 13,
|
|
54
|
-
lineHeight: "20px",
|
|
55
|
-
fontWeight: 600
|
|
56
|
-
},
|
|
57
|
-
list: {
|
|
52
|
+
gap: 6,
|
|
58
53
|
margin: 0,
|
|
59
|
-
borderTop: "1px solid var(--dsw-alias-border-l2)",
|
|
60
54
|
padding: 0,
|
|
61
55
|
listStyle: "none"
|
|
62
56
|
},
|
|
63
|
-
|
|
57
|
+
factRow: {
|
|
64
58
|
display: "flex",
|
|
65
59
|
flexWrap: "wrap",
|
|
66
60
|
alignItems: "baseline",
|
|
67
|
-
columnGap:
|
|
68
|
-
rowGap:
|
|
69
|
-
borderBottom: "1px solid var(--dsw-alias-border-l2)",
|
|
70
|
-
padding: "12px 2px"
|
|
61
|
+
columnGap: 12,
|
|
62
|
+
rowGap: 2
|
|
71
63
|
},
|
|
72
64
|
label: {
|
|
73
|
-
flex: "0 0
|
|
65
|
+
flex: "0 0 52px",
|
|
74
66
|
color: "var(--dsw-alias-label-tertiary)",
|
|
75
67
|
fontSize: 12,
|
|
76
|
-
lineHeight: "
|
|
68
|
+
lineHeight: "20px"
|
|
69
|
+
},
|
|
70
|
+
value: {
|
|
71
|
+
flex: "1 1 240px",
|
|
72
|
+
minWidth: 0,
|
|
73
|
+
overflowWrap: "anywhere",
|
|
74
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
75
|
+
fontSize: 13,
|
|
76
|
+
lineHeight: "20px"
|
|
77
77
|
},
|
|
78
|
-
|
|
79
|
-
flex: "1 1
|
|
78
|
+
installValue: {
|
|
79
|
+
flex: "1 1 240px",
|
|
80
80
|
minWidth: 0,
|
|
81
81
|
overflowWrap: "anywhere",
|
|
82
82
|
color: "var(--dsw-alias-label-primary)",
|
|
83
|
-
fontSize:
|
|
84
|
-
lineHeight: "
|
|
83
|
+
fontSize: 13,
|
|
84
|
+
lineHeight: "20px"
|
|
85
85
|
},
|
|
86
|
-
|
|
86
|
+
aside: {
|
|
87
|
+
display: "flex",
|
|
88
|
+
alignItems: "flex-start",
|
|
89
|
+
gap: 8,
|
|
87
90
|
margin: 0,
|
|
91
|
+
borderTop: "1px solid var(--dsw-alias-border-l2)",
|
|
92
|
+
paddingTop: 14,
|
|
88
93
|
color: "var(--dsw-alias-label-tertiary)",
|
|
89
|
-
fontSize:
|
|
90
|
-
lineHeight: "
|
|
94
|
+
fontSize: 13,
|
|
95
|
+
lineHeight: "20px"
|
|
96
|
+
},
|
|
97
|
+
asideIcon: {
|
|
98
|
+
flex: "0 0 auto",
|
|
99
|
+
marginTop: 3
|
|
100
|
+
},
|
|
101
|
+
asideLead: {
|
|
102
|
+
color: "var(--dsw-alias-label-primary)",
|
|
103
|
+
fontWeight: 600
|
|
91
104
|
}
|
|
92
105
|
};
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
106
|
+
/** The recommended plugins, in the order the tab presents them. */
|
|
107
|
+
const recommendedKeys = [{
|
|
108
|
+
package: "claudePackage",
|
|
109
|
+
purpose: "claudePurpose",
|
|
110
|
+
requires: "claudeRequires",
|
|
111
|
+
install: "claudeInstall",
|
|
112
|
+
verify: "claudeVerify"
|
|
113
|
+
}, {
|
|
114
|
+
package: "codexPackage",
|
|
115
|
+
purpose: "codexPurpose",
|
|
116
|
+
requires: "codexRequires",
|
|
117
|
+
install: "codexInstall",
|
|
118
|
+
verify: "codexVerify"
|
|
119
|
+
}];
|
|
120
|
+
/** Dependency-free info glyph marking the tab's one aside. */
|
|
121
|
+
function InfoIcon() {
|
|
122
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
123
|
+
style: styles.asideIcon,
|
|
124
|
+
width: "14",
|
|
125
|
+
height: "14",
|
|
126
|
+
viewBox: "0 0 16 16",
|
|
127
|
+
fill: "none",
|
|
128
|
+
stroke: "currentColor",
|
|
129
|
+
strokeWidth: "1.4",
|
|
130
|
+
"aria-hidden": "true",
|
|
131
|
+
focusable: "false",
|
|
104
132
|
children: [
|
|
105
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
children: t("title")
|
|
110
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
111
|
-
style: styles.intro,
|
|
112
|
-
children: t("intro")
|
|
113
|
-
})]
|
|
114
|
-
}),
|
|
115
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
116
|
-
style: styles.notice,
|
|
117
|
-
children: t("confirmation")
|
|
133
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
|
|
134
|
+
cx: "8",
|
|
135
|
+
cy: "8",
|
|
136
|
+
r: "6.5"
|
|
118
137
|
}),
|
|
119
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
style: styles.examplesTitle,
|
|
123
|
-
children: t("examples")
|
|
124
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
125
|
-
style: styles.list,
|
|
126
|
-
children: exampleKeys.map(([label, prompt]) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
|
|
127
|
-
style: styles.row,
|
|
128
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
129
|
-
style: styles.label,
|
|
130
|
-
children: t(label)
|
|
131
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
132
|
-
style: styles.prompt,
|
|
133
|
-
"data-chat-prompt": true,
|
|
134
|
-
children: t(prompt)
|
|
135
|
-
})]
|
|
136
|
-
}, prompt))
|
|
137
|
-
})]
|
|
138
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
139
|
+
d: "M8 7.2v4",
|
|
140
|
+
strokeLinecap: "round"
|
|
138
141
|
}),
|
|
139
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
140
|
-
|
|
141
|
-
|
|
142
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
143
|
+
d: "M8 4.9v.1",
|
|
144
|
+
strokeLinecap: "round"
|
|
142
145
|
})
|
|
143
146
|
]
|
|
144
147
|
});
|
|
145
148
|
}
|
|
149
|
+
/** Render one self-contained card per recommended plugin, then one aside. */
|
|
150
|
+
function MarketplaceSettingsTab({ t }) {
|
|
151
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
152
|
+
style: styles.section,
|
|
153
|
+
"data-plugin-marketplace-help": true,
|
|
154
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
155
|
+
style: styles.plugins,
|
|
156
|
+
children: recommendedKeys.map((plugin) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
|
|
157
|
+
style: styles.plugin,
|
|
158
|
+
"data-recommended-plugin": true,
|
|
159
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
|
|
160
|
+
style: styles.pluginHeader,
|
|
161
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", {
|
|
162
|
+
style: styles.packageName,
|
|
163
|
+
"data-plugin-package": true,
|
|
164
|
+
children: t(plugin.package)
|
|
165
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
166
|
+
style: styles.purpose,
|
|
167
|
+
children: t(plugin.purpose)
|
|
168
|
+
})]
|
|
169
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("ul", {
|
|
170
|
+
style: styles.facts,
|
|
171
|
+
children: [
|
|
172
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
|
|
173
|
+
style: styles.factRow,
|
|
174
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
175
|
+
style: styles.label,
|
|
176
|
+
children: t("requiresLabel")
|
|
177
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
178
|
+
style: styles.value,
|
|
179
|
+
children: t(plugin.requires)
|
|
180
|
+
})]
|
|
181
|
+
}),
|
|
182
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
|
|
183
|
+
style: styles.factRow,
|
|
184
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
185
|
+
style: styles.label,
|
|
186
|
+
children: t("installLabel")
|
|
187
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
188
|
+
style: styles.installValue,
|
|
189
|
+
"data-chat-prompt": true,
|
|
190
|
+
children: t(plugin.install)
|
|
191
|
+
})]
|
|
192
|
+
}),
|
|
193
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
|
|
194
|
+
style: styles.factRow,
|
|
195
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
196
|
+
style: styles.label,
|
|
197
|
+
children: t("verifyLabel")
|
|
198
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
199
|
+
style: styles.value,
|
|
200
|
+
children: t(plugin.verify)
|
|
201
|
+
})]
|
|
202
|
+
})
|
|
203
|
+
]
|
|
204
|
+
})]
|
|
205
|
+
}, plugin.package))
|
|
206
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
207
|
+
style: styles.aside,
|
|
208
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(InfoIcon, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
209
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", {
|
|
210
|
+
style: styles.asideLead,
|
|
211
|
+
children: t("otherLead")
|
|
212
|
+
}),
|
|
213
|
+
" ",
|
|
214
|
+
t("other")
|
|
215
|
+
] })]
|
|
216
|
+
})]
|
|
217
|
+
});
|
|
218
|
+
}
|
|
146
219
|
//#endregion
|
|
147
220
|
//#region src/client/locales.ts
|
|
148
221
|
/** Simplified Chinese dictionary and key source of truth. */
|
|
149
222
|
const zh = {
|
|
150
|
-
tab: "
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
223
|
+
tab: "推荐插件",
|
|
224
|
+
requiresLabel: "需要",
|
|
225
|
+
installLabel: "安装",
|
|
226
|
+
verifyLabel: "装好后",
|
|
227
|
+
claudePackage: "relay-dsh-plugin-claude",
|
|
228
|
+
claudePurpose: "在 DSH 里使用 Claude Code",
|
|
229
|
+
claudeRequires: "本机的 Claude Code 已能正常调用",
|
|
230
|
+
claudeInstall: "在聊天里发送「安装 npm 包 relay-dsh-plugin-claude」",
|
|
231
|
+
claudeVerify: "新建会话,在模式菜单里选 Claude Code",
|
|
232
|
+
codexPackage: "relay-dsh-plugin-codex",
|
|
233
|
+
codexPurpose: "在 DSH 里使用 Codex",
|
|
234
|
+
codexRequires: "本机的 Codex 已能正常调用",
|
|
235
|
+
codexInstall: "在聊天里发送「安装 npm 包 relay-dsh-plugin-codex」",
|
|
236
|
+
codexVerify: "新建会话,在模式菜单里选 Codex",
|
|
237
|
+
otherLead: "想安装/查看/卸载其他插件?",
|
|
238
|
+
other: "直接在聊天里说,比如「找一个能发送系统通知的插件」「卸载 relay-dsh-plugin-codex」。"
|
|
164
239
|
};
|
|
165
|
-
/** English dictionary
|
|
240
|
+
/** English dictionary, mirroring every Simplified Chinese key. */
|
|
166
241
|
const en = {
|
|
167
|
-
tab: "
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
242
|
+
tab: "Recommended plugins",
|
|
243
|
+
requiresLabel: "Requires",
|
|
244
|
+
installLabel: "Install",
|
|
245
|
+
verifyLabel: "After install",
|
|
246
|
+
claudePackage: "relay-dsh-plugin-claude",
|
|
247
|
+
claudePurpose: "Use Claude Code inside DSH",
|
|
248
|
+
claudeRequires: "Claude Code already works on this machine",
|
|
249
|
+
claudeInstall: "Send “install the npm package relay-dsh-plugin-claude” in chat",
|
|
250
|
+
claudeVerify: "Start a session and pick Claude Code from the mode menu",
|
|
251
|
+
codexPackage: "relay-dsh-plugin-codex",
|
|
252
|
+
codexPurpose: "Use Codex inside DSH",
|
|
253
|
+
codexRequires: "Codex already works on this machine",
|
|
254
|
+
codexInstall: "Send “install the npm package relay-dsh-plugin-codex” in chat",
|
|
255
|
+
codexVerify: "Start a session and pick Codex from the mode menu",
|
|
256
|
+
otherLead: "Want to install, review, or remove another plugin?",
|
|
257
|
+
other: "Just say so in chat — “find a plugin that sends desktop notifications”, “remove relay-dsh-plugin-codex”."
|
|
181
258
|
};
|
|
182
259
|
//#endregion
|
|
183
260
|
//#region src/client/index.tsx
|
|
@@ -195,7 +272,7 @@ window.__ModuleLoader__.load({
|
|
|
195
272
|
ctx.slots.inject("settings.plugins.tab", () => ctx.slots.register({
|
|
196
273
|
name: "settings.plugins.tab",
|
|
197
274
|
id: "marketplace",
|
|
198
|
-
order:
|
|
275
|
+
order: -10,
|
|
199
276
|
label: () => t("tab"),
|
|
200
277
|
locale: NS
|
|
201
278
|
}, MarketplaceSettingsTab));
|
package/lib/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":[],"sources":["../src/client/MarketplaceSettingsTab.tsx","../src/client/locales.ts","../src/client/index.tsx"],"sourcesContent":["import type { CSSProperties, ReactNode } from 'react'\nimport type { PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { MarketplaceLocaleKey } from './locales.ts'\n\n/** Props assembled by the Settings slot renderer. */\nexport type MarketplaceSettingsTabProps =\n PropsRuntime<'settings.plugins.tab'>\n & PropsLocale<'settings.pluginMarketplace'>\n\nconst styles = {\n section: {\n display: 'flex',\n flexDirection: 'column',\n gap: 20,\n width: '100%',\n maxWidth: 720,\n color: 'var(--dsw-alias-label-primary)',\n },\n header: {\n display: 'flex',\n flexDirection: 'column',\n gap: 6,\n },\n title: {\n margin: 0,\n fontSize: 18,\n lineHeight: '26px',\n fontWeight: 600,\n },\n intro: {\n maxWidth: 620,\n margin: 0,\n color: 'var(--dsw-alias-label-secondary)',\n fontSize: 14,\n lineHeight: '22px',\n },\n notice: {\n margin: 0,\n borderLeft: '3px solid var(--dsw-alias-state-business-primary)',\n borderRadius: 6,\n padding: '10px 12px',\n background: 'var(--dsw-alias-bg-layer-1)',\n color: 'var(--dsw-alias-label-secondary)',\n fontSize: 13,\n lineHeight: '20px',\n },\n examples: {\n display: 'flex',\n flexDirection: 'column',\n gap: 8,\n },\n examplesTitle: {\n margin: 0,\n fontSize: 13,\n lineHeight: '20px',\n fontWeight: 600,\n },\n list: {\n margin: 0,\n borderTop: '1px solid var(--dsw-alias-border-l2)',\n padding: 0,\n listStyle: 'none',\n },\n row: {\n display: 'flex',\n flexWrap: 'wrap',\n alignItems: 'baseline',\n columnGap: 16,\n rowGap: 4,\n borderBottom: '1px solid var(--dsw-alias-border-l2)',\n padding: '12px 2px',\n },\n label: {\n flex: '0 0 92px',\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: 12,\n lineHeight: '18px',\n },\n prompt: {\n flex: '1 1 220px',\n minWidth: 0,\n overflowWrap: 'anywhere',\n color: 'var(--dsw-alias-label-primary)',\n fontSize: 14,\n lineHeight: '21px',\n },\n hint: {\n margin: 0,\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: 12,\n lineHeight: '19px',\n },\n} satisfies Record<string, CSSProperties>\n\nconst exampleKeys = [\n ['searchLabel', 'searchPrompt'],\n ['installLabel', 'installPrompt'],\n ['removeLabel', 'removePrompt'],\n ['listLabel', 'listPrompt'],\n] as const satisfies readonly (readonly [MarketplaceLocaleKey, MarketplaceLocaleKey])[]\n\n/** Render concise, read-only guidance for conversation-based plugin management. */\nexport function MarketplaceSettingsTab({ t }: MarketplaceSettingsTabProps): ReactNode {\n return (\n <section style={styles.section} data-plugin-marketplace-help>\n <header style={styles.header}>\n <h3 style={styles.title}>{t('title')}</h3>\n <p style={styles.intro}>{t('intro')}</p>\n </header>\n <p style={styles.notice}>{t('confirmation')}</p>\n <div style={styles.examples}>\n <h4 style={styles.examplesTitle}>{t('examples')}</h4>\n <ul style={styles.list}>\n {exampleKeys.map(([label, prompt]) => (\n <li style={styles.row} key={prompt}>\n <span style={styles.label}>{t(label)}</span>\n <span style={styles.prompt} data-chat-prompt>{t(prompt)}</span>\n </li>\n ))}\n </ul>\n </div>\n <p style={styles.hint}>{t('commandHint')}</p>\n </section>\n )\n}\n","/** Simplified Chinese dictionary and key source of truth. */\nexport const zh = {\n tab: '插件市场',\n title: '在聊天中管理插件',\n intro: '直接在聊天窗口描述你想做的事。DSH 会帮助你寻找插件,并通过对话完成安装和管理。',\n confirmation: '安装、卸载、启用或停用前,DSH 会先展示操作计划,并等待你的确认。',\n examples: '你可以这样说',\n searchLabel: '寻找插件',\n searchPrompt: '找一个能连接飞书的插件',\n installLabel: '安装插件',\n installPrompt: '安装 relay-dsh-plugin-codex',\n removeLabel: '卸载插件',\n removePrompt: '卸载 relay-dsh-plugin-codex',\n listLabel: '查看插件',\n listPrompt: '列出当前已安装的插件',\n commandHint: '也可以在聊天窗口输入 /plugins,后面跟上同样的请求。',\n} satisfies Record<string, string>\n\n/** Locale key union shared by the tab component and registration. */\nexport type MarketplaceLocaleKey = keyof typeof zh\n\n/** English dictionary checked against the Chinese key set. */\nexport const en = {\n tab: 'Plugin marketplace',\n title: 'Manage plugins in Chat',\n intro: 'Describe what you need in the Chat window. DSH can find plugins and manage them through conversation.',\n confirmation: 'Before installing, removing, enabling, or disabling anything, DSH shows a plan and waits for your confirmation.',\n examples: 'Try asking',\n searchLabel: 'Find a plugin',\n searchPrompt: 'Find a plugin that connects to Lark',\n installLabel: 'Install a plugin',\n installPrompt: 'Install relay-dsh-plugin-codex',\n removeLabel: 'Remove a plugin',\n removePrompt: 'Remove relay-dsh-plugin-codex',\n listLabel: 'View plugins',\n listPrompt: 'List the currently installed plugins',\n commandHint: 'You can also type /plugins in Chat, followed by the same request.',\n} satisfies Record<MarketplaceLocaleKey, string>\n","/** Read-only Plugin Marketplace help registered into Web Settings. */\n\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\nimport type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\nimport { MarketplaceSettingsTab } from './MarketplaceSettingsTab.tsx'\nimport { en, zh, type MarketplaceLocaleKey } from './locales.ts'\n\nexport type { MarketplaceSettingsTabProps } from './MarketplaceSettingsTab.tsx'\nexport type { MarketplaceLocaleKey } from './locales.ts'\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n /** Read-only conversation help for plugin discovery and management. */\n 'settings.pluginMarketplace': MarketplaceLocaleKey\n }\n}\n\n/** Dictionary namespace owned by this plugin. */\nexport const NS = 'settings.pluginMarketplace'\n\n/** The tab needs only the Settings slot ledger and locale service. */\nexport const inject = ['slots', 'locale']\n\n/** Contribute the localized help tab to Settings > Plugins. */\nexport function apply(ctx: ClientContext): void {\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'relay-plugin-manager: marketplace dictionaries')\n const t = ctx.locale.bind(NS)\n\n ctx.slots.inject('settings.plugins.tab', () => ctx.slots.register({\n name: 'settings.plugins.tab',\n id: 'marketplace',\n order: 20,\n label: () => t('tab'),\n locale: NS,\n }, MarketplaceSettingsTab))\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.js","names":[],"sources":["../src/client/MarketplaceSettingsTab.tsx","../src/client/locales.ts","../src/client/index.tsx"],"sourcesContent":["import type { CSSProperties, ReactNode } from 'react'\nimport type { PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { MarketplaceLocaleKey } from './locales.ts'\n\n/** Props assembled by the Settings slot renderer. */\nexport type MarketplaceSettingsTabProps =\n PropsRuntime<'settings.plugins.tab'>\n & PropsLocale<'settings.pluginMarketplace'>\n\nconst MONO = 'ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, monospace'\n\nconst styles = {\n section: {\n display: 'flex',\n flexDirection: 'column',\n gap: 14,\n width: '100%',\n maxWidth: 640,\n color: 'var(--dsw-alias-label-primary)',\n },\n plugins: {\n display: 'flex',\n flexDirection: 'column',\n gap: 12,\n },\n plugin: {\n display: 'flex',\n flexDirection: 'column',\n gap: 14,\n border: '1px solid var(--dsw-alias-border-l2)',\n borderRadius: 8,\n padding: '16px 18px',\n },\n pluginHeader: {\n display: 'flex',\n flexDirection: 'column',\n gap: 4,\n },\n packageName: {\n margin: 0,\n fontFamily: MONO,\n fontSize: 15,\n lineHeight: '22px',\n fontWeight: 600,\n },\n purpose: {\n margin: 0,\n color: 'var(--dsw-alias-label-secondary)',\n fontSize: 13,\n lineHeight: '20px',\n },\n facts: {\n display: 'flex',\n flexDirection: 'column',\n gap: 6,\n margin: 0,\n padding: 0,\n listStyle: 'none',\n },\n factRow: {\n display: 'flex',\n flexWrap: 'wrap',\n alignItems: 'baseline',\n columnGap: 12,\n rowGap: 2,\n },\n label: {\n flex: '0 0 52px',\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: 12,\n lineHeight: '20px',\n },\n value: {\n flex: '1 1 240px',\n minWidth: 0,\n overflowWrap: 'anywhere',\n color: 'var(--dsw-alias-label-secondary)',\n fontSize: 13,\n lineHeight: '20px',\n },\n installValue: {\n flex: '1 1 240px',\n minWidth: 0,\n overflowWrap: 'anywhere',\n color: 'var(--dsw-alias-label-primary)',\n fontSize: 13,\n lineHeight: '20px',\n },\n aside: {\n display: 'flex',\n alignItems: 'flex-start',\n gap: 8,\n margin: 0,\n borderTop: '1px solid var(--dsw-alias-border-l2)',\n paddingTop: 14,\n color: 'var(--dsw-alias-label-tertiary)',\n fontSize: 13,\n lineHeight: '20px',\n },\n asideIcon: {\n flex: '0 0 auto',\n marginTop: 3,\n },\n asideLead: {\n color: 'var(--dsw-alias-label-primary)',\n fontWeight: 600,\n },\n} satisfies Record<string, CSSProperties>\n\n/** The recommended plugins, in the order the tab presents them. */\nconst recommendedKeys = [\n {\n package: 'claudePackage',\n purpose: 'claudePurpose',\n requires: 'claudeRequires',\n install: 'claudeInstall',\n verify: 'claudeVerify',\n },\n {\n package: 'codexPackage',\n purpose: 'codexPurpose',\n requires: 'codexRequires',\n install: 'codexInstall',\n verify: 'codexVerify',\n },\n] as const satisfies readonly Record<'package' | 'purpose' | 'requires' | 'install' | 'verify', MarketplaceLocaleKey>[]\n\n/** Dependency-free info glyph marking the tab's one aside. */\nfunction InfoIcon(): ReactNode {\n return (\n <svg\n style={styles.asideIcon}\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.4\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <circle cx=\"8\" cy=\"8\" r=\"6.5\" />\n <path d=\"M8 7.2v4\" strokeLinecap=\"round\" />\n <path d=\"M8 4.9v.1\" strokeLinecap=\"round\" />\n </svg>\n )\n}\n\n/** Render one self-contained card per recommended plugin, then one aside. */\nexport function MarketplaceSettingsTab({ t }: MarketplaceSettingsTabProps): ReactNode {\n return (\n <section style={styles.section} data-plugin-marketplace-help>\n <div style={styles.plugins}>\n {recommendedKeys.map((plugin) => (\n <article style={styles.plugin} key={plugin.package} data-recommended-plugin>\n <header style={styles.pluginHeader}>\n <h4 style={styles.packageName} data-plugin-package>{t(plugin.package)}</h4>\n <p style={styles.purpose}>{t(plugin.purpose)}</p>\n </header>\n <ul style={styles.facts}>\n <li style={styles.factRow}>\n <span style={styles.label}>{t('requiresLabel')}</span>\n <span style={styles.value}>{t(plugin.requires)}</span>\n </li>\n <li style={styles.factRow}>\n <span style={styles.label}>{t('installLabel')}</span>\n <span style={styles.installValue} data-chat-prompt>{t(plugin.install)}</span>\n </li>\n <li style={styles.factRow}>\n <span style={styles.label}>{t('verifyLabel')}</span>\n <span style={styles.value}>{t(plugin.verify)}</span>\n </li>\n </ul>\n </article>\n ))}\n </div>\n <p style={styles.aside}>\n <InfoIcon />\n <span>\n <strong style={styles.asideLead}>{t('otherLead')}</strong>\n {' '}\n {t('other')}\n </span>\n </p>\n </section>\n )\n}\n","/** Simplified Chinese dictionary and key source of truth. */\nexport const zh = {\n tab: '推荐插件',\n requiresLabel: '需要',\n installLabel: '安装',\n verifyLabel: '装好后',\n claudePackage: 'relay-dsh-plugin-claude',\n claudePurpose: '在 DSH 里使用 Claude Code',\n claudeRequires: '本机的 Claude Code 已能正常调用',\n claudeInstall: '在聊天里发送「安装 npm 包 relay-dsh-plugin-claude」',\n claudeVerify: '新建会话,在模式菜单里选 Claude Code',\n codexPackage: 'relay-dsh-plugin-codex',\n codexPurpose: '在 DSH 里使用 Codex',\n codexRequires: '本机的 Codex 已能正常调用',\n codexInstall: '在聊天里发送「安装 npm 包 relay-dsh-plugin-codex」',\n codexVerify: '新建会话,在模式菜单里选 Codex',\n otherLead: '想安装/查看/卸载其他插件?',\n other: '直接在聊天里说,比如「找一个能发送系统通知的插件」「卸载 relay-dsh-plugin-codex」。',\n} satisfies Record<string, string>\n\nexport type MarketplaceLocaleKey = keyof typeof zh\n\n/** English dictionary, mirroring every Simplified Chinese key. */\nexport const en = {\n tab: 'Recommended plugins',\n requiresLabel: 'Requires',\n installLabel: 'Install',\n verifyLabel: 'After install',\n claudePackage: 'relay-dsh-plugin-claude',\n claudePurpose: 'Use Claude Code inside DSH',\n claudeRequires: 'Claude Code already works on this machine',\n claudeInstall: 'Send “install the npm package relay-dsh-plugin-claude” in chat',\n claudeVerify: 'Start a session and pick Claude Code from the mode menu',\n codexPackage: 'relay-dsh-plugin-codex',\n codexPurpose: 'Use Codex inside DSH',\n codexRequires: 'Codex already works on this machine',\n codexInstall: 'Send “install the npm package relay-dsh-plugin-codex” in chat',\n codexVerify: 'Start a session and pick Codex from the mode menu',\n otherLead: 'Want to install, review, or remove another plugin?',\n other: 'Just say so in chat — “find a plugin that sends desktop notifications”, “remove relay-dsh-plugin-codex”.',\n} satisfies Record<MarketplaceLocaleKey, string>\n","/** Read-only recommended-plugins help registered into Web Settings. */\n\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\nimport type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\nimport { MarketplaceSettingsTab } from './MarketplaceSettingsTab.tsx'\nimport { en, zh, type MarketplaceLocaleKey } from './locales.ts'\n\nexport type { MarketplaceSettingsTabProps } from './MarketplaceSettingsTab.tsx'\nexport type { MarketplaceLocaleKey } from './locales.ts'\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n /** Read-only conversation help for plugin discovery and management. */\n 'settings.pluginMarketplace': MarketplaceLocaleKey\n }\n}\n\n/** Dictionary namespace owned by this plugin. */\nexport const NS = 'settings.pluginMarketplace'\n\n/** The tab needs only the Settings slot ledger and locale service. */\nexport const inject = ['slots', 'locale']\n\n/** Contribute the localized help tab to Settings > Plugins. */\nexport function apply(ctx: ClientContext): void {\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'relay-plugin-manager: marketplace dictionaries')\n const t = ctx.locale.bind(NS)\n\n ctx.slots.inject('settings.plugins.tab', () => ctx.slots.register({\n name: 'settings.plugins.tab',\n id: 'marketplace',\n order: -10,\n label: () => t('tab'),\n locale: NS,\n }, MarketplaceSettingsTab))\n}\n"],"mappings":"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"}
|