@morehao/dsh-github-trending 0.7.7 → 0.7.9
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/CHANGELOG.md +30 -0
- package/README.md +9 -9
- package/client.js +58 -51
- package/lib/{chunk-RB6W2PK7.js → chunk-YJ5GF3MW.js} +70 -121
- package/lib/index.js +1 -2
- package/lib/internal.d.ts +18 -37
- package/lib/internal.js +5 -5
- package/package.json +2 -2
- package/lib/chunk-R7BK7SJK.js +0 -121
- package/lib/exec-VMDINNX5.js +0 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [v0.7.9] - 2026-11-01
|
|
4
|
+
|
|
5
|
+
> 内部重构:把重复的通用实现收敛到共享底座 `@morehao/dsh-plugin-kit@^0.3.1`。对外接口与业务语义保持不变。
|
|
6
|
+
|
|
7
|
+
### 改进 — 迁移到 dsh-plugin-kit 0.3.1
|
|
8
|
+
|
|
9
|
+
- **子进程执行**:`src/core/exec.ts` 收敛到 kit `./exec` 的 `spawnCollect` / `sanitizedEnv`,删除本地实现;握手阶段改为判 `result.error` 抛 `CORE_SPAWN_FAILED`(kit 的 `spawnCollect` 永不 reject)。
|
|
10
|
+
- **插件身份**:`plugin-info.ts` 的仓库地址规范化与读包改用 kit `./github` + `./meta`(`createPluginMeta`),保留 `readPluginInfo` / `normalizeRepositoryUrl` 导出面与返回形状。
|
|
11
|
+
- **HTTP 路由**:`routes.ts` 的 `sendJson` / `readBody` / 头校验改用 kit `./http` 的 `createRouteHandler`;业务 `dispatch`、`IpcError` 错误码与 `PluginUpdateError→409` 映射保持不变,错误码翻译仍留在插件侧。
|
|
12
|
+
- 对外路由响应形状、读包字段、错误码/映射均无变化(行为等价)。
|
|
13
|
+
|
|
14
|
+
## [v0.7.8] - 2026-11-01
|
|
15
|
+
|
|
16
|
+
> 统一「订阅」口径:这个功能不再叫「发版」,运行记录、概览、设置、订阅页与提示文案一致;顺带修好运行记录里的类型胶囊样式。
|
|
17
|
+
|
|
18
|
+
### 改进 — 全站口径统一为「订阅」
|
|
19
|
+
|
|
20
|
+
- **运行记录**:类型胶囊与筛选由「发版」改为「订阅」;空态改为「还没有订阅运行记录」,展开说明改为「订阅运行只做订阅检查与变更文档渲染」。
|
|
21
|
+
- **概览 / 设置 / 订阅页**:「发版订阅」统一为「订阅」(速览卡、设置分区、用量卡、分区跳转);速览 KPI「新发版」改为「新版本」,与运行记录里的「新版本」计数一致。
|
|
22
|
+
- **订阅抽屉**:「发版记录」改为「变更记录」,加载与空态文案同步。
|
|
23
|
+
- **英文**:`Releases` 口径统一为 `Subscriptions`;运行记录胶囊用 `Subs`(列宽 56px,完整单词会挤压右侧列)。
|
|
24
|
+
- **Host 提示**:`SUBSCRIBE_FAILED` 的「发版文档」改为「变更文档」;`trending_run` 输出「发版 N 个新版本」改为「订阅 N 个新版本」;配置校验「发版日」改为「订阅检查日」。
|
|
25
|
+
- `README.md` / `docs/dsh-plugin-summary.md` 同步口径;「发布插件到 npm」语义的「发版」保持不变。
|
|
26
|
+
|
|
27
|
+
### 修复 — 运行记录类型胶囊样式
|
|
28
|
+
|
|
29
|
+
- 订阅行此前只带 `.dshgt-pchip` 基础类,渲染成灰描边小盒子,和日报的「日榜」胶囊不是一套。现补上 `release` 变体,与日/周/月同高、同圆角、同字重,只差色相(暖橙 `#b45309`)。
|
|
30
|
+
- 四个变体的颜色改为从 `--tone` 派生到宿主 token(文字 82% / 描边 30% / 填充 12%),深色主题下不再出现「亮色贴纸」。
|
|
31
|
+
- 胶囊统一由 `kindChip()` 渲染,避免以后新增类型再漏类名。
|
|
32
|
+
|
|
3
33
|
## [v0.7.7] - 2026-11-01
|
|
4
34
|
|
|
5
35
|
> 升级核心 `dsh.core.version` 0.8.2 → 0.8.3:修复「英文占比高的仓库被误判为摘要无效、降级为原文」;订阅抽屉遮罩背景色对齐 dsh-skills-console。
|
package/README.md
CHANGED
|
@@ -47,20 +47,20 @@ dsh plugin --profile <profile> add @morehao/dsh-github-trending
|
|
|
47
47
|
## 用量(token)
|
|
48
48
|
|
|
49
49
|
- **每次运行的 token 总量**与**历史累计总量**都会记录。**只展示总用量,不拆** prompt / completion / cached 等维度。
|
|
50
|
-
- 「本次任务总量」= 榜单摘要阶段(`usage.totalTokens`)+
|
|
50
|
+
- 「本次任务总量」= 榜单摘要阶段(`usage.totalTokens`)+ 订阅阶段(`releases.usage.totalTokens`),**订阅消耗计入总量**。
|
|
51
51
|
- 累计 = 历史里全部运行 `tokens` 之和,**读时求和、不落盘**(`history.json` 只存每次的 `tokens`)。
|
|
52
52
|
- 插件**不做费用估算、不内置定价表**(价格随 provider / 区域变动,易过期):只展示核心回报的 token 真值。
|
|
53
|
-
- 展示位置:概览速览块(本次 / 累计 /
|
|
53
|
+
- 展示位置:概览速览块(本次 / 累计 / 新版本 / 订阅仓库数)、运行记录(每行本次 tokens、展开明细、页脚累计)、历史。数据来自契约 `Usage`。旧核心无 `usage` / `releases` 时对应速览块整体隐藏(不铺「—」、不伪造 0)。
|
|
54
54
|
|
|
55
|
-
##
|
|
55
|
+
## 订阅(`releases` 阶段)
|
|
56
56
|
|
|
57
|
-
- 订阅一组仓库,之后**每周一次**把每个仓库这一周「**新增的 Release**(无 Release 时回退 Tag)」合成一段中文总结,写到 `<output.dir>/releases/<owner>/<repo>-01.md`(每册都带两位序号,超出行数预算后下一次写入开 `-02.md`,最新一周在最上面),与榜单**同分支、同 PR**
|
|
57
|
+
- 订阅一组仓库,之后**每周一次**把每个仓库这一周「**新增的 Release**(无 Release 时回退 Tag)」合成一段中文总结,写到 `<output.dir>/releases/<owner>/<repo>-01.md`(每册都带两位序号,超出行数预算后下一次写入开 `-02.md`,最新一周在最上面),与榜单**同分支、同 PR** 一起提交。订阅阶段**常开**;没有订阅时不产出,既有榜单产物逐字节不变。跨仓的周汇总(`releases/_weekly/<年>/<ISO周>.{md,json}`)继续生成,供外部 Web 服务的 `GET /api/v2/releases*` 消费。
|
|
58
58
|
- **订阅列表随数据仓版本化**:文件在 `<repo>/<OutputRoot(output.dir)>/subscriptions.yaml`,随产物同一次 commit / PR,可审计、可复现。
|
|
59
59
|
- **插件不直接写仓**:列表经核心 `subscribe` IPC 命令读改——`add` / `remove` 只写 `.git/trendradar-subscriptions.pending`,下一次 `run` 切分支后落盘并随 artifact 提交。插件侧的子进程只做一次 stdin 交互:`RunRequest{command:"subscribe", action, repo?, volume?, configPath}`;核心把 payload 放进结果信封(`subscriptions` / `subscriptionDoc`),旧核心把 `list` 结果逐行打到信封前,插件两种都认。`configPath` 由插件生成(与 `run` 同源的临时配置),保证 `subscribe` 与 `run` 解析到同一个订阅文件;代理模式下 `model.baseURL` 为空,临时配置补一个回环占位端点以通过核心 `config.Load`(订阅命令不调用模型)。
|
|
60
|
-
- 界面:「订阅」页管理列表(增删 +
|
|
60
|
+
- 界面:「订阅」页管理列表(增删 + 逐仓库状态),可展开某仓库的变更文档(`GET /subscriptions/releases?repo=&volume=`);「设置 → 订阅」分区放行为参数与每周触发节奏。
|
|
61
61
|
- 周期:0.7.0 起只支持**每周**(`releases.period=weekly`)——每个 ISO 周、每仓库一条中文摘要,文档按周累积并按行数预算自动分卷;填 `daily`/`monthly` 会被校验拦下并说明原因。
|
|
62
|
-
-
|
|
63
|
-
- 历史里每条运行记录带 `releases` 摘要(仓库数 /
|
|
62
|
+
- 每周订阅行程与榜单调度**互相独立**:`releases.schedule`(`enabled` / `weekday`(ISO 1=周一…7=周日)/ `time` / `timezone`)驱动 `run --stages releases`——只跑订阅阶段,不抓榜单、不渲染 digest、不合并订阅 pending;成功后按 ISO 周(如 `2026-W44`)去重。
|
|
63
|
+
- 历史里每条运行记录带 `releases` 摘要(仓库数 / 新版本 / 已摘要 / 降级 / 失败 / 跳过)与本次 `tokens`;旧核心没有 `releases` 块时缺省。
|
|
64
64
|
|
|
65
65
|
|
|
66
66
|
|
|
@@ -118,13 +118,13 @@ dsh plugin --profile <profile> add @morehao/dsh-github-trending
|
|
|
118
118
|
| `summarize.batchSize` / `maxRetries` | `10` / `1` | 摘要批量与失败重试(映射核心 `summarize.*`) |
|
|
119
119
|
| `summarize.enrich` | `none` | `none` / `repo` / `readme`:是否抓取 GitHub topics / README 作为增强上下文;`repo`/`readme` 建议配只读 `GITHUB_READ_TOKEN` |
|
|
120
120
|
| `summarize.readmeChars` | `800` | README 摘录长度(enrich=readme 时) |
|
|
121
|
-
| `releases.includePrerelease` / `includeDrafts` | `false` / `false` | 是否含预发布 /
|
|
121
|
+
| `releases.includePrerelease` / `includeDrafts` | `false` / `false` | 是否含预发布 / 草稿(订阅阶段常开,不提供 `enabled` 开关) |
|
|
122
122
|
| `releases.fallbackToTags` / `baselineOnFirstRun` | `true` / `true` | 无 Release 时回退 Tag / 首次只记基线 |
|
|
123
123
|
| `releases.perRepoLimit` / `maxNotesChars` | `10` / `4000` | 文档列出的版本条数(1–20)/ notes 截断(500–20000) |
|
|
124
124
|
| `releases.summaryMaxChars` / `docMaxLines` | `1200` / `600` | 每仓每周摘要字数(500–2000)/ 文档行数预算(100–2000,超了开新卷) |
|
|
125
125
|
| `releases.concurrency` / `budgetSeconds` | `auto` / `auto` | 订阅并发(`auto` 或 1–8)/ 模型预算秒(`auto` 或 1–300);`auto` 由插件按订阅数解析 |
|
|
126
126
|
| `releases.period` | `weekly` | 只支持 `weekly`(每个 ISO 周一条摘要) |
|
|
127
|
-
| `releases.schedule.enabled` / `weekday` / `time` / `timezone` | `true` / `1` / `08:00:00` / `Asia/Shanghai` |
|
|
127
|
+
| `releases.schedule.enabled` / `weekday` / `time` / `timezone` | `true` / `1` / `08:00:00` / `Asia/Shanghai` | 每周订阅行程(插件自己的 tick;`weekday` 为 ISO 1=周一…7=周日);**不写进核心 YAML** |
|
|
128
128
|
| `output.dir` | `trending` | 仓库内相对目录 |
|
|
129
129
|
| `schedule.enabled` / `time` / `timezone` | `true` / `08:30:00` / `Asia/Shanghai` | 插件自己的 60 s tick 驱动 |
|
|
130
130
|
| `schedule.periods` | `daily,weekly,monthly` | 定时自动产出的周期:默认三周期全产出(无需勾选),日=每天、周=周日、月=月末触发;旧配置自动升级为三周期 |
|
package/client.js
CHANGED
|
@@ -56,7 +56,7 @@ var DICT = {
|
|
|
56
56
|
"st.auth": "认证",
|
|
57
57
|
"st.scope": "榜单",
|
|
58
58
|
"st.summarize": "摘要与用量",
|
|
59
|
-
"st.releases": "
|
|
59
|
+
"st.releases": "订阅",
|
|
60
60
|
"st.schedule": "调度",
|
|
61
61
|
"card.source.title": "内容来源",
|
|
62
62
|
"card.source.hint": "唯一来源是本地二进制",
|
|
@@ -243,7 +243,7 @@ var DICT = {
|
|
|
243
243
|
"shell.digest.dek": "按周期回看日榜 / 周榜 / 月榜;只有保留过预览副本的期数能读。",
|
|
244
244
|
"shell.runs.dek": "最近 30 次运行;展开看交付物、错误与日志。",
|
|
245
245
|
"shell.settings.dek": "沿用现有设置页;每个分区独立保存。",
|
|
246
|
-
"shell.subscriptions.dek": "
|
|
246
|
+
"shell.subscriptions.dek": "仓库订阅列表,随数据仓版本化;经核心 subscribe 命令增删。",
|
|
247
247
|
"shell.nextRun": "下次运行",
|
|
248
248
|
"shell.scheduleOff": "定时未开启",
|
|
249
249
|
"shell.ready": "就绪 {ready} / {total}",
|
|
@@ -312,8 +312,8 @@ var DICT = {
|
|
|
312
312
|
"runs.filter.dry": "试跑",
|
|
313
313
|
"runs.type.all": "全部",
|
|
314
314
|
"runs.type.digest": "日报",
|
|
315
|
-
"runs.type.release": "
|
|
316
|
-
"runs.release.empty": "
|
|
315
|
+
"runs.type.release": "订阅",
|
|
316
|
+
"runs.release.empty": "还没有订阅运行记录",
|
|
317
317
|
"runs.release.status.ok": "成功",
|
|
318
318
|
"runs.release.status.failed": "失败",
|
|
319
319
|
"runs.release.status.skipped": "跳过",
|
|
@@ -329,7 +329,7 @@ var DICT = {
|
|
|
329
329
|
"runs.release.startedAt": "开始",
|
|
330
330
|
"runs.release.finishedAt": "结束",
|
|
331
331
|
"runs.release.error": "错误",
|
|
332
|
-
"runs.release.note": "
|
|
332
|
+
"runs.release.note": "订阅运行只做订阅检查与变更文档渲染,不产出日报、也不合并待提交的订阅改动。",
|
|
333
333
|
"runs.pendingPr": "待合并",
|
|
334
334
|
"runs.prUnknown": "状态未知",
|
|
335
335
|
"runs.prCreated": "PR 已创建",
|
|
@@ -392,15 +392,15 @@ var DICT = {
|
|
|
392
392
|
"log.close": "关闭",
|
|
393
393
|
"run.usage.tokens": "本次任务 tokens",
|
|
394
394
|
"run.usage.tokensTotal": "累计全部用量",
|
|
395
|
-
"run.usage.tokensNote": "只展示总用量,不拆 prompt/completion 等维度;本次任务总量 = 榜单摘要 +
|
|
396
|
-
"run.usage.breakdown": "榜单摘要 {summary} ·
|
|
395
|
+
"run.usage.tokensNote": "只展示总用量,不拆 prompt/completion 等维度;本次任务总量 = 榜单摘要 + 订阅阶段(含订阅检查的模型调用)。旧核心无数据时显示「—」。",
|
|
396
|
+
"run.usage.breakdown": "榜单摘要 {summary} · 订阅 {releases} · 合计 {total}",
|
|
397
397
|
"run.usage.breakdownSimple": "榜单摘要 {summary} · 合计 {total}",
|
|
398
|
-
"run.usage.releasesOnly": "
|
|
399
|
-
"releases.card.title": "
|
|
398
|
+
"run.usage.releasesOnly": "订阅 {releases} · 合计 {total}",
|
|
399
|
+
"releases.card.title": "订阅(releases 阶段)",
|
|
400
400
|
"releases.card.on": "已开启",
|
|
401
401
|
"releases.card.off": "未开启",
|
|
402
402
|
"releases.stat.repos": "仓库",
|
|
403
|
-
"releases.stat.new": "
|
|
403
|
+
"releases.stat.new": "新版本",
|
|
404
404
|
"releases.stat.summarized": "已摘要",
|
|
405
405
|
"releases.stat.degraded": "降级",
|
|
406
406
|
"releases.stat.failed": "失败",
|
|
@@ -410,9 +410,9 @@ var DICT = {
|
|
|
410
410
|
"releases.badge.summarized": "已摘要",
|
|
411
411
|
"releases.badge.degraded": "降级为原文",
|
|
412
412
|
"releases.badge.off": "未启用",
|
|
413
|
-
"releases.empty": "
|
|
413
|
+
"releases.empty": "本次未启用订阅",
|
|
414
414
|
"runs.detail.tokens": "本次任务 tokens",
|
|
415
|
-
"runs.detail.releases": "
|
|
415
|
+
"runs.detail.releases": "订阅",
|
|
416
416
|
"runs.detail.tokensNone": "—",
|
|
417
417
|
"runs.footer.total": "历史累计 tokens:{total}",
|
|
418
418
|
"card.summarize.title": "摘要与用量",
|
|
@@ -429,10 +429,10 @@ var DICT = {
|
|
|
429
429
|
"summarize.readmeChars": "README 摘录长度",
|
|
430
430
|
"summarize.readmeChars.help": "enrich 为 readme 时,每个仓库 README 摘录的最大字符数(超出截断)。",
|
|
431
431
|
"summarize.enrichNote": "外部增强需要只读 token:enrich=repo/readme 建议配置 GITHUB_READ_TOKEN(独立只读);readme 模式在网络慢时可能因预算耗尽跳过部分仓库(自动降级,不影响运行)。",
|
|
432
|
-
"card.releases.title": "
|
|
432
|
+
"card.releases.title": "订阅",
|
|
433
433
|
"card.releases.hint": "对应核心 releases.*(core 0.5.0+)",
|
|
434
434
|
"releases.includePrerelease": "含预发布",
|
|
435
|
-
"releases.includePrerelease.help": "GitHub 上标记为 pre-release
|
|
435
|
+
"releases.includePrerelease.help": "GitHub 上标记为 pre-release 的版本也计入新版本。",
|
|
436
436
|
"releases.includeDrafts": "含草稿",
|
|
437
437
|
"releases.includeDrafts.help": "草稿(draft)Release 也计入;草稿只有写权限的 token 才看得到。",
|
|
438
438
|
"releases.notesChars": "notes 截断",
|
|
@@ -450,11 +450,11 @@ var DICT = {
|
|
|
450
450
|
"releases.concurrency.auto": "自动",
|
|
451
451
|
"releases.concurrency.fixed": "指定",
|
|
452
452
|
"releases.budget": "模型预算(秒)",
|
|
453
|
-
"releases.budget.help": "
|
|
453
|
+
"releases.budget.help": "订阅阶段调模型的预算总时长;「自动」按订阅数解析(min(300, 30 + 3×N))。",
|
|
454
454
|
"releases.budget.auto": "自动",
|
|
455
455
|
"releases.budget.fixed": "指定",
|
|
456
456
|
"subs.title": "订阅",
|
|
457
|
-
"subs.desc": "
|
|
457
|
+
"subs.desc": "管理订阅仓库,查看每周变更记录。",
|
|
458
458
|
"subs.select": "选择",
|
|
459
459
|
"subs.select.done": "完成",
|
|
460
460
|
"subs.cmd.placeholder": "搜索 owner/repo,或输入完整仓库名直接添加",
|
|
@@ -470,7 +470,7 @@ var DICT = {
|
|
|
470
470
|
"subs.meta.match": "匹配 {matched} / {total}",
|
|
471
471
|
"subs.meta.lastWeek": "上周 {from} ~ {to} · {changed} 个仓库有变化",
|
|
472
472
|
"subs.meta.thisWeek": "本周 {from} ~ {to} · {changed} 个仓库有变化",
|
|
473
|
-
"subs.meta.lastCheck": "
|
|
473
|
+
"subs.meta.lastCheck": "上次订阅检查 {time}",
|
|
474
474
|
"subs.add": "添加",
|
|
475
475
|
"subs.add.title": "添加订阅仓库",
|
|
476
476
|
"subs.add.exists": "{repo} 已在订阅列表中",
|
|
@@ -534,14 +534,14 @@ var DICT = {
|
|
|
534
534
|
"subs.empty.clear": "清除搜索",
|
|
535
535
|
"subs.loading": "加载订阅列表…",
|
|
536
536
|
"subs.input.invalid": "请输入 owner/repo 形态,例如 vercel/next.js",
|
|
537
|
-
"subs.drawer.title": "
|
|
537
|
+
"subs.drawer.title": "变更记录 · {repo}",
|
|
538
538
|
"subs.drawer.close": "关闭",
|
|
539
539
|
"subs.drawer.updated": "最近更新 {date}",
|
|
540
540
|
"subs.drawer.volume": "第 {index} 册 / 共 {total} 册",
|
|
541
541
|
"subs.drawer.prevVolume": "上一册",
|
|
542
542
|
"subs.drawer.nextVolume": "下一册",
|
|
543
|
-
"subs.drawer.loading": "
|
|
544
|
-
"subs.drawer.empty": "
|
|
543
|
+
"subs.drawer.loading": "读取变更记录…",
|
|
544
|
+
"subs.drawer.empty": "这个仓库还没有变更记录,第一周检查后会出现在这里",
|
|
545
545
|
"subs.drawer.retry": "重试",
|
|
546
546
|
"subs.drawer.warn.rate_limited": "本周未更新(限流),下次运行会重试",
|
|
547
547
|
"subs.drawer.warn.failed": "本周未更新(失败),下次运行会重试",
|
|
@@ -553,13 +553,13 @@ var DICT = {
|
|
|
553
553
|
"weekday.5": "周五",
|
|
554
554
|
"weekday.6": "周六",
|
|
555
555
|
"weekday.7": "周日",
|
|
556
|
-
"subs.param.hint": "阶段行为参数(每仓上限、回退 Tag
|
|
557
|
-
"subs.param.link": "前往设置 →
|
|
556
|
+
"subs.param.hint": "阶段行为参数(每仓上限、回退 Tag、周期等)在设置页「订阅」分区调整。",
|
|
557
|
+
"subs.param.link": "前往设置 → 订阅",
|
|
558
558
|
"overview.tokens.title": "Token 用量",
|
|
559
559
|
"overview.tokens.thisRun": "本次任务",
|
|
560
560
|
"overview.tokens.total": "累计全部",
|
|
561
|
-
"overview.releases.title": "
|
|
562
|
-
"overview.releases.new": "
|
|
561
|
+
"overview.releases.title": "订阅",
|
|
562
|
+
"overview.releases.new": "新版本",
|
|
563
563
|
"overview.releases.repos": "仓库",
|
|
564
564
|
"overview.tokens.note": "概览一屏带出「这次任务共花了多少 token / 历史上累计多少 / 订阅仓库有几个新版本」;只给总用量,不拆维度;本次任务总量已含订阅阶段消耗。旧核心无数据时对应小块整体隐藏,不留 0。",
|
|
565
565
|
"about.title": "关于",
|
|
@@ -585,7 +585,7 @@ var DICT = {
|
|
|
585
585
|
"st.auth": "Auth",
|
|
586
586
|
"st.scope": "Scope",
|
|
587
587
|
"st.summarize": "Summary & usage",
|
|
588
|
-
"st.releases": "
|
|
588
|
+
"st.releases": "Subscriptions",
|
|
589
589
|
"st.schedule": "Schedule",
|
|
590
590
|
"card.source.title": "Content source",
|
|
591
591
|
"card.source.hint": "one source: the local binary",
|
|
@@ -772,7 +772,7 @@ var DICT = {
|
|
|
772
772
|
"shell.digest.dek": "Look back per period — daily / weekly / monthly; only issues with a saved preview copy can be read.",
|
|
773
773
|
"shell.runs.dek": "The last 30 runs; expand one for artifacts, errors and logs.",
|
|
774
774
|
"shell.settings.dek": "The existing settings page; each section saves on its own.",
|
|
775
|
-
"shell.subscriptions.dek": "Repo
|
|
775
|
+
"shell.subscriptions.dek": "Repo subscription list, versioned in the data repo; add or remove via the core subscribe command.",
|
|
776
776
|
"shell.nextRun": "Next run",
|
|
777
777
|
"shell.scheduleOff": "Schedule off",
|
|
778
778
|
"shell.ready": "Ready {ready} / {total}",
|
|
@@ -841,8 +841,8 @@ var DICT = {
|
|
|
841
841
|
"runs.filter.dry": "Dry run",
|
|
842
842
|
"runs.type.all": "All",
|
|
843
843
|
"runs.type.digest": "Digest",
|
|
844
|
-
"runs.type.release": "
|
|
845
|
-
"runs.release.empty": "No
|
|
844
|
+
"runs.type.release": "Subs",
|
|
845
|
+
"runs.release.empty": "No subscription runs yet",
|
|
846
846
|
"runs.release.status.ok": "OK",
|
|
847
847
|
"runs.release.status.failed": "Failed",
|
|
848
848
|
"runs.release.status.skipped": "Skipped",
|
|
@@ -858,7 +858,7 @@ var DICT = {
|
|
|
858
858
|
"runs.release.startedAt": "Started",
|
|
859
859
|
"runs.release.finishedAt": "Finished",
|
|
860
860
|
"runs.release.error": "Error",
|
|
861
|
-
"runs.release.note": "A
|
|
861
|
+
"runs.release.note": "A subscription run only checks subscriptions and renders change documents; it produces no digest and does not merge pending subscription changes.",
|
|
862
862
|
"runs.pendingPr": "Pending merge",
|
|
863
863
|
"runs.prUnknown": "State unknown",
|
|
864
864
|
"runs.prCreated": "PR created",
|
|
@@ -921,11 +921,11 @@ var DICT = {
|
|
|
921
921
|
"log.close": "Close",
|
|
922
922
|
"run.usage.tokens": "This run tokens",
|
|
923
923
|
"run.usage.tokensTotal": "All-time total",
|
|
924
|
-
"run.usage.tokensNote": 'Only total usage is shown, not split into prompt/completion; this run total = board summary +
|
|
925
|
-
"run.usage.breakdown": "Board {summary} ·
|
|
924
|
+
"run.usage.tokensNote": 'Only total usage is shown, not split into prompt/completion; this run total = board summary + subscriptions stage (including the model calls of the subscription check). Old core with no data shows "—".',
|
|
925
|
+
"run.usage.breakdown": "Board {summary} · Subscriptions {releases} · Total {total}",
|
|
926
926
|
"run.usage.breakdownSimple": "Board {summary} · Total {total}",
|
|
927
|
-
"run.usage.releasesOnly": "
|
|
928
|
-
"releases.card.title": "
|
|
927
|
+
"run.usage.releasesOnly": "Subscriptions {releases} · Total {total}",
|
|
928
|
+
"releases.card.title": "Subscriptions stage",
|
|
929
929
|
"releases.card.on": "On",
|
|
930
930
|
"releases.card.off": "Off",
|
|
931
931
|
"releases.stat.repos": "Repos",
|
|
@@ -939,9 +939,9 @@ var DICT = {
|
|
|
939
939
|
"releases.badge.summarized": "Summarized",
|
|
940
940
|
"releases.badge.degraded": "Degraded to original",
|
|
941
941
|
"releases.badge.off": "Disabled",
|
|
942
|
-
"releases.empty": "
|
|
942
|
+
"releases.empty": "Subscriptions were not enabled for this run",
|
|
943
943
|
"runs.detail.tokens": "This run tokens",
|
|
944
|
-
"runs.detail.releases": "
|
|
944
|
+
"runs.detail.releases": "Subscriptions",
|
|
945
945
|
"runs.detail.tokensNone": "—",
|
|
946
946
|
"runs.footer.total": "All-time tokens: {total}",
|
|
947
947
|
"card.summarize.title": "Summary & usage",
|
|
@@ -958,7 +958,7 @@ var DICT = {
|
|
|
958
958
|
"summarize.readmeChars": "README excerpt chars",
|
|
959
959
|
"summarize.readmeChars.help": "Max README characters excerpted per repo when enrich=readme (longer text is truncated).",
|
|
960
960
|
"summarize.enrichNote": "Enrich needs a read-only token: enrich=repo/readme is best paired with GITHUB_READ_TOKEN (separate, read-only). In readme mode slow networks may skip some repos when the budget runs out (auto-degrades; the run is unaffected).",
|
|
961
|
-
"card.releases.title": "
|
|
961
|
+
"card.releases.title": "Subscriptions",
|
|
962
962
|
"card.releases.hint": "Maps to core releases.* (core 0.5.0+)",
|
|
963
963
|
"releases.includePrerelease": "Include pre-releases",
|
|
964
964
|
"releases.includePrerelease.help": "Releases marked as pre-release on GitHub also count as new releases.",
|
|
@@ -979,11 +979,11 @@ var DICT = {
|
|
|
979
979
|
"releases.concurrency.auto": "Auto",
|
|
980
980
|
"releases.concurrency.fixed": "Fixed",
|
|
981
981
|
"releases.budget": "Model budget (s)",
|
|
982
|
-
"releases.budget.help": "Overall budget for model calls in the
|
|
982
|
+
"releases.budget.help": "Overall budget for model calls in the subscriptions stage; “Auto” resolves by subscription count (min(300, 30 + 3×N)).",
|
|
983
983
|
"releases.budget.auto": "Auto",
|
|
984
984
|
"releases.budget.fixed": "Fixed",
|
|
985
985
|
"subs.title": "Subscriptions",
|
|
986
|
-
"subs.desc": "Manage
|
|
986
|
+
"subs.desc": "Manage subscribed repos and review weekly change records.",
|
|
987
987
|
"subs.select": "Select",
|
|
988
988
|
"subs.select.done": "Done",
|
|
989
989
|
"subs.cmd.placeholder": "Search owner/repo, or type a full repo name to add it",
|
|
@@ -999,7 +999,7 @@ var DICT = {
|
|
|
999
999
|
"subs.meta.match": "Match {matched} / {total}",
|
|
1000
1000
|
"subs.meta.lastWeek": "Last week {from} ~ {to} · {changed} repos changed",
|
|
1001
1001
|
"subs.meta.thisWeek": "This week {from} ~ {to} · {changed} repos changed",
|
|
1002
|
-
"subs.meta.lastCheck": "Last
|
|
1002
|
+
"subs.meta.lastCheck": "Last subscription check {time}",
|
|
1003
1003
|
"subs.add": "Add",
|
|
1004
1004
|
"subs.add.title": "Add a repository",
|
|
1005
1005
|
"subs.add.exists": "{repo} is already subscribed",
|
|
@@ -1063,14 +1063,14 @@ var DICT = {
|
|
|
1063
1063
|
"subs.empty.clear": "Clear search",
|
|
1064
1064
|
"subs.loading": "Loading subscriptions…",
|
|
1065
1065
|
"subs.input.invalid": "Enter owner/repo form, e.g. vercel/next.js",
|
|
1066
|
-
"subs.drawer.title": "
|
|
1066
|
+
"subs.drawer.title": "Change log · {repo}",
|
|
1067
1067
|
"subs.drawer.close": "Close",
|
|
1068
1068
|
"subs.drawer.updated": "Updated {date}",
|
|
1069
1069
|
"subs.drawer.volume": "Volume {index} of {total}",
|
|
1070
1070
|
"subs.drawer.prevVolume": "Previous volume",
|
|
1071
1071
|
"subs.drawer.nextVolume": "Next volume",
|
|
1072
|
-
"subs.drawer.loading": "Reading the
|
|
1073
|
-
"subs.drawer.empty": "This repo has no
|
|
1072
|
+
"subs.drawer.loading": "Reading the change log…",
|
|
1073
|
+
"subs.drawer.empty": "This repo has no change log yet; it appears here after the first weekly check.",
|
|
1074
1074
|
"subs.drawer.retry": "Retry",
|
|
1075
1075
|
"subs.drawer.warn.rate_limited": "Not updated this week (rate limited); the next run retries.",
|
|
1076
1076
|
"subs.drawer.warn.failed": "Not updated this week (failed); the next run retries.",
|
|
@@ -1082,12 +1082,12 @@ var DICT = {
|
|
|
1082
1082
|
"weekday.5": "Fri",
|
|
1083
1083
|
"weekday.6": "Sat",
|
|
1084
1084
|
"weekday.7": "Sun",
|
|
1085
|
-
"subs.param.hint": "Stage behaviour parameters (per-repo limit, tag fallback, period, etc.) are adjusted in the settings page
|
|
1086
|
-
"subs.param.link": "Go to Settings →
|
|
1085
|
+
"subs.param.hint": "Stage behaviour parameters (per-repo limit, tag fallback, period, etc.) are adjusted in the settings page Subscriptions section.",
|
|
1086
|
+
"subs.param.link": "Go to Settings → Subscriptions",
|
|
1087
1087
|
"overview.tokens.title": "Token usage",
|
|
1088
1088
|
"overview.tokens.thisRun": "This run",
|
|
1089
1089
|
"overview.tokens.total": "All-time",
|
|
1090
|
-
"overview.releases.title": "
|
|
1090
|
+
"overview.releases.title": "Subscriptions",
|
|
1091
1091
|
"overview.releases.new": "New",
|
|
1092
1092
|
"overview.releases.repos": "Repos",
|
|
1093
1093
|
"overview.tokens.note": 'The overview surfaces "how many tokens this run spent / all-time accumulated / how many new versions across subscribed repos"; total only, not split by dimension; this run total already includes the subscriptions stage. With an old core that has no data, the corresponding tile is hidden entirely, never shown as 0.',
|
|
@@ -1382,9 +1382,13 @@ var CSS = `
|
|
|
1382
1382
|
|
|
1383
1383
|
/* ——— 周期标签 / 分段 ——— */
|
|
1384
1384
|
.dshgt-pchip{display:inline-flex;align-items:center;justify-content:center;height:20px;padding:0 8px;border-radius:999px;font-size:11px;font-weight:600;line-height:18px;white-space:nowrap;border:1px solid var(--gt-border);color:var(--gt-muted);background:var(--gt-bg);}
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
.dshgt-pchip.
|
|
1385
|
+
/* 周期 / 订阅同族:同一套尺寸与「填充 + 同色描边 + 同色文字」,只差色相。
|
|
1386
|
+
色值从 --tone 派生到宿主 token,深色主题下不会变成刺眼的浅色贴纸。 */
|
|
1387
|
+
.dshgt-pchip.daily{--tone:#2563eb;}
|
|
1388
|
+
.dshgt-pchip.weekly{--tone:#7c3aed;}
|
|
1389
|
+
.dshgt-pchip.monthly{--tone:#0f766e;}
|
|
1390
|
+
.dshgt-pchip.release{--tone:#b45309;}
|
|
1391
|
+
.dshgt-pchip.daily,.dshgt-pchip.weekly,.dshgt-pchip.monthly,.dshgt-pchip.release{color:color-mix(in srgb,var(--tone) 82%,var(--gt-fg));border-color:color-mix(in srgb,var(--tone) 30%,var(--gt-bg));background:color-mix(in srgb,var(--tone) 12%,var(--gt-bg));}
|
|
1388
1392
|
.dshgt-period-seg{display:inline-flex;border:1px solid var(--gt-border);border-radius:9px;padding:3px;background:var(--gt-card);gap:3px;}
|
|
1389
1393
|
.dshgt-period-seg button{display:inline-flex;align-items:center;gap:7px;border:0;background:none;height:30px;padding:0 12px;border-radius:7px;font:inherit;font-size:13px;color:var(--gt-muted);cursor:pointer;}
|
|
1390
1394
|
.dshgt-period-seg button:hover{color:var(--gt-fg);}
|
|
@@ -3464,6 +3468,9 @@ function prStatus(t, state, record) {
|
|
|
3464
3468
|
}
|
|
3465
3469
|
return { label: t("runs.prCreated"), kind: "ok" };
|
|
3466
3470
|
}
|
|
3471
|
+
function kindChip(text, tone) {
|
|
3472
|
+
return h("span", { className: `dshgt-pchip ${tone}` }, text);
|
|
3473
|
+
}
|
|
3467
3474
|
function LogDrawer(props) {
|
|
3468
3475
|
const { t, runId } = props;
|
|
3469
3476
|
const [loading, setLoading] = import_react.default.useState(true);
|
|
@@ -3577,7 +3584,7 @@ function RunsView(props) {
|
|
|
3577
3584
|
},
|
|
3578
3585
|
h("span", { className: `dshgt-lamp ${record.ok ? record.skipped || record.kind === "dry-run" ? "warn" : "ok" : "err"}` }),
|
|
3579
3586
|
h("span", { className: "dshgt-run-date" }, shortTime(record.at)),
|
|
3580
|
-
|
|
3587
|
+
kindChip(t(`period.${record.period ?? "daily"}`), record.period ?? "daily"),
|
|
3581
3588
|
h(
|
|
3582
3589
|
"span",
|
|
3583
3590
|
{ className: "dshgt-run-what" },
|
|
@@ -3608,7 +3615,7 @@ function RunsView(props) {
|
|
|
3608
3615
|
detailItem(t, "run.usage.branch", record.branch === void 0 ? "—" : h("span", { className: "dshgt-mono" }, record.branch)),
|
|
3609
3616
|
detailItem(t, "runs.detail.coreModel", `${record.coreVersion || "—"} · ${record.model?.model ?? "—"}`),
|
|
3610
3617
|
detailItem(t, "runs.detail.date", record.date ?? "—"),
|
|
3611
|
-
detailItem(t, "runs.detail.period",
|
|
3618
|
+
detailItem(t, "runs.detail.period", kindChip(t(`period.${record.period ?? "daily"}`), record.period ?? "daily")),
|
|
3612
3619
|
detailItem(
|
|
3613
3620
|
t,
|
|
3614
3621
|
"run.usage.pr",
|
|
@@ -3736,7 +3743,7 @@ function ReleaseRunItem(props) {
|
|
|
3736
3743
|
},
|
|
3737
3744
|
h("span", { className: `dshgt-lamp ${lamp}` }),
|
|
3738
3745
|
h("span", { className: "dshgt-run-date" }, shortTime(run.startedAt)),
|
|
3739
|
-
|
|
3746
|
+
kindChip(t("runs.type.release"), "release"),
|
|
3740
3747
|
h(
|
|
3741
3748
|
"span",
|
|
3742
3749
|
{ className: "dshgt-run-what" },
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
}
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __export = (target, all) => {
|
|
3
|
+
for (var name in all)
|
|
4
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
|
+
};
|
|
6
6
|
|
|
7
7
|
// src/config.ts
|
|
8
8
|
var config_exports = {};
|
|
@@ -327,7 +327,7 @@ function validateSettings(settings, providers = CORE_PROVIDERS) {
|
|
|
327
327
|
problems.push({
|
|
328
328
|
field: "releases.period",
|
|
329
329
|
code: "CONFIG_INVALID",
|
|
330
|
-
message: "\u672C\u7248\u672C\u53EA\u652F\u6301\u6BCF\u5468\uFF08weekly\uFF09\
|
|
330
|
+
message: "\u672C\u7248\u672C\u53EA\u652F\u6301\u6BCF\u5468\uFF08weekly\uFF09\u8BA2\u9605\u6458\u8981\uFF0C\u8BF7\u628A releases.period \u6539\u4E3A weekly"
|
|
331
331
|
});
|
|
332
332
|
}
|
|
333
333
|
if (!Number.isInteger(releases.perRepoLimit) || releases.perRepoLimit < 1 || releases.perRepoLimit > 20) {
|
|
@@ -349,7 +349,7 @@ function validateSettings(settings, providers = CORE_PROVIDERS) {
|
|
|
349
349
|
problems.push({ field: "releases.budgetSeconds", code: "CONFIG_INVALID", message: "budgetSeconds \u5FC5\u987B\u662F auto \u6216 1\u2013300 \u7684\u6574\u6570" });
|
|
350
350
|
}
|
|
351
351
|
if (!Number.isInteger(releases.schedule.weekday) || releases.schedule.weekday < 1 || releases.schedule.weekday > 7) {
|
|
352
|
-
problems.push({ field: "releases.schedule.weekday", code: "CONFIG_INVALID", message: "\
|
|
352
|
+
problems.push({ field: "releases.schedule.weekday", code: "CONFIG_INVALID", message: "\u8BA2\u9605\u68C0\u67E5\u65E5\u5FC5\u987B\u662F ISO \u661F\u671F 1\u20137\uFF081=\u5468\u4E00\uFF09" });
|
|
353
353
|
}
|
|
354
354
|
if (!TIME_RE.test(releases.schedule.time)) {
|
|
355
355
|
problems.push({ field: "releases.schedule.time", code: "CONFIG_INVALID", message: "\u65F6\u95F4\u683C\u5F0F\u5FC5\u987B\u662F HH:MM \u6216 HH:MM:SS" });
|
|
@@ -1148,16 +1148,15 @@ __export(handshake_exports, {
|
|
|
1148
1148
|
DEFAULT_PROVIDERS: () => DEFAULT_PROVIDERS,
|
|
1149
1149
|
handshake: () => handshake
|
|
1150
1150
|
});
|
|
1151
|
+
import { spawnCollect as execCapture } from "@morehao/dsh-plugin-kit/exec";
|
|
1151
1152
|
var DEFAULT_PROVIDERS = ["deepseek", "openai-compatible"];
|
|
1152
1153
|
async function handshake(core, options = {}) {
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
} catch (error) {
|
|
1160
|
-
const detail = error instanceof Error ? error.message : String(error);
|
|
1154
|
+
const result = await execCapture(core.path, ["version", "--json"], {
|
|
1155
|
+
timeoutMs: options.timeoutMs ?? 5e3,
|
|
1156
|
+
signal: options.signal
|
|
1157
|
+
});
|
|
1158
|
+
if (result.error !== void 0) {
|
|
1159
|
+
const detail = result.error.message;
|
|
1161
1160
|
throw new IpcError("CORE_SPAWN_FAILED", `\u65E0\u6CD5\u6267\u884C\u6838\u5FC3 ${core.path}\uFF1A${detail}`);
|
|
1162
1161
|
}
|
|
1163
1162
|
if (result.aborted || options.signal?.aborted === true) {
|
|
@@ -1590,6 +1589,7 @@ __export(run_exports, {
|
|
|
1590
1589
|
runCore: () => runCore
|
|
1591
1590
|
});
|
|
1592
1591
|
import { spawn as spawn2 } from "child_process";
|
|
1592
|
+
import { sanitizedEnv } from "@morehao/dsh-plugin-kit/exec";
|
|
1593
1593
|
var DEFAULT_RUN_TIMEOUT_MS = 12e4;
|
|
1594
1594
|
var MAX_STDOUT = 16 * 1024 * 1024;
|
|
1595
1595
|
var MAX_STDERR = 2 * 1024 * 1024;
|
|
@@ -1772,6 +1772,7 @@ __export(core_exports, {
|
|
|
1772
1772
|
});
|
|
1773
1773
|
import { accessSync as accessSync2, constants as constants3, statSync as statSync4 } from "fs";
|
|
1774
1774
|
import path7 from "path";
|
|
1775
|
+
import { spawnCollect as execCapture2 } from "@morehao/dsh-plugin-kit/exec";
|
|
1775
1776
|
function coreRepoFromSource(repo) {
|
|
1776
1777
|
let ownerRepo = repo;
|
|
1777
1778
|
if (ownerRepo === void 0) {
|
|
@@ -1876,7 +1877,7 @@ async function detectCoexistence(ownPath, options = {}) {
|
|
|
1876
1877
|
}
|
|
1877
1878
|
let status;
|
|
1878
1879
|
try {
|
|
1879
|
-
const result = await
|
|
1880
|
+
const result = await execCapture2(found, ["version", "--json"], { timeoutMs: 3e3 });
|
|
1880
1881
|
if (result.code !== 0) {
|
|
1881
1882
|
status = {
|
|
1882
1883
|
found: true,
|
|
@@ -1970,8 +1971,8 @@ async function defaultGhToken(fresh = false) {
|
|
|
1970
1971
|
if (!fresh && ghTokenCache !== void 0 && Date.now() - ghTokenCache.at < GH_TOKEN_TTL_MS) {
|
|
1971
1972
|
return ghTokenCache.value;
|
|
1972
1973
|
}
|
|
1973
|
-
const {
|
|
1974
|
-
const result = await
|
|
1974
|
+
const { spawnCollect: execCapture6 } = await import("@morehao/dsh-plugin-kit/exec");
|
|
1975
|
+
const result = await execCapture6("gh", ["auth", "token"], { timeoutMs: 2e3 });
|
|
1975
1976
|
const token = result.code === 0 ? result.stdout.trim() : "";
|
|
1976
1977
|
const value = token === "" ? void 0 : token;
|
|
1977
1978
|
ghTokenCache = { value, at: Date.now() };
|
|
@@ -2407,7 +2408,7 @@ function nextReleaseOccurrence(now, cfg) {
|
|
|
2407
2408
|
const candidate = zonedTimeToUtc(year, month, day, hour, minute, second, cfg.timezone);
|
|
2408
2409
|
if (candidate.getTime() > now.getTime()) return candidate;
|
|
2409
2410
|
}
|
|
2410
|
-
throw new Error(`\u65E0\u6CD5\u8BA1\u7B97\u4E0B\u4E00\u6B21\
|
|
2411
|
+
throw new Error(`\u65E0\u6CD5\u8BA1\u7B97\u4E0B\u4E00\u6B21\u8BA2\u9605\u8FD0\u884C\u65F6\u523B\uFF08weekday=${String(cfg.weekday)}\uFF09`);
|
|
2411
2412
|
}
|
|
2412
2413
|
function isReleaseDue(now, cfg) {
|
|
2413
2414
|
if (isoWeekdayOf(now, cfg.timezone) !== cfg.weekday) return false;
|
|
@@ -2660,6 +2661,7 @@ __export(subscribe_exports, {
|
|
|
2660
2661
|
import { mkdtempSync as mkdtempSync2, writeFileSync as writeFileSync2, rmSync as rmSync2 } from "fs";
|
|
2661
2662
|
import os3 from "os";
|
|
2662
2663
|
import path8 from "path";
|
|
2664
|
+
import { spawnCollect as execCapture3, sanitizedEnv as sanitizedEnv2 } from "@morehao/dsh-plugin-kit/exec";
|
|
2663
2665
|
var SUBSCRIBE_TIMEOUT_MS = 8e3;
|
|
2664
2666
|
var RELEASES_TIMEOUT_MS = 3e4;
|
|
2665
2667
|
var REPO_PATTERN2 = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
|
|
@@ -2709,8 +2711,8 @@ async function runSubscribe(input, deps) {
|
|
|
2709
2711
|
configPath: file
|
|
2710
2712
|
};
|
|
2711
2713
|
const timeoutMs = input.action === "releases" ? RELEASES_TIMEOUT_MS : SUBSCRIBE_TIMEOUT_MS;
|
|
2712
|
-
const result = await
|
|
2713
|
-
env:
|
|
2714
|
+
const result = await execCapture3(corePath, ["subscribe", "--json"], {
|
|
2715
|
+
env: sanitizedEnv2(env),
|
|
2714
2716
|
input: JSON.stringify(request),
|
|
2715
2717
|
timeoutMs
|
|
2716
2718
|
});
|
|
@@ -3411,40 +3413,17 @@ __export(plugin_info_exports, {
|
|
|
3411
3413
|
normalizeRepositoryUrl: () => normalizeRepositoryUrl,
|
|
3412
3414
|
readPluginInfo: () => readPluginInfo
|
|
3413
3415
|
});
|
|
3414
|
-
import {
|
|
3416
|
+
import { normalizeRepositoryUrl } from "@morehao/dsh-plugin-kit/github";
|
|
3417
|
+
import { createPluginMeta } from "@morehao/dsh-plugin-kit/meta";
|
|
3415
3418
|
var DEFAULT_NAME = "@morehao/dsh-github-trending";
|
|
3416
|
-
|
|
3417
|
-
if (typeof value !== "string") return void 0;
|
|
3418
|
-
let url = value.trim();
|
|
3419
|
-
if (url === "") return void 0;
|
|
3420
|
-
url = url.replace(/^git\+/i, "");
|
|
3421
|
-
const ssh = /^git@github\.com:([^/]+)\/(.+?)(?:\.git)?$/i.exec(url);
|
|
3422
|
-
if (ssh !== null) url = `https://github.com/${ssh[1]}/${ssh[2]}`;
|
|
3423
|
-
url = url.replace(/\.git$/i, "");
|
|
3424
|
-
try {
|
|
3425
|
-
const parsed = new URL(url);
|
|
3426
|
-
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") return void 0;
|
|
3427
|
-
if (parsed.hostname.toLowerCase() !== "github.com") return void 0;
|
|
3428
|
-
const pathname = parsed.pathname.replace(/\/+$/, "");
|
|
3429
|
-
if (pathname === "") return void 0;
|
|
3430
|
-
return `https://github.com${pathname}`;
|
|
3431
|
-
} catch {
|
|
3432
|
-
return void 0;
|
|
3433
|
-
}
|
|
3434
|
-
}
|
|
3419
|
+
var PKG_URL = new URL("../package.json", import.meta.url);
|
|
3435
3420
|
function readPluginInfo() {
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
version: typeof pkg.version === "string" ? pkg.version : "0.0.0",
|
|
3443
|
-
...repository === void 0 ? {} : { repository }
|
|
3444
|
-
};
|
|
3445
|
-
} catch {
|
|
3446
|
-
return { name: DEFAULT_NAME, version: "0.0.0" };
|
|
3447
|
-
}
|
|
3421
|
+
const meta = createPluginMeta({ pkgUrl: PKG_URL, defaultName: DEFAULT_NAME });
|
|
3422
|
+
return {
|
|
3423
|
+
name: meta.name,
|
|
3424
|
+
version: meta.version,
|
|
3425
|
+
...meta.repository === void 0 ? {} : { repository: meta.repository }
|
|
3426
|
+
};
|
|
3448
3427
|
}
|
|
3449
3428
|
|
|
3450
3429
|
// src/host/github.ts
|
|
@@ -3958,6 +3937,7 @@ __export(repo_exports, {
|
|
|
3958
3937
|
});
|
|
3959
3938
|
import { statSync as statSync6 } from "fs";
|
|
3960
3939
|
import path11 from "path";
|
|
3940
|
+
import { spawnCollect as execCapture4 } from "@morehao/dsh-plugin-kit/exec";
|
|
3961
3941
|
function isDirectory(dir) {
|
|
3962
3942
|
try {
|
|
3963
3943
|
return statSync6(dir).isDirectory();
|
|
@@ -3967,7 +3947,7 @@ function isDirectory(dir) {
|
|
|
3967
3947
|
}
|
|
3968
3948
|
async function git(dir, args, env) {
|
|
3969
3949
|
try {
|
|
3970
|
-
const result = await
|
|
3950
|
+
const result = await execCapture4("git", ["-C", dir, ...args], { env, timeoutMs: 5e3 });
|
|
3971
3951
|
return result.code === 0 ? result.stdout.trim() : void 0;
|
|
3972
3952
|
} catch {
|
|
3973
3953
|
return void 0;
|
|
@@ -3998,77 +3978,53 @@ __export(routes_exports, {
|
|
|
3998
3978
|
ROUTE_PREFIX: () => ROUTE_PREFIX,
|
|
3999
3979
|
createRoutes: () => createRoutes
|
|
4000
3980
|
});
|
|
3981
|
+
import { createRouteHandler, HttpError } from "@morehao/dsh-plugin-kit/http";
|
|
4001
3982
|
import { PluginUpdateError } from "@morehao/dsh-plugin-kit/update";
|
|
4002
3983
|
var ROUTE_PREFIX = "/api/morehao/github-trending";
|
|
4003
3984
|
var HEADER = "x-dsh-github-trending";
|
|
4004
3985
|
var MAX_BODY2 = 512 * 1024;
|
|
4005
|
-
function sendJson2(response, status, payload) {
|
|
4006
|
-
const body = JSON.stringify(payload);
|
|
4007
|
-
response.writeHead(status, {
|
|
4008
|
-
"content-type": "application/json; charset=utf-8",
|
|
4009
|
-
"cache-control": "no-store",
|
|
4010
|
-
"content-length": Buffer.byteLength(body)
|
|
4011
|
-
});
|
|
4012
|
-
response.end(body);
|
|
4013
|
-
}
|
|
4014
|
-
async function readBody2(request) {
|
|
4015
|
-
const chunks = [];
|
|
4016
|
-
let size = 0;
|
|
4017
|
-
for await (const chunk of request) {
|
|
4018
|
-
size += chunk.length;
|
|
4019
|
-
if (size > MAX_BODY2) throw new IpcError("PAYLOAD_TOO_LARGE", "\u8BF7\u6C42\u4F53\u8FC7\u5927");
|
|
4020
|
-
chunks.push(chunk);
|
|
4021
|
-
}
|
|
4022
|
-
if (chunks.length === 0) return {};
|
|
4023
|
-
const text = Buffer.concat(chunks).toString("utf8").trim();
|
|
4024
|
-
if (text === "") return {};
|
|
4025
|
-
try {
|
|
4026
|
-
const value = JSON.parse(text);
|
|
4027
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
4028
|
-
throw new Error("body must be a JSON object");
|
|
4029
|
-
}
|
|
4030
|
-
return value;
|
|
4031
|
-
} catch (error) {
|
|
4032
|
-
throw new IpcError("CONFIG_INVALID", `\u8BF7\u6C42\u4F53\u4E0D\u662F JSON \u5BF9\u8C61\uFF1A${error instanceof Error ? error.message : String(error)}`);
|
|
4033
|
-
}
|
|
4034
|
-
}
|
|
4035
3986
|
function createRoutes(deps) {
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
if (response.writableEnded) return;
|
|
3987
|
+
const logger = deps.logger;
|
|
3988
|
+
let current = { method: "GET", pathname: "/" };
|
|
3989
|
+
const handler = createRouteHandler({
|
|
3990
|
+
prefix: ROUTE_PREFIX,
|
|
3991
|
+
header: HEADER,
|
|
3992
|
+
maxBodyBytes: MAX_BODY2,
|
|
3993
|
+
dispatch: async ({ method, pathname, url, body }) => {
|
|
3994
|
+
current = { method, pathname };
|
|
3995
|
+
return dispatch(method, pathname, url, body, deps);
|
|
3996
|
+
},
|
|
3997
|
+
// 错误码翻译留在插件侧(dispatcher 不做映射):保持与原实现的响应形状逐字一致。
|
|
3998
|
+
onError: (error) => {
|
|
4049
3999
|
if (error instanceof PluginUpdateError) {
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4000
|
+
logger?.("update.failed", { code: error.code, message: error.message });
|
|
4001
|
+
return {
|
|
4002
|
+
status: 409,
|
|
4053
4003
|
code: "UPDATE_FAILED",
|
|
4054
|
-
updateCode: error.code,
|
|
4055
4004
|
message: redact(error.message),
|
|
4056
|
-
update: deps.update?.view() ?? null
|
|
4057
|
-
}
|
|
4058
|
-
|
|
4005
|
+
extra: { updateCode: error.code, update: deps.update?.view() ?? null }
|
|
4006
|
+
};
|
|
4007
|
+
}
|
|
4008
|
+
if (error instanceof HttpError) {
|
|
4009
|
+
const code2 = error.code === "PAYLOAD_TOO_LARGE" ? "PAYLOAD_TOO_LARGE" : "CONFIG_INVALID";
|
|
4010
|
+
return { status: 400, code: code2, message: redact(error.message) };
|
|
4059
4011
|
}
|
|
4060
4012
|
const code = error instanceof IpcError ? error.code : "INTERNAL";
|
|
4061
4013
|
const message = redact(error instanceof Error ? error.message : String(error));
|
|
4062
|
-
|
|
4014
|
+
logger?.("route.error", { pathname: current.pathname, method: current.method, code, message });
|
|
4063
4015
|
const status = code === "CONFIG_INVALID" ? (
|
|
4064
4016
|
// 「已有一次运行在进行中」是并发冲突而非参数错误:用 409,前端据此禁用按钮并提示。
|
|
4065
4017
|
message.includes("\u8FD0\u884C\u5728\u8FDB\u884C\u4E2D") ? 409 : 400
|
|
4066
4018
|
) : code === "NOT_FOUND" ? 404 : 500;
|
|
4067
|
-
|
|
4068
|
-
}
|
|
4019
|
+
return { status, code, message };
|
|
4020
|
+
},
|
|
4021
|
+
logger
|
|
4022
|
+
});
|
|
4023
|
+
return async function routeHandler(request, response) {
|
|
4024
|
+
await handler(request, response);
|
|
4069
4025
|
};
|
|
4070
4026
|
}
|
|
4071
|
-
async function dispatch(method, pathname, url,
|
|
4027
|
+
async function dispatch(method, pathname, url, body, deps) {
|
|
4072
4028
|
const env = deps.env ?? process.env;
|
|
4073
4029
|
const settings = deps.store.readSettings();
|
|
4074
4030
|
if (method === "GET" && pathname === "/state") return statePayload(deps, settings);
|
|
@@ -4079,7 +4035,6 @@ async function dispatch(method, pathname, url, request, deps) {
|
|
|
4079
4035
|
}
|
|
4080
4036
|
if (method === "POST" && pathname === "/update") {
|
|
4081
4037
|
if (deps.update === void 0) throw new IpcError("NOT_FOUND", "\u81EA\u66F4\u65B0\u670D\u52A1\u4E0D\u53EF\u7528");
|
|
4082
|
-
const body = await readBody2(request);
|
|
4083
4038
|
const version = typeof body.version === "string" && body.version.trim() !== "" ? body.version.trim() : void 0;
|
|
4084
4039
|
const result = await deps.update.apply(version === void 0 ? {} : { version });
|
|
4085
4040
|
return { result, update: deps.update.view() };
|
|
@@ -4095,7 +4050,6 @@ async function dispatch(method, pathname, url, request, deps) {
|
|
|
4095
4050
|
return { downloaded: true, path: core.path, tag: core.tag ?? null, core: status };
|
|
4096
4051
|
}
|
|
4097
4052
|
if (method === "POST" && pathname === "/config") {
|
|
4098
|
-
const body = await readBody2(request);
|
|
4099
4053
|
const incoming = normalizeSettings(body.settings ?? body);
|
|
4100
4054
|
const section = typeof body.section === "string" && SETTINGS_SECTIONS.includes(body.section) ? body.section : void 0;
|
|
4101
4055
|
let next = section === void 0 ? incoming : mergeSettingsSection(settings, incoming, section);
|
|
@@ -4114,7 +4068,6 @@ async function dispatch(method, pathname, url, request, deps) {
|
|
|
4114
4068
|
return { saved: true, settings: next, problems: [] };
|
|
4115
4069
|
}
|
|
4116
4070
|
if (method === "POST" && pathname === "/preflight") {
|
|
4117
|
-
const body = await readBody2(request);
|
|
4118
4071
|
const candidate = body.settings === void 0 ? settings : normalizeSettings(body.settings);
|
|
4119
4072
|
const result = await preflightModel({
|
|
4120
4073
|
settings: candidate,
|
|
@@ -4125,7 +4078,6 @@ async function dispatch(method, pathname, url, request, deps) {
|
|
|
4125
4078
|
return { preflight: result };
|
|
4126
4079
|
}
|
|
4127
4080
|
if (method === "POST" && pathname === "/run") {
|
|
4128
|
-
const body = await readBody2(request);
|
|
4129
4081
|
const base = {
|
|
4130
4082
|
dryRun: body.dryRun === true,
|
|
4131
4083
|
...typeof body.date === "string" && body.date !== "" ? { date: body.date } : {},
|
|
@@ -4143,7 +4095,6 @@ async function dispatch(method, pathname, url, request, deps) {
|
|
|
4143
4095
|
return { cancelled: deps.runner.cancel() };
|
|
4144
4096
|
}
|
|
4145
4097
|
if (method === "POST" && pathname === "/releases/run") {
|
|
4146
|
-
const body = await readBody2(request);
|
|
4147
4098
|
let repo;
|
|
4148
4099
|
if (body.repo !== void 0) {
|
|
4149
4100
|
if (typeof body.repo !== "string" || !isValidRepo(body.repo.trim())) {
|
|
@@ -4183,15 +4134,14 @@ async function dispatch(method, pathname, url, request, deps) {
|
|
|
4183
4134
|
{ store: deps.store, env }
|
|
4184
4135
|
);
|
|
4185
4136
|
if (!result.ok) {
|
|
4186
|
-
throw new IpcError("SUBSCRIBE_FAILED", result.error?.message ?? `\u8BFB\u53D6 ${repo} \u7684\
|
|
4137
|
+
throw new IpcError("SUBSCRIBE_FAILED", result.error?.message ?? `\u8BFB\u53D6 ${repo} \u7684\u53D8\u66F4\u6587\u6863\u5931\u8D25`);
|
|
4187
4138
|
}
|
|
4188
4139
|
if (result.doc === void 0) {
|
|
4189
|
-
throw new IpcError("SUBSCRIBE_FAILED", `\u6838\u5FC3\u6CA1\u6709\u8FD4\u56DE ${repo} \u7684\
|
|
4140
|
+
throw new IpcError("SUBSCRIBE_FAILED", `\u6838\u5FC3\u6CA1\u6709\u8FD4\u56DE ${repo} \u7684\u53D8\u66F4\u6587\u6863`);
|
|
4190
4141
|
}
|
|
4191
4142
|
return { ...result.doc };
|
|
4192
4143
|
}
|
|
4193
4144
|
if (method === "POST" && pathname === "/subscriptions") {
|
|
4194
|
-
const body = await readBody2(request);
|
|
4195
4145
|
const action = body.action === "add" || body.action === "remove" ? body.action : void 0;
|
|
4196
4146
|
if (action === void 0) throw new IpcError("CONFIG_INVALID", "action \u5FC5\u987B\u662F add \u6216 remove");
|
|
4197
4147
|
const repos = Array.isArray(body.repos) ? body.repos.filter((item) => typeof item === "string" && item.trim() !== "").map((item) => item.trim()) : typeof body.repo === "string" && body.repo.trim() !== "" ? [body.repo.trim()] : [];
|
|
@@ -4206,7 +4156,6 @@ async function dispatch(method, pathname, url, request, deps) {
|
|
|
4206
4156
|
return { repos: latest.ok ? latest.repos : [], items: latest.ok ? latest.items ?? [] : [] };
|
|
4207
4157
|
}
|
|
4208
4158
|
if (method === "POST" && pathname === "/github/test") {
|
|
4209
|
-
const body = await readBody2(request);
|
|
4210
4159
|
const candidate = body.settings === void 0 ? settings : normalizeSettings(body.settings);
|
|
4211
4160
|
const probe = await probeGithubAuth({
|
|
4212
4161
|
credentials: credentialServices(deps.get),
|
|
@@ -4225,7 +4174,6 @@ async function dispatch(method, pathname, url, request, deps) {
|
|
|
4225
4174
|
return { providers: candidates, defaultSelection: readDefaultSelection(deps.get) ?? null };
|
|
4226
4175
|
}
|
|
4227
4176
|
if (method === "POST" && pathname === "/quickfill") {
|
|
4228
|
-
const body = await readBody2(request);
|
|
4229
4177
|
const candidates = await listProviderCandidates({
|
|
4230
4178
|
llm: llmServices(deps.get),
|
|
4231
4179
|
credentials: credentialServices(deps.get),
|
|
@@ -4357,6 +4305,7 @@ __export(update_exports, {
|
|
|
4357
4305
|
});
|
|
4358
4306
|
import { normalizeProfile } from "@morehao/dsh-plugin-kit";
|
|
4359
4307
|
import { createPluginUpdater } from "@morehao/dsh-plugin-kit/update";
|
|
4308
|
+
import { spawnCollect as execCapture5, sanitizedEnv as sanitizedEnv3 } from "@morehao/dsh-plugin-kit/exec";
|
|
4360
4309
|
function pnpmViewRunner(get, env, exec) {
|
|
4361
4310
|
return async (spec) => {
|
|
4362
4311
|
const profile = normalizeProfile(get("profileContext"));
|
|
@@ -4367,7 +4316,7 @@ function pnpmViewRunner(get, env, exec) {
|
|
|
4367
4316
|
try {
|
|
4368
4317
|
result = await exec(command, [...prefix, "view", spec, "version", "--json"], {
|
|
4369
4318
|
cwd: profile.dir,
|
|
4370
|
-
env:
|
|
4319
|
+
env: sanitizedEnv3(env),
|
|
4371
4320
|
timeoutMs: 8e3,
|
|
4372
4321
|
maxStdout: 64 * 1024,
|
|
4373
4322
|
maxStderr: 16 * 1024
|
|
@@ -4389,7 +4338,7 @@ function pnpmViewRunner(get, env, exec) {
|
|
|
4389
4338
|
};
|
|
4390
4339
|
}
|
|
4391
4340
|
function createUpdateService(deps) {
|
|
4392
|
-
const exec = deps.exec ??
|
|
4341
|
+
const exec = deps.exec ?? execCapture5;
|
|
4393
4342
|
return createPluginUpdater({
|
|
4394
4343
|
meta: deps.meta,
|
|
4395
4344
|
getPluginManager: () => deps.get("pluginManager"),
|
|
@@ -4505,7 +4454,7 @@ function createTrendingRunTool(runner) {
|
|
|
4505
4454
|
if (summary.tokens !== void 0) {
|
|
4506
4455
|
const parts = [`\u672C\u6B21 tokens ${summary.tokens.toLocaleString("en-US")}`];
|
|
4507
4456
|
if (summary.releases !== void 0 && summary.releases.enabled) {
|
|
4508
|
-
parts.push(`\
|
|
4457
|
+
parts.push(`\u8BA2\u9605 ${summary.releases.newReleases} \u4E2A\u65B0\u7248\u672C / ${summary.releases.repos} \u4E2A\u4ED3\u5E93`);
|
|
4509
4458
|
}
|
|
4510
4459
|
lines.push(`\xB7 ${parts.join(" \xB7 ")}`);
|
|
4511
4460
|
}
|
package/lib/index.js
CHANGED
package/lib/internal.d.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { ErrorCode, FileArtifact, Usage, ReleasesReport, SubscriptionItem, SubscriptionDoc, SubscriptionStatus, ErrorInfo, RunRequest, RunResult, State, StateRun, SubscriptionList, SubscriptionVolume } from '@morehao/trendradar-contract';
|
|
2
|
+
import { ExecOptions, ExecResult } from '@morehao/dsh-plugin-kit/exec';
|
|
3
|
+
import * as exec from '@morehao/dsh-plugin-kit/exec';
|
|
4
|
+
export { exec };
|
|
5
|
+
import { normalizeRepositoryUrl } from '@morehao/dsh-plugin-kit/github';
|
|
2
6
|
import http from 'node:http';
|
|
3
7
|
import { Updater, PluginMeta, Logger } from '@morehao/dsh-plugin-kit/update';
|
|
4
8
|
|
|
@@ -930,40 +934,6 @@ declare namespace channel {
|
|
|
930
934
|
export { type channel_ChannelKind as ChannelKind, type channel_ConfigChannel as ConfigChannel, channel_WRITE_TIMEOUT_MS as WRITE_TIMEOUT_MS, channel_openConfigChannel as openConfigChannel, channel_removeChannelDir as removeChannelDir };
|
|
931
935
|
}
|
|
932
936
|
|
|
933
|
-
interface ExecResult {
|
|
934
|
-
code: number | null;
|
|
935
|
-
signal: NodeJS.Signals | null;
|
|
936
|
-
stdout: string;
|
|
937
|
-
stderr: string;
|
|
938
|
-
timedOut: boolean;
|
|
939
|
-
aborted: boolean;
|
|
940
|
-
durationMs: number;
|
|
941
|
-
}
|
|
942
|
-
declare function sanitizedEnv(source?: NodeJS.ProcessEnv, extra?: Record<string, string | undefined>): Record<string, string>;
|
|
943
|
-
interface ExecOptions {
|
|
944
|
-
env?: NodeJS.ProcessEnv;
|
|
945
|
-
cwd?: string;
|
|
946
|
-
timeoutMs?: number;
|
|
947
|
-
signal?: AbortSignal;
|
|
948
|
-
maxStdout?: number;
|
|
949
|
-
maxStderr?: number;
|
|
950
|
-
/** 写入子进程 stdin 的内容(写完即关闭);省略则 stdin 为 ignore。 */
|
|
951
|
-
input?: string;
|
|
952
|
-
}
|
|
953
|
-
/**
|
|
954
|
-
* 执行一次短命令并收集输出(握手、共存探测都走这里)。
|
|
955
|
-
* 超时与取消都先 SIGTERM、3 s 后 SIGKILL——核心是单进程,不需要 process group。
|
|
956
|
-
*/
|
|
957
|
-
declare function execCapture(file: string, args: string[], options?: ExecOptions): Promise<ExecResult>;
|
|
958
|
-
|
|
959
|
-
type exec_ExecOptions = ExecOptions;
|
|
960
|
-
type exec_ExecResult = ExecResult;
|
|
961
|
-
declare const exec_execCapture: typeof execCapture;
|
|
962
|
-
declare const exec_sanitizedEnv: typeof sanitizedEnv;
|
|
963
|
-
declare namespace exec {
|
|
964
|
-
export { type exec_ExecOptions as ExecOptions, type exec_ExecResult as ExecResult, exec_execCapture as execCapture, exec_sanitizedEnv as sanitizedEnv };
|
|
965
|
-
}
|
|
966
|
-
|
|
967
937
|
declare const DEFAULT_RUN_TIMEOUT_MS = 120000;
|
|
968
938
|
interface RunCoreOptions {
|
|
969
939
|
core: CoreLocation;
|
|
@@ -1654,13 +1624,24 @@ declare namespace subscribe {
|
|
|
1654
1624
|
export { subscribe_RELEASES_TIMEOUT_MS as RELEASES_TIMEOUT_MS, subscribe_SUBSCRIBE_TIMEOUT_MS as SUBSCRIBE_TIMEOUT_MS, type subscribe_SubscribeDeps as SubscribeDeps, subscribe_isValidRepo as isValidRepo, subscribe_runSubscribe as runSubscribe };
|
|
1655
1625
|
}
|
|
1656
1626
|
|
|
1627
|
+
/**
|
|
1628
|
+
* 插件自身元数据:包名、版本、仓库地址。
|
|
1629
|
+
*
|
|
1630
|
+
* `/state.plugin` 是界面上「关于」的唯一来源:版本不能硬编码在客户端,仓库地址
|
|
1631
|
+
* 也不能从客户端猜。`package.json.repository.url` 常见形态是
|
|
1632
|
+
* `git+https://github.com/o/r.git` 或 `git@github.com:o/r.git`,统一规范化成
|
|
1633
|
+
* `https://github.com/o/r`;解析不了就返回 undefined,界面隐藏外链而不是猜。
|
|
1634
|
+
*
|
|
1635
|
+
* 读包与规范化仓库地址都交给 `@morehao/dsh-plugin-kit` 的 `./meta` + `./github`;
|
|
1636
|
+
* 这里保留 `readPluginInfo()` / `normalizeRepositoryUrl()` 两个对内部(测试与 index)
|
|
1637
|
+
* 的既有导出面,形状不变。
|
|
1638
|
+
*/
|
|
1639
|
+
|
|
1657
1640
|
interface PluginInfo {
|
|
1658
1641
|
name: string;
|
|
1659
1642
|
version: string;
|
|
1660
1643
|
repository?: string;
|
|
1661
1644
|
}
|
|
1662
|
-
/** 只放行 GitHub 的 http(s) 地址;ssh / git+ 前缀先归一化。 */
|
|
1663
|
-
declare function normalizeRepositoryUrl(value: unknown): string | undefined;
|
|
1664
1645
|
declare function readPluginInfo(): PluginInfo;
|
|
1665
1646
|
|
|
1666
1647
|
type pluginInfo_PluginInfo = PluginInfo;
|
|
@@ -2164,4 +2145,4 @@ declare namespace tools {
|
|
|
2164
2145
|
export { tools_createTrendingHistoryTool as createTrendingHistoryTool, tools_createTrendingRunTool as createTrendingRunTool };
|
|
2165
2146
|
}
|
|
2166
2147
|
|
|
2167
|
-
export { channel, config, core, credentials, errors,
|
|
2148
|
+
export { channel, config, core, credentials, errors, github, handshake$1 as handshake, importCli, ipc, locate, paths, pendingPr, pluginInfo, preflight, proxy, quickfill, release, repo, routes, run, runner, schedule, state, subscribe, tools, update as updateService, version };
|
package/lib/internal.js
CHANGED
|
@@ -26,17 +26,17 @@ import {
|
|
|
26
26
|
tools_exports,
|
|
27
27
|
update_exports,
|
|
28
28
|
version_exports
|
|
29
|
-
} from "./chunk-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
} from "./chunk-YJ5GF3MW.js";
|
|
30
|
+
|
|
31
|
+
// src/internal.ts
|
|
32
|
+
import * as exec from "@morehao/dsh-plugin-kit/exec";
|
|
33
33
|
export {
|
|
34
34
|
channel_exports as channel,
|
|
35
35
|
config_exports as config,
|
|
36
36
|
core_exports as core,
|
|
37
37
|
credentials_exports as credentials,
|
|
38
38
|
errors_exports as errors,
|
|
39
|
-
|
|
39
|
+
exec,
|
|
40
40
|
github_exports as github,
|
|
41
41
|
handshake_exports as handshake,
|
|
42
42
|
import_cli_exports as importCli,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@morehao/dsh-github-trending",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.9",
|
|
4
4
|
"description": "GitHub 趋势日报插件:每天定时 spawn 本地 trendradar 核心,抓取 Trending、生成中文简介与总结,提交到你的仓库并自动合并 PR。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
}
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@morehao/dsh-plugin-kit": "0.
|
|
53
|
+
"@morehao/dsh-plugin-kit": "^0.3.1",
|
|
54
54
|
"@morehao/trendradar-contract": "0.5.0"
|
|
55
55
|
},
|
|
56
56
|
"dsh": {
|
package/lib/chunk-R7BK7SJK.js
DELETED
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __export = (target, all) => {
|
|
3
|
-
for (var name in all)
|
|
4
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
// src/core/exec.ts
|
|
8
|
-
var exec_exports = {};
|
|
9
|
-
__export(exec_exports, {
|
|
10
|
-
execCapture: () => execCapture,
|
|
11
|
-
sanitizedEnv: () => sanitizedEnv
|
|
12
|
-
});
|
|
13
|
-
import { spawn } from "child_process";
|
|
14
|
-
var ENV_KEYS = [
|
|
15
|
-
"PATH",
|
|
16
|
-
"HOME",
|
|
17
|
-
"USER",
|
|
18
|
-
"LOGNAME",
|
|
19
|
-
"SHELL",
|
|
20
|
-
"TMPDIR",
|
|
21
|
-
"TMP",
|
|
22
|
-
"TEMP",
|
|
23
|
-
"LANG",
|
|
24
|
-
"LC_ALL",
|
|
25
|
-
"LC_CTYPE",
|
|
26
|
-
"SSL_CERT_FILE",
|
|
27
|
-
"SSL_CERT_DIR",
|
|
28
|
-
"GIT_AUTHOR_NAME",
|
|
29
|
-
"GIT_AUTHOR_EMAIL",
|
|
30
|
-
"GIT_COMMITTER_NAME",
|
|
31
|
-
"GIT_COMMITTER_EMAIL",
|
|
32
|
-
"GIT_CONFIG_GLOBAL",
|
|
33
|
-
"GIT_SSH_COMMAND"
|
|
34
|
-
];
|
|
35
|
-
var PROXY_KEYS = [
|
|
36
|
-
"HTTP_PROXY",
|
|
37
|
-
"HTTPS_PROXY",
|
|
38
|
-
"NO_PROXY",
|
|
39
|
-
"ALL_PROXY",
|
|
40
|
-
"http_proxy",
|
|
41
|
-
"https_proxy",
|
|
42
|
-
"no_proxy",
|
|
43
|
-
"all_proxy"
|
|
44
|
-
];
|
|
45
|
-
function sanitizedEnv(source = process.env, extra = {}) {
|
|
46
|
-
const env = {};
|
|
47
|
-
for (const key of [...ENV_KEYS, ...PROXY_KEYS]) {
|
|
48
|
-
const value = source[key];
|
|
49
|
-
if (typeof value === "string" && value !== "") env[key] = value;
|
|
50
|
-
}
|
|
51
|
-
for (const [key, value] of Object.entries(extra)) {
|
|
52
|
-
if (typeof value === "string" && value !== "") env[key] = value;
|
|
53
|
-
}
|
|
54
|
-
return env;
|
|
55
|
-
}
|
|
56
|
-
function killTree(child, signal) {
|
|
57
|
-
try {
|
|
58
|
-
child.kill(signal);
|
|
59
|
-
} catch {
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
async function execCapture(file, args, options = {}) {
|
|
63
|
-
const started = Date.now();
|
|
64
|
-
const timeoutMs = options.timeoutMs ?? 1e4;
|
|
65
|
-
const maxStdout = options.maxStdout ?? 1024 * 1024;
|
|
66
|
-
const maxStderr = options.maxStderr ?? 1024 * 1024;
|
|
67
|
-
const child = spawn(file, args, {
|
|
68
|
-
cwd: options.cwd,
|
|
69
|
-
env: options.env ?? process.env,
|
|
70
|
-
stdio: [options.input === void 0 ? "ignore" : "pipe", "pipe", "pipe"],
|
|
71
|
-
windowsHide: true
|
|
72
|
-
});
|
|
73
|
-
if (options.input !== void 0) {
|
|
74
|
-
child.stdin?.on("error", () => void 0);
|
|
75
|
-
child.stdin?.end(options.input);
|
|
76
|
-
}
|
|
77
|
-
let stdout = "";
|
|
78
|
-
let stderr = "";
|
|
79
|
-
let timedOut = false;
|
|
80
|
-
let aborted = false;
|
|
81
|
-
const hardKill = setTimeout(() => killTree(child, "SIGKILL"), timeoutMs + 3e3);
|
|
82
|
-
const timer = setTimeout(() => {
|
|
83
|
-
timedOut = true;
|
|
84
|
-
killTree(child, "SIGTERM");
|
|
85
|
-
}, timeoutMs);
|
|
86
|
-
const onAbort = () => {
|
|
87
|
-
aborted = true;
|
|
88
|
-
killTree(child, "SIGTERM");
|
|
89
|
-
};
|
|
90
|
-
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
91
|
-
child.stdout?.setEncoding("utf8");
|
|
92
|
-
child.stdout?.on("data", (chunk) => {
|
|
93
|
-
if (stdout.length < maxStdout) stdout += chunk;
|
|
94
|
-
});
|
|
95
|
-
child.stderr?.setEncoding("utf8");
|
|
96
|
-
child.stderr?.on("data", (chunk) => {
|
|
97
|
-
if (stderr.length < maxStderr) stderr += chunk;
|
|
98
|
-
});
|
|
99
|
-
const result = await new Promise((resolve, reject) => {
|
|
100
|
-
child.on("error", (error) => reject(error));
|
|
101
|
-
child.on("close", (code, signal) => resolve({ code, signal }));
|
|
102
|
-
});
|
|
103
|
-
clearTimeout(timer);
|
|
104
|
-
clearTimeout(hardKill);
|
|
105
|
-
options.signal?.removeEventListener("abort", onAbort);
|
|
106
|
-
return {
|
|
107
|
-
...result,
|
|
108
|
-
stdout,
|
|
109
|
-
stderr,
|
|
110
|
-
timedOut,
|
|
111
|
-
aborted,
|
|
112
|
-
durationMs: Date.now() - started
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export {
|
|
117
|
-
__export,
|
|
118
|
-
sanitizedEnv,
|
|
119
|
-
execCapture,
|
|
120
|
-
exec_exports
|
|
121
|
-
};
|