dsh-github-flow 0.5.0 → 0.6.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/README.en.md +16 -4
- package/README.md +16 -4
- package/docs/UPGRADE-NOTES.md +8 -8
- package/docs/architecture.md +33 -17
- package/docs/images/1.png +0 -0
- package/lib/api/routes-actions.js +139 -8
- package/lib/api/routes-overview.js +147 -29
- package/lib/cache.d.ts +77 -4
- package/lib/cache.js +114 -7
- package/lib/client.d.ts +7 -3
- package/lib/client.js +3309 -314
- package/lib/executor/error-classifier.d.ts +55 -0
- package/lib/executor/error-classifier.js +199 -0
- package/lib/executor/git-parser.d.ts +124 -0
- package/lib/executor/git-parser.js +397 -0
- package/lib/executor.d.ts +122 -4
- package/lib/executor.js +685 -80
- package/lib/tools/help.js +22 -7
- package/lib/tools/image-utils.d.ts +27 -0
- package/lib/tools/image-utils.js +73 -3
- package/lib/types.d.ts +331 -0
- package/lib/ui/help-modal.d.ts +6 -0
- package/lib/ui/help-modal.js +113 -15
- package/lib/ui/issue-modal.d.ts +14 -0
- package/lib/ui/issue-modal.js +366 -0
- package/lib/ui/markdown-lite.d.ts +66 -0
- package/lib/ui/markdown-lite.js +312 -0
- package/lib/ui/network-banner.d.ts +12 -0
- package/lib/ui/network-banner.js +35 -0
- package/lib/ui/pr-modal.d.ts +17 -0
- package/lib/ui/pr-modal.js +516 -0
- package/lib/ui/repo-badges.d.ts +43 -0
- package/lib/ui/repo-badges.js +82 -0
- package/lib/ui/repo-selector.d.ts +14 -0
- package/lib/ui/repo-selector.js +112 -0
- package/lib/ui/storage.d.ts +47 -0
- package/lib/ui/storage.js +139 -0
- package/lib/ui/styles.d.ts +1 -1
- package/lib/ui/styles.js +960 -0
- package/lib/ui/utils.js +13 -1
- package/lib/ui/workspace-panel.js +169 -27
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +1 -1
package/lib/tools/help.js
CHANGED
|
@@ -12,7 +12,7 @@ const KNOWLEDGE_BASE = {
|
|
|
12
12
|
| \`github_api\` | 原生 GitHub REST/GraphQL 逃生门 | 调用任意端点、获取原始文件字节 (raw)、支持自动翻页 (paginate) |
|
|
13
13
|
| \`github_release\` | 版本发布与构建资产交付 | 查看发版历史、自动生成 Release Notes、上传 .tgz 等构建产物 |
|
|
14
14
|
| \`github_secret\` | CI/CD 密钥与变量管理 | 查看 NPM_TOKEN 等密钥清单、经 stdin 安全写入密文、删除密钥;kind:'variable' 管理明文变量(set/get/delete) |
|
|
15
|
-
| \`github_skill\` | 跨 Agent 开源 Skills
|
|
15
|
+
| \`github_skill\` | 跨 Agent 开源 Skills 生态发现与维护 | 检索/预览/安装 GitHub 上的 Agent Skills(gh preview 特性);\`publish\` 规范自检与发布、\`update\` 检查并同步更新已安装技能 |
|
|
16
16
|
| \`github_label\` | 标签体系管理与跨仓库克隆 | 查看标签列表、创建/编辑标签、从源仓库一键 clone 标签体系、删除标签(需 confirm) |
|
|
17
17
|
| \`github_ruleset\` | 分支保护规则与策略诊断 | 检查分支适用的合并策略规则 (check)、查看规则集列表与详情,权威回答“PR 为何无法合并” |
|
|
18
18
|
| \`github_cache\` | Actions 构建缓存盘点与安全清理 | 查看缓存列表与体积占用、按 ID/Key 删除指定缓存、全量清空缓存(需 confirm) |
|
|
@@ -25,7 +25,9 @@ const KNOWLEDGE_BASE = {
|
|
|
25
25
|
| \`github_help\` | 路由导航、官方语法速查与故障自愈 | 遇到不确定的操作、搜索语法或接口报错时查询用法与诊断配方 |
|
|
26
26
|
|
|
27
27
|
💡 **使用准则**:优先调用高层语义工具(pr / issue / run / repo / release / secret);当高层工具无法满足特殊接口需求时,再降级使用 \`github_api\`。
|
|
28
|
+
📊 **规模口径**:18 个工具 / 103 个业务 action(不含 \`github_help\` 的 21 个查询主题与 \`github_api\` 的 4 个 HTTP method——它们不是业务动作)。
|
|
28
29
|
💬 **人类指令**:聊天框支持 \`/gh status\`(大盘看板)、\`/gh upgrade\`(一键升级插件)、\`/gh help\`(快捷帮助)。
|
|
30
|
+
🖥️ **可视化工作台**:最左侧 Octocat 图标打开全景驾驶舱(4 标签:本地工作区 / 我的仓库 / Pull Requests / 待办 Issues);每个会话右侧栏有 5 个 Tab(Git / 未提交 / PR / Issues / Actions)。点击任一 PR 或 Issue 卡片可在线查看详情与评论,无需跳浏览器。
|
|
29
31
|
🗺️ **命令对照**:不确定某 gh 命令对应哪个工具?\`github_help(topic: 'mapping')\` 查询完整映射表(含未覆盖域的 API 引导)。`,
|
|
30
32
|
pr: `### 🔀 github_pr 详细操作指南
|
|
31
33
|
|
|
@@ -47,7 +49,9 @@ const KNOWLEDGE_BASE = {
|
|
|
47
49
|
- **分支落后自愈**: \`github_pr(action: 'update_branch', pr_number: 123)\`
|
|
48
50
|
- 将基准分支最新提交同步进 PR 分支,解决「分支落后需更新」的 CI 门禁失败。
|
|
49
51
|
- **上传本地附件/图片**: \`github_pr(action: 'create', title: 'UI 重构', body: '对比图如下', attach_images: ['./before.png', './after.png'])\`
|
|
50
|
-
- 需 gh ≥ 2.99;支持 create/edit/comment 动作,单批上限 50 个文件,禁止网络 URL,与 view_images
|
|
52
|
+
- 需 gh ≥ 2.99;支持 create/edit/comment 动作,单批上限 50 个文件,禁止网络 URL,与 view_images 对称闭环。
|
|
53
|
+
- **追加评论与编辑**: \`github_pr(action: 'comment', pr_number: 123, body: 'LGTM'); github_pr(action: 'edit', pr_number: 123, body: '更新后的描述')\`
|
|
54
|
+
- 两者同样支持 \`attach_images\` 附件通道。`,
|
|
51
55
|
issue: `### 🎯 github_issue 详细操作指南
|
|
52
56
|
|
|
53
57
|
- **筛选 Issue**: \`github_issue(action: 'list', state: 'open' | 'closed' | 'all', labels: ['bug'], assignees: ['octocat'], limit: 20)\`
|
|
@@ -164,7 +168,13 @@ const KNOWLEDGE_BASE = {
|
|
|
164
168
|
- \`github_skill(action: 'publish')\` —— 默认 \`--dry-run\` 模式,对本地技能目录进行 agentskills.io 合规性检查(命名规范、目录匹配、必需 frontmatter 字段等),零副作用安全自检。
|
|
165
169
|
- \`github_skill(action: 'publish', fix: true)\` —— 自动清洗并剥离残留的安装元数据(\`metadata.github-*\`),修改本地文件但不发布。
|
|
166
170
|
- \`github_skill(action: 'publish', tag: 'v1.0.0', dry_run: false, confirm: true)\` —— 正式发布,强制要求指定 \`tag\` 并附带 \`confirm: true\`(防无头挂起与误发布),自动创建 GitHub Release。
|
|
167
|
-
- ⚠️ 若报「unknown command」,说明宿主机 gh 版本过低,需升级到 2.9x
|
|
171
|
+
- ⚠️ 若报「unknown command」,说明宿主机 gh 版本过低,需升级到 2.9x 以上。
|
|
172
|
+
|
|
173
|
+
- **检查并同步更新已安装技能**:
|
|
174
|
+
- \`github_skill(action: 'update')\` —— **默认 dry-run**,只检查哪些技能有新版本,零副作用。
|
|
175
|
+
- \`github_skill(action: 'update', dry_run: false)\` —— 真正执行同步更新。
|
|
176
|
+
- \`github_skill(action: 'update', all: true)\` —— 更新全部已安装技能(否则只处理 \`skill_names\` 指定项)。
|
|
177
|
+
- \`github_skill(action: 'update', skill_names: ['code-review', 'devops'])\` —— 定向更新指定技能。`,
|
|
168
178
|
label: `### 🏷️ github_label 详细操作指南
|
|
169
179
|
|
|
170
180
|
- **查看标签列表**: \`github_label(action: 'list', limit: 30, search: 'bug')\`
|
|
@@ -269,10 +279,11 @@ const KNOWLEDGE_BASE = {
|
|
|
269
279
|
|
|
270
280
|
#### 一、已覆盖域映射(语义化 action 精确对照)
|
|
271
281
|
|
|
272
|
-
**PR(github_pr,
|
|
282
|
+
**PR(github_pr,15 action)**
|
|
273
283
|
| gh 命令 | 插件调用 | 备注 |
|
|
274
284
|
| :--- | :--- | :--- |
|
|
275
|
-
| \`gh pr list/view/create/diff/edit/comment\` | \`github_pr(action:'list'/'view'/'create'/'diff'/'edit'/'comment')\` |
|
|
285
|
+
| \`gh pr list/view/create/diff/edit/comment\` | \`github_pr(action:'list'/'view'/'create'/'diff'/'edit'/'comment')\` | 高频基础操作;edit/comment 支持 attach_images |
|
|
286
|
+
| (PR 图片查看,gh 无对应命令) | \`github_pr(action:'view_images', pr_number:n)\` | 插件独有:正文+评论图片下载并转为可读图像块 |
|
|
276
287
|
| \`gh pr close\` | 暂无专用 action——用 \`github_pr(action:'edit')\` 或 \`github_api(endpoint:'repos/{o}/{r}/pulls/{n}', method:'PATCH', fields:{state:'closed'})\` | 插件侧未覆盖 |
|
|
277
288
|
| \`gh pr checks\` | \`github_pr(action:'checks', pr_number:n)\` | CI 状态药丸 |
|
|
278
289
|
| \`gh pr review\` | \`github_pr(action:'review', review_decision:'APPROVE'…)\` | |
|
|
@@ -287,6 +298,7 @@ const KNOWLEDGE_BASE = {
|
|
|
287
298
|
| gh 命令 | 插件调用 | 备注 |
|
|
288
299
|
| :--- | :--- | :--- |
|
|
289
300
|
| \`gh issue list/view/create/comment/close/reopen/edit\` | \`github_issue(action:…)\` | 基础操作 |
|
|
301
|
+
| (Issue 图片查看,gh 无对应命令) | \`github_issue(action:'view_images', issue_number:n)\` | 插件独有:报障截图转图像块 |
|
|
290
302
|
| \`gh issue develop\` | \`github_issue(action:'develop', branch_name:…)\` | 关联开发分支 |
|
|
291
303
|
| \`gh issue delete\` | \`github_issue(action:'delete', confirm:true)\` | 物理删除(非 close) |
|
|
292
304
|
| \`gh issue transfer\` | \`github_issue(action:'transfer', target_repo:…, confirm:true)\` | 跨仓库迁移 |
|
|
@@ -325,8 +337,11 @@ const KNOWLEDGE_BASE = {
|
|
|
325
337
|
| \`gh variable list/set/get/delete\` | \`github_secret(action:…, kind:'variable')\` | CI 明文:-b 直传、get 可回显 |
|
|
326
338
|
| (gh secret get 不存在) | — | GitHub 侧加密存储,物理不可读取 |
|
|
327
339
|
|
|
328
|
-
**Skill(github_skill,
|
|
329
|
-
|
|
340
|
+
**Skill(github_skill,6 action)**
|
|
341
|
+
| gh 命令 | 插件调用 | 备注 |
|
|
342
|
+
| :--- | :--- | :--- |
|
|
343
|
+
| \`gh skill search/preview/install/list/publish\` | \`github_skill(action:…)\` | install 需 confirm(写磁盘);publish 默认 dry-run 安全自检,正式发布需 tag 与 confirm |
|
|
344
|
+
| \`gh skill update\` | \`github_skill(action:'update')\` | 默认 dry-run 检查;\`all:true\` 或 \`skill_names\` 定向;\`dry_run:false\` 才真正更新 |
|
|
330
345
|
|
|
331
346
|
**Label(github_label,5 action)**
|
|
332
347
|
| gh 命令 | 插件调用 | 备注 |
|
|
@@ -37,6 +37,33 @@ export declare function sniffImageMime(buf: Buffer): string | null;
|
|
|
37
37
|
/** 图片下载护栏:按真实资源消耗计算——单图字节与目录总量,无张数截断 */
|
|
38
38
|
export declare const IMG_MAX_BYTES: number;
|
|
39
39
|
export declare const IMG_DIR_MAX_BYTES: number;
|
|
40
|
+
export declare const IMG_DIR_LOW_WATERMARK: number;
|
|
41
|
+
/**
|
|
42
|
+
* 图片落盘目录(按内容寻址命名,重复下载天然去重)。
|
|
43
|
+
*
|
|
44
|
+
* 为什么支持 DSH_IMAGE_DIR 覆盖:目录里有 LRU 淘汰,按 mtime 删最旧文件。
|
|
45
|
+
* 若测试把 13MB 假数据写进真实用户目录,淘汰就会优先命中用户更早下载的
|
|
46
|
+
* 真图(用户图 mtime 更老,排序更靠前),造成静默数据丢失。
|
|
47
|
+
* 测试必须能把目录重定向到临时区——这与 upgrade-manager 的 DSH_CLI_BIN /
|
|
48
|
+
* DSH_PROFILE_DIR 覆盖是同一套思路。
|
|
49
|
+
*/
|
|
50
|
+
export declare function imageStoreDir(): string;
|
|
51
|
+
/** 粗略统计图片目录现有总量(遍历一次,文件数有护栏上限不会失控) */
|
|
52
|
+
export declare function imageDirSize(dir: string): number;
|
|
53
|
+
export interface LruEvictionResult {
|
|
54
|
+
freedBytes: number;
|
|
55
|
+
evictedCount: number;
|
|
56
|
+
evictedFiles: string[];
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* LRU 图片缓存淘汰:当目录空间不足以容纳新图片时,按最后修改时间(mtime)淘汰最旧的历史文件。
|
|
60
|
+
*
|
|
61
|
+
* 护栏纪律:
|
|
62
|
+
* 1. 保护当前批次已写入的文件(protectFiles):避免同一批次内前一张图被后一张图立即顶替;
|
|
63
|
+
* 2. 仅淘汰历史文件:按 mtime 升序排列(最旧优先),逐一清理直到目录大小降至目标低水位;
|
|
64
|
+
* 3. 容错防御:单文件删除失败(如文件被锁定)静默跳过继续尝试下一个,绝不崩溃中断。
|
|
65
|
+
*/
|
|
66
|
+
export declare function evictLruImages(dir: string, neededBytes: number, protectFiles?: Set<string>, maxDirBytes?: number, targetBytes?: number): LruEvictionResult;
|
|
40
67
|
export interface DownloadedImage {
|
|
41
68
|
file: string;
|
|
42
69
|
mimeType: string;
|
package/lib/tools/image-utils.js
CHANGED
|
@@ -132,12 +132,24 @@ export function sniffImageMime(buf) {
|
|
|
132
132
|
/** 图片下载护栏:按真实资源消耗计算——单图字节与目录总量,无张数截断 */
|
|
133
133
|
export const IMG_MAX_BYTES = 5 * 1024 * 1024; // 单图 5MB
|
|
134
134
|
export const IMG_DIR_MAX_BYTES = 15 * 1024 * 1024; // 图片缓存目录总量 15MB
|
|
135
|
-
|
|
136
|
-
|
|
135
|
+
export const IMG_DIR_LOW_WATERMARK = 10 * 1024 * 1024; // LRU 淘汰低水位目标 10MB
|
|
136
|
+
/**
|
|
137
|
+
* 图片落盘目录(按内容寻址命名,重复下载天然去重)。
|
|
138
|
+
*
|
|
139
|
+
* 为什么支持 DSH_IMAGE_DIR 覆盖:目录里有 LRU 淘汰,按 mtime 删最旧文件。
|
|
140
|
+
* 若测试把 13MB 假数据写进真实用户目录,淘汰就会优先命中用户更早下载的
|
|
141
|
+
* 真图(用户图 mtime 更老,排序更靠前),造成静默数据丢失。
|
|
142
|
+
* 测试必须能把目录重定向到临时区——这与 upgrade-manager 的 DSH_CLI_BIN /
|
|
143
|
+
* DSH_PROFILE_DIR 覆盖是同一套思路。
|
|
144
|
+
*/
|
|
145
|
+
export function imageStoreDir() {
|
|
146
|
+
const override = (process.env.DSH_IMAGE_DIR || '').trim();
|
|
147
|
+
if (override)
|
|
148
|
+
return path.resolve(override);
|
|
137
149
|
return path.join(os.homedir(), '.dsh', 'data', 'dsh-github-flow', 'images');
|
|
138
150
|
}
|
|
139
151
|
/** 粗略统计图片目录现有总量(遍历一次,文件数有护栏上限不会失控) */
|
|
140
|
-
function imageDirSize(dir) {
|
|
152
|
+
export function imageDirSize(dir) {
|
|
141
153
|
let total = 0;
|
|
142
154
|
try {
|
|
143
155
|
for (const f of fs.readdirSync(dir)) {
|
|
@@ -150,6 +162,57 @@ function imageDirSize(dir) {
|
|
|
150
162
|
catch { }
|
|
151
163
|
return total;
|
|
152
164
|
}
|
|
165
|
+
/**
|
|
166
|
+
* LRU 图片缓存淘汰:当目录空间不足以容纳新图片时,按最后修改时间(mtime)淘汰最旧的历史文件。
|
|
167
|
+
*
|
|
168
|
+
* 护栏纪律:
|
|
169
|
+
* 1. 保护当前批次已写入的文件(protectFiles):避免同一批次内前一张图被后一张图立即顶替;
|
|
170
|
+
* 2. 仅淘汰历史文件:按 mtime 升序排列(最旧优先),逐一清理直到目录大小降至目标低水位;
|
|
171
|
+
* 3. 容错防御:单文件删除失败(如文件被锁定)静默跳过继续尝试下一个,绝不崩溃中断。
|
|
172
|
+
*/
|
|
173
|
+
export function evictLruImages(dir, neededBytes, protectFiles = new Set(), maxDirBytes = IMG_DIR_MAX_BYTES, targetBytes = IMG_DIR_LOW_WATERMARK) {
|
|
174
|
+
const result = { freedBytes: 0, evictedCount: 0, evictedFiles: [] };
|
|
175
|
+
if (!fs.existsSync(dir))
|
|
176
|
+
return result;
|
|
177
|
+
let currentSize = imageDirSize(dir);
|
|
178
|
+
if (currentSize + neededBytes <= maxDirBytes) {
|
|
179
|
+
return result;
|
|
180
|
+
}
|
|
181
|
+
const candidates = [];
|
|
182
|
+
try {
|
|
183
|
+
const entries = fs.readdirSync(dir);
|
|
184
|
+
for (const name of entries) {
|
|
185
|
+
const fullPath = path.join(dir, name);
|
|
186
|
+
if (protectFiles.has(fullPath))
|
|
187
|
+
continue;
|
|
188
|
+
try {
|
|
189
|
+
const stat = fs.statSync(fullPath);
|
|
190
|
+
if (stat.isFile()) {
|
|
191
|
+
candidates.push({ path: fullPath, size: stat.size, mtime: stat.mtimeMs });
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
catch { }
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
return result;
|
|
199
|
+
}
|
|
200
|
+
candidates.sort((a, b) => a.mtime - b.mtime);
|
|
201
|
+
for (const item of candidates) {
|
|
202
|
+
if (currentSize + neededBytes <= maxDirBytes && currentSize <= targetBytes) {
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
try {
|
|
206
|
+
fs.unlinkSync(item.path);
|
|
207
|
+
currentSize -= item.size;
|
|
208
|
+
result.freedBytes += item.size;
|
|
209
|
+
result.evictedCount++;
|
|
210
|
+
result.evictedFiles.push(item.path);
|
|
211
|
+
}
|
|
212
|
+
catch { }
|
|
213
|
+
}
|
|
214
|
+
return result;
|
|
215
|
+
}
|
|
153
216
|
/**
|
|
154
217
|
* 交集过滤:把调用方请求的 URL 硬约束在正文实际提取的合法清单内。
|
|
155
218
|
* 为什么必须交集而非直接信任传入:image_urls 来自模型生成参数,存在幻觉或
|
|
@@ -190,6 +253,7 @@ export async function downloadImages(urls, run) {
|
|
|
190
253
|
const images = [];
|
|
191
254
|
const failures = [];
|
|
192
255
|
const remaining = [];
|
|
256
|
+
const currentBatchFiles = new Set();
|
|
193
257
|
let budgetExhausted = false;
|
|
194
258
|
// 无张数截断:字节护栏按真实资源消耗逐张判定。触顶后仍继续遍历——
|
|
195
259
|
// 剩余 URL 全部收进 remaining 供 Agent 分批续传,而非静默丢弃。
|
|
@@ -213,6 +277,11 @@ export async function downloadImages(urls, run) {
|
|
|
213
277
|
failures.push(`${url.slice(-24)}: 内容不是图片(魔数校验失败)`);
|
|
214
278
|
continue;
|
|
215
279
|
}
|
|
280
|
+
// 空间护栏检查:若超出目录上限,优先触发 LRU 淘汰历史文件以腾出预算
|
|
281
|
+
if (dirSize + buf.length > IMG_DIR_MAX_BYTES) {
|
|
282
|
+
const { freedBytes } = evictLruImages(dir, buf.length, currentBatchFiles);
|
|
283
|
+
dirSize = Math.max(0, dirSize - freedBytes);
|
|
284
|
+
}
|
|
216
285
|
if (dirSize + buf.length > IMG_DIR_MAX_BYTES) {
|
|
217
286
|
budgetExhausted = true;
|
|
218
287
|
remaining.push(url);
|
|
@@ -222,6 +291,7 @@ export async function downloadImages(urls, run) {
|
|
|
222
291
|
const ext = mime.includes('svg') ? 'svg' : mime.split('/')[1].replace('jpeg', 'jpg');
|
|
223
292
|
const file = path.join(dir, `${crypto.createHash('sha256').update(buf).digest('hex').slice(0, 16)}.${ext}`);
|
|
224
293
|
fs.writeFileSync(file, buf);
|
|
294
|
+
currentBatchFiles.add(file);
|
|
225
295
|
// 累计已写入量:下张图的总量护栏判定必须基于最新值(否则多图可突破上限)
|
|
226
296
|
dirSize += buf.length;
|
|
227
297
|
images.push({ file, mimeType: mime, url, bytes: buf.length });
|
package/lib/types.d.ts
CHANGED
|
@@ -68,6 +68,18 @@ export interface GhExecutionOptions {
|
|
|
68
68
|
* 暴露在进程命令行(ps / 任务管理器 / 审计日志可见)的传入通道。
|
|
69
69
|
*/
|
|
70
70
|
stdin?: string;
|
|
71
|
+
/**
|
|
72
|
+
* 单次调用的输出字符上限覆盖(默认沿用实例配置的 maxOutputChars=24000)。
|
|
73
|
+
*
|
|
74
|
+
* 为什么需要按调用覆盖:这个默认值是按「喂给模型上下文的工具输出」调校的,
|
|
75
|
+
* 目的是防 Token 爆窗。但有些输出是**程序化消费**的——例如 PR 全量 Unified Diff
|
|
76
|
+
* 会被切片成按文件索引、前端一次只渲染一个文件,永远不会整段进模型上下文。
|
|
77
|
+
* 对这类调用沿用 24KB 会静默截断真实数据(实测一个普通 PR 的 diff 已达 39KB,
|
|
78
|
+
* 被截断后后半数文件点开皆空)。消费者不同,阈值就该不同。
|
|
79
|
+
*/
|
|
80
|
+
maxOutputChars?: number;
|
|
81
|
+
/** 单次调用的输出 UTF-8 字节上限覆盖,语义同 maxOutputChars */
|
|
82
|
+
maxOutputBytes?: number;
|
|
71
83
|
}
|
|
72
84
|
export interface GhResult<T = unknown> {
|
|
73
85
|
ok: boolean;
|
|
@@ -78,6 +90,22 @@ export interface GhResult<T = unknown> {
|
|
|
78
90
|
truncated?: boolean;
|
|
79
91
|
/** 二进制模式下的字节长度(data 为 Buffer 时存在) */
|
|
80
92
|
binaryBytes?: number;
|
|
93
|
+
/**
|
|
94
|
+
* 失败语义分类(仅 ok=false 时存在)。
|
|
95
|
+
*
|
|
96
|
+
* 为什么挂在结果上而不是让调用方自己 parse error 文本:调用方散落在
|
|
97
|
+
* 各工具与路由里,重复实现文本匹配必然漂移;分类规则只应有一份事实源
|
|
98
|
+
* (src/executor/error-classifier.ts)。上层据此决定「重试 / 回退快照 / 直接降级」。
|
|
99
|
+
*/
|
|
100
|
+
errorKind?: 'transient' | 'deterministic' | 'unknown';
|
|
101
|
+
/**
|
|
102
|
+
* 权限不足时的可操作处置指引(仅 errorKind=deterministic 且命中权限特征时存在)。
|
|
103
|
+
*
|
|
104
|
+
* 为什么单独成字段而不直接拼进 error:error 是「发生了什么」,
|
|
105
|
+
* 这是「接下来怎么做」。工具层可以选择只抛 error(静默场景)
|
|
106
|
+
* 或把两者一起抛给模型(需要模型自愈的场景)。
|
|
107
|
+
*/
|
|
108
|
+
permissionRemedy?: string;
|
|
81
109
|
}
|
|
82
110
|
export interface AuthInstallGuide {
|
|
83
111
|
/** 推荐包管理器命令,例如 Windows 下 "winget install --id GitHub.cli" */
|
|
@@ -107,6 +135,47 @@ export interface AuthStatus {
|
|
|
107
135
|
/** 本地是否已检测到持久化凭据(如 hosts.yml 或 Keyring) */
|
|
108
136
|
hasLocalToken?: boolean;
|
|
109
137
|
}
|
|
138
|
+
/**
|
|
139
|
+
* 当前账号对仓库的权限档位(gh `viewerPermission` 字段的取值域)。
|
|
140
|
+
* 只读(READ / TRIAGE)意味着任何写操作都会被 GitHub 拒绝,
|
|
141
|
+
* UI 应据此在操作前给出提示,而不是让用户点了才吃 403。
|
|
142
|
+
*/
|
|
143
|
+
export type ViewerPermission = 'ADMIN' | 'MAINTAIN' | 'WRITE' | 'TRIAGE' | 'READ';
|
|
144
|
+
/**
|
|
145
|
+
* 工作区的远程布局分类(离线解析得出,用于确定「该用哪个 remote 的身份」)。
|
|
146
|
+
*
|
|
147
|
+
* 为什么要分类:混合布局下若按 `.git/config` 的书写顺序选 remote,
|
|
148
|
+
* 同一个工作区在两次 `git remote` 操作后可能解析出不同仓库。
|
|
149
|
+
* 分类后每种布局的处置规则固定,与书写顺序无关。
|
|
150
|
+
*/
|
|
151
|
+
export type RepoLayoutKind =
|
|
152
|
+
/** 全部 remote 都是 github.com */
|
|
153
|
+
'github-only'
|
|
154
|
+
/** 含 GitHub remote,但 git 选中的那个不是 GitHub */
|
|
155
|
+
| 'github-mixed'
|
|
156
|
+
/** 无任何 GitHub remote(全 GHE 或其他 host) */
|
|
157
|
+
| 'no-github'
|
|
158
|
+
/** 无 remote */
|
|
159
|
+
| 'no-remote';
|
|
160
|
+
/**
|
|
161
|
+
* 关联仓库角色标识:
|
|
162
|
+
* - fork: 属于当前登录用户的个人复刻仓库
|
|
163
|
+
* - upstream: 社区上游主干仓库(名为 upstream 或作为 parent)
|
|
164
|
+
* - origin: 默认 origin 远程仓库
|
|
165
|
+
* - parent: 上游源仓库(在线识别自 repo.parent,本地尚未添加 remote)
|
|
166
|
+
* - remote: 其他自定义名称的远程仓库
|
|
167
|
+
*/
|
|
168
|
+
export type AssociatedRepoRole = 'origin' | 'upstream' | 'fork' | 'parent' | 'remote';
|
|
169
|
+
/**
|
|
170
|
+
* 当前工作区可切换的关联 GitHub 仓库项(供仓库切换器下拉菜单消费)。
|
|
171
|
+
*/
|
|
172
|
+
export interface AssociatedRepoItem {
|
|
173
|
+
nameWithOwner: string;
|
|
174
|
+
remoteName?: string;
|
|
175
|
+
url: string;
|
|
176
|
+
isCurrent: boolean;
|
|
177
|
+
role: AssociatedRepoRole;
|
|
178
|
+
}
|
|
110
179
|
export interface RepoMetadata {
|
|
111
180
|
nameWithOwner: string;
|
|
112
181
|
name: string;
|
|
@@ -118,6 +187,30 @@ export interface RepoMetadata {
|
|
|
118
187
|
url?: string;
|
|
119
188
|
stargazerCount?: number;
|
|
120
189
|
forkCount?: number;
|
|
190
|
+
/** 是否为 fork(影响 star 取谁、是否提示可查看上游) */
|
|
191
|
+
isFork?: boolean;
|
|
192
|
+
/**
|
|
193
|
+
* fork 的上游。
|
|
194
|
+
* gh 的 `parent` 只返回骨架(id/name/owner.login),nameWithOwner 需自行拼接;
|
|
195
|
+
* 上游 star 数拿不到(`--json` 不支持嵌套子字段),故此处不含热度字段。
|
|
196
|
+
*/
|
|
197
|
+
parent?: {
|
|
198
|
+
nameWithOwner: string;
|
|
199
|
+
url?: string;
|
|
200
|
+
};
|
|
201
|
+
/**
|
|
202
|
+
* 当前账号对该仓库的权限。
|
|
203
|
+
* 离线解析时为 undefined——**不猜测**:猜错会导致 UI 给出错误的操作许可。
|
|
204
|
+
*/
|
|
205
|
+
viewerPermission?: ViewerPermission;
|
|
206
|
+
/** 远程布局分类(仅离线解析产生,供 UI 与诊断区分场景) */
|
|
207
|
+
layout?: RepoLayoutKind;
|
|
208
|
+
/**
|
|
209
|
+
* 当前工作区可供用户手动切换的关联仓库列表。
|
|
210
|
+
* 包含:本地 Git 配置的全部 GitHub remote (origin, upstream 等) 及在线 parent。
|
|
211
|
+
* 仅当数量 > 1 时 UI 渲染切换控件,单仓库场景保持零噪音。
|
|
212
|
+
*/
|
|
213
|
+
associatedRepos?: AssociatedRepoItem[];
|
|
121
214
|
}
|
|
122
215
|
/** Git 分支详情项(供分支切换器下拉列表消费) */
|
|
123
216
|
export interface GitBranchItem {
|
|
@@ -200,6 +293,105 @@ export interface PrItem {
|
|
|
200
293
|
url: string;
|
|
201
294
|
updatedAt: string;
|
|
202
295
|
}
|
|
296
|
+
/** PR 变动文件详情项 */
|
|
297
|
+
export interface PrFileItem {
|
|
298
|
+
path: string;
|
|
299
|
+
additions: number;
|
|
300
|
+
deletions: number;
|
|
301
|
+
changeType?: string;
|
|
302
|
+
}
|
|
303
|
+
/** PR 评论项 */
|
|
304
|
+
export interface PrCommentItem {
|
|
305
|
+
id: string;
|
|
306
|
+
author: {
|
|
307
|
+
login: string;
|
|
308
|
+
avatarUrl?: string;
|
|
309
|
+
};
|
|
310
|
+
authorAssociation?: string;
|
|
311
|
+
body: string;
|
|
312
|
+
createdAt: string;
|
|
313
|
+
url: string;
|
|
314
|
+
}
|
|
315
|
+
/** PR 审查记录项 */
|
|
316
|
+
export interface PrReviewItem {
|
|
317
|
+
id: string;
|
|
318
|
+
author: {
|
|
319
|
+
login: string;
|
|
320
|
+
};
|
|
321
|
+
state: string;
|
|
322
|
+
body: string;
|
|
323
|
+
submittedAt: string;
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* PR 行级审查评论项(代码行上的评论,区别于 Issue 级讨论)。
|
|
327
|
+
*
|
|
328
|
+
* 为什么必须单列:`gh pr view --json comments` 只返回**对话区**的 issue-level 评论,
|
|
329
|
+
* 完全不包含挂在具体代码行上的 review comment。实测 cli/cli#14752 有 10 条行级评论,
|
|
330
|
+
* 而 `--json comments` 一条都拿不到——必须走
|
|
331
|
+
* `GET /repos/{owner}/{repo}/pulls/{number}/comments` 独立通道。
|
|
332
|
+
*
|
|
333
|
+
* 不做的部分:不把评论按行号精确嵌进 diff 的 hunk 中间(需反查 hunk 偏移,
|
|
334
|
+
* 多行/折叠上下文下极易错位)。改为在文件级 diff 下方按行号列出,信息完整且确定。
|
|
335
|
+
*/
|
|
336
|
+
export interface PrLineCommentItem {
|
|
337
|
+
id: string;
|
|
338
|
+
/** 所属文件路径,与 fileDiffs 的键一致 */
|
|
339
|
+
path: string;
|
|
340
|
+
/** 评论锚定的行号(新文件侧);纯删除行可能为 null */
|
|
341
|
+
line: number | null;
|
|
342
|
+
side?: string;
|
|
343
|
+
author: {
|
|
344
|
+
login: string;
|
|
345
|
+
};
|
|
346
|
+
body: string;
|
|
347
|
+
createdAt: string;
|
|
348
|
+
}
|
|
349
|
+
/** PR 完整详情与差异数据契约(供 PrDetailModal 在线审阅消费) */
|
|
350
|
+
export interface PrDetailData {
|
|
351
|
+
number: number;
|
|
352
|
+
title: string;
|
|
353
|
+
state: 'OPEN' | 'CLOSED' | 'MERGED';
|
|
354
|
+
isDraft: boolean;
|
|
355
|
+
url: string;
|
|
356
|
+
createdAt: string;
|
|
357
|
+
updatedAt: string;
|
|
358
|
+
author: {
|
|
359
|
+
login: string;
|
|
360
|
+
avatarUrl?: string;
|
|
361
|
+
};
|
|
362
|
+
headRefName: string;
|
|
363
|
+
baseRefName: string;
|
|
364
|
+
headRepoOwner?: string;
|
|
365
|
+
body: string;
|
|
366
|
+
reviewDecision?: string;
|
|
367
|
+
statusCheckRollup?: any;
|
|
368
|
+
additions: number;
|
|
369
|
+
deletions: number;
|
|
370
|
+
files: PrFileItem[];
|
|
371
|
+
comments: PrCommentItem[];
|
|
372
|
+
reviews: PrReviewItem[];
|
|
373
|
+
/**
|
|
374
|
+
* 行级审查评论(挂在具体代码行上的 review comment)。
|
|
375
|
+
* 与 comments 是**两套独立数据源**:comments 来自对话区,lineComments 来自
|
|
376
|
+
* /pulls/{n}/comments。拉取失败时降级为空数组,不阻塞主详情。
|
|
377
|
+
*/
|
|
378
|
+
lineComments?: PrLineCommentItem[];
|
|
379
|
+
/** 按文件相对路径切片索引的 Git Unified Diff 字典 */
|
|
380
|
+
fileDiffs: Record<string, string>;
|
|
381
|
+
/**
|
|
382
|
+
* 为什么不回传 fullDiff 原文:`fileDiffs` 已经是全量 diff 的等价切分
|
|
383
|
+
* (每段拼起来就是原文),再附带一份原文会让 HTTP 响应体整整翻倍。
|
|
384
|
+
* 实测一个普通 PR 的 diff 就有 39KB,2MB 上限下翻倍意味着 4MB JSON——
|
|
385
|
+
* 白占带宽、白占浏览器内存、白耗 JSON.parse 时间,且没有任何消费方。
|
|
386
|
+
* 原文仅在服务端用于切片,切片完即丢弃。
|
|
387
|
+
*/
|
|
388
|
+
/**
|
|
389
|
+
* diff 是否被输出阈值截断。
|
|
390
|
+
* 为什么必须透出:超巨量 PR 仍可能触顶,此时部分文件拿不到 diff。
|
|
391
|
+
* 静默展示「该文件无差异」会让用户误以为代码没改动——必须显式提示。
|
|
392
|
+
*/
|
|
393
|
+
diffTruncated?: boolean;
|
|
394
|
+
}
|
|
203
395
|
/**
|
|
204
396
|
* Issue 分类维度契约:
|
|
205
397
|
* - reported: 用户提起的(他人向我名下项目或本仓库提交的 Issue 反馈)
|
|
@@ -207,6 +399,107 @@ export interface PrItem {
|
|
|
207
399
|
* - created: 我创建的(由当前账号亲自发起的 Issue)
|
|
208
400
|
*/
|
|
209
401
|
export type IssueCategory = 'reported' | 'assigned' | 'created';
|
|
402
|
+
/** Issue 评论项(在线查看弹窗的讨论时间线消费) */
|
|
403
|
+
export interface IssueCommentItem {
|
|
404
|
+
id: string;
|
|
405
|
+
author: {
|
|
406
|
+
login: string;
|
|
407
|
+
avatarUrl?: string;
|
|
408
|
+
};
|
|
409
|
+
authorAssociation?: string;
|
|
410
|
+
body: string;
|
|
411
|
+
createdAt: string;
|
|
412
|
+
url: string;
|
|
413
|
+
/**
|
|
414
|
+
* GitHub 侧被折叠/隐藏的评论(垃圾、攻击性内容等)。
|
|
415
|
+
* 为什么必须透出:实测 cli/cli#1 的评论带 `isMinimized: true, minimizedReason: "SPAM"`,
|
|
416
|
+
* 若照常渲染成普通讨论,用户会把垃圾内容当成真实技术意见。
|
|
417
|
+
*/
|
|
418
|
+
isMinimized?: boolean;
|
|
419
|
+
minimizedReason?: string;
|
|
420
|
+
includesCreatedEdit?: boolean;
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Issue 关联的 PR 引用。
|
|
424
|
+
*
|
|
425
|
+
* 字段集受限于 gh 的实际返回:实测 `gh issue view --json closedByPullRequestsReferences`
|
|
426
|
+
* 的节点只有 `id / number / repository / url`,**没有 title 与 state**。
|
|
427
|
+
* UI 因此只渲染 `#number` 链接,不得假设更多字段存在。
|
|
428
|
+
*/
|
|
429
|
+
export interface IssueLinkedPrRef {
|
|
430
|
+
number: number;
|
|
431
|
+
url: string;
|
|
432
|
+
/** `owner/repo`;跨仓关联时与 Issue 自身仓库不同 */
|
|
433
|
+
repository?: string;
|
|
434
|
+
}
|
|
435
|
+
/** Issue 里程碑(实测形态:number/title/description/dueOn,无 state) */
|
|
436
|
+
export interface IssueMilestoneInfo {
|
|
437
|
+
number?: number;
|
|
438
|
+
title: string;
|
|
439
|
+
/** ISO 时间;未设置截止日时为缺省 */
|
|
440
|
+
dueOn?: string;
|
|
441
|
+
}
|
|
442
|
+
/** 子议题完成度摘要(gh `subIssuesSummary` 的直接映射) */
|
|
443
|
+
export interface IssueSubIssuesSummary {
|
|
444
|
+
completed: number;
|
|
445
|
+
total: number;
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Issue 完整详情数据契约(供 IssueDetailModal 在线查看消费)。
|
|
449
|
+
*
|
|
450
|
+
* 为什么不复用 `IssueItem`:列表项只需要渲染一行卡片,字段刻意精简;
|
|
451
|
+
* 详情需要正文、评论时间线、里程碑、子议题等重字段,混在一起会让
|
|
452
|
+
* 全局概览的缓存与快照体积翻数倍(每条 Issue 都拖着全部评论)。
|
|
453
|
+
*/
|
|
454
|
+
export interface IssueDetailData {
|
|
455
|
+
number: number;
|
|
456
|
+
title: string;
|
|
457
|
+
state: 'OPEN' | 'CLOSED';
|
|
458
|
+
/** COMPLETED / NOT_PLANNED / REOPENED / ''(实测空串形态存在) */
|
|
459
|
+
stateReason?: string;
|
|
460
|
+
url: string;
|
|
461
|
+
createdAt: string;
|
|
462
|
+
updatedAt: string;
|
|
463
|
+
closedAt?: string;
|
|
464
|
+
author: {
|
|
465
|
+
login: string;
|
|
466
|
+
avatarUrl?: string;
|
|
467
|
+
};
|
|
468
|
+
body: string;
|
|
469
|
+
labels: Array<{
|
|
470
|
+
name: string;
|
|
471
|
+
color?: string;
|
|
472
|
+
description?: string;
|
|
473
|
+
}>;
|
|
474
|
+
assignees: Array<{
|
|
475
|
+
login: string;
|
|
476
|
+
}>;
|
|
477
|
+
milestone?: IssueMilestoneInfo;
|
|
478
|
+
isPinned?: boolean;
|
|
479
|
+
issueType?: string;
|
|
480
|
+
comments: IssueCommentItem[];
|
|
481
|
+
linkedPrs: IssueLinkedPrRef[];
|
|
482
|
+
subIssues?: IssueSubIssuesSummary;
|
|
483
|
+
/**
|
|
484
|
+
* 正文与评论中识别到的图片 URL(与 github_issue(view_images) 同源提取)。
|
|
485
|
+
*
|
|
486
|
+
* 为什么只给清单不在弹窗内联渲染:图片可能来自任意 https 外域,
|
|
487
|
+
* 在面板里直接 `<img src>` 会把宿主页面 Referer/来源暴露给第三方,
|
|
488
|
+
* 也绕过了插件的域名白名单防线。UI 只展示「附件 N 张」并给外链。
|
|
489
|
+
*/
|
|
490
|
+
images: string[];
|
|
491
|
+
/**
|
|
492
|
+
* 是否发生过字段集降级。
|
|
493
|
+
* 为什么需要:老版本 gh 遇到未知 JSON 字段会整体失败(实测
|
|
494
|
+
* `Unknown JSON field: "closedAt"`),此时回退到 BASE 字段集重试;
|
|
495
|
+
* 该标记供排查「为什么没看到里程碑/关联 PR」这类差异,不弹错。
|
|
496
|
+
*
|
|
497
|
+
* 注意:不设 truncated 标记——响应被输出阈值截断时 executor 直接返回
|
|
498
|
+
* `ok:false` + 浏览器直达链接,绝不会产出「零评论」的空详情对象,
|
|
499
|
+
* 因此该失败语义不需要在数据契约里再表达一次。
|
|
500
|
+
*/
|
|
501
|
+
fieldsDegraded?: boolean;
|
|
502
|
+
}
|
|
210
503
|
export interface IssueStats {
|
|
211
504
|
total: number;
|
|
212
505
|
reported: number;
|
|
@@ -255,6 +548,14 @@ export interface GitHubOverviewData {
|
|
|
255
548
|
networkError?: boolean;
|
|
256
549
|
/** 网络异常的原因或提示 */
|
|
257
550
|
networkErrorReason?: string;
|
|
551
|
+
/**
|
|
552
|
+
* 确定性降级说明(非错误)。
|
|
553
|
+
*
|
|
554
|
+
* 为什么与 networkError 分开:仓库关闭 Issues、未启用 Discussions 这类
|
|
555
|
+
* 「配置事实」不是故障,不该触发网络告警横幅与重试。它们只需要在面板上
|
|
556
|
+
* 安静地说明一句「该仓库未开启 Issues」,让用户知道空列表是正常的。
|
|
557
|
+
*/
|
|
558
|
+
notices?: string[];
|
|
258
559
|
/** 插件版本与升级信息(由内存缓存快速读取,不阻塞首屏业务) */
|
|
259
560
|
updateInfo?: UpdateInfo;
|
|
260
561
|
/** 本地 Git 状态(ahead/behind/dirty,remote-tracking 快照语义);非 Git 工作区为 undefined */
|
|
@@ -278,6 +579,17 @@ export interface GitHubOverviewData {
|
|
|
278
579
|
} | null;
|
|
279
580
|
/** 当前工作区的 Git 分支列表(供右侧栏分支选择器 0ms 秒开) */
|
|
280
581
|
branches?: GitBranchesResult | null;
|
|
582
|
+
/**
|
|
583
|
+
* 单仓库 PR 列表是否触及条数上限(仅触顶时下发)。
|
|
584
|
+
*
|
|
585
|
+
* 为什么必须透出:查询已放宽为 `--state all`,列表按 number 降序取前 N 条,
|
|
586
|
+
* 历史 PR 超过上限时界面会静默少显示——用户切到「Closed」看到几条
|
|
587
|
+
* 就会误以为仓库只有这么几个已关闭 PR,无法区分「就这么多」与「被截断了」。
|
|
588
|
+
* 与全局面板的 prsTruncated 同一语义。
|
|
589
|
+
*/
|
|
590
|
+
prsTruncated?: boolean;
|
|
591
|
+
/** 单仓库 Issue 列表是否触及条数上限(语义同 prsTruncated) */
|
|
592
|
+
issuesTruncated?: boolean;
|
|
281
593
|
}
|
|
282
594
|
export interface UserRepoItem {
|
|
283
595
|
name: string;
|
|
@@ -328,14 +640,28 @@ export interface GlobalOverviewData {
|
|
|
328
640
|
myPrs: Array<{
|
|
329
641
|
number: number;
|
|
330
642
|
title: string;
|
|
643
|
+
/**
|
|
644
|
+
* PR 状态。为什么必须下发:主面板默认展示「全部」而非仅 open
|
|
645
|
+
* (实测账号可能零 open PR,只查 open 会恒为空白),
|
|
646
|
+
* 前端要靠这个字段做状态胶囊筛选与徽章标注。
|
|
647
|
+
*/
|
|
648
|
+
state?: 'OPEN' | 'CLOSED' | 'MERGED';
|
|
331
649
|
repository: {
|
|
332
650
|
nameWithOwner: string;
|
|
333
651
|
};
|
|
334
652
|
url: string;
|
|
335
653
|
updatedAt: string;
|
|
654
|
+
isDraft?: boolean;
|
|
336
655
|
}>;
|
|
337
656
|
myIssues: GlobalIssueItem[];
|
|
338
657
|
issueStats?: IssueStats;
|
|
658
|
+
/**
|
|
659
|
+
* PR 检索是否触及上限(仅触顶时下发)。
|
|
660
|
+
* 为什么必须透出:去掉 open 过滤后按 updatedAt 降序返回最近 N 条,
|
|
661
|
+
* 若账号历史 PR 超过上限,界面会静默少显示,用户无法区分
|
|
662
|
+
* 「列表到此为止」与「数据没取到」。
|
|
663
|
+
*/
|
|
664
|
+
prsTruncated?: boolean;
|
|
339
665
|
lastUpdated: string;
|
|
340
666
|
error?: string;
|
|
341
667
|
/** 网络是否发生异常(超时、连接拒绝、代理阻断等) */
|
|
@@ -344,6 +670,11 @@ export interface GlobalOverviewData {
|
|
|
344
670
|
networkErrorReason?: string;
|
|
345
671
|
/** 工作区矩阵读取失败的原因。区分「没有工作区」与「读不到工作区」,避免把故障显示成空状态 */
|
|
346
672
|
workspaceError?: string;
|
|
673
|
+
/**
|
|
674
|
+
* 确定性降级说明(非错误):仓库关闭 Issues、未启用 Discussions 等配置事实。
|
|
675
|
+
* 与 networkError 互斥——它不是故障,不该触发告警横幅与重试。
|
|
676
|
+
*/
|
|
677
|
+
notices?: string[];
|
|
347
678
|
/** 插件版本与升级信息(由内存缓存快速读取,不阻塞首屏业务) */
|
|
348
679
|
updateInfo?: UpdateInfo;
|
|
349
680
|
}
|
package/lib/ui/help-modal.d.ts
CHANGED
|
@@ -7,6 +7,12 @@
|
|
|
7
7
|
* 3. 拒绝技术自嗨清单,从用户行动视角组织:3分钟快速上手、Agent实战Prompt、双界面图解与常见排错;
|
|
8
8
|
* 4. 宽屏卡片排列,配备 Prompt 一键复制到剪贴板与短暂反馈气泡;
|
|
9
9
|
* 5. 监听键盘 Esc 键与遮罩点击秒关,复制完指令直接回到聊天输入框发送,零打扰、不中断工作流。
|
|
10
|
+
*
|
|
11
|
+
* 【内容与代码同步的纪律】
|
|
12
|
+
* 本文件里出现的工具数量、action 数量、Tab 名称、按钮文案,全部以当前代码为准:
|
|
13
|
+
* 工具矩阵 = src/main.ts 的 18 处 ctx.tools.register;
|
|
14
|
+
* Tab 布局 = src/client.ts 的 TAB_DEFS 与 src/ui/workspace-panel.ts 的四个标签;
|
|
15
|
+
* 若后续增删工具或 Tab,必须同步改这里,否则用户会照着过时说明去找不存在的入口。
|
|
10
16
|
*/
|
|
11
17
|
export declare function GithubHelpModal(props: {
|
|
12
18
|
isOpen: boolean;
|