dsh-m 0.9.16 → 0.9.17

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
@@ -48,9 +48,15 @@
48
48
 
49
49
  以下重启链路仅适用于 **Web**(Desktop 的生效走官方应用生命周期:安装完成后退出并重新打开 Desktop 应用即可,见 0.9.0 节)。安装 / 卸载 / 升级完成后,当前已打开的市场页与已装页会一起重新读取 profile 状态并同步徽标/卡片,不需要关闭后重新打开插件市场;随后出现「⚡ 一键重启」横幅——受 systemd 管理时通过 DSH launcher 的 `appExit` 交给服务的 `Restart` 策略,避免在待停止 unit 的 cgroup 内启动 `systemctl` helper;无 `appExit` 的 systemd 兜底改用 manager-owned transient `systemd-run`,最后才退回 detached-helper。客户端按 boot id 确认新进程已恢复后关闭横幅,交由 DSH Web 自身的后台连接重试恢复页面,不强制整页刷新,避免认证/路由切换期间白屏。重启链路已在当前 DSH Web `0.2.0-rc.2` 实机核验(2026-10-01):dsh-m 探测 unit `Restart=` 策略后经 `appExit` 交还 systemd,`status=75/TEMPFAIL` 退出由 Restart 策略接住自动拉起,服务恢复后页面后台重连、面板全功能可用。历史口径:`0.1.5-rc.1` 时代已核验 `/dshm` ping 与带认证 `303 → 200`;`0.1.2-rc.1` 按契约核对 + 形态探测兜底收录(verified 数组),部署面演进后不再追旧代 live E2E;transient `systemd-run` 兜底仅适用于无 `appExit` 的宿主(受支持代际均提供 `appExit`),保持设计兜底而非发布门槛;连续安装/卸载由 profile 事务测试面(补偿事务、装后守卫等 813 用例)与 0.4.0→0.4.2 连续发布实证覆盖。安装过程实时显示 pnpm 进度(解析 → 下载 → 链接 → 构建)。
50
50
 
51
+ ### 0.9.17 变更:策展桶次级归属(一插件跨桶)+「iasi自研」更名
52
+
53
+ - **次级归属 `alsoCategories`**:收录条目可声明次级策展桶——chips 计数与桶过滤按「主桶 ∪ 次桶」计(跨桶条目在每个桶里都出现),详情页分类标签仍随主桶。首批双席位:**better-sidebar**(装机必备 ⊕ 崔添翼精选)、**dsh-m**(装机必备 ⊕ iasi自研);better-sidebar 原第 5 个「崔添翼精选」tag 由真实席位取代(tags 回归 ≤4 软规范)。
54
+ - **更名**:策展桶「我的自研」→「**iasi自研**」(slug `self-dev` 不变,chips/工具/CLI/详情标签四端同步)。
55
+ - **例行过渡**:schema 加字段后旧客户端校验拒收新 registry → 回落缓存/包内快照显示旧数据,升级即愈。
56
+
51
57
  ### 0.9.16 变更:精选策展五桶分类法 + 严筛收录(23→19)+ 新收录 DSH TUI
52
58
 
53
- - **策展分类法**:精选区分类从功能五分类(市场/工具/界面/搜索/其他)改为**策展五桶**——装机必备 / 崔添翼精选 / 我的自研 / 腾讯轻量云专区 / 观察区(chips 按此序,腾讯轻量云垫后)。分类语义从「插件是什么」转为「为什么值得进精选」;重叠归属按 装机必备 > 崔添翼精选 > 自研 > 腾讯轻量云 优先级归桶,功能属性转 tags 保留检索,旧分类值仍可作开放 slug 命中自定义源(ADR-0004 修订)。
59
+ - **策展分类法**:精选区分类从功能五分类(市场/工具/界面/搜索/其他)改为**策展五桶**——装机必备 / 崔添翼精选 / iasi自研 / 腾讯轻量云专区 / 观察区(chips 按此序,腾讯轻量云垫后)。分类语义从「插件是什么」转为「为什么值得进精选」;重叠归属按 装机必备 > 崔添翼精选 > 自研 > 腾讯轻量云 优先级归桶,功能属性转 tags 保留检索,旧分类值仍可作开放 slug 命中自定义源(ADR-0004 修订)。
54
60
  - **严筛收录 23→19**:通道五件套(lark/qqbot/weixin/wecom/dingtalk)退出精选——社区层(4,000+ 条)仍收录可装,只是退出策展位;新增收录 **DSH TUI**(崔添翼 9/26 X 推荐:终端 TUI 客户端,`dsh-tui`,走 DSH 客户端契约 ctx.remote);better-sidebar 因优先级归装机必备,以 tag「崔添翼精选」保留 9/27 推荐出处。
55
61
  - **同版本携带**(本地增强随发版收编):desktop 安装 enable 阶段失败自动重试一次(高频装卸/插件树重载竞速实证)+ 失败文案按 packageResult 精确化;市场页「缓存快照」横幅退役——stale 状态由设置页社区卡承接,浏览页不再提示临时缓存状态。
56
62
 
package/lib/cli.js CHANGED
@@ -16,7 +16,7 @@ import { resolve } from 'node:path';
16
16
  const CLI_CATEGORY_LABELS = {
17
17
  essentials: '装机必备',
18
18
  'cui-picks': '崔添翼精选',
19
- 'self-dev': '我的自研',
19
+ 'self-dev': 'iasi自研',
20
20
  'tencent-lighthouse': '腾讯轻量云专区',
21
21
  watchlist: '观察区',
22
22
  };
package/lib/client.js CHANGED
@@ -205,7 +205,7 @@ var init_market_state = __esm({
205
205
  CURATED_LABELS = {
206
206
  essentials: "\u88C5\u673A\u5FC5\u5907",
207
207
  "cui-picks": "\u5D14\u6DFB\u7FFC\u7CBE\u9009",
208
- "self-dev": "\u6211\u7684\u81EA\u7814",
208
+ "self-dev": "iasi\u81EA\u7814",
209
209
  "tencent-lighthouse": "\u817E\u8BAF\u8F7B\u91CF\u4E91\u4E13\u533A",
210
210
  watchlist: "\u89C2\u5BDF\u533A"
211
211
  };
@@ -1175,7 +1175,7 @@ var ZH = {
1175
1175
  "cat.all": "\u5168\u90E8",
1176
1176
  "cat.essentials": "\u88C5\u673A\u5FC5\u5907",
1177
1177
  "cat.cui-picks": "\u5D14\u6DFB\u7FFC\u7CBE\u9009",
1178
- "cat.self-dev": "\u6211\u7684\u81EA\u7814",
1178
+ "cat.self-dev": "iasi\u81EA\u7814",
1179
1179
  "cat.tencent-lighthouse": "\u817E\u8BAF\u8F7B\u91CF\u4E91\u4E13\u533A",
1180
1180
  "cat.watchlist": "\u89C2\u5BDF\u533A",
1181
1181
  "zone.community": "\u793E\u533A",
@@ -1435,7 +1435,7 @@ var EN = {
1435
1435
  "cat.all": "All",
1436
1436
  "cat.essentials": "Essentials",
1437
1437
  "cat.cui-picks": "Cui Picks",
1438
- "cat.self-dev": "Self-dev",
1438
+ "cat.self-dev": "iasi Self-dev",
1439
1439
  "cat.tencent-lighthouse": "Tencent Lighthouse",
1440
1440
  "cat.watchlist": "Watchlist",
1441
1441
  "zone.community": "Community",
@@ -471,14 +471,22 @@ export async function listMarket(cfg = {}, opts = {}, deps = {}) {
471
471
  ? merged.filter((entry) => !isCommunityEntry(entry))
472
472
  : merged;
473
473
  const counts = zeroCounts();
474
- for (const entry of zoned)
474
+ for (const entry of zoned) {
475
475
  counts[entry.category] = (counts[entry.category] ?? 0) + 1;
476
+ // 0.9.17 次级策展桶:跨桶条目在每个归属桶里都计一次(Σcounts 可大于去重总数);
477
+ // 社区条目无 alsoCategories(开放集 string),cast 到 RegistryEntry 侧读取
478
+ const also = entry.alsoCategories;
479
+ for (const extra of also ?? []) {
480
+ counts[extra] = (counts[extra] ?? 0) + 1;
481
+ }
482
+ }
476
483
  const cat = opts.category ?? null;
477
484
  // 相关性搜索(0.7.0 Task 3):归一化分词 + 字段加权评分;0 分不返回;
478
485
  // id 整串精确匹配保证命中(收藏 stale 检测依赖)。
479
486
  const terms = tokenizeSearchText(normalizeSearchText(opts.query ?? ''));
480
487
  const filtered = zoned.filter((entry) => {
481
- if (cat && entry.category !== cat)
488
+ const also = entry.alsoCategories ?? [];
489
+ if (cat && entry.category !== cat && !also.includes(cat))
482
490
  return false;
483
491
  if (terms.length === 0)
484
492
  return true;
@@ -124,7 +124,7 @@ export function parseRegistryAddress(raw) {
124
124
  }
125
125
  // ---------- 严格 v1 校验 ----------
126
126
  const TOP_LEVEL_KEYS = new Set(['version', 'plugins']);
127
- const ENTRY_KEYS = new Set(['id', 'name', 'description', 'category', 'tags', 'source', 'npm', 'github', 'homepage', 'icon', 'verified']);
127
+ const ENTRY_KEYS = new Set(['id', 'name', 'description', 'category', 'tags', 'source', 'npm', 'github', 'homepage', 'icon', 'verified', 'alsoCategories']);
128
128
  /** 精确 semver 判定(与 versions.ts EXACT_VERSION_RE 同语义;接受 prerelease/build,拒绝 range/前缀)。 */
129
129
  const EXACT_SEMVER_RE = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
130
130
  function semverParse(value) {
@@ -307,6 +307,37 @@ export function validateRegistry(raw) {
307
307
  verified = list;
308
308
  }
309
309
  }
310
+ // alsoCategories(0.9.17):可选次级策展桶——值 ∈ CATEGORIES、不含主 category、去重;
311
+ // 空数组 = 无次级归属(不产生键)
312
+ let alsoCategories;
313
+ if (e.alsoCategories !== undefined) {
314
+ if (!Array.isArray(e.alsoCategories)) {
315
+ errors.push(`${where}.alsoCategories: 必须是字符串数组`);
316
+ }
317
+ else {
318
+ const list = [];
319
+ const seenAlso = new Set();
320
+ e.alsoCategories.forEach((c, ci) => {
321
+ const cs = typeof c === 'string' ? c : '';
322
+ if (!CATEGORIES.includes(cs)) {
323
+ errors.push(`${where}.alsoCategories[${ci}]: 无效 ${JSON.stringify(c)}(须为策展桶)`);
324
+ return;
325
+ }
326
+ if (cs === category) {
327
+ errors.push(`${where}.alsoCategories[${ci}]: 与主 category 重复 ${cs}`);
328
+ return;
329
+ }
330
+ if (seenAlso.has(cs)) {
331
+ errors.push(`${where}.alsoCategories[${ci}]: 重复 ${cs}`);
332
+ return;
333
+ }
334
+ seenAlso.add(cs);
335
+ list.push(cs);
336
+ });
337
+ if (list.length > 0)
338
+ alsoCategories = list;
339
+ }
340
+ }
310
341
  plugins.push({
311
342
  id,
312
343
  name,
@@ -319,6 +350,7 @@ export function validateRegistry(raw) {
319
350
  ...(entryHomepage !== undefined ? { homepage: entryHomepage } : {}),
320
351
  ...(entryIcon !== undefined ? { icon: entryIcon } : {}),
321
352
  ...(verified !== undefined ? { verified } : {}),
353
+ ...(alsoCategories !== undefined ? { alsoCategories } : {}),
322
354
  });
323
355
  });
324
356
  return { ok: errors.length === 0, errors, registry: errors.length === 0 ? { version: 1, plugins } : null };
package/lib/tools.js CHANGED
@@ -9,7 +9,7 @@ import { desktopInstallFromRegistry, desktopToggle, desktopUninstall, desktopUpg
9
9
  export const CATEGORY_LABELS = {
10
10
  essentials: '装机必备',
11
11
  'cui-picks': '崔添翼精选',
12
- 'self-dev': '我的自研',
12
+ 'self-dev': 'iasi自研',
13
13
  'tencent-lighthouse': '腾讯轻量云专区',
14
14
  watchlist: '观察区',
15
15
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-m",
3
- "version": "0.9.16",
3
+ "version": "0.9.17",
4
4
  "description": "可自定义收录清单的 DSH 插件市场:收录、安装、卸载、升级一站完成,附 agent 工具与 dshm CLI。",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/registry.json CHANGED
@@ -6,6 +6,9 @@
6
6
  "name": "DSH Marketplace",
7
7
  "description": "自定义清单的 DSH 插件市场,收录/安装/卸载/升级;已适配 DSH 0.2.0-rc.2,支持 web 与 desktop 双 profile,详见仓库。",
8
8
  "category": "essentials",
9
+ "alsoCategories": [
10
+ "self-dev"
11
+ ],
9
12
  "tags": [
10
13
  "市场",
11
14
  "插件管理"
@@ -29,12 +32,14 @@
29
32
  "name": "DSH Better Sidebar",
30
33
  "description": "开放的侧边栏底座,支持三方拓展注册侧边栏页面;内置文件编辑、终端、侧边对话、Git 与子代理页。",
31
34
  "category": "essentials",
35
+ "alsoCategories": [
36
+ "cui-picks"
37
+ ],
32
38
  "tags": [
33
39
  "侧边栏",
34
40
  "文件编辑",
35
41
  "终端",
36
- "Git",
37
- "崔添翼精选"
42
+ "Git"
38
43
  ],
39
44
  "source": "npm",
40
45
  "npm": "dsh-better-sidebar",