dsh-plugin-marketplace 0.2.4 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,6 +4,10 @@
4
4
 
5
5
  **GitHub**: [Scorp1o117/dsh-plugin-marketplace](https://github.com/Scorp1o117/dsh-plugin-marketplace) · **npm**: [dsh-plugin-marketplace](https://www.npmjs.com/package/dsh-plugin-marketplace)
6
6
 
7
+ [![Enhancement Suite](https://img.shields.io/badge/part%20of-Enhancement%20Suite-3964fe)](https://github.com/Scorp1o117/dsh-enhancement-suite) [![npm](https://img.shields.io/npm/v/dsh-enhancement-suite)](https://www.npmjs.com/package/dsh-enhancement-suite)
8
+
9
+ Part of the [DeepSeek Harness Enhancement Suite](https://github.com/Scorp1o117/dsh-enhancement-suite) — Vision · Soul/Persona · Long-term Memory · Plugin Marketplace.
10
+
7
11
  A **plugin marketplace** inside the DeepSeek Harness Web UI: browse
8
12
  [github.com/topics/dsh-plugin](https://github.com/topics/dsh-plugin) right
9
13
  from the settings page — no terminal needed.
package/README.zh.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  **GitHub**: [Scorp1o117/dsh-plugin-marketplace](https://github.com/Scorp1o117/dsh-plugin-marketplace) · **npm**: [dsh-plugin-marketplace](https://www.npmjs.com/package/dsh-plugin-marketplace) · [English](README.md)
4
4
 
5
+ [![Enhancement Suite](https://img.shields.io/badge/part%20of-Enhancement%20Suite-3964fe)](https://github.com/Scorp1o117/dsh-enhancement-suite) [![npm](https://img.shields.io/npm/v/dsh-enhancement-suite)](https://www.npmjs.com/package/dsh-enhancement-suite)
6
+
7
+ 属于 [DeepSeek Harness Enhancement Suite](https://github.com/Scorp1o117/dsh-enhancement-suite) —— Vision · Soul/Persona · 长期记忆 · 插件市场。
8
+
5
9
  在 DeepSeek Harness **Web UI 里内置的插件市场**:直接在设置页浏览
6
10
  [github.com/topics/dsh-plugin](https://github.com/topics/dsh-plugin),无需打开终端。
7
11
 
package/client.js CHANGED
@@ -207,7 +207,10 @@ window.__ModuleLoader__.load({
207
207
  var st = props.installState; // {status, message, pkg} from the settings scope
208
208
  var active = st && st.pkg === installName;
209
209
  var status = active ? st.status : "idle";
210
- var explainState = props.explainState; // {status, text} from the settings scope
210
+ var explainState = props.explainState; // {status, text, repo} from the settings scope
211
+ // The settings field is namespace-global and persists across sessions,
212
+ // so only show it when it belongs to the plugin currently open.
213
+ var explainMine = !!explainState && explainState.repo === p.fullName;
211
214
  var [confirming, setConfirming] = react.useState(false);
212
215
  var statusNode = null;
213
216
  if (status === "running") {
@@ -264,14 +267,14 @@ window.__ModuleLoader__.load({
264
267
  h("div", { className: "__mp_translateRow" },
265
268
  h("button", { type: "button", className: "__mp_translateBtn",
266
269
  style: { marginTop: "8px", padding: "4px 10px", fontSize: "12px", cursor: "pointer", background: "var(--dsw-alias-bg-hover, #21262d)", color: "var(--dsw-alias-label-primary, #e6edf3)", border: "1px solid var(--dsw-alias-border, #30363d)", borderRadius: "6px" },
267
- disabled: explainState && explainState.status === "running",
270
+ disabled: explainMine && explainState.status === "running",
268
271
  onClick: function () { props.onExplain(p.fullName, p.desc, props.readme || ""); }
269
272
  }, props.t("aiExplain")),
270
273
  h("div", { id: "__mp_translateOut", style: { fontSize: "12px", lineHeight: "1.6", color: "var(--dsw-alias-label-secondary, #8b949e)", whiteSpace: "pre-wrap", wordBreak: "break-word", marginTop: "8px", borderTop: "1px solid var(--dsw-alias-border, #21262d)", paddingTop: "8px" } },
271
- props.explainError ? h("span", { style: { color: "var(--dsw-alias-state-danger-text, #f85149)" } }, props.explainError)
272
- : explainState && explainState.status === "running" ? props.t("aiExplaining")
273
- : explainState && explainState.status === "error" ? props.t("aiExplainErr").replace("{msg}", explainState.text || "unknown")
274
- : explainState && explainState.status === "ok" ? explainState.text
274
+ explainMine && props.explainError ? h("span", { style: { color: "var(--dsw-alias-state-danger-text, #f85149)" } }, props.explainError)
275
+ : explainMine && explainState.status === "running" ? props.t("aiExplaining")
276
+ : explainMine && explainState.status === "error" ? props.t("aiExplainErr").replace("{msg}", explainState.text || "unknown")
277
+ : explainMine && explainState.status === "ok" ? explainState.text
275
278
  : ""
276
279
  )
277
280
  )
package/index.js CHANGED
@@ -49,6 +49,8 @@ const Config = z.object({
49
49
  aiExplainResult: z.object({
50
50
  status: z.string().default("idle"), // idle | running | ok | error
51
51
  text: z.string().default(""),
52
+ /** repo this result belongs to ("owner/name"); client gates display on it. */
53
+ repo: z.string().default(""),
52
54
  ts: z.number().default(0),
53
55
  }),
54
56
  });
@@ -135,15 +137,24 @@ function apply(ctx, config) {
135
137
  * Bundle plugins (already in `dsh.profile.bundles`, or whose installed
136
138
  * package declares `dsh.bundle.patch`) are mounted by their own bundle
137
139
  * layer — adding a manual row would create a duplicate loader entry and
138
- * abort boot, so they are skipped here.
140
+ * abort boot. A STALE manual row left by an earlier non-bundle version is
141
+ * removed instead, so reinstalling a bundle plugin never breaks boot.
139
142
  */
140
143
  function ensureMounted(pkg, profile) {
141
144
  const dshHome = process.env.DSH_HOME || join(os.homedir(), ".dsh");
142
145
  const patchPath = join(dshHome, "profiles", profile, "cordis.patch.yml");
143
146
  if (!existsSync(patchPath)) return " (patch file not found; mount manually)";
144
147
  const bundles = profileManifest(profile)?.dsh?.profile?.bundles ?? [];
145
- if (bundles.includes(pkg)) return " (already mounted via dsh.profile.bundles)";
146
- if (isBundlePackage(pkg, profile)) return " (bundle plugin: auto-mounted via its own dsh.bundle layer)";
148
+ if (bundles.includes(pkg) || isBundlePackage(pkg, profile)) {
149
+ // Bundle layer auto-mounts; remove any stale manual row (pre-bundle).
150
+ const src = readFileSync(patchPath, "utf8");
151
+ const cleaned = src.replace(new RegExp(`[ \\t]*- id: [^\\n]*\\n[ \\t]*name: ['"]${pkg.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}['"]\\n?`, "g"), "");
152
+ if (cleaned !== src) {
153
+ writeFileSync(patchPath, cleaned, "utf8");
154
+ return " (removed stale manual mount row; bundle layer auto-mounts)";
155
+ }
156
+ return bundles.includes(pkg) ? " (already mounted via dsh.profile.bundles)" : " (bundle plugin: auto-mounted via its own dsh.bundle layer)";
157
+ }
147
158
  const id = pkg.replace(/^@[^/]+\//, "").replace(/[^a-z0-9-]/g, "-") || pkg;
148
159
  let src = readFileSync(patchPath, "utf8");
149
160
  if (src.includes(`name: '${pkg}'`) || src.includes(`name: "${pkg}"`)) return " (already mounted)";
@@ -218,12 +229,12 @@ function apply(ctx, config) {
218
229
  }
219
230
 
220
231
  /** Write the AI-explain result report (and clear the consumed request). */
221
- async function reportExplain(status, text) {
232
+ async function reportExplain(status, text, repo) {
222
233
  const settings = ctx.get("settings");
223
234
  if (!settings) return;
224
235
  const ts = Date.now();
225
236
  await settings.update(NS, {
226
- aiExplainResult: { status, text, ts },
237
+ aiExplainResult: { status, text, repo: repo || "", ts },
227
238
  aiExplain: { repo: "", desc: "", readme: "", ts: 0 },
228
239
  }).catch((error) => {
229
240
  ctx.logger.warn(`[plugin-marketplace] explain state write failed: ${String(error)}`);
@@ -236,14 +247,16 @@ function apply(ctx, config) {
236
247
  * settings-backed message channel as the install flow.
237
248
  */
238
249
  async function maybeRunExplain() {
250
+ let repo = "";
239
251
  try {
240
252
  const cfg = current();
241
253
  const req = cfg?.aiExplain;
242
254
  if (!req || !req.repo || req.ts === lastExplainTs || req.ts === 0) return;
243
255
  lastExplainTs = req.ts;
256
+ repo = String(req.repo);
244
257
  const llm = ctx.llm;
245
258
  if (!llm) {
246
- await reportExplain("error", "LLM service unavailable; configure a model in Settings → Models.");
259
+ await reportExplain("error", "LLM service unavailable; configure a model in Settings → Models.", repo);
247
260
  return;
248
261
  }
249
262
  // Route through the deployment's default model when one is configured.
@@ -252,7 +265,6 @@ function apply(ctx, config) {
252
265
  const defaults = ctx.agentDefaultModel?.currentSelection?.();
253
266
  if (defaults?.provider && defaults?.model) route = defaults;
254
267
  } catch { /* no default model service; fall back to the adapter default */ }
255
- const repo = String(req.repo);
256
268
  const desc = String(req.desc || "").trim();
257
269
  const readme = String(req.readme || "").trim().slice(0, 1500);
258
270
  const prompt =
@@ -260,7 +272,7 @@ function apply(ctx, config) {
260
272
  (desc ? `简介:${desc}\n` : "") +
261
273
  (readme ? `README 摘要:\n${readme}\n` : "") +
262
274
  `\n请用简体中文、3~5 句话直接告诉我这个插件大概是干嘛的(核心用途、解决什么问题、适合谁)。不要复述仓库名,不要罗列安装步骤。`;
263
- await reportExplain("running", "");
275
+ await reportExplain("running", "", repo);
264
276
  ctx.logger.info(`[plugin-marketplace] explaining ${repo} (model=${route ? `${route.provider}/${route.model}` : "default"})…`);
265
277
  const messages = [createUserMessage({
266
278
  content: [{ type: "text", text: prompt }],
@@ -284,10 +296,10 @@ function apply(ctx, config) {
284
296
  .join(" ")
285
297
  .trim();
286
298
  if (!text) throw new Error("model produced no text");
287
- await reportExplain("ok", text);
299
+ await reportExplain("ok", text, repo);
288
300
  } catch (error) {
289
301
  ctx.logger.warn(`[plugin-marketplace] explain flow failed: ${String(error)}`);
290
- await reportExplain("error", String(error instanceof Error ? error.message : error));
302
+ await reportExplain("error", String(error instanceof Error ? error.message : error), repo);
291
303
  }
292
304
  }
293
305
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-plugin-marketplace",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "description": "DeepSeek Harness Web UI 内置插件市场:在设置页直接浏览 github.com/topics/dsh-plugin,支持搜索、按 Star 排序、查看安装方式。",
5
5
  "type": "module",
6
6
  "main": "index.js",