dsh-github-flow 0.3.0 → 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.
Files changed (121) hide show
  1. package/README.en.md +287 -143
  2. package/README.md +270 -125
  3. package/docs/UPGRADE-NOTES.md +12 -9
  4. package/docs/architecture.md +126 -126
  5. package/lib/api/routes-actions.js +249 -0
  6. package/lib/api/routes-overview.js +94 -2
  7. package/lib/cache.d.ts +4 -0
  8. package/lib/cache.js +14 -0
  9. package/lib/client.d.ts +14 -1
  10. package/lib/client.js +4287 -2500
  11. package/lib/commands/gh.d.ts +6 -1
  12. package/lib/commands/gh.js +144 -71
  13. package/lib/executor/git-parser.d.ts +57 -0
  14. package/lib/executor/git-parser.js +255 -0
  15. package/lib/executor/platform-guide.d.ts +14 -0
  16. package/lib/executor/platform-guide.js +40 -0
  17. package/lib/executor/process-utils.d.ts +51 -0
  18. package/lib/executor/process-utils.js +162 -0
  19. package/lib/executor/version-utils.d.ts +12 -0
  20. package/lib/executor/version-utils.js +27 -0
  21. package/lib/executor.d.ts +70 -48
  22. package/lib/executor.js +371 -356
  23. package/lib/git-watcher.d.ts +36 -0
  24. package/lib/git-watcher.js +91 -0
  25. package/lib/main.js +37 -3
  26. package/lib/renderers/agent-task.d.ts +16 -0
  27. package/lib/renderers/agent-task.js +107 -0
  28. package/lib/renderers/cache.d.ts +8 -0
  29. package/lib/renderers/cache.js +66 -0
  30. package/lib/renderers/codespace.d.ts +16 -0
  31. package/lib/renderers/codespace.js +103 -0
  32. package/lib/renderers/common.d.ts +24 -0
  33. package/lib/renderers/common.js +88 -0
  34. package/lib/renderers/discussion.d.ts +16 -0
  35. package/lib/renderers/discussion.js +101 -0
  36. package/lib/renderers/gist.d.ts +15 -0
  37. package/lib/renderers/gist.js +99 -0
  38. package/lib/renderers/issue.d.ts +4 -0
  39. package/lib/renderers/issue.js +70 -0
  40. package/lib/renderers/label.d.ts +4 -0
  41. package/lib/renderers/label.js +48 -0
  42. package/lib/renderers/markdown.d.ts +19 -32
  43. package/lib/renderers/markdown.js +19 -624
  44. package/lib/renderers/pr.d.ts +4 -0
  45. package/lib/renderers/pr.js +107 -0
  46. package/lib/renderers/project.d.ts +20 -0
  47. package/lib/renderers/project.js +128 -0
  48. package/lib/renderers/release.d.ts +4 -0
  49. package/lib/renderers/release.js +74 -0
  50. package/lib/renderers/repo.d.ts +4 -0
  51. package/lib/renderers/repo.js +149 -0
  52. package/lib/renderers/ruleset.d.ts +4 -0
  53. package/lib/renderers/ruleset.js +74 -0
  54. package/lib/renderers/run.d.ts +4 -0
  55. package/lib/renderers/run.js +79 -0
  56. package/lib/renderers/skill.d.ts +34 -0
  57. package/lib/renderers/skill.js +241 -0
  58. package/lib/renderers/status.d.ts +28 -0
  59. package/lib/renderers/status.js +176 -0
  60. package/lib/telemetry.d.ts +70 -0
  61. package/lib/telemetry.js +161 -0
  62. package/lib/tools/agent-task.d.ts +54 -0
  63. package/lib/tools/agent-task.js +135 -0
  64. package/lib/tools/cache.d.ts +64 -0
  65. package/lib/tools/cache.js +186 -0
  66. package/lib/tools/codespace.d.ts +51 -0
  67. package/lib/tools/codespace.js +154 -0
  68. package/lib/tools/discussion.d.ts +70 -0
  69. package/lib/tools/discussion.js +195 -0
  70. package/lib/tools/gist.d.ts +155 -0
  71. package/lib/tools/gist.js +190 -0
  72. package/lib/tools/help.js +214 -13
  73. package/lib/tools/image-utils.d.ts +8 -0
  74. package/lib/tools/image-utils.js +34 -0
  75. package/lib/tools/issue.d.ts +8 -1
  76. package/lib/tools/issue.js +26 -4
  77. package/lib/tools/label.d.ts +80 -0
  78. package/lib/tools/label.js +237 -0
  79. package/lib/tools/pr.d.ts +8 -0
  80. package/lib/tools/pr.js +48 -3
  81. package/lib/tools/project.d.ts +80 -0
  82. package/lib/tools/project.js +241 -0
  83. package/lib/tools/repo.js +13 -1
  84. package/lib/tools/ruleset.d.ts +80 -0
  85. package/lib/tools/ruleset.js +177 -0
  86. package/lib/tools/skill.d.ts +24 -1
  87. package/lib/tools/skill.js +115 -5
  88. package/lib/tools/status.d.ts +40 -0
  89. package/lib/tools/status.js +58 -0
  90. package/lib/types.d.ts +44 -0
  91. package/lib/ui/auth-guide-card.d.ts +4 -0
  92. package/lib/ui/auth-guide-card.js +161 -0
  93. package/lib/ui/branch-selector.d.ts +10 -0
  94. package/lib/ui/branch-selector.js +163 -0
  95. package/lib/ui/commit-modal.d.ts +8 -0
  96. package/lib/ui/commit-modal.js +219 -0
  97. package/lib/ui/help-modal.d.ts +15 -0
  98. package/lib/ui/help-modal.js +202 -0
  99. package/lib/ui/icons.d.ts +7 -0
  100. package/lib/ui/icons.js +53 -0
  101. package/lib/ui/network-banner.d.ts +10 -0
  102. package/lib/ui/network-banner.js +54 -0
  103. package/lib/ui/storage.d.ts +35 -0
  104. package/lib/ui/storage.js +158 -0
  105. package/lib/ui/styles.d.ts +6 -0
  106. package/lib/ui/styles.js +1544 -0
  107. package/lib/ui/sync-settings-modal.d.ts +11 -0
  108. package/lib/ui/sync-settings-modal.js +350 -0
  109. package/lib/ui/sync-status-badge.d.ts +8 -0
  110. package/lib/ui/sync-status-badge.js +64 -0
  111. package/lib/ui/upgrade-card.d.ts +7 -0
  112. package/lib/ui/upgrade-card.js +222 -0
  113. package/lib/ui/utils.d.ts +45 -0
  114. package/lib/ui/utils.js +226 -0
  115. package/lib/ui/workspace-panel.d.ts +4 -0
  116. package/lib/ui/workspace-panel.js +489 -0
  117. package/lib/upgrade-manager.d.ts +5 -1
  118. package/lib/upgrade-manager.js +24 -1
  119. package/lib/version.d.ts +1 -1
  120. package/lib/version.js +1 -1
  121. package/package.json +2 -2
@@ -1,4 +1,6 @@
1
- import { renderSkillMarkdown } from '../renderers/markdown.js';
1
+ import path from 'node:path';
2
+ import fs from 'node:fs';
3
+ import { renderSkillMarkdown, parseSkillPublishOutput } from '../renderers/markdown.js';
2
4
  function normalizeOutput(data) {
3
5
  if (data && typeof data === 'object' && !Array.isArray(data)) {
4
6
  return data;
@@ -11,14 +13,14 @@ function normalizeOutput(data) {
11
13
  export function createSkillTool(executor) {
12
14
  return {
13
15
  name: 'github_skill',
14
- description: '通过 GitHub CLI 官方生态发现与管理 Agent Skills:跨仓库检索开源 Skills、预览 SKILL.md 内容、安装到本地 Agent 宿主(Claude Code / Cursor / Copilot 等)、查看已安装列表。install 会写入本地磁盘,需 confirm: true。基于 gh CLI preview 特性(需 gh >= 2.9x)。',
16
+ description: '通过 GitHub CLI 官方生态发现与管理 Agent Skills:跨仓库检索开源 Skills、预览 SKILL.md 内容、安装到本地 Agent 宿主(Claude Code / Cursor / Copilot 等)、查看已安装列表、合规自检与安全发布(publish)以及检查与同步更新(update)。install 会写入磁盘需 confirm;publish 默认 --dry-run 自检,正式发布需 tag 与 confirm;update 默认 --dry-run 检查。基于 gh CLI preview 特性(需 gh >= 2.9x)。',
15
17
  parameters: {
16
18
  type: 'object',
17
19
  properties: {
18
20
  action: {
19
21
  type: 'string',
20
- enum: ['search', 'preview', 'install', 'list'],
21
- description: 'Skill 操作类型。',
22
+ enum: ['search', 'preview', 'install', 'list', 'publish', 'update'],
23
+ description: 'Skill 操作类型。search 检索、preview 预览、install 安装、list 查看已安装、publish 校验/发布、update 检查与同步更新。',
22
24
  },
23
25
  query: {
24
26
  type: 'string',
@@ -53,9 +55,30 @@ export function createSkillTool(executor) {
53
55
  type: 'number',
54
56
  description: '搜索返回数量上限(search 动作使用,默认 15)。',
55
57
  },
58
+ directory: {
59
+ type: 'string',
60
+ description: '待检查或发布的技能目录(publish 动作使用,缺省为当前工作区根目录)。',
61
+ },
62
+ dry_run: {
63
+ type: 'boolean',
64
+ description: '是否仅进行合规性验证而不发布(publish 动作使用,默认 true,零副作用安全验证模式)。',
65
+ },
66
+ fix: {
67
+ type: 'boolean',
68
+ description: '是否自动修复问题(如剥离残留的安装元数据,publish 动作使用,默认 false)。',
69
+ },
70
+ tag: {
71
+ type: 'string',
72
+ description: '发布的版本 Tag(如 "v1.0.0"),正式发布(dry_run: false)时必填(防交互式挂起)。',
73
+ },
74
+ skill_names: {
75
+ type: 'array',
76
+ items: { type: 'string' },
77
+ description: '要更新的特定 Skill 名称列表(update 动作可选)。',
78
+ },
56
79
  confirm: {
57
80
  type: 'boolean',
58
- description: '安装操作确认标志。install 会向本地磁盘写入文件,未传 true 时仅输出将要执行的安装预览。',
81
+ description: '高危操作确认标志。install 写入本地磁盘、publish 正式创建 Release 时必需。未传 true 时输出影响评估并拦截。',
59
82
  },
60
83
  },
61
84
  required: ['action'],
@@ -138,6 +161,93 @@ export function createSkillTool(executor) {
138
161
  throw new Error(res.error);
139
162
  return normalizeOutput(res.data || res.rawOutput);
140
163
  }
164
+ case 'publish': {
165
+ const isFix = args.fix === true;
166
+ const isDryRun = args.dry_run !== false && !isFix;
167
+ const targetDir = typeof args.directory === 'string' && args.directory.trim() ? args.directory.trim() : undefined;
168
+ // 1. 目录存在性前置安全校验
169
+ if (targetDir) {
170
+ const resolvedPath = path.resolve(cwd, targetDir);
171
+ if (!fs.existsSync(resolvedPath)) {
172
+ throw new Error(`指定的技能目录不存在: ${targetDir}`);
173
+ }
174
+ }
175
+ // 2. 正式发布分支(dry_run 为 false 且非 fix 模式)
176
+ if (!isDryRun && !isFix) {
177
+ // 防线 1: 必须显式指定版本 tag,防止 CLI 弹出交互式向导导致子进程永久挂起
178
+ if (!args.tag || typeof args.tag !== 'string' || !args.tag.trim()) {
179
+ throw new Error('正式发布 Skill(dry_run: false)必须提供版本 tag(如 "v1.0.0"),以防止 CLI 尝试进入交互式向导导致进程挂起');
180
+ }
181
+ const cleanTag = args.tag.trim();
182
+ // 防线 2: 破坏性发布二级确认拦截(创建 Release 与打 Tag 属于公开制品发布)
183
+ if (args.confirm !== true) {
184
+ return {
185
+ status: 'AWAITING_CONFIRMATION',
186
+ warning: `⚠️ 发布确认拦截:你即将正式发布 Agent Skill 并创建 GitHub Release(Tag: ${cleanTag})。`,
187
+ impact: `该操作将在仓库中打上「agent-skills」Topic、创建 Git Tag「${cleanTag}」并发布正式 GitHub Release,向所有用户公开提供该版本。`,
188
+ requiredAction: `如确认发布,请核实版本号并在参数中附加 \`confirm: true\` 重新调用。`,
189
+ };
190
+ }
191
+ const publishCmd = ['skill', 'publish'];
192
+ if (targetDir)
193
+ publishCmd.push(targetDir);
194
+ publishCmd.push('--tag', cleanTag);
195
+ const res = await executor.run(publishCmd, { ...runOpts, rawText: true, timeoutMs: 120_000 });
196
+ if (!res.ok) {
197
+ if (res.rawOutput) {
198
+ return parseSkillPublishOutput(res.rawOutput, res.error || '', false, 'publish', targetDir, cleanTag);
199
+ }
200
+ throw new Error(res.error || '发布 Skill 失败');
201
+ }
202
+ return parseSkillPublishOutput(res.rawOutput || '', '', true, 'publish', targetDir, cleanTag);
203
+ }
204
+ // 3. 自动剥离安装元数据分支 (--fix)
205
+ if (isFix) {
206
+ const fixCmd = ['skill', 'publish'];
207
+ if (targetDir)
208
+ fixCmd.push(targetDir);
209
+ fixCmd.push('--fix');
210
+ const res = await executor.run(fixCmd, { ...runOpts, rawText: true, timeoutMs: 60_000 });
211
+ const output = res.rawOutput || (res.ok ? '' : res.error || '');
212
+ return parseSkillPublishOutput(output, res.error || '', res.ok, 'fix', targetDir);
213
+ }
214
+ // 4. 默认只读自检分支 (--dry-run)
215
+ const dryRunCmd = ['skill', 'publish'];
216
+ if (targetDir)
217
+ dryRunCmd.push(targetDir);
218
+ dryRunCmd.push('--dry-run');
219
+ const res = await executor.run(dryRunCmd, { ...runOpts, rawText: true, timeoutMs: 60_000 });
220
+ const combinedOutput = res.rawOutput || '';
221
+ const stderrText = res.error || '';
222
+ return parseSkillPublishOutput(combinedOutput, stderrText, res.ok, 'dry-run', targetDir);
223
+ }
224
+ case 'update': {
225
+ const isDryRun = args.dry_run !== false;
226
+ const updateCmd = ['skill', 'update'];
227
+ if (isDryRun)
228
+ updateCmd.push('--dry-run');
229
+ if (args.all === true)
230
+ updateCmd.push('--all');
231
+ if (Array.isArray(args.skill_names) && args.skill_names.length > 0) {
232
+ args.skill_names.forEach((name) => {
233
+ if (name && typeof name === 'string' && name.trim()) {
234
+ updateCmd.push(name.trim());
235
+ }
236
+ });
237
+ }
238
+ else if (args.skill_name && typeof args.skill_name === 'string') {
239
+ updateCmd.push(args.skill_name.trim());
240
+ }
241
+ const res = await executor.run(updateCmd, { ...runOpts, rawText: true, timeoutMs: 90_000 });
242
+ if (!res.ok)
243
+ throw new Error(res.error);
244
+ return {
245
+ mode: isDryRun ? 'dry-run' : 'update',
246
+ action: 'update',
247
+ message: isDryRun ? 'Agent Skills 更新检查完成(Dry-run 只读模式)' : 'Agent Skills 已完成更新同步',
248
+ output: res.rawOutput || 'All skills up to date.',
249
+ };
250
+ }
141
251
  default:
142
252
  throw new Error(`未知的 Skill 操作: ${args.action}`);
143
253
  }
@@ -0,0 +1,40 @@
1
+ import type { GhExecutor } from '../executor.js';
2
+ import { TelemetryCollector } from '../telemetry.js';
3
+ export declare function createStatusTool(executor: GhExecutor, telemetryCollector?: TelemetryCollector): {
4
+ name: string;
5
+ description: string;
6
+ parameters: {
7
+ type: string;
8
+ properties: {
9
+ action: {
10
+ type: string;
11
+ enum: string[];
12
+ description: string;
13
+ };
14
+ org: {
15
+ type: string;
16
+ description: string;
17
+ };
18
+ exclude: {
19
+ type: string;
20
+ items: {
21
+ type: string;
22
+ };
23
+ description: string;
24
+ };
25
+ };
26
+ };
27
+ output: {
28
+ schema: {
29
+ type: string;
30
+ };
31
+ render(args: any, value: any): {
32
+ type: string;
33
+ text: string;
34
+ }[];
35
+ };
36
+ execute(args: any, execContext: any): Promise<import("../telemetry.js").TelemetrySummary | {
37
+ parsed: import("../renderers/status.js").ParsedStatusReport;
38
+ rawText: string;
39
+ }>;
40
+ };
@@ -0,0 +1,58 @@
1
+ import { renderStatusMarkdown, parseStatusOutput } from '../renderers/markdown.js';
2
+ import { defaultTelemetryCollector } from '../telemetry.js';
3
+ export function createStatusTool(executor, telemetryCollector) {
4
+ return {
5
+ name: 'github_status',
6
+ description: '聚合展示当前登录用户的跨仓库全局待办与动态大盘(view),或审计当前工具链运行时健康度、API 降级率与自愈建议(health)。无需指定单仓,账号与系统维度一站式概览。',
7
+ parameters: {
8
+ type: 'object',
9
+ properties: {
10
+ action: {
11
+ type: 'string',
12
+ enum: ['view', 'health'],
13
+ description: '操作类型。view 查看个人全局待办与动态看板(默认)、health 查看工具链健康度与 API 降级率审计报表。',
14
+ },
15
+ org: {
16
+ type: 'string',
17
+ description: '组织名称(可选,限定仅汇报指定组织内部的待办与动态)。',
18
+ },
19
+ exclude: {
20
+ type: 'array',
21
+ items: { type: 'string' },
22
+ description: '要排除的仓库名称列表 [owner/repo](可选,支持排除噪音仓库)。',
23
+ },
24
+ },
25
+ },
26
+ output: {
27
+ schema: { type: 'object' },
28
+ render(args, value) {
29
+ return [{ type: 'text', text: renderStatusMarkdown(args, value) }];
30
+ },
31
+ },
32
+ async execute(args, execContext) {
33
+ if (args?.action === 'health') {
34
+ const collector = telemetryCollector || defaultTelemetryCollector;
35
+ return collector.getSummary();
36
+ }
37
+ const cwd = execContext?.cwd || process.cwd();
38
+ const sessionId = execContext?.sessionId || execContext?.session?.id || process.env.DSH_SESSION_ID;
39
+ const statusCmd = ['status'];
40
+ if (args?.org) {
41
+ statusCmd.push('-o', String(args.org));
42
+ }
43
+ if (args?.exclude && Array.isArray(args.exclude)) {
44
+ for (const ex of args.exclude) {
45
+ statusCmd.push('-e', String(ex));
46
+ }
47
+ }
48
+ const res = await executor.run(statusCmd, { cwd, sessionId, rawText: true });
49
+ if (!res.ok)
50
+ throw new Error(res.error);
51
+ const parsed = parseStatusOutput(res.rawOutput || '');
52
+ return {
53
+ parsed,
54
+ rawText: res.rawOutput || '',
55
+ };
56
+ },
57
+ };
58
+ }
package/lib/types.d.ts CHANGED
@@ -37,6 +37,15 @@ export interface PluginConfig {
37
37
  */
38
38
  proxyUrl?: string;
39
39
  }
40
+ /** 数据同步与自动化感知偏好配置 */
41
+ export interface SyncSettings {
42
+ /** 刷新策略三选一:'swr' 秒开并在首屏拉新 | 'auto' SWR秒开+云端定时轮询 | 'manual' 仅手动点击拉取 */
43
+ strategy: 'swr' | 'auto' | 'manual';
44
+ /** 云端定时同步周期(毫秒,不少于 300,000 即 5 分钟,默认 600,000 即 10 分钟) */
45
+ cloudSyncIntervalMs: number;
46
+ /** 是否开启本地 .git 监控(感知代码修改、暂存与分支切换,仅右侧栏当前工作区生效,默认开启,用户可取消勾选) */
47
+ localGitWatch: boolean;
48
+ }
40
49
  export interface GhExecutionOptions {
41
50
  /** 命令执行的工作目录,优先使用当前 Agent 会话所在的 Workspace 物理路径 */
42
51
  cwd?: string;
@@ -91,6 +100,12 @@ export interface AuthStatus {
91
100
  scopes?: string[];
92
101
  installGuide?: AuthInstallGuide;
93
102
  raw?: string;
103
+ /** 网络是否发生异常(超时、DNS解析失败、连接被拒、代理阻断等) */
104
+ networkError?: boolean;
105
+ /** 网络异常的人类可读原因或排查建议 */
106
+ networkErrorReason?: string;
107
+ /** 本地是否已检测到持久化凭据(如 hosts.yml 或 Keyring) */
108
+ hasLocalToken?: boolean;
94
109
  }
95
110
  export interface RepoMetadata {
96
111
  nameWithOwner: string;
@@ -101,6 +116,22 @@ export interface RepoMetadata {
101
116
  description?: string;
102
117
  isPrivate?: boolean;
103
118
  url?: string;
119
+ stargazerCount?: number;
120
+ forkCount?: number;
121
+ }
122
+ /** Git 分支详情项(供分支切换器下拉列表消费) */
123
+ export interface GitBranchItem {
124
+ name: string;
125
+ isCurrent: boolean;
126
+ isRemote: boolean;
127
+ upstream?: string;
128
+ shortSha: string;
129
+ subject: string;
130
+ relativeTime: string;
131
+ }
132
+ export interface GitBranchesResult {
133
+ current: string;
134
+ branches: GitBranchItem[];
104
135
  }
105
136
  /**
106
137
  * 本地 Git 工作区状态快照(ahead/behind 是 remote-tracking ref 的「上次 fetch」视图,
@@ -220,6 +251,10 @@ export interface GitHubOverviewData {
220
251
  runs: WorkflowRunItem[];
221
252
  lastUpdated: string;
222
253
  error?: string;
254
+ /** 网络是否发生异常(超时、连接拒绝、代理阻断等) */
255
+ networkError?: boolean;
256
+ /** 网络异常的原因或提示 */
257
+ networkErrorReason?: string;
223
258
  /** 插件版本与升级信息(由内存缓存快速读取,不阻塞首屏业务) */
224
259
  updateInfo?: UpdateInfo;
225
260
  /** 本地 Git 状态(ahead/behind/dirty,remote-tracking 快照语义);非 Git 工作区为 undefined */
@@ -241,6 +276,8 @@ export interface GitHubOverviewData {
241
276
  url?: string;
242
277
  isDraft?: boolean;
243
278
  } | null;
279
+ /** 当前工作区的 Git 分支列表(供右侧栏分支选择器 0ms 秒开) */
280
+ branches?: GitBranchesResult | null;
244
281
  }
245
282
  export interface UserRepoItem {
246
283
  name: string;
@@ -301,6 +338,10 @@ export interface GlobalOverviewData {
301
338
  issueStats?: IssueStats;
302
339
  lastUpdated: string;
303
340
  error?: string;
341
+ /** 网络是否发生异常(超时、连接拒绝、代理阻断等) */
342
+ networkError?: boolean;
343
+ /** 网络异常的原因或提示 */
344
+ networkErrorReason?: string;
304
345
  /** 工作区矩阵读取失败的原因。区分「没有工作区」与「读不到工作区」,避免把故障显示成空状态 */
305
346
  workspaceError?: string;
306
347
  /** 插件版本与升级信息(由内存缓存快速读取,不阻塞首屏业务) */
@@ -324,11 +365,13 @@ export interface UpdateInfo {
324
365
  checkedAt: number;
325
366
  }
326
367
  export type UpgradeState = 'idle' | 'upgrading' | 'success' | 'failed';
368
+ export type UpgradeErrorType = 'MINIMUM_RELEASE_AGE_VIOLATION' | 'TIMEOUT' | 'UNKNOWN';
327
369
  export interface UpgradeStatusResult {
328
370
  state: UpgradeState;
329
371
  targetVersion?: string;
330
372
  message?: string;
331
373
  log?: string;
374
+ errorType?: UpgradeErrorType;
332
375
  startedAt?: number;
333
376
  completedAt?: number;
334
377
  /** 识别到的宿主环境类型:desktop 为桌面版,web 为网页/CLI版 */
@@ -338,6 +381,7 @@ export interface UpgradeExecutionResult {
338
381
  ok: boolean;
339
382
  message: string;
340
383
  needRestart: boolean;
384
+ errorType?: UpgradeErrorType;
341
385
  log?: string;
342
386
  environment?: 'desktop' | 'web';
343
387
  }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * 认证与安装引导卡片组件(响应式自适应中央大面板与右侧栏)
3
+ */
4
+ export declare function AuthGuideCard(props: any): any;
@@ -0,0 +1,161 @@
1
+ /**
2
+ * 认证与安装引导卡片组件(响应式自适应中央大面板与右侧栏)
3
+ */
4
+ export function AuthGuideCard(props) {
5
+ var auth = props ? props.auth : null;
6
+ var onRefresh = props ? props.onRefresh : () => { };
7
+ var isRightbar = Boolean(props && props.isRightbar);
8
+ var [copied, setCopied] = React.useState(false);
9
+ var [launching, setLaunching] = React.useState(false);
10
+ var [toastMsg, setToastMsg] = React.useState(null);
11
+ var isNetwork = Boolean(auth?.networkError);
12
+ var notInstalled = !isNetwork && Boolean(auth && auth.installed === false);
13
+ var notLoggedIn = !isNetwork && !notInstalled && Boolean(!auth?.loggedIn);
14
+ var guide = auth?.installGuide;
15
+ var defaultCmd = isNetwork
16
+ ? "gh auth status"
17
+ : notInstalled
18
+ ? (guide?.command || "winget install --id GitHub.cli")
19
+ : "gh auth login";
20
+ var copyCmd = (cmd) => {
21
+ try {
22
+ if (navigator && navigator.clipboard && navigator.clipboard.writeText) {
23
+ navigator.clipboard.writeText(cmd);
24
+ }
25
+ else {
26
+ var input = document.createElement("textarea");
27
+ input.value = cmd;
28
+ document.body.appendChild(input);
29
+ input.select();
30
+ document.execCommand("copy");
31
+ document.body.removeChild(input);
32
+ }
33
+ setCopied(true);
34
+ setTimeout(() => setCopied(false), 2000);
35
+ }
36
+ catch (e) {
37
+ console.warn("复制失败:", e);
38
+ }
39
+ };
40
+ var launchTerminal = async (cmd) => {
41
+ setLaunching(true);
42
+ setToastMsg(null);
43
+ try {
44
+ var res = await fetch("/api/github/action", {
45
+ method: "POST",
46
+ headers: { "Content-Type": "application/json" },
47
+ body: JSON.stringify({ action: "open_terminal", command: cmd })
48
+ });
49
+ var json = await res.json();
50
+ if (json.ok) {
51
+ setToastMsg("已唤起系统终端,请在弹出窗口中完成操作;若未弹出,可手动打开终端执行上方命令");
52
+ setTimeout(() => setToastMsg(null), 6000);
53
+ }
54
+ else {
55
+ setToastMsg("❌ " + (json.message || "唤起失败,请手动打开终端执行上方命令"));
56
+ }
57
+ }
58
+ catch (e) {
59
+ setToastMsg("无法连接后台服务,请手动打开终端执行上方命令");
60
+ }
61
+ finally {
62
+ setLaunching(false);
63
+ }
64
+ };
65
+ var openDownload = async () => {
66
+ var url = guide?.downloadUrl || "https://cli.github.com/";
67
+ try {
68
+ await fetch("/api/github/action", {
69
+ method: "POST",
70
+ headers: { "Content-Type": "application/json" },
71
+ body: JSON.stringify({ action: "open_browser", url })
72
+ });
73
+ }
74
+ catch (e) {
75
+ window.open(url, "_blank", "noopener,noreferrer");
76
+ }
77
+ };
78
+ var openProxySettings = () => {
79
+ try {
80
+ window.dispatchEvent(new CustomEvent("dsh-github-open-proxy"));
81
+ }
82
+ catch (e) { }
83
+ };
84
+ var h = React.createElement;
85
+ return h("div", {
86
+ className: "dsh-github-guide-card " + (isNetwork ? "warning" : notInstalled ? "danger" : "warning"),
87
+ style: isRightbar ? { padding: "12px", marginBottom: "12px" } : undefined
88
+ }, h("div", { className: "dsh-github-guide-header" }, isNetwork
89
+ ? "🌐 无法连接 GitHub 服务器"
90
+ : notInstalled
91
+ ? "⚠️ 未检测到 GitHub CLI (gh)"
92
+ : "🔑 GitHub 账号尚未登录", h("span", { className: "dsh-github-badge " + (isNetwork ? "dsh-badge-yellow" : notInstalled ? "dsh-badge-red" : "dsh-badge-yellow") }, isNetwork ? "网络受限" : notInstalled ? "未安装" : "未认证")), h("div", { className: "dsh-github-guide-desc" }, isNetwork
93
+ ? (auth?.networkErrorReason || "检测到本机已安装 GitHub CLI,但当前无法连接至 api.github.com(网络超时、DNS 无法解析或被系统代理阻断)。")
94
+ : notInstalled
95
+ ? (guide?.description || "DSH GitHub Flow 插件依赖官方 GitHub CLI 工具与云端进行安全交互,当前系统 PATH 中未检测到该工具。")
96
+ : "检测到本机已安装 GitHub CLI,请完成账号授权以解锁仓库管理、PR 审查和 Issues 待办。"), h("div", { className: "dsh-github-cmd-box" }, h("code", null, defaultCmd), h("button", {
97
+ className: "dsh-github-copy-btn " + (copied ? "copied" : ""),
98
+ onClick: () => copyCmd(defaultCmd),
99
+ title: "复制命令到剪贴板"
100
+ }, copied ? "✓ 已复制" : "📋 复制命令")), !notInstalled && !isRightbar
101
+ ? (isNetwork
102
+ ? h("ol", { className: "dsh-github-steps-list" }, h("li", null, "检查系统本地网络连接或 DNS 解析,确认能正常访问 github.com;"), h("li", null, "若使用了网络代理工具,可在下方点击「配置网络代理」填写 HTTP 或 SOCKS5 代理;"), h("li", null, "配置或恢复网络后,切回本面板或点击「重试连接」即可自动同步数据。"))
103
+ : h("ol", { className: "dsh-github-steps-list" }, h("li", null, "打开系统终端(PowerShell / CMD / Terminal),运行上述命令;"), h("li", null, "按提示依次选择「GitHub.com」➜「HTTPS」➜「Login with a web browser」;"), h("li", null, "按回车打开浏览器确认授权后,切回本页面即可自动恢复。")))
104
+ : null, h("div", { className: "dsh-github-guide-actions" }, isNetwork
105
+ ? h("button", {
106
+ className: "dsh-github-action-btn",
107
+ onClick: onRefresh,
108
+ title: "重新发起网络连接校验"
109
+ }, "🔄 重试网络连接")
110
+ : null, isNetwork
111
+ ? h("button", {
112
+ className: "dsh-github-action-btn",
113
+ onClick: openProxySettings,
114
+ title: "打开网络代理设置,配置 HTTP/SOCKS5 代理服务器"
115
+ }, "⚙️ 配置网络代理")
116
+ : null, h("button", {
117
+ className: "dsh-github-action-btn",
118
+ onClick: () => launchTerminal(defaultCmd),
119
+ disabled: launching,
120
+ title: "自动唤起系统终端并执行该命令"
121
+ }, launching ? "正在唤起..." : (isNetwork ? "💻 终端排查状态" : notInstalled ? "💻 唤起终端安装" : "💻 唤起终端登录")), notInstalled
122
+ ? h("button", {
123
+ className: "dsh-github-action-btn",
124
+ onClick: openDownload,
125
+ title: "打开 GitHub CLI 官方下载主页获取安装包"
126
+ }, "🌐 官网安装包 (.msi/.pkg)")
127
+ : null, !isNetwork
128
+ ? h("button", {
129
+ className: "dsh-github-action-btn",
130
+ onClick: function () {
131
+ setToastMsg("正在快速检测登录状态...");
132
+ var probeController = new AbortController();
133
+ var probeTimer = setTimeout(function () { probeController.abort(); }, 10000);
134
+ fetch("/api/github/auth?force=true", { signal: probeController.signal })
135
+ .then(function (res) { return res.json(); })
136
+ .then(function (json) {
137
+ clearTimeout(probeTimer);
138
+ if (json && json.ok && json.auth && json.auth.loggedIn) {
139
+ setToastMsg("✅ 已识别到 GitHub CLI 登录态,正在拉取数据...");
140
+ clearStoredGlobalOverview();
141
+ onRefresh();
142
+ }
143
+ else {
144
+ setToastMsg("⚠️ 暂未检测到登录凭据,请在终端执行 gh auth login 完成授权");
145
+ onRefresh();
146
+ }
147
+ })
148
+ .catch(function () {
149
+ clearTimeout(probeTimer);
150
+ setToastMsg("❌ 检测超时或后端不可达,请稍后重试");
151
+ onRefresh();
152
+ });
153
+ },
154
+ title: "重新检测登录与安装状态"
155
+ }, "🔄 刷新状态")
156
+ : null), toastMsg
157
+ ? h("div", { style: { fontSize: "12px", color: "var(--dsw-alias-link, #0969da)", marginTop: "8px" } }, `ℹ️ ${toastMsg}`)
158
+ : null, h("div", { className: "dsh-github-guide-tip" }, notInstalled
159
+ ? "💡 提示:使用包管理器安装完成后,若未立即识别,可重启 DeepSeek Harness 应用刷新系统环境变量 PATH。"
160
+ : "💡 提示:凭证由官方 GitHub CLI 加密保存在操作系统安全凭据库中,授权完毕切回本窗口将自动识别刷新。"));
161
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * 分支查看与快速切换下拉选择器组件
3
+ */
4
+ export declare function BranchSelectorDropdown(props: {
5
+ currentBranch: string;
6
+ cwd: string | null;
7
+ branchesData?: any;
8
+ onBranchSwitched?: (branch: string) => void;
9
+ showToast?: (msg: string) => void;
10
+ }): any;