@morehao/dsh-github-trending 0.4.4 → 0.5.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/CHANGELOG.md +13 -0
- package/README.md +27 -2
- package/client.js +465 -7
- package/lib/{chunk-XLIFTAVL.js → chunk-R7BK7SJK.js} +5 -1
- package/lib/{chunk-GBXP2NGW.js → chunk-WFCULY72.js} +290 -9
- package/lib/{exec-33EQXGUA.js → exec-VMDINNX5.js} +1 -1
- package/lib/index.js +2 -2
- package/lib/internal.d.ts +195 -8
- package/lib/internal.js +4 -2
- package/package.json +3 -3
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
__export,
|
|
3
3
|
execCapture,
|
|
4
4
|
sanitizedEnv
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-R7BK7SJK.js";
|
|
6
6
|
|
|
7
7
|
// src/config.ts
|
|
8
8
|
var config_exports = {};
|
|
@@ -13,6 +13,7 @@ __export(config_exports, {
|
|
|
13
13
|
PROVIDER_BASE_URLS: () => PROVIDER_BASE_URLS,
|
|
14
14
|
SETTINGS_SECTIONS: () => SETTINGS_SECTIONS,
|
|
15
15
|
effectiveBaseURL: () => effectiveBaseURL,
|
|
16
|
+
isEnrich: () => isEnrich,
|
|
16
17
|
isPeriod: () => isPeriod,
|
|
17
18
|
isValidTimezone: () => isValidTimezone,
|
|
18
19
|
mergeSettingsSection: () => mergeSettingsSection,
|
|
@@ -27,6 +28,9 @@ var PERIODS = ["daily", "weekly", "monthly"];
|
|
|
27
28
|
function isPeriod(value) {
|
|
28
29
|
return value === "daily" || value === "weekly" || value === "monthly";
|
|
29
30
|
}
|
|
31
|
+
function isEnrich(value) {
|
|
32
|
+
return value === "none" || value === "repo" || value === "readme";
|
|
33
|
+
}
|
|
30
34
|
var DEFAULT_SETTINGS = {
|
|
31
35
|
model: {
|
|
32
36
|
provider: "deepseek",
|
|
@@ -55,6 +59,26 @@ var DEFAULT_SETTINGS = {
|
|
|
55
59
|
},
|
|
56
60
|
github: { authMode: "gh", tokenRef: "GITHUB_TOKEN" },
|
|
57
61
|
trending: { since: "daily", languages: ["all", "typescript", "python", "go", "rust"], topN: 25 },
|
|
62
|
+
summarize: {
|
|
63
|
+
batchSize: 10,
|
|
64
|
+
maxRetries: 1,
|
|
65
|
+
enrich: "none",
|
|
66
|
+
readmeChars: 800,
|
|
67
|
+
enrichCacheTTLHours: 168,
|
|
68
|
+
enrichConcurrency: 4,
|
|
69
|
+
enrichTimeoutSeconds: 5,
|
|
70
|
+
enrichBudgetSeconds: 8
|
|
71
|
+
},
|
|
72
|
+
releases: {
|
|
73
|
+
enabled: false,
|
|
74
|
+
includePrerelease: false,
|
|
75
|
+
includeDrafts: false,
|
|
76
|
+
fallbackToTags: true,
|
|
77
|
+
baselineOnFirstRun: true,
|
|
78
|
+
perRepoLimit: 5,
|
|
79
|
+
maxNotesChars: 4e3,
|
|
80
|
+
period: "daily"
|
|
81
|
+
},
|
|
58
82
|
output: { dir: "trending" },
|
|
59
83
|
schedule: { enabled: true, time: "08:30:00", timezone: "Asia/Shanghai", periods: ["daily", "weekly", "monthly"] },
|
|
60
84
|
corePath: "",
|
|
@@ -66,12 +90,14 @@ var PROVIDER_BASE_URLS = {
|
|
|
66
90
|
anthropic: ""
|
|
67
91
|
};
|
|
68
92
|
var CORE_PROVIDERS = ["deepseek", "openai-compatible"];
|
|
69
|
-
var SETTINGS_SECTIONS = ["source", "model", "repo", "auth", "scope", "schedule"];
|
|
93
|
+
var SETTINGS_SECTIONS = ["source", "model", "repo", "auth", "scope", "summarize", "releases", "schedule"];
|
|
70
94
|
function sectionOfField(field) {
|
|
71
95
|
if (field.startsWith("model.")) return "model";
|
|
72
96
|
if (field.startsWith("repo.") || field.startsWith("output.") || field.startsWith("pr.")) return "repo";
|
|
73
97
|
if (field.startsWith("github.")) return "auth";
|
|
74
98
|
if (field.startsWith("trending.")) return "scope";
|
|
99
|
+
if (field.startsWith("summarize.")) return "summarize";
|
|
100
|
+
if (field.startsWith("releases.")) return "releases";
|
|
75
101
|
if (field.startsWith("schedule.")) return "schedule";
|
|
76
102
|
if (field === "corePath" || field === "coreAutoDownload") return "source";
|
|
77
103
|
return void 0;
|
|
@@ -97,6 +123,12 @@ function mergeSettingsSection(stored, incoming, section) {
|
|
|
97
123
|
case "scope":
|
|
98
124
|
next.trending = incoming.trending;
|
|
99
125
|
break;
|
|
126
|
+
case "summarize":
|
|
127
|
+
next.summarize = incoming.summarize;
|
|
128
|
+
break;
|
|
129
|
+
case "releases":
|
|
130
|
+
next.releases = incoming.releases;
|
|
131
|
+
break;
|
|
100
132
|
case "schedule":
|
|
101
133
|
next.schedule = incoming.schedule;
|
|
102
134
|
break;
|
|
@@ -127,11 +159,15 @@ function normalizeSettings(input) {
|
|
|
127
159
|
const pr = raw.pr ?? {};
|
|
128
160
|
const github = raw.github ?? {};
|
|
129
161
|
const trending = raw.trending ?? {};
|
|
162
|
+
const summarize = raw.summarize ?? {};
|
|
163
|
+
const releases = raw.releases ?? {};
|
|
130
164
|
const output = raw.output ?? {};
|
|
131
165
|
const schedule = raw.schedule ?? {};
|
|
132
166
|
const commitMode = str(repo.commitMode, DEFAULT_SETTINGS.repo.commitMode);
|
|
133
167
|
const authMode = str(github.authMode, DEFAULT_SETTINGS.github.authMode);
|
|
134
168
|
const since = str(trending.since, DEFAULT_SETTINGS.trending.since);
|
|
169
|
+
const enrich = str(summarize.enrich, DEFAULT_SETTINGS.summarize.enrich);
|
|
170
|
+
const releasesPeriod = str(releases.period, DEFAULT_SETTINGS.releases.period);
|
|
135
171
|
return {
|
|
136
172
|
model: {
|
|
137
173
|
provider: str(model.provider, DEFAULT_SETTINGS.model.provider),
|
|
@@ -168,6 +204,26 @@ function normalizeSettings(input) {
|
|
|
168
204
|
languages: strArray(trending.languages, DEFAULT_SETTINGS.trending.languages),
|
|
169
205
|
topN: Math.round(num(trending.topN, DEFAULT_SETTINGS.trending.topN))
|
|
170
206
|
},
|
|
207
|
+
summarize: {
|
|
208
|
+
batchSize: Math.round(num(summarize.batchSize, DEFAULT_SETTINGS.summarize.batchSize)),
|
|
209
|
+
maxRetries: Math.round(num(summarize.maxRetries, DEFAULT_SETTINGS.summarize.maxRetries)),
|
|
210
|
+
enrich: isEnrich(enrich) ? enrich : DEFAULT_SETTINGS.summarize.enrich,
|
|
211
|
+
readmeChars: Math.round(num(summarize.readmeChars, DEFAULT_SETTINGS.summarize.readmeChars)),
|
|
212
|
+
enrichCacheTTLHours: Math.round(num(summarize.enrichCacheTTLHours, DEFAULT_SETTINGS.summarize.enrichCacheTTLHours)),
|
|
213
|
+
enrichConcurrency: Math.round(num(summarize.enrichConcurrency, DEFAULT_SETTINGS.summarize.enrichConcurrency)),
|
|
214
|
+
enrichTimeoutSeconds: Math.round(num(summarize.enrichTimeoutSeconds, DEFAULT_SETTINGS.summarize.enrichTimeoutSeconds)),
|
|
215
|
+
enrichBudgetSeconds: Math.round(num(summarize.enrichBudgetSeconds, DEFAULT_SETTINGS.summarize.enrichBudgetSeconds))
|
|
216
|
+
},
|
|
217
|
+
releases: {
|
|
218
|
+
enabled: bool(releases.enabled, DEFAULT_SETTINGS.releases.enabled),
|
|
219
|
+
includePrerelease: bool(releases.includePrerelease, DEFAULT_SETTINGS.releases.includePrerelease),
|
|
220
|
+
includeDrafts: bool(releases.includeDrafts, DEFAULT_SETTINGS.releases.includeDrafts),
|
|
221
|
+
fallbackToTags: bool(releases.fallbackToTags, DEFAULT_SETTINGS.releases.fallbackToTags),
|
|
222
|
+
baselineOnFirstRun: bool(releases.baselineOnFirstRun, DEFAULT_SETTINGS.releases.baselineOnFirstRun),
|
|
223
|
+
perRepoLimit: Math.round(num(releases.perRepoLimit, DEFAULT_SETTINGS.releases.perRepoLimit)),
|
|
224
|
+
maxNotesChars: Math.round(num(releases.maxNotesChars, DEFAULT_SETTINGS.releases.maxNotesChars)),
|
|
225
|
+
period: isPeriod(releasesPeriod) ? releasesPeriod : DEFAULT_SETTINGS.releases.period
|
|
226
|
+
},
|
|
171
227
|
output: {
|
|
172
228
|
dir: str(output.dir, DEFAULT_SETTINGS.output.dir).trim() || DEFAULT_SETTINGS.output.dir
|
|
173
229
|
},
|
|
@@ -193,7 +249,7 @@ function isValidTimezone(timezone) {
|
|
|
193
249
|
}
|
|
194
250
|
function validateSettings(settings, providers = CORE_PROVIDERS) {
|
|
195
251
|
const problems = [];
|
|
196
|
-
const { model, repo, trending, output, schedule } = settings;
|
|
252
|
+
const { model, repo, trending, summarize, releases, output, schedule } = settings;
|
|
197
253
|
if (model.provider.trim() === "") {
|
|
198
254
|
problems.push({ field: "model.provider", code: "CONFIG_INVALID", message: "\u7F3A\u5C11 provider" });
|
|
199
255
|
} else if (!providers.includes(model.provider)) {
|
|
@@ -232,6 +288,27 @@ function validateSettings(settings, providers = CORE_PROVIDERS) {
|
|
|
232
288
|
if (!Number.isInteger(trending.topN) || trending.topN <= 0) {
|
|
233
289
|
problems.push({ field: "trending.topN", code: "CONFIG_INVALID", message: "\u6BCF\u8BED\u8A00\u6761\u6570\u5FC5\u987B\u662F\u6B63\u6574\u6570" });
|
|
234
290
|
}
|
|
291
|
+
if (!isEnrich(summarize.enrich)) {
|
|
292
|
+
problems.push({ field: "summarize.enrich", code: "CONFIG_INVALID", message: "enrich \u5FC5\u987B\u662F none / repo / readme" });
|
|
293
|
+
}
|
|
294
|
+
if (!Number.isInteger(summarize.batchSize) || summarize.batchSize <= 0) {
|
|
295
|
+
problems.push({ field: "summarize.batchSize", code: "CONFIG_INVALID", message: "batchSize \u5FC5\u987B\u662F\u6B63\u6574\u6570" });
|
|
296
|
+
}
|
|
297
|
+
if (!Number.isInteger(summarize.maxRetries) || summarize.maxRetries < 0) {
|
|
298
|
+
problems.push({ field: "summarize.maxRetries", code: "CONFIG_INVALID", message: "maxRetries \u5FC5\u987B\u662F\u975E\u8D1F\u6574\u6570" });
|
|
299
|
+
}
|
|
300
|
+
if (!Number.isInteger(summarize.readmeChars) || summarize.readmeChars <= 0) {
|
|
301
|
+
problems.push({ field: "summarize.readmeChars", code: "CONFIG_INVALID", message: "readmeChars \u5FC5\u987B\u662F\u6B63\u6574\u6570" });
|
|
302
|
+
}
|
|
303
|
+
if (!isPeriod(releases.period)) {
|
|
304
|
+
problems.push({ field: "releases.period", code: "CONFIG_INVALID", message: "releases.period \u5FC5\u987B\u662F daily / weekly / monthly" });
|
|
305
|
+
}
|
|
306
|
+
if (!Number.isInteger(releases.perRepoLimit) || releases.perRepoLimit < 1 || releases.perRepoLimit > 20) {
|
|
307
|
+
problems.push({ field: "releases.perRepoLimit", code: "CONFIG_INVALID", message: "perRepoLimit \u5FC5\u987B\u662F 1\u201320 \u7684\u6574\u6570" });
|
|
308
|
+
}
|
|
309
|
+
if (!Number.isInteger(releases.maxNotesChars) || releases.maxNotesChars < 500 || releases.maxNotesChars > 2e4) {
|
|
310
|
+
problems.push({ field: "releases.maxNotesChars", code: "CONFIG_INVALID", message: "maxNotesChars \u5FC5\u987B\u662F 500\u201320000 \u7684\u6574\u6570" });
|
|
311
|
+
}
|
|
235
312
|
if (output.dir.trim() === "" || path.isAbsolute(output.dir) || output.dir.split(/[\\/]/).includes("..")) {
|
|
236
313
|
problems.push({ field: "output.dir", code: "CONFIG_INVALID", message: "\u8F93\u51FA\u76EE\u5F55\u5FC5\u987B\u662F\u4ED3\u5E93\u5185\u7684\u76F8\u5BF9\u8DEF\u5F84\uFF0C\u4E14\u4E0D\u542B .." });
|
|
237
314
|
}
|
|
@@ -275,6 +352,26 @@ function toCoreConfig(settings, apiKey, baseURLOverride, period) {
|
|
|
275
352
|
since: period ?? settings.trending.since,
|
|
276
353
|
perLanguage: settings.trending.topN
|
|
277
354
|
},
|
|
355
|
+
summarize: {
|
|
356
|
+
batchSize: settings.summarize.batchSize,
|
|
357
|
+
maxRetries: settings.summarize.maxRetries,
|
|
358
|
+
enrich: settings.summarize.enrich,
|
|
359
|
+
readmeChars: settings.summarize.readmeChars,
|
|
360
|
+
enrichCacheTTLHours: settings.summarize.enrichCacheTTLHours,
|
|
361
|
+
enrichConcurrency: settings.summarize.enrichConcurrency,
|
|
362
|
+
enrichTimeoutSeconds: settings.summarize.enrichTimeoutSeconds,
|
|
363
|
+
enrichBudgetSeconds: settings.summarize.enrichBudgetSeconds
|
|
364
|
+
},
|
|
365
|
+
releases: {
|
|
366
|
+
enabled: settings.releases.enabled,
|
|
367
|
+
includePrerelease: settings.releases.includePrerelease,
|
|
368
|
+
includeDrafts: settings.releases.includeDrafts,
|
|
369
|
+
fallbackToTags: settings.releases.fallbackToTags,
|
|
370
|
+
baselineOnFirstRun: settings.releases.baselineOnFirstRun,
|
|
371
|
+
perRepoLimit: settings.releases.perRepoLimit,
|
|
372
|
+
maxNotesChars: settings.releases.maxNotesChars,
|
|
373
|
+
period: settings.releases.period
|
|
374
|
+
},
|
|
278
375
|
output: {
|
|
279
376
|
dir: settings.output.dir,
|
|
280
377
|
branchPrefix: "trending/",
|
|
@@ -354,6 +451,7 @@ __export(state_exports, {
|
|
|
354
451
|
PREVIEW_MAX_BYTES: () => PREVIEW_MAX_BYTES,
|
|
355
452
|
Store: () => Store,
|
|
356
453
|
newRunId: () => newRunId,
|
|
454
|
+
sumTokens: () => sumTokens,
|
|
357
455
|
writeJsonAtomic: () => writeJsonAtomic
|
|
358
456
|
});
|
|
359
457
|
import { mkdirSync, readFileSync, readdirSync, renameSync, statSync, unlinkSync, writeFileSync, appendFileSync, existsSync } from "fs";
|
|
@@ -566,6 +664,17 @@ function newRunId(now = /* @__PURE__ */ new Date()) {
|
|
|
566
664
|
const random = Math.random().toString(36).slice(2, 8);
|
|
567
665
|
return `${stamp}-${random}`;
|
|
568
666
|
}
|
|
667
|
+
function sumTokens(records) {
|
|
668
|
+
let total = 0;
|
|
669
|
+
let seen = false;
|
|
670
|
+
for (const record of records) {
|
|
671
|
+
if (typeof record.tokens === "number" && Number.isFinite(record.tokens)) {
|
|
672
|
+
total += record.tokens;
|
|
673
|
+
seen = true;
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
return seen ? total : void 0;
|
|
677
|
+
}
|
|
569
678
|
|
|
570
679
|
// src/errors.ts
|
|
571
680
|
var errors_exports = {};
|
|
@@ -593,7 +702,8 @@ var PLUGIN_CODES = [
|
|
|
593
702
|
"MODEL_PROVIDER_UNSUPPORTED",
|
|
594
703
|
"GITHUB_AUTH",
|
|
595
704
|
"PUSH_FAILED",
|
|
596
|
-
"REPO_DIRTY"
|
|
705
|
+
"REPO_DIRTY",
|
|
706
|
+
"SUBSCRIBE_FAILED"
|
|
597
707
|
];
|
|
598
708
|
var RETRIABLE = {
|
|
599
709
|
INTERNAL: true,
|
|
@@ -626,7 +736,8 @@ var RETRIABLE = {
|
|
|
626
736
|
MODEL_NOT_FOUND: false,
|
|
627
737
|
MODEL_PROVIDER_UNSUPPORTED: false,
|
|
628
738
|
GITHUB_AUTH: false,
|
|
629
|
-
PUSH_FAILED: true
|
|
739
|
+
PUSH_FAILED: true,
|
|
740
|
+
SUBSCRIBE_FAILED: true
|
|
630
741
|
};
|
|
631
742
|
function isRetriable(code) {
|
|
632
743
|
return RETRIABLE[code] === true;
|
|
@@ -709,6 +820,8 @@ function hintOf(code, message, reason) {
|
|
|
709
820
|
return "PR \u65E0\u6CD5\u81EA\u52A8\u5408\u5E76\uFF08\u5E38\u89C1\u4E8E\u5206\u652F\u4FDD\u62A4\uFF09\uFF1APR \u5DF2\u4FDD\u7559\uFF0C\u9700\u4EBA\u5DE5\u5904\u7406\u3002";
|
|
710
821
|
case "PUSH_FAILED":
|
|
711
822
|
return "\u63A8\u9001\u5931\u8D25\uFF1A\u672C\u5730 commit \u5DF2\u4FDD\u7559\uFF0C\u4FEE\u590D\u6743\u9650/\u7F51\u7EDC\u540E\u91CD\u8BD5\u5373\u53EF\u590D\u7528\u3002";
|
|
823
|
+
case "SUBSCRIBE_FAILED":
|
|
824
|
+
return "\u8BA2\u9605\u547D\u4EE4\u5931\u8D25\uFF1A\u6838\u5BF9 owner/repo \u5F62\u6001\uFF08\u5982 vercel/next.js\uFF09\uFF0C\u786E\u8BA4\u4ED3\u5E93\u6709\u5199\u6743\u9650\u540E\u91CD\u8BD5\uFF1B\u8BA2\u9605\u5217\u8868\u968F\u4E0B\u6B21\u8FD0\u884C\u843D\u76D8\u63D0\u4EA4\u3002";
|
|
712
825
|
case "PR_FAILED":
|
|
713
826
|
return "\u521B\u5EFA PR \u5931\u8D25\uFF1A\u672C\u5730 commit \u4E0E\u5206\u652F\u5DF2\u4FDD\u7559\u3002";
|
|
714
827
|
case "FETCH_FAILED":
|
|
@@ -802,6 +915,7 @@ __export(ipc_exports, {
|
|
|
802
915
|
isVersionInfo: () => isVersionInfo,
|
|
803
916
|
parseJsonObject: () => parseJsonObject,
|
|
804
917
|
parseRunResult: () => parseRunResult,
|
|
918
|
+
parseSubscribeResult: () => parseSubscribeResult,
|
|
805
919
|
parseVersionInfo: () => parseVersionInfo
|
|
806
920
|
});
|
|
807
921
|
import { validators } from "@morehao/trendradar-contract";
|
|
@@ -871,6 +985,8 @@ function parseRunResult(text, options) {
|
|
|
871
985
|
commit: typeof result.commit === "string" ? result.commit : void 0,
|
|
872
986
|
prUrl: typeof result.prUrl === "string" ? result.prUrl : void 0,
|
|
873
987
|
skipReason: typeof skipReason === "string" && skipReason !== "" ? skipReason : void 0,
|
|
988
|
+
...result.usage === void 0 ? {} : { usage: result.usage },
|
|
989
|
+
...result.releases === void 0 ? {} : { releases: result.releases },
|
|
874
990
|
error,
|
|
875
991
|
warnings: Array.isArray(result.warnings) ? result.warnings.filter((item) => typeof item === "string") : [],
|
|
876
992
|
...timing(options),
|
|
@@ -880,6 +996,35 @@ function parseRunResult(text, options) {
|
|
|
880
996
|
function timing(options) {
|
|
881
997
|
return { startedAt: options.startedAt, finishedAt: options.finishedAt, durationMs: options.durationMs };
|
|
882
998
|
}
|
|
999
|
+
var REPO_PATTERN = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
|
|
1000
|
+
function parseSubscribeResult(text) {
|
|
1001
|
+
const trimmed = text.trim();
|
|
1002
|
+
if (trimmed === "") throw new IpcError("IPC_INVALID", "\u6838\u5FC3 subscribe \u8F93\u51FA\u4E3A\u7A7A");
|
|
1003
|
+
const lines = trimmed.split("\n");
|
|
1004
|
+
const lastLine = (lines[lines.length - 1] ?? "").trim();
|
|
1005
|
+
let envelope;
|
|
1006
|
+
try {
|
|
1007
|
+
envelope = JSON.parse(lastLine);
|
|
1008
|
+
} catch (error2) {
|
|
1009
|
+
const detail = error2 instanceof Error ? error2.message : String(error2);
|
|
1010
|
+
throw new IpcError("IPC_INVALID", `\u6838\u5FC3 subscribe \u672A\u4EE5\u7ED3\u679C\u4FE1\u5C01\u7ED3\u5C3E\uFF1A${detail}`);
|
|
1011
|
+
}
|
|
1012
|
+
if (!isRecord(envelope) || envelope.ipcSchema !== IPC_SCHEMA_VERSION || typeof envelope.ok !== "boolean") {
|
|
1013
|
+
throw new IpcError("IPC_INVALID", "\u6838\u5FC3 subscribe --json \u4E0D\u662F\u5951\u7EA6\u4FE1\u5C01\uFF08ipcSchema=2 / ok\uFF09");
|
|
1014
|
+
}
|
|
1015
|
+
const error = normalizeError(envelope.error);
|
|
1016
|
+
const repos = [];
|
|
1017
|
+
for (const line of lines.slice(0, -1)) {
|
|
1018
|
+
const value = line.trim();
|
|
1019
|
+
if (value === "") continue;
|
|
1020
|
+
if (REPO_PATTERN.test(value)) repos.push(value);
|
|
1021
|
+
}
|
|
1022
|
+
return {
|
|
1023
|
+
ok: envelope.ok === true,
|
|
1024
|
+
repos,
|
|
1025
|
+
...error === void 0 ? {} : { error }
|
|
1026
|
+
};
|
|
1027
|
+
}
|
|
883
1028
|
|
|
884
1029
|
// src/core/handshake.ts
|
|
885
1030
|
var handshake_exports = {};
|
|
@@ -1698,7 +1843,7 @@ async function defaultGhToken(fresh = false) {
|
|
|
1698
1843
|
if (!fresh && ghTokenCache !== void 0 && Date.now() - ghTokenCache.at < GH_TOKEN_TTL_MS) {
|
|
1699
1844
|
return ghTokenCache.value;
|
|
1700
1845
|
}
|
|
1701
|
-
const { execCapture: execCapture2 } = await import("./exec-
|
|
1846
|
+
const { execCapture: execCapture2 } = await import("./exec-VMDINNX5.js");
|
|
1702
1847
|
const result = await execCapture2("gh", ["auth", "token"], { timeoutMs: 2e3 });
|
|
1703
1848
|
const token = result.code === 0 ? result.stdout.trim() : "";
|
|
1704
1849
|
const value = token === "" ? void 0 : token;
|
|
@@ -2244,7 +2389,8 @@ var runner_exports = {};
|
|
|
2244
2389
|
__export(runner_exports, {
|
|
2245
2390
|
Runner: () => Runner,
|
|
2246
2391
|
isoWeekName: () => isoWeekName,
|
|
2247
|
-
periodFileBase: () => periodFileBase
|
|
2392
|
+
periodFileBase: () => periodFileBase,
|
|
2393
|
+
projectUsage: () => projectUsage
|
|
2248
2394
|
});
|
|
2249
2395
|
import { createHash as createHash2 } from "crypto";
|
|
2250
2396
|
import { existsSync as existsSync4, readFileSync as readFileSync3, realpathSync, statSync as statSync5 } from "fs";
|
|
@@ -2297,6 +2443,27 @@ function periodFileBase(period, date) {
|
|
|
2297
2443
|
if (period === "weekly") return isoWeekName(date);
|
|
2298
2444
|
return date;
|
|
2299
2445
|
}
|
|
2446
|
+
function projectUsage(outcome) {
|
|
2447
|
+
const usageTokens = outcome.usage?.totalTokens;
|
|
2448
|
+
const releasesTokens = outcome.releases?.usage?.totalTokens;
|
|
2449
|
+
let tokens;
|
|
2450
|
+
if (typeof usageTokens === "number" || typeof releasesTokens === "number") {
|
|
2451
|
+
tokens = (typeof usageTokens === "number" ? usageTokens : 0) + (typeof releasesTokens === "number" ? releasesTokens : 0);
|
|
2452
|
+
}
|
|
2453
|
+
const releases = outcome.releases === void 0 ? void 0 : {
|
|
2454
|
+
enabled: outcome.releases.enabled,
|
|
2455
|
+
repos: outcome.releases.repos,
|
|
2456
|
+
newReleases: outcome.releases.newReleases,
|
|
2457
|
+
...outcome.releases.summarized === void 0 ? {} : { summarized: outcome.releases.summarized },
|
|
2458
|
+
...outcome.releases.degraded === void 0 ? {} : { degraded: outcome.releases.degraded },
|
|
2459
|
+
...outcome.releases.failed === void 0 ? {} : { failed: outcome.releases.failed },
|
|
2460
|
+
...outcome.releases.skipped === void 0 ? {} : { skipped: outcome.releases.skipped }
|
|
2461
|
+
};
|
|
2462
|
+
return {
|
|
2463
|
+
...tokens === void 0 ? {} : { tokens },
|
|
2464
|
+
...releases === void 0 ? {} : { releases }
|
|
2465
|
+
};
|
|
2466
|
+
}
|
|
2300
2467
|
var Runner = class {
|
|
2301
2468
|
active;
|
|
2302
2469
|
/** 批量运行(一次触发跑多个周期)期间为 true,挡住外部并发触发。 */
|
|
@@ -2494,6 +2661,7 @@ var Runner = class {
|
|
|
2494
2661
|
...outcome.prUrl === void 0 ? {} : { prUrl: outcome.prUrl },
|
|
2495
2662
|
...outcome.skipReason === void 0 ? {} : { skipReason: outcome.skipReason },
|
|
2496
2663
|
...error === void 0 ? {} : { error },
|
|
2664
|
+
...projectUsage(outcome),
|
|
2497
2665
|
warnings: outcome.warnings,
|
|
2498
2666
|
logFile: input.logFile,
|
|
2499
2667
|
...input.channel === void 0 ? {} : { channel: input.channel },
|
|
@@ -2538,7 +2706,9 @@ var Runner = class {
|
|
|
2538
2706
|
const markdown = outcome.files.filter((file) => {
|
|
2539
2707
|
const ext = path8.extname(file.path).toLowerCase();
|
|
2540
2708
|
const base = path8.basename(file.path).toLowerCase();
|
|
2541
|
-
|
|
2709
|
+
const normalized = file.path.replace(/\\/g, "/");
|
|
2710
|
+
const inReleases = normalized === "releases" || normalized.startsWith("releases/");
|
|
2711
|
+
return ext === ".md" && base !== "readme.md" && base !== "index.md" && !inReleases;
|
|
2542
2712
|
});
|
|
2543
2713
|
if (markdown.length === 0) return skip("no-markdown");
|
|
2544
2714
|
const expected = period === void 0 ? `${date}.md` : `${periodFileBase(period, date)}.md`;
|
|
@@ -2608,6 +2778,8 @@ var Runner = class {
|
|
|
2608
2778
|
...summary.commit === void 0 ? {} : { commit: summary.commit },
|
|
2609
2779
|
...summary.prUrl === void 0 ? {} : { prUrl: summary.prUrl },
|
|
2610
2780
|
...summary.preview === void 0 ? {} : { preview: summary.preview },
|
|
2781
|
+
...summary.tokens === void 0 ? {} : { tokens: summary.tokens },
|
|
2782
|
+
...summary.releases === void 0 ? {} : { releases: summary.releases },
|
|
2611
2783
|
coreVersion: summary.coreVersion,
|
|
2612
2784
|
model: { provider: settings.model.provider, model: settings.model.model },
|
|
2613
2785
|
languages: settings.trending.languages,
|
|
@@ -3228,6 +3400,74 @@ async function readDefaultBranch(repoPath, options = {}) {
|
|
|
3228
3400
|
return { source: "none", message: "\u672A\u8BFB\u53D6\u5230\u9ED8\u8BA4\u5206\u652F\uFF08\u53EF\u80FD\u662F\u7A7A\u4ED3\u5E93\u6216\u6CA1\u6709 origin\uFF09" };
|
|
3229
3401
|
}
|
|
3230
3402
|
|
|
3403
|
+
// src/host/subscribe.ts
|
|
3404
|
+
var subscribe_exports = {};
|
|
3405
|
+
__export(subscribe_exports, {
|
|
3406
|
+
SUBSCRIBE_TIMEOUT_MS: () => SUBSCRIBE_TIMEOUT_MS,
|
|
3407
|
+
isValidRepo: () => isValidRepo,
|
|
3408
|
+
runSubscribe: () => runSubscribe
|
|
3409
|
+
});
|
|
3410
|
+
import { mkdtempSync as mkdtempSync2, writeFileSync as writeFileSync2, rmSync as rmSync2 } from "fs";
|
|
3411
|
+
import os4 from "os";
|
|
3412
|
+
import path11 from "path";
|
|
3413
|
+
var SUBSCRIBE_TIMEOUT_MS = 8e3;
|
|
3414
|
+
var REPO_PATTERN2 = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
|
|
3415
|
+
function isValidRepo(repo) {
|
|
3416
|
+
return REPO_PATTERN2.test(repo.trim());
|
|
3417
|
+
}
|
|
3418
|
+
function writeTempConfig(settings) {
|
|
3419
|
+
const dir = mkdtempSync2(path11.join(os4.tmpdir(), "dsh-subscribe-"));
|
|
3420
|
+
const file = path11.join(dir, "config.yml");
|
|
3421
|
+
const yaml = `${toYaml(toCoreConfig(settings, ""))}
|
|
3422
|
+
`;
|
|
3423
|
+
writeFileSync2(file, yaml, { mode: 384 });
|
|
3424
|
+
return { file, dir };
|
|
3425
|
+
}
|
|
3426
|
+
function requireUsableConfig(settings) {
|
|
3427
|
+
const problems = validateSettings(settings);
|
|
3428
|
+
if (problems.length > 0) {
|
|
3429
|
+
const first = problems[0];
|
|
3430
|
+
throw new IpcError("CONFIG_INVALID", `\u914D\u7F6E\u4E0D\u5B8C\u6574\uFF0C\u65E0\u6CD5\u7BA1\u7406\u8BA2\u9605\uFF1A${first?.message ?? "\u672A\u77E5\u95EE\u9898"}`);
|
|
3431
|
+
}
|
|
3432
|
+
}
|
|
3433
|
+
async function runSubscribe(input, deps) {
|
|
3434
|
+
const env = deps.env ?? process.env;
|
|
3435
|
+
const settings = deps.store.readSettings();
|
|
3436
|
+
requireUsableConfig(settings);
|
|
3437
|
+
if (input.action !== "list") {
|
|
3438
|
+
const repo = (input.repo ?? "").trim();
|
|
3439
|
+
if (!isValidRepo(repo)) {
|
|
3440
|
+
throw new IpcError("CONFIG_INVALID", `\u4ED3\u5E93\u5FC5\u987B\u662F owner/repo \u5F62\u6001\uFF1A${repo || "(\u7A7A)"}`);
|
|
3441
|
+
}
|
|
3442
|
+
}
|
|
3443
|
+
const corePath = deps.corePath !== void 0 ? deps.corePath : (await locateCore({ settings, env, allowDownload: settings.coreAutoDownload })).path;
|
|
3444
|
+
const { file, dir } = writeTempConfig(settings);
|
|
3445
|
+
try {
|
|
3446
|
+
const request = {
|
|
3447
|
+
ipcSchema: 2,
|
|
3448
|
+
command: "subscribe",
|
|
3449
|
+
action: input.action,
|
|
3450
|
+
...input.action === "list" ? {} : { repo: (input.repo ?? "").trim() },
|
|
3451
|
+
configPath: file
|
|
3452
|
+
};
|
|
3453
|
+
const result = await execCapture(corePath, ["subscribe", "--json"], {
|
|
3454
|
+
env: sanitizedEnv(env),
|
|
3455
|
+
input: JSON.stringify(request),
|
|
3456
|
+
timeoutMs: SUBSCRIBE_TIMEOUT_MS
|
|
3457
|
+
});
|
|
3458
|
+
if (result.timedOut) {
|
|
3459
|
+
throw new IpcError("SUBSCRIBE_FAILED", `\u8BA2\u9605\u547D\u4EE4\u8D85\u65F6\uFF08${Math.round(SUBSCRIBE_TIMEOUT_MS / 1e3)} s\uFF09`);
|
|
3460
|
+
}
|
|
3461
|
+
if (result.stdout.trim() === "") {
|
|
3462
|
+
const detail = result.stderr.trim();
|
|
3463
|
+
throw new IpcError("SUBSCRIBE_FAILED", `\u8BA2\u9605\u547D\u4EE4\u65E0\u8F93\u51FA${detail === "" ? "" : `\uFF1A${detail}`}`);
|
|
3464
|
+
}
|
|
3465
|
+
return parseSubscribeResult(result.stdout);
|
|
3466
|
+
} finally {
|
|
3467
|
+
rmSync2(dir, { recursive: true, force: true });
|
|
3468
|
+
}
|
|
3469
|
+
}
|
|
3470
|
+
|
|
3231
3471
|
// src/host/routes.ts
|
|
3232
3472
|
var routes_exports = {};
|
|
3233
3473
|
__export(routes_exports, {
|
|
@@ -3379,6 +3619,28 @@ async function dispatch(method, pathname, url, request, deps) {
|
|
|
3379
3619
|
const repoPath = url.searchParams.get("path") ?? settings.repo.path;
|
|
3380
3620
|
return { repo: await readDefaultBranch(repoPath, { env }) };
|
|
3381
3621
|
}
|
|
3622
|
+
if (method === "GET" && pathname === "/subscriptions") {
|
|
3623
|
+
const result = await runSubscribe({ action: "list" }, { store: deps.store, env });
|
|
3624
|
+
if (!result.ok) {
|
|
3625
|
+
throw new IpcError("SUBSCRIBE_FAILED", result.error?.message ?? "\u8BFB\u53D6\u8BA2\u9605\u5217\u8868\u5931\u8D25");
|
|
3626
|
+
}
|
|
3627
|
+
return { repos: result.repos };
|
|
3628
|
+
}
|
|
3629
|
+
if (method === "POST" && pathname === "/subscriptions") {
|
|
3630
|
+
const body = await readBody2(request);
|
|
3631
|
+
const action = body.action === "add" || body.action === "remove" ? body.action : void 0;
|
|
3632
|
+
if (action === void 0) throw new IpcError("CONFIG_INVALID", "action \u5FC5\u987B\u662F add \u6216 remove");
|
|
3633
|
+
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()] : [];
|
|
3634
|
+
if (repos.length === 0) throw new IpcError("CONFIG_INVALID", "\u5FC5\u987B\u63D0\u4F9B\u8981\u64CD\u4F5C\u7684 owner/repo");
|
|
3635
|
+
for (const repo of repos) {
|
|
3636
|
+
const result = await runSubscribe({ action, repo }, { store: deps.store, env });
|
|
3637
|
+
if (!result.ok) {
|
|
3638
|
+
throw new IpcError("SUBSCRIBE_FAILED", result.error?.message ?? `${action} ${repo} \u5931\u8D25`);
|
|
3639
|
+
}
|
|
3640
|
+
}
|
|
3641
|
+
const latest = await runSubscribe({ action: "list" }, { store: deps.store, env });
|
|
3642
|
+
return { repos: latest.ok ? latest.repos : [] };
|
|
3643
|
+
}
|
|
3382
3644
|
if (method === "POST" && pathname === "/github/test") {
|
|
3383
3645
|
const body = await readBody2(request);
|
|
3384
3646
|
const candidate = body.settings === void 0 ? settings : normalizeSettings(body.settings);
|
|
@@ -3495,7 +3757,12 @@ async function statePayload(deps, settings) {
|
|
|
3495
3757
|
lastResult: state.lastResult ?? null,
|
|
3496
3758
|
pendingPr,
|
|
3497
3759
|
...pendingPrState === void 0 ? {} : { pendingPrState },
|
|
3498
|
-
history
|
|
3760
|
+
history,
|
|
3761
|
+
/** 历史里全部运行的 token 累计(读时求和,不落盘);全无数据则省略。 */
|
|
3762
|
+
...(() => {
|
|
3763
|
+
const totalTokens = sumTokens(history);
|
|
3764
|
+
return totalTokens === void 0 ? {} : { totalTokens };
|
|
3765
|
+
})()
|
|
3499
3766
|
},
|
|
3500
3767
|
model: {
|
|
3501
3768
|
mode: settings.model.mode,
|
|
@@ -3664,6 +3931,13 @@ function createTrendingRunTool(runner) {
|
|
|
3664
3931
|
const head = summary.ok ? summary.skipped ? "\u65E0\u53D8\u66F4\uFF08skipped\uFF09" : summary.dryRun ? "\u8BD5\u8DD1\u5B8C\u6210" : "\u8FD0\u884C\u6210\u529F" : `\u8FD0\u884C\u5931\u8D25\uFF1A${summary.error?.code ?? "INTERNAL"}`;
|
|
3665
3932
|
lines.push(`${summary.ok ? "\u2713" : "\u2717"} [${periodLabel}] ${head}`);
|
|
3666
3933
|
lines.push(`\xB7 \u6838\u5FC3 ${summary.coreVersion || "(\u672A\u77E5)"} \xB7 ${formatDuration(summary.durationMs)} \xB7 ${summary.files} \u4E2A\u6587\u4EF6`);
|
|
3934
|
+
if (summary.tokens !== void 0) {
|
|
3935
|
+
const parts = [`\u672C\u6B21 tokens ${summary.tokens.toLocaleString("en-US")}`];
|
|
3936
|
+
if (summary.releases !== void 0 && summary.releases.enabled) {
|
|
3937
|
+
parts.push(`\u53D1\u7248 ${summary.releases.newReleases} \u4E2A\u65B0\u7248\u672C / ${summary.releases.repos} \u4E2A\u4ED3\u5E93`);
|
|
3938
|
+
}
|
|
3939
|
+
lines.push(`\xB7 ${parts.join(" \xB7 ")}`);
|
|
3940
|
+
}
|
|
3667
3941
|
if (summary.contentHash !== void 0) lines.push(`\xB7 contentHash ${summary.contentHash.slice(0, 12)}`);
|
|
3668
3942
|
if (summary.branch !== void 0) lines.push(`\xB7 \u5206\u652F ${summary.branch}`);
|
|
3669
3943
|
if (summary.prUrl !== void 0) lines.push(`\xB7 PR ${summary.prUrl}`);
|
|
@@ -3686,6 +3960,8 @@ function createTrendingRunTool(runner) {
|
|
|
3686
3960
|
dryRun: summary.dryRun,
|
|
3687
3961
|
durationMs: summary.durationMs,
|
|
3688
3962
|
files: summary.files,
|
|
3963
|
+
...summary.tokens === void 0 ? {} : { tokens: summary.tokens },
|
|
3964
|
+
...summary.releases === void 0 ? {} : { releases: summary.releases },
|
|
3689
3965
|
...summary.branch === void 0 ? {} : { branch: summary.branch },
|
|
3690
3966
|
...summary.prUrl === void 0 ? {} : { prUrl: summary.prUrl },
|
|
3691
3967
|
...summary.error === void 0 ? {} : { errorCode: summary.error.code, errorMessage: summary.error.message }
|
|
@@ -3695,6 +3971,10 @@ function createTrendingRunTool(runner) {
|
|
|
3695
3971
|
dryRun: base.dryRun,
|
|
3696
3972
|
durationMs: summaries.reduce((sum, summary) => sum + summary.durationMs, 0),
|
|
3697
3973
|
files: summaries.reduce((sum, summary) => sum + summary.files, 0),
|
|
3974
|
+
...(() => {
|
|
3975
|
+
const total = summaries.reduce((sum, summary) => sum + (summary.tokens ?? 0), 0);
|
|
3976
|
+
return summaries.some((summary) => summary.tokens !== void 0) ? { tokens: total } : {};
|
|
3977
|
+
})(),
|
|
3698
3978
|
warnings: summaries.flatMap((summary) => summary.warnings),
|
|
3699
3979
|
...primary?.error === void 0 ? {} : { errorCode: primary.error.code, errorMessage: primary.error.message, errorHint: primary.error.hint },
|
|
3700
3980
|
markdown: lines.join("\n")
|
|
@@ -3772,6 +4052,7 @@ export {
|
|
|
3772
4052
|
pending_pr_exports,
|
|
3773
4053
|
preflight_exports,
|
|
3774
4054
|
repo_exports,
|
|
4055
|
+
subscribe_exports,
|
|
3775
4056
|
ROUTE_PREFIX,
|
|
3776
4057
|
createRoutes,
|
|
3777
4058
|
routes_exports,
|
package/lib/index.js
CHANGED
|
@@ -8,8 +8,8 @@ import {
|
|
|
8
8
|
createTrendingRunTool,
|
|
9
9
|
createUpdateService,
|
|
10
10
|
readPluginInfo
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-WFCULY72.js";
|
|
12
|
+
import "./chunk-R7BK7SJK.js";
|
|
13
13
|
|
|
14
14
|
// src/index.ts
|
|
15
15
|
var name = "dsh-github-trending";
|