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 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
- # Plugin Manager for DeepSeek Harness
1
+ # Manage DeepSeek Harness Plugins from Chat
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/relay-dsh-plugin-manager?label=npm)](https://www.npmjs.com/package/relay-dsh-plugin-manager)
4
4
  [![CI](https://github.com/yangbobo2021/relay-dsh-plugin-manager/actions/workflows/ci.yml/badge.svg)](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
- `relay-dsh-plugin-manager` lets you discover and manage DSH plugins directly
17
- from a DeepSeek Harness Chat conversation. Ask for the capability you need, or
18
- ask DSH to install, update, enable, disable, or remove a plugin. DSH shows a plan
19
- and waits for confirmation before changing your Profile.
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
+ [![Plugin Manager installs relay-dsh-plugin-codex successfully in DSH](https://raw.githubusercontent.com/yangbobo2021/Relay/codex/relay-foundation/docs/media/dsh-plugin-manager-codex-install-success.png)](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
- The plugin appears under **Settings > Plugins > Plugin marketplace**. This page
37
- is a short help view; plugin management itself happens in Chat.
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
- [![Plugin Manager installs relay-dsh-plugin-codex successfully in DSH](https://raw.githubusercontent.com/yangbobo2021/Relay/codex/relay-foundation/docs/media/dsh-plugin-manager-codex-install-success.png)](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
  [![npm 版本](https://img.shields.io/npm/v/relay-dsh-plugin-manager?label=npm)](https://www.npmjs.com/package/relay-dsh-plugin-manager)
4
4
  [![CI](https://github.com/yangbobo2021/relay-dsh-plugin-manager/actions/workflows/ci.yml/badge.svg)](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
- `relay-dsh-plugin-manager` 让你直接在 DeepSeek Harness 的 Chat 对话中寻找和
17
- 管理 DSH 插件。你可以描述需要的能力,也可以让 DSH 安装、更新、启用、停用
18
- 或卸载插件。修改 Profile 前,DSH 会先展示操作计划并等待确认。
16
+ **只需描述需要的能力,就能查找和管理 DSH 插件;不必离开对话,也不必手工
17
+ 编辑 Profile 文件。**
18
+
19
+ `relay-dsh-plugin-manager` 让 DeepSeek Harness Chat 可以查找、安装、更新、
20
+ 启用、停用和卸载插件。搜索和查看只读;任何变更执行前,DSH 都会先展示计划,
21
+ 并等待单独确认。
22
+
23
+ [![插件管理器在 DSH 中成功安装 relay-dsh-plugin-codex](https://raw.githubusercontent.com/yangbobo2021/Relay/codex/relay-foundation/docs/media/dsh-plugin-manager-codex-install-success.png)](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
- Chat 对话中完成。
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
- [![插件管理器在 DSH 中成功安装 relay-dsh-plugin-codex](https://raw.githubusercontent.com/yangbobo2021/Relay/codex/relay-foundation/docs/media/dsh-plugin-manager-codex-install-success.png)](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 Plugin Marketplace help tab under
14
- Settings > Plugins. That tab explains how to search, install, remove, and list
15
- plugins from Chat; it does not call the Host or mutate plugin state.
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`. It briefly explains conversation-based discovery and lifecycle management, includes representative search/install/remove/list prompts, and states that mutations wait for confirmation. It exposes no management control, Remote call, or additional Host service. |
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 Plugin Marketplace help tab is explicitly in scope.
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
@@ -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 contains one localized Plugin Marketplace tab with search/install/remove/list Chat examples and confirmation guidance; 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 |
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 |
@@ -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
- Plugin Marketplace help tab in `settings.plugins.tab`. The client has no Remote
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 > Plugin Marketplace
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: 20,
13
+ gap: 14,
14
14
  width: "100%",
15
- maxWidth: 720,
15
+ maxWidth: 640,
16
16
  color: "var(--dsw-alias-label-primary)"
17
17
  },
18
- header: {
18
+ plugins: {
19
19
  display: "flex",
20
20
  flexDirection: "column",
21
- gap: 6
21
+ gap: 12
22
22
  },
23
- title: {
24
- margin: 0,
25
- fontSize: 18,
26
- lineHeight: "26px",
27
- fontWeight: 600
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
- intro: {
30
- maxWidth: 620,
36
+ packageName: {
31
37
  margin: 0,
32
- color: "var(--dsw-alias-label-secondary)",
33
- fontSize: 14,
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
- notice: {
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
- examples: {
49
+ facts: {
47
50
  display: "flex",
48
51
  flexDirection: "column",
49
- gap: 8
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
- row: {
57
+ factRow: {
64
58
  display: "flex",
65
59
  flexWrap: "wrap",
66
60
  alignItems: "baseline",
67
- columnGap: 16,
68
- rowGap: 4,
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 92px",
65
+ flex: "0 0 52px",
74
66
  color: "var(--dsw-alias-label-tertiary)",
75
67
  fontSize: 12,
76
- lineHeight: "18px"
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
- prompt: {
79
- flex: "1 1 220px",
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: 14,
84
- lineHeight: "21px"
83
+ fontSize: 13,
84
+ lineHeight: "20px"
85
85
  },
86
- hint: {
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: 12,
90
- lineHeight: "19px"
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
- const exampleKeys = [
94
- ["searchLabel", "searchPrompt"],
95
- ["installLabel", "installPrompt"],
96
- ["removeLabel", "removePrompt"],
97
- ["listLabel", "listPrompt"]
98
- ];
99
- /** Render concise, read-only guidance for conversation-based plugin management. */
100
- function MarketplaceSettingsTab({ t }) {
101
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
102
- style: styles.section,
103
- "data-plugin-marketplace-help": true,
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.jsxs)("header", {
106
- style: styles.header,
107
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
108
- style: styles.title,
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.jsxs)("div", {
120
- style: styles.examples,
121
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", {
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)("p", {
140
- style: styles.hint,
141
- children: t("commandHint")
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
- title: "在聊天中管理插件",
152
- intro: "直接在聊天窗口描述你想做的事。DSH 会帮助你寻找插件,并通过对话完成安装和管理。",
153
- confirmation: "安装、卸载、启用或停用前,DSH 会先展示操作计划,并等待你的确认。",
154
- examples: "你可以这样说",
155
- searchLabel: "寻找插件",
156
- searchPrompt: "找一个能连接飞书的插件",
157
- installLabel: "安装插件",
158
- installPrompt: "安装 relay-dsh-plugin-codex",
159
- removeLabel: "卸载插件",
160
- removePrompt: "卸载 relay-dsh-plugin-codex",
161
- listLabel: "查看插件",
162
- listPrompt: "列出当前已安装的插件",
163
- commandHint: "也可以在聊天窗口输入 /plugins,后面跟上同样的请求。"
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 checked against the Chinese key set. */
240
+ /** English dictionary, mirroring every Simplified Chinese key. */
166
241
  const en = {
167
- tab: "Plugin marketplace",
168
- title: "Manage plugins in Chat",
169
- intro: "Describe what you need in the Chat window. DSH can find plugins and manage them through conversation.",
170
- confirmation: "Before installing, removing, enabling, or disabling anything, DSH shows a plan and waits for your confirmation.",
171
- examples: "Try asking",
172
- searchLabel: "Find a plugin",
173
- searchPrompt: "Find a plugin that connects to Lark",
174
- installLabel: "Install a plugin",
175
- installPrompt: "Install relay-dsh-plugin-codex",
176
- removeLabel: "Remove a plugin",
177
- removePrompt: "Remove relay-dsh-plugin-codex",
178
- listLabel: "View plugins",
179
- listPrompt: "List the currently installed plugins",
180
- commandHint: "You can also type /plugins in Chat, followed by the same request."
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: 20,
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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "relay-dsh-plugin-manager",
3
- "version": "0.1.0-rc.4",
3
+ "version": "0.1.0",
4
4
  "description": "Conversation-first plugin discovery and lifecycle management for DeepSeek Harness.",
5
5
  "keywords": [
6
6
  "deepseek-harness",