dsh-m 0.6.0 → 0.8.4

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/lib/tools.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { defineTool } from '@deepseek-ai/dsh-tools';
2
2
  import { installTimeoutMs } from './core/env.js';
3
3
  import { installFromRegistry, listInstalledWithMeta, listMarket, uninstallPlugin, upgradePlugin, InstallGuardError, } from './core/market.js';
4
+ import { COMMUNITY_CATEGORY_LABELS } from './core/community.js';
4
5
  import { appExitFromContext, scheduleRestart } from './core/restart.js';
5
6
  import { togglePlugin as coreTogglePlugin } from './core/toggle.js';
6
7
  export const CATEGORY_LABELS = {
@@ -10,6 +11,12 @@ export const CATEGORY_LABELS = {
10
11
  search: '搜索',
11
12
  other: '其他',
12
13
  };
14
+ /** 分类中文标签(0.7.0 Task 5):精选 5 类 + 社区已知标签(单一事实源 COMMUNITY_CATEGORY_LABELS);未知 slug 原样。 */
15
+ function categoryLabelOf(category) {
16
+ return (CATEGORY_LABELS[category] ??
17
+ COMMUNITY_CATEGORY_LABELS[category] ??
18
+ category);
19
+ }
13
20
  /** 工具 deadline 对齐(M1 Task 7):search 45s(core 44s)、list/outdated 65s(core 60s + 5s 回包余量)。 */
14
21
  const SEARCH_TOOL_TIMEOUT_MS = 45_000;
15
22
  const SEARCH_CORE_DEADLINE_MS = 44_000;
@@ -63,15 +70,19 @@ export function registerTools(ctx, cfg, deps = {}) {
63
70
  const getService = () => ctx.get?.('pluginManager');
64
71
  ctx.tools.register(defineTool({
65
72
  name: 'dshm_search',
66
- description: 'Search your personal DSH plugin marketplace (dsh-m) and show clickable plugin cards. ALWAYS call this instead of web_search or bash when the user wants to find/recommend/browse their curated DSH plugins (插件). Call EXACTLY ONCE per user message; extract a real keyword (主题, 搜索) rather than pasting the whole sentence. Omit query to browse all listings. After cards appear, reply with AT MOST one short sentence. Do not print install commands.',
73
+ description: 'Search the DSH plugin marketplace (dsh-m) and show clickable plugin cards. ALWAYS call this instead of web_search or bash when the user wants to find/recommend/browse DSH plugins (插件). Call EXACTLY ONCE per user message; extract a real keyword (主题, 搜索) rather than pasting the whole sentence. Dual catalog: ~22 hand-curated 精选 entries plus a 4,000+ community catalog — default searches all; pass source="community" or "primary" to zone in. Returns 10 cards by default; use offset (take nextOffset from the result) for more batches. After cards appear, reply with AT MOST one short sentence. Do not print install commands.',
67
74
  parameters: {
68
- query: { type: 'string', description: 'Main keyword, e.g. 主题 or 搜索. Optional.' },
75
+ query: { type: 'string', description: 'Main keyword, e.g. 主题 or 搜索. Optional; omit to browse.' },
69
76
  category: {
70
77
  type: 'string',
71
78
  description: `Optional category: curated ${Object.keys(CATEGORY_LABELS).join('/')} or any community slug ([a-z0-9-]{1,32}, e.g. theme/memory/git).`,
72
79
  },
73
- limit: { type: 'number', description: 'Cards in this batch. Default all (registry is curated & small).' },
74
- primary_only: { type: 'boolean', description: '只看主清单(排除社区条目). Optional.' },
80
+ source: {
81
+ type: 'string',
82
+ description: 'Zone filter: "community" (4,000+ community catalog), "primary" (hand-curated 精选), or "all" (default).',
83
+ },
84
+ limit: { type: 'number', description: 'Cards in this batch. Default 10, clamp 1-80.' },
85
+ offset: { type: 'number', description: 'Pagination offset (0-based). Pass nextOffset from the previous result to fetch the next batch.' },
75
86
  },
76
87
  output: {
77
88
  schema: { type: 'object', additionalProperties: true },
@@ -80,7 +91,7 @@ export function registerTools(ctx, cfg, deps = {}) {
80
91
  },
81
92
  presentCall: (args) => ({
82
93
  card: 'generic',
83
- title: `DSH 市场 · ${String(args.query || args.category || '浏览')}`,
94
+ title: `DSH 市场 · ${String(args.query || args.category || (args.source && args.source !== 'all' ? args.source : '') || '浏览')}`,
84
95
  kind: 'search',
85
96
  content: [],
86
97
  }),
@@ -99,16 +110,24 @@ export function registerTools(ctx, cfg, deps = {}) {
99
110
  else
100
111
  throw new Error(`非法分类: ${categoryRaw}(需精选分类或 [a-z0-9-]{1,32} slug)`);
101
112
  }
113
+ // 分区参数(0.7.0 Task 5):与 GUI 分区对齐;primary_only 已删除(D6a 允许破坏性变更)
114
+ const sourceRaw = typeof args.source === 'string' ? args.source.trim() : '';
115
+ if (sourceRaw !== '' && sourceRaw !== 'primary' && sourceRaw !== 'community' && sourceRaw !== 'all') {
116
+ throw new Error(`非法 source: ${sourceRaw}(需 primary/community/all)`);
117
+ }
118
+ const source = sourceRaw === '' ? 'all' : sourceRaw;
102
119
  const rawLimit = Number(args.limit);
103
- const limit = Number.isFinite(rawLimit) && rawLimit > 0 ? clamp(rawLimit, 1, 80) : undefined;
120
+ const limit = Number.isFinite(rawLimit) && rawLimit > 0 ? clamp(rawLimit, 1, 80) : 10;
121
+ const rawOffset = Number(args.offset);
122
+ const offset = Number.isFinite(rawOffset) && rawOffset > 0 ? Math.floor(rawOffset) : 0;
104
123
  // metadata-only:agent 卡片不需要 latest;与 Host GUI 共用 host namespace;
105
124
  // deadline 44s 是本 waiter 的绝对上限(工具 timeout 45s 先到兜底)
106
125
  const result = await m.listMarket(cfg, {
107
126
  query: String(args.query || ''),
108
127
  category,
109
- offset: 0,
128
+ source,
129
+ offset,
110
130
  limit,
111
- primaryOnly: args.primary_only === true,
112
131
  withLatest: false,
113
132
  namespace: 'host',
114
133
  deadlineMs: SEARCH_CORE_DEADLINE_MS,
@@ -120,9 +139,14 @@ export function registerTools(ctx, cfg, deps = {}) {
120
139
  if (!result.installedComplete && result.items.length > 0) {
121
140
  throw new Error('读取 web profile 安装状态失败,安装标注不可用;请稍后重试');
122
141
  }
142
+ const shown = result.items.length;
143
+ const nextOffset = offset + shown < result.total ? offset + shown : null;
123
144
  return cloneJson({
124
145
  query: String(args.query || ''),
125
146
  category,
147
+ source,
148
+ offset,
149
+ nextOffset,
126
150
  total: result.total,
127
151
  registry: summaryOf(result.registryState),
128
152
  community: communityToolSummary(result.community),
@@ -131,6 +155,7 @@ export function registerTools(ctx, cfg, deps = {}) {
131
155
  name: e.name,
132
156
  description: e.description,
133
157
  category: e.category,
158
+ categoryLabel: categoryLabelOf(e.category),
134
159
  tags: e.tags,
135
160
  source: e.source,
136
161
  npm: e.npm,
@@ -139,6 +164,9 @@ export function registerTools(ctx, cfg, deps = {}) {
139
164
  installed: e.installed,
140
165
  installedPkg: e.installedPkg,
141
166
  installedVersion: e.installedVersion,
167
+ community: e.community === true,
168
+ downloads: e.downloads ?? null,
169
+ stars: e.stars ?? null,
142
170
  })),
143
171
  });
144
172
  },
@@ -427,13 +455,20 @@ function buildsNote(out) {
427
455
  function renderSearch(out) {
428
456
  if (!out.items?.length)
429
457
  return '收录清单中没有匹配的插件。对用户只说一句:没找到,可以换个词再搜。不要写长文。';
458
+ const offset = out.offset ?? 0;
430
459
  const lines = out.items.map((it, i) => {
431
460
  const inst = it.installed ? `(已安装 v${it.installedVersion || '?'})` : '';
432
- return `${i + 1}. ${it.name} · ${it.id}${inst} · ${CATEGORY_LABELS[it.category] || it.category}`;
461
+ const zone = it.community === true ? '[社区]' : '';
462
+ return `${i + 1}. ${it.name} · ${it.id}${zone}${inst} · ${it.categoryLabel || it.category}`;
433
463
  });
464
+ // 翻页尾行(0.7.0 Task 5):nextOffset 为空 = 已到末尾
465
+ const pager = typeof out.nextOffset === 'number'
466
+ ? `共 ${out.total ?? out.items.length} 条 · 已显示 ${offset + 1}–${offset + out.items.length} · 传 offset=${out.nextOffset} 翻页`
467
+ : `共 ${out.total ?? out.items.length} 条 · 已到末尾`;
434
468
  return [
435
469
  `插件卡片已展示 ${out.items.length}${out.total && out.total > out.items.length ? `/${out.total}` : ''} 条(内部序号,禁止复述给用户):`,
436
470
  lines.join('\n'),
471
+ pager,
437
472
  '对用户最多回一句短话。禁止清单和长文。用户点名安装时才调 dshm_install(id)。',
438
473
  ].join('\n');
439
474
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-m",
3
- "version": "0.6.0",
3
+ "version": "0.8.4",
4
4
  "description": "可自定义收录清单的 DSH 插件市场:收录、安装、卸载、升级一站完成,附 agent 工具与 dshm CLI。",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -63,7 +63,7 @@
63
63
  },
64
64
  "peerDependencies": {
65
65
  "@deepseek-ai/cordis": "*",
66
- "@deepseek-ai/dsh-tools": "*",
66
+ "@deepseek-ai/dsh-tools": "^0.1.7-rc.2 || ^0.2.0-rc.1 || >=0.2.0",
67
67
  "@deepseek-ai/schemastery": "*",
68
68
  "react": "^18.2.0"
69
69
  },
package/registry.json CHANGED
@@ -4,7 +4,7 @@
4
4
  {
5
5
  "id": "dsh-m",
6
6
  "name": "DSH Marketplace",
7
- "description": "自定义清单的 DSH 插件市场,收录/安装/卸载/升级;已适配 0.1.2-rc.1、0.1.5-rc.1/rc.2 与 0.1.7-rc.1/rc.2,详见仓库。",
7
+ "description": "自定义清单的 DSH 插件市场,收录/安装/卸载/升级;已适配 0.1.5-rc.1 至 0.2.0-rc.1/rc.2 各代,详见仓库。",
8
8
  "category": "market",
9
9
  "tags": [
10
10
  "市场",
@@ -15,7 +15,9 @@
15
15
  "0.1.5-rc.1",
16
16
  "0.1.5-rc.2",
17
17
  "0.1.7-rc.1",
18
- "0.1.7-rc.2"
18
+ "0.1.7-rc.2",
19
+ "0.2.0-rc.1",
20
+ "0.2.0-rc.2"
19
21
  ],
20
22
  "source": "npm",
21
23
  "npm": "dsh-m",
@@ -25,7 +27,7 @@
25
27
  {
26
28
  "id": "dsh-skins",
27
29
  "name": "DSH Skins",
28
- "description": "DSH Web 皮肤插件:多套品牌皮肤侧栏热切换,一键回到官方界面。已适配 0.1.7-rc.2,详见仓库。",
30
+ "description": "DSH Web 皮肤插件:多套品牌皮肤侧栏热切换,一键回到官方界面。已适配 0.1.7-rc.2 与 0.2.0-rc.1,详见仓库。",
29
31
  "category": "ui",
30
32
  "tags": [
31
33
  "皮肤",
@@ -34,7 +36,8 @@
34
36
  ],
35
37
  "verified": [
36
38
  "0.1.2-rc.1",
37
- "0.1.7-rc.2"
39
+ "0.1.7-rc.2",
40
+ "0.2.0-rc.1"
38
41
  ],
39
42
  "source": "npm",
40
43
  "npm": "@iasiv5/dsh-skins",
@@ -44,7 +47,7 @@
44
47
  {
45
48
  "id": "dsh-copilot-auth",
46
49
  "name": "DSH Copilot Auth",
47
- "description": "为内置 Copilot 提供方补登录/注销设置页与开箱路由;模型目录兜底不覆盖定制。适配 0.1.7-rc.2,旧版用 1.1.x。",
50
+ "description": "为内置 Copilot 提供方补登录/注销设置页与开箱路由;模型目录兜底不覆盖定制。适配 0.1.7-rc.2 与 0.2.0-rc.1,旧版用 1.1.x。",
48
51
  "category": "tools",
49
52
  "tags": [
50
53
  "Copilot",
@@ -52,7 +55,8 @@
52
55
  "模型接入"
53
56
  ],
54
57
  "verified": [
55
- "0.1.7-rc.2"
58
+ "0.1.7-rc.2",
59
+ "0.2.0-rc.1"
56
60
  ],
57
61
  "source": "npm",
58
62
  "npm": "@inventec/dsh-copilot-auth",
@@ -62,7 +66,7 @@
62
66
  {
63
67
  "id": "dsh-skip-browser-auth",
64
68
  "name": "DSH Skip Browser Auth",
65
- "description": "替换官方 Connection 提供方跳过 BrowserAuth,免输 Token;已适配 0.1.2-rc.1、0.1.5-rc.1/rc.2 与 0.1.7-rc.1/rc.2。",
69
+ "description": "替换官方 Connection 跳过 BrowserAuth,免 Token;已适配 0.1.2-rc.1、0.1.5-rc.1/rc.2、0.1.7-rc.1/rc.2 与 0.2.0-rc.1/rc.2。",
66
70
  "category": "tools",
67
71
  "tags": [
68
72
  "BrowserAuth",
@@ -74,7 +78,9 @@
74
78
  "0.1.5-rc.1",
75
79
  "0.1.5-rc.2",
76
80
  "0.1.7-rc.1",
77
- "0.1.7-rc.2"
81
+ "0.1.7-rc.2",
82
+ "0.2.0-rc.1",
83
+ "0.2.0-rc.2"
78
84
  ],
79
85
  "source": "npm",
80
86
  "npm": "@iasiv5/dsh-skip-browser-auth",
@@ -364,6 +370,22 @@
364
370
  "npm": "dsh-chat-manager",
365
371
  "github": "WSL043/dsh-chat-manager",
366
372
  "homepage": "https://github.com/WSL043/dsh-chat-manager"
373
+ },
374
+ {
375
+ "id": "dsh-context",
376
+ "name": "DSH Context",
377
+ "description": "上下文透视:Context 仪表盘、侧栏面板与 /context 命令,查看上下文组成、演进趋势与压缩剪枝等事件,支持跨会话用量统计。",
378
+ "category": "ui",
379
+ "tags": [
380
+ "上下文",
381
+ "Token 统计",
382
+ "可视化",
383
+ "仪表盘"
384
+ ],
385
+ "source": "npm",
386
+ "npm": "dsh-context",
387
+ "github": "bowenliang123/dsh-context",
388
+ "homepage": "https://github.com/bowenliang123/dsh-context"
367
389
  }
368
390
  ]
369
391
  }