@morehao/dsh-github-trending 0.1.4 → 0.3.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 +52 -0
- package/README.md +32 -14
- package/client.js +2545 -540
- package/lib/{chunk-RXYA5WFW.js → chunk-X4PBXIZE.js} +905 -268
- package/lib/index.js +29 -11
- package/lib/internal.d.ts +284 -91
- package/lib/internal.js +9 -1
- package/package.json +7 -6
- package/contract/CONTRACT.sha256 +0 -10
- package/contract/UPSTREAM.json +0 -37
- package/contract/fixtures/digest-degraded.json +0 -39
- package/contract/fixtures/digest-empty-lang.json +0 -39
- package/contract/fixtures/digest-normal.json +0 -91
- package/contract/schema/api.v1.yaml +0 -70
- package/contract/schema/digest.v1.json +0 -24
- package/contract/schema/ipc.v1.json +0 -103
- package/contract/schema/model.v1.json +0 -46
package/lib/internal.d.ts
CHANGED
|
@@ -1,60 +1,8 @@
|
|
|
1
|
+
import { ErrorCode, FileArtifact, ErrorInfo, RunRequest, RunResult, State, StateRun } from '@morehao/trendradar-contract';
|
|
1
2
|
import http from 'node:http';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
|
-
*
|
|
5
|
-
* 上游:https://github.com/morehao/trendradar.git@d3bf720a869732e7a2ee04fa39d32dd50868fd61
|
|
6
|
-
* aggregate:eb7f1ac9e117a709d15d87de89cf30e309c479e62dfa3d320cb8f154d3f1dc1e
|
|
7
|
-
* 重新生成:npm run gen:ipc
|
|
8
|
-
*/
|
|
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";
|
|
10
|
-
interface ErrorInfo {
|
|
11
|
-
code: ErrorCode;
|
|
12
|
-
message: string;
|
|
13
|
-
retriable: boolean;
|
|
14
|
-
details?: Record<string, unknown>;
|
|
15
|
-
[key: string]: unknown;
|
|
16
|
-
}
|
|
17
|
-
interface FileArtifact {
|
|
18
|
-
path: string;
|
|
19
|
-
bytes: number;
|
|
20
|
-
sha256: string;
|
|
21
|
-
[key: string]: unknown;
|
|
22
|
-
}
|
|
23
|
-
interface RunRequest {
|
|
24
|
-
ipcSchema: 1;
|
|
25
|
-
command: "run" | "serve" | "config" | "version";
|
|
26
|
-
configPath?: string;
|
|
27
|
-
date?: string;
|
|
28
|
-
dryRun?: boolean;
|
|
29
|
-
outputDir?: string;
|
|
30
|
-
}
|
|
31
|
-
interface RunResult {
|
|
32
|
-
ipcSchema: 1;
|
|
33
|
-
ok: boolean;
|
|
34
|
-
command: "run" | "serve" | "config" | "version";
|
|
35
|
-
startedAt: string;
|
|
36
|
-
finishedAt: string;
|
|
37
|
-
skipped: boolean;
|
|
38
|
-
files: FileArtifact[];
|
|
39
|
-
error?: ErrorInfo;
|
|
40
|
-
warnings?: string[];
|
|
41
|
-
[key: string]: unknown;
|
|
42
|
-
}
|
|
43
|
-
interface StateRun {
|
|
44
|
-
date: string;
|
|
45
|
-
contentHash: string;
|
|
46
|
-
runAt: string;
|
|
47
|
-
[key: string]: unknown;
|
|
48
|
-
}
|
|
49
|
-
interface State {
|
|
50
|
-
ipcSchema: 1;
|
|
51
|
-
lastRun?: StateRun;
|
|
52
|
-
[key: string]: unknown;
|
|
53
|
-
}
|
|
54
|
-
declare const IPC_SCHEMA_VERSION: 1;
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* 错误码:核心码(`ipc.v1` 的 17 个)+ 插件自己的码。
|
|
5
|
+
* 错误码:核心码(契约包 `ipc.v2` / `errors.v2` 的 17 个)+ 插件自己的码。
|
|
58
6
|
*
|
|
59
7
|
* 核心当前只在 stderr 打 `error: <CODE>: <message>`,模型/抓取的失败甚至没有码,
|
|
60
8
|
* 所以这里承担两件事:
|
|
@@ -78,13 +26,22 @@ declare function isRetriable(code: string): boolean;
|
|
|
78
26
|
/** 错误码 → 界面落点。UI 用这个决定红字出现在哪个区块。 */
|
|
79
27
|
type ErrorArea = 'core' | 'model' | 'repo' | 'auth' | 'run';
|
|
80
28
|
declare function areaOf(code: string): ErrorArea;
|
|
29
|
+
/**
|
|
30
|
+
* push 失败的细分原因。核心新版本会在 `details.reason` 里给出;旧核心只有
|
|
31
|
+
* stderr 时按文本兜底。`stale-lease` 必须排在 `non-fast-forward` 之前:
|
|
32
|
+
* 前者是 lease 基线过期,后者是历史分叉,下一步完全不同。
|
|
33
|
+
*/
|
|
34
|
+
type GitReason = 'stale-lease' | 'non-fast-forward' | 'auth' | 'protected' | 'hook' | 'pathspec' | 'unknown';
|
|
35
|
+
declare function reasonOf(code: string, message?: string, details?: Record<string, unknown>): string | undefined;
|
|
81
36
|
/** 每种码一句「下一步怎么做」,避免界面只给码不给路。 */
|
|
82
|
-
declare function hintOf(code: string): string;
|
|
37
|
+
declare function hintOf(code: string, message?: string, reason?: string): string;
|
|
83
38
|
/**
|
|
84
39
|
* 从核心的 stderr 里解出一个结构化错误。
|
|
85
40
|
*
|
|
86
41
|
* 优先级:`error: <CODE>: ...` 的显式码 > 文本归类 > INTERNAL。
|
|
87
|
-
*
|
|
42
|
+
* 显式码命中的那一行往往只是首行(如 `error: GIT_OPERATION_FAILED: To github.com:...`),
|
|
43
|
+
* 真正的根因在其后的多行里(`! [rejected] ... (non-fast-forward)`、`hint: ...`),
|
|
44
|
+
* 因此把这些诊断行一并保留进 message,避免界面只看到半句。
|
|
88
45
|
*/
|
|
89
46
|
declare function classifyStderr(stderr: string): ClassifiedError;
|
|
90
47
|
/**
|
|
@@ -96,38 +53,32 @@ declare function redact(input: string, secrets?: Array<string | undefined>): str
|
|
|
96
53
|
type errors_AnyCode = AnyCode;
|
|
97
54
|
type errors_ClassifiedError = ClassifiedError;
|
|
98
55
|
type errors_ErrorArea = ErrorArea;
|
|
56
|
+
type errors_GitReason = GitReason;
|
|
99
57
|
declare const errors_PLUGIN_CODES: typeof PLUGIN_CODES;
|
|
100
58
|
type errors_PluginCode = PluginCode;
|
|
101
59
|
declare const errors_areaOf: typeof areaOf;
|
|
102
60
|
declare const errors_classifyStderr: typeof classifyStderr;
|
|
103
61
|
declare const errors_hintOf: typeof hintOf;
|
|
104
62
|
declare const errors_isRetriable: typeof isRetriable;
|
|
63
|
+
declare const errors_reasonOf: typeof reasonOf;
|
|
105
64
|
declare const errors_redact: typeof redact;
|
|
106
65
|
declare namespace errors {
|
|
107
|
-
export { type errors_AnyCode as AnyCode, type errors_ClassifiedError as ClassifiedError, type errors_ErrorArea as ErrorArea, 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_redact as redact };
|
|
66
|
+
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 };
|
|
108
67
|
}
|
|
109
68
|
|
|
110
|
-
/**
|
|
111
|
-
|
|
112
|
-
*
|
|
113
|
-
* 类型来自 `contract/schema/ipc.v1.json` 的生成物(`ipc.gen.ts`);本文件只放
|
|
114
|
-
* 契约没有、但插件必须理解的东西:核心 `version --json` 的握手形状、核心 `run --json`
|
|
115
|
-
* 的输出形状,以及把两种结果形状归一化成 `RunOutcome` 的解析器。
|
|
116
|
-
*
|
|
117
|
-
* 为什么同时接受两种形状:`contract/schema/ipc.v1.json` 定义的是 `RunResult`
|
|
118
|
-
* (`ok`/`startedAt`/`error.code`),而当前核心的 `run --json` 输出的是一份更小的
|
|
119
|
-
* `runOutput`(`files`/`skipped`/`branch`/`prUrl`/`digest.contentHash`),错误只走
|
|
120
|
-
* stderr 文本。核心补上信封后,`parseRunResult` 无需改动即可接住。
|
|
121
|
-
*/
|
|
122
|
-
|
|
69
|
+
/** 插件实现所对应的 IPC 契约版本(契约包 `ipc.v2.json` 的 wire 整数)。 */
|
|
70
|
+
declare const IPC_SCHEMA_VERSION: 2;
|
|
123
71
|
/** 插件能接受的 digest 契约版本(与核心 `version --json` 的 digestSchema 比对)。 */
|
|
124
|
-
declare const SUPPORTED_DIGEST_SCHEMA
|
|
72
|
+
declare const SUPPORTED_DIGEST_SCHEMA: 2;
|
|
73
|
+
/** 契约包 `contractVersion` 的主版本;0.x 期间同主版本即视为同一契约线。 */
|
|
74
|
+
declare const SUPPORTED_CONTRACT_MAJOR = 0;
|
|
125
75
|
/** 核心 `version --json` 的输出。 */
|
|
126
76
|
interface VersionInfo {
|
|
127
77
|
version: string;
|
|
128
78
|
commit?: string;
|
|
129
79
|
ipcSchema: number;
|
|
130
80
|
digestSchema: number;
|
|
81
|
+
contractVersion?: string;
|
|
131
82
|
supportedProviders?: string[];
|
|
132
83
|
}
|
|
133
84
|
/** 插件侧的错误信息:`code` 可能是核心码,也可能是插件码(`CORE_*` 等)。 */
|
|
@@ -147,6 +98,8 @@ interface RunOutcome {
|
|
|
147
98
|
branch?: string;
|
|
148
99
|
commit?: string;
|
|
149
100
|
prUrl?: string;
|
|
101
|
+
/** 核心给出的跳过原因:merged | pr-closed | unchanged(可选,旧核心没有)。 */
|
|
102
|
+
skipReason?: string;
|
|
150
103
|
error?: RunError;
|
|
151
104
|
warnings: string[];
|
|
152
105
|
startedAt: string;
|
|
@@ -165,6 +118,7 @@ declare class IpcError extends Error {
|
|
|
165
118
|
declare function parseJsonObject(text: string): Record<string, unknown>;
|
|
166
119
|
declare function isVersionInfo(value: unknown): value is VersionInfo;
|
|
167
120
|
declare function parseVersionInfo(text: string): VersionInfo;
|
|
121
|
+
/** 契约包 `RunResult` → 插件内部 `RunOutcome` 的唯一映射。 */
|
|
168
122
|
interface ParseRunOptions {
|
|
169
123
|
coreVersion: string;
|
|
170
124
|
startedAt: string;
|
|
@@ -175,38 +129,40 @@ interface ParseRunOptions {
|
|
|
175
129
|
/**
|
|
176
130
|
* 把核心 `run --json` 的 stdout 归一化成 `RunOutcome`。
|
|
177
131
|
*
|
|
178
|
-
*
|
|
179
|
-
*
|
|
180
|
-
*
|
|
132
|
+
* 唯一接受的形状是契约 `RunResult`(`ipcSchema=2` / `command=run`),并用契约包
|
|
133
|
+
* 自带的 ajv 校验器校验。任何其它形状直接 `IPC_INVALID`——结果信封读错会把失败
|
|
134
|
+
* 当成功写进状态。
|
|
181
135
|
*/
|
|
182
136
|
declare function parseRunResult(text: string, options: ParseRunOptions): RunOutcome;
|
|
183
137
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
138
|
+
declare const ipc_ErrorCode: typeof ErrorCode;
|
|
139
|
+
declare const ipc_ErrorInfo: typeof ErrorInfo;
|
|
140
|
+
declare const ipc_FileArtifact: typeof FileArtifact;
|
|
187
141
|
declare const ipc_IPC_SCHEMA_VERSION: typeof IPC_SCHEMA_VERSION;
|
|
188
142
|
type ipc_IpcError = IpcError;
|
|
189
143
|
declare const ipc_IpcError: typeof IpcError;
|
|
190
144
|
type ipc_ParseRunOptions = ParseRunOptions;
|
|
191
145
|
type ipc_RunError = RunError;
|
|
192
146
|
type ipc_RunOutcome = RunOutcome;
|
|
193
|
-
|
|
194
|
-
|
|
147
|
+
declare const ipc_RunRequest: typeof RunRequest;
|
|
148
|
+
declare const ipc_RunResult: typeof RunResult;
|
|
149
|
+
declare const ipc_SUPPORTED_CONTRACT_MAJOR: typeof SUPPORTED_CONTRACT_MAJOR;
|
|
195
150
|
declare const ipc_SUPPORTED_DIGEST_SCHEMA: typeof SUPPORTED_DIGEST_SCHEMA;
|
|
196
|
-
|
|
197
|
-
|
|
151
|
+
declare const ipc_State: typeof State;
|
|
152
|
+
declare const ipc_StateRun: typeof StateRun;
|
|
198
153
|
type ipc_VersionInfo = VersionInfo;
|
|
199
154
|
declare const ipc_isVersionInfo: typeof isVersionInfo;
|
|
200
155
|
declare const ipc_parseJsonObject: typeof parseJsonObject;
|
|
201
156
|
declare const ipc_parseRunResult: typeof parseRunResult;
|
|
202
157
|
declare const ipc_parseVersionInfo: typeof parseVersionInfo;
|
|
203
158
|
declare namespace ipc {
|
|
204
|
-
export {
|
|
159
|
+
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, 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_VersionInfo as VersionInfo, ipc_isVersionInfo as isVersionInfo, ipc_parseJsonObject as parseJsonObject, ipc_parseRunResult as parseRunResult, ipc_parseVersionInfo as parseVersionInfo };
|
|
205
160
|
}
|
|
206
161
|
|
|
207
162
|
type Provider = string;
|
|
208
163
|
type CommitMode = 'branch' | 'direct';
|
|
209
|
-
|
|
164
|
+
/** 只保留两种真正可用的方式:本机 `gh` 登录态、手动 PAT。历史的 `device` 在归一化时迁移为 `gh`。 */
|
|
165
|
+
type AuthMode = 'pat' | 'gh';
|
|
210
166
|
type Since = 'daily' | 'weekly';
|
|
211
167
|
interface ModelSettings {
|
|
212
168
|
provider: Provider;
|
|
@@ -271,6 +227,16 @@ declare const DEFAULT_SETTINGS: Settings;
|
|
|
271
227
|
/** 核心支持的 provider 默认端点(空字符串 = 必须由用户填)。 */
|
|
272
228
|
declare const PROVIDER_BASE_URLS: Record<string, string>;
|
|
273
229
|
declare const CORE_PROVIDERS: readonly ["deepseek", "openai-compatible"];
|
|
230
|
+
/** 设置页分区;分段保存时只提交并校验对应分区,互不牵连。 */
|
|
231
|
+
declare const SETTINGS_SECTIONS: readonly ["source", "model", "repo", "auth", "scope", "schedule"];
|
|
232
|
+
type SettingsSection = (typeof SETTINGS_SECTIONS)[number];
|
|
233
|
+
/** 校验问题字段 → 所属分区(用于分段保存时只把本分区的问题回给界面)。 */
|
|
234
|
+
declare function sectionOfField(field: string): SettingsSection | undefined;
|
|
235
|
+
/**
|
|
236
|
+
* 分段保存:只把 `incoming` 里 `section` 的字段合并进 `stored`,其余分区保持已保存值。
|
|
237
|
+
* 这样一个 tab 的保存不会顺带提交或覆盖其它 tab 里尚未保存的改动。
|
|
238
|
+
*/
|
|
239
|
+
declare function mergeSettingsSection(stored: Settings, incoming: Settings, section: SettingsSection): Settings;
|
|
274
240
|
/**
|
|
275
241
|
* 把任意来源的对象(磁盘上的旧版本、HTTP 请求体、CLI 导入)收敛成完整设置。
|
|
276
242
|
* 未知字段一律丢弃:settings.json 只有以下形状,避免旧版本字段悄悄生效。
|
|
@@ -349,18 +315,22 @@ type config_PRSettings = PRSettings;
|
|
|
349
315
|
type config_Problem = Problem;
|
|
350
316
|
type config_Provider = Provider;
|
|
351
317
|
type config_RepoSettings = RepoSettings;
|
|
318
|
+
declare const config_SETTINGS_SECTIONS: typeof SETTINGS_SECTIONS;
|
|
352
319
|
type config_ScheduleSettings = ScheduleSettings;
|
|
353
320
|
type config_Settings = Settings;
|
|
321
|
+
type config_SettingsSection = SettingsSection;
|
|
354
322
|
type config_Since = Since;
|
|
355
323
|
type config_TrendingSettings = TrendingSettings;
|
|
356
324
|
declare const config_effectiveBaseURL: typeof effectiveBaseURL;
|
|
357
325
|
declare const config_isValidTimezone: typeof isValidTimezone;
|
|
326
|
+
declare const config_mergeSettingsSection: typeof mergeSettingsSection;
|
|
358
327
|
declare const config_normalizeSettings: typeof normalizeSettings;
|
|
328
|
+
declare const config_sectionOfField: typeof sectionOfField;
|
|
359
329
|
declare const config_toCoreConfig: typeof toCoreConfig;
|
|
360
330
|
declare const config_toYaml: typeof toYaml;
|
|
361
331
|
declare const config_validateSettings: typeof validateSettings;
|
|
362
332
|
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 };
|
|
333
|
+
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
334
|
}
|
|
365
335
|
|
|
366
336
|
declare const PLUGIN_DIR_NAME = "github-trending";
|
|
@@ -385,11 +355,30 @@ declare namespace paths {
|
|
|
385
355
|
}
|
|
386
356
|
|
|
387
357
|
declare const HISTORY_LIMIT = 30;
|
|
358
|
+
/** 预览副本上限:最多保留 30 份,和 history 的 30 天窗口对齐。 */
|
|
359
|
+
declare const PREVIEW_LIMIT = 30;
|
|
360
|
+
/** 一次预览只读这么多字节;超过的不复制,避免把大文件塞进状态目录。 */
|
|
361
|
+
declare const PREVIEW_MAX_BYTES: number;
|
|
362
|
+
/** 契约 v2 的固定内容哈希算法;旧版状态没有这个字段,据此识别 legacy。 */
|
|
363
|
+
declare const CONTENT_HASH_ALGO_V2 = "jcs-sha256-v1";
|
|
388
364
|
interface DigestIdentity {
|
|
389
365
|
date: string;
|
|
390
366
|
contentHash: string;
|
|
367
|
+
/** 产出该 hash 的算法;v2 新写的一律是 jcs-sha256-v1。 */
|
|
368
|
+
contentHashAlgo: string;
|
|
391
369
|
coreVersion: string;
|
|
392
370
|
}
|
|
371
|
+
/**
|
|
372
|
+
* 预览副本的元数据:只记「哪份文件、多大、内容 sha256」,正文进 previews/。
|
|
373
|
+
* `file` 是仓库内相对路径,不落绝对路径(避免把用户目录写进状态)。
|
|
374
|
+
*/
|
|
375
|
+
interface PreviewMeta {
|
|
376
|
+
file: string;
|
|
377
|
+
bytes: number;
|
|
378
|
+
sha256: string;
|
|
379
|
+
/** 只读接口截断时为 true;当前 512 KB 上限下正常不会出现。 */
|
|
380
|
+
truncated?: boolean;
|
|
381
|
+
}
|
|
393
382
|
interface RunRecord {
|
|
394
383
|
id: string;
|
|
395
384
|
at: string;
|
|
@@ -399,12 +388,19 @@ interface RunRecord {
|
|
|
399
388
|
/** `null` 表示没有错误。 */
|
|
400
389
|
errorCode?: string;
|
|
401
390
|
errorMessage?: string;
|
|
391
|
+
/** push 等失败的机器可判定原因(stale-lease / non-fast-forward / auth ...)。 */
|
|
392
|
+
errorReason?: string;
|
|
393
|
+
/** 跳过原因:merged / pr-closed / unchanged。 */
|
|
394
|
+
skipReason?: string;
|
|
402
395
|
durationMs: number;
|
|
403
396
|
files: number;
|
|
397
|
+
/** 运行所属的调度时区日期(YYYY-MM-DD);旧记录可能没有。 */
|
|
398
|
+
date?: string;
|
|
404
399
|
contentHash?: string;
|
|
405
400
|
branch?: string;
|
|
406
401
|
commit?: string;
|
|
407
402
|
prUrl?: string;
|
|
403
|
+
preview?: PreviewMeta;
|
|
408
404
|
coreVersion: string;
|
|
409
405
|
model: {
|
|
410
406
|
provider: string;
|
|
@@ -413,13 +409,19 @@ interface RunRecord {
|
|
|
413
409
|
languages: string[];
|
|
414
410
|
warnings: string[];
|
|
415
411
|
logFile?: string;
|
|
412
|
+
/** true = 契约 v1 时代留下的旧记录(contentHash 算法不同,不可与 v2 比较)。 */
|
|
413
|
+
legacy?: boolean;
|
|
416
414
|
}
|
|
417
415
|
interface PendingPr {
|
|
418
416
|
url: string;
|
|
419
417
|
createdAt: string;
|
|
418
|
+
/** 该 PR 对应的 digest 日期(YYYY-MM-DD);用于判断「同日重跑」是否真的会撞分支。 */
|
|
419
|
+
date?: string;
|
|
420
420
|
}
|
|
421
421
|
interface PluginState {
|
|
422
422
|
lastRunAt?: string;
|
|
423
|
+
/** 最近一次成功(ok=true,含 skipped)的运行时间;调度用它锁当天。 */
|
|
424
|
+
lastSuccessAt?: string;
|
|
423
425
|
lastDigest?: DigestIdentity;
|
|
424
426
|
lastResult?: RunRecord;
|
|
425
427
|
pendingPr?: PendingPr;
|
|
@@ -427,6 +429,12 @@ interface PluginState {
|
|
|
427
429
|
interface HistoryFile {
|
|
428
430
|
records: RunRecord[];
|
|
429
431
|
}
|
|
432
|
+
interface LegacyMigrationResult {
|
|
433
|
+
stateChanged: boolean;
|
|
434
|
+
clearedDigest: boolean;
|
|
435
|
+
clearedPendingPr: boolean;
|
|
436
|
+
historyMarked: number;
|
|
437
|
+
}
|
|
430
438
|
/** 原子写:同目录临时文件写完再 rename,权限 0600。 */
|
|
431
439
|
declare function writeJsonAtomic(file: string, value: unknown): void;
|
|
432
440
|
interface StoreOptions {
|
|
@@ -442,26 +450,50 @@ declare class Store {
|
|
|
442
450
|
get statePath(): string;
|
|
443
451
|
get historyPath(): string;
|
|
444
452
|
get logsPath(): string;
|
|
453
|
+
get previewsPath(): string;
|
|
445
454
|
readSettings(): Settings;
|
|
446
455
|
writeSettings(settings: Settings): void;
|
|
447
456
|
readState(): PluginState;
|
|
448
457
|
writeState(state: PluginState): void;
|
|
458
|
+
/**
|
|
459
|
+
* 把 v1 时代遗留的 state / history 一次性清洗落盘:清掉不可信的 lastDigest 与
|
|
460
|
+
* 与之绑定的 pendingPr,并给旧历史记录打 legacy 标。插件启动时调用一次。
|
|
461
|
+
*/
|
|
462
|
+
migrateLegacyState(): LegacyMigrationResult;
|
|
449
463
|
readHistory(): RunRecord[];
|
|
464
|
+
/** 原始历史(不做 legacy 标注):写入路径用它,避免把「读时标注」持久化。 */
|
|
465
|
+
private readHistoryRaw;
|
|
450
466
|
/** 记录一次运行:历史裁剪到 30 条,state 同步更新。 */
|
|
451
467
|
recordRun(record: RunRecord, next?: Partial<PluginState>): void;
|
|
452
468
|
newLogPath(id: string): string;
|
|
453
469
|
appendLog(file: string, line: string): void;
|
|
454
470
|
hasLog(file: string): boolean;
|
|
455
471
|
readLog(file: string, maxBytes?: number): string;
|
|
472
|
+
/** 预览副本路径;写入前才建目录,读接口不会凭空创建目录。 */
|
|
473
|
+
previewPath(id: string): string;
|
|
474
|
+
/** 写预览副本:同目录临时文件 + rename、0600;写完裁到 30 份。 */
|
|
475
|
+
writePreview(id: string, text: string): void;
|
|
476
|
+
/** 读预览副本;不存在/不可读返回 undefined,超过上限时截断。 */
|
|
477
|
+
readPreview(id: string, maxBytes?: number): {
|
|
478
|
+
text: string;
|
|
479
|
+
truncated: boolean;
|
|
480
|
+
} | undefined;
|
|
481
|
+
/** 只保留最近 `keep` 份预览副本;按 mtime 倒序,任何错误都忽略。 */
|
|
482
|
+
prunePreviews(keep?: number): void;
|
|
456
483
|
}
|
|
457
484
|
/** 运行 id:时间前缀便于按时间排序,随机后缀避免同毫秒撞车。 */
|
|
458
485
|
declare function newRunId(now?: Date): string;
|
|
459
486
|
|
|
487
|
+
declare const state_CONTENT_HASH_ALGO_V2: typeof CONTENT_HASH_ALGO_V2;
|
|
460
488
|
type state_DigestIdentity = DigestIdentity;
|
|
461
489
|
declare const state_HISTORY_LIMIT: typeof HISTORY_LIMIT;
|
|
462
490
|
type state_HistoryFile = HistoryFile;
|
|
491
|
+
type state_LegacyMigrationResult = LegacyMigrationResult;
|
|
492
|
+
declare const state_PREVIEW_LIMIT: typeof PREVIEW_LIMIT;
|
|
493
|
+
declare const state_PREVIEW_MAX_BYTES: typeof PREVIEW_MAX_BYTES;
|
|
463
494
|
type state_PendingPr = PendingPr;
|
|
464
495
|
type state_PluginState = PluginState;
|
|
496
|
+
type state_PreviewMeta = PreviewMeta;
|
|
465
497
|
type state_RunRecord = RunRecord;
|
|
466
498
|
type state_Store = Store;
|
|
467
499
|
declare const state_Store: typeof Store;
|
|
@@ -469,7 +501,7 @@ type state_StoreOptions = StoreOptions;
|
|
|
469
501
|
declare const state_newRunId: typeof newRunId;
|
|
470
502
|
declare const state_writeJsonAtomic: typeof writeJsonAtomic;
|
|
471
503
|
declare namespace state {
|
|
472
|
-
export { type state_DigestIdentity as DigestIdentity, state_HISTORY_LIMIT as HISTORY_LIMIT, type state_HistoryFile as HistoryFile, type state_PendingPr as PendingPr, type state_PluginState as PluginState, type state_RunRecord as RunRecord, state_Store as Store, type state_StoreOptions as StoreOptions, state_newRunId as newRunId, state_writeJsonAtomic as writeJsonAtomic };
|
|
504
|
+
export { state_CONTENT_HASH_ALGO_V2 as CONTENT_HASH_ALGO_V2, type state_DigestIdentity as DigestIdentity, state_HISTORY_LIMIT as HISTORY_LIMIT, type state_HistoryFile as HistoryFile, type state_LegacyMigrationResult as LegacyMigrationResult, state_PREVIEW_LIMIT as PREVIEW_LIMIT, state_PREVIEW_MAX_BYTES as PREVIEW_MAX_BYTES, type state_PendingPr as PendingPr, type state_PluginState as PluginState, type state_PreviewMeta as PreviewMeta, type state_RunRecord as RunRecord, state_Store as Store, type state_StoreOptions as StoreOptions, state_newRunId as newRunId, state_writeJsonAtomic as writeJsonAtomic };
|
|
473
505
|
}
|
|
474
506
|
|
|
475
507
|
interface CoreRelease {
|
|
@@ -489,7 +521,7 @@ interface ReleaseDescriptor extends CoreRelease {
|
|
|
489
521
|
binaryPath: string;
|
|
490
522
|
cached: boolean;
|
|
491
523
|
}
|
|
492
|
-
/** 从本包的 package.json 读核心版本(`
|
|
524
|
+
/** 从本包的 package.json 读核心版本(`scripts/set-core-version.mjs` 会更新它)。 */
|
|
493
525
|
declare function readCoreRelease(pkg?: {
|
|
494
526
|
dsh?: {
|
|
495
527
|
core?: {
|
|
@@ -697,6 +729,8 @@ interface RunCoreOptions {
|
|
|
697
729
|
token?: string;
|
|
698
730
|
date?: string;
|
|
699
731
|
dryRun: boolean;
|
|
732
|
+
/** 谁触发的运行:核心用它在定时运行时尊重「人工关闭的 PR」。 */
|
|
733
|
+
trigger?: 'manual' | 'schedule';
|
|
700
734
|
/** 回环代理地址:覆盖配置里的 model.baseURL(代理模式专用)。 */
|
|
701
735
|
baseURLOverride?: string;
|
|
702
736
|
signal?: AbortSignal;
|
|
@@ -820,10 +854,11 @@ interface CredentialServices {
|
|
|
820
854
|
declare function credentialServices(get: (name: string) => unknown): CredentialServices | undefined;
|
|
821
855
|
declare function describeRef(services: CredentialServices | undefined, ref: string, env?: NodeJS.ProcessEnv): Promise<CredentialDescription>;
|
|
822
856
|
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: '
|
|
857
|
+
/** GitHub token:按 authMode 取,`gh` 模式读本机 gh 的登录态,`pat` 读凭据/环境变量。 */
|
|
858
|
+
declare function resolveGithubToken(services: CredentialServices | undefined, authMode: 'pat' | 'gh', tokenRef: string, deps?: {
|
|
825
859
|
env?: NodeJS.ProcessEnv;
|
|
826
860
|
execGh?: () => Promise<string | undefined>;
|
|
861
|
+
freshGh?: boolean;
|
|
827
862
|
}): Promise<{
|
|
828
863
|
token?: string;
|
|
829
864
|
source: string;
|
|
@@ -840,6 +875,57 @@ declare namespace credentials {
|
|
|
840
875
|
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
876
|
}
|
|
842
877
|
|
|
878
|
+
/**
|
|
879
|
+
* GitHub 认证探测:供设置页「测试认证」按钮调用。
|
|
880
|
+
*
|
|
881
|
+
* 只做一次 `GET https://api.github.com/user`,把「有没有 token、token 是否有效」
|
|
882
|
+
* 一次性验证清楚并回显登录账号;token 不进日志、不进响应明文。
|
|
883
|
+
*/
|
|
884
|
+
|
|
885
|
+
interface GithubProbeResult {
|
|
886
|
+
ok: boolean;
|
|
887
|
+
login?: string;
|
|
888
|
+
/** token 来源(gh / env / credentials)。 */
|
|
889
|
+
source?: string;
|
|
890
|
+
code?: string;
|
|
891
|
+
message?: string;
|
|
892
|
+
}
|
|
893
|
+
declare function probeGithubAuth(options: {
|
|
894
|
+
credentials: CredentialServices | undefined;
|
|
895
|
+
authMode: 'pat' | 'gh';
|
|
896
|
+
tokenRef: string;
|
|
897
|
+
env?: NodeJS.ProcessEnv;
|
|
898
|
+
fetchImpl?: typeof fetch;
|
|
899
|
+
}): Promise<GithubProbeResult>;
|
|
900
|
+
|
|
901
|
+
type github_GithubProbeResult = GithubProbeResult;
|
|
902
|
+
declare const github_probeGithubAuth: typeof probeGithubAuth;
|
|
903
|
+
declare namespace github {
|
|
904
|
+
export { type github_GithubProbeResult as GithubProbeResult, github_probeGithubAuth as probeGithubAuth };
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
interface DefaultBranchResult {
|
|
908
|
+
branch?: string;
|
|
909
|
+
/** `origin-head` = 远端默认分支;`head` = 本地当前分支兜底;`none` = 读不到。 */
|
|
910
|
+
source: 'origin-head' | 'head' | 'none';
|
|
911
|
+
message?: string;
|
|
912
|
+
}
|
|
913
|
+
/**
|
|
914
|
+
* 读取仓库默认分支:
|
|
915
|
+
* 1. `refs/remotes/origin/HEAD` → 远端默认分支(最准确);
|
|
916
|
+
* 2. 回退到本地当前分支 `HEAD`(空仓库/未 fetch 时仍能给个值);
|
|
917
|
+
* 3. 都失败返回 `none`,由界面提示。
|
|
918
|
+
*/
|
|
919
|
+
declare function readDefaultBranch(repoPath: string, options?: {
|
|
920
|
+
env?: NodeJS.ProcessEnv;
|
|
921
|
+
}): Promise<DefaultBranchResult>;
|
|
922
|
+
|
|
923
|
+
type repo_DefaultBranchResult = DefaultBranchResult;
|
|
924
|
+
declare const repo_readDefaultBranch: typeof readDefaultBranch;
|
|
925
|
+
declare namespace repo {
|
|
926
|
+
export { type repo_DefaultBranchResult as DefaultBranchResult, repo_readDefaultBranch as readDefaultBranch };
|
|
927
|
+
}
|
|
928
|
+
|
|
843
929
|
/**
|
|
844
930
|
* 从宿主的 provider 目录快速填充模型配置(FR-P-03 / AC-P-03)。
|
|
845
931
|
*
|
|
@@ -910,6 +996,18 @@ interface CandidateOptions {
|
|
|
910
996
|
env?: NodeJS.ProcessEnv;
|
|
911
997
|
}
|
|
912
998
|
declare function listProviderCandidates(options: CandidateOptions): Promise<LlmProviderCandidate[]>;
|
|
999
|
+
/** 宿主当前的默认模型选择(`ctx.agentDefaultModel`);没有该服务或读取失败时返回 undefined。 */
|
|
1000
|
+
interface DefaultSelection {
|
|
1001
|
+
provider: string;
|
|
1002
|
+
model: string;
|
|
1003
|
+
reasoningEffort?: string;
|
|
1004
|
+
}
|
|
1005
|
+
declare function readDefaultSelection(get: (name: string) => unknown): DefaultSelection | undefined;
|
|
1006
|
+
/**
|
|
1007
|
+
* 把「DSH 默认模型」落成模型设置:能匹配到已生效路由就复用其认证形态,
|
|
1008
|
+
* 否则按代理模式(hostProvider = 该路由 id)交给宿主转发。
|
|
1009
|
+
*/
|
|
1010
|
+
declare function applyDefaultSelection(settings: Settings, selection: DefaultSelection, candidate?: LlmProviderCandidate): Settings;
|
|
913
1011
|
/**
|
|
914
1012
|
* 把候选落成模型设置。`mode: 'proxy'` 时清空 baseURL 与 apiKeyRef——
|
|
915
1013
|
* 端点由插件在运行时注入回环代理地址,留存旧值只会误导。
|
|
@@ -923,17 +1021,20 @@ declare function resolveModelKey(settings: Settings, credentials: CredentialServ
|
|
|
923
1021
|
}>;
|
|
924
1022
|
|
|
925
1023
|
type quickfill_CandidateOptions = CandidateOptions;
|
|
1024
|
+
type quickfill_DefaultSelection = DefaultSelection;
|
|
926
1025
|
type quickfill_LlmModelCandidate = LlmModelCandidate;
|
|
927
1026
|
type quickfill_LlmProviderCandidate = LlmProviderCandidate;
|
|
928
1027
|
type quickfill_LlmServices = LlmServices;
|
|
929
1028
|
declare const quickfill_applyCandidate: typeof applyCandidate;
|
|
1029
|
+
declare const quickfill_applyDefaultSelection: typeof applyDefaultSelection;
|
|
930
1030
|
declare const quickfill_coreProviderFor: typeof coreProviderFor;
|
|
931
1031
|
declare const quickfill_credentialServices: typeof credentialServices;
|
|
932
1032
|
declare const quickfill_listProviderCandidates: typeof listProviderCandidates;
|
|
933
1033
|
declare const quickfill_llmServices: typeof llmServices;
|
|
1034
|
+
declare const quickfill_readDefaultSelection: typeof readDefaultSelection;
|
|
934
1035
|
declare const quickfill_resolveModelKey: typeof resolveModelKey;
|
|
935
1036
|
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 };
|
|
1037
|
+
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
1038
|
}
|
|
938
1039
|
|
|
939
1040
|
/**
|
|
@@ -1026,6 +1127,59 @@ declare namespace proxy {
|
|
|
1026
1127
|
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
1128
|
}
|
|
1028
1129
|
|
|
1130
|
+
/**
|
|
1131
|
+
* 未合并 PR 的「对账」:把 `state.pendingPr` 和 GitHub 上的真实状态对齐。
|
|
1132
|
+
*
|
|
1133
|
+
* 背景:插件把「上次成功创建的 PR」记在 `pendingPr`,但它不会感知这个 PR 之后
|
|
1134
|
+
* 在 GitHub 上被**合并或关闭**——于是界面/工具会一直显示「未合并」,而且在同日
|
|
1135
|
+
* 重跑时给出误导性的判断。这里做一次只读核对(GET /pulls/{n}):
|
|
1136
|
+
*
|
|
1137
|
+
* - open → 仍是未合并 PR,保留;
|
|
1138
|
+
* - merged → 已完成,清掉陈旧记录;
|
|
1139
|
+
* - closed → 已放弃,清掉陈旧记录;
|
|
1140
|
+
* - unknown → 无 token / 解析失败 / 网络异常,先不动(下次再试)。
|
|
1141
|
+
*
|
|
1142
|
+
* 只读、可注入 `fetchImpl`,并对同一 URL 做 60 s 缓存,避免 `/state` 5 s 轮询
|
|
1143
|
+
* 每次都打 GitHub。任何失败都降级为 `unknown`,绝不让对账影响主流程。
|
|
1144
|
+
*/
|
|
1145
|
+
type PullState = 'open' | 'closed' | 'merged' | 'unknown';
|
|
1146
|
+
interface PendingPrStatus {
|
|
1147
|
+
state: PullState;
|
|
1148
|
+
url: string;
|
|
1149
|
+
number?: number;
|
|
1150
|
+
title?: string;
|
|
1151
|
+
reason?: string;
|
|
1152
|
+
}
|
|
1153
|
+
interface ParsedPullUrl {
|
|
1154
|
+
owner: string;
|
|
1155
|
+
repo: string;
|
|
1156
|
+
number: number;
|
|
1157
|
+
}
|
|
1158
|
+
/** 只认标准的 `https://github.com/<owner>/<repo>/pull/<n>` 形态。 */
|
|
1159
|
+
declare function parsePullUrl(url: string): ParsedPullUrl | undefined;
|
|
1160
|
+
/** 清空缓存(测试与「强制刷新」用)。 */
|
|
1161
|
+
declare function clearPendingPrCache(): void;
|
|
1162
|
+
interface CheckPendingPrOptions {
|
|
1163
|
+
url: string;
|
|
1164
|
+
token?: string;
|
|
1165
|
+
fetchImpl?: typeof fetch;
|
|
1166
|
+
now?: number;
|
|
1167
|
+
/** false = 跳过缓存,强制请求。 */
|
|
1168
|
+
cache?: boolean;
|
|
1169
|
+
}
|
|
1170
|
+
declare function checkPendingPr(options: CheckPendingPrOptions): Promise<PendingPrStatus>;
|
|
1171
|
+
|
|
1172
|
+
type pendingPr_CheckPendingPrOptions = CheckPendingPrOptions;
|
|
1173
|
+
type pendingPr_ParsedPullUrl = ParsedPullUrl;
|
|
1174
|
+
type pendingPr_PendingPrStatus = PendingPrStatus;
|
|
1175
|
+
type pendingPr_PullState = PullState;
|
|
1176
|
+
declare const pendingPr_checkPendingPr: typeof checkPendingPr;
|
|
1177
|
+
declare const pendingPr_clearPendingPrCache: typeof clearPendingPrCache;
|
|
1178
|
+
declare const pendingPr_parsePullUrl: typeof parsePullUrl;
|
|
1179
|
+
declare namespace pendingPr {
|
|
1180
|
+
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 };
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1029
1183
|
interface RunSummary {
|
|
1030
1184
|
id: string;
|
|
1031
1185
|
ok: boolean;
|
|
@@ -1037,7 +1191,11 @@ interface RunSummary {
|
|
|
1037
1191
|
files: number;
|
|
1038
1192
|
contentHash?: string;
|
|
1039
1193
|
branch?: string;
|
|
1194
|
+
commit?: string;
|
|
1040
1195
|
prUrl?: string;
|
|
1196
|
+
preview?: PreviewMeta;
|
|
1197
|
+
/** 核心给出的跳过原因(merged / pr-closed / unchanged)。 */
|
|
1198
|
+
skipReason?: string;
|
|
1041
1199
|
error?: {
|
|
1042
1200
|
code: string;
|
|
1043
1201
|
message: string;
|
|
@@ -1045,6 +1203,8 @@ interface RunSummary {
|
|
|
1045
1203
|
area: string;
|
|
1046
1204
|
retriable: boolean;
|
|
1047
1205
|
inferred?: boolean;
|
|
1206
|
+
/** 机器可判定的细分原因(push 失败时由核心给出)。 */
|
|
1207
|
+
reason?: string;
|
|
1048
1208
|
};
|
|
1049
1209
|
warnings: string[];
|
|
1050
1210
|
logFile?: string;
|
|
@@ -1065,6 +1225,8 @@ interface RunnerDeps {
|
|
|
1065
1225
|
env?: NodeJS.ProcessEnv;
|
|
1066
1226
|
/** 运行结束(成功或失败)后回调,用于刷新调度/界面缓存。 */
|
|
1067
1227
|
onFinished?: (summary: RunSummary) => void;
|
|
1228
|
+
/** 预览副本这类「可失败但不阻断运行」的事件走这里,不写进 warnings。 */
|
|
1229
|
+
logger?: (event: string, data?: Record<string, unknown>) => void;
|
|
1068
1230
|
}
|
|
1069
1231
|
declare class Runner {
|
|
1070
1232
|
private active;
|
|
@@ -1078,6 +1240,15 @@ declare class Runner {
|
|
|
1078
1240
|
run(options: RunRequestOptions): Promise<RunSummary>;
|
|
1079
1241
|
private summarize;
|
|
1080
1242
|
private failureSummary;
|
|
1243
|
+
/**
|
|
1244
|
+
* 从本次核心返回的 artifact 清单里选当天的 `.md`,只读复制到 previews/。
|
|
1245
|
+
*
|
|
1246
|
+
* 这是插件**唯一**读取用户仓库的场景,而且只读核心自己刚写出的那一份:
|
|
1247
|
+
* - 路径必须在 `repo.path` 内(词法 + realpath 各判一次,挡 `..`/绝对路径/符号链接);
|
|
1248
|
+
* - 上限 512 KB、拒绝 NUL、sha256 必须与契约声明一致;
|
|
1249
|
+
* - 任何一步失败都只记日志,返回 undefined;运行结果不受影响。
|
|
1250
|
+
*/
|
|
1251
|
+
private capturePreview;
|
|
1081
1252
|
/** 写历史与状态;同一天的 skipped 运行不覆盖 lastDigest。 */
|
|
1082
1253
|
private record;
|
|
1083
1254
|
/** 给设置页/工具用的「核心现在什么状态」。 */
|
|
@@ -1093,6 +1264,22 @@ declare namespace runner {
|
|
|
1093
1264
|
export { type runner_RunRequestOptions as RunRequestOptions, type runner_RunSummary as RunSummary, runner_Runner as Runner, type runner_RunnerDeps as RunnerDeps };
|
|
1094
1265
|
}
|
|
1095
1266
|
|
|
1267
|
+
interface PluginInfo {
|
|
1268
|
+
name: string;
|
|
1269
|
+
version: string;
|
|
1270
|
+
repository?: string;
|
|
1271
|
+
}
|
|
1272
|
+
/** 只放行 GitHub 的 http(s) 地址;ssh / git+ 前缀先归一化。 */
|
|
1273
|
+
declare function normalizeRepositoryUrl(value: unknown): string | undefined;
|
|
1274
|
+
declare function readPluginInfo(): PluginInfo;
|
|
1275
|
+
|
|
1276
|
+
type pluginInfo_PluginInfo = PluginInfo;
|
|
1277
|
+
declare const pluginInfo_normalizeRepositoryUrl: typeof normalizeRepositoryUrl;
|
|
1278
|
+
declare const pluginInfo_readPluginInfo: typeof readPluginInfo;
|
|
1279
|
+
declare namespace pluginInfo {
|
|
1280
|
+
export { type pluginInfo_PluginInfo as PluginInfo, pluginInfo_normalizeRepositoryUrl as normalizeRepositoryUrl, pluginInfo_readPluginInfo as readPluginInfo };
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1096
1283
|
/**
|
|
1097
1284
|
* 调度(FR-P-08 / 规格 §9)。
|
|
1098
1285
|
*
|
|
@@ -1136,7 +1323,8 @@ declare class Scheduler {
|
|
|
1136
1323
|
private readonly deps;
|
|
1137
1324
|
private timerHandle;
|
|
1138
1325
|
private stopped;
|
|
1139
|
-
|
|
1326
|
+
/** 当天已尝试次数与时间;只在内存里,进程重启后重新计数。 */
|
|
1327
|
+
private readonly attempts;
|
|
1140
1328
|
constructor(deps: SchedulerDeps);
|
|
1141
1329
|
start(): void;
|
|
1142
1330
|
stop(): void;
|
|
@@ -1186,7 +1374,12 @@ interface RouteDeps {
|
|
|
1186
1374
|
scheduler: Scheduler;
|
|
1187
1375
|
get: (name: string) => unknown;
|
|
1188
1376
|
env?: NodeJS.ProcessEnv;
|
|
1377
|
+
/** 注入用:pendingPr 对账的 fetch 实现(测试不联网)。 */
|
|
1378
|
+
fetchImpl?: typeof fetch;
|
|
1189
1379
|
version: string;
|
|
1380
|
+
/** 包名与仓库地址都来自 package.json,由 src/index.ts 传入。 */
|
|
1381
|
+
pluginName?: string;
|
|
1382
|
+
repository?: string;
|
|
1190
1383
|
logger?: (event: string, data?: Record<string, unknown>) => void;
|
|
1191
1384
|
}
|
|
1192
1385
|
declare function createRoutes(deps: RouteDeps): (request: http.IncomingMessage, response: http.ServerResponse) => Promise<void>;
|
|
@@ -1440,4 +1633,4 @@ declare namespace tools {
|
|
|
1440
1633
|
export { tools_createTrendingHistoryTool as createTrendingHistoryTool, tools_createTrendingRunTool as createTrendingRunTool };
|
|
1441
1634
|
}
|
|
1442
1635
|
|
|
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 };
|
|
1636
|
+
export { channel, config, core, credentials, errors, exec, github, handshake$1 as handshake, importCli, ipc, locate, paths, pendingPr, pluginInfo, preflight, proxy, quickfill, release, repo, routes, run, runner, schedule, state, tools };
|