dsh-preview-market 0.1.0 → 0.1.1
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 +6 -0
- package/README.md +19 -1
- package/VERIFY.md +40 -5
- package/lib/client.js +90 -9
- package/package.json +5 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.1
|
|
4
|
+
|
|
5
|
+
- Enable/disable installed preview plugins from the market when dsh-market is present (`/dsh-market/toggle`), with the current state read from `/dsh-market/installed`.
|
|
6
|
+
- Add a "Configure" entry per installed card that points to the child plugin's Settings → Plugins page.
|
|
7
|
+
- Without dsh-market, the toggle is disabled and the card explains where to manage it.
|
|
8
|
+
|
|
3
9
|
## 0.1.0
|
|
4
10
|
|
|
5
11
|
- New vertical preview market plugin: catalog, installed inventory, Settings → Plugins tab.
|
package/README.md
CHANGED
|
@@ -44,8 +44,26 @@ Settings → Plugins → Preview market (namespace `preview-market`):
|
|
|
44
44
|
node --test test/*.test.js
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
+
Settings-tab end-to-end (requires a running host with the plugin installed):
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
node scripts/e2e-settings.mjs --base http://127.0.0.1:<port> --token <token>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Fallback install/copy check (requires a profile where one catalog entry is not installed):
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
node scripts/e2e-fallback.mjs --base http://127.0.0.1:<port> --token <token>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Toggle/configure check (requires dsh-market and an installed STL preview):
|
|
60
|
+
|
|
61
|
+
```sh
|
|
62
|
+
node scripts/e2e-toggle.mjs --base http://127.0.0.1:<port> --token <token>
|
|
63
|
+
```
|
|
64
|
+
|
|
47
65
|
The client bundle is `lib/client.js` (classic `__ModuleLoader__.load` factory, no build step).
|
|
48
66
|
|
|
49
67
|
## Status
|
|
50
68
|
|
|
51
|
-
`0.1.
|
|
69
|
+
`0.1.1` — catalog + installed inventory + Settings → Plugins tab + enable/disable through dsh-market. One-click install requires the package to be present in the connected dsh-market registry; otherwise use the copyable command. Configuration stays in each child plugin's own Settings → Plugins page.
|
package/VERIFY.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Verification record — dsh-preview-market 0.1.
|
|
1
|
+
# Verification record — dsh-preview-market 0.1.1
|
|
2
2
|
|
|
3
3
|
## Unit tests (2026-10-23)
|
|
4
4
|
|
|
@@ -11,10 +11,45 @@
|
|
|
11
11
|
| `test/installed.test.js` | profile `package.json` + `node_modules` inventory, missing profile, `profileContext` resolution |
|
|
12
12
|
| `test/client.test.js` | bundle registers exactly one `settings.plugins.tab` entry with id `dsh-preview-market` |
|
|
13
13
|
|
|
14
|
+
## Host / bundle smoke (2026-10-23, preview-test profile)
|
|
15
|
+
|
|
16
|
+
- Installed the packed tarball into a throwaway `preview-test` profile with `dsh plugin --profile preview-test add …`.
|
|
17
|
+
- `dsh --profile preview-test --dump-config` contains one `id: preview-market` row with `routeRoot: /api/preview-market`.
|
|
18
|
+
- The Web boot graph (`__DSH_BOOT__`) contains `dsh-preview-market` and injects `__DSH_PREVIEW_MARKET_CONFIG__`.
|
|
19
|
+
- The combo bundle URL returned **200** (16,213 B) and contains `settings.plugins.tab` + `dsh-preview-market`.
|
|
20
|
+
|
|
21
|
+
## Settings tab e2e (2026-10-23, preview-test)
|
|
22
|
+
|
|
23
|
+
Installed `dsh-preview-market@0.1.0` plus `dsh-preview-media@0.1.4`, `dsh-preview-blender@0.1.0`, `dsh-preview-stl@0.1.0` into `preview-test`, started the Web host, and ran:
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
node scripts/e2e-settings.mjs --base http://127.0.0.1:59003 --token <token>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Result: **PASS** — opened Settings → Built-in plugins → Preview market and found the tab plus the three installed cards (`dsh-preview-media`, `dsh-preview-blender`, `dsh-preview-stl`). No page errors; the only console 404 is the expected `/dsh-market/status` probe when dsh-market is absent. Screenshot: `%TEMP%\dsh-preview-market-settings.png`.
|
|
30
|
+
|
|
31
|
+
## Fallback install/copy e2e (2026-10-23, preview-test)
|
|
32
|
+
|
|
33
|
+
Removed `dsh-preview-stl` from `preview-test`, restarted the host, and ran:
|
|
34
|
+
|
|
35
|
+
```sh
|
|
36
|
+
node scripts/e2e-fallback.mjs --base http://127.0.0.1:59004 --token <token>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Result: **PASS** — the STL card showed `安装`; clicking it displayed `dsh plugin --profile preview-test add dsh-preview-stl@0.1.0` (dsh-market absent); the media card's copy button reported `命令已复制` and the clipboard held `dsh plugin --profile preview-test add dsh-preview-media@0.1.4`. No page errors. STL was reinstalled afterwards.
|
|
40
|
+
|
|
41
|
+
## Toggle / configure e2e (2026-10-23, preview-test + dsh-market 1.67.0)
|
|
42
|
+
|
|
43
|
+
With dsh-market installed, ran:
|
|
44
|
+
|
|
45
|
+
```sh
|
|
46
|
+
node scripts/e2e-toggle.mjs --base http://127.0.0.1:59006 --token <token>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Result: **PASS** — the STL card showed `停用`; clicking it wrote `dsh-preview-stl` into `/dsh-market/installed`'s `disabled` list and showed `已切换,刷新页面后生效`; clicking `启用` removed it again. The media card's `配置` showed `在 设置 → 插件 → dsh-preview-media 配置。` No page errors; screenshot: `%TEMP%\dsh-preview-market-toggle.png`.
|
|
50
|
+
|
|
14
51
|
## Not yet verified live
|
|
15
52
|
|
|
16
|
-
-
|
|
17
|
-
- One-click install through dsh-market (requires the new packages in its curated registry).
|
|
18
|
-
- Fallback command copy in a real browser.
|
|
53
|
+
- One-click install through dsh-market (requires the new packages in its curated registry; the market entries are scheduled for 2026-10-24).
|
|
19
54
|
|
|
20
|
-
|
|
55
|
+
This is the next check after the new market entries are accepted.
|
package/lib/client.js
CHANGED
|
@@ -45,7 +45,15 @@ window.__ModuleLoader__.load({
|
|
|
45
45
|
note: "安装/更新由 dsh-market 或 dsh CLI 完成;本页只做目录、状态与入口,不复制子插件代码。",
|
|
46
46
|
version: "版本",
|
|
47
47
|
notInstalled: "未安装",
|
|
48
|
-
disabledHint: "启用/停用请到 设置 → 插件 列表。"
|
|
48
|
+
disabledHint: "启用/停用请到 设置 → 插件 列表。",
|
|
49
|
+
enable: "启用",
|
|
50
|
+
disable: "停用",
|
|
51
|
+
config: "配置",
|
|
52
|
+
configHint: "在 设置 → 插件 → {name} 配置。",
|
|
53
|
+
manageHint: "到 设置 → 插件 启用/停用。",
|
|
54
|
+
toggled: "已切换。",
|
|
55
|
+
toggleRefresh: "已切换,刷新页面后生效。",
|
|
56
|
+
toggleFailed: "切换失败"
|
|
49
57
|
};
|
|
50
58
|
|
|
51
59
|
const en = {
|
|
@@ -74,7 +82,15 @@ window.__ModuleLoader__.load({
|
|
|
74
82
|
note: "Installs and updates go through dsh-market or the dsh CLI; this page only provides the catalog, status and entry points. Child plugin code is never copied.",
|
|
75
83
|
version: "Version",
|
|
76
84
|
notInstalled: "Not installed",
|
|
77
|
-
disabledHint: "Enable or disable it in Settings → Plugins."
|
|
85
|
+
disabledHint: "Enable or disable it in Settings → Plugins.",
|
|
86
|
+
enable: "Enable",
|
|
87
|
+
disable: "Disable",
|
|
88
|
+
config: "Configure",
|
|
89
|
+
configHint: "Configure it in Settings → Plugins → {name}.",
|
|
90
|
+
manageHint: "Use Settings → Plugins to enable or disable it.",
|
|
91
|
+
toggled: "Toggled.",
|
|
92
|
+
toggleRefresh: "Toggled; refresh the page to apply.",
|
|
93
|
+
toggleFailed: "Toggle failed"
|
|
78
94
|
};
|
|
79
95
|
|
|
80
96
|
/** Route root published by the Host at boot. */
|
|
@@ -102,7 +118,7 @@ window.__ModuleLoader__.load({
|
|
|
102
118
|
}
|
|
103
119
|
|
|
104
120
|
/** A single catalog card. */
|
|
105
|
-
function Card({ item, installed, profile, dshmarket, busy, onInstall, onCopy, t }) {
|
|
121
|
+
function Card({ item, installed, profile, dshmarket, enabled, busy, onInstall, onCopy, onToggle, onConfig, t }) {
|
|
106
122
|
const current = installed !== undefined ? installed.version : "";
|
|
107
123
|
const newer = current !== "" && current !== item.version;
|
|
108
124
|
const formats = item.formats !== undefined
|
|
@@ -149,7 +165,27 @@ window.__ModuleLoader__.load({
|
|
|
149
165
|
t("copy")
|
|
150
166
|
),
|
|
151
167
|
current !== ""
|
|
152
|
-
? React.createElement(
|
|
168
|
+
? React.createElement(
|
|
169
|
+
"button",
|
|
170
|
+
{
|
|
171
|
+
type: "button",
|
|
172
|
+
className: "dsh-pm-button",
|
|
173
|
+
disabled: busy === item.name || !dshmarket,
|
|
174
|
+
title: dshmarket ? "" : t("manageHint"),
|
|
175
|
+
onClick: () => onToggle(item)
|
|
176
|
+
},
|
|
177
|
+
enabled ? t("disable") : t("enable")
|
|
178
|
+
)
|
|
179
|
+
: null,
|
|
180
|
+
current !== ""
|
|
181
|
+
? React.createElement(
|
|
182
|
+
"button",
|
|
183
|
+
{ type: "button", className: "dsh-pm-button", onClick: () => onConfig(item) },
|
|
184
|
+
t("config")
|
|
185
|
+
)
|
|
186
|
+
: null,
|
|
187
|
+
current !== "" && !dshmarket
|
|
188
|
+
? React.createElement("span", { className: "dsh-pm-hint" }, t("manageHint"))
|
|
153
189
|
: null
|
|
154
190
|
)
|
|
155
191
|
);
|
|
@@ -163,6 +199,7 @@ window.__ModuleLoader__.load({
|
|
|
163
199
|
error: "",
|
|
164
200
|
catalog: [],
|
|
165
201
|
installed: [],
|
|
202
|
+
disabled: [],
|
|
166
203
|
profile: "desktop",
|
|
167
204
|
dshmarket: false
|
|
168
205
|
});
|
|
@@ -172,18 +209,32 @@ window.__ModuleLoader__.load({
|
|
|
172
209
|
const load = React.useCallback(async () => {
|
|
173
210
|
setState((previous) => ({ ...previous, loading: true, error: "" }));
|
|
174
211
|
try {
|
|
175
|
-
const
|
|
212
|
+
const status = await fetch("/dsh-market/status", { cache: "no-store" })
|
|
213
|
+
.then((response) => response.ok)
|
|
214
|
+
.catch(() => false);
|
|
215
|
+
const [catalog, inventory] = await Promise.all([
|
|
176
216
|
getJson(`${marketRoute}/catalog`),
|
|
177
|
-
getJson(`${marketRoute}/installed`)
|
|
178
|
-
fetch("/dsh-market/status", { cache: "no-store" })
|
|
179
|
-
.then((response) => response.ok)
|
|
180
|
-
.catch(() => false)
|
|
217
|
+
getJson(`${marketRoute}/installed`)
|
|
181
218
|
]);
|
|
219
|
+
let disabled = [];
|
|
220
|
+
if (status === true) {
|
|
221
|
+
try {
|
|
222
|
+
const detailResponse = await fetch("/dsh-market/installed", { cache: "no-store" });
|
|
223
|
+
if (detailResponse.ok) {
|
|
224
|
+
const detail = await detailResponse.json();
|
|
225
|
+
if (Array.isArray(detail.disabled)) disabled = detail.disabled;
|
|
226
|
+
else if (Array.isArray(detail.patch?.disables)) disabled = detail.patch.disables;
|
|
227
|
+
}
|
|
228
|
+
} catch {
|
|
229
|
+
disabled = [];
|
|
230
|
+
}
|
|
231
|
+
}
|
|
182
232
|
setState({
|
|
183
233
|
loading: false,
|
|
184
234
|
error: "",
|
|
185
235
|
catalog: Array.isArray(catalog.plugins) ? catalog.plugins : [],
|
|
186
236
|
installed: Array.isArray(inventory.installed) ? inventory.installed : [],
|
|
237
|
+
disabled: Array.isArray(disabled) ? disabled : [],
|
|
187
238
|
profile: typeof inventory.profile === "string" && inventory.profile !== "" ? inventory.profile : "desktop",
|
|
188
239
|
dshmarket: status === true
|
|
189
240
|
});
|
|
@@ -235,6 +286,33 @@ window.__ModuleLoader__.load({
|
|
|
235
286
|
}
|
|
236
287
|
}, [state.profile, t]);
|
|
237
288
|
|
|
289
|
+
const toggle = React.useCallback(async (item) => {
|
|
290
|
+
setBusy(item.name);
|
|
291
|
+
setNotice("");
|
|
292
|
+
try {
|
|
293
|
+
const enabled = state.disabled.includes(item.name);
|
|
294
|
+
const response = await fetch("/dsh-market/toggle", {
|
|
295
|
+
method: "POST",
|
|
296
|
+
headers: { "content-type": "application/json" },
|
|
297
|
+
body: JSON.stringify({ name: item.name, enabled })
|
|
298
|
+
});
|
|
299
|
+
const body = await response.json().catch(() => null);
|
|
300
|
+
if (!response.ok || body === null || body.ok !== true) {
|
|
301
|
+
throw new Error(body !== null && typeof body.error === "string" ? body.error : `HTTP ${response.status}`);
|
|
302
|
+
}
|
|
303
|
+
setNotice(body.refresh ? t("toggleRefresh") : t("toggled"));
|
|
304
|
+
await load();
|
|
305
|
+
} catch (error) {
|
|
306
|
+
setNotice(`${t("toggleFailed")}: ${error instanceof Error ? error.message : String(error)}`);
|
|
307
|
+
} finally {
|
|
308
|
+
setBusy("");
|
|
309
|
+
}
|
|
310
|
+
}, [state.disabled, load, t]);
|
|
311
|
+
|
|
312
|
+
const config = React.useCallback((item) => {
|
|
313
|
+
setNotice(t("configHint").replace("{name}", item.name));
|
|
314
|
+
}, [t]);
|
|
315
|
+
|
|
238
316
|
installStyle();
|
|
239
317
|
|
|
240
318
|
return React.createElement(
|
|
@@ -277,9 +355,12 @@ window.__ModuleLoader__.load({
|
|
|
277
355
|
installed: installedByName.get(item.name),
|
|
278
356
|
profile: state.profile,
|
|
279
357
|
dshmarket: state.dshmarket,
|
|
358
|
+
enabled: !state.disabled.includes(item.name),
|
|
280
359
|
busy,
|
|
281
360
|
onInstall: (entry) => void install(entry),
|
|
282
361
|
onCopy: (entry) => void copy(entry),
|
|
362
|
+
onToggle: (entry) => void toggle(entry),
|
|
363
|
+
onConfig: (entry) => config(entry),
|
|
283
364
|
t
|
|
284
365
|
})
|
|
285
366
|
)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-preview-market",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Vertical preview market for DeepSeek Harness: discover, install and configure preview plugins (media, Blender, STL, ...) from one panel.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -65,6 +65,9 @@
|
|
|
65
65
|
"url": "https://github.com/439436269-ctrl/dsh-preview-market/issues"
|
|
66
66
|
},
|
|
67
67
|
"scripts": {
|
|
68
|
-
"test": "node --test test/*.test.js"
|
|
68
|
+
"test": "node --test test/*.test.js",
|
|
69
|
+
"e2e": "node scripts/e2e-settings.mjs",
|
|
70
|
+
"e2e:fallback": "node scripts/e2e-fallback.mjs",
|
|
71
|
+
"e2e:toggle": "node scripts/e2e-toggle.mjs"
|
|
69
72
|
}
|
|
70
73
|
}
|