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.
- package/README.en.md +287 -143
- package/README.md +270 -125
- package/docs/UPGRADE-NOTES.md +12 -9
- package/docs/architecture.md +126 -126
- package/lib/api/routes-actions.js +249 -0
- package/lib/api/routes-overview.js +94 -2
- package/lib/cache.d.ts +4 -0
- package/lib/cache.js +14 -0
- package/lib/client.d.ts +14 -1
- package/lib/client.js +4287 -2500
- package/lib/commands/gh.d.ts +6 -1
- package/lib/commands/gh.js +144 -71
- package/lib/executor/git-parser.d.ts +57 -0
- package/lib/executor/git-parser.js +255 -0
- package/lib/executor/platform-guide.d.ts +14 -0
- package/lib/executor/platform-guide.js +40 -0
- package/lib/executor/process-utils.d.ts +51 -0
- package/lib/executor/process-utils.js +162 -0
- package/lib/executor/version-utils.d.ts +12 -0
- package/lib/executor/version-utils.js +27 -0
- package/lib/executor.d.ts +70 -48
- package/lib/executor.js +371 -356
- package/lib/git-watcher.d.ts +36 -0
- package/lib/git-watcher.js +91 -0
- package/lib/main.js +37 -3
- package/lib/renderers/agent-task.d.ts +16 -0
- package/lib/renderers/agent-task.js +107 -0
- package/lib/renderers/cache.d.ts +8 -0
- package/lib/renderers/cache.js +66 -0
- package/lib/renderers/codespace.d.ts +16 -0
- package/lib/renderers/codespace.js +103 -0
- package/lib/renderers/common.d.ts +24 -0
- package/lib/renderers/common.js +88 -0
- package/lib/renderers/discussion.d.ts +16 -0
- package/lib/renderers/discussion.js +101 -0
- package/lib/renderers/gist.d.ts +15 -0
- package/lib/renderers/gist.js +99 -0
- package/lib/renderers/issue.d.ts +4 -0
- package/lib/renderers/issue.js +70 -0
- package/lib/renderers/label.d.ts +4 -0
- package/lib/renderers/label.js +48 -0
- package/lib/renderers/markdown.d.ts +19 -32
- package/lib/renderers/markdown.js +19 -624
- package/lib/renderers/pr.d.ts +4 -0
- package/lib/renderers/pr.js +107 -0
- package/lib/renderers/project.d.ts +20 -0
- package/lib/renderers/project.js +128 -0
- package/lib/renderers/release.d.ts +4 -0
- package/lib/renderers/release.js +74 -0
- package/lib/renderers/repo.d.ts +4 -0
- package/lib/renderers/repo.js +149 -0
- package/lib/renderers/ruleset.d.ts +4 -0
- package/lib/renderers/ruleset.js +74 -0
- package/lib/renderers/run.d.ts +4 -0
- package/lib/renderers/run.js +79 -0
- package/lib/renderers/skill.d.ts +34 -0
- package/lib/renderers/skill.js +241 -0
- package/lib/renderers/status.d.ts +28 -0
- package/lib/renderers/status.js +176 -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/cache.d.ts +64 -0
- package/lib/tools/cache.js +186 -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/gist.d.ts +155 -0
- package/lib/tools/gist.js +190 -0
- package/lib/tools/help.js +214 -13
- package/lib/tools/image-utils.d.ts +8 -0
- package/lib/tools/image-utils.js +34 -0
- package/lib/tools/issue.d.ts +8 -1
- package/lib/tools/issue.js +26 -4
- package/lib/tools/label.d.ts +80 -0
- package/lib/tools/label.js +237 -0
- package/lib/tools/pr.d.ts +8 -0
- package/lib/tools/pr.js +48 -3
- 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/ruleset.d.ts +80 -0
- package/lib/tools/ruleset.js +177 -0
- package/lib/tools/skill.d.ts +24 -1
- package/lib/tools/skill.js +115 -5
- package/lib/tools/status.d.ts +40 -0
- package/lib/tools/status.js +58 -0
- package/lib/types.d.ts +44 -0
- package/lib/ui/auth-guide-card.d.ts +4 -0
- package/lib/ui/auth-guide-card.js +161 -0
- package/lib/ui/branch-selector.d.ts +10 -0
- package/lib/ui/branch-selector.js +163 -0
- package/lib/ui/commit-modal.d.ts +8 -0
- package/lib/ui/commit-modal.js +219 -0
- package/lib/ui/help-modal.d.ts +15 -0
- package/lib/ui/help-modal.js +202 -0
- package/lib/ui/icons.d.ts +7 -0
- package/lib/ui/icons.js +53 -0
- package/lib/ui/network-banner.d.ts +10 -0
- package/lib/ui/network-banner.js +54 -0
- package/lib/ui/storage.d.ts +35 -0
- package/lib/ui/storage.js +158 -0
- package/lib/ui/styles.d.ts +6 -0
- package/lib/ui/styles.js +1544 -0
- package/lib/ui/sync-settings-modal.d.ts +11 -0
- package/lib/ui/sync-settings-modal.js +350 -0
- package/lib/ui/sync-status-badge.d.ts +8 -0
- package/lib/ui/sync-status-badge.js +64 -0
- package/lib/ui/upgrade-card.d.ts +7 -0
- package/lib/ui/upgrade-card.js +222 -0
- package/lib/ui/utils.d.ts +45 -0
- package/lib/ui/utils.js +226 -0
- package/lib/ui/workspace-panel.d.ts +4 -0
- package/lib/ui/workspace-panel.js +489 -0
- 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
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 全局工作区仪表盘主面板组件 (Dashboard View)
|
|
3
|
+
*/
|
|
4
|
+
export function GithubWorkspacePanel() {
|
|
5
|
+
var initialSettings = React.useMemo(() => getLocalSyncSettings(), []);
|
|
6
|
+
var initialSnapshot = React.useMemo(() => getStoredGlobalOverview(), []);
|
|
7
|
+
var [syncSettings, setSyncSettings] = React.useState(initialSettings);
|
|
8
|
+
var [data, setData] = React.useState(initialSnapshot?.data || null);
|
|
9
|
+
var [loading, setLoading] = React.useState(!initialSnapshot);
|
|
10
|
+
var [syncStatus, setSyncStatus] = React.useState(initialSnapshot ? "cached" : "loading");
|
|
11
|
+
var [lastSyncedAt, setLastSyncedAt] = React.useState(initialSnapshot?.savedAt || 0);
|
|
12
|
+
var [isSettingsModalOpen, setIsSettingsModalOpen] = React.useState(false);
|
|
13
|
+
var [settingsInitialSection, setSettingsInitialSection] = React.useState("sync");
|
|
14
|
+
var [isHelpModalOpen, setIsHelpModalOpen] = React.useState(false);
|
|
15
|
+
var [error, setError] = React.useState(null);
|
|
16
|
+
var [updateInfo, setUpdateInfo] = React.useState(null);
|
|
17
|
+
var [activeTab, setActiveTab] = React.useState("workspaces");
|
|
18
|
+
var [searchQuery, setSearchQuery] = React.useState("");
|
|
19
|
+
var [issueFilter, setIssueFilter] = React.useState("all");
|
|
20
|
+
var [toastMsg, setToastMsg] = React.useState(null);
|
|
21
|
+
var cloudTimerRef = React.useRef(null);
|
|
22
|
+
var dataRef = React.useRef(data);
|
|
23
|
+
dataRef.current = data;
|
|
24
|
+
var showToast = (msg) => {
|
|
25
|
+
setToastMsg(msg);
|
|
26
|
+
setTimeout(() => setToastMsg(null), 5000);
|
|
27
|
+
};
|
|
28
|
+
var [proxyActive, setProxyActive] = React.useState(null);
|
|
29
|
+
var refreshProxyBadge = React.useCallback(function () {
|
|
30
|
+
fetch("/api/github/proxy")
|
|
31
|
+
.then(function (r) { return r.json(); })
|
|
32
|
+
.then(function (j) {
|
|
33
|
+
if (j && j.ok && j.state && j.state.config) {
|
|
34
|
+
setProxyActive({ enabled: Boolean(j.state.config.url), url: j.state.config.url || "" });
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
setProxyActive({ enabled: false, url: "" });
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
.catch(function () { });
|
|
41
|
+
}, []);
|
|
42
|
+
React.useEffect(function () { refreshProxyBadge(); }, [refreshProxyBadge]);
|
|
43
|
+
React.useEffect(() => {
|
|
44
|
+
var timer = setTimeout(function () {
|
|
45
|
+
fetch("/api/github/check-update")
|
|
46
|
+
.then(function (res) { return res.json(); })
|
|
47
|
+
.then(function (json) {
|
|
48
|
+
if (json && json.ok && json.data) {
|
|
49
|
+
setUpdateInfo(json.data);
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
.catch(function () { });
|
|
53
|
+
}, 300);
|
|
54
|
+
return function () { clearTimeout(timer); };
|
|
55
|
+
}, []);
|
|
56
|
+
var panelRef = React.useRef(null);
|
|
57
|
+
React.useEffect(() => {
|
|
58
|
+
var onOpenAbout = () => {
|
|
59
|
+
var el = panelRef && panelRef.current;
|
|
60
|
+
if (!el)
|
|
61
|
+
return;
|
|
62
|
+
var rect = el.getBoundingClientRect();
|
|
63
|
+
if (rect.width > 0 && rect.height > 0) {
|
|
64
|
+
setSettingsInitialSection("about");
|
|
65
|
+
setIsSettingsModalOpen(true);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
var onOpenProxy = () => {
|
|
69
|
+
var el = panelRef && panelRef.current;
|
|
70
|
+
if (!el)
|
|
71
|
+
return;
|
|
72
|
+
var rect = el.getBoundingClientRect();
|
|
73
|
+
if (rect.width > 0 && rect.height > 0) {
|
|
74
|
+
setSettingsInitialSection("proxy");
|
|
75
|
+
setIsSettingsModalOpen(true);
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
window.addEventListener("dsh-github-open-about", onOpenAbout);
|
|
79
|
+
window.addEventListener("dsh-github-open-proxy", onOpenProxy);
|
|
80
|
+
return () => {
|
|
81
|
+
window.removeEventListener("dsh-github-open-about", onOpenAbout);
|
|
82
|
+
window.removeEventListener("dsh-github-open-proxy", onOpenProxy);
|
|
83
|
+
};
|
|
84
|
+
}, []);
|
|
85
|
+
var openSettingsDefault = () => {
|
|
86
|
+
setSettingsInitialSection("sync");
|
|
87
|
+
setIsSettingsModalOpen(true);
|
|
88
|
+
};
|
|
89
|
+
var loadData = React.useCallback(async (forceRefresh = false) => {
|
|
90
|
+
if (!forceRefresh && syncSettings.strategy === "manual" && dataRef.current) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (forceRefresh || !dataRef.current) {
|
|
94
|
+
setLoading(true);
|
|
95
|
+
}
|
|
96
|
+
setSyncStatus(dataRef.current ? "syncing" : "loading");
|
|
97
|
+
setError(null);
|
|
98
|
+
var controller = new AbortController();
|
|
99
|
+
var timedOut = false;
|
|
100
|
+
var timer = setTimeout(function () { timedOut = true; controller.abort(); }, 45000);
|
|
101
|
+
try {
|
|
102
|
+
if (forceRefresh)
|
|
103
|
+
await fetch("/api/github/refresh", { method: "POST", signal: controller.signal }).catch(() => { });
|
|
104
|
+
var url = "/api/github/global-overview";
|
|
105
|
+
if (forceRefresh) {
|
|
106
|
+
url += "?force=true";
|
|
107
|
+
}
|
|
108
|
+
// 接入 1s/2s/4s 阶梯退避重试,平滑吸收代理节点与网络的偶发抖动断流
|
|
109
|
+
var { res, json } = await fetchWithRetry(url, {}, {
|
|
110
|
+
signal: controller.signal,
|
|
111
|
+
maxRetries: 3,
|
|
112
|
+
baseDelayMs: 1000,
|
|
113
|
+
onRetry: (attempt) => {
|
|
114
|
+
setSyncStatus("syncing");
|
|
115
|
+
setError(`网络抖动,正在自愈重试 (${attempt}/3)...`);
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
if (!res.ok) {
|
|
119
|
+
var errText = (typeof json === "string" ? json : JSON.stringify(json)) || res.statusText;
|
|
120
|
+
var failMsg = `获取全局数据失败(HTTP ${res.status})${errText ? ": " + errText : ""}`;
|
|
121
|
+
setSyncStatus("failed");
|
|
122
|
+
setError(failMsg);
|
|
123
|
+
if (forceRefresh)
|
|
124
|
+
showToast("❌ 刷新失败:" + failMsg);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (json.ok && json.data) {
|
|
128
|
+
var isFail = Boolean(json.partialFailure ||
|
|
129
|
+
json.data.partialFailure ||
|
|
130
|
+
json.data.networkError ||
|
|
131
|
+
json.data.auth?.networkError ||
|
|
132
|
+
json.error);
|
|
133
|
+
var failReason = String(json.error ||
|
|
134
|
+
json.fetchError ||
|
|
135
|
+
json.data.networkErrorReason ||
|
|
136
|
+
json.data.auth?.networkErrorReason ||
|
|
137
|
+
"拉取全局数据失败");
|
|
138
|
+
if (isFail) {
|
|
139
|
+
setSyncStatus("failed");
|
|
140
|
+
setError(failReason);
|
|
141
|
+
var curData = dataRef.current;
|
|
142
|
+
if (curData && (curData.userRepos?.length > 0 || curData.myPrs?.length > 0 || curData.myIssues?.length > 0)) {
|
|
143
|
+
if (json.data.userRepos?.length > 0 || json.data.myPrs?.length > 0) {
|
|
144
|
+
setData(json.data);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
setData(json.data);
|
|
149
|
+
}
|
|
150
|
+
if (forceRefresh)
|
|
151
|
+
showToast("❌ 刷新失败:" + failReason);
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
setData(json.data);
|
|
155
|
+
saveStoredGlobalOverview(json.data);
|
|
156
|
+
var syncTs = json.fromCache && json.data.lastUpdated
|
|
157
|
+
? (Date.parse(json.data.lastUpdated) || Date.now())
|
|
158
|
+
: Date.now();
|
|
159
|
+
setLastSyncedAt(syncTs);
|
|
160
|
+
setSyncStatus(json.fromCache ? "cached" : "fresh");
|
|
161
|
+
setError(null);
|
|
162
|
+
if (forceRefresh)
|
|
163
|
+
showToast("✅ 刷新成功,已同步最新数据");
|
|
164
|
+
}
|
|
165
|
+
if (json.data.updateInfo) {
|
|
166
|
+
setUpdateInfo(json.data.updateInfo);
|
|
167
|
+
}
|
|
168
|
+
if (json.data.workspaceError) {
|
|
169
|
+
setError("工作区列表读取失败:" + json.data.workspaceError);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
setSyncStatus("failed");
|
|
174
|
+
var errPayload = String(json?.error || "获取全局数据失败");
|
|
175
|
+
setError(errPayload);
|
|
176
|
+
if (forceRefresh)
|
|
177
|
+
showToast("❌ 刷新失败:" + errPayload);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
catch (err) {
|
|
181
|
+
setSyncStatus("failed");
|
|
182
|
+
var failReason = (timedOut || err.name === "AbortError")
|
|
183
|
+
? "获取超时(45 秒):本机 gh 命令响应过慢或网络代理劫持了回环请求。可稍后重试,或在「⚙️ 设置 → 🌐 网络代理」确认代理已放行 127.0.0.1。"
|
|
184
|
+
: ("无法连接后端服务:" + (err.message || err));
|
|
185
|
+
setError(failReason);
|
|
186
|
+
if (forceRefresh)
|
|
187
|
+
showToast("❌ 刷新失败:" + failReason);
|
|
188
|
+
}
|
|
189
|
+
finally {
|
|
190
|
+
clearTimeout(timer);
|
|
191
|
+
setLoading(false);
|
|
192
|
+
if (syncSettings.strategy === "auto") {
|
|
193
|
+
scheduleNextCloudSync();
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}, [syncSettings.strategy]);
|
|
197
|
+
// 云端定时自动同步:拉取结算后才启动计时器,倒计时到期后再执行下一次,并做息屏避让
|
|
198
|
+
var scheduleNextCloudSync = React.useCallback(() => {
|
|
199
|
+
if (cloudTimerRef.current)
|
|
200
|
+
clearTimeout(cloudTimerRef.current);
|
|
201
|
+
if (syncSettings.strategy !== "auto")
|
|
202
|
+
return;
|
|
203
|
+
var interval = Math.max(300000, Number(syncSettings.cloudSyncIntervalMs) || 600000);
|
|
204
|
+
cloudTimerRef.current = setTimeout(() => {
|
|
205
|
+
if (typeof document !== "undefined" && document.visibilityState === "hidden") {
|
|
206
|
+
var onVisible = () => {
|
|
207
|
+
if (document.visibilityState === "visible") {
|
|
208
|
+
document.removeEventListener("visibilitychange", onVisible);
|
|
209
|
+
loadData(false);
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
document.addEventListener("visibilitychange", onVisible);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
loadData(false);
|
|
216
|
+
}, interval);
|
|
217
|
+
}, [syncSettings.strategy, syncSettings.cloudSyncIntervalMs, loadData]);
|
|
218
|
+
// 挂载加载调度:开启 SWR 或 开启云端定时时,首屏均立即静默拉新;
|
|
219
|
+
// 云端定时在首屏拉取结算后自动启动下一次倒计时。首页坚决不挂载任何文件监控!
|
|
220
|
+
React.useEffect(() => {
|
|
221
|
+
if (cloudTimerRef.current)
|
|
222
|
+
clearTimeout(cloudTimerRef.current);
|
|
223
|
+
if (syncSettings.strategy === "swr" || syncSettings.strategy === "auto") {
|
|
224
|
+
var timer = setTimeout(function () { loadData(false); }, 300);
|
|
225
|
+
return function () {
|
|
226
|
+
clearTimeout(timer);
|
|
227
|
+
if (cloudTimerRef.current)
|
|
228
|
+
clearTimeout(cloudTimerRef.current);
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
else if (!dataRef.current) {
|
|
232
|
+
loadData(false);
|
|
233
|
+
}
|
|
234
|
+
return function () {
|
|
235
|
+
if (cloudTimerRef.current)
|
|
236
|
+
clearTimeout(cloudTimerRef.current);
|
|
237
|
+
};
|
|
238
|
+
}, [syncSettings.strategy, syncSettings.cloudSyncIntervalMs, loadData]);
|
|
239
|
+
React.useEffect(() => {
|
|
240
|
+
var onFocus = () => {
|
|
241
|
+
if (!data?.auth?.loggedIn) {
|
|
242
|
+
fetch("/api/github/auth?force=true")
|
|
243
|
+
.then(function (res) { return res.json(); })
|
|
244
|
+
.then(function (json) {
|
|
245
|
+
if (json && json.ok && json.auth && json.auth.loggedIn) {
|
|
246
|
+
clearStoredGlobalOverview();
|
|
247
|
+
loadData(true);
|
|
248
|
+
}
|
|
249
|
+
})
|
|
250
|
+
.catch(function () { });
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
var onOnline = () => {
|
|
254
|
+
// 监听网络由断网恢复连接瞬间,自动静默发起一次全量同步,消除离线警告横幅并拉新
|
|
255
|
+
loadData(false);
|
|
256
|
+
};
|
|
257
|
+
window.addEventListener("focus", onFocus);
|
|
258
|
+
window.addEventListener("online", onOnline);
|
|
259
|
+
return () => {
|
|
260
|
+
window.removeEventListener("focus", onFocus);
|
|
261
|
+
window.removeEventListener("online", onOnline);
|
|
262
|
+
};
|
|
263
|
+
}, [data, loadData]);
|
|
264
|
+
var h = React.createElement;
|
|
265
|
+
var headerEl = h("div", { className: "dsh-github-header" }, h("div", { className: "dsh-github-title" }, renderOctocatBadge(32), h("h2", null, "GitHub 全景驾驶舱"), renderPluginBadge(h), h(SyncStatusBadge, { syncStatus, lastSyncedAt }), proxyActive && proxyActive.enabled
|
|
266
|
+
? h("span", {
|
|
267
|
+
style: {
|
|
268
|
+
display: "inline-flex",
|
|
269
|
+
alignItems: "center",
|
|
270
|
+
gap: "4px",
|
|
271
|
+
fontSize: "11px",
|
|
272
|
+
fontWeight: 500,
|
|
273
|
+
padding: "2px 8px",
|
|
274
|
+
borderRadius: "999px",
|
|
275
|
+
background: "rgba(9, 105, 218, 0.1)",
|
|
276
|
+
border: "1px solid rgba(9, 105, 218, 0.35)",
|
|
277
|
+
color: "var(--dsw-alias-link, #0969da)",
|
|
278
|
+
cursor: "default",
|
|
279
|
+
},
|
|
280
|
+
title: "插件网络代理已启用: " + proxyActive.url + "(GitHub 数据链路与工具调用经此代理;点击 ⚙️ 可修改)",
|
|
281
|
+
}, "🌐 代理")
|
|
282
|
+
: null), h("div", { style: { display: "flex", alignItems: "center", gap: "8px" } }, h("button", {
|
|
283
|
+
className: "dsh-github-refresh-btn",
|
|
284
|
+
onClick: () => loadData(true),
|
|
285
|
+
disabled: loading,
|
|
286
|
+
}, loading ? "同步中..." : "🔄 刷新全局数据"), h("button", {
|
|
287
|
+
className: "dsh-github-btn-sm",
|
|
288
|
+
onClick: () => setIsHelpModalOpen(true),
|
|
289
|
+
title: "打开使用帮助与实战手册大窗口(Esc 可退出)",
|
|
290
|
+
style: { padding: "6px 12px" },
|
|
291
|
+
}, "📖 使用指南"), h("button", {
|
|
292
|
+
className: "dsh-github-btn-sm",
|
|
293
|
+
onClick: openSettingsDefault,
|
|
294
|
+
title: "配置数据同步节奏、本地缓存、网络代理与插件信息",
|
|
295
|
+
style: { padding: "6px 12px" },
|
|
296
|
+
}, "⚙️ 设置")));
|
|
297
|
+
if (loading && !data) {
|
|
298
|
+
return h("div", { className: "dsh-github-panel", ref: panelRef }, headerEl, h("div", { className: "dsh-github-empty" }, "正在加载全局 GitHub 账号与工作区数据..."));
|
|
299
|
+
}
|
|
300
|
+
var effectiveUpdateInfo = updateInfo || data?.updateInfo;
|
|
301
|
+
var upgradeBannerEl = effectiveUpdateInfo && effectiveUpdateInfo.hasUpdate
|
|
302
|
+
? h(UpgradeNotificationCard, { updateInfo: effectiveUpdateInfo, isRightbar: false })
|
|
303
|
+
: null;
|
|
304
|
+
var settingsModalEl = h(GlobalSyncSettingsModal, {
|
|
305
|
+
isOpen: isSettingsModalOpen,
|
|
306
|
+
initialSection: settingsInitialSection,
|
|
307
|
+
onClose: () => {
|
|
308
|
+
setIsSettingsModalOpen(false);
|
|
309
|
+
refreshProxyBadge();
|
|
310
|
+
},
|
|
311
|
+
currentSettings: syncSettings,
|
|
312
|
+
onSave: (newSettings) => {
|
|
313
|
+
setSyncSettings(newSettings);
|
|
314
|
+
},
|
|
315
|
+
onClearCache: () => {
|
|
316
|
+
setSyncStatus("loading");
|
|
317
|
+
setData(null);
|
|
318
|
+
setLastSyncedAt(0);
|
|
319
|
+
},
|
|
320
|
+
});
|
|
321
|
+
if (!data && error) {
|
|
322
|
+
return h("div", { className: "dsh-github-panel", ref: panelRef }, headerEl, upgradeBannerEl, h("div", {
|
|
323
|
+
style: {
|
|
324
|
+
padding: "24px",
|
|
325
|
+
borderRadius: "8px",
|
|
326
|
+
background: "rgba(248, 81, 73, 0.08)",
|
|
327
|
+
border: "1px solid rgba(248, 81, 73, 0.3)",
|
|
328
|
+
margin: "16px 0",
|
|
329
|
+
textAlign: "center",
|
|
330
|
+
},
|
|
331
|
+
}, h("div", { style: { fontSize: "16px", fontWeight: 600, color: "#f85149", marginBottom: "8px" } }, "⚠️ 后端服务加载异常"), h("div", { style: { fontSize: "13px", color: "var(--dsw-alias-label-secondary, #656d76)", marginBottom: "16px" } }, error), h("button", {
|
|
332
|
+
className: "dsh-github-btn-sm",
|
|
333
|
+
onClick: () => loadData(true),
|
|
334
|
+
style: { padding: "6px 18px", background: "var(--dsw-alias-link, #0969da)", color: "#ffffff", borderColor: "var(--dsw-alias-link, #0969da)" },
|
|
335
|
+
}, "🔄 重新请求")), settingsModalEl);
|
|
336
|
+
}
|
|
337
|
+
var auth = data ? data.auth : null;
|
|
338
|
+
var userRepos = (data && data.userRepos) || [];
|
|
339
|
+
var workspaceMatrix = (data && data.workspaceMatrix) || [];
|
|
340
|
+
var myPrs = (data && data.myPrs) || [];
|
|
341
|
+
var myIssues = (data && data.myIssues) || [];
|
|
342
|
+
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;
|
|
343
|
+
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?.networkError
|
|
344
|
+
? (auth.user ? `👤 ${auth.user} (离线)` : "🌐 网络连接受限")
|
|
345
|
+
: auth?.loggedIn
|
|
346
|
+
? `👤 ${auth.user}`
|
|
347
|
+
: !auth?.installed
|
|
348
|
+
? "❌ 未安装 CLI"
|
|
349
|
+
: "⚠️ 未登录", auth?.networkError
|
|
350
|
+
? h("span", { className: "dsh-github-badge dsh-badge-yellow" }, "Offline")
|
|
351
|
+
: auth?.loggedIn
|
|
352
|
+
? h("span", { className: "dsh-github-badge dsh-badge-green" }, "Active")
|
|
353
|
+
: !auth?.installed
|
|
354
|
+
? h("span", { className: "dsh-github-badge dsh-badge-red" }, "Missing")
|
|
355
|
+
: 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} 个已关联)`)), h("div", { className: "dsh-github-card" }, h("div", { className: "dsh-github-card-title" }, "📥 待处理 Issues"), (data && data.issueStats && (data.issueStats.reported || data.issueStats.assigned || data.issueStats.created))
|
|
356
|
+
? h("div", { className: "dsh-github-card-value", style: { fontSize: "14px" } }, `📥 用户提单 ${data.issueStats.reported || 0} · 🎯 分配给我 ${data.issueStats.assigned || 0} · ✍️ 我创建 ${data.issueStats.created || 0}`)
|
|
357
|
+
: h("div", { className: "dsh-github-card-value" }, "无待办 ✓")));
|
|
358
|
+
var authGuideEl = (!auth?.loggedIn && !auth?.networkError && syncStatus !== "failed")
|
|
359
|
+
? h(AuthGuideCard, { auth, onRefresh: () => loadData(true), isRightbar: false })
|
|
360
|
+
: null;
|
|
361
|
+
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})`));
|
|
362
|
+
var contentEl = null;
|
|
363
|
+
if (activeTab === 'workspaces') {
|
|
364
|
+
contentEl = h("div", { className: "dsh-github-list" }, workspaceMatrix.map((ws) => h("div", { key: ws.id, className: "dsh-github-card dsh-github-workspace-card" }, h("div", { style: { display: "flex", flexDirection: "column", gap: "4px" } }, h("div", { className: "dsh-github-ws-title" }, ws.title), h("div", { className: "dsh-github-ws-path" }, ws.path), h("div", { style: { fontSize: "12px", marginTop: "4px", display: "flex", gap: "8px", alignItems: "center" } }, ws.repo
|
|
365
|
+
? h("span", { className: "dsh-github-ws-repo-link" }, renderOctocat(13, "currentColor"), `关联远程: ${ws.repo.nameWithOwner} (${ws.repo.defaultBranch})`)
|
|
366
|
+
: h("span", { className: "dsh-github-ws-path" }, ws.hasGit ? "本地有 Git,未关联 GitHub 远程" : "本地无 Git 仓库"), ws.repo ? h("span", { className: "dsh-github-badge dsh-badge-green" }, "已关联") : null), ws.gitStatus
|
|
367
|
+
? h("div", {
|
|
368
|
+
style: { fontSize: "11px", display: "flex", gap: "8px", alignItems: "center", opacity: 0.85 },
|
|
369
|
+
title: "ahead/behind 相对上次 git fetch 的快照(非实时)",
|
|
370
|
+
}, h("span", { style: { display: "inline-flex", alignItems: "center", gap: "4px" } }, renderGitIcon(12, "#1296db"), ws.gitStatus.branch), ws.gitStatus.hasUpstream
|
|
371
|
+
? h("span", null, `${ws.gitStatus.ahead > 0 ? "↑" + ws.gitStatus.ahead + " " : ""}${ws.gitStatus.behind > 0 ? "↓" + ws.gitStatus.behind : ""}${ws.gitStatus.ahead === 0 && ws.gitStatus.behind === 0 ? "✓ 同步" : ""}`)
|
|
372
|
+
: h("span", { style: { opacity: 0.7 } }, "↑? ↓?"), ws.gitStatus.dirtyCount > 0
|
|
373
|
+
? h("span", null, `${ws.gitStatus.dirtyCount} 文件未提交`)
|
|
374
|
+
: h("span", null, "干净"))
|
|
375
|
+
: null, ws.gitStatus && ws.gitStatus.dirtyFiles && ws.gitStatus.dirtyFiles.length > 0
|
|
376
|
+
? h("details", { style: { fontSize: "11px" } }, h("summary", { style: { cursor: "pointer", opacity: 0.8 } }, `未提交清单(${ws.gitStatus.dirtyFiles.length})`), h("div", { style: { padding: "4px 8px", borderRadius: "6px", background: "var(--dsw-alias-bg-module-platform, #f6f8fa)", lineHeight: "1.6", marginTop: "4px" } }, ws.gitStatus.dirtyFiles.map(function (f, i) {
|
|
377
|
+
return h("div", { key: i }, h("span", { style: { opacity: 0.7, marginRight: "6px" } }, f.status === "??" ? "??" : f.status), f.path);
|
|
378
|
+
})))
|
|
379
|
+
: null), h("div", { style: { display: "flex", gap: "8px" } }, ws.repo
|
|
380
|
+
? h("a", { className: "dsh-github-btn-sm", href: ws.repo.url, target: "_blank" }, "在 GitHub 打开")
|
|
381
|
+
: null))));
|
|
382
|
+
}
|
|
383
|
+
else if (activeTab === 'repos') {
|
|
384
|
+
if (!auth?.loggedIn) {
|
|
385
|
+
contentEl = h("div", { className: "dsh-github-empty" }, "当前尚未认证登录 GitHub 账号,无法读取云端仓库列表。请先完成上方的安装或登录指引。");
|
|
386
|
+
}
|
|
387
|
+
else {
|
|
388
|
+
var filteredRepos = userRepos.filter((r) => !searchQuery || r.nameWithOwner.toLowerCase().includes(searchQuery.toLowerCase()) || r.description?.toLowerCase().includes(searchQuery.toLowerCase()));
|
|
389
|
+
contentEl = h("div", null, h("input", {
|
|
390
|
+
className: "dsh-github-search-input",
|
|
391
|
+
placeholder: "🔍 搜索我的 GitHub 仓库...",
|
|
392
|
+
value: searchQuery,
|
|
393
|
+
onChange: (e) => setSearchQuery(e.target.value)
|
|
394
|
+
}), 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}`), formatRelativeTime(r.updatedAt)
|
|
395
|
+
? h("span", { title: `更新于 ${r.updatedAt}` }, `活跃于 ${formatRelativeTime(r.updatedAt)}`)
|
|
396
|
+
: null)))));
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
else {
|
|
400
|
+
if (!auth?.loggedIn) {
|
|
401
|
+
contentEl = h("div", { className: "dsh-github-empty" }, "当前尚未认证登录 GitHub 账号,无法读取个人待办 PR 与 Issues。请先完成上方的安装或登录指引。");
|
|
402
|
+
}
|
|
403
|
+
else {
|
|
404
|
+
var issueStats = (data && data.issueStats) || {
|
|
405
|
+
total: myIssues.length,
|
|
406
|
+
reported: myIssues.filter((i) => (i.categories || []).includes('reported')).length,
|
|
407
|
+
assigned: myIssues.filter((i) => (i.categories || []).includes('assigned')).length,
|
|
408
|
+
created: myIssues.filter((i) => (i.categories || []).includes('created')).length,
|
|
409
|
+
};
|
|
410
|
+
var filteredIssues = myIssues.filter((is) => {
|
|
411
|
+
if (issueFilter === 'all')
|
|
412
|
+
return true;
|
|
413
|
+
var cats = is.categories || [];
|
|
414
|
+
return cats.includes(issueFilter);
|
|
415
|
+
});
|
|
416
|
+
var issuePillsEl = h("div", { className: "dsh-github-pills" }, h("button", {
|
|
417
|
+
className: `dsh-github-pill-btn ${issueFilter === 'all' ? 'active' : ''}`,
|
|
418
|
+
onClick: () => setIssueFilter('all'),
|
|
419
|
+
}, `全部 (${issueStats.total || myIssues.length})`), h("button", {
|
|
420
|
+
className: `dsh-github-pill-btn ${issueFilter === 'reported' ? 'active' : ''}`,
|
|
421
|
+
onClick: () => setIssueFilter('reported'),
|
|
422
|
+
}, `📥 用户提起的 (${issueStats.reported || 0})`), h("button", {
|
|
423
|
+
className: `dsh-github-pill-btn ${issueFilter === 'assigned' ? 'active' : ''}`,
|
|
424
|
+
onClick: () => setIssueFilter('assigned'),
|
|
425
|
+
}, `🎯 分配给我的 (${issueStats.assigned || 0})`), h("button", {
|
|
426
|
+
className: `dsh-github-pill-btn ${issueFilter === 'created' ? 'active' : ''}`,
|
|
427
|
+
onClick: () => setIssueFilter('created'),
|
|
428
|
+
}, `✍️ 我创建的 (${issueStats.created || 0})`));
|
|
429
|
+
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", style: { display: "flex", alignItems: "center", gap: "8px", flexWrap: "wrap" } }, h("a", {
|
|
430
|
+
className: "dsh-github-item-title",
|
|
431
|
+
href: pr.url,
|
|
432
|
+
target: "_blank",
|
|
433
|
+
title: pr.updatedAt ? `更新于 ${pr.updatedAt}` : undefined,
|
|
434
|
+
}, `${pr.isDraft ? "⚪ " : ""}[${pr.repository?.nameWithOwner || 'Repo'}] #${pr.number} ${pr.title}`), pr.isDraft ? h("span", { className: "dsh-github-badge dsh-badge-yellow" }, "DRAFT") : null, formatRelativeTime(pr.updatedAt)
|
|
435
|
+
? h("span", { style: { fontSize: "11px", color: "var(--dsw-alias-label-secondary, #656d76)", whiteSpace: "nowrap" } }, formatRelativeTime(pr.updatedAt))
|
|
436
|
+
: null))), 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) => {
|
|
437
|
+
var cats = is.categories || [];
|
|
438
|
+
var badges = [];
|
|
439
|
+
if (cats.includes("reported")) {
|
|
440
|
+
badges.push(h("span", { key: "rep", className: "dsh-github-badge dsh-badge-purple" }, "用户提单"));
|
|
441
|
+
}
|
|
442
|
+
if (cats.includes("assigned")) {
|
|
443
|
+
badges.push(h("span", { key: "asn", className: "dsh-github-badge dsh-badge-blue" }, "分配待办"));
|
|
444
|
+
}
|
|
445
|
+
if (cats.includes("created")) {
|
|
446
|
+
badges.push(h("span", { key: "crt", className: "dsh-github-badge dsh-badge-green" }, "我发起的"));
|
|
447
|
+
}
|
|
448
|
+
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
|
|
449
|
+
? h("span", null, `指派: ${is.assignees.map((a) => '@' + a.login).join(', ')}`)
|
|
450
|
+
: null, is.labels && is.labels.length > 0
|
|
451
|
+
? is.labels.map((lbl) => h("span", { key: lbl.name, className: "dsh-github-badge dsh-badge-yellow" }, lbl.name))
|
|
452
|
+
: null, is.updatedAt ? h("span", null, `更新于: ${new Date(is.updatedAt).toLocaleDateString()}`) : null));
|
|
453
|
+
})));
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
var toastEl = toastMsg
|
|
457
|
+
? h("div", {
|
|
458
|
+
style: {
|
|
459
|
+
padding: "8px 12px",
|
|
460
|
+
marginBottom: "12px",
|
|
461
|
+
borderRadius: "6px",
|
|
462
|
+
fontSize: "12px",
|
|
463
|
+
background: toastMsg.startsWith("✅") ? "rgba(46, 160, 67, 0.15)" : "rgba(207, 34, 46, 0.15)",
|
|
464
|
+
color: toastMsg.startsWith("✅") ? "var(--dsw-alias-state-success, #2ea043)" : "var(--dsw-alias-state-error-primary, #cf222e)",
|
|
465
|
+
border: "1px solid " + (toastMsg.startsWith("✅") ? "rgba(46, 160, 67, 0.35)" : "rgba(207, 34, 46, 0.35)"),
|
|
466
|
+
display: "flex",
|
|
467
|
+
alignItems: "center",
|
|
468
|
+
justifyContent: "space-between",
|
|
469
|
+
gap: "8px",
|
|
470
|
+
},
|
|
471
|
+
}, h("span", null, toastMsg), h("button", { onClick: () => setToastMsg(null), style: { background: "none", border: "none", cursor: "pointer", color: "inherit", fontSize: "14px" } }, "✕"))
|
|
472
|
+
: null;
|
|
473
|
+
var networkAlertBannerEl = (syncStatus === "failed" || auth?.networkError || (error && data))
|
|
474
|
+
? h(NetworkAlertBanner, {
|
|
475
|
+
isRightbar: false,
|
|
476
|
+
networkErrorReason: auth?.networkErrorReason || error || "连接 GitHub API 超时或网络不可达,本次未能获取最新数据。",
|
|
477
|
+
lastSyncedAt,
|
|
478
|
+
onRefresh: () => loadData(true),
|
|
479
|
+
onOpenProxy: function () {
|
|
480
|
+
setSettingsInitialSection("proxy");
|
|
481
|
+
setIsSettingsModalOpen(true);
|
|
482
|
+
},
|
|
483
|
+
})
|
|
484
|
+
: null;
|
|
485
|
+
return h("div", { className: "dsh-github-panel", ref: panelRef }, toastEl, headerEl, networkAlertBannerEl, upgradeBannerEl, errorEl, statsCardsEl, authGuideEl, tabsEl, contentEl, settingsModalEl, h(GithubHelpModal, {
|
|
486
|
+
isOpen: isHelpModalOpen,
|
|
487
|
+
onClose: () => setIsHelpModalOpen(false),
|
|
488
|
+
}));
|
|
489
|
+
}
|
package/lib/upgrade-manager.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import type { UpgradeExecutionResult, UpgradeStatusResult } from './types.js';
|
|
1
|
+
import type { UpgradeExecutionResult, UpgradeStatusResult, UpgradeErrorType } from './types.js';
|
|
2
2
|
import type { ProxyManager } from './proxy.js';
|
|
3
|
+
/**
|
|
4
|
+
* 分析升级失败日志中的深层错误特征(重点识别 DSH 内置包管理器 minimumReleaseAge 24 小时防投毒策略)
|
|
5
|
+
*/
|
|
6
|
+
export declare function detectUpgradeErrorType(log?: string): UpgradeErrorType;
|
|
3
7
|
/**
|
|
4
8
|
* 构建跨平台环境自愈增强的 ProcessEnv (重点解决 macOS GUI 应用丢失 PATH 的痛点)
|
|
5
9
|
*
|
package/lib/upgrade-manager.js
CHANGED
|
@@ -4,6 +4,20 @@ import fs from 'node:fs';
|
|
|
4
4
|
import os from 'node:os';
|
|
5
5
|
import { fileURLToPath } from 'node:url';
|
|
6
6
|
import { PLUGIN_PACKAGE_NAME } from './version.js';
|
|
7
|
+
/**
|
|
8
|
+
* 分析升级失败日志中的深层错误特征(重点识别 DSH 内置包管理器 minimumReleaseAge 24 小时防投毒策略)
|
|
9
|
+
*/
|
|
10
|
+
export function detectUpgradeErrorType(log) {
|
|
11
|
+
if (!log)
|
|
12
|
+
return 'UNKNOWN';
|
|
13
|
+
if (/ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION|minimumReleaseAge/i.test(log)) {
|
|
14
|
+
return 'MINIMUM_RELEASE_AGE_VIOLATION';
|
|
15
|
+
}
|
|
16
|
+
if (/ETIMEDOUT|timeout|执行超时/i.test(log)) {
|
|
17
|
+
return 'TIMEOUT';
|
|
18
|
+
}
|
|
19
|
+
return 'UNKNOWN';
|
|
20
|
+
}
|
|
7
21
|
/**
|
|
8
22
|
* 构建跨平台环境自愈增强的 ProcessEnv (重点解决 macOS GUI 应用丢失 PATH 的痛点)
|
|
9
23
|
*
|
|
@@ -370,10 +384,18 @@ export class UpgradeManager {
|
|
|
370
384
|
this.lastResult = { state: 'success', targetVersion: wantVersion, message: successMsg, completedAt, environment: env.isDesktop ? 'desktop' : 'web' };
|
|
371
385
|
}
|
|
372
386
|
else {
|
|
387
|
+
const fullLog = this.logBuffer.join('\n');
|
|
388
|
+
const errorType = detectUpgradeErrorType(fullLog);
|
|
389
|
+
let failMsg = `升级失败(安装命令返回非零退出码)。${targetVersion ? `目标版本 ${targetVersion} 未安装成功。` : ''}${actionHint},或稍后重试一键升级。`;
|
|
390
|
+
// 智能识别:DSH 内置包管理器 minimumReleaseAge 24 小时防投毒安全锁机制
|
|
391
|
+
if (errorType === 'MINIMUM_RELEASE_AGE_VIOLATION') {
|
|
392
|
+
failMsg = `🛡️ 触发 DSH 新版本 24 小时安全保护期(npm 供应链防投毒策略)。检测到目标版本刚刚发布未满 24 小时,DSH 内置包管理器暂缓了自动静默升级以保障系统安全。\n【推荐解决步骤】:\n1. 立即尝鲜:请先【完全退出关闭 DSH 应用程序】,然后在系统终端执行手动安装命令(点击「📋 复制命令」获取);\n2. 稍后升级:无需操作,发版满 24 小时后直接在此点击「⚡ 一键自动升级」即可平滑完成。`;
|
|
393
|
+
}
|
|
373
394
|
this.lastResult = {
|
|
374
395
|
state: 'failed',
|
|
375
396
|
targetVersion,
|
|
376
|
-
|
|
397
|
+
errorType,
|
|
398
|
+
message: failMsg,
|
|
377
399
|
completedAt,
|
|
378
400
|
environment: env.isDesktop ? 'desktop' : 'web',
|
|
379
401
|
};
|
|
@@ -581,6 +603,7 @@ export class UpgradeManager {
|
|
|
581
603
|
ok: false,
|
|
582
604
|
message: this.lastResult.message || `升级退出码异常 (${code})`,
|
|
583
605
|
needRestart: false,
|
|
606
|
+
errorType: this.lastResult.errorType,
|
|
584
607
|
environment: env.isDesktop ? 'desktop' : 'web',
|
|
585
608
|
log: this.logBuffer.join('\n'),
|
|
586
609
|
};
|
package/lib/version.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* 2. 避免在 ESM 运行时动态读取 package.json 引入 fs 权限和路径解析边界问题;
|
|
7
7
|
* 3. 方便在 CI 发布流水线或 build 脚本中自动化校准。
|
|
8
8
|
*/
|
|
9
|
-
export declare const CURRENT_PLUGIN_VERSION = "0.
|
|
9
|
+
export declare const CURRENT_PLUGIN_VERSION = "0.5.0";
|
|
10
10
|
export declare const PLUGIN_PACKAGE_NAME = "dsh-github-flow";
|
|
11
11
|
export declare const NPM_PACKAGE_URL = "https://www.npmjs.com/package/dsh-github-flow";
|
|
12
12
|
export declare const NPM_REGISTRY_MIRROR = "https://registry.npmmirror.com";
|
package/lib/version.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* 2. 避免在 ESM 运行时动态读取 package.json 引入 fs 权限和路径解析边界问题;
|
|
7
7
|
* 3. 方便在 CI 发布流水线或 build 脚本中自动化校准。
|
|
8
8
|
*/
|
|
9
|
-
export const CURRENT_PLUGIN_VERSION = '0.
|
|
9
|
+
export const CURRENT_PLUGIN_VERSION = '0.5.0';
|
|
10
10
|
export const PLUGIN_PACKAGE_NAME = 'dsh-github-flow';
|
|
11
11
|
export const NPM_PACKAGE_URL = 'https://www.npmjs.com/package/dsh-github-flow';
|
|
12
12
|
export const NPM_REGISTRY_MIRROR = 'https://registry.npmmirror.com';
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-github-flow",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"icon": "icon.svg",
|
|
5
|
-
"description": "GitHub 工作流引擎:为 DeepSeek Harness 提供原生 GitHub CLI (gh) 集成——
|
|
5
|
+
"description": "GitHub 工作流引擎:为 DeepSeek Harness 提供原生 GitHub CLI (gh) 集成——18 大 Agent 领域工具(PR 审查合并、Issue 任务流转、CI 失败诊断、发版交付、密钥管理、Agent Skills、标签与保护规则集、构建缓存治理、代码片段 Gist、跨仓待办大盘、Copilot 智能体调度、社区 Discussions、Projects v2 看板、云端 Codespaces、运行时遥测与自愈健康度)、/gh 人类快捷指令、Web UI 全景驾驶舱与一键跨平台自动升级;零凭证侵入复用宿主机 gh 登录态,内置 Token 防溢出截断、高危操作二次确认与密文安全输入通道。",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./lib/main.js",
|
|
8
8
|
"repository": {
|