@morehao/dsh-github-trending 0.8.22 → 0.9.0
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/client.js +48 -2
- package/lib/{chunk-SLY2RKCZ.js → chunk-JMIWABMY.js} +82 -136
- package/lib/index.js +1 -1
- package/lib/internal.d.ts +38 -49
- package/lib/internal.js +3 -5
- package/package.json +3 -3
package/client.js
CHANGED
|
@@ -457,6 +457,14 @@ var DICT = {
|
|
|
457
457
|
"summarize.readmeChars": "README 摘录长度",
|
|
458
458
|
"summarize.readmeChars.help": "enrich 为 readme 时,每个仓库 README 摘录的最大字符数(超出截断)。",
|
|
459
459
|
"summarize.enrichNote": "外部增强需要只读 token:enrich=repo/readme 建议配置 GITHUB_READ_TOKEN(独立只读);readme 模式在网络慢时可能因预算耗尽跳过部分仓库(自动降级,不影响运行)。",
|
|
460
|
+
"card.observe.title": "本地观测库",
|
|
461
|
+
"observe.enabled": "启用观测库",
|
|
462
|
+
"observe.enabled.help": "每日记录候选仓库的 star 快照,用本地差分算出「今日新增」,不再依赖趋势页那行数字;关闭即回到「增量只来自趋势页」的旧行为。数据存在本机 $DSH_HOME,不进归档仓库。",
|
|
463
|
+
"observe.backfillDays": "回填天数",
|
|
464
|
+
"observe.backfillDays.help": "首次见到的仓库从 GitHub 历史接口回填多少天(0=不回填,从今天开始攒;上限 365)。",
|
|
465
|
+
"observe.maxCandidates": "候选上限",
|
|
466
|
+
"observe.maxCandidates.help": "单次运行最多记多少个候选仓库(越多覆盖越广、请求越多;建议 300,约 3 个批量请求/天)。",
|
|
467
|
+
"observe.disabledNote": "观测库已关闭:本次运行的「今日新增」仍来自趋势页/搜索,可能为 0。",
|
|
460
468
|
"card.releases.title": "订阅",
|
|
461
469
|
"card.releases.hint": "对应核心 releases.*(core 0.5.0+)",
|
|
462
470
|
"releases.includePrerelease": "含预发布",
|
|
@@ -1013,6 +1021,14 @@ var DICT = {
|
|
|
1013
1021
|
"summarize.readmeChars": "README excerpt chars",
|
|
1014
1022
|
"summarize.readmeChars.help": "Max README characters excerpted per repo when enrich=readme (longer text is truncated).",
|
|
1015
1023
|
"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).",
|
|
1024
|
+
"card.observe.title": "Local observation store",
|
|
1025
|
+
"observe.enabled": "Enable observation store",
|
|
1026
|
+
"observe.enabled.help": 'Records a daily star snapshot of candidate repos and derives "stars today" from local diffs instead of the trending-page number; turn it off to fall back to the old "increment only from the trending page" behaviour. Data lives in $DSH_HOME, never in the archive repo.',
|
|
1027
|
+
"observe.backfillDays": "Backfill days",
|
|
1028
|
+
"observe.backfillDays.help": "How many days to backfill a first-seen repo from GitHub history (0 = no backfill, accumulate from today; max 365).",
|
|
1029
|
+
"observe.maxCandidates": "Candidate cap",
|
|
1030
|
+
"observe.maxCandidates.help": "Max candidate repos recorded per run (more = broader coverage and more requests; 300 ≈ 3 batch requests/day is recommended).",
|
|
1031
|
+
"observe.disabledNote": `Observation store is off: this run's "stars today" still comes from the trending page/search and may be 0.`,
|
|
1016
1032
|
"card.releases.title": "Subscriptions",
|
|
1017
1033
|
"card.releases.hint": "Maps to core releases.* (core 0.5.0+)",
|
|
1018
1034
|
"releases.includePrerelease": "Include pre-releases",
|
|
@@ -2242,7 +2258,7 @@ function sectionSlice(settings, section) {
|
|
|
2242
2258
|
case "auth":
|
|
2243
2259
|
return { github: settings.github };
|
|
2244
2260
|
case "scope":
|
|
2245
|
-
return { trending: settings.trending, schedule: settings.schedule, summarize: settings.summarize };
|
|
2261
|
+
return { trending: settings.trending, schedule: settings.schedule, summarize: settings.summarize, observe: settings.observe };
|
|
2246
2262
|
case "releases":
|
|
2247
2263
|
return { releases: settings.releases };
|
|
2248
2264
|
}
|
|
@@ -2730,6 +2746,8 @@ function SettingsView(props) {
|
|
|
2730
2746
|
)
|
|
2731
2747
|
)
|
|
2732
2748
|
);
|
|
2749
|
+
const observeOf = (s) => s.observe ?? { enabled: true, backfillDays: 30, maxCandidates: 300 };
|
|
2750
|
+
const observe = observeOf(draft);
|
|
2733
2751
|
const scopeCard = h(
|
|
2734
2752
|
Card,
|
|
2735
2753
|
{
|
|
@@ -2822,7 +2840,35 @@ function SettingsView(props) {
|
|
|
2822
2840
|
next.summarize.readmeChars = Math.round(Number(value) || 0);
|
|
2823
2841
|
}) })
|
|
2824
2842
|
),
|
|
2825
|
-
draft.summarize.enrich === "none" ? null : h(Alert, { kind: "warn" }, h("div", null, t("summarize.enrichNote")))
|
|
2843
|
+
draft.summarize.enrich === "none" ? null : h(Alert, { kind: "warn" }, h("div", null, t("summarize.enrichNote"))),
|
|
2844
|
+
// 本地 star 观测库(核心 observe.*):旧设置里可能还没有该字段,先取默认再编辑。
|
|
2845
|
+
// 观测库让「今日新增」来自本地每日快照的差分;关闭即回到「增量只来自趋势页」的旧行为。
|
|
2846
|
+
h("h4", { className: "dshgt-subhead" }, t("card.observe.title")),
|
|
2847
|
+
h(
|
|
2848
|
+
Row,
|
|
2849
|
+
{ label: t("observe.enabled"), help: t("observe.enabled.help") },
|
|
2850
|
+
h(Toggle, {
|
|
2851
|
+
checked: observe.enabled,
|
|
2852
|
+
onChange: (value) => update((next) => {
|
|
2853
|
+
next.observe = { ...observeOf(next), enabled: value };
|
|
2854
|
+
})
|
|
2855
|
+
})
|
|
2856
|
+
),
|
|
2857
|
+
h(
|
|
2858
|
+
Row,
|
|
2859
|
+
{ label: t("observe.backfillDays"), help: t("observe.backfillDays.help") },
|
|
2860
|
+
h(Input, { mono: true, width: 90, value: String(observe.backfillDays), onInput: (value) => update((next) => {
|
|
2861
|
+
next.observe = { ...observeOf(next), backfillDays: Math.round(Number(value) || 0) };
|
|
2862
|
+
}) })
|
|
2863
|
+
),
|
|
2864
|
+
h(
|
|
2865
|
+
Row,
|
|
2866
|
+
{ label: t("observe.maxCandidates"), help: t("observe.maxCandidates.help") },
|
|
2867
|
+
h(Input, { mono: true, width: 90, value: String(observe.maxCandidates), onInput: (value) => update((next) => {
|
|
2868
|
+
next.observe = { ...observeOf(next), maxCandidates: Math.round(Number(value) || 0) };
|
|
2869
|
+
}) })
|
|
2870
|
+
),
|
|
2871
|
+
observe.enabled ? null : h(Alert, { kind: "info" }, h("div", null, t("observe.disabledNote")))
|
|
2826
2872
|
);
|
|
2827
2873
|
const releaseSchedule = draft.releases.schedule ?? { enabled: false, weekday: 1, time: "08:00:00", timezone: "Asia/Shanghai" };
|
|
2828
2874
|
const releaseConcurrency = draft.releases.concurrency ?? "auto";
|
|
@@ -69,6 +69,7 @@ var DEFAULT_SETTINGS = {
|
|
|
69
69
|
enrichTimeoutSeconds: 5,
|
|
70
70
|
enrichBudgetSeconds: 8
|
|
71
71
|
},
|
|
72
|
+
observe: { enabled: true, backfillDays: 30, maxCandidates: 300 },
|
|
72
73
|
releases: {
|
|
73
74
|
includePrerelease: false,
|
|
74
75
|
includeDrafts: false,
|
|
@@ -102,6 +103,7 @@ function sectionOfField(field) {
|
|
|
102
103
|
if (field.startsWith("github.")) return "auth";
|
|
103
104
|
if (field.startsWith("trending.")) return "scope";
|
|
104
105
|
if (field.startsWith("summarize.")) return "summarize";
|
|
106
|
+
if (field.startsWith("observe.")) return "scope";
|
|
105
107
|
if (field.startsWith("releases.")) return "releases";
|
|
106
108
|
if (field.startsWith("schedule.")) return "schedule";
|
|
107
109
|
if (field === "corePath" || field === "coreAutoDownload" || field === "network.proxy") return "source";
|
|
@@ -128,6 +130,7 @@ function mergeSettingsSection(stored, incoming, section) {
|
|
|
128
130
|
break;
|
|
129
131
|
case "scope":
|
|
130
132
|
next.trending = incoming.trending;
|
|
133
|
+
next.observe = incoming.observe;
|
|
131
134
|
break;
|
|
132
135
|
case "summarize":
|
|
133
136
|
next.summarize = incoming.summarize;
|
|
@@ -171,6 +174,7 @@ function normalizeSettings(input) {
|
|
|
171
174
|
const github = raw.github ?? {};
|
|
172
175
|
const trending = raw.trending ?? {};
|
|
173
176
|
const summarize = raw.summarize ?? {};
|
|
177
|
+
const observe = raw.observe ?? {};
|
|
174
178
|
const releases = raw.releases ?? {};
|
|
175
179
|
const releasesSchedule = releases.schedule ?? {};
|
|
176
180
|
const output = raw.output ?? {};
|
|
@@ -225,6 +229,11 @@ function normalizeSettings(input) {
|
|
|
225
229
|
enrichTimeoutSeconds: Math.round(num(summarize.enrichTimeoutSeconds, DEFAULT_SETTINGS.summarize.enrichTimeoutSeconds)),
|
|
226
230
|
enrichBudgetSeconds: Math.round(num(summarize.enrichBudgetSeconds, DEFAULT_SETTINGS.summarize.enrichBudgetSeconds))
|
|
227
231
|
},
|
|
232
|
+
observe: {
|
|
233
|
+
enabled: bool(observe.enabled, DEFAULT_SETTINGS.observe.enabled),
|
|
234
|
+
backfillDays: Math.round(num(observe.backfillDays, DEFAULT_SETTINGS.observe.backfillDays)),
|
|
235
|
+
maxCandidates: Math.round(num(observe.maxCandidates, DEFAULT_SETTINGS.observe.maxCandidates))
|
|
236
|
+
},
|
|
228
237
|
releases: {
|
|
229
238
|
includePrerelease: bool(releases.includePrerelease, DEFAULT_SETTINGS.releases.includePrerelease),
|
|
230
239
|
includeDrafts: bool(releases.includeDrafts, DEFAULT_SETTINGS.releases.includeDrafts),
|
|
@@ -332,6 +341,13 @@ function validateSettings(settings, providers = CORE_PROVIDERS) {
|
|
|
332
341
|
if (!Number.isInteger(summarize.readmeChars) || summarize.readmeChars <= 0) {
|
|
333
342
|
problems.push({ field: "summarize.readmeChars", code: "CONFIG_INVALID", message: "readmeChars \u5FC5\u987B\u662F\u6B63\u6574\u6570" });
|
|
334
343
|
}
|
|
344
|
+
const { observe } = settings;
|
|
345
|
+
if (!Number.isInteger(observe.backfillDays) || observe.backfillDays < 0 || observe.backfillDays > 365) {
|
|
346
|
+
problems.push({ field: "observe.backfillDays", code: "CONFIG_INVALID", message: "backfillDays \u5FC5\u987B\u662F 0\u2013365 \u7684\u6574\u6570" });
|
|
347
|
+
}
|
|
348
|
+
if (!Number.isInteger(observe.maxCandidates) || observe.maxCandidates < 1 || observe.maxCandidates > 1e3) {
|
|
349
|
+
problems.push({ field: "observe.maxCandidates", code: "CONFIG_INVALID", message: "maxCandidates \u5FC5\u987B\u662F 1\u20131000 \u7684\u6574\u6570" });
|
|
350
|
+
}
|
|
335
351
|
if (releases.period !== "weekly") {
|
|
336
352
|
problems.push({
|
|
337
353
|
field: "releases.period",
|
|
@@ -422,6 +438,11 @@ function toCoreConfig(settings, apiKey, baseURLOverride, period, repoCount = 0)
|
|
|
422
438
|
enrichTimeoutSeconds: settings.summarize.enrichTimeoutSeconds,
|
|
423
439
|
enrichBudgetSeconds: settings.summarize.enrichBudgetSeconds
|
|
424
440
|
},
|
|
441
|
+
observe: {
|
|
442
|
+
enabled: settings.observe.enabled,
|
|
443
|
+
backfillDays: settings.observe.backfillDays,
|
|
444
|
+
maxCandidates: settings.observe.maxCandidates
|
|
445
|
+
},
|
|
425
446
|
releases: {
|
|
426
447
|
// 发版订阅常开:插件侧不再提供开关,是否产出由订阅列表决定。
|
|
427
448
|
enabled: true,
|
|
@@ -1031,8 +1052,9 @@ __export(ipc_exports, {
|
|
|
1031
1052
|
parseSubscribeResult: () => parseSubscribeResult,
|
|
1032
1053
|
parseVersionInfo: () => parseVersionInfo
|
|
1033
1054
|
});
|
|
1055
|
+
import { createHash } from "crypto";
|
|
1034
1056
|
import { validators } from "@morehao/trendradar-contract";
|
|
1035
|
-
var IPC_SCHEMA_VERSION =
|
|
1057
|
+
var IPC_SCHEMA_VERSION = 3;
|
|
1036
1058
|
var SUPPORTED_DIGEST_SCHEMA = 2;
|
|
1037
1059
|
var SUPPORTED_CONTRACT_MAJOR = 0;
|
|
1038
1060
|
var SUBSCRIPTION_STATUSES = ["baseline", "ok", "no_change", "rate_limited", "failed"];
|
|
@@ -1091,20 +1113,50 @@ function normalizeError(value) {
|
|
|
1091
1113
|
...isRecord(value.details) ? { details: value.details } : {}
|
|
1092
1114
|
};
|
|
1093
1115
|
}
|
|
1116
|
+
function parseDigest(value, files) {
|
|
1117
|
+
if (value === void 0 || value === null) return void 0;
|
|
1118
|
+
if (!isRecord(value)) throw new IpcError("IPC_INVALID", "\u6838\u5FC3 run --json \u7684 digest \u4E0D\u662F\u5BF9\u8C61");
|
|
1119
|
+
const file = value.path;
|
|
1120
|
+
const bytes = value.bytes;
|
|
1121
|
+
const sha256 = value.sha256;
|
|
1122
|
+
const text = value.text;
|
|
1123
|
+
if (typeof file !== "string" || file === "" || typeof text !== "string" || typeof bytes !== "number" || typeof sha256 !== "string") {
|
|
1124
|
+
throw new IpcError("IPC_INVALID", "\u6838\u5FC3 run --json \u7684 digest \u7F3A path/bytes/sha256/text");
|
|
1125
|
+
}
|
|
1126
|
+
const buffer = Buffer.from(text, "utf8");
|
|
1127
|
+
if (buffer.length !== bytes) {
|
|
1128
|
+
throw new IpcError("IPC_INVALID", `digest.bytes=${bytes} \u4E0E text \u5B9E\u9645 ${buffer.length} \u5B57\u8282\u4E0D\u4E00\u81F4`);
|
|
1129
|
+
}
|
|
1130
|
+
const actual = `sha256:${createHash("sha256").update(buffer).digest("hex")}`;
|
|
1131
|
+
if (actual !== sha256) {
|
|
1132
|
+
throw new IpcError("IPC_INVALID", `digest.sha256 \u4E0E text \u4E0D\u4E00\u81F4\uFF1A\u58F0\u660E ${sha256}\uFF0C\u5B9E\u9645 ${actual}`);
|
|
1133
|
+
}
|
|
1134
|
+
const listed = files.find((item) => item.path === file);
|
|
1135
|
+
if (listed === void 0) {
|
|
1136
|
+
throw new IpcError("IPC_INVALID", `digest.path=${file} \u4E0D\u5728 files \u91CC`);
|
|
1137
|
+
}
|
|
1138
|
+
if (listed.sha256 !== sha256 || listed.bytes !== bytes) {
|
|
1139
|
+
throw new IpcError("IPC_INVALID", `digest \u4E0E files \u91CC ${file} \u7684 bytes/sha256 \u4E0D\u4E00\u81F4`);
|
|
1140
|
+
}
|
|
1141
|
+
return { path: file, bytes, sha256, text };
|
|
1142
|
+
}
|
|
1094
1143
|
function parseRunResult(text, options) {
|
|
1095
1144
|
const value = parseJsonObject(text);
|
|
1096
1145
|
if (value.files === null || value.files === void 0) value.files = [];
|
|
1097
1146
|
if (value.command !== "run" || value.ipcSchema !== IPC_SCHEMA_VERSION || !validators.runResult(value)) {
|
|
1098
|
-
throw new IpcError("IPC_INVALID", "\u6838\u5FC3 run --json \u4E0D\u662F\u5951\u7EA6 RunResult\uFF08ipcSchema=
|
|
1147
|
+
throw new IpcError("IPC_INVALID", "\u6838\u5FC3 run --json \u4E0D\u662F\u5951\u7EA6 RunResult\uFF08ipcSchema=3 / command=run\uFF09");
|
|
1099
1148
|
}
|
|
1100
1149
|
const result = value;
|
|
1101
1150
|
const error = normalizeError(result.error);
|
|
1102
1151
|
const skipReason = value.skipReason;
|
|
1152
|
+
const files = Array.isArray(result.files) ? result.files : [];
|
|
1153
|
+
const digest = parseDigest(value.digest, files);
|
|
1103
1154
|
return {
|
|
1104
1155
|
ok: result.ok,
|
|
1105
1156
|
skipped: result.skipped === true,
|
|
1106
1157
|
dryRun: options.dryRun,
|
|
1107
|
-
files
|
|
1158
|
+
files,
|
|
1159
|
+
...digest === void 0 ? {} : { digest },
|
|
1108
1160
|
contentHash: typeof result.contentHash === "string" ? result.contentHash : void 0,
|
|
1109
1161
|
branch: typeof result.branch === "string" ? result.branch : void 0,
|
|
1110
1162
|
commit: typeof result.commit === "string" ? result.commit : void 0,
|
|
@@ -1225,7 +1277,7 @@ __export(release_exports, {
|
|
|
1225
1277
|
readCoreRelease: () => readCoreRelease,
|
|
1226
1278
|
verifyCached: () => verifyCached
|
|
1227
1279
|
});
|
|
1228
|
-
import { createHash } from "crypto";
|
|
1280
|
+
import { createHash as createHash2 } from "crypto";
|
|
1229
1281
|
import { chmodSync, createWriteStream, existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, renameSync as renameSync2, rmSync, statSync as statSync2, unlinkSync as unlinkSync2 } from "fs";
|
|
1230
1282
|
import { createRequire } from "module";
|
|
1231
1283
|
import { pipeline } from "stream/promises";
|
|
@@ -1285,7 +1337,7 @@ function describeRelease(release, options = {}) {
|
|
|
1285
1337
|
};
|
|
1286
1338
|
}
|
|
1287
1339
|
function sha256File(file) {
|
|
1288
|
-
return
|
|
1340
|
+
return createHash2("sha256").update(readFileSync2(file)).digest("hex");
|
|
1289
1341
|
}
|
|
1290
1342
|
function markerPath(binaryPath) {
|
|
1291
1343
|
return `${binaryPath}.sha256`;
|
|
@@ -1357,7 +1409,7 @@ async function download(descriptor, options) {
|
|
|
1357
1409
|
}
|
|
1358
1410
|
mkdirSync2(descriptor.cacheDir, { recursive: true, mode: 448 });
|
|
1359
1411
|
const temp = `${descriptor.binaryPath}.${process.pid}.${Date.now()}.part`;
|
|
1360
|
-
const hash =
|
|
1412
|
+
const hash = createHash2("sha256");
|
|
1361
1413
|
const total = Number(response.headers.get("content-length") ?? "0") || void 0;
|
|
1362
1414
|
let bytes = 0;
|
|
1363
1415
|
try {
|
|
@@ -2795,44 +2847,15 @@ async function runSubscribe(input, deps) {
|
|
|
2795
2847
|
}
|
|
2796
2848
|
}
|
|
2797
2849
|
|
|
2798
|
-
// src/host/version.ts
|
|
2799
|
-
var version_exports = {};
|
|
2800
|
-
__export(version_exports, {
|
|
2801
|
-
versionAtLeast: () => versionAtLeast
|
|
2802
|
-
});
|
|
2803
|
-
function parseTriplet(value) {
|
|
2804
|
-
const match = /^v?(\d+)\.(\d+)\.(\d+)/.exec(value.trim());
|
|
2805
|
-
if (match === null) return void 0;
|
|
2806
|
-
return [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
2807
|
-
}
|
|
2808
|
-
function versionAtLeast(a, b) {
|
|
2809
|
-
const left = parseTriplet(a);
|
|
2810
|
-
const right = parseTriplet(b);
|
|
2811
|
-
if (left === void 0 || right === void 0) return false;
|
|
2812
|
-
for (let i = 0; i < 3; i += 1) {
|
|
2813
|
-
const l = left[i];
|
|
2814
|
-
const r = right[i];
|
|
2815
|
-
if (l > r) return true;
|
|
2816
|
-
if (l < r) return false;
|
|
2817
|
-
}
|
|
2818
|
-
return true;
|
|
2819
|
-
}
|
|
2820
|
-
|
|
2821
2850
|
// src/host/runner.ts
|
|
2822
2851
|
var runner_exports = {};
|
|
2823
2852
|
__export(runner_exports, {
|
|
2824
|
-
FORCE_MIN_CORE_VERSION: () => FORCE_MIN_CORE_VERSION,
|
|
2825
|
-
REPO_MIN_CORE_VERSION: () => REPO_MIN_CORE_VERSION,
|
|
2826
2853
|
Runner: () => Runner,
|
|
2827
|
-
isoWeekName: () => isoWeekName,
|
|
2828
|
-
periodFileBase: () => periodFileBase,
|
|
2829
2854
|
projectUsage: () => projectUsage
|
|
2830
2855
|
});
|
|
2831
|
-
import { createHash as
|
|
2832
|
-
import { existsSync as existsSync4,
|
|
2856
|
+
import { createHash as createHash3 } from "crypto";
|
|
2857
|
+
import { existsSync as existsSync4, statSync as statSync5 } from "fs";
|
|
2833
2858
|
import path9 from "path";
|
|
2834
|
-
var FORCE_MIN_CORE_VERSION = "0.7.1";
|
|
2835
|
-
var REPO_MIN_CORE_VERSION = "0.8.0";
|
|
2836
2859
|
function repoProblem(repoPath) {
|
|
2837
2860
|
if (repoPath.trim() === "") return { code: "CONFIG_INVALID", message: "\u8FD8\u6CA1\u6709\u9009\u62E9\u5F52\u6863\u4ED3\u5E93" };
|
|
2838
2861
|
if (!existsSync4(repoPath)) return { code: "REPO_NOT_GIT", message: `\u76EE\u5F55\u4E0D\u5B58\u5728\uFF1A${repoPath}` };
|
|
@@ -2853,30 +2876,9 @@ function runDate(settings, now = /* @__PURE__ */ new Date()) {
|
|
|
2853
2876
|
return now.toISOString().slice(0, 10);
|
|
2854
2877
|
}
|
|
2855
2878
|
}
|
|
2856
|
-
function isInside(root, target) {
|
|
2857
|
-
const rel = path9.relative(root, target);
|
|
2858
|
-
return rel !== "" && !rel.startsWith("..") && !path9.isAbsolute(rel);
|
|
2859
|
-
}
|
|
2860
|
-
function normalizeSha256(value) {
|
|
2861
|
-
if (typeof value !== "string") return void 0;
|
|
2862
|
-
const hex = value.trim().replace(/^sha256:/i, "").toLowerCase();
|
|
2863
|
-
return /^[0-9a-f]{64}$/.test(hex) ? hex : void 0;
|
|
2864
|
-
}
|
|
2865
2879
|
function counterOf(value) {
|
|
2866
2880
|
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
2867
2881
|
}
|
|
2868
|
-
function isoWeekName(date) {
|
|
2869
|
-
const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(date);
|
|
2870
|
-
if (match === null) return date;
|
|
2871
|
-
const d = new Date(Date.UTC(Number(match[1]), Number(match[2]) - 1, Number(match[3])));
|
|
2872
|
-
if (Number.isNaN(d.getTime())) return date;
|
|
2873
|
-
return isoWeekKey(d, "UTC");
|
|
2874
|
-
}
|
|
2875
|
-
function periodFileBase(period, date) {
|
|
2876
|
-
if (period === "monthly") return date.slice(0, 7);
|
|
2877
|
-
if (period === "weekly") return isoWeekName(date);
|
|
2878
|
-
return date;
|
|
2879
|
-
}
|
|
2880
2882
|
function projectUsage(outcome) {
|
|
2881
2883
|
const usageTokens = outcome.usage?.totalTokens;
|
|
2882
2884
|
const releasesTokens = outcome.releases?.usage?.totalTokens;
|
|
@@ -2951,15 +2953,7 @@ var Runner = class {
|
|
|
2951
2953
|
`\u6838\u5FC3\u4E0D\u652F\u6301 provider\u300C${settings.model.provider}\u300D\uFF1B\u53EF\u7528\uFF1A${handshakeResult.supportedProviders.join(" / ")}`
|
|
2952
2954
|
);
|
|
2953
2955
|
}
|
|
2954
|
-
const
|
|
2955
|
-
const forceSupported = versionAtLeast(handshakeResult.version.version, FORCE_MIN_CORE_VERSION);
|
|
2956
|
-
const effectiveForce = forceRequested && forceSupported;
|
|
2957
|
-
if (forceRequested && !forceSupported) {
|
|
2958
|
-
store.appendLog(
|
|
2959
|
-
logFile,
|
|
2960
|
-
`[force] \u6838\u5FC3 ${handshakeResult.version.version} \u4F4E\u4E8E ${FORCE_MIN_CORE_VERSION}\uFF0C\u4E0D\u652F\u6301 --force\uFF0C\u5DF2\u964D\u7EA7\u4E3A\u666E\u901A\u91CD\u8DD1`
|
|
2961
|
-
);
|
|
2962
|
-
}
|
|
2956
|
+
const effectiveForce = options.force === true;
|
|
2963
2957
|
const model = await this.openModelChannel({ settings, credentials, env, logFile });
|
|
2964
2958
|
const apiKey = model.apiKey;
|
|
2965
2959
|
proxy = model.proxy;
|
|
@@ -2997,15 +2991,7 @@ var Runner = class {
|
|
|
2997
2991
|
...core.tag === void 0 ? {} : { coreTag: core.tag },
|
|
2998
2992
|
...effectiveForce ? { forced: true } : {}
|
|
2999
2993
|
});
|
|
3000
|
-
const preview = this.capturePreview({
|
|
3001
|
-
id,
|
|
3002
|
-
date,
|
|
3003
|
-
period,
|
|
3004
|
-
settings,
|
|
3005
|
-
outcome,
|
|
3006
|
-
secrets: [apiKey, github.token],
|
|
3007
|
-
...effectiveForce ? { force: true } : {}
|
|
3008
|
-
});
|
|
2994
|
+
const preview = this.capturePreview({ id, outcome, secrets: [apiKey, github.token] });
|
|
3009
2995
|
if (preview !== void 0) summary.preview = preview;
|
|
3010
2996
|
this.record(summary, settings);
|
|
3011
2997
|
return summary;
|
|
@@ -3096,14 +3082,7 @@ var Runner = class {
|
|
|
3096
3082
|
`\u6838\u5FC3\u4E0D\u652F\u6301 provider\u300C${settings.model.provider}\u300D\uFF1B\u53EF\u7528\uFF1A${handshakeResult.supportedProviders.join(" / ")}`
|
|
3097
3083
|
);
|
|
3098
3084
|
}
|
|
3099
|
-
|
|
3100
|
-
if (requestedRepo !== void 0 && !versionAtLeast(handshakeResult.version.version, REPO_MIN_CORE_VERSION)) {
|
|
3101
|
-
store.appendLog(
|
|
3102
|
-
logFile,
|
|
3103
|
-
`[release] \u6838\u5FC3 ${handshakeResult.version.version} \u4F4E\u4E8E ${REPO_MIN_CORE_VERSION}\uFF0C\u5355\u4ED3\u5206\u6790\u964D\u7EA7\u4E3A\u5168\u91CF`
|
|
3104
|
-
);
|
|
3105
|
-
effectiveRepo = void 0;
|
|
3106
|
-
}
|
|
3085
|
+
const effectiveRepo = requestedRepo;
|
|
3107
3086
|
const model = await this.openModelChannel({ settings, credentials, env, logFile });
|
|
3108
3087
|
proxy = model.proxy;
|
|
3109
3088
|
const github = await resolveGithubToken(credentials, settings.github.authMode, settings.github.tokenRef, { env });
|
|
@@ -3344,70 +3323,38 @@ var Runner = class {
|
|
|
3344
3323
|
};
|
|
3345
3324
|
}
|
|
3346
3325
|
/**
|
|
3347
|
-
*
|
|
3326
|
+
* 把本次运行渲染的 digest 原文写进 previews/(ipc v3 起由核心随 RunResult 回传)。
|
|
3348
3327
|
*
|
|
3349
|
-
*
|
|
3350
|
-
*
|
|
3351
|
-
*
|
|
3328
|
+
* 这里**不再读用户仓库**:分支可能在运行结束前就被合并、切回 base 并删除,
|
|
3329
|
+
* 任何「事后去工作树里找文件」的做法都会读到旧版或空。文本、字节数与 sha256
|
|
3330
|
+
* 的跨字段一致性已在 `parseRunResult` 里校验过;这里只做展示侧的防御:
|
|
3331
|
+
* - 上限 512 KB(与预览读取上限一致)、拒绝 NUL;
|
|
3332
|
+
* - 落盘前统一 `redact()`,避免把密钥写进预览文件;
|
|
3352
3333
|
* - 任何一步失败都只记日志,返回 undefined;运行结果不受影响。
|
|
3353
3334
|
*/
|
|
3354
3335
|
capturePreview(input) {
|
|
3355
|
-
const { outcome,
|
|
3356
|
-
if (!outcome.ok || outcome.dryRun
|
|
3357
|
-
if (outcome.skipped && input.force !== true) return void 0;
|
|
3336
|
+
const { outcome, id } = input;
|
|
3337
|
+
if (!outcome.ok || outcome.dryRun) return void 0;
|
|
3358
3338
|
const skip = (reason, extra = {}) => {
|
|
3359
3339
|
this.deps.logger?.("preview.skip", { id, reason, ...extra });
|
|
3360
3340
|
return void 0;
|
|
3361
3341
|
};
|
|
3362
|
-
const
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
});
|
|
3369
|
-
if (markdown.length === 0) return skip("no-markdown");
|
|
3370
|
-
const expected = period === void 0 ? `${date}.md` : `${periodFileBase(period, date)}.md`;
|
|
3371
|
-
const named = markdown.filter((file) => path9.basename(file.path) === expected);
|
|
3372
|
-
const chosen = named.length > 0 ? named[0] : markdown.length === 1 ? markdown[0] : void 0;
|
|
3373
|
-
if (chosen === void 0) return skip("ambiguous", { candidates: markdown.length, expected, period: period ?? null });
|
|
3374
|
-
const repoPath = settings.repo.path;
|
|
3375
|
-
const resolved = path9.resolve(repoPath, chosen.path);
|
|
3376
|
-
if (!isInside(repoPath, resolved)) return skip("outside-repo", { path: chosen.path });
|
|
3377
|
-
let fileReal;
|
|
3378
|
-
try {
|
|
3379
|
-
const repoReal = realpathSync(repoPath);
|
|
3380
|
-
fileReal = realpathSync(resolved);
|
|
3381
|
-
if (!isInside(repoReal, fileReal)) return skip("symlink-outside-repo", { path: chosen.path });
|
|
3382
|
-
} catch {
|
|
3383
|
-
return skip("missing-file", { path: chosen.path });
|
|
3384
|
-
}
|
|
3385
|
-
let buffer;
|
|
3386
|
-
try {
|
|
3387
|
-
const stat2 = statSync5(fileReal);
|
|
3388
|
-
if (!stat2.isFile()) return skip("not-a-file", { path: chosen.path });
|
|
3389
|
-
if (stat2.size > PREVIEW_MAX_BYTES) return skip("too-large", { bytes: stat2.size });
|
|
3390
|
-
buffer = readFileSync3(fileReal);
|
|
3391
|
-
} catch {
|
|
3392
|
-
return skip("read-failed", { path: chosen.path });
|
|
3393
|
-
}
|
|
3394
|
-
if (buffer.includes(0)) return skip("contains-nul", { path: chosen.path });
|
|
3395
|
-
const declared = normalizeSha256(chosen.sha256);
|
|
3396
|
-
const actual = createHash2("sha256").update(buffer).digest("hex");
|
|
3397
|
-
if (declared === void 0 || declared !== actual) {
|
|
3398
|
-
return skip("sha-mismatch", { path: chosen.path, declared: declared ?? null, actual });
|
|
3399
|
-
}
|
|
3400
|
-
const text = redact(buffer.toString("utf8"), input.secrets);
|
|
3342
|
+
const digest = outcome.digest;
|
|
3343
|
+
if (digest === void 0) return skip("no-digest");
|
|
3344
|
+
const buffer = Buffer.from(digest.text, "utf8");
|
|
3345
|
+
if (buffer.length > PREVIEW_MAX_BYTES) return skip("too-large", { path: digest.path, bytes: buffer.length });
|
|
3346
|
+
if (buffer.includes(0)) return skip("contains-nul", { path: digest.path });
|
|
3347
|
+
const text = redact(digest.text, input.secrets);
|
|
3401
3348
|
const stored = Buffer.from(text, "utf8");
|
|
3402
3349
|
try {
|
|
3403
3350
|
this.deps.store.writePreview(id, text);
|
|
3404
3351
|
} catch {
|
|
3405
|
-
return skip("write-failed", { path:
|
|
3352
|
+
return skip("write-failed", { path: digest.path });
|
|
3406
3353
|
}
|
|
3407
3354
|
return {
|
|
3408
|
-
file:
|
|
3355
|
+
file: digest.path,
|
|
3409
3356
|
bytes: stored.length,
|
|
3410
|
-
sha256:
|
|
3357
|
+
sha256: createHash3("sha256").update(stored).digest("hex")
|
|
3411
3358
|
};
|
|
3412
3359
|
}
|
|
3413
3360
|
/** 写历史与状态;同一天的 skipped 运行不覆盖 lastDigest。 */
|
|
@@ -3818,7 +3765,7 @@ __export(import_cli_exports, {
|
|
|
3818
3765
|
importFromCli: () => importFromCli,
|
|
3819
3766
|
parseSimpleYaml: () => parseSimpleYaml
|
|
3820
3767
|
});
|
|
3821
|
-
import { readFileSync as
|
|
3768
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
3822
3769
|
import os4 from "os";
|
|
3823
3770
|
import path10 from "path";
|
|
3824
3771
|
function cliConfigCandidates(env = process.env, home = os4.homedir()) {
|
|
@@ -3910,7 +3857,7 @@ function isSecretKey(key) {
|
|
|
3910
3857
|
function importFromCli(filePath, base = DEFAULT_SETTINGS) {
|
|
3911
3858
|
let text;
|
|
3912
3859
|
try {
|
|
3913
|
-
text =
|
|
3860
|
+
text = readFileSync3(filePath, "utf8");
|
|
3914
3861
|
} catch (error) {
|
|
3915
3862
|
return {
|
|
3916
3863
|
ok: false,
|
|
@@ -4929,7 +4876,6 @@ export {
|
|
|
4929
4876
|
Scheduler,
|
|
4930
4877
|
schedule_exports,
|
|
4931
4878
|
subscribe_exports,
|
|
4932
|
-
version_exports,
|
|
4933
4879
|
Runner,
|
|
4934
4880
|
runner_exports,
|
|
4935
4881
|
readPluginInfo,
|
package/lib/index.js
CHANGED
package/lib/internal.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ErrorCode, FileArtifact, Usage, ReleasesReport, SubscriptionItem, SubscriptionDoc, SubscriptionStatus, ErrorInfo, RunRequest, RunResult, State, StateRun, SubscriptionList, SubscriptionVolume } from '@morehao/trendradar-contract';
|
|
1
|
+
import { ErrorCode, FileArtifact, DigestArtifact, Usage, ReleasesReport, SubscriptionItem, SubscriptionDoc, SubscriptionStatus, ErrorInfo, RunRequest, RunResult, State, StateRun, SubscriptionList, SubscriptionVolume } from '@morehao/trendradar-contract';
|
|
2
2
|
import { ExecOptions, ExecResult } from '@morehao/dsh-plugin-kit/exec';
|
|
3
3
|
import * as exec from '@morehao/dsh-plugin-kit/exec';
|
|
4
4
|
export { exec };
|
|
@@ -71,8 +71,8 @@ declare namespace errors {
|
|
|
71
71
|
export { type errors_AnyCode as AnyCode, type errors_ClassifiedError as ClassifiedError, type errors_ErrorArea as ErrorArea, type errors_GitReason as GitReason, errors_PLUGIN_CODES as PLUGIN_CODES, type errors_PluginCode as PluginCode, errors_areaOf as areaOf, errors_classifyStderr as classifyStderr, errors_hintOf as hintOf, errors_isRetriable as isRetriable, errors_reasonOf as reasonOf, errors_redact as redact };
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
/** 插件实现所对应的 IPC 契约版本(契约包 `ipc.
|
|
75
|
-
declare const IPC_SCHEMA_VERSION:
|
|
74
|
+
/** 插件实现所对应的 IPC 契约版本(契约包 `ipc.v3.json` 的 wire 整数)。 */
|
|
75
|
+
declare const IPC_SCHEMA_VERSION: 3;
|
|
76
76
|
/** 插件能接受的 digest 契约版本(与核心 `version --json` 的 digestSchema 比对)。 */
|
|
77
77
|
declare const SUPPORTED_DIGEST_SCHEMA: 2;
|
|
78
78
|
/** 契约包 `contractVersion` 的主版本;0.x 期间同主版本即视为同一契约线。 */
|
|
@@ -99,6 +99,8 @@ interface RunOutcome {
|
|
|
99
99
|
skipped: boolean;
|
|
100
100
|
dryRun: boolean;
|
|
101
101
|
files: FileArtifact[];
|
|
102
|
+
/** 本次渲染的 digest 原文(ipc v3);没有渲染(dry-run / 纯发版 / 渲染前失败)时缺省。 */
|
|
103
|
+
digest?: DigestArtifact;
|
|
102
104
|
contentHash?: string;
|
|
103
105
|
branch?: string;
|
|
104
106
|
commit?: string;
|
|
@@ -173,6 +175,7 @@ type SubscribeAction = 'list' | 'add' | 'remove' | 'releases';
|
|
|
173
175
|
*/
|
|
174
176
|
declare function parseSubscribeResult(text: string): SubscribeOutcome;
|
|
175
177
|
|
|
178
|
+
declare const ipc_DigestArtifact: typeof DigestArtifact;
|
|
176
179
|
declare const ipc_ErrorCode: typeof ErrorCode;
|
|
177
180
|
declare const ipc_ErrorInfo: typeof ErrorInfo;
|
|
178
181
|
declare const ipc_FileArtifact: typeof FileArtifact;
|
|
@@ -206,7 +209,7 @@ declare const ipc_parseRunResult: typeof parseRunResult;
|
|
|
206
209
|
declare const ipc_parseSubscribeResult: typeof parseSubscribeResult;
|
|
207
210
|
declare const ipc_parseVersionInfo: typeof parseVersionInfo;
|
|
208
211
|
declare namespace ipc {
|
|
209
|
-
export { ipc_ErrorCode as ErrorCode, ipc_ErrorInfo as ErrorInfo, ipc_FileArtifact as FileArtifact, ipc_IPC_SCHEMA_VERSION as IPC_SCHEMA_VERSION, ipc_IpcError as IpcError, type ipc_ParseRunOptions as ParseRunOptions, ipc_ReleasesReport as ReleasesReport, type ipc_RunError as RunError, type ipc_RunOutcome as RunOutcome, ipc_RunRequest as RunRequest, ipc_RunResult as RunResult, ipc_SUPPORTED_CONTRACT_MAJOR as SUPPORTED_CONTRACT_MAJOR, ipc_SUPPORTED_DIGEST_SCHEMA as SUPPORTED_DIGEST_SCHEMA, ipc_State as State, ipc_StateRun as StateRun, type ipc_SubscribeAction as SubscribeAction, type ipc_SubscribeOutcome as SubscribeOutcome, ipc_SubscriptionDoc as SubscriptionDoc, ipc_SubscriptionItem as SubscriptionItem, ipc_SubscriptionList as SubscriptionList, ipc_SubscriptionStatus as SubscriptionStatus, ipc_SubscriptionVolume as SubscriptionVolume, ipc_Usage as Usage, type ipc_VersionInfo as VersionInfo, ipc_isSubscriptionDoc as isSubscriptionDoc, ipc_isSubscriptionStatus as isSubscriptionStatus, ipc_isVersionInfo as isVersionInfo, ipc_parseJsonObject as parseJsonObject, ipc_parseRunResult as parseRunResult, ipc_parseSubscribeResult as parseSubscribeResult, ipc_parseVersionInfo as parseVersionInfo };
|
|
212
|
+
export { ipc_DigestArtifact as DigestArtifact, ipc_ErrorCode as ErrorCode, ipc_ErrorInfo as ErrorInfo, ipc_FileArtifact as FileArtifact, ipc_IPC_SCHEMA_VERSION as IPC_SCHEMA_VERSION, ipc_IpcError as IpcError, type ipc_ParseRunOptions as ParseRunOptions, ipc_ReleasesReport as ReleasesReport, type ipc_RunError as RunError, type ipc_RunOutcome as RunOutcome, ipc_RunRequest as RunRequest, ipc_RunResult as RunResult, ipc_SUPPORTED_CONTRACT_MAJOR as SUPPORTED_CONTRACT_MAJOR, ipc_SUPPORTED_DIGEST_SCHEMA as SUPPORTED_DIGEST_SCHEMA, ipc_State as State, ipc_StateRun as StateRun, type ipc_SubscribeAction as SubscribeAction, type ipc_SubscribeOutcome as SubscribeOutcome, ipc_SubscriptionDoc as SubscriptionDoc, ipc_SubscriptionItem as SubscriptionItem, ipc_SubscriptionList as SubscriptionList, ipc_SubscriptionStatus as SubscriptionStatus, ipc_SubscriptionVolume as SubscriptionVolume, ipc_Usage as Usage, type ipc_VersionInfo as VersionInfo, ipc_isSubscriptionDoc as isSubscriptionDoc, ipc_isSubscriptionStatus as isSubscriptionStatus, ipc_isVersionInfo as isVersionInfo, ipc_parseJsonObject as parseJsonObject, ipc_parseRunResult as parseRunResult, ipc_parseSubscribeResult as parseSubscribeResult, ipc_parseVersionInfo as parseVersionInfo };
|
|
210
213
|
}
|
|
211
214
|
|
|
212
215
|
type Provider = string;
|
|
@@ -282,6 +285,21 @@ interface SummarizeSettings {
|
|
|
282
285
|
enrichTimeoutSeconds: number;
|
|
283
286
|
enrichBudgetSeconds: number;
|
|
284
287
|
}
|
|
288
|
+
/**
|
|
289
|
+
* 本地 star 观测库(核心 `observe.*`,core ≥ 0.8.8)。
|
|
290
|
+
* 观测库让「今日新增」来自本地每日快照的差分,而不是趋势页上的一行字;
|
|
291
|
+
* 默认开启,`enabled=false` 是回滚开关(回到「增量只来自趋势页」的旧行为)。
|
|
292
|
+
* 存储位置由核心自己解析到 `$DSH_HOME`(计划 D4),**不**在这里暴露,避免用户
|
|
293
|
+
* 把观测库指进归档仓库。
|
|
294
|
+
*/
|
|
295
|
+
interface ObserveSettings {
|
|
296
|
+
/** 是否启用观测库;关闭即回到旧行为(`starsInPeriod` 只来自趋势页/搜索)。 */
|
|
297
|
+
enabled: boolean;
|
|
298
|
+
/** 首次见到的仓库从历史接口回填多少天(0=不回填,从今天开始攒)。 */
|
|
299
|
+
backfillDays: number;
|
|
300
|
+
/** 单次运行最多记多少个候选仓库(上限 300,约 3 个 GraphQL 批量/天)。 */
|
|
301
|
+
maxCandidates: number;
|
|
302
|
+
}
|
|
285
303
|
/**
|
|
286
304
|
* 每周发版运行的插件侧节奏(核心没有这个字段,**绝不**写进核心 YAML)。
|
|
287
305
|
* 与榜单调度(`schedule.*`)完全独立:两者各有自己的开关与时间点。
|
|
@@ -345,6 +363,7 @@ interface Settings {
|
|
|
345
363
|
github: GithubSettings;
|
|
346
364
|
trending: TrendingSettings;
|
|
347
365
|
summarize: SummarizeSettings;
|
|
366
|
+
observe: ObserveSettings;
|
|
348
367
|
releases: ReleasesSettings;
|
|
349
368
|
output: OutputSettings;
|
|
350
369
|
schedule: ScheduleSettings;
|
|
@@ -432,6 +451,11 @@ interface CoreConfig {
|
|
|
432
451
|
enrichTimeoutSeconds: number;
|
|
433
452
|
enrichBudgetSeconds: number;
|
|
434
453
|
};
|
|
454
|
+
observe: {
|
|
455
|
+
enabled: boolean;
|
|
456
|
+
backfillDays: number;
|
|
457
|
+
maxCandidates: number;
|
|
458
|
+
};
|
|
435
459
|
releases: {
|
|
436
460
|
enabled: boolean;
|
|
437
461
|
includePrerelease: boolean;
|
|
@@ -480,6 +504,7 @@ type config_Enrich = Enrich;
|
|
|
480
504
|
type config_GithubSettings = GithubSettings;
|
|
481
505
|
type config_ModelSettings = ModelSettings;
|
|
482
506
|
type config_NetworkSettings = NetworkSettings;
|
|
507
|
+
type config_ObserveSettings = ObserveSettings;
|
|
483
508
|
type config_OutputSettings = OutputSettings;
|
|
484
509
|
declare const config_PERIODS: typeof PERIODS;
|
|
485
510
|
declare const config_PROVIDER_BASE_URLS: typeof PROVIDER_BASE_URLS;
|
|
@@ -508,7 +533,7 @@ declare const config_toCoreConfig: typeof toCoreConfig;
|
|
|
508
533
|
declare const config_toYaml: typeof toYaml;
|
|
509
534
|
declare const config_validateSettings: typeof validateSettings;
|
|
510
535
|
declare namespace config {
|
|
511
|
-
export { type config_AuthMode as AuthMode, config_CORE_PROVIDERS as CORE_PROVIDERS, type config_CommitMode as CommitMode, type config_CoreConfig as CoreConfig, config_DEFAULT_SETTINGS as DEFAULT_SETTINGS, type config_Enrich as Enrich, type config_GithubSettings as GithubSettings, type config_ModelSettings as ModelSettings, type config_NetworkSettings as NetworkSettings, type config_OutputSettings as OutputSettings, config_PERIODS as PERIODS, config_PROVIDER_BASE_URLS as PROVIDER_BASE_URLS, type config_PRSettings as PRSettings, type config_Period as Period, type config_Problem as Problem, type config_Provider as Provider, type config_ReleaseScheduleSettings as ReleaseScheduleSettings, type config_ReleasesSettings as ReleasesSettings, type config_RepoSettings as RepoSettings, config_SETTINGS_SECTIONS as SETTINGS_SECTIONS, type config_ScheduleSettings as ScheduleSettings, type config_Settings as Settings, type config_SettingsSection as SettingsSection, type config_Since as Since, type config_SummarizeSettings as SummarizeSettings, type config_TrendingSettings as TrendingSettings, config_effectiveBaseURL as effectiveBaseURL, config_isEnrich as isEnrich, config_isPeriod as isPeriod, config_isValidTimezone as isValidTimezone, config_mergeSettingsSection as mergeSettingsSection, config_normalizeSettings as normalizeSettings, config_sectionOfField as sectionOfField, config_toCoreConfig as toCoreConfig, config_toYaml as toYaml, config_validateSettings as validateSettings };
|
|
536
|
+
export { type config_AuthMode as AuthMode, config_CORE_PROVIDERS as CORE_PROVIDERS, type config_CommitMode as CommitMode, type config_CoreConfig as CoreConfig, config_DEFAULT_SETTINGS as DEFAULT_SETTINGS, type config_Enrich as Enrich, type config_GithubSettings as GithubSettings, type config_ModelSettings as ModelSettings, type config_NetworkSettings as NetworkSettings, type config_ObserveSettings as ObserveSettings, type config_OutputSettings as OutputSettings, config_PERIODS as PERIODS, config_PROVIDER_BASE_URLS as PROVIDER_BASE_URLS, type config_PRSettings as PRSettings, type config_Period as Period, type config_Problem as Problem, type config_Provider as Provider, type config_ReleaseScheduleSettings as ReleaseScheduleSettings, type config_ReleasesSettings as ReleasesSettings, type config_RepoSettings as RepoSettings, config_SETTINGS_SECTIONS as SETTINGS_SECTIONS, type config_ScheduleSettings as ScheduleSettings, type config_Settings as Settings, type config_SettingsSection as SettingsSection, type config_Since as Since, type config_SummarizeSettings as SummarizeSettings, type config_TrendingSettings as TrendingSettings, config_effectiveBaseURL as effectiveBaseURL, config_isEnrich as isEnrich, config_isPeriod as isPeriod, config_isValidTimezone as isValidTimezone, config_mergeSettingsSection as mergeSettingsSection, config_normalizeSettings as normalizeSettings, config_sectionOfField as sectionOfField, config_toCoreConfig as toCoreConfig, config_toYaml as toYaml, config_validateSettings as validateSettings };
|
|
512
537
|
}
|
|
513
538
|
|
|
514
539
|
declare const PLUGIN_DIR_NAME = "github-trending";
|
|
@@ -1595,16 +1620,6 @@ declare namespace pendingPr {
|
|
|
1595
1620
|
export { type pendingPr_CheckPendingPrOptions as CheckPendingPrOptions, type pendingPr_ParsedPullUrl as ParsedPullUrl, type pendingPr_PendingPrStatus as PendingPrStatus, type pendingPr_PullState as PullState, pendingPr_checkPendingPr as checkPendingPr, pendingPr_clearPendingPrCache as clearPendingPrCache, pendingPr_parsePullUrl as parsePullUrl };
|
|
1596
1621
|
}
|
|
1597
1622
|
|
|
1598
|
-
/**
|
|
1599
|
-
* 支持 `run --force`(忽略摘要缓存重新生成)的最低核心版本。
|
|
1600
|
-
* 与 core patch 发版 `0.7.1` 对齐;`dsh.core.version` 应 >= 它,dev override 指向更旧核心时靠闸门降级。
|
|
1601
|
-
*/
|
|
1602
|
-
declare const FORCE_MIN_CORE_VERSION = "0.7.1";
|
|
1603
|
-
/**
|
|
1604
|
-
* 支持 `run --stages releases --repo`(单仓发版分析)的最低核心版本。
|
|
1605
|
-
* 与 core v0.8.0 对齐;核心更旧时单仓触发降级为全量(不传 --repo)。
|
|
1606
|
-
*/
|
|
1607
|
-
declare const REPO_MIN_CORE_VERSION = "0.8.0";
|
|
1608
1623
|
interface RunSummary {
|
|
1609
1624
|
id: string;
|
|
1610
1625
|
ok: boolean;
|
|
@@ -1665,13 +1680,6 @@ interface RunnerDeps {
|
|
|
1665
1680
|
/** 预览副本这类「可失败但不阻断运行」的事件走这里,不写进 warnings。 */
|
|
1666
1681
|
logger?: (event: string, data?: Record<string, unknown>) => void;
|
|
1667
1682
|
}
|
|
1668
|
-
/**
|
|
1669
|
-
* 与 core `render.NameOf` 对齐的产物基名(不含扩展名):
|
|
1670
|
-
* daily → YYYY-MM-DD;weekly → YYYY-Wnn(ISO 周年/周);monthly → YYYY-MM。
|
|
1671
|
-
* 用于在 outcome.files 里按周期精确挑出本期 digest 的 `.md`(而不是猜)。
|
|
1672
|
-
*/
|
|
1673
|
-
declare function isoWeekName(date: string): string;
|
|
1674
|
-
declare function periodFileBase(period: Period, date: string): string;
|
|
1675
1683
|
/**
|
|
1676
1684
|
* 从契约 `RunOutcome` 投影出「token 总量」与「发版摘要」:
|
|
1677
1685
|
* - `tokens` = usage.totalTokens + releases.usage.totalTokens(含订阅阶段);
|
|
@@ -1739,11 +1747,13 @@ declare class Runner {
|
|
|
1739
1747
|
private summarize;
|
|
1740
1748
|
private failureSummary;
|
|
1741
1749
|
/**
|
|
1742
|
-
*
|
|
1750
|
+
* 把本次运行渲染的 digest 原文写进 previews/(ipc v3 起由核心随 RunResult 回传)。
|
|
1743
1751
|
*
|
|
1744
|
-
*
|
|
1745
|
-
*
|
|
1746
|
-
*
|
|
1752
|
+
* 这里**不再读用户仓库**:分支可能在运行结束前就被合并、切回 base 并删除,
|
|
1753
|
+
* 任何「事后去工作树里找文件」的做法都会读到旧版或空。文本、字节数与 sha256
|
|
1754
|
+
* 的跨字段一致性已在 `parseRunResult` 里校验过;这里只做展示侧的防御:
|
|
1755
|
+
* - 上限 512 KB(与预览读取上限一致)、拒绝 NUL;
|
|
1756
|
+
* - 落盘前统一 `redact()`,避免把密钥写进预览文件;
|
|
1747
1757
|
* - 任何一步失败都只记日志,返回 undefined;运行结果不受影响。
|
|
1748
1758
|
*/
|
|
1749
1759
|
private capturePreview;
|
|
@@ -1753,18 +1763,14 @@ declare class Runner {
|
|
|
1753
1763
|
coreStatus(fresh?: boolean): Promise<CoreStatus>;
|
|
1754
1764
|
}
|
|
1755
1765
|
|
|
1756
|
-
declare const runner_FORCE_MIN_CORE_VERSION: typeof FORCE_MIN_CORE_VERSION;
|
|
1757
|
-
declare const runner_REPO_MIN_CORE_VERSION: typeof REPO_MIN_CORE_VERSION;
|
|
1758
1766
|
type runner_RunRequestOptions = RunRequestOptions;
|
|
1759
1767
|
type runner_RunSummary = RunSummary;
|
|
1760
1768
|
type runner_Runner = Runner;
|
|
1761
1769
|
declare const runner_Runner: typeof Runner;
|
|
1762
1770
|
type runner_RunnerDeps = RunnerDeps;
|
|
1763
|
-
declare const runner_isoWeekName: typeof isoWeekName;
|
|
1764
|
-
declare const runner_periodFileBase: typeof periodFileBase;
|
|
1765
1771
|
declare const runner_projectUsage: typeof projectUsage;
|
|
1766
1772
|
declare namespace runner {
|
|
1767
|
-
export {
|
|
1773
|
+
export { type runner_RunRequestOptions as RunRequestOptions, type runner_RunSummary as RunSummary, runner_Runner as Runner, type runner_RunnerDeps as RunnerDeps, runner_projectUsage as projectUsage };
|
|
1768
1774
|
}
|
|
1769
1775
|
|
|
1770
1776
|
/** 订阅命令超时:核心只做一次 GitHub 请求/本地文件读写,8 s 足够。 */
|
|
@@ -1958,23 +1964,6 @@ declare namespace schedule {
|
|
|
1958
1964
|
export { schedule_RELEASE_CATCH_UP_MINUTES as RELEASE_CATCH_UP_MINUTES, type schedule_ReleaseScheduleConfig as ReleaseScheduleConfig, type schedule_ScheduleConfig as ScheduleConfig, schedule_Scheduler as Scheduler, type schedule_SchedulerDeps as SchedulerDeps, schedule_daysInMonth as daysInMonth, schedule_isDue as isDue, schedule_isPeriodTriggerDay as isPeriodTriggerDay, schedule_isReleaseDue as isReleaseDue, schedule_isoWeekKey as isoWeekKey, schedule_nextOccurrence as nextOccurrence, schedule_nextOccurrenceFor as nextOccurrenceFor, schedule_nextReleaseOccurrence as nextReleaseOccurrence, schedule_parseClock as parseClock, schedule_zonedDateString as zonedDateString, schedule_zonedTimeToUtc as zonedTimeToUtc };
|
|
1959
1965
|
}
|
|
1960
1966
|
|
|
1961
|
-
/**
|
|
1962
|
-
* 版本比较:只用于「核心是否足够新到支持某个 CLI flag」这类能力闸门。
|
|
1963
|
-
*
|
|
1964
|
-
* 核心的 `version --json` 只给 `x.y.z`(偶带预发布后缀),这里按三段数字比较,
|
|
1965
|
-
* 后缀忽略。不做完整 semver 区间——项目只需要「>= 阈值」这一种判断,够用且不易错。
|
|
1966
|
-
*/
|
|
1967
|
-
/**
|
|
1968
|
-
* `a >= b` 时返回 true。任一方不可解析时返回 false(保守:当作「不满足」,
|
|
1969
|
-
* 让调用方降级为不带新 flag 的行为,避免向旧核心传未知参数)。
|
|
1970
|
-
*/
|
|
1971
|
-
declare function versionAtLeast(a: string, b: string): boolean;
|
|
1972
|
-
|
|
1973
|
-
declare const version_versionAtLeast: typeof versionAtLeast;
|
|
1974
|
-
declare namespace version {
|
|
1975
|
-
export { version_versionAtLeast as versionAtLeast };
|
|
1976
|
-
}
|
|
1977
|
-
|
|
1978
1967
|
/**
|
|
1979
1968
|
* Host HTTP 面:`/api/morehao/github-trending/*`。
|
|
1980
1969
|
*
|
|
@@ -2324,4 +2313,4 @@ declare namespace tools {
|
|
|
2324
2313
|
export { tools_createTrendingHistoryTool as createTrendingHistoryTool, tools_createTrendingRunTool as createTrendingRunTool };
|
|
2325
2314
|
}
|
|
2326
2315
|
|
|
2327
|
-
export { channel, config, core, credentials, errors, github, githubAuth, 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
|
|
2316
|
+
export { channel, config, core, credentials, errors, github, githubAuth, 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 };
|
package/lib/internal.js
CHANGED
|
@@ -25,9 +25,8 @@ import {
|
|
|
25
25
|
state_exports,
|
|
26
26
|
subscribe_exports,
|
|
27
27
|
tools_exports,
|
|
28
|
-
update_exports
|
|
29
|
-
|
|
30
|
-
} from "./chunk-SLY2RKCZ.js";
|
|
28
|
+
update_exports
|
|
29
|
+
} from "./chunk-JMIWABMY.js";
|
|
31
30
|
|
|
32
31
|
// src/internal.ts
|
|
33
32
|
import * as exec from "@morehao/dsh-plugin-kit/exec";
|
|
@@ -59,6 +58,5 @@ export {
|
|
|
59
58
|
state_exports as state,
|
|
60
59
|
subscribe_exports as subscribe,
|
|
61
60
|
tools_exports as tools,
|
|
62
|
-
update_exports as updateService
|
|
63
|
-
version_exports as version
|
|
61
|
+
update_exports as updateService
|
|
64
62
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@morehao/dsh-github-trending",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "GitHub 趋势日报的 DeepSeek Harness 插件:按日 / 周 / 月周期定时 spawn 本地 trendradar 核心,抓取 Trending、生成中文简介与周期总结,并可选把订阅仓库的新 Release 合成中文摘要,一起提交到你的仓库、自动开 PR 合并;内置概览 / 榜单 / 运行记录 / 订阅 / 设置工作台。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"@morehao/dsh-plugin-kit": "^0.4.1",
|
|
55
|
-
"@morehao/trendradar-contract": "0.
|
|
55
|
+
"@morehao/trendradar-contract": "0.6.0"
|
|
56
56
|
},
|
|
57
57
|
"dsh": {
|
|
58
58
|
"bundle": {
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
},
|
|
61
61
|
"core": {
|
|
62
62
|
"repo": "morehao/trendradar",
|
|
63
|
-
"version": "0.
|
|
63
|
+
"version": "0.9.0"
|
|
64
64
|
},
|
|
65
65
|
"client": {
|
|
66
66
|
"platform": "web",
|