dshmarket 1.2.2 → 1.2.3

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
@@ -51,6 +51,14 @@ Installs prefer npm tarballs over full-repo GitHub downloads whenever a plugin p
51
51
 
52
52
  Live from [awesome-dsh-plugin.com/plugins.json](https://awesome-dsh-plugin.com/plugins.json) — curated entries, npm mapping, and star counts refreshed daily by CI — with a bundled snapshot as offline fallback.
53
53
 
54
+ ## Related projects
55
+
56
+ ### DeepSeek Harness Desktop
57
+
58
+ [DeepSeek Harness Desktop](https://github.com/anywhere-labs/deepseek-harness-desktop) is a modern desktop client for the DeepSeek Harness ecosystem — start and manage a local Harness service without installing Node.js or touching the command line. Plugin marketplace, mobile remote control, and IM Channels are on its roadmap.
59
+
60
+ [Website](https://www.dshdesktop.cn) · [GitHub](https://github.com/anywhere-labs/deepseek-harness-desktop)
61
+
54
62
  ## License
55
63
 
56
64
  MIT · [dshmarket.com](https://dshmarket.com)
package/README.zh.md CHANGED
@@ -51,6 +51,14 @@ dsh plugin --profile web add dshmarket
51
51
 
52
52
  实时来自 [awesome-dsh-plugin.com/plugins.json](https://awesome-dsh-plugin.com/plugins.json)——精选条目、npm 映射、star 数由 CI 每日刷新——内置快照做离线兜底。
53
53
 
54
+ ## 友情链接
55
+
56
+ ### DeepSeek Harness Desktop
57
+
58
+ [DeepSeek Harness Desktop](https://github.com/anywhere-labs/deepseek-harness-desktop) 是一款为 DeepSeek Harness 生态打造的现代化桌面端,让用户无需配置 Node.js 或执行命令,即可启动和管理本地 Harness 服务。项目后续还将支持插件市场、移动端远程控制和 IM Channels。
59
+
60
+ [访问官网](https://www.dshdesktop.cn) · [GitHub](https://github.com/anywhere-labs/deepseek-harness-desktop)
61
+
54
62
  ## 许可
55
63
 
56
64
  MIT · [dshmarket.com](https://dshmarket.com)
package/client/client.js CHANGED
@@ -38,6 +38,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
38
38
  update: "更新",
39
39
  updating: "更新中…",
40
40
  updated: "✓ 已更新,重启后生效",
41
+ updateNow: "立即更新",
41
42
  updateFail: "更新失败",
42
43
  upToDate: "已是最新",
43
44
  linkedDev: "本地开发链接",
@@ -96,6 +97,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
96
97
  update: "Update",
97
98
  updating: "Updating…",
98
99
  updated: "✓ Updated — restart to apply",
100
+ updateNow: "Update now",
99
101
  updateFail: "Update failed",
100
102
  upToDate: "Up to date",
101
103
  linkedDev: "linked (dev)",
@@ -132,10 +134,6 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
132
134
  for (let i = 0; i < name.length; i++) hash = hash * 31 + name.charCodeAt(i) | 0;
133
135
  return "hsl(" + (hash % 360 + 360) % 360 + " 55% 52%)";
134
136
  }
135
- function repoOf(url) {
136
- const m = /^https:\/\/github\.com\/([^/]+\/[^/]+?)(?:\/tree\/.+)?\/?$/.exec(url);
137
- return m ? m[1] : null;
138
- }
139
137
  function readSession(key) {
140
138
  try {
141
139
  return JSON.parse(sessionStorage.getItem(key) || "null");
@@ -149,6 +147,34 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
149
147
  return /\b(tui|cli|tty|terminal)\b|终端|命令行/i.test(plugin.name + " " + desc);
150
148
  }
151
149
  /**
150
+ * The discover list: category filter, then search across name / owner /
151
+ * localized description, then the selected sort. Pure — the section renders
152
+ * exactly this.
153
+ */
154
+ function visiblePlugins(plugins, options) {
155
+ const query = options.query.trim().toLowerCase();
156
+ const list = plugins.filter((p) => {
157
+ if (options.category !== "all" && p.category !== options.category) return false;
158
+ if (query === "") return true;
159
+ const desc = p.description && (p.description[options.lang] || p.description.en) || "";
160
+ return p.name.toLowerCase().includes(query) || p.owner.toLowerCase().includes(query) || desc.toLowerCase().includes(query);
161
+ });
162
+ if (options.sort === "hot") return [...list].sort((a, b) => (b.stars ?? -1) - (a.stars ?? -1));
163
+ if (options.sort === "new") return [...list].sort((a, b) => String(b.added).localeCompare(String(a.added)));
164
+ return list;
165
+ }
166
+ /** The themes tab listing: theme category only, most-starred first. */
167
+ function themePlugins(plugins) {
168
+ return plugins.filter((p) => p.category === "theme").sort((a, b) => (b.stars || 0) - (a.stars || 0));
169
+ }
170
+ /**
171
+ * Category chip order: collapsed with an active non-'all' chip, the active
172
+ * one moves to the front so it stays visible inside the two-row clip.
173
+ */
174
+ function orderedCategories(categories, active, open) {
175
+ return open || active === "all" ? categories : [active, ...categories.filter((id) => id !== active)];
176
+ }
177
+ /**
152
178
  * Unified installed-state matching (#15): both sides collapse to lowercase
153
179
  * identity sets — the registry entry contributes its bare name, npm name and
154
180
  * owner/repo; the dependency contributes its key and the repo inside its
@@ -158,16 +184,19 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
158
184
  function entryIdentities(plugin) {
159
185
  const ids = /* @__PURE__ */ new Set([plugin.name.toLowerCase()]);
160
186
  if (plugin.npm) ids.add(plugin.npm.toLowerCase());
161
- const repo = repoOf(plugin.url);
162
- if (repo !== null) ids.add(repo.toLowerCase());
187
+ const m = /^https:\/\/github\.com\/([^/]+\/[^/]+?)(?:\/tree\/[^/]+\/(.+?))?\/?$/.exec(plugin.url);
188
+ if (m !== null) ids.add(m[2] !== void 0 ? `${m[1].toLowerCase()}#path:/${m[2].toLowerCase()}` : m[1].toLowerCase());
163
189
  return ids;
164
190
  }
165
191
  function depIdentities(name, spec) {
166
192
  const ids = /* @__PURE__ */ new Set([name.toLowerCase()]);
167
193
  const scoped = /^@([^/]+)\/(.+)$/.exec(name);
168
194
  if (scoped !== null) ids.add(`${scoped[1].toLowerCase()}/${scoped[2].toLowerCase()}`);
169
- const match = /github:([A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+)/i.exec(spec);
170
- if (match !== null) ids.add(match[1].toLowerCase());
195
+ const match = /github:([A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+)(?:#path:\/([A-Za-z0-9_./-]+))?/i.exec(spec);
196
+ if (match !== null) {
197
+ ids.add(match[1].toLowerCase());
198
+ if (match[2] !== void 0) ids.add(`${match[1].toLowerCase()}#path:/${match[2].toLowerCase()}`);
199
+ }
171
200
  return ids;
172
201
  }
173
202
  /** The installed dependency name a registry entry corresponds to, or null. */
@@ -235,7 +264,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
235
264
  }
236
265
  //#endregion
237
266
  //#region \0dsh-css:/home/runner/work/dsh-market/dsh-market/src/client/Market.module.css.mjs
238
- const css = ".eGUBIq_root{min-width:0;height:100%;color:var(--dsw-alias-label-primary,#1f2328);flex-direction:column;display:flex;position:relative}.eGUBIq_head{flex-direction:column;gap:12px;padding:4px 4px 12px;display:flex}.eGUBIq_title{margin:0;font-size:16px;font-weight:500;line-height:24px}.eGUBIq_sub{color:var(--dsw-alias-label-tertiary,#8b93a1);margin:0;font-size:14px;line-height:22px}.eGUBIq_searchInline{flex-shrink:0;width:200px;margin-bottom:6px}.eGUBIq_tabs{border-bottom:1px solid var(--dsw-alias-border-l2,#e5e7eb);align-items:flex-end;gap:2px;display:flex}.eGUBIq_tab{font:inherit;color:var(--dsw-alias-label-secondary,#6b7280);cursor:pointer;white-space:nowrap;background:0 0;border:none;border-bottom:2px solid #0000;padding:7px 12px;font-size:13px}.eGUBIq_tab.eGUBIq_on{color:var(--dsw-alias-brand-primary,#4f6ef7);border-bottom-color:var(--dsw-alias-brand-primary,#4f6ef7);font-weight:600}.eGUBIq_restart{background:var(--dsw-alias-bg-layer-2,#fdf3e3);border:1px solid var(--dsw-alias-border-l2,#f3e3c3);border-radius:8px;align-items:center;gap:8px;margin:0;padding:8px 12px;font-size:12px;display:flex}.eGUBIq_body{flex:1;padding:12px 4px 24px;overflow-x:hidden;overflow-y:auto}.eGUBIq_cats{z-index:5;background:var(--dsw-alias-bg-layer-2,#f7f8fa);margin:-12px -4px 2px;padding:12px 4px 4px;position:sticky;top:-13px}.eGUBIq_catsRow{align-items:flex-start;gap:8px;display:flex;position:relative}.eGUBIq_sort{background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l1,#e5e7eb);border-radius:8px;flex-shrink:0;gap:2px;padding:2px;display:flex}.eGUBIq_sort button{font:inherit;color:var(--dsw-alias-label-secondary,#6b7280);cursor:pointer;background:0 0;border:none;border-radius:6px;padding:3px 10px;font-size:12px}.eGUBIq_sort button.eGUBIq_on{background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-primary,#1f2328);font-weight:600;box-shadow:0 1px 3px #00000014}.eGUBIq_star{color:var(--dsw-alias-label-secondary,#9ca3af);font-size:11px}.eGUBIq_top{z-index:20;border:1px solid var(--dsw-alias-border-l1,#e5e7eb);background:var(--dsw-alias-bg-layer-1,#fff);width:38px;height:38px;color:var(--dsw-alias-label-secondary,#6b7280);cursor:pointer;border-radius:99px;font-size:16px;position:absolute;bottom:18px;right:18px;box-shadow:0 4px 14px #0000001f}.eGUBIq_top:hover{color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_tag{border:1px solid var(--dsw-alias-border-l3,#d9dde3);color:var(--dsw-alias-label-secondary,#6b7280);border-radius:4px;flex-shrink:0;padding:1px 6px;font-size:11px;line-height:16px}.eGUBIq_okState{color:var(--dsw-alias-state-success-primary,#16a34a);white-space:nowrap;font-size:12px;font-weight:600}.eGUBIq_dangerBtn.eGUBIq_dangerBtn{border-color:var(--dsw-alias-state-error-primary,#dc2626);color:var(--dsw-alias-state-error-primary,#dc2626)}.eGUBIq_dangerArmed.eGUBIq_dangerArmed{background:var(--dsw-alias-state-error-primary,#dc2626);color:#fff}.eGUBIq_warnBtn.eGUBIq_warnBtn{background:var(--dsw-alias-state-warn-primary,#ea580c);color:#fff}.eGUBIq_catsWrap{flex-wrap:wrap;flex:1;align-items:center;gap:6px;min-width:0;display:flex}.eGUBIq_catsCollapsed{max-height:62px;overflow:hidden}.eGUBIq_catsToggle.eGUBIq_catsToggle{height:26px;min-height:26px;color:var(--dsw-alias-label-secondary,#6b7280);padding:0 6px}.eGUBIq_cmdDetails{margin:0}.eGUBIq_cmdSummary{cursor:pointer;width:fit-content;color:var(--dsw-alias-label-secondary,#6b7280);border-radius:6px;align-items:center;gap:6px;margin-left:-4px;padding:2px 4px;font-size:12px;font-weight:500;line-height:18px;list-style:none;display:flex}.eGUBIq_cmdSummary::-webkit-details-marker{display:none}.eGUBIq_cmdSummary:before{content:\"\";border-bottom:1.5px solid;border-right:1.5px solid;width:5px;height:5px;transition:transform .12s;transform:rotate(-45deg)translate(-1px,-1px)}.eGUBIq_cmdDetails[open]>.eGUBIq_cmdSummary:before{transform:rotate(45deg)translate(-1px,-1px)}.eGUBIq_cmdSummary:hover{color:var(--dsw-alias-label-primary,#1f2328)}.eGUBIq_cmd{background:var(--dsw-alias-bg-layer-2,#f3f4f6);word-break:break-all;border-radius:6px;margin:8px 0 0;padding:8px 10px;font-family:ui-monospace,Menlo,monospace;font-size:11px;line-height:18px}.eGUBIq_warnLine{color:var(--dsw-alias-state-warn-primary,#b45309);margin:0;font-size:12px;font-weight:600;line-height:18px}.eGUBIq_modalNote{color:var(--dsw-alias-label-tertiary,#8b93a1);margin:12px 0 0;font-size:12px;line-height:18px}.eGUBIq_grid{grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:12px;display:grid}.eGUBIq_sect{color:var(--dsw-alias-label-secondary,#6b7280);margin:14px 2px 8px;font-size:12px;font-weight:600}.eGUBIq_sect:first-child{margin-top:2px}.eGUBIq_swatches{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:8px;gap:0;height:34px;display:flex;overflow:hidden}.eGUBIq_themesGrid{margin-bottom:12px}.eGUBIq_swatches i{flex:1}.eGUBIq_card{background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:12px;flex-direction:column;gap:12px;padding:12px 14px;display:flex}.eGUBIq_row1{align-items:center;gap:10px;min-width:0;display:flex}.eGUBIq_av{color:#fff;object-fit:cover;background:var(--dsw-alias-bg-layer-2,#f3f4f6);border-radius:8px;flex-shrink:0;place-items:center;width:32px;height:32px;font-size:14px;font-weight:700;display:grid}.eGUBIq_nm{text-overflow:ellipsis;white-space:nowrap;font-size:14px;font-weight:500;line-height:22px;overflow:hidden}.eGUBIq_owner{color:var(--dsw-alias-label-secondary,#9ca3af);font-size:11px}.eGUBIq_desc{color:var(--dsw-alias-label-tertiary,#8b93a1);min-height:36px;margin:0;font-size:12px;line-height:18px}.eGUBIq_foot{align-items:center;gap:8px;margin-top:auto;display:flex}.eGUBIq_grow{flex:1}.eGUBIq_titleRow{align-items:center;gap:10px;display:flex}.eGUBIq_descTight{min-height:0}.eGUBIq_src{color:var(--dsw-alias-label-secondary,#9ca3af);font-size:11px;text-decoration:none}.eGUBIq_src:hover{color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_dot{vertical-align:2px;margin-left:5px}.eGUBIq_loading{color:var(--dsw-alias-label-secondary,#9ca3af);flex-direction:column;align-items:center;gap:12px;padding:48px;font-size:13px;display:flex}.eGUBIq_spin{border:3px solid var(--dsw-alias-border-l1,#e5e7eb);border-top-color:var(--dsw-alias-brand-primary,#4f6ef7);border-radius:99px;width:22px;height:22px;animation:.8s linear infinite eGUBIq_sp}@keyframes eGUBIq_sp{to{transform:rotate(360deg)}}.eGUBIq_progress{background:var(--dsw-alias-bg-layer-2,#f3f4f6);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);color:var(--dsw-alias-label-secondary,#6b7280);border-radius:8px;align-items:center;gap:9px;margin:0;padding:8px 12px;font-size:12px;display:flex}.eGUBIq_irow .eGUBIq_progress{margin-top:8px}.eGUBIq_progress .eGUBIq_spin{border-width:2px;flex-shrink:0;width:14px;height:14px}.eGUBIq_progress code{text-overflow:ellipsis;white-space:nowrap;font-family:ui-monospace,Menlo,monospace;font-size:11px;overflow:hidden}.eGUBIq_empty{color:var(--dsw-alias-label-secondary,#9ca3af);text-align:center;padding:32px;font-size:13px}.eGUBIq_err{color:var(--dsw-alias-state-error-primary,#dc2626);white-space:pre-wrap;word-break:break-all;margin:8px 0;font-size:12px}.eGUBIq_irow{background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:12px;align-items:center;gap:10px;margin-bottom:8px;padding:12px 14px;display:flex}.eGUBIq_irow>.eGUBIq_src,.eGUBIq_irow>.eGUBIq_owner,.eGUBIq_irow>.eGUBIq_btn{white-space:nowrap;flex-shrink:0}.eGUBIq_spec{color:var(--dsw-alias-label-secondary,#9ca3af);font-family:ui-monospace,Menlo,monospace;font-size:11px}";
267
+ const css = ".eGUBIq_root{min-width:0;height:100%;color:var(--dsw-alias-label-primary,#1f2328);flex-direction:column;display:flex;position:relative}.eGUBIq_head{flex-direction:column;gap:12px;padding:4px 4px 12px;display:flex}.eGUBIq_title{margin:0;font-size:16px;font-weight:500;line-height:24px}.eGUBIq_sub{color:var(--dsw-alias-label-tertiary,#8b93a1);margin:0;font-size:14px;line-height:22px}.eGUBIq_searchInline{flex-shrink:0;width:200px;margin-bottom:6px}.eGUBIq_tabs{border-bottom:1px solid var(--dsw-alias-border-l2,#e5e7eb);align-items:flex-end;gap:2px;display:flex}.eGUBIq_tab{font:inherit;color:var(--dsw-alias-label-secondary,#6b7280);cursor:pointer;white-space:nowrap;background:0 0;border:none;border-bottom:2px solid #0000;padding:7px 12px;font-size:13px}.eGUBIq_tab.eGUBIq_on{color:var(--dsw-alias-brand-primary,#4f6ef7);border-bottom-color:var(--dsw-alias-brand-primary,#4f6ef7);font-weight:600}.eGUBIq_restart{background:var(--dsw-alias-bg-layer-2,#fdf3e3);border:1px solid var(--dsw-alias-border-l2,#f3e3c3);border-radius:8px;align-items:center;gap:8px;margin:0;padding:8px 12px;font-size:12px;display:flex}.eGUBIq_body{flex:1;padding:12px 4px 24px;overflow-x:hidden;overflow-y:auto}.eGUBIq_cats{z-index:5;background:var(--dsw-alias-bg-layer-2,#f7f8fa);margin:-12px -4px 2px;padding:12px 4px 4px;position:sticky;top:-13px}.eGUBIq_catsRow{align-items:flex-start;gap:8px;display:flex;position:relative}.eGUBIq_sort{background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l1,#e5e7eb);border-radius:8px;flex-shrink:0;gap:2px;padding:2px;display:flex}.eGUBIq_sort button{font:inherit;color:var(--dsw-alias-label-secondary,#6b7280);cursor:pointer;background:0 0;border:none;border-radius:6px;padding:3px 10px;font-size:12px}.eGUBIq_sort button.eGUBIq_on{background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-primary,#1f2328);font-weight:600;box-shadow:0 1px 3px #00000014}.eGUBIq_star{color:var(--dsw-alias-label-secondary,#9ca3af);font-size:11px}.eGUBIq_top{z-index:20;border:1px solid var(--dsw-alias-border-l1,#e5e7eb);background:var(--dsw-alias-bg-layer-1,#fff);width:38px;height:38px;color:var(--dsw-alias-label-secondary,#6b7280);cursor:pointer;border-radius:99px;font-size:16px;position:absolute;bottom:18px;right:18px;box-shadow:0 4px 14px #0000001f}.eGUBIq_top:hover{color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_tag{border:1px solid var(--dsw-alias-border-l3,#d9dde3);color:var(--dsw-alias-label-secondary,#6b7280);border-radius:4px;flex-shrink:0;padding:1px 6px;font-size:11px;line-height:16px}.eGUBIq_okState{color:var(--dsw-alias-state-success-primary,#16a34a);white-space:nowrap;font-size:12px;font-weight:600}.eGUBIq_dangerBtn.eGUBIq_dangerBtn{border-color:var(--dsw-alias-state-error-primary,#dc2626);color:var(--dsw-alias-state-error-primary,#dc2626)}.eGUBIq_dangerArmed.eGUBIq_dangerArmed{background:var(--dsw-alias-state-error-primary,#dc2626);color:#fff}.eGUBIq_warnBtn.eGUBIq_warnBtn{background:var(--dsw-alias-state-warn-primary,#ea580c);color:#fff}.eGUBIq_catsWrap{flex-wrap:wrap;flex:1;align-items:center;gap:6px;min-width:0;display:flex}.eGUBIq_catsCollapsed{max-height:62px;overflow:hidden}.eGUBIq_catsToggle.eGUBIq_catsToggle{height:26px;min-height:26px;color:var(--dsw-alias-label-secondary,#6b7280);padding:0 6px}.eGUBIq_cmdDetails{margin:0}.eGUBIq_cmdSummary{cursor:pointer;width:fit-content;color:var(--dsw-alias-label-secondary,#6b7280);border-radius:6px;align-items:center;gap:6px;margin-left:-4px;padding:2px 4px;font-size:12px;font-weight:500;line-height:18px;list-style:none;display:flex}.eGUBIq_cmdSummary::-webkit-details-marker{display:none}.eGUBIq_cmdSummary:before{content:\"\";border-bottom:1.5px solid;border-right:1.5px solid;width:5px;height:5px;transition:transform .12s;transform:rotate(-45deg)translate(-1px,-1px)}.eGUBIq_cmdDetails[open]>.eGUBIq_cmdSummary:before{transform:rotate(45deg)translate(-1px,-1px)}.eGUBIq_cmdSummary:hover{color:var(--dsw-alias-label-primary,#1f2328)}.eGUBIq_cmd{background:var(--dsw-alias-bg-layer-2,#f3f4f6);word-break:break-all;border-radius:6px;margin:8px 0 0;padding:8px 10px;font-family:ui-monospace,Menlo,monospace;font-size:11px;line-height:18px}.eGUBIq_warnLine{color:var(--dsw-alias-state-warn-primary,#b45309);margin:0;font-size:12px;font-weight:600;line-height:18px}.eGUBIq_modalNote{color:var(--dsw-alias-label-tertiary,#8b93a1);margin:12px 0 0;font-size:12px;line-height:18px}.eGUBIq_grid{grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:12px;display:grid}.eGUBIq_sect{color:var(--dsw-alias-label-secondary,#6b7280);margin:14px 2px 8px;font-size:12px;font-weight:600}.eGUBIq_sect:first-child{margin-top:2px}.eGUBIq_swatches{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:8px;gap:0;height:34px;display:flex;overflow:hidden}.eGUBIq_themesGrid{margin-bottom:12px}.eGUBIq_swatches i{flex:1}.eGUBIq_card{background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:12px;flex-direction:column;gap:12px;padding:12px 14px;display:flex}.eGUBIq_row1{align-items:center;gap:10px;min-width:0;display:flex}.eGUBIq_av{color:#fff;object-fit:cover;background:var(--dsw-alias-bg-layer-2,#f3f4f6);border-radius:8px;flex-shrink:0;place-items:center;width:32px;height:32px;font-size:14px;font-weight:700;display:grid}.eGUBIq_nm{text-overflow:ellipsis;white-space:nowrap;font-size:14px;font-weight:500;line-height:22px;overflow:hidden}.eGUBIq_owner{color:var(--dsw-alias-label-secondary,#9ca3af);font-size:11px}.eGUBIq_desc{color:var(--dsw-alias-label-tertiary,#8b93a1);min-height:36px;margin:0;font-size:12px;line-height:18px}.eGUBIq_foot{align-items:center;gap:8px;margin-top:auto;display:flex}.eGUBIq_grow{flex:1}.eGUBIq_titleRow{align-items:center;gap:10px;display:flex}.eGUBIq_descTight{min-height:0}.eGUBIq_src{color:var(--dsw-alias-label-secondary,#9ca3af);font-size:11px;text-decoration:none}.eGUBIq_src:hover{color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_dot{vertical-align:2px;margin-left:5px}.eGUBIq_loading{color:var(--dsw-alias-label-secondary,#9ca3af);flex-direction:column;align-items:center;gap:12px;padding:48px;font-size:13px;display:flex}.eGUBIq_spin{border:3px solid var(--dsw-alias-border-l1,#e5e7eb);border-top-color:var(--dsw-alias-brand-primary,#4f6ef7);border-radius:99px;width:22px;height:22px;animation:.8s linear infinite eGUBIq_sp}@keyframes eGUBIq_sp{to{transform:rotate(360deg)}}.eGUBIq_progress{background:var(--dsw-alias-bg-layer-2,#f3f4f6);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);color:var(--dsw-alias-label-secondary,#6b7280);border-radius:8px;align-items:center;gap:9px;margin:0;padding:8px 12px;font-size:12px;display:flex}.eGUBIq_irow .eGUBIq_progress{margin-top:8px}.eGUBIq_progress .eGUBIq_spin{border-width:2px;flex-shrink:0;width:14px;height:14px}.eGUBIq_progress code{text-overflow:ellipsis;white-space:nowrap;font-family:ui-monospace,Menlo,monospace;font-size:11px;overflow:hidden}.eGUBIq_empty{color:var(--dsw-alias-label-secondary,#9ca3af);text-align:center;padding:32px;font-size:13px}.eGUBIq_err{color:var(--dsw-alias-state-error-primary,#dc2626);white-space:pre-wrap;word-break:break-all;margin:8px 0;font-size:12px}.eGUBIq_irow{background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:12px;align-items:center;gap:10px;margin-bottom:8px;padding:12px 14px;display:flex}.eGUBIq_irow>.eGUBIq_src,.eGUBIq_irow>.eGUBIq_owner,.eGUBIq_dangerBtn.eGUBIq_dangerBtn,.eGUBIq_warnBtn.eGUBIq_warnBtn,.eGUBIq_dangerArmed.eGUBIq_dangerArmed{white-space:nowrap;flex-shrink:0}.eGUBIq_spec{color:var(--dsw-alias-label-secondary,#9ca3af);font-family:ui-monospace,Menlo,monospace;font-size:11px}.eGUBIq_staleAction{margin-top:8px}";
239
268
  const tagId = "dshmarket/Market.module.css";
240
269
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
241
270
  const tag = document.createElement("style");
@@ -245,59 +274,59 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
245
274
  document.head.appendChild(tag);
246
275
  }
247
276
  var Market_module_css_default = {
248
- "tabs": "eGUBIq_tabs",
249
- "swatches": "eGUBIq_swatches",
250
- "star": "eGUBIq_star",
251
- "okState": "eGUBIq_okState",
252
- "themesGrid": "eGUBIq_themesGrid",
253
- "dangerBtn": "eGUBIq_dangerBtn",
254
- "modalNote": "eGUBIq_modalNote",
255
- "nm": "eGUBIq_nm",
256
- "btn": "eGUBIq_btn",
257
- "descTight": "eGUBIq_descTight",
258
- "empty": "eGUBIq_empty",
259
- "cats": "eGUBIq_cats",
277
+ "grid": "eGUBIq_grid",
278
+ "cmdDetails": "eGUBIq_cmdDetails",
260
279
  "title": "eGUBIq_title",
261
- "on": "eGUBIq_on",
262
- "row1": "eGUBIq_row1",
263
280
  "body": "eGUBIq_body",
264
- "top": "eGUBIq_top",
265
- "searchInline": "eGUBIq_searchInline",
266
- "sub": "eGUBIq_sub",
267
- "catsWrap": "eGUBIq_catsWrap",
268
- "head": "eGUBIq_head",
269
- "av": "eGUBIq_av",
270
- "warnBtn": "eGUBIq_warnBtn",
271
- "owner": "eGUBIq_owner",
272
- "cmdDetails": "eGUBIq_cmdDetails",
273
- "restart": "eGUBIq_restart",
281
+ "empty": "eGUBIq_empty",
282
+ "nm": "eGUBIq_nm",
283
+ "on": "eGUBIq_on",
284
+ "loading": "eGUBIq_loading",
285
+ "card": "eGUBIq_card",
286
+ "modalNote": "eGUBIq_modalNote",
274
287
  "catsRow": "eGUBIq_catsRow",
288
+ "cats": "eGUBIq_cats",
275
289
  "foot": "eGUBIq_foot",
290
+ "tabs": "eGUBIq_tabs",
291
+ "catsWrap": "eGUBIq_catsWrap",
292
+ "titleRow": "eGUBIq_titleRow",
293
+ "warnLine": "eGUBIq_warnLine",
276
294
  "src": "eGUBIq_src",
295
+ "cmdSummary": "eGUBIq_cmdSummary",
296
+ "restart": "eGUBIq_restart",
277
297
  "root": "eGUBIq_root",
278
- "tab": "eGUBIq_tab",
298
+ "dangerArmed": "eGUBIq_dangerArmed",
279
299
  "desc": "eGUBIq_desc",
280
- "sect": "eGUBIq_sect",
300
+ "err": "eGUBIq_err",
301
+ "top": "eGUBIq_top",
281
302
  "catsToggle": "eGUBIq_catsToggle",
282
- "card": "eGUBIq_card",
283
- "titleRow": "eGUBIq_titleRow",
303
+ "tab": "eGUBIq_tab",
304
+ "av": "eGUBIq_av",
305
+ "dangerBtn": "eGUBIq_dangerBtn",
284
306
  "dot": "eGUBIq_dot",
285
- "progress": "eGUBIq_progress",
286
- "tag": "eGUBIq_tag",
287
- "sp": "eGUBIq_sp",
307
+ "irow": "eGUBIq_irow",
288
308
  "cmd": "eGUBIq_cmd",
289
- "cmdSummary": "eGUBIq_cmdSummary",
290
- "grid": "eGUBIq_grid",
291
- "catsCollapsed": "eGUBIq_catsCollapsed",
309
+ "swatches": "eGUBIq_swatches",
310
+ "spin": "eGUBIq_spin",
292
311
  "sort": "eGUBIq_sort",
312
+ "spec": "eGUBIq_spec",
293
313
  "grow": "eGUBIq_grow",
294
- "warnLine": "eGUBIq_warnLine",
295
- "dangerArmed": "eGUBIq_dangerArmed",
296
- "loading": "eGUBIq_loading",
297
- "spin": "eGUBIq_spin",
298
- "irow": "eGUBIq_irow",
299
- "err": "eGUBIq_err",
300
- "spec": "eGUBIq_spec"
314
+ "star": "eGUBIq_star",
315
+ "themesGrid": "eGUBIq_themesGrid",
316
+ "okState": "eGUBIq_okState",
317
+ "sect": "eGUBIq_sect",
318
+ "staleAction": "eGUBIq_staleAction",
319
+ "sub": "eGUBIq_sub",
320
+ "row1": "eGUBIq_row1",
321
+ "owner": "eGUBIq_owner",
322
+ "sp": "eGUBIq_sp",
323
+ "head": "eGUBIq_head",
324
+ "warnBtn": "eGUBIq_warnBtn",
325
+ "catsCollapsed": "eGUBIq_catsCollapsed",
326
+ "progress": "eGUBIq_progress",
327
+ "searchInline": "eGUBIq_searchInline",
328
+ "tag": "eGUBIq_tag",
329
+ "descTight": "eGUBIq_descTight"
301
330
  };
302
331
  //#endregion
303
332
  //#region src/client/MarketSection.tsx
@@ -347,6 +376,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
347
376
  const [installError, setInstallError] = (0, react.useState)(null);
348
377
  const [updates, setUpdates] = (0, react.useState)({});
349
378
  const [updatingName, setUpdatingName] = (0, react.useState)(null);
379
+ const [staleName, setStaleName] = (0, react.useState)(null);
350
380
  const [updatingAll, setUpdatingAll] = (0, react.useState)(false);
351
381
  const [updatedNames, setUpdatedNames] = (0, react.useState)([]);
352
382
  const [hotUrls, setHotUrls] = (0, react.useState)([]);
@@ -453,19 +483,12 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
453
483
  updatingName,
454
484
  data
455
485
  ]);
456
- const plugins = (0, react.useMemo)(() => {
457
- if (data === null) return [];
458
- const query = q.trim().toLowerCase();
459
- const list = data.plugins.filter((p) => {
460
- if (cat !== "all" && p.category !== cat) return false;
461
- if (query === "") return true;
462
- const desc = p.description && (p.description[lang] || p.description.en) || "";
463
- return p.name.toLowerCase().includes(query) || p.owner.toLowerCase().includes(query) || desc.toLowerCase().includes(query);
464
- });
465
- if (sort === "hot") return [...list].sort((a, b) => (b.stars ?? -1) - (a.stars ?? -1));
466
- if (sort === "new") return [...list].sort((a, b) => String(b.added).localeCompare(String(a.added)));
467
- return list;
468
- }, [
486
+ const plugins = (0, react.useMemo)(() => data === null ? [] : visiblePlugins(data.plugins, {
487
+ category: cat,
488
+ query: q,
489
+ lang,
490
+ sort
491
+ }), [
469
492
  data,
470
493
  q,
471
494
  cat,
@@ -509,13 +532,17 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
509
532
  setInstallError(t("installFail") + ": " + String(error));
510
533
  }).finally(() => setBusyUrl(null));
511
534
  }, [refreshInstalled, t]);
512
- const doUpdate = (0, react.useCallback)((name) => {
535
+ const doUpdate = (0, react.useCallback)((name, force = false) => {
513
536
  setInstallError(null);
537
+ setStaleName(null);
514
538
  setUpdatingName(name);
515
539
  return fetch("/dsh-market/update", {
516
540
  method: "POST",
517
541
  headers: { "content-type": "application/json" },
518
- body: JSON.stringify({ name })
542
+ body: JSON.stringify(force ? {
543
+ name,
544
+ force: true
545
+ } : { name })
519
546
  }).then((res) => res.json().then((body) => ({
520
547
  status: res.status,
521
548
  body
@@ -524,6 +551,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
524
551
  setUpdatedNames((names) => names.concat(name));
525
552
  refreshInstalled();
526
553
  } else {
554
+ if (body.stale === true) setStaleName(name);
527
555
  const text = (v) => typeof v === "string" ? v : v && typeof v.text === "string" ? v.text : v == null ? "" : JSON.stringify(v);
528
556
  const detail = text(body.error) || [text(body.stderr), text(body.stdout)].filter(Boolean).join("\n").trim() || "exit " + body.exitCode;
529
557
  setInstallError(t("updateFail") + ": " + name + " — " + detail.trim().slice(-600));
@@ -586,7 +614,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
586
614
  }, [updatableNames, doUpdate]);
587
615
  const pendingRestart = doneUrls.length + updatedNames.length + removedCount;
588
616
  const hasUpdates = Object.keys(installed).some((name) => !updatedNames.includes(name) && updates[name] && updates[name].updateAvailable);
589
- const themePlugins = data === null ? [] : data.plugins.filter((p) => p.category === "theme").sort((a, b) => (b.stars || 0) - (a.stars || 0));
617
+ const themePlugins$1 = data === null ? [] : themePlugins(data.plugins);
590
618
  const pluginCard = (p) => {
591
619
  const desc = p.description && (p.description[lang] || p.description.en) || "";
592
620
  const done = doneUrls.includes(p.url) || hotUrls.includes(p.url);
@@ -970,9 +998,16 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
970
998
  })
971
999
  ]
972
1000
  }),
973
- installError !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1001
+ installError !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
974
1002
  className: Market_module_css_default.err,
975
- children: installError
1003
+ children: [installError, staleName !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1004
+ className: Market_module_css_default.staleAction,
1005
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1006
+ size: "sm",
1007
+ onClick: () => doUpdate(staleName, true),
1008
+ children: t("updateNow")
1009
+ })
1010
+ })]
976
1011
  }),
977
1012
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
978
1013
  className: Market_module_css_default.body,
@@ -992,7 +1027,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
992
1027
  ref: catsWrapRef,
993
1028
  className: catsOpen || visibleCats === null ? `${Market_module_css_default.catsWrap} ${Market_module_css_default.catsCollapsed}` : Market_module_css_default.catsWrap,
994
1029
  children: (() => {
995
- const ordered = catsOpen || cat === "all" ? categories : [cat, ...categories.filter((id) => id !== cat)];
1030
+ const ordered = orderedCategories(categories, cat, catsOpen);
996
1031
  const shown = catsOpen || visibleCats === null ? ordered : ordered.slice(0, Math.max(0, visibleCats - 1));
997
1032
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
998
1033
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Pill, {
@@ -1041,12 +1076,12 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
1041
1076
  })(), data === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1042
1077
  className: Market_module_css_default.loading,
1043
1078
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: Market_module_css_default.spin }), t("loading")]
1044
- }) : themePlugins.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1079
+ }) : themePlugins$1.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1045
1080
  className: Market_module_css_default.empty,
1046
1081
  children: t("themeEmpty")
1047
1082
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1048
1083
  className: Market_module_css_default.grid,
1049
- children: themePlugins.map(themePluginCard)
1084
+ children: themePlugins$1.map(themePluginCard)
1050
1085
  })] }) : Object.keys(installed).length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1051
1086
  className: Market_module_css_default.empty,
1052
1087
  children: t("installedEmpty")