dsh-github-flow 0.4.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.
- package/README.en.md +75 -8
- package/README.md +75 -8
- package/docs/UPGRADE-NOTES.md +9 -12
- package/docs/architecture.md +39 -21
- package/lib/api/routes-actions.js +132 -0
- package/lib/client.d.ts +4 -3
- package/lib/client.js +1436 -80
- package/lib/commands/gh.d.ts +6 -1
- package/lib/commands/gh.js +144 -71
- package/lib/executor/git-parser.d.ts +33 -1
- package/lib/executor/git-parser.js +116 -4
- package/lib/executor.d.ts +27 -2
- package/lib/executor.js +189 -5
- package/lib/main.js +28 -4
- package/lib/renderers/agent-task.d.ts +16 -0
- package/lib/renderers/agent-task.js +107 -0
- package/lib/renderers/codespace.d.ts +16 -0
- package/lib/renderers/codespace.js +103 -0
- package/lib/renderers/discussion.d.ts +16 -0
- package/lib/renderers/discussion.js +101 -0
- package/lib/renderers/markdown.d.ts +4 -0
- package/lib/renderers/markdown.js +4 -0
- package/lib/renderers/project.d.ts +20 -0
- package/lib/renderers/project.js +128 -0
- package/lib/renderers/skill.d.ts +30 -0
- package/lib/renderers/skill.js +180 -0
- package/lib/renderers/status.d.ts +5 -0
- package/lib/renderers/status.js +52 -0
- package/lib/telemetry.d.ts +70 -0
- package/lib/telemetry.js +161 -0
- package/lib/tools/agent-task.d.ts +54 -0
- package/lib/tools/agent-task.js +135 -0
- package/lib/tools/codespace.d.ts +51 -0
- package/lib/tools/codespace.js +154 -0
- package/lib/tools/discussion.d.ts +70 -0
- package/lib/tools/discussion.js +195 -0
- package/lib/tools/help.js +109 -9
- package/lib/tools/project.d.ts +80 -0
- package/lib/tools/project.js +241 -0
- package/lib/tools/repo.js +13 -1
- package/lib/tools/skill.d.ts +24 -1
- package/lib/tools/skill.js +115 -5
- package/lib/tools/status.d.ts +3 -2
- package/lib/tools/status.js +9 -4
- package/lib/types.d.ts +5 -0
- package/lib/ui/commit-modal.js +144 -14
- package/lib/ui/help-modal.d.ts +15 -0
- package/lib/ui/help-modal.js +202 -0
- package/lib/ui/storage.d.ts +9 -0
- package/lib/ui/storage.js +24 -0
- package/lib/ui/styles.d.ts +1 -1
- package/lib/ui/styles.js +259 -0
- package/lib/ui/sync-settings-modal.js +1 -1
- package/lib/ui/upgrade-card.js +39 -14
- package/lib/ui/utils.d.ts +35 -0
- package/lib/ui/utils.js +160 -0
- package/lib/ui/workspace-panel.js +30 -5
- package/lib/upgrade-manager.d.ts +5 -1
- package/lib/upgrade-manager.js +24 -1
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +2 -2
package/lib/ui/commit-modal.js
CHANGED
|
@@ -36,13 +36,16 @@ export function CommitDetailModal(props) {
|
|
|
36
36
|
if (!effectiveBody && !effectiveStat && fetchedDetail) {
|
|
37
37
|
effectiveStat = fetchedDetail;
|
|
38
38
|
}
|
|
39
|
+
var parsedStat = React.useMemo(() => {
|
|
40
|
+
return effectiveStat && typeof parseGitStatText === "function" ? parseGitStatText(effectiveStat) : null;
|
|
41
|
+
}, [effectiveStat]);
|
|
39
42
|
return h("div", {
|
|
40
43
|
className: "dsh-github-modal-overlay",
|
|
41
44
|
onClick: props.onClose,
|
|
42
45
|
style: { zIndex: 100000 },
|
|
43
46
|
}, h("div", {
|
|
44
47
|
className: "dsh-github-modal-dialog",
|
|
45
|
-
style: { width: "94%", maxWidth: "
|
|
48
|
+
style: { width: "94%", maxWidth: "520px", maxHeight: "86vh", display: "flex", flexDirection: "column", overflow: "hidden" },
|
|
46
49
|
onClick: function (e) { e.stopPropagation(); },
|
|
47
50
|
}, h("div", { className: "dsh-github-modal-header", style: { flexShrink: 0 } }, h("div", { style: { display: "flex", alignItems: "center", gap: "8px" } }, renderGitIcon(15, "#1296db"), h("h3", { style: { margin: 0, fontSize: "14px", fontWeight: 600 } }, "提交详情")), h("button", {
|
|
48
51
|
style: { background: "none", border: "none", cursor: "pointer", fontSize: "18px", color: "var(--dsw-alias-label-secondary, #656d76)", padding: "0 4px" },
|
|
@@ -65,22 +68,149 @@ export function CommitDetailModal(props) {
|
|
|
65
68
|
},
|
|
66
69
|
}, effectiveBody)
|
|
67
70
|
: null, effectiveStat
|
|
68
|
-
? h("div",
|
|
69
|
-
className: "dsh-github-commit-pre",
|
|
71
|
+
? h("div", { style: { display: "flex", flexDirection: "column", gap: "6px" } }, h("div", {
|
|
70
72
|
style: {
|
|
73
|
+
display: "flex",
|
|
74
|
+
alignItems: "center",
|
|
75
|
+
justifyContent: "space-between",
|
|
71
76
|
fontSize: "11px",
|
|
72
|
-
|
|
73
|
-
whiteSpace: "pre-wrap",
|
|
74
|
-
wordBreak: "break-word",
|
|
75
|
-
margin: 0,
|
|
76
|
-
maxHeight: "34vh",
|
|
77
|
-
overflowY: "auto",
|
|
78
|
-
padding: "8px 10px",
|
|
79
|
-
borderRadius: "6px",
|
|
80
|
-
background: "var(--dsw-alias-bg-module-platform, #f6f8fa)",
|
|
81
|
-
border: "1px solid var(--dsw-alias-border-l2, #e1e4e8)",
|
|
77
|
+
fontWeight: 600,
|
|
82
78
|
},
|
|
83
|
-
},
|
|
79
|
+
}, h("div", { style: { opacity: 0.85, display: "flex", alignItems: "center", gap: "6px" } }, "📁 文件变更统计", parsedStat?.summary
|
|
80
|
+
? h("span", { style: { opacity: 0.65, fontWeight: 400 } }, `(${parsedStat.summary.filesChanged} 个文件)`)
|
|
81
|
+
: parsedStat?.files
|
|
82
|
+
? h("span", { style: { opacity: 0.65, fontWeight: 400 } }, `(${parsedStat.files.length} 个文件)`)
|
|
83
|
+
: null), parsedStat?.summary
|
|
84
|
+
? h("div", { style: { display: "flex", gap: "6px", fontFamily: "monospace", fontWeight: 600 } }, parsedStat.summary.insertions > 0
|
|
85
|
+
? h("span", {
|
|
86
|
+
style: {
|
|
87
|
+
color: "var(--dsw-alias-state-success-primary, #1a7f37)",
|
|
88
|
+
backgroundColor: "var(--dsw-alias-state-success-subtle, rgba(46,160,67,0.12))",
|
|
89
|
+
padding: "1px 6px",
|
|
90
|
+
borderRadius: "10px",
|
|
91
|
+
},
|
|
92
|
+
}, `+${parsedStat.summary.insertions}`)
|
|
93
|
+
: null, parsedStat.summary.deletions > 0
|
|
94
|
+
? h("span", {
|
|
95
|
+
style: {
|
|
96
|
+
color: "var(--dsw-alias-state-error-primary, #cf222e)",
|
|
97
|
+
backgroundColor: "var(--dsw-alias-state-error-subtle, rgba(248,81,73,0.12))",
|
|
98
|
+
padding: "1px 6px",
|
|
99
|
+
borderRadius: "10px",
|
|
100
|
+
},
|
|
101
|
+
}, `-${parsedStat.summary.deletions}`)
|
|
102
|
+
: null)
|
|
103
|
+
: null), parsedStat && parsedStat.files && parsedStat.files.length > 0
|
|
104
|
+
? h("div", {
|
|
105
|
+
className: "dsh-github-stat-list",
|
|
106
|
+
style: {
|
|
107
|
+
borderRadius: "6px",
|
|
108
|
+
border: "1px solid var(--dsw-alias-border-l2, #e1e4e8)",
|
|
109
|
+
background: "var(--dsw-alias-bg-module-platform, #f6f8fa)",
|
|
110
|
+
maxHeight: "36vh",
|
|
111
|
+
overflowY: "auto",
|
|
112
|
+
display: "flex",
|
|
113
|
+
flexDirection: "column",
|
|
114
|
+
},
|
|
115
|
+
}, parsedStat.files.map(function (f, idx) {
|
|
116
|
+
var diffBlocks = [];
|
|
117
|
+
if (!f.isBinary && f.total > 0) {
|
|
118
|
+
var totalRatio = f.additions + f.deletions;
|
|
119
|
+
var addBlocks = totalRatio > 0 ? Math.round((f.additions / totalRatio) * 5) : 0;
|
|
120
|
+
var delBlocks = totalRatio > 0 ? Math.round((f.deletions / totalRatio) * 5) : 0;
|
|
121
|
+
if (f.additions > 0 && addBlocks === 0)
|
|
122
|
+
addBlocks = 1;
|
|
123
|
+
if (f.deletions > 0 && delBlocks === 0)
|
|
124
|
+
delBlocks = 1;
|
|
125
|
+
while (addBlocks + delBlocks > 5) {
|
|
126
|
+
if (addBlocks > delBlocks)
|
|
127
|
+
addBlocks--;
|
|
128
|
+
else
|
|
129
|
+
delBlocks--;
|
|
130
|
+
}
|
|
131
|
+
var neutralBlocks = Math.max(0, 5 - addBlocks - delBlocks);
|
|
132
|
+
for (var bi = 0; bi < addBlocks; bi++) {
|
|
133
|
+
diffBlocks.push(h("span", { key: "a" + bi, style: { width: "3px", height: "8px", borderRadius: "1px", backgroundColor: "var(--dsw-alias-state-success-primary, #1a7f37)" } }));
|
|
134
|
+
}
|
|
135
|
+
for (var bj = 0; bj < delBlocks; bj++) {
|
|
136
|
+
diffBlocks.push(h("span", { key: "d" + bj, style: { width: "3px", height: "8px", borderRadius: "1px", backgroundColor: "var(--dsw-alias-state-error-primary, #cf222e)" } }));
|
|
137
|
+
}
|
|
138
|
+
for (var bk = 0; bk < neutralBlocks; bk++) {
|
|
139
|
+
diffBlocks.push(h("span", { key: "n" + bk, style: { width: "3px", height: "8px", borderRadius: "1px", backgroundColor: "var(--dsw-alias-border-subtle, rgba(0,0,0,0.15))" } }));
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return h("div", {
|
|
143
|
+
key: idx,
|
|
144
|
+
className: "dsh-github-stat-row",
|
|
145
|
+
style: {
|
|
146
|
+
display: "flex",
|
|
147
|
+
alignItems: "center",
|
|
148
|
+
justifyContent: "space-between",
|
|
149
|
+
padding: "6px 10px",
|
|
150
|
+
fontSize: "11px",
|
|
151
|
+
lineHeight: "1.4",
|
|
152
|
+
borderBottom: idx < parsedStat.files.length - 1 ? "1px solid var(--dsw-alias-border-subtle, rgba(0,0,0,0.06))" : "none",
|
|
153
|
+
gap: "8px",
|
|
154
|
+
},
|
|
155
|
+
title: f.path + (f.isBinary ? " (二进制文件)" : ` (+${f.additions}, -${f.deletions})`),
|
|
156
|
+
}, h("div", {
|
|
157
|
+
style: {
|
|
158
|
+
fontFamily: "ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, monospace",
|
|
159
|
+
overflow: "hidden",
|
|
160
|
+
textOverflow: "ellipsis",
|
|
161
|
+
whiteSpace: "nowrap",
|
|
162
|
+
flex: 1,
|
|
163
|
+
minWidth: 0,
|
|
164
|
+
color: "var(--dsw-alias-label-primary, #1f2328)",
|
|
165
|
+
},
|
|
166
|
+
}, f.path), h("div", {
|
|
167
|
+
style: {
|
|
168
|
+
display: "flex",
|
|
169
|
+
alignItems: "center",
|
|
170
|
+
gap: "6px",
|
|
171
|
+
flexShrink: 0,
|
|
172
|
+
fontFamily: "monospace",
|
|
173
|
+
fontWeight: 600,
|
|
174
|
+
},
|
|
175
|
+
}, f.isBinary
|
|
176
|
+
? h("span", { style: { opacity: 0.6, fontSize: "10px" } }, "二进制")
|
|
177
|
+
: [
|
|
178
|
+
f.additions > 0
|
|
179
|
+
? h("span", {
|
|
180
|
+
key: "add",
|
|
181
|
+
style: { color: "var(--dsw-alias-state-success-primary, #1a7f37)" },
|
|
182
|
+
}, `+${f.additions}`)
|
|
183
|
+
: null,
|
|
184
|
+
f.deletions > 0
|
|
185
|
+
? h("span", {
|
|
186
|
+
key: "del",
|
|
187
|
+
style: { color: "var(--dsw-alias-state-error-primary, #cf222e)" },
|
|
188
|
+
}, `-${f.deletions}`)
|
|
189
|
+
: null,
|
|
190
|
+
diffBlocks.length > 0
|
|
191
|
+
? h("div", {
|
|
192
|
+
key: "bar",
|
|
193
|
+
style: { display: "flex", gap: "1px", marginLeft: "2px", alignItems: "center" },
|
|
194
|
+
}, ...diffBlocks)
|
|
195
|
+
: null,
|
|
196
|
+
]));
|
|
197
|
+
}))
|
|
198
|
+
: h("pre", {
|
|
199
|
+
className: "dsh-github-commit-pre",
|
|
200
|
+
style: {
|
|
201
|
+
fontSize: "11px",
|
|
202
|
+
lineHeight: "1.5",
|
|
203
|
+
whiteSpace: "pre-wrap",
|
|
204
|
+
wordBreak: "break-word",
|
|
205
|
+
margin: 0,
|
|
206
|
+
maxHeight: "34vh",
|
|
207
|
+
overflowY: "auto",
|
|
208
|
+
padding: "8px 10px",
|
|
209
|
+
borderRadius: "6px",
|
|
210
|
+
background: "var(--dsw-alias-bg-module-platform, #f6f8fa)",
|
|
211
|
+
border: "1px solid var(--dsw-alias-border-l2, #e1e4e8)",
|
|
212
|
+
},
|
|
213
|
+
}, effectiveStat))
|
|
84
214
|
: null, !effectiveBody && !effectiveStat
|
|
85
215
|
? (fetchingDetail
|
|
86
216
|
? h("div", { style: { fontSize: "12px", opacity: 0.7, padding: "8px 0" } }, "⏳ 正在获取详细变更说明…")
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 独立沉浸式指南大窗口组件 (Dedicated Large Reader Modal)
|
|
3
|
+
*
|
|
4
|
+
* 核心设计理由与交互契约:
|
|
5
|
+
* 1. 彻底从设置小窗口剥离,打造 920px 宽屏、85vh 高度的沉浸式阅读视界;
|
|
6
|
+
* 2. 深度适配 DSH 主题系统,全套样式基于 CSS 类与主题变量,支持深色 (data-ds-dark-theme) 与浅色无缝自适应;
|
|
7
|
+
* 3. 拒绝技术自嗨清单,从用户行动视角组织:3分钟快速上手、Agent实战Prompt、双界面图解与常见排错;
|
|
8
|
+
* 4. 宽屏卡片排列,配备 Prompt 一键复制到剪贴板与短暂反馈气泡;
|
|
9
|
+
* 5. 监听键盘 Esc 键与遮罩点击秒关,复制完指令直接回到聊天输入框发送,零打扰、不中断工作流。
|
|
10
|
+
*/
|
|
11
|
+
export declare function GithubHelpModal(props: {
|
|
12
|
+
isOpen: boolean;
|
|
13
|
+
onClose: () => void;
|
|
14
|
+
initialTab?: string;
|
|
15
|
+
}): any;
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 独立沉浸式指南大窗口组件 (Dedicated Large Reader Modal)
|
|
3
|
+
*
|
|
4
|
+
* 核心设计理由与交互契约:
|
|
5
|
+
* 1. 彻底从设置小窗口剥离,打造 920px 宽屏、85vh 高度的沉浸式阅读视界;
|
|
6
|
+
* 2. 深度适配 DSH 主题系统,全套样式基于 CSS 类与主题变量,支持深色 (data-ds-dark-theme) 与浅色无缝自适应;
|
|
7
|
+
* 3. 拒绝技术自嗨清单,从用户行动视角组织:3分钟快速上手、Agent实战Prompt、双界面图解与常见排错;
|
|
8
|
+
* 4. 宽屏卡片排列,配备 Prompt 一键复制到剪贴板与短暂反馈气泡;
|
|
9
|
+
* 5. 监听键盘 Esc 键与遮罩点击秒关,复制完指令直接回到聊天输入框发送,零打扰、不中断工作流。
|
|
10
|
+
*/
|
|
11
|
+
export function GithubHelpModal(props) {
|
|
12
|
+
if (!props.isOpen)
|
|
13
|
+
return null;
|
|
14
|
+
var [activeTab, setActiveTab] = React.useState(props.initialTab || "quickstart");
|
|
15
|
+
var [copiedIdx, setCopiedIdx] = React.useState(-1);
|
|
16
|
+
React.useEffect(function () {
|
|
17
|
+
if (props.isOpen && props.initialTab) {
|
|
18
|
+
setActiveTab(props.initialTab);
|
|
19
|
+
}
|
|
20
|
+
}, [props.isOpen, props.initialTab]);
|
|
21
|
+
React.useEffect(function () {
|
|
22
|
+
var onKeyDown = function (e) {
|
|
23
|
+
if (e.key === "Escape" || e.keyCode === 27) {
|
|
24
|
+
props.onClose();
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
window.addEventListener("keydown", onKeyDown);
|
|
28
|
+
return function () { window.removeEventListener("keydown", onKeyDown); };
|
|
29
|
+
}, [props.onClose]);
|
|
30
|
+
var handleCopy = function (text, idx) {
|
|
31
|
+
if (navigator.clipboard) {
|
|
32
|
+
navigator.clipboard.writeText(text);
|
|
33
|
+
setCopiedIdx(idx);
|
|
34
|
+
setTimeout(function () { setCopiedIdx(-1); }, 2000);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
prompt("请复制提示词:", text);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
var h = React.createElement;
|
|
41
|
+
// 1. 顶部 Tab 导航项
|
|
42
|
+
var tabs = [
|
|
43
|
+
{ id: "quickstart", label: "🚀 3分钟极速上手" },
|
|
44
|
+
{ id: "prompts", label: "🤖 Agent 提示词实战" },
|
|
45
|
+
{ id: "panels", label: "🖥️ 两大界面操作图解" },
|
|
46
|
+
{ id: "faq", label: "🔑 常见自愈排错" },
|
|
47
|
+
];
|
|
48
|
+
// 2. 渲染各 Tab 独立视图
|
|
49
|
+
var renderContent = function () {
|
|
50
|
+
if (activeTab === "quickstart") {
|
|
51
|
+
return h("div", null, h("div", { className: "dsh-github-help-desc", style: { fontSize: "13px", marginBottom: "16px" } }, "欢迎使用 DSH GitHub Flow!本插件让 DeepSeek Harness Agent 具备直接操作 GitHub 仓库的能力,同时为你提供沉浸式的本地与云端协作工作台。跟着下面 3 步即可快速跑通你的第一个人机协作研发闭环:"), [
|
|
52
|
+
{
|
|
53
|
+
step: "1",
|
|
54
|
+
title: "确认 GitHub CLI 登录状态",
|
|
55
|
+
desc: "本插件直接复用宿主机已有的安全登录态,绝不触碰任何明文 Token。",
|
|
56
|
+
actionText: "操作方式:在 DSH 任意聊天框输入 /gh 直接按回车;或查看右侧栏抽屉顶部的账号徽标。若显示未登录,在系统终端执行单行命令 gh auth login 即可完成授权。",
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
step: "2",
|
|
60
|
+
title: "打开你的代码仓库",
|
|
61
|
+
desc: "在 DSH 中打开任何包含 .git 的项目文件夹,插件将自动毫秒级绑定当前仓库上下文。",
|
|
62
|
+
actionText: "无需每次告诉 Agent 仓库叫什么名字,插件底层已自动完成 CWD 工作区绑定,提单与审查均精准面向当前项目。",
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
step: "3",
|
|
66
|
+
title: "直接向 Agent 下达工作指令",
|
|
67
|
+
desc: "像和资深研发搭档协作一样,在聊天输入框中直接吩咐 Agent 处理日常 GitHub 任务。",
|
|
68
|
+
actionText: "初次体验试一试直接对 Agent 说:\n👉 \"查看当前仓库有哪些开放的 PR,总结下改动要点\"",
|
|
69
|
+
},
|
|
70
|
+
].map(function (s, i) {
|
|
71
|
+
return h("div", { key: i, className: "dsh-github-help-card", style: { display: "flex", gap: "14px", alignItems: "flex-start" } }, h("div", { className: "dsh-github-help-step-badge" }, s.step), h("div", { style: { flex: 1 } }, h("div", { className: "dsh-github-help-title", style: { marginBottom: "4px" } }, s.title), h("div", { className: "dsh-github-help-desc", style: { marginBottom: "6px" } }, s.desc), h("div", { style: { fontSize: "12px", lineHeight: "1.6", whiteSpace: "pre-line", color: "inherit" } }, s.actionText)));
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
if (activeTab === "prompts") {
|
|
75
|
+
var promptCards = [
|
|
76
|
+
{
|
|
77
|
+
title: "🔀 场景一:自动创建 PR 并发起代码审查",
|
|
78
|
+
desc: "本地写完代码或实现新功能后,无需打开浏览器手动点点点,让 Agent 自主完成端到端提单。",
|
|
79
|
+
prompt: "帮我把当前分支创建一个 PR,标题简明概括改动要点,附带详细描述",
|
|
80
|
+
aiAction: "Agent 自动检查本地当前分支、比对与主干的 diff、推送到远程仓库并创建 GitHub PR,附带优雅的改动说明与关联标记。",
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
title: "🚨 场景二:CI / Actions 门禁报错秒级排查与自动修复",
|
|
84
|
+
desc: "构建挂了不用在网页反复翻几十页日志,直接吩咐 Agent 定位报错步骤并就地改代码。",
|
|
85
|
+
prompt: "检查当前仓库最近一次 CI 失败的原因,精确定位报错步骤并帮我尝试修复代码",
|
|
86
|
+
aiAction: "Agent 自动调用失败日志探测工具,秒级提取具体挂掉的构建步骤输出,精准定位语法/单测异常并就地修改本地代码。",
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
title: "📌 场景三:早会与每日任务待办盘点",
|
|
90
|
+
desc: "晨会前或开始工作时,一键拉取名下所有关联事项,做到心中有数。",
|
|
91
|
+
prompt: "帮我看看今天在 GitHub 上分配给我的 Issue 待办与等待我评审的 PR,汇总近期动态",
|
|
92
|
+
aiAction: "Agent 自动在账号维度跨仓库聚合所有分配给你的议题、等待评审的拉取请求以及提及你的动态,输出整洁紧凑的待办看板。",
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
title: "🛡️ 场景四:代码差异 (Diff) 安全审查与重构建议",
|
|
96
|
+
desc: "合并前把好最后一关,让大模型充当资深 Tech Lead 开展多维度代码走查。",
|
|
97
|
+
prompt: "审查当前分支与主干的代码差异 (diff),检查是否存在潜在 Bug 或安全隐患并给出重构建议",
|
|
98
|
+
aiAction: "Agent 自动获取改动文件与行级差异,结合工程最佳实践逐项排查边界条件、内存泄漏、空指针与安全漏洞。",
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
title: "💬 场景五:团队方案提案与开源 RFC 研讨",
|
|
102
|
+
desc: "需要和团队讨论架构思路或征集想法时,直接将讨论沉淀在 GitHub Discussions 知识库中。",
|
|
103
|
+
prompt: "在当前仓库发起一个关于 '优化前端构建性能' 的 RFC 讨论方案",
|
|
104
|
+
aiAction: "Agent 自动调用 Discussions 工具在指定分类下发起主题,格式化排版技术方案正文,并返回可供团队直达探讨的链接。",
|
|
105
|
+
},
|
|
106
|
+
];
|
|
107
|
+
return h("div", null, h("div", { className: "dsh-github-help-desc", style: { fontSize: "13px", marginBottom: "14px" } }, "以下精选了开发者日常研发中最高频的 5 大真实协作场景。点击卡片右侧的「📋 一键复制」按钮,直接粘贴到聊天输入框发给 Agent 即可:"), promptCards.map(function (c, idx) {
|
|
108
|
+
var isCopied = copiedIdx === idx;
|
|
109
|
+
return h("div", { key: idx, className: "dsh-github-help-card" }, h("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: "8px" } }, h("div", { className: "dsh-github-help-title" }, c.title), h("button", {
|
|
110
|
+
className: "dsh-github-btn-sm",
|
|
111
|
+
onClick: function () { handleCopy(c.prompt, idx); },
|
|
112
|
+
style: {
|
|
113
|
+
padding: "4px 10px",
|
|
114
|
+
fontSize: "12px",
|
|
115
|
+
background: isCopied ? "#2ea043" : "var(--dsw-alias-link, #0969da)",
|
|
116
|
+
color: "#ffffff",
|
|
117
|
+
borderColor: isCopied ? "#2ea043" : "var(--dsw-alias-link, #0969da)",
|
|
118
|
+
fontWeight: 600,
|
|
119
|
+
transition: "all 0.2s ease",
|
|
120
|
+
},
|
|
121
|
+
}, isCopied ? "✅ 已复制到剪贴板!" : "📋 一键复制 Prompt")), h("div", { className: "dsh-github-help-desc", style: { marginBottom: "10px" } }, c.desc), h("div", { className: "dsh-github-prompt-box" }, `"${c.prompt}"`), h("div", { style: { fontSize: "11px", color: "var(--dsw-alias-state-attention-primary, #d29922)", lineHeight: "1.4" } }, "💡 " + c.aiAction));
|
|
122
|
+
}));
|
|
123
|
+
}
|
|
124
|
+
if (activeTab === "panels") {
|
|
125
|
+
return h("div", null, h("div", { className: "dsh-github-help-desc", style: { fontSize: "13px", marginBottom: "16px" } }, "插件为人类开发者量身打造了两套互补的可视化工作台,消灭频繁在 VS Code、终端与浏览器切屏的上下文丢失痛点:"), [
|
|
126
|
+
{
|
|
127
|
+
title: "1. 全景驾驶舱 (Main Dashboard) —— 掌控全局资产",
|
|
128
|
+
items: [
|
|
129
|
+
"打开入口:点击 DSH 最左侧主导航栏的 Octocat 猫咪徽标,瞬间全屏展开;",
|
|
130
|
+
"SWR 0ms 瞬间秒开:采用本地持久化快照体系,打开界面零转圈、零等待;",
|
|
131
|
+
"名下仓库一览:一屏透视名下所有 GitHub 仓库、默认分支与 Star 状态,支持一键切换工作区;",
|
|
132
|
+
"三维待办 Issue 矩阵:智能划分「📥 用户提单(反馈到我名下仓库)」、「🎯 指派待办(分配给我)」与「✍️ 我发起的」,一键药丸筛选;",
|
|
133
|
+
"全局配置中心:右上方提供数据同步节奏、网络代理与更新源的集中配置弹窗。",
|
|
134
|
+
],
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
title: "2. 会话右侧栏面板 (Sidebar Panel) —— 深度协同当前工作区",
|
|
138
|
+
items: [
|
|
139
|
+
"打开入口:位于每个会话工作区的右侧抽屉栏,深度锁定当前会话的物理 Git 仓库;",
|
|
140
|
+
"未提交改动 (Dirty Tab):实时监听本地未提交文件列表与改动数量,开发改代码一目了然;",
|
|
141
|
+
"分支查看与安全切换:点击分支名称下拉秒级搜索本地/远程分支;具备未提交变更安全拦截,杜绝代码被冲掉;",
|
|
142
|
+
"Git 提交时间线 (Git Tab):清晰三段式呈现待推送(领先)、待拉取(落后)与最近提交,点击任意提交行可弹出 Commit 完整详情弹窗;",
|
|
143
|
+
"动静解耦架构:修改本地代码只定向查询本地 .git 核心元数据(耗时仅 5ms),绝对不发起远端网络请求,杜绝网络风暴。",
|
|
144
|
+
],
|
|
145
|
+
},
|
|
146
|
+
].map(function (sec, idx) {
|
|
147
|
+
return h("div", { key: idx, className: "dsh-github-help-card" }, h("div", { className: "dsh-github-help-title", style: { marginBottom: "8px" } }, sec.title), h("ul", { style: { margin: 0, paddingLeft: "18px", fontSize: "12px", lineHeight: "1.7", color: "var(--dsw-alias-label-secondary, #8b949e)" } }, sec.items.map(function (it, i) { return h("li", { key: i }, it); })));
|
|
148
|
+
}));
|
|
149
|
+
}
|
|
150
|
+
if (activeTab === "faq") {
|
|
151
|
+
var faqs = [
|
|
152
|
+
{
|
|
153
|
+
q: "Q1: 界面提示「未登录 GitHub」或「Authentication Required」怎么办?",
|
|
154
|
+
a: "插件直接复用宿主系统的 GitHub CLI 登录态。请打开系统终端运行命令 `gh auth login`,依次选择 GitHub.com ➔ HTTPS ➔ 网页回车授权,一分钟内即可完成登录。登录完成后刷新界面即可自动识别。",
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
q: "Q2: 提示「缺少权限 (Scope)」或「SCOPE_REQUIRED」怎么办?",
|
|
158
|
+
a: "当调用项目看板(Projects v2)或云端开发机(Codespaces)时,GitHub 要求专有的 Token Scope。在系统终端执行对应的一键自愈命令完成增量授权即可(无需重新登录):\n- 项目看板:`gh auth refresh -s read:project`\n- 云端开发机:`gh auth refresh -h github.com -s codespace`",
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
q: "Q3: 点击一键升级提示「处于 24h 安全保护期 (防投毒策略)」怎么办?",
|
|
162
|
+
a: "这是 DSH 官方内置包管理器针对刚发布未满 24 小时新版本的供应链防投毒安全锁机制。\n- 立即体验:请先【完全退出关闭 DSH 应用程序】,然后在系统终端执行复制的手动安装命令;\n- 稍后升级:无需任何操作,新版本发版满 24 小时后,再次点击一键升级即可自动安装。",
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
q: "Q4: 使用代理节点时偶尔出现网络波动怎么办?",
|
|
166
|
+
a: "插件内置了 1s ➔ 2s ➔ 4s 的阶梯指数退避重试机制。代理节点若发生短时抖动断流,系统会自动在后台静默发起自愈重试,在节点恢复后瞬间平滑拉取最新数据,不会立刻亮出大红横幅打扰你。同时电脑联网恢复瞬间也会自动触发静默更新。",
|
|
167
|
+
},
|
|
168
|
+
];
|
|
169
|
+
return h("div", null, h("div", { className: "dsh-github-help-desc", style: { fontSize: "13px", marginBottom: "14px" } }, "常见环境、权限与网络问题的排查与自愈指引:"), faqs.map(function (f, idx) {
|
|
170
|
+
return h("div", { key: idx, className: "dsh-github-help-card" }, h("div", { className: "dsh-github-help-title", style: { marginBottom: "6px", fontSize: "13px" } }, f.q), h("div", { className: "dsh-github-help-desc", style: { lineHeight: "1.6", whiteSpace: "pre-line" } }, f.a));
|
|
171
|
+
}));
|
|
172
|
+
}
|
|
173
|
+
return null;
|
|
174
|
+
};
|
|
175
|
+
return h("div", { className: "dsh-github-modal-overlay", onClick: props.onClose }, h("div", {
|
|
176
|
+
className: "dsh-github-help-dialog",
|
|
177
|
+
onClick: function (e) { e.stopPropagation(); },
|
|
178
|
+
},
|
|
179
|
+
// 顶部标题栏
|
|
180
|
+
h("div", { className: "dsh-github-help-header" }, h("div", { style: { display: "flex", alignItems: "center", gap: "8px" } }, h("span", { style: { fontSize: "20px" } }, "📖"), h("h3", { style: { margin: 0, fontSize: "16px", fontWeight: 600, color: "inherit" } }, "DSH GitHub Flow · 使用指南与实战手册")), h("button", {
|
|
181
|
+
style: { background: "none", border: "none", cursor: "pointer", fontSize: "18px", color: "var(--dsw-alias-label-secondary, #8b949e)", padding: "0 4px" },
|
|
182
|
+
onClick: props.onClose,
|
|
183
|
+
title: "关闭 (Esc)",
|
|
184
|
+
}, "✕")),
|
|
185
|
+
// 顶部四分类 Segment 导航栏
|
|
186
|
+
h("div", { className: "dsh-github-help-nav" }, tabs.map(function (t) {
|
|
187
|
+
var isActive = activeTab === t.id;
|
|
188
|
+
return h("button", {
|
|
189
|
+
key: t.id,
|
|
190
|
+
className: "dsh-github-help-tab-btn" + (isActive ? " active" : ""),
|
|
191
|
+
onClick: function () { setActiveTab(t.id); },
|
|
192
|
+
}, t.label);
|
|
193
|
+
})),
|
|
194
|
+
// 主内容滚动区
|
|
195
|
+
h("div", { className: "dsh-github-help-scroll-body" }, renderContent()),
|
|
196
|
+
// 底部工具栏
|
|
197
|
+
h("div", { className: "dsh-github-help-footer" }, h("div", { style: { fontSize: "12px", color: "var(--dsw-alias-label-tertiary, #8c959f)" } }, "💡 提示:按键盘 Esc 键可随时快速关闭大窗口返回会话"), h("button", {
|
|
198
|
+
className: "dsh-github-btn-sm",
|
|
199
|
+
style: { padding: "6px 16px", fontWeight: 600 },
|
|
200
|
+
onClick: props.onClose,
|
|
201
|
+
}, "关闭窗口"))));
|
|
202
|
+
}
|
package/lib/ui/storage.d.ts
CHANGED
|
@@ -24,3 +24,12 @@ export declare function getStoredRightbarSnapshot(cwd: string | null): {
|
|
|
24
24
|
savedAt: any;
|
|
25
25
|
} | null;
|
|
26
26
|
export declare function saveStoredRightbarData(cwd: string | null, data: any): void;
|
|
27
|
+
export declare const HEADER_CARDS_STORAGE_KEY = "dsh_github_header_cards_visible_v1";
|
|
28
|
+
/**
|
|
29
|
+
* 读取右侧栏上方仓库卡片与快捷操作栏的折叠/展开偏好(默认为 true 展开)
|
|
30
|
+
*/
|
|
31
|
+
export declare function getStoredHeaderCardsVisible(): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* 持久化保存右侧栏上方仓库卡片与快捷操作栏的展开/折叠偏好
|
|
34
|
+
*/
|
|
35
|
+
export declare function saveStoredHeaderCardsVisible(visible: boolean): void;
|
package/lib/ui/storage.js
CHANGED
|
@@ -132,3 +132,27 @@ export function saveStoredRightbarData(cwd, data) {
|
|
|
132
132
|
}
|
|
133
133
|
catch (e) { }
|
|
134
134
|
}
|
|
135
|
+
export const HEADER_CARDS_STORAGE_KEY = "dsh_github_header_cards_visible_v1";
|
|
136
|
+
/**
|
|
137
|
+
* 读取右侧栏上方仓库卡片与快捷操作栏的折叠/展开偏好(默认为 true 展开)
|
|
138
|
+
*/
|
|
139
|
+
export function getStoredHeaderCardsVisible() {
|
|
140
|
+
try {
|
|
141
|
+
var raw = localStorage.getItem(HEADER_CARDS_STORAGE_KEY);
|
|
142
|
+
if (raw === null || raw === undefined)
|
|
143
|
+
return true;
|
|
144
|
+
return raw !== "false";
|
|
145
|
+
}
|
|
146
|
+
catch (e) {
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* 持久化保存右侧栏上方仓库卡片与快捷操作栏的展开/折叠偏好
|
|
152
|
+
*/
|
|
153
|
+
export function saveStoredHeaderCardsVisible(visible) {
|
|
154
|
+
try {
|
|
155
|
+
localStorage.setItem(HEADER_CARDS_STORAGE_KEY, visible ? "true" : "false");
|
|
156
|
+
}
|
|
157
|
+
catch (e) { }
|
|
158
|
+
}
|