dsh-github-flow 0.1.5 → 0.1.7
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 +12 -7
- package/README.md +12 -7
- package/docs/architecture.md +18 -3
- package/lib/api/routes.js +149 -10
- package/lib/client/panel.js +28 -1
- package/lib/client.js +424 -13
- package/lib/executor.d.ts +8 -5
- package/lib/executor.js +58 -14
- package/lib/tools/api.js +2 -1
- package/lib/tools/issue.js +13 -8
- package/lib/tools/pr.js +14 -9
- package/lib/tools/repo.js +6 -4
- package/lib/tools/run.js +12 -7
- package/lib/types.d.ts +53 -9
- package/lib/workspace.d.ts +6 -3
- package/lib/workspace.js +24 -9
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -250,6 +250,16 @@ body[data-ds-dark-theme] .dsh-github-card-subtext {
|
|
|
250
250
|
color: #9a6700;
|
|
251
251
|
border: 1px solid rgba(154, 103, 0, 0.2);
|
|
252
252
|
}
|
|
253
|
+
.dsh-badge-blue {
|
|
254
|
+
background: rgba(9, 105, 218, 0.12);
|
|
255
|
+
color: #0969da;
|
|
256
|
+
border: 1px solid rgba(9, 105, 218, 0.2);
|
|
257
|
+
}
|
|
258
|
+
.dsh-badge-purple {
|
|
259
|
+
background: rgba(137, 87, 229, 0.12);
|
|
260
|
+
color: #8250df;
|
|
261
|
+
border: 1px solid rgba(137, 87, 229, 0.2);
|
|
262
|
+
}
|
|
253
263
|
body[data-ds-dark-theme] .dsh-badge-green {
|
|
254
264
|
background: rgba(46, 160, 67, 0.22);
|
|
255
265
|
color: #3fb950;
|
|
@@ -265,6 +275,63 @@ body[data-ds-dark-theme] .dsh-badge-yellow {
|
|
|
265
275
|
color: #d29922;
|
|
266
276
|
border-color: rgba(210, 153, 34, 0.3);
|
|
267
277
|
}
|
|
278
|
+
body[data-ds-dark-theme] .dsh-badge-blue {
|
|
279
|
+
background: rgba(56, 139, 253, 0.22);
|
|
280
|
+
color: #58a6ff;
|
|
281
|
+
border-color: rgba(56, 139, 253, 0.3);
|
|
282
|
+
}
|
|
283
|
+
body[data-ds-dark-theme] .dsh-badge-purple {
|
|
284
|
+
background: rgba(163, 113, 247, 0.22);
|
|
285
|
+
color: #bc8cff;
|
|
286
|
+
border-color: rgba(163, 113, 247, 0.3);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/* 7.5. 分类筛选药丸栏 */
|
|
290
|
+
.dsh-github-pills {
|
|
291
|
+
display: flex;
|
|
292
|
+
align-items: center;
|
|
293
|
+
gap: 6px;
|
|
294
|
+
flex-wrap: wrap;
|
|
295
|
+
margin-bottom: 12px;
|
|
296
|
+
}
|
|
297
|
+
.dsh-github-pill-btn {
|
|
298
|
+
display: inline-flex;
|
|
299
|
+
align-items: center;
|
|
300
|
+
gap: 4px;
|
|
301
|
+
padding: 4px 10px;
|
|
302
|
+
border-radius: 14px;
|
|
303
|
+
font-size: 11px;
|
|
304
|
+
font-weight: 500;
|
|
305
|
+
border: 1px solid var(--dsw-alias-border-l2, #d0d7de);
|
|
306
|
+
background: var(--dsw-alias-bg-module-platform, #f6f8fa);
|
|
307
|
+
color: var(--dsw-alias-label-secondary, #656d76);
|
|
308
|
+
cursor: pointer;
|
|
309
|
+
transition: all 0.15s ease;
|
|
310
|
+
}
|
|
311
|
+
.dsh-github-pill-btn:hover {
|
|
312
|
+
color: var(--dsw-alias-label-primary, #1f2328);
|
|
313
|
+
border-color: var(--dsw-alias-border-l3, #b0b8c1);
|
|
314
|
+
}
|
|
315
|
+
.dsh-github-pill-btn.active {
|
|
316
|
+
background: var(--dsw-alias-bg-module-platform, rgba(9, 105, 218, 0.1));
|
|
317
|
+
color: var(--dsw-alias-link, #0969da);
|
|
318
|
+
border-color: var(--dsw-alias-link, #0969da);
|
|
319
|
+
font-weight: 600;
|
|
320
|
+
}
|
|
321
|
+
body[data-ds-dark-theme] .dsh-github-pill-btn {
|
|
322
|
+
background: var(--dsw-alias-bg-layer-2, #21262d);
|
|
323
|
+
color: var(--dsw-alias-label-secondary, #8b949e);
|
|
324
|
+
border-color: var(--dsw-alias-border-l1, #30363d);
|
|
325
|
+
}
|
|
326
|
+
body[data-ds-dark-theme] .dsh-github-pill-btn:hover {
|
|
327
|
+
color: var(--dsw-alias-label-primary, #f0f6fc);
|
|
328
|
+
border-color: #8b949e;
|
|
329
|
+
}
|
|
330
|
+
body[data-ds-dark-theme] .dsh-github-pill-btn.active {
|
|
331
|
+
background: rgba(56, 139, 253, 0.18);
|
|
332
|
+
color: #58a6ff;
|
|
333
|
+
border-color: #58a6ff;
|
|
334
|
+
}
|
|
268
335
|
|
|
269
336
|
/* 8. 快捷操作网格 */
|
|
270
337
|
.dsh-github-quick-actions {
|
|
@@ -633,6 +700,110 @@ body[data-ds-dark-theme] .dsh-github-repo-link {
|
|
|
633
700
|
body[data-ds-dark-theme] .dsh-github-subheading {
|
|
634
701
|
color: var(--dsw-alias-label-primary, #f0f6fc);
|
|
635
702
|
}
|
|
703
|
+
|
|
704
|
+
/* 15. 就绪引导横幅 (Setup Guide Banner) */
|
|
705
|
+
.dsh-github-guide-card {
|
|
706
|
+
padding: 16px;
|
|
707
|
+
border-radius: 8px;
|
|
708
|
+
margin-bottom: 16px;
|
|
709
|
+
border: 1px solid var(--dsw-alias-border-l2, #d0d7de);
|
|
710
|
+
background: var(--dsw-alias-bg-layer-1, #f6f8fa);
|
|
711
|
+
}
|
|
712
|
+
.dsh-github-guide-card.warning {
|
|
713
|
+
border-color: rgba(210, 153, 34, 0.4);
|
|
714
|
+
background: rgba(210, 153, 34, 0.08);
|
|
715
|
+
}
|
|
716
|
+
.dsh-github-guide-card.danger {
|
|
717
|
+
border-color: rgba(248, 81, 73, 0.4);
|
|
718
|
+
background: rgba(248, 81, 73, 0.08);
|
|
719
|
+
}
|
|
720
|
+
.dsh-github-guide-header {
|
|
721
|
+
display: flex;
|
|
722
|
+
align-items: center;
|
|
723
|
+
gap: 8px;
|
|
724
|
+
font-size: 15px;
|
|
725
|
+
font-weight: 600;
|
|
726
|
+
margin-bottom: 6px;
|
|
727
|
+
color: var(--dsw-alias-label-primary, #1f2328);
|
|
728
|
+
}
|
|
729
|
+
body[data-ds-dark-theme] .dsh-github-guide-header {
|
|
730
|
+
color: var(--dsw-alias-label-primary, #f0f6fc);
|
|
731
|
+
}
|
|
732
|
+
.dsh-github-guide-desc {
|
|
733
|
+
font-size: 13px;
|
|
734
|
+
color: var(--dsw-alias-label-secondary, #656d76);
|
|
735
|
+
line-height: 1.5;
|
|
736
|
+
margin-bottom: 12px;
|
|
737
|
+
}
|
|
738
|
+
body[data-ds-dark-theme] .dsh-github-guide-desc {
|
|
739
|
+
color: var(--dsw-alias-label-secondary, #8c8c8c);
|
|
740
|
+
}
|
|
741
|
+
.dsh-github-cmd-box {
|
|
742
|
+
display: flex;
|
|
743
|
+
align-items: center;
|
|
744
|
+
justify-content: space-between;
|
|
745
|
+
background: var(--dsw-alias-bg-base, #ffffff);
|
|
746
|
+
border: 1px solid var(--dsw-alias-border-l2, #d0d7de);
|
|
747
|
+
border-radius: 6px;
|
|
748
|
+
padding: 8px 12px;
|
|
749
|
+
font-family: var(--ds-font-family-code, monospace);
|
|
750
|
+
font-size: 13px;
|
|
751
|
+
color: var(--dsw-alias-label-primary, #1f2328);
|
|
752
|
+
margin-bottom: 12px;
|
|
753
|
+
}
|
|
754
|
+
body[data-ds-dark-theme] .dsh-github-cmd-box {
|
|
755
|
+
background: var(--dsw-alias-bg-layer-2, #161b22);
|
|
756
|
+
border-color: var(--dsw-alias-border-l1, #30363d);
|
|
757
|
+
color: var(--dsw-alias-label-primary, #f0f6fc);
|
|
758
|
+
}
|
|
759
|
+
.dsh-github-copy-btn {
|
|
760
|
+
padding: 4px 10px;
|
|
761
|
+
font-size: 12px;
|
|
762
|
+
border-radius: 4px;
|
|
763
|
+
border: 1px solid var(--dsw-alias-border-l2, #d0d7de);
|
|
764
|
+
background: var(--dsw-alias-bg-layer-1, #f6f8fa);
|
|
765
|
+
color: var(--dsw-alias-label-primary, #1f2328);
|
|
766
|
+
cursor: pointer;
|
|
767
|
+
white-space: nowrap;
|
|
768
|
+
transition: all 0.15s ease;
|
|
769
|
+
}
|
|
770
|
+
body[data-ds-dark-theme] .dsh-github-copy-btn {
|
|
771
|
+
background: var(--dsw-alias-bg-layer-2, #21262d);
|
|
772
|
+
border-color: var(--dsw-alias-border-l1, #30363d);
|
|
773
|
+
color: var(--dsw-alias-label-primary, #c9d1d9);
|
|
774
|
+
}
|
|
775
|
+
.dsh-github-copy-btn:hover {
|
|
776
|
+
background: var(--dsw-alias-interactive-bg-hover, #ebeef1);
|
|
777
|
+
}
|
|
778
|
+
body[data-ds-dark-theme] .dsh-github-copy-btn:hover {
|
|
779
|
+
background: #30363d;
|
|
780
|
+
}
|
|
781
|
+
.dsh-github-copy-btn.copied {
|
|
782
|
+
color: #2da44e !important;
|
|
783
|
+
border-color: #2da44e !important;
|
|
784
|
+
background: rgba(45, 164, 78, 0.15) !important;
|
|
785
|
+
}
|
|
786
|
+
.dsh-github-steps-list {
|
|
787
|
+
font-size: 12px;
|
|
788
|
+
color: var(--dsw-alias-label-secondary, #656d76);
|
|
789
|
+
line-height: 1.6;
|
|
790
|
+
margin: 0 0 12px 18px;
|
|
791
|
+
padding: 0;
|
|
792
|
+
}
|
|
793
|
+
body[data-ds-dark-theme] .dsh-github-steps-list {
|
|
794
|
+
color: var(--dsw-alias-label-secondary, #8c8c8c);
|
|
795
|
+
}
|
|
796
|
+
.dsh-github-guide-actions {
|
|
797
|
+
display: flex;
|
|
798
|
+
gap: 8px;
|
|
799
|
+
flex-wrap: wrap;
|
|
800
|
+
}
|
|
801
|
+
.dsh-github-guide-tip {
|
|
802
|
+
font-size: 11px;
|
|
803
|
+
color: var(--dsw-alias-label-tertiary, #8c8c8c);
|
|
804
|
+
margin-top: 10px;
|
|
805
|
+
line-height: 1.4;
|
|
806
|
+
}
|
|
636
807
|
`;
|
|
637
808
|
function injectStyles() {
|
|
638
809
|
var styleId = "dsh-plugin-github-styles";
|
|
@@ -672,11 +843,126 @@ body[data-ds-dark-theme] .dsh-github-subheading {
|
|
|
672
843
|
}
|
|
673
844
|
}, renderOctocat(Math.round(size * 0.58), "#ffffff"));
|
|
674
845
|
}
|
|
846
|
+
// 认证与安装引导卡片组件(响应式自适应中央大面板与右侧栏)
|
|
847
|
+
function AuthGuideCard(props) {
|
|
848
|
+
var auth = props ? props.auth : null;
|
|
849
|
+
var onRefresh = props ? props.onRefresh : () => { };
|
|
850
|
+
var isRightbar = Boolean(props && props.isRightbar);
|
|
851
|
+
var [copied, setCopied] = React.useState(false);
|
|
852
|
+
var [launching, setLaunching] = React.useState(false);
|
|
853
|
+
var [toastMsg, setToastMsg] = React.useState(null);
|
|
854
|
+
var notInstalled = !auth?.installed;
|
|
855
|
+
var guide = auth?.installGuide;
|
|
856
|
+
var defaultCmd = notInstalled
|
|
857
|
+
? (guide?.command || "winget install --id GitHub.cli")
|
|
858
|
+
: "gh auth login";
|
|
859
|
+
var copyCmd = (cmd) => {
|
|
860
|
+
try {
|
|
861
|
+
if (navigator && navigator.clipboard && navigator.clipboard.writeText) {
|
|
862
|
+
navigator.clipboard.writeText(cmd);
|
|
863
|
+
}
|
|
864
|
+
else {
|
|
865
|
+
var input = document.createElement("textarea");
|
|
866
|
+
input.value = cmd;
|
|
867
|
+
document.body.appendChild(input);
|
|
868
|
+
input.select();
|
|
869
|
+
document.execCommand("copy");
|
|
870
|
+
document.body.removeChild(input);
|
|
871
|
+
}
|
|
872
|
+
setCopied(true);
|
|
873
|
+
setTimeout(() => setCopied(false), 2000);
|
|
874
|
+
}
|
|
875
|
+
catch (e) {
|
|
876
|
+
console.warn("复制失败:", e);
|
|
877
|
+
}
|
|
878
|
+
};
|
|
879
|
+
var launchTerminal = async (cmd) => {
|
|
880
|
+
setLaunching(true);
|
|
881
|
+
setToastMsg(null);
|
|
882
|
+
try {
|
|
883
|
+
var res = await fetch("/api/github/action", {
|
|
884
|
+
method: "POST",
|
|
885
|
+
headers: { "Content-Type": "application/json" },
|
|
886
|
+
body: JSON.stringify({ action: "open_terminal", command: cmd })
|
|
887
|
+
});
|
|
888
|
+
var json = await res.json();
|
|
889
|
+
if (json.ok) {
|
|
890
|
+
setToastMsg("已唤起系统终端,请在弹出窗口中完成操作");
|
|
891
|
+
setTimeout(() => setToastMsg(null), 4000);
|
|
892
|
+
}
|
|
893
|
+
else {
|
|
894
|
+
setToastMsg(json.message || "唤起失败,请在终端手动运行");
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
catch (e) {
|
|
898
|
+
setToastMsg("无法连接后台服务,请在终端手动运行");
|
|
899
|
+
}
|
|
900
|
+
finally {
|
|
901
|
+
setLaunching(false);
|
|
902
|
+
}
|
|
903
|
+
};
|
|
904
|
+
var openDownload = async () => {
|
|
905
|
+
var url = guide?.downloadUrl || "https://cli.github.com/";
|
|
906
|
+
try {
|
|
907
|
+
await fetch("/api/github/action", {
|
|
908
|
+
method: "POST",
|
|
909
|
+
headers: { "Content-Type": "application/json" },
|
|
910
|
+
body: JSON.stringify({ action: "open_browser", url })
|
|
911
|
+
});
|
|
912
|
+
}
|
|
913
|
+
catch (e) {
|
|
914
|
+
window.open(url, "_blank", "noopener,noreferrer");
|
|
915
|
+
}
|
|
916
|
+
};
|
|
917
|
+
var h = React.createElement;
|
|
918
|
+
return h("div", {
|
|
919
|
+
className: "dsh-github-guide-card " + (notInstalled ? "danger" : "warning"),
|
|
920
|
+
style: isRightbar ? { padding: "12px", marginBottom: "12px" } : undefined
|
|
921
|
+
},
|
|
922
|
+
// 头部
|
|
923
|
+
h("div", { className: "dsh-github-guide-header" }, notInstalled ? "⚠️ 未检测到 GitHub CLI (gh)" : "🔑 GitHub 账号尚未登录", h("span", { className: "dsh-github-badge " + (notInstalled ? "dsh-badge-red" : "dsh-badge-yellow") }, notInstalled ? "未安装" : "未认证")),
|
|
924
|
+
// 描述
|
|
925
|
+
h("div", { className: "dsh-github-guide-desc" }, notInstalled
|
|
926
|
+
? (guide?.description || "DSH GitHub Flow 插件依赖官方 GitHub CLI 工具与云端进行安全交互,当前系统 PATH 中未检测到该工具。")
|
|
927
|
+
: "检测到本机已安装 GitHub CLI,请完成账号授权以解锁仓库管理、PR 审查和 Issues 待办。"),
|
|
928
|
+
// 命令代码展示框
|
|
929
|
+
h("div", { className: "dsh-github-cmd-box" }, h("code", null, defaultCmd), h("button", {
|
|
930
|
+
className: "dsh-github-copy-btn " + (copied ? "copied" : ""),
|
|
931
|
+
onClick: () => copyCmd(defaultCmd),
|
|
932
|
+
title: "复制命令到剪贴板"
|
|
933
|
+
}, copied ? "✓ 已复制" : "📋 复制命令")),
|
|
934
|
+
// 步骤提示
|
|
935
|
+
!notInstalled && !isRightbar
|
|
936
|
+
? 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, "按回车打开浏览器确认授权后,切回本页面即可自动恢复。"))
|
|
937
|
+
: null,
|
|
938
|
+
// 操作按钮区域
|
|
939
|
+
h("div", { className: "dsh-github-guide-actions" }, h("button", {
|
|
940
|
+
className: "dsh-github-action-btn",
|
|
941
|
+
onClick: () => launchTerminal(defaultCmd),
|
|
942
|
+
disabled: launching,
|
|
943
|
+
title: "自动唤起系统终端并执行该命令"
|
|
944
|
+
}, launching ? "正在唤起..." : (notInstalled ? "💻 唤起终端安装" : "💻 唤起终端登录")), notInstalled
|
|
945
|
+
? h("button", {
|
|
946
|
+
className: "dsh-github-action-btn",
|
|
947
|
+
onClick: openDownload,
|
|
948
|
+
title: "打开 GitHub CLI 官方下载主页获取安装包"
|
|
949
|
+
}, "🌐 官网安装包 (.msi/.pkg)")
|
|
950
|
+
: null, h("button", {
|
|
951
|
+
className: "dsh-github-action-btn",
|
|
952
|
+
onClick: onRefresh,
|
|
953
|
+
title: "重新检测登录与安装状态"
|
|
954
|
+
}, "🔄 刷新状态")), toastMsg
|
|
955
|
+
? h("div", { style: { fontSize: "12px", color: "var(--dsw-alias-link, #0969da)", marginTop: "8px" } }, `ℹ️ ${toastMsg}`)
|
|
956
|
+
: null, h("div", { className: "dsh-github-guide-tip" }, notInstalled
|
|
957
|
+
? "💡 提示:使用包管理器安装完成后,若未立即识别,可重启 DeepSeek Harness 应用刷新系统环境变量 PATH。"
|
|
958
|
+
: "💡 提示:凭证由官方 GitHub CLI 加密保存在操作系统安全凭据库中,授权完毕切回本窗口将自动识别刷新。"));
|
|
959
|
+
}
|
|
675
960
|
// 渲染 GitHub 仓库信息与操作视图的核心函数
|
|
676
961
|
function renderGithubRepoView(h, data, loading, error, onRefresh, isRightbar = false) {
|
|
677
962
|
var auth = data ? data.auth : null;
|
|
678
963
|
var repo = data ? data.repo : null;
|
|
679
964
|
var prs = (data && data.pullRequests) || [];
|
|
965
|
+
var issues = (data && data.issues) || [];
|
|
680
966
|
var runs = (data && data.runs) || [];
|
|
681
967
|
var headerEl = h("div", { className: "dsh-github-header" }, h("div", { className: "dsh-github-title" }, renderOctocatBadge(isRightbar ? 26 : 30), h("h2", null, isRightbar ? "GitHub 仓库" : "GitHub 工作台")), h("button", {
|
|
682
968
|
className: "dsh-github-refresh-btn",
|
|
@@ -725,7 +1011,17 @@ body[data-ds-dark-theme] .dsh-github-subheading {
|
|
|
725
1011
|
}
|
|
726
1012
|
},
|
|
727
1013
|
}, "🚀 快速创建 PR"),
|
|
728
|
-
// 4.
|
|
1014
|
+
// 4. 查看所有 Issues (官方 Issues 列表直达)
|
|
1015
|
+
h("button", {
|
|
1016
|
+
className: "dsh-github-action-btn",
|
|
1017
|
+
title: "在系统默认浏览器中查看当前仓库所有 Issues",
|
|
1018
|
+
onClick: () => {
|
|
1019
|
+
if (repo?.url) {
|
|
1020
|
+
window.open(`${repo.url}/issues`, "_blank", "noopener,noreferrer");
|
|
1021
|
+
}
|
|
1022
|
+
},
|
|
1023
|
+
}, "📋 查看所有 Issues"),
|
|
1024
|
+
// 5. 📝 新建 Issue (官方 Issue 模板页直达)
|
|
729
1025
|
h("button", {
|
|
730
1026
|
className: "dsh-github-action-btn",
|
|
731
1027
|
title: "在系统默认浏览器中打开 GitHub 官方新建 Issue 页面",
|
|
@@ -741,6 +1037,33 @@ body[data-ds-dark-theme] .dsh-github-subheading {
|
|
|
741
1037
|
: h("div", { className: "dsh-github-list" }, prs.map((pr) => h("div", { key: pr.number, className: "dsh-github-item" }, h("a", { className: "dsh-github-item-title", href: pr.url, target: "_blank" }, `#${pr.number} ${pr.title}`), h("div", { className: "dsh-github-item-meta" }, h("span", null, `${pr.headRefName} → ${pr.baseRefName}`), pr.mergeable === "CONFLICTING"
|
|
742
1038
|
? h("span", { className: "dsh-github-badge dsh-badge-red" }, "代码冲突")
|
|
743
1039
|
: h("span", { className: "dsh-github-badge dsh-badge-green" }, "可合并"))))));
|
|
1040
|
+
// 仓库 Issues 列表
|
|
1041
|
+
var issueSectionEl = h("div", { className: "dsh-github-section" }, h("div", { className: "dsh-github-section-header" }, h("h3", null, `📋 仓库 Issues (${issues.length})`), repo?.url
|
|
1042
|
+
? h("a", {
|
|
1043
|
+
href: `${repo.url}/issues`,
|
|
1044
|
+
target: "_blank",
|
|
1045
|
+
style: { fontSize: "11px", color: "var(--dsw-alias-link, #0969da)", textDecoration: "none" },
|
|
1046
|
+
}, "全部 ↗")
|
|
1047
|
+
: null), issues.length === 0
|
|
1048
|
+
? h("div", { className: "dsh-github-empty" }, "当前无开放中的 Issue")
|
|
1049
|
+
: h("div", { className: "dsh-github-list" }, issues.map((issue) => {
|
|
1050
|
+
var cats = issue.categories || [];
|
|
1051
|
+
var badges = [];
|
|
1052
|
+
if (cats.includes("reported")) {
|
|
1053
|
+
badges.push(h("span", { key: "rep", className: "dsh-github-badge dsh-badge-purple" }, "用户反馈"));
|
|
1054
|
+
}
|
|
1055
|
+
if (cats.includes("assigned")) {
|
|
1056
|
+
badges.push(h("span", { key: "asn", className: "dsh-github-badge dsh-badge-blue" }, "已分配"));
|
|
1057
|
+
}
|
|
1058
|
+
if (cats.includes("created")) {
|
|
1059
|
+
badges.push(h("span", { key: "crt", className: "dsh-github-badge dsh-badge-green" }, "我发起的"));
|
|
1060
|
+
}
|
|
1061
|
+
return h("div", { key: issue.number, className: "dsh-github-item" }, h("div", { style: { display: "flex", alignItems: "center", gap: "6px", flexWrap: "wrap" } }, h("a", { className: "dsh-github-item-title", href: issue.url, target: "_blank" }, `#${issue.number} ${issue.title}`), ...badges), h("div", { className: "dsh-github-item-meta" }, h("span", null, `由 ${issue.author?.login || "未知"} 提出`), issue.assignees && issue.assignees.length > 0
|
|
1062
|
+
? h("span", null, `指派: ${issue.assignees.map((a) => a.login).join(", ")}`)
|
|
1063
|
+
: null, issue.labels && issue.labels.length > 0
|
|
1064
|
+
? issue.labels.map((lbl) => h("span", { key: lbl.name, className: "dsh-github-badge dsh-badge-yellow" }, lbl.name))
|
|
1065
|
+
: null));
|
|
1066
|
+
})));
|
|
744
1067
|
// Actions 流水线
|
|
745
1068
|
var runSectionEl = h("div", { className: "dsh-github-section" }, h("div", { className: "dsh-github-section-header" }, h("h3", null, `⚡ 最近 Actions 流水线 (${runs.length})`)), runs.length === 0
|
|
746
1069
|
? h("div", { className: "dsh-github-empty" }, "暂无工作流记录")
|
|
@@ -749,7 +1072,10 @@ body[data-ds-dark-theme] .dsh-github-subheading {
|
|
|
749
1072
|
: r.conclusion === "failure"
|
|
750
1073
|
? h("span", { className: "dsh-github-badge dsh-badge-red" }, "✕ 失败")
|
|
751
1074
|
: h("span", { className: "dsh-github-badge dsh-badge-yellow" }, r.status))))));
|
|
752
|
-
|
|
1075
|
+
var authGuideEl = !auth?.loggedIn
|
|
1076
|
+
? h(AuthGuideCard, { auth, onRefresh, isRightbar })
|
|
1077
|
+
: null;
|
|
1078
|
+
return [headerEl, authGuideEl, repoCardEl, actionsBarEl, prSectionEl, issueSectionEl, runSectionEl].filter(Boolean);
|
|
753
1079
|
}
|
|
754
1080
|
// 1. 右侧栏专属视图 (Right Sidebar Tab Body)
|
|
755
1081
|
function GithubRightbarBody(props) {
|
|
@@ -806,6 +1132,16 @@ body[data-ds-dark-theme] .dsh-github-subheading {
|
|
|
806
1132
|
React.useEffect(() => {
|
|
807
1133
|
loadData(false);
|
|
808
1134
|
}, [loadData]);
|
|
1135
|
+
// 窗口切回自动探测自愈
|
|
1136
|
+
React.useEffect(() => {
|
|
1137
|
+
var onFocus = () => {
|
|
1138
|
+
if (!data?.auth?.loggedIn) {
|
|
1139
|
+
loadData(false);
|
|
1140
|
+
}
|
|
1141
|
+
};
|
|
1142
|
+
window.addEventListener("focus", onFocus);
|
|
1143
|
+
return () => window.removeEventListener("focus", onFocus);
|
|
1144
|
+
}, [data, loadData]);
|
|
809
1145
|
var h = React.createElement;
|
|
810
1146
|
return h("div", { className: "dsh-github-rightbar-container" }, ...renderGithubRepoView(h, data, loading, error, () => loadData(true), true));
|
|
811
1147
|
}
|
|
@@ -834,6 +1170,7 @@ body[data-ds-dark-theme] .dsh-github-subheading {
|
|
|
834
1170
|
var [error, setError] = React.useState(null);
|
|
835
1171
|
var [activeTab, setActiveTab] = React.useState("workspaces"); // 'workspaces' | 'repos' | 'mywork'
|
|
836
1172
|
var [searchQuery, setSearchQuery] = React.useState("");
|
|
1173
|
+
var [issueFilter, setIssueFilter] = React.useState("all"); // 'all' | 'reported' | 'assigned' | 'created'
|
|
837
1174
|
var loadData = React.useCallback(async (forceRefresh = false) => {
|
|
838
1175
|
setLoading(true);
|
|
839
1176
|
setError(null);
|
|
@@ -878,6 +1215,16 @@ body[data-ds-dark-theme] .dsh-github-subheading {
|
|
|
878
1215
|
}
|
|
879
1216
|
}, []);
|
|
880
1217
|
React.useEffect(() => { loadData(false); }, [loadData]);
|
|
1218
|
+
// 窗口切回自动探测自愈
|
|
1219
|
+
React.useEffect(() => {
|
|
1220
|
+
var onFocus = () => {
|
|
1221
|
+
if (!data?.auth?.loggedIn) {
|
|
1222
|
+
loadData(false);
|
|
1223
|
+
}
|
|
1224
|
+
};
|
|
1225
|
+
window.addEventListener("focus", onFocus);
|
|
1226
|
+
return () => window.removeEventListener("focus", onFocus);
|
|
1227
|
+
}, [data, loadData]);
|
|
881
1228
|
var h = React.createElement;
|
|
882
1229
|
var headerEl = h("div", { className: "dsh-github-header" }, h("div", { className: "dsh-github-title" }, renderOctocatBadge(32), h("h2", null, "GitHub 全景驾驶舱")), h("button", {
|
|
883
1230
|
className: "dsh-github-refresh-btn",
|
|
@@ -894,9 +1241,21 @@ body[data-ds-dark-theme] .dsh-github-subheading {
|
|
|
894
1241
|
var myIssues = (data && data.myIssues) || [];
|
|
895
1242
|
var errorEl = error ? h("div", { style: { color: "#f85149", background: "rgba(248,81,73,0.1)", border: "1px solid rgba(248,81,73,0.3)", padding: "8px 12px", borderRadius: "6px", marginBottom: "16px", fontSize: "12px" } }, `⚠️ 加载失败: ${error}`) : null;
|
|
896
1243
|
// 顶部统计卡片
|
|
897
|
-
var statsCardsEl = h("div", { className: "dsh-github-overview-cards" }, h("div", { className: "dsh-github-card" }, h("div", { className: "dsh-github-card-title" }, "CLI 认证账号"), h("div", { className: "dsh-github-card-value" }, auth?.loggedIn
|
|
1244
|
+
var statsCardsEl = h("div", { className: "dsh-github-overview-cards" }, h("div", { className: "dsh-github-card" }, h("div", { className: "dsh-github-card-title" }, "CLI 认证账号"), h("div", { className: "dsh-github-card-value" }, auth?.loggedIn
|
|
1245
|
+
? `👤 ${auth.user}`
|
|
1246
|
+
: !auth?.installed
|
|
1247
|
+
? "❌ 未安装 CLI"
|
|
1248
|
+
: "⚠️ 未登录", auth?.loggedIn
|
|
1249
|
+
? h("span", { className: "dsh-github-badge dsh-badge-green" }, "Active")
|
|
1250
|
+
: !auth?.installed
|
|
1251
|
+
? h("span", { className: "dsh-github-badge dsh-badge-red" }, "Missing")
|
|
1252
|
+
: h("span", { className: "dsh-github-badge dsh-badge-yellow" }, "Required"))), h("div", { className: "dsh-github-card" }, h("div", { className: "dsh-github-card-title" }, "账号云端仓库"), h("div", { className: "dsh-github-card-value" }, `${userRepos.length} 个 Repositories`)), h("div", { className: "dsh-github-card" }, h("div", { className: "dsh-github-card-title" }, "本地工作区联动"), h("div", { className: "dsh-github-card-value" }, `${workspaceMatrix.length} 个工作区 (${workspaceMatrix.filter((w) => w.repo).length} 个已关联)`)));
|
|
1253
|
+
// 安装与登录引导组件(未登录或未安装时显式展开)
|
|
1254
|
+
var authGuideEl = !auth?.loggedIn
|
|
1255
|
+
? h(AuthGuideCard, { auth, onRefresh: () => loadData(true), isRightbar: false })
|
|
1256
|
+
: null;
|
|
898
1257
|
// Tab 栏
|
|
899
|
-
var tabsEl = h("div", { className: "dsh-github-tabs" }, h("button", { className: `dsh-github-tab-btn ${activeTab === 'workspaces' ? 'active' : ''}`, onClick: () => setActiveTab('workspaces') }, `📂 本地工作区矩阵 (${workspaceMatrix.length})`), h("button", { className: `dsh-github-tab-btn ${activeTab === 'repos' ? 'active' : ''}`, onClick: () => setActiveTab('repos') }, `☁️ 我的 GitHub 仓库 (${userRepos.length})`), h("button", { className: `dsh-github-tab-btn ${activeTab === 'mywork' ? 'active' : ''}`, onClick: () => setActiveTab('mywork') }, `📋
|
|
1258
|
+
var tabsEl = h("div", { className: "dsh-github-tabs" }, h("button", { className: `dsh-github-tab-btn ${activeTab === 'workspaces' ? 'active' : ''}`, onClick: () => setActiveTab('workspaces') }, `📂 本地工作区矩阵 (${workspaceMatrix.length})`), h("button", { className: `dsh-github-tab-btn ${activeTab === 'repos' ? 'active' : ''}`, onClick: () => setActiveTab('repos') }, `☁️ 我的 GitHub 仓库 (${userRepos.length})`), h("button", { className: `dsh-github-tab-btn ${activeTab === 'mywork' ? 'active' : ''}`, onClick: () => setActiveTab('mywork') }, `📋 任务与待办 (PR: ${myPrs.length} · Issue: ${myIssues.length})`));
|
|
900
1259
|
// 内容区
|
|
901
1260
|
var contentEl = null;
|
|
902
1261
|
if (activeTab === 'workspaces') {
|
|
@@ -907,18 +1266,70 @@ body[data-ds-dark-theme] .dsh-github-subheading {
|
|
|
907
1266
|
: null))));
|
|
908
1267
|
}
|
|
909
1268
|
else if (activeTab === 'repos') {
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
1269
|
+
if (!auth?.loggedIn) {
|
|
1270
|
+
contentEl = h("div", { className: "dsh-github-empty" }, "当前尚未认证登录 GitHub 账号,无法读取云端仓库列表。请先完成上方的安装或登录指引。");
|
|
1271
|
+
}
|
|
1272
|
+
else {
|
|
1273
|
+
var filteredRepos = userRepos.filter((r) => !searchQuery || r.nameWithOwner.toLowerCase().includes(searchQuery.toLowerCase()) || r.description?.toLowerCase().includes(searchQuery.toLowerCase()));
|
|
1274
|
+
contentEl = h("div", null, h("input", {
|
|
1275
|
+
className: "dsh-github-search-input",
|
|
1276
|
+
placeholder: "🔍 搜索我的 GitHub 仓库...",
|
|
1277
|
+
value: searchQuery,
|
|
1278
|
+
onChange: (e) => setSearchQuery(e.target.value)
|
|
1279
|
+
}), h("div", { className: "dsh-github-list" }, filteredRepos.map((r) => h("div", { key: r.nameWithOwner, className: "dsh-github-item" }, h("a", { className: "dsh-github-item-title", href: r.url, target: "_blank" }, r.nameWithOwner), r.description ? h("div", { className: "dsh-github-item-desc" }, r.description) : null, h("div", { className: "dsh-github-item-meta" }, h("span", null, `默认分支: ${r.defaultBranch}`), r.isPrivate ? h("span", { className: "dsh-github-badge dsh-badge-yellow" }, "Private") : h("span", { className: "dsh-github-badge dsh-badge-green" }, "Public"), h("span", null, `⭐ ${r.stargazerCount}`))))));
|
|
1280
|
+
}
|
|
917
1281
|
}
|
|
918
1282
|
else {
|
|
919
|
-
|
|
1283
|
+
if (!auth?.loggedIn) {
|
|
1284
|
+
contentEl = h("div", { className: "dsh-github-empty" }, "当前尚未认证登录 GitHub 账号,无法读取个人待办 PR 与 Issues。请先完成上方的安装或登录指引。");
|
|
1285
|
+
}
|
|
1286
|
+
else {
|
|
1287
|
+
var issueStats = (data && data.issueStats) || {
|
|
1288
|
+
total: myIssues.length,
|
|
1289
|
+
reported: myIssues.filter((i) => (i.categories || []).includes('reported')).length,
|
|
1290
|
+
assigned: myIssues.filter((i) => (i.categories || []).includes('assigned')).length,
|
|
1291
|
+
created: myIssues.filter((i) => (i.categories || []).includes('created')).length,
|
|
1292
|
+
};
|
|
1293
|
+
var filteredIssues = myIssues.filter((is) => {
|
|
1294
|
+
if (issueFilter === 'all')
|
|
1295
|
+
return true;
|
|
1296
|
+
var cats = is.categories || [];
|
|
1297
|
+
return cats.includes(issueFilter);
|
|
1298
|
+
});
|
|
1299
|
+
var issuePillsEl = h("div", { className: "dsh-github-pills" }, h("button", {
|
|
1300
|
+
className: `dsh-github-pill-btn ${issueFilter === 'all' ? 'active' : ''}`,
|
|
1301
|
+
onClick: () => setIssueFilter('all'),
|
|
1302
|
+
}, `全部 (${issueStats.total || myIssues.length})`), h("button", {
|
|
1303
|
+
className: `dsh-github-pill-btn ${issueFilter === 'reported' ? 'active' : ''}`,
|
|
1304
|
+
onClick: () => setIssueFilter('reported'),
|
|
1305
|
+
}, `📥 用户提起的 (${issueStats.reported || 0})`), h("button", {
|
|
1306
|
+
className: `dsh-github-pill-btn ${issueFilter === 'assigned' ? 'active' : ''}`,
|
|
1307
|
+
onClick: () => setIssueFilter('assigned'),
|
|
1308
|
+
}, `🎯 分配给我的 (${issueStats.assigned || 0})`), h("button", {
|
|
1309
|
+
className: `dsh-github-pill-btn ${issueFilter === 'created' ? 'active' : ''}`,
|
|
1310
|
+
onClick: () => setIssueFilter('created'),
|
|
1311
|
+
}, `✍️ 我创建的 (${issueStats.created || 0})`));
|
|
1312
|
+
contentEl = h("div", null, h("h3", { className: "dsh-github-subheading" }, `🔀 我发起的 PR (${myPrs.length})`), myPrs.length === 0 ? h("div", { className: "dsh-github-empty", style: { marginBottom: "16px" } }, "暂无开放中的 PR") : h("div", { className: "dsh-github-list", style: { marginBottom: "16px" } }, myPrs.map((pr) => h("div", { key: pr.number, className: "dsh-github-item" }, h("a", { className: "dsh-github-item-title", href: pr.url, target: "_blank" }, `[${pr.repository?.nameWithOwner || 'Repo'}] #${pr.number} ${pr.title}`)))), h("h3", { className: "dsh-github-subheading" }, `📝 任务与待办 Issues (${filteredIssues.length})`), issuePillsEl, filteredIssues.length === 0 ? h("div", { className: "dsh-github-empty" }, "当前分类下暂无开放中的 Issue") : h("div", { className: "dsh-github-list" }, filteredIssues.map((is) => {
|
|
1313
|
+
var cats = is.categories || [];
|
|
1314
|
+
var badges = [];
|
|
1315
|
+
if (cats.includes("reported")) {
|
|
1316
|
+
badges.push(h("span", { key: "rep", className: "dsh-github-badge dsh-badge-purple" }, "用户提单"));
|
|
1317
|
+
}
|
|
1318
|
+
if (cats.includes("assigned")) {
|
|
1319
|
+
badges.push(h("span", { key: "asn", className: "dsh-github-badge dsh-badge-blue" }, "分配待办"));
|
|
1320
|
+
}
|
|
1321
|
+
if (cats.includes("created")) {
|
|
1322
|
+
badges.push(h("span", { key: "crt", className: "dsh-github-badge dsh-badge-green" }, "我发起的"));
|
|
1323
|
+
}
|
|
1324
|
+
return h("div", { key: is.url || is.number, className: "dsh-github-item" }, h("div", { style: { display: "flex", alignItems: "center", gap: "6px", flexWrap: "wrap" } }, h("a", { className: "dsh-github-item-title", href: is.url, target: "_blank" }, `[${is.repository?.nameWithOwner || 'Repo'}] #${is.number} ${is.title}`), ...badges), h("div", { className: "dsh-github-item-meta" }, is.author ? h("span", null, `由 @${is.author.login} 提出`) : null, is.assignees && is.assignees.length > 0
|
|
1325
|
+
? h("span", null, `指派: ${is.assignees.map((a) => '@' + a.login).join(', ')}`)
|
|
1326
|
+
: null, is.labels && is.labels.length > 0
|
|
1327
|
+
? is.labels.map((lbl) => h("span", { key: lbl.name, className: "dsh-github-badge dsh-badge-yellow" }, lbl.name))
|
|
1328
|
+
: null, is.updatedAt ? h("span", null, `更新于: ${new Date(is.updatedAt).toLocaleDateString()}`) : null));
|
|
1329
|
+
})));
|
|
1330
|
+
}
|
|
920
1331
|
}
|
|
921
|
-
return h("div", { className: "dsh-github-panel" }, headerEl, errorEl, statsCardsEl, tabsEl, contentEl);
|
|
1332
|
+
return h("div", { className: "dsh-github-panel" }, headerEl, errorEl, statsCardsEl, authGuideEl, tabsEl, contentEl);
|
|
922
1333
|
}
|
|
923
1334
|
var inject = ["slots", "sidebarRightTabs", "sessions", "layout", "theme"];
|
|
924
1335
|
function apply(ctx) {
|
package/lib/executor.d.ts
CHANGED
|
@@ -21,11 +21,12 @@ export declare class GhExecutor {
|
|
|
21
21
|
/**
|
|
22
22
|
* 智能解析最可靠的工作区物理路径:
|
|
23
23
|
* 1. 优先使用显式指定的有效 cwd(若包含 .git 目录)
|
|
24
|
-
* 2.
|
|
25
|
-
* 3.
|
|
26
|
-
* 4.
|
|
24
|
+
* 2. 使用显式传入的 sessionId 或环境变量 DSH_SESSION_ID 精确反查工作区
|
|
25
|
+
* 3. 递归探测:若传入了 explicitCwd(如聚合父目录),自动检查其直系子目录中是否包含 Git 仓库
|
|
26
|
+
* 4. 匹配 ~/.dsh/storages/workspace.json 中最近活跃且存在 .git 的仓库工作区
|
|
27
|
+
* 5. 回退到 process.cwd()
|
|
27
28
|
*/
|
|
28
|
-
resolveWorkspaceCwd(explicitCwd?: string): string;
|
|
29
|
+
resolveWorkspaceCwd(explicitCwd?: string, explicitSessionId?: string): string;
|
|
29
30
|
/**
|
|
30
31
|
* 安全执行 gh 命令
|
|
31
32
|
* 采用 execFile 参数数组隔离,彻底杜绝 Shell 字符串拼接注入漏洞
|
|
@@ -39,6 +40,8 @@ export declare class GhExecutor {
|
|
|
39
40
|
* 而 Web 面板每次挂载都会来问一次,重复执行实测要 5.4 秒,属于纯浪费。
|
|
40
41
|
*/
|
|
41
42
|
checkAuth(cwd?: string, bypassCache?: boolean): Promise<AuthStatus>;
|
|
43
|
+
/** 生成当前操作系统平台的推荐安装引导与命令 */
|
|
44
|
+
private getPlatformInstallGuide;
|
|
42
45
|
/** 实际执行 `gh auth status` 并解析结果,不含缓存逻辑 */
|
|
43
46
|
private probeAuth;
|
|
44
47
|
/**
|
|
@@ -55,5 +58,5 @@ export declare class GhExecutor {
|
|
|
55
58
|
* 获取当前目录(工作区)关联的远程仓库元数据
|
|
56
59
|
* 采用 gh repo view + 本地 git remote 双保险机制,彻底杜绝已配置远程却误判未关联的问题
|
|
57
60
|
*/
|
|
58
|
-
getRepoMetadata(cwd?: string): Promise<RepoMetadata | null>;
|
|
61
|
+
getRepoMetadata(cwd?: string, sessionId?: string): Promise<RepoMetadata | null>;
|
|
59
62
|
}
|