@morehao/dsh-github-trending 0.1.4 → 0.2.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/lib/index.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  createRoutes,
7
7
  createTrendingHistoryTool,
8
8
  createTrendingRunTool
9
- } from "./chunk-RXYA5WFW.js";
9
+ } from "./chunk-HIJIQJCZ.js";
10
10
  import "./chunk-XLIFTAVL.js";
11
11
 
12
12
  // src/index.ts
package/lib/internal.d.ts CHANGED
@@ -2,8 +2,8 @@ import http from 'node:http';
2
2
 
3
3
  /**
4
4
  * 由 scripts/gen-ipc-types.mjs 从 contract/schema/ipc.v1.json 生成,**不要手改**。
5
- * 上游:https://github.com/morehao/trendradar.git@d3bf720a869732e7a2ee04fa39d32dd50868fd61
6
- * aggregate:eb7f1ac9e117a709d15d87de89cf30e309c479e62dfa3d320cb8f154d3f1dc1e
5
+ * 上游:https://github.com/morehao/trendradar.git@5cf0ad26c5748cf2bc9a1cc4ce66a09411d590f7
6
+ * aggregate:4717074d26d1a6d85c1885bd052d411f81c20b39467cb81c398f565bbe34dcde
7
7
  * 重新生成:npm run gen:ipc
8
8
  */
9
9
  type ErrorCode = "INTERNAL" | "CONFIG_INVALID" | "PAYLOAD_TOO_LARGE" | "FETCH_FAILED" | "FETCH_RATE_LIMITED" | "PARSE_FAILED" | "MODEL_UNAUTHORIZED" | "MODEL_RATE_LIMITED" | "MODEL_TIMEOUT" | "MODEL_FAILED" | "MODEL_BAD_OUTPUT" | "GIT_NOT_INSTALLED" | "REPO_NOT_GIT" | "REPO_DIRTY" | "GIT_OPERATION_FAILED" | "PR_FAILED" | "NOT_MERGEABLE";
@@ -43,6 +43,7 @@ interface RunResult {
43
43
  interface StateRun {
44
44
  date: string;
45
45
  contentHash: string;
46
+ outputDir?: string;
46
47
  runAt: string;
47
48
  [key: string]: unknown;
48
49
  }
@@ -79,12 +80,14 @@ declare function isRetriable(code: string): boolean;
79
80
  type ErrorArea = 'core' | 'model' | 'repo' | 'auth' | 'run';
80
81
  declare function areaOf(code: string): ErrorArea;
81
82
  /** 每种码一句「下一步怎么做」,避免界面只给码不给路。 */
82
- declare function hintOf(code: string): string;
83
+ declare function hintOf(code: string, message?: string): string;
83
84
  /**
84
85
  * 从核心的 stderr 里解出一个结构化错误。
85
86
  *
86
87
  * 优先级:`error: <CODE>: ...` 的显式码 > 文本归类 > INTERNAL。
87
- * message 只取最后一条非空行(核心把根因打在最外层,前面的行多是上下文)。
88
+ * 显式码命中的那一行往往只是首行(如 `error: GIT_OPERATION_FAILED: To github.com:...`),
89
+ * 真正的根因在其后的多行里(`! [rejected] ... (non-fast-forward)`、`hint: ...`),
90
+ * 因此把这些诊断行一并保留进 message,避免界面只看到半句。
88
91
  */
89
92
  declare function classifyStderr(stderr: string): ClassifiedError;
90
93
  /**
@@ -206,7 +209,8 @@ declare namespace ipc {
206
209
 
207
210
  type Provider = string;
208
211
  type CommitMode = 'branch' | 'direct';
209
- type AuthMode = 'device' | 'pat' | 'gh';
212
+ /** 只保留两种真正可用的方式:本机 `gh` 登录态、手动 PAT。历史的 `device` 在归一化时迁移为 `gh`。 */
213
+ type AuthMode = 'pat' | 'gh';
210
214
  type Since = 'daily' | 'weekly';
211
215
  interface ModelSettings {
212
216
  provider: Provider;
@@ -271,6 +275,16 @@ declare const DEFAULT_SETTINGS: Settings;
271
275
  /** 核心支持的 provider 默认端点(空字符串 = 必须由用户填)。 */
272
276
  declare const PROVIDER_BASE_URLS: Record<string, string>;
273
277
  declare const CORE_PROVIDERS: readonly ["deepseek", "openai-compatible"];
278
+ /** 设置页分区;分段保存时只提交并校验对应分区,互不牵连。 */
279
+ declare const SETTINGS_SECTIONS: readonly ["source", "model", "repo", "auth", "scope", "schedule"];
280
+ type SettingsSection = (typeof SETTINGS_SECTIONS)[number];
281
+ /** 校验问题字段 → 所属分区(用于分段保存时只把本分区的问题回给界面)。 */
282
+ declare function sectionOfField(field: string): SettingsSection | undefined;
283
+ /**
284
+ * 分段保存:只把 `incoming` 里 `section` 的字段合并进 `stored`,其余分区保持已保存值。
285
+ * 这样一个 tab 的保存不会顺带提交或覆盖其它 tab 里尚未保存的改动。
286
+ */
287
+ declare function mergeSettingsSection(stored: Settings, incoming: Settings, section: SettingsSection): Settings;
274
288
  /**
275
289
  * 把任意来源的对象(磁盘上的旧版本、HTTP 请求体、CLI 导入)收敛成完整设置。
276
290
  * 未知字段一律丢弃:settings.json 只有以下形状,避免旧版本字段悄悄生效。
@@ -349,18 +363,22 @@ type config_PRSettings = PRSettings;
349
363
  type config_Problem = Problem;
350
364
  type config_Provider = Provider;
351
365
  type config_RepoSettings = RepoSettings;
366
+ declare const config_SETTINGS_SECTIONS: typeof SETTINGS_SECTIONS;
352
367
  type config_ScheduleSettings = ScheduleSettings;
353
368
  type config_Settings = Settings;
369
+ type config_SettingsSection = SettingsSection;
354
370
  type config_Since = Since;
355
371
  type config_TrendingSettings = TrendingSettings;
356
372
  declare const config_effectiveBaseURL: typeof effectiveBaseURL;
357
373
  declare const config_isValidTimezone: typeof isValidTimezone;
374
+ declare const config_mergeSettingsSection: typeof mergeSettingsSection;
358
375
  declare const config_normalizeSettings: typeof normalizeSettings;
376
+ declare const config_sectionOfField: typeof sectionOfField;
359
377
  declare const config_toCoreConfig: typeof toCoreConfig;
360
378
  declare const config_toYaml: typeof toYaml;
361
379
  declare const config_validateSettings: typeof validateSettings;
362
380
  declare namespace config {
363
- 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_GithubSettings as GithubSettings, type config_ModelSettings as ModelSettings, type config_OutputSettings as OutputSettings, config_PROVIDER_BASE_URLS as PROVIDER_BASE_URLS, type config_PRSettings as PRSettings, type config_Problem as Problem, type config_Provider as Provider, type config_RepoSettings as RepoSettings, type config_ScheduleSettings as ScheduleSettings, type config_Settings as Settings, type config_Since as Since, type config_TrendingSettings as TrendingSettings, config_effectiveBaseURL as effectiveBaseURL, config_isValidTimezone as isValidTimezone, config_normalizeSettings as normalizeSettings, config_toCoreConfig as toCoreConfig, config_toYaml as toYaml, config_validateSettings as validateSettings };
381
+ 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_GithubSettings as GithubSettings, type config_ModelSettings as ModelSettings, type config_OutputSettings as OutputSettings, config_PROVIDER_BASE_URLS as PROVIDER_BASE_URLS, type config_PRSettings as PRSettings, type config_Problem as Problem, type config_Provider as Provider, 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_TrendingSettings as TrendingSettings, config_effectiveBaseURL as effectiveBaseURL, 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 };
364
382
  }
365
383
 
366
384
  declare const PLUGIN_DIR_NAME = "github-trending";
@@ -417,6 +435,8 @@ interface RunRecord {
417
435
  interface PendingPr {
418
436
  url: string;
419
437
  createdAt: string;
438
+ /** 该 PR 对应的 digest 日期(YYYY-MM-DD);用于判断「同日重跑」是否真的会撞分支。 */
439
+ date?: string;
420
440
  }
421
441
  interface PluginState {
422
442
  lastRunAt?: string;
@@ -820,10 +840,11 @@ interface CredentialServices {
820
840
  declare function credentialServices(get: (name: string) => unknown): CredentialServices | undefined;
821
841
  declare function describeRef(services: CredentialServices | undefined, ref: string, env?: NodeJS.ProcessEnv): Promise<CredentialDescription>;
822
842
  declare function resolveRef(services: CredentialServices | undefined, ref: string, env?: NodeJS.ProcessEnv): Promise<ResolvedSecret>;
823
- /** GitHub token:按 authMode 取,`gh` 模式读本机 gh 的登录态。 */
824
- declare function resolveGithubToken(services: CredentialServices | undefined, authMode: 'device' | 'pat' | 'gh', tokenRef: string, deps?: {
843
+ /** GitHub token:按 authMode 取,`gh` 模式读本机 gh 的登录态,`pat` 读凭据/环境变量。 */
844
+ declare function resolveGithubToken(services: CredentialServices | undefined, authMode: 'pat' | 'gh', tokenRef: string, deps?: {
825
845
  env?: NodeJS.ProcessEnv;
826
846
  execGh?: () => Promise<string | undefined>;
847
+ freshGh?: boolean;
827
848
  }): Promise<{
828
849
  token?: string;
829
850
  source: string;
@@ -840,6 +861,57 @@ declare namespace credentials {
840
861
  export { type credentials_CredentialDescription as CredentialDescription, type credentials_CredentialServices as CredentialServices, type credentials_ResolvedSecret as ResolvedSecret, credentials_credentialServices as credentialServices, credentials_describeRef as describeRef, credentials_resolveGithubToken as resolveGithubToken, credentials_resolveRef as resolveRef };
841
862
  }
842
863
 
864
+ /**
865
+ * GitHub 认证探测:供设置页「测试认证」按钮调用。
866
+ *
867
+ * 只做一次 `GET https://api.github.com/user`,把「有没有 token、token 是否有效」
868
+ * 一次性验证清楚并回显登录账号;token 不进日志、不进响应明文。
869
+ */
870
+
871
+ interface GithubProbeResult {
872
+ ok: boolean;
873
+ login?: string;
874
+ /** token 来源(gh / env / credentials)。 */
875
+ source?: string;
876
+ code?: string;
877
+ message?: string;
878
+ }
879
+ declare function probeGithubAuth(options: {
880
+ credentials: CredentialServices | undefined;
881
+ authMode: 'pat' | 'gh';
882
+ tokenRef: string;
883
+ env?: NodeJS.ProcessEnv;
884
+ fetchImpl?: typeof fetch;
885
+ }): Promise<GithubProbeResult>;
886
+
887
+ type github_GithubProbeResult = GithubProbeResult;
888
+ declare const github_probeGithubAuth: typeof probeGithubAuth;
889
+ declare namespace github {
890
+ export { type github_GithubProbeResult as GithubProbeResult, github_probeGithubAuth as probeGithubAuth };
891
+ }
892
+
893
+ interface DefaultBranchResult {
894
+ branch?: string;
895
+ /** `origin-head` = 远端默认分支;`head` = 本地当前分支兜底;`none` = 读不到。 */
896
+ source: 'origin-head' | 'head' | 'none';
897
+ message?: string;
898
+ }
899
+ /**
900
+ * 读取仓库默认分支:
901
+ * 1. `refs/remotes/origin/HEAD` → 远端默认分支(最准确);
902
+ * 2. 回退到本地当前分支 `HEAD`(空仓库/未 fetch 时仍能给个值);
903
+ * 3. 都失败返回 `none`,由界面提示。
904
+ */
905
+ declare function readDefaultBranch(repoPath: string, options?: {
906
+ env?: NodeJS.ProcessEnv;
907
+ }): Promise<DefaultBranchResult>;
908
+
909
+ type repo_DefaultBranchResult = DefaultBranchResult;
910
+ declare const repo_readDefaultBranch: typeof readDefaultBranch;
911
+ declare namespace repo {
912
+ export { type repo_DefaultBranchResult as DefaultBranchResult, repo_readDefaultBranch as readDefaultBranch };
913
+ }
914
+
843
915
  /**
844
916
  * 从宿主的 provider 目录快速填充模型配置(FR-P-03 / AC-P-03)。
845
917
  *
@@ -910,6 +982,18 @@ interface CandidateOptions {
910
982
  env?: NodeJS.ProcessEnv;
911
983
  }
912
984
  declare function listProviderCandidates(options: CandidateOptions): Promise<LlmProviderCandidate[]>;
985
+ /** 宿主当前的默认模型选择(`ctx.agentDefaultModel`);没有该服务或读取失败时返回 undefined。 */
986
+ interface DefaultSelection {
987
+ provider: string;
988
+ model: string;
989
+ reasoningEffort?: string;
990
+ }
991
+ declare function readDefaultSelection(get: (name: string) => unknown): DefaultSelection | undefined;
992
+ /**
993
+ * 把「DSH 默认模型」落成模型设置:能匹配到已生效路由就复用其认证形态,
994
+ * 否则按代理模式(hostProvider = 该路由 id)交给宿主转发。
995
+ */
996
+ declare function applyDefaultSelection(settings: Settings, selection: DefaultSelection, candidate?: LlmProviderCandidate): Settings;
913
997
  /**
914
998
  * 把候选落成模型设置。`mode: 'proxy'` 时清空 baseURL 与 apiKeyRef——
915
999
  * 端点由插件在运行时注入回环代理地址,留存旧值只会误导。
@@ -923,17 +1007,20 @@ declare function resolveModelKey(settings: Settings, credentials: CredentialServ
923
1007
  }>;
924
1008
 
925
1009
  type quickfill_CandidateOptions = CandidateOptions;
1010
+ type quickfill_DefaultSelection = DefaultSelection;
926
1011
  type quickfill_LlmModelCandidate = LlmModelCandidate;
927
1012
  type quickfill_LlmProviderCandidate = LlmProviderCandidate;
928
1013
  type quickfill_LlmServices = LlmServices;
929
1014
  declare const quickfill_applyCandidate: typeof applyCandidate;
1015
+ declare const quickfill_applyDefaultSelection: typeof applyDefaultSelection;
930
1016
  declare const quickfill_coreProviderFor: typeof coreProviderFor;
931
1017
  declare const quickfill_credentialServices: typeof credentialServices;
932
1018
  declare const quickfill_listProviderCandidates: typeof listProviderCandidates;
933
1019
  declare const quickfill_llmServices: typeof llmServices;
1020
+ declare const quickfill_readDefaultSelection: typeof readDefaultSelection;
934
1021
  declare const quickfill_resolveModelKey: typeof resolveModelKey;
935
1022
  declare namespace quickfill {
936
- export { type quickfill_CandidateOptions as CandidateOptions, type quickfill_LlmModelCandidate as LlmModelCandidate, type quickfill_LlmProviderCandidate as LlmProviderCandidate, type quickfill_LlmServices as LlmServices, quickfill_applyCandidate as applyCandidate, quickfill_coreProviderFor as coreProviderFor, quickfill_credentialServices as credentialServices, quickfill_listProviderCandidates as listProviderCandidates, quickfill_llmServices as llmServices, quickfill_resolveModelKey as resolveModelKey };
1023
+ export { type quickfill_CandidateOptions as CandidateOptions, type quickfill_DefaultSelection as DefaultSelection, type quickfill_LlmModelCandidate as LlmModelCandidate, type quickfill_LlmProviderCandidate as LlmProviderCandidate, type quickfill_LlmServices as LlmServices, quickfill_applyCandidate as applyCandidate, quickfill_applyDefaultSelection as applyDefaultSelection, quickfill_coreProviderFor as coreProviderFor, quickfill_credentialServices as credentialServices, quickfill_listProviderCandidates as listProviderCandidates, quickfill_llmServices as llmServices, quickfill_readDefaultSelection as readDefaultSelection, quickfill_resolveModelKey as resolveModelKey };
937
1024
  }
938
1025
 
939
1026
  /**
@@ -1026,6 +1113,59 @@ declare namespace proxy {
1026
1113
  export { type proxy_LlmLike as LlmLike, type proxy_ProxyHandle as ProxyHandle, type proxy_ProxyOptions as ProxyOptions, proxy_foldMessages as foldMessages, proxy_startProxy as startProxy };
1027
1114
  }
1028
1115
 
1116
+ /**
1117
+ * 未合并 PR 的「对账」:把 `state.pendingPr` 和 GitHub 上的真实状态对齐。
1118
+ *
1119
+ * 背景:插件把「上次成功创建的 PR」记在 `pendingPr`,但它不会感知这个 PR 之后
1120
+ * 在 GitHub 上被**合并或关闭**——于是界面/工具会一直显示「未合并」,而且在同日
1121
+ * 重跑时给出误导性的判断。这里做一次只读核对(GET /pulls/{n}):
1122
+ *
1123
+ * - open → 仍是未合并 PR,保留;
1124
+ * - merged → 已完成,清掉陈旧记录;
1125
+ * - closed → 已放弃,清掉陈旧记录;
1126
+ * - unknown → 无 token / 解析失败 / 网络异常,先不动(下次再试)。
1127
+ *
1128
+ * 只读、可注入 `fetchImpl`,并对同一 URL 做 60 s 缓存,避免 `/state` 5 s 轮询
1129
+ * 每次都打 GitHub。任何失败都降级为 `unknown`,绝不让对账影响主流程。
1130
+ */
1131
+ type PullState = 'open' | 'closed' | 'merged' | 'unknown';
1132
+ interface PendingPrStatus {
1133
+ state: PullState;
1134
+ url: string;
1135
+ number?: number;
1136
+ title?: string;
1137
+ reason?: string;
1138
+ }
1139
+ interface ParsedPullUrl {
1140
+ owner: string;
1141
+ repo: string;
1142
+ number: number;
1143
+ }
1144
+ /** 只认标准的 `https://github.com/<owner>/<repo>/pull/<n>` 形态。 */
1145
+ declare function parsePullUrl(url: string): ParsedPullUrl | undefined;
1146
+ /** 清空缓存(测试与「强制刷新」用)。 */
1147
+ declare function clearPendingPrCache(): void;
1148
+ interface CheckPendingPrOptions {
1149
+ url: string;
1150
+ token?: string;
1151
+ fetchImpl?: typeof fetch;
1152
+ now?: number;
1153
+ /** false = 跳过缓存,强制请求。 */
1154
+ cache?: boolean;
1155
+ }
1156
+ declare function checkPendingPr(options: CheckPendingPrOptions): Promise<PendingPrStatus>;
1157
+
1158
+ type pendingPr_CheckPendingPrOptions = CheckPendingPrOptions;
1159
+ type pendingPr_ParsedPullUrl = ParsedPullUrl;
1160
+ type pendingPr_PendingPrStatus = PendingPrStatus;
1161
+ type pendingPr_PullState = PullState;
1162
+ declare const pendingPr_checkPendingPr: typeof checkPendingPr;
1163
+ declare const pendingPr_clearPendingPrCache: typeof clearPendingPrCache;
1164
+ declare const pendingPr_parsePullUrl: typeof parsePullUrl;
1165
+ declare namespace pendingPr {
1166
+ 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 };
1167
+ }
1168
+
1029
1169
  interface RunSummary {
1030
1170
  id: string;
1031
1171
  ok: boolean;
@@ -1186,6 +1326,8 @@ interface RouteDeps {
1186
1326
  scheduler: Scheduler;
1187
1327
  get: (name: string) => unknown;
1188
1328
  env?: NodeJS.ProcessEnv;
1329
+ /** 注入用:pendingPr 对账的 fetch 实现(测试不联网)。 */
1330
+ fetchImpl?: typeof fetch;
1189
1331
  version: string;
1190
1332
  logger?: (event: string, data?: Record<string, unknown>) => void;
1191
1333
  }
@@ -1440,4 +1582,4 @@ declare namespace tools {
1440
1582
  export { tools_createTrendingHistoryTool as createTrendingHistoryTool, tools_createTrendingRunTool as createTrendingRunTool };
1441
1583
  }
1442
1584
 
1443
- export { channel, config, core, credentials, errors, exec, handshake$1 as handshake, importCli, ipc, locate, paths, preflight, proxy, quickfill, release, routes, run, runner, schedule, state, tools };
1585
+ export { channel, config, core, credentials, errors, exec, github, handshake$1 as handshake, importCli, ipc, locate, paths, pendingPr, preflight, proxy, quickfill, release, repo, routes, run, runner, schedule, state, tools };
package/lib/internal.js CHANGED
@@ -4,22 +4,25 @@ import {
4
4
  core_exports,
5
5
  credentials_exports,
6
6
  errors_exports,
7
+ github_exports,
7
8
  handshake_exports,
8
9
  import_cli_exports,
9
10
  ipc_exports,
10
11
  locate_exports,
11
12
  paths_exports,
13
+ pending_pr_exports,
12
14
  preflight_exports,
13
15
  proxy_exports,
14
16
  quickfill_exports,
15
17
  release_exports,
18
+ repo_exports,
16
19
  routes_exports,
17
20
  run_exports,
18
21
  runner_exports,
19
22
  schedule_exports,
20
23
  state_exports,
21
24
  tools_exports
22
- } from "./chunk-RXYA5WFW.js";
25
+ } from "./chunk-HIJIQJCZ.js";
23
26
  import {
24
27
  exec_exports
25
28
  } from "./chunk-XLIFTAVL.js";
@@ -30,15 +33,18 @@ export {
30
33
  credentials_exports as credentials,
31
34
  errors_exports as errors,
32
35
  exec_exports as exec,
36
+ github_exports as github,
33
37
  handshake_exports as handshake,
34
38
  import_cli_exports as importCli,
35
39
  ipc_exports as ipc,
36
40
  locate_exports as locate,
37
41
  paths_exports as paths,
42
+ pending_pr_exports as pendingPr,
38
43
  preflight_exports as preflight,
39
44
  proxy_exports as proxy,
40
45
  quickfill_exports as quickfill,
41
46
  release_exports as release,
47
+ repo_exports as repo,
42
48
  routes_exports as routes,
43
49
  run_exports as run,
44
50
  runner_exports as runner,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@morehao/dsh-github-trending",
3
- "version": "0.1.4",
3
+ "version": "0.2.0",
4
4
  "description": "GitHub 趋势日报插件:每天定时 spawn 本地 trendradar 核心,抓取 Trending、生成中文简介与总结,提交到你的仓库并自动合并 PR。",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -57,7 +57,7 @@
57
57
  },
58
58
  "core": {
59
59
  "repo": "morehao/trendradar",
60
- "version": "0.1.0"
60
+ "version": "0.2.0"
61
61
  },
62
62
  "client": {
63
63
  "platform": "web",