dsh-github-flow 0.4.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.
Files changed (82) hide show
  1. package/README.en.md +91 -12
  2. package/README.md +91 -12
  3. package/docs/UPGRADE-NOTES.md +9 -12
  4. package/docs/architecture.md +63 -29
  5. package/docs/images/1.png +0 -0
  6. package/lib/api/routes-actions.js +268 -5
  7. package/lib/api/routes-overview.js +147 -29
  8. package/lib/cache.d.ts +77 -4
  9. package/lib/cache.js +114 -7
  10. package/lib/client.d.ts +9 -4
  11. package/lib/client.js +5293 -942
  12. package/lib/commands/gh.d.ts +6 -1
  13. package/lib/commands/gh.js +144 -71
  14. package/lib/executor/error-classifier.d.ts +55 -0
  15. package/lib/executor/error-classifier.js +199 -0
  16. package/lib/executor/git-parser.d.ts +157 -1
  17. package/lib/executor/git-parser.js +513 -4
  18. package/lib/executor.d.ts +147 -4
  19. package/lib/executor.js +866 -77
  20. package/lib/main.js +28 -4
  21. package/lib/renderers/agent-task.d.ts +16 -0
  22. package/lib/renderers/agent-task.js +107 -0
  23. package/lib/renderers/codespace.d.ts +16 -0
  24. package/lib/renderers/codespace.js +103 -0
  25. package/lib/renderers/discussion.d.ts +16 -0
  26. package/lib/renderers/discussion.js +101 -0
  27. package/lib/renderers/markdown.d.ts +4 -0
  28. package/lib/renderers/markdown.js +4 -0
  29. package/lib/renderers/project.d.ts +20 -0
  30. package/lib/renderers/project.js +128 -0
  31. package/lib/renderers/skill.d.ts +30 -0
  32. package/lib/renderers/skill.js +180 -0
  33. package/lib/renderers/status.d.ts +5 -0
  34. package/lib/renderers/status.js +52 -0
  35. package/lib/telemetry.d.ts +70 -0
  36. package/lib/telemetry.js +161 -0
  37. package/lib/tools/agent-task.d.ts +54 -0
  38. package/lib/tools/agent-task.js +135 -0
  39. package/lib/tools/codespace.d.ts +51 -0
  40. package/lib/tools/codespace.js +154 -0
  41. package/lib/tools/discussion.d.ts +70 -0
  42. package/lib/tools/discussion.js +195 -0
  43. package/lib/tools/help.js +129 -14
  44. package/lib/tools/image-utils.d.ts +27 -0
  45. package/lib/tools/image-utils.js +73 -3
  46. package/lib/tools/project.d.ts +80 -0
  47. package/lib/tools/project.js +241 -0
  48. package/lib/tools/repo.js +13 -1
  49. package/lib/tools/skill.d.ts +24 -1
  50. package/lib/tools/skill.js +115 -5
  51. package/lib/tools/status.d.ts +3 -2
  52. package/lib/tools/status.js +9 -4
  53. package/lib/types.d.ts +336 -0
  54. package/lib/ui/commit-modal.js +144 -14
  55. package/lib/ui/help-modal.d.ts +21 -0
  56. package/lib/ui/help-modal.js +300 -0
  57. package/lib/ui/issue-modal.d.ts +14 -0
  58. package/lib/ui/issue-modal.js +366 -0
  59. package/lib/ui/markdown-lite.d.ts +66 -0
  60. package/lib/ui/markdown-lite.js +312 -0
  61. package/lib/ui/network-banner.d.ts +12 -0
  62. package/lib/ui/network-banner.js +35 -0
  63. package/lib/ui/pr-modal.d.ts +17 -0
  64. package/lib/ui/pr-modal.js +516 -0
  65. package/lib/ui/repo-badges.d.ts +43 -0
  66. package/lib/ui/repo-badges.js +82 -0
  67. package/lib/ui/repo-selector.d.ts +14 -0
  68. package/lib/ui/repo-selector.js +112 -0
  69. package/lib/ui/storage.d.ts +56 -0
  70. package/lib/ui/storage.js +163 -0
  71. package/lib/ui/styles.d.ts +1 -1
  72. package/lib/ui/styles.js +1219 -0
  73. package/lib/ui/sync-settings-modal.js +1 -1
  74. package/lib/ui/upgrade-card.js +39 -14
  75. package/lib/ui/utils.d.ts +35 -0
  76. package/lib/ui/utils.js +172 -0
  77. package/lib/ui/workspace-panel.js +198 -31
  78. package/lib/upgrade-manager.d.ts +5 -1
  79. package/lib/upgrade-manager.js +24 -1
  80. package/lib/version.d.ts +1 -1
  81. package/lib/version.js +1 -1
  82. package/package.json +2 -2
@@ -9,7 +9,7 @@ import type { GitLocalStatus, GitCommitEntry, GitBranchesResult } from '../types
9
9
  * `## master` / `## HEAD (no branch)` 无 upstream(ahead/behind 未知=-1)
10
10
  * 后续每行 `<XY> <path>` 为 porcelain 变更项(XY 两字符状态码,?? = untracked)。
11
11
  */
12
- export declare function parseGitStatusOutput(output: string): GitLocalStatus | null;
12
+ export declare function parseGitStatusOutput(output: string, maxFiles?: number): GitLocalStatus | null;
13
13
  /**
14
14
  * 解析 `git log` 输出为提交条目数组。
15
15
  * 支持两种形态:
@@ -23,3 +23,159 @@ export declare function parseGitLogLines(output: string): GitCommitEntry[];
23
23
  * 格式为: %(refname:short)|%(HEAD)|%(upstream:short)|%(committerdate:relative)|%(objectname:short)|%(subject)
24
24
  */
25
25
  export declare function parseGitBranchLines(output: string): GitBranchesResult;
26
+ /**
27
+ * 解析 unified diff 输出,统计增删行数与区块数量。
28
+ * 忽略 diff 文件头(--- 和 +++),仅统计真正的改动行(+ 与 -)。
29
+ */
30
+ export declare function parseUncommittedDiff(rawDiff: string): {
31
+ additions: number;
32
+ deletions: number;
33
+ hunksCount: number;
34
+ };
35
+ export interface GitStatFileInfo {
36
+ path: string;
37
+ total: number;
38
+ additions: number;
39
+ deletions: number;
40
+ isBinary: boolean;
41
+ rawRight?: string;
42
+ }
43
+ export interface GitStatSummary {
44
+ filesChanged: number;
45
+ insertions: number;
46
+ deletions: number;
47
+ }
48
+ export interface GitStatParsedResult {
49
+ files: GitStatFileInfo[];
50
+ summary: GitStatSummary | null;
51
+ }
52
+ /**
53
+ * 解析 `git show --stat` 或 `git log --stat` 的统计文本为结构化列表与增删数字。
54
+ * 能够从 `19 ++++++++++++++++++-` 精准推导 additions=18, deletions=1,
55
+ * 提取文件路径与 `X files changed, Y insertions(+), Z deletions(-)` 汇总。
56
+ */
57
+ export declare function parseGitStatText(statText: string): GitStatParsedResult | null;
58
+ /**
59
+ * 提取 `.git/config` 中所有 `[remote "..."]` 段内的 url。
60
+ *
61
+ * 为什么必须按段扫描而不是全文抓 `url = `:`[submodule "..."]` 段同样带 url
62
+ * (实测 `[submodule "lib"] url = https://github.com/x/y.git`)。全文正则会把
63
+ * 子模块的远程算进指纹,导致一次 `git submodule add` 就触发整个面板缓存的
64
+ * 无谓作废。子模块的 url 与本工作区关联哪个 GitHub 仓库毫无关系。
65
+ *
66
+ * 输出语义:保持文件中的出现顺序、已去重、不含空值。
67
+ * 排序交给调用方(指纹需要稳定顺序,但那是调用方的语义,纯函数不该替它决定)。
68
+ */
69
+ export declare function parseRemoteUrls(configText: string): string[];
70
+ /** 单个 remote 段的解析结果 */
71
+ export interface ParsedRemote {
72
+ name: string;
73
+ url: string;
74
+ }
75
+ /** `.git/config` + `HEAD` 的解析结果,是「这个工作区关联哪个仓库」的唯一事实源 */
76
+ export interface ParsedGitConfig {
77
+ /** 每个 remote 名对应的第一个 url(身份解析用;同名多 url 时取首个) */
78
+ remotes: ParsedRemote[];
79
+ /**
80
+ * 全部 remote url 行(指纹用)。
81
+ *
82
+ * 为什么与 remotes 分开:身份解析需要「remote 名 → url」的一对一映射,
83
+ * 而指纹需要「配置里出现过的所有 url」。同一个 remote 允许写多行 url
84
+ * (git 认首个,但配置确实是多行),若指纹也按名字去重,第二行 url 的
85
+ * 变化就检测不到——那会让「用户改了备用 url」这种情况静默漏检。
86
+ */
87
+ allUrls: string[];
88
+ /** 当前分支名(来自 HEAD 的 `ref: refs/heads/<name>`);detached HEAD 时为 null */
89
+ currentBranch: string | null;
90
+ /** `branch.<currentBranch>.remote` 的值;无配置或无当前分支时为 null */
91
+ branchRemote: string | null;
92
+ }
93
+ /**
94
+ * 解析 `.git/config` 与 `HEAD`,产出与 git 语义一致的远程视图。
95
+ *
96
+ * 为什么把 HEAD 一起解析:`branch.<name>.remote` 的 `<name>` 是**当前分支**,
97
+ * 不知道当前分支就无法按 git 的规则选出 remote,只能退化成「取第一个」——
98
+ * 那正是本次要修的错误。
99
+ *
100
+ * @param configText `.git/config` 全文
101
+ * @param headText HEAD 文件全文。worktree 场景必须传**局部 gitdir** 下的那个,
102
+ * 传共享目录的会拿到主工作树分支名(实测两者不同)。
103
+ */
104
+ export declare function parseGitConfig(configText: string, headText?: string | null): ParsedGitConfig;
105
+ /**
106
+ * 按 git 的规则选出「这个工作区关联的 remote」。
107
+ *
108
+ * 优先级与 git 一致:
109
+ * 1. `branch.<当前分支>.remote` —— 当前分支显式跟踪的 remote
110
+ * 2. `origin` —— git 的默认远程
111
+ * 3. 第一个 remote —— 兜底(保持既有行为)
112
+ *
113
+ * 特殊值 `.` 表示跟踪**本地分支**而非远程(实测可设置),跳过第 1 级——
114
+ * 拿 "." 去查 `[remote "."]` 必然查不到,且语义上它根本不是远程。
115
+ */
116
+ export declare function resolveRemoteTarget(cfg: ParsedGitConfig): ParsedRemote | null;
117
+ /**
118
+ * 从 remote url 中提取 GitHub 的 owner/repo。
119
+ *
120
+ * 覆盖形态(均实测于真实 clone / hand-written config):
121
+ * https://github.com/o/r.git
122
+ * git@github.com:o/r.git
123
+ * ssh://git@github.com/o/r.git
124
+ * https://user:token@github.com/o/r.git
125
+ * 带尾斜杠 / 不带 .git
126
+ *
127
+ * 非 github.com 的 host 一律返回 null(GHE 不在支持范围)。
128
+ * 为什么绝不"猜一个":错误身份比没有身份更有害——面板会显示一个
129
+ * 用户根本不认识的仓库,且所有后续判断都建立在错误前提上。
130
+ * 正则两端锚定,杜绝 `github.com.evil.com` 这类子串误匹配。
131
+ */
132
+ export declare function parseGithubUrl(url: string): {
133
+ owner: string;
134
+ repo: string;
135
+ } | null;
136
+ /**
137
+ * 从 remote url 中提取 host(小写)。
138
+ *
139
+ * 覆盖:https://host/o/r、git@host:o/r、ssh://git@host:2222/o/r、带 token 的 https。
140
+ * 无法解析返回 null。
141
+ *
142
+ * 为什么不直接复用 parseGithubUrl:本函数要处理**任意 host**(GHE / GitLab),
143
+ * 用于判断「这个 remote 是不是 GitHub」,而不是「这个 remote 属于哪个 GitHub 仓库」。
144
+ */
145
+ export declare function parseRemoteHost(url: string): string | null;
146
+ /**
147
+ * 判断工作区处于哪种远程布局。
148
+ *
149
+ * 为什么需要分类而不是顺序盲扫:S2 的兜底逻辑按 `.git/config` 的书写顺序
150
+ * 挑第一个能解析出 GitHub 身份的 remote,而用户执行 `git remote rename` /
151
+ * `git remote add` 的先后会改变这个顺序——同一个工作区在两次配置操作后
152
+ * 可能解析出不同仓库。分类后每种布局的处置规则固定,与顺序无关。
153
+ *
154
+ * 分类只看 host 与 git 选中的 remote,不看 URL 的仓库名——后者是身份层的事。
155
+ */
156
+ export declare function classifyRepoLayout(cfg: ParsedGitConfig): 'github-only' | 'github-mixed' | 'no-github' | 'no-remote';
157
+ /**
158
+ * 在混合布局中确定性地选出一个 GitHub remote。
159
+ *
160
+ * 规则(与书写顺序无关):
161
+ * 1. 名字为 `origin` 的优先
162
+ * 2. 否则按 remote 名字字典序最小的
163
+ *
164
+ * 为什么用字典序而不是「第一个出现的」:后者让同一个工作区的解析结果
165
+ * 依赖用户执行 git remote 命令的先后,属于不可复现的行为。
166
+ * 字典序是可复现、可断言的确定性规则。
167
+ */
168
+ export declare function pickGithubRemote(cfg: ParsedGitConfig): ParsedRemote | null;
169
+ /**
170
+ * 将整段 Git Unified Diff 纯文本按变动文件切分为字典映射。
171
+ *
172
+ * 为什么需要按文件切片:PR 可能会修改数十个文件,前端需要支持「点击某个文件即刻查看该文件改动」。
173
+ * 在内存做切片索引后,切换文件无需发起网络请求(0ms 响应),体验极致流畅。
174
+ *
175
+ * 键必须与 `gh pr view --json files` 返回的 `files[].path` **逐字一致**,
176
+ * 否则点击文件查不到 diff。因此需要处理 core.quotePath 的八进制转义。
177
+ *
178
+ * @param rawDiff gh pr diff 或 git diff 输出的原始文本
179
+ * @returns 映射字典:{ [filePath: string]: string (该文件的完整 diff 文本段) }
180
+ */
181
+ export declare function splitUnifiedDiff(rawDiff: string): Record<string, string>;