dsh-lighthouse 0.3.3 → 0.3.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.
@@ -110,7 +110,9 @@ async function main() {
110
110
  const bits = [];
111
111
  bits.push(local.available === true ? `本地 ${local.version ?? '?'}` : '本地 读不到');
112
112
  bits.push(github.exists === true ? `star ${github.stars}` : 'GitHub 无/读不到');
113
- bits.push(market.listed === true ? `市场已收录(${market.downloads} 下载)` : (market.available === true ? '市场未收录' : '市场读不到'));
113
+ bits.push(market.listed !== true
114
+ ? (market.available === true ? '市场未收录' : '市场读不到')
115
+ : (market.downloads === null || market.downloads === undefined ? '市场已收录(下载数暂无)' : `市场已收录(${market.downloads} 下载)`));
114
116
  if (github.pr) bits.push(`PR #${github.pr.number} ${github.pr.mergedAt ? '已合并' : github.pr.state}`);
115
117
  console.log(` · ${work.name}:${bits.join('|')}`);
116
118
  }
package/client.js CHANGED
@@ -160,7 +160,7 @@ window.__ModuleLoader__.load({ id: "dsh-lighthouse", factory: (require) => {
160
160
  released ? "✅ 已发布" : (gh.exists === false ? "❌ 仓库不存在" : "❌ 读不到仓库")))
161
161
  stateLine.push(h("span", { key: "mk", className: "lh-state" },
162
162
  listed
163
- ? "✅ 市场已收录" + (market.downloads !== undefined ? "(下载 " + market.downloads + ")" : "")
163
+ ? "✅ 市场已收录" + (market.downloads === null || market.downloads === undefined ? "(下载数暂无)" : "(下载 " + market.downloads + ")")
164
164
  : (market.available === true ? "⏳ 收录中" : "❌ 市场读不到")))
165
165
  if (pr) {
166
166
  const waited = (Date.now() - Date.parse(pr.createdAt)) / 3600000
package/lib/collect.js CHANGED
@@ -245,10 +245,14 @@ export function marketFactOf(registry, name) {
245
245
  const hit = list.find((item) => item?.name === name);
246
246
  if (!hit) return { available: true, listed: false, registryUpdated: registry.updated ?? null, registryCount: registry.count ?? list.length };
247
247
  const categories = Array.isArray(hit.category) ? hit.category : [];
248
- const downloads = Number(hit.downloads ?? 0);
248
+ // 市场的 downloads 只统计发到 npm 的包;没发 npm 的条目字段是缺的(不是 0)。
249
+ // 把"没有数据"当成 0 会把它排到真有包但没人用的后面,也会显示成"下载 0"。
250
+ const toCount = (v) => (v === null || v === undefined || v === '' || Number.isNaN(Number(v)) ? null : Number(v));
251
+ const downloads = toCount(hit.downloads);
249
252
  const sameCat = list
250
253
  .filter((item) => Array.isArray(item?.category) && categories.some((c) => item.category.includes(c)))
251
- .map((item) => Number(item.downloads ?? 0))
254
+ .map((item) => toCount(item.downloads))
255
+ .filter((v) => v !== null)
252
256
  .sort((a, b) => b - a);
253
257
  return {
254
258
  available: true,
@@ -265,7 +269,7 @@ export function marketFactOf(registry, name) {
265
269
  /** 市场条目页(可以点进去看的那个)—— 没收录时没有。 */
266
270
  page: typeof hit.page === 'string' && hit.page !== '' ? hit.page : null,
267
271
  descriptionZh: typeof hit.description?.zh === 'string' ? hit.description.zh : null,
268
- rankInCategory: sameCat.indexOf(downloads) + 1,
272
+ rankInCategory: downloads === null ? null : sameCat.indexOf(downloads) + 1,
269
273
  categorySize: sameCat.length,
270
274
  };
271
275
  }
@@ -435,13 +439,15 @@ export async function collectAll(fleet, deps = {}) {
435
439
  const [local, github, npm] = await Promise.all([
436
440
  collectLocal(work),
437
441
  collectGitHub(work, { owner: fleet.owner, token, fetchImpl, prIndex }),
438
- includeNpm ? collectNpm(work.name, { fetchImpl }) : Promise.resolve({ available: false, reason: '已跳过' }),
442
+ // npm 包名可以和目录/GitHub 仓库名不同(例:仓库 dsh-tool-gate,npm 包 dsh-ctx-gate)。
443
+ // 名册里给了 work.npm 就用它,否则退回 work.name。
444
+ includeNpm ? collectNpm(work.npm ?? work.name, { fetchImpl }) : Promise.resolve({ available: false, reason: '已跳过' }),
439
445
  ]);
440
446
  const market = marketFactOf(registry, work.name);
441
447
  // 直达链接:名册显式给的优先;否则 GitHub 仓库;npm 与市场页面能确定才给(不确定就不编)。
442
448
  const links = {
443
449
  github: work.url ?? `https://github.com/${fleet.owner}/${work.repo}`,
444
- npm: `https://www.npmjs.com/package/${work.name}`,
450
+ npm: `https://www.npmjs.com/package/${work.npm ?? work.name}`,
445
451
  market: market.listed === true ? market.page : null,
446
452
  };
447
453
  return { work, local, github, market, npm, links };
@@ -469,7 +475,7 @@ export async function collectAll(fleet, deps = {}) {
469
475
  works: works.length,
470
476
  published: works.filter((w) => w.github.exists === true).length,
471
477
  listed: works.filter((w) => w.market?.listed === true).length,
472
- totalDownloads: works.reduce((sum, w) => sum + (w.market?.listed === true ? Number(w.market.downloads ?? 0) : 0), 0),
478
+ totalDownloads: works.reduce((sum, w) => sum + (w.market?.listed === true && w.market.downloads !== null && w.market.downloads !== undefined ? Number(w.market.downloads) : 0), 0),
473
479
  totalStars: works.reduce((sum, w) => sum + Number(w.github.stars ?? 0), 0),
474
480
  openPrs: waiting.length,
475
481
  longestWaitHours: waiting.length > 0 ? Math.max(...waiting) : null,
package/lib/fleet.js CHANGED
@@ -86,6 +86,8 @@ export function validateFleet(data) {
86
86
  nameZh: typeof work.nameZh === 'string' && work.nameZh.trim() !== '' ? work.nameZh.trim() : null,
87
87
  /** 直达链接(不填就按 owner/repo 生成 GitHub 地址)。 */
88
88
  url: typeof work.url === 'string' && work.url.trim() !== '' ? work.url.trim() : null,
89
+ /** npm 包名(仓库名与包名不一定一样,例:仓库 dsh-tool-gate → 包 dsh-ctx-gate)。不填就用 name 查。 */
90
+ npm: typeof work.npm === 'string' && work.npm.trim() !== '' ? work.npm.trim() : null,
89
91
  /** 额外的发布源(例如 Gitee / GitLab / npm),形如 { platform, url }。 */
90
92
  mirrors: Array.isArray(work.mirrors)
91
93
  ? work.mirrors
package/lib/index.js CHANGED
@@ -359,7 +359,7 @@ export function apply(ctx, config) {
359
359
  /* 没有 web server 的表面(例如纯 CLI):观察区缺席,其它能力不受影响 */
360
360
  }
361
361
 
362
- if (cfg.announceToAgent !== false && ctx.systemPrompt !== undefined
362
+ if (cfg.announceToAgent === true && ctx.systemPrompt !== undefined
363
363
  && typeof ctx.systemPrompt.section === 'function') {
364
364
  disposers.push(ctx.systemPrompt.section({
365
365
  name: 'plugin:lighthouse',
package/lib/render.js CHANGED
@@ -124,7 +124,10 @@ export function renderText(report) {
124
124
  bits.push(local.available === true ? `本地 ${local.version ?? '?'} / ${local.files ?? '?'} 文件${local.hasSmoke ? ' / 有自测' : ''}` : `本地 **读不到**(${local.reason ?? '?'})`);
125
125
  bits.push(github.exists === true ? `GitHub star ${github.stars} / 最后推送 ${shortTime(github.pushedAt)}` : (github.exists === false ? 'GitHub **没有仓库**' : `GitHub **读不到**(${github.reason ?? '?'})`));
126
126
  if (market.listed === true) {
127
- bits.push(`市场 **已收录**(下载 ${market.downloads}${market.rankInCategory ? `,同类第 ${market.rankInCategory}/${market.categorySize}` : ''})`);
127
+ // 没下载数 ≠ 没发 npm:下载字段市场侧可能不统计。npm 发没发看下面那行 npm 事实,不在这里推。
128
+ bits.push(market.downloads === null || market.downloads === undefined
129
+ ? '市场 **已收录**(没有下载数据)'
130
+ : `市场 **已收录**(下载 ${market.downloads}${market.rankInCategory ? `,同类第 ${market.rankInCategory}/${market.categorySize}` : ''})`);
128
131
  } else if (market.available === true) {
129
132
  bits.push('市场 **未收录**');
130
133
  } else {
@@ -147,7 +150,10 @@ export function renderText(report) {
147
150
 
148
151
  if (compact) {
149
152
  // 一行一个:名字(中文) · 版本 · star · 市场/PR 状态(详情与链接看卡片)
150
- const marketText = market.listed === true ? `已收录 ${market.downloads}↓` : (market.available === true ? '未收录' : '市场读不到');
153
+ const dl = market.downloads === null || market.downloads === undefined ? '下载数暂无' : `${market.downloads}↓`;
154
+ const marketText = market.listed !== true
155
+ ? (market.available === true ? '未收录' : '市场读不到')
156
+ : (npm?.published === true ? `已收录 · ${dl}` : (npm?.available === true ? `已收录 · ${dl} · npm 未发` : `已收录 · ${dl}`));
151
157
  const prShort = github.pr
152
158
  ? (github.pr.mergedAt ? `#${github.pr.number} 已合并` : (github.pr.state === 'open' ? `#${github.pr.number} 等 ${hoursText((Date.now() - Date.parse(github.pr.createdAt)) / 3600000)}` : `#${github.pr.number} ${github.pr.state}`))
153
159
  : '无 PR';
@@ -183,7 +189,7 @@ function dot(kind) {
183
189
  */
184
190
  function renderGrid(ordered) {
185
191
  const rows = ordered.map((item) => {
186
- const { work, local, github, market } = item;
192
+ const { work, local, github, market, npm } = item;
187
193
  const key = urgencyOf(item);
188
194
  const pr = github?.pr;
189
195
  const prText = pr
@@ -193,9 +199,12 @@ function renderGrid(ordered) {
193
199
  ? `${dot('warn')} #${pr.number} 等 ${hoursText((Date.now() - Date.parse(pr.createdAt)) / 3600000)}`
194
200
  : `#${pr.number} ${esc(pr.state)}`))
195
201
  : '<span class="bad">没有 PR</span>';
196
- const marketText = market.listed === true
197
- ? `${dot('good')} 已收录 · ${market.downloads}↓`
198
- : (market.available === true ? `${dot('warn')} 未收录` : '<span class="bad">读不到</span>');
202
+ const dlGrid = market.downloads === null || market.downloads === undefined ? '下载数暂无' : `${market.downloads}↓`;
203
+ const marketText = market.listed !== true
204
+ ? (market.available === true ? `${dot('warn')} 未收录` : '<span class="bad">读不到</span>')
205
+ : (npm?.available === true && npm.published !== true
206
+ ? `${dot('warn')} 已收录 · ${dlGrid} · npm 未发`
207
+ : `${dot('good')} 已收录 · ${dlGrid}`);
199
208
  const ghText = github.exists === true
200
209
  ? `${dot('idle')} star ${github.stars}`
201
210
  : (github.exists === false ? '<span class="bad">仓库不存在</span>' : '<span class="bad">读不到</span>');
@@ -253,7 +262,9 @@ export function renderHtml(report) {
253
262
 
254
263
  rows.push(`<div class="row"><span class="k">市场</span><span class="v">${
255
264
  listed
256
- ? `${dot('good')} 已收录 · 下载 <b>${market.downloads}</b>${market.rankInCategory ? ` · 同类 ${market.rankInCategory}/${market.categorySize}` : ''}`
265
+ ? (market.downloads === null || market.downloads === undefined
266
+ ? `${dot('warn')} 已收录 · 下载数暂无`
267
+ : `${dot('good')} 已收录 · 下载 <b>${market.downloads}</b>${market.rankInCategory ? ` · 同类 ${market.rankInCategory}/${market.categorySize}` : ''}`)
257
268
  : (market.available === true ? `${dot('warn')} 还没收录` : `<span class="bad">读不到(${esc(market.reason ?? '')})</span>`)
258
269
  }</span></div>`);
259
270
 
@@ -272,6 +283,10 @@ export function renderHtml(report) {
272
283
 
273
284
  if (npm?.published === true) {
274
285
  rows.push(`<div class="row"><span class="k">npm</span><span class="v">${dot('good')} 有包 ${esc(npm.version ?? '')}</span></div>`);
286
+ } else if (npm?.available === true) {
287
+ rows.push(`<div class="row"><span class="k">npm</span><span class="v">${dot('warn')} registry 上没有这个包</span></div>`);
288
+ } else if (npm?.reason) {
289
+ rows.push(`<div class="row"><span class="k">npm</span><span class="v">${dot('idle')} 没查到(${esc(npm.reason)})</span></div>`);
275
290
  }
276
291
 
277
292
  const head = listed ? 'listed' : (github.exists === true ? 'shipped' : 'local');
package/package.json CHANGED
@@ -1,93 +1,93 @@
1
- {
2
- "name": "dsh-lighthouse",
3
- "version": "0.3.3",
4
- "description": "一屏看清每个作品现在什么样:本地版本、GitHub star、市场收没收、下载量和同类排名,还能落一张可截图的卡片。 One screen for every work you have shipped: local version, GitHub stars, market listing, downloads and category rank, plus a ready-to-screenshot card.",
5
- "type": "module",
6
- "main": "lib/index.js",
7
- "bin": {
8
- "dsh-lighthouse": "bin/dsh-lighthouse.mjs"
9
- },
10
- "exports": {
11
- ".": "./lib/index.js",
12
- "./fleet": "./lib/fleet.js",
13
- "./collect": "./lib/collect.js",
14
- "./render": "./lib/render.js",
15
- "./status-route": "./lib/status-route.js",
16
- "./client": "./client.js",
17
- "./package.json": "./package.json"
18
- },
19
- "files": [
20
- "lib",
21
- "bin",
22
- "client.js",
23
- "cordis.patch.yml",
24
- "README.md",
25
- "LICENSE"
26
- ],
27
- "keywords": [
28
- "deepseek-harness",
29
- "dsh",
30
- "dsh-plugin",
31
- "dashboard",
32
- "release-tracker",
33
- "market-registry",
34
- "downloads",
35
- "watchers",
36
- "pull-request",
37
- "observability",
38
- "作品看板",
39
- "观察区"
40
- ],
41
- "engines": {
42
- "node": ">=18"
43
- },
44
- "scripts": {
45
- "test": "node test/smoke.mjs"
46
- },
47
- "publishConfig": {
48
- "access": "public"
49
- },
50
- "license": "MIT",
51
- "repository": {
52
- "type": "git",
53
- "url": "git+https://github.com/7gzgn/dsh-lighthouse.git"
54
- },
55
- "homepage": "https://github.com/7gzgn/dsh-lighthouse#readme",
56
- "bugs": {
57
- "url": "https://github.com/7gzgn/dsh-lighthouse/issues"
58
- },
59
- "dsh": {
60
- "compatibility": {
61
- "dshReleases": {
62
- "0.2.0-rc.2": "compatible",
63
- "0.2.1-rc.2": "compatible"
64
- }
65
- },
66
- "bundle": {
67
- "patch": "./cordis.patch.yml"
68
- },
69
- "client": {
70
- "platform": "web",
71
- "inject": [
72
- "@deepseek-ai/dsh-client-ui-slots"
73
- ]
74
- }
75
- },
76
- "peerDependencies": {
77
- "@deepseek-ai/cordis": ">=4.0.4 <5.0.0",
78
- "@deepseek-ai/dsh-client-ui-slots": ">=0.2.0-rc.2 <0.3.0-0",
79
- "@deepseek-ai/dsh-system-prompt": ">=0.2.0-rc.2 <0.3.0-0",
80
- "@deepseek-ai/dsh-tools": ">=0.2.0-rc.2 <0.3.0-0"
81
- },
82
- "peerDependenciesMeta": {
83
- "@deepseek-ai/dsh-client-ui-slots": {
84
- "optional": true
85
- },
86
- "@deepseek-ai/dsh-system-prompt": {
87
- "optional": true
88
- },
89
- "@deepseek-ai/dsh-tools": {
90
- "optional": true
91
- }
92
- }
93
- }
1
+ {
2
+ "name": "dsh-lighthouse",
3
+ "version": "0.3.4",
4
+ "description": "一屏看清每个作品现在什么样:本地版本、GitHub star、市场收没收、下载量和同类排名,还能落一张可截图的卡片。 One screen for every work you have shipped: local version, GitHub stars, market listing, downloads and category rank, plus a ready-to-screenshot card.",
5
+ "type": "module",
6
+ "main": "lib/index.js",
7
+ "bin": {
8
+ "dsh-lighthouse": "bin/dsh-lighthouse.mjs"
9
+ },
10
+ "exports": {
11
+ ".": "./lib/index.js",
12
+ "./fleet": "./lib/fleet.js",
13
+ "./collect": "./lib/collect.js",
14
+ "./render": "./lib/render.js",
15
+ "./status-route": "./lib/status-route.js",
16
+ "./client": "./client.js",
17
+ "./package.json": "./package.json"
18
+ },
19
+ "files": [
20
+ "lib",
21
+ "bin",
22
+ "client.js",
23
+ "cordis.patch.yml",
24
+ "README.md",
25
+ "LICENSE"
26
+ ],
27
+ "keywords": [
28
+ "deepseek-harness",
29
+ "dsh",
30
+ "dsh-plugin",
31
+ "dashboard",
32
+ "release-tracker",
33
+ "market-registry",
34
+ "downloads",
35
+ "watchers",
36
+ "pull-request",
37
+ "observability",
38
+ "作品看板",
39
+ "观察区"
40
+ ],
41
+ "engines": {
42
+ "node": ">=18"
43
+ },
44
+ "scripts": {
45
+ "test": "node test/smoke.mjs"
46
+ },
47
+ "publishConfig": {
48
+ "access": "public"
49
+ },
50
+ "license": "MIT",
51
+ "repository": {
52
+ "type": "git",
53
+ "url": "git+https://github.com/7gzgn/dsh-lighthouse.git"
54
+ },
55
+ "homepage": "https://github.com/7gzgn/dsh-lighthouse#readme",
56
+ "bugs": {
57
+ "url": "https://github.com/7gzgn/dsh-lighthouse/issues"
58
+ },
59
+ "dsh": {
60
+ "compatibility": {
61
+ "dshReleases": {
62
+ "0.2.0-rc.2": "compatible",
63
+ "0.2.1-rc.2": "compatible"
64
+ }
65
+ },
66
+ "bundle": {
67
+ "patch": "./cordis.patch.yml"
68
+ },
69
+ "client": {
70
+ "platform": "web",
71
+ "inject": [
72
+ "@deepseek-ai/dsh-client-ui-slots"
73
+ ]
74
+ }
75
+ },
76
+ "peerDependencies": {
77
+ "@deepseek-ai/cordis": ">=4.0.4 <5.0.0",
78
+ "@deepseek-ai/dsh-client-ui-slots": ">=0.2.0-rc.2 <0.3.0-0",
79
+ "@deepseek-ai/dsh-system-prompt": ">=0.2.0-rc.2 <0.3.0-0",
80
+ "@deepseek-ai/dsh-tools": ">=0.2.0-rc.2 <0.3.0-0"
81
+ },
82
+ "peerDependenciesMeta": {
83
+ "@deepseek-ai/dsh-client-ui-slots": {
84
+ "optional": true
85
+ },
86
+ "@deepseek-ai/dsh-system-prompt": {
87
+ "optional": true
88
+ },
89
+ "@deepseek-ai/dsh-tools": {
90
+ "optional": true
91
+ }
92
+ }
93
+ }