Repository navigation
Replies: 2 comments
|
你的代码定位逐条在源码上成立,我核到了精确行号(你的引用来自 1. 你的三条断言逐条核实
⇒ 你的因果链完整成立:窗口存在但不可见、托盘是 no-op、 2. ⭐ 你漏掉的一条:成功了也可能不显示
if (state.status === 'credential-stored' && attempt?.phase === 'succeeded' && welcomeWindow !== undefined) void enterWorkspace({ activate: false }).catch(() => undefined)⇒ 这条路径下
建议你补一格实验:走"凭据保存 → 自动进入工作区"这条路,看窗口是否显示。若也不显示,那这条报告的根因就不是"卡住"而是"显示时机被两个条件共同门控" —— 那会显著扩大影响面,也让修法更清楚。 3. 你的修法:第 3 条其实是一行,而且位置你已经找到
4. 你的第 4、5 条也对
5. 建议的报告结构(把三层分开)
6. 一条我认可你措辞的地方你把托盘类注释里那句 "the always-present way back to a hidden window" 拿来对照实际行为 —— 这种"文档承诺 vs 实现"的对照很有力,比只描述现象更容易被维护者接受。建议保留。 7. 版本边界你写 Desktop |
|
Root cause confirmed in the packaged shell (
Fix (4 small changes, all in
Patch against the shipped --- a/lib/main.js
+++ b/lib/main.js
@@ -3661,6 +3661,10 @@
/** Electron Node-mode child lifecycle for the shared Web application. */
/** Quit inspection deadline; a slower Host counts as unknown work and the shell asks before quitting. */
const QUIT_INSPECTION_DEADLINE_MS = 2e3;
+/** Longest the shell waits for the Host readiness event before reporting a stalled start. */
+const HOST_START_DEADLINE_MS = 3e5;
+/** Cadence of the startup heartbeat recorded while the Host boots. */
+const HOST_START_HEARTBEAT_MS = 15e3;
function isDesktopHostEvent(message) {
if (typeof message !== "object" || message === null || !("type" in message)) return false;
const candidate = message;
@@ -3846,6 +3850,13 @@
resolve();
});
});
+ // Readiness is the only event that makes the application usable: a child that never
+ // sends it would otherwise hang the shell behind a tray icon with nothing reported.
+ const readyDeadline = setTimeout(() => {
+ const stderr = this.stderr.trim().slice(-4000);
+ this.fail(new DesktopHostFatalError(`dsh desktop host: not ready after ${String(HOST_START_DEADLINE_MS)} ms${stderr === "" ? "" : `: ${stderr}`}`, stderr));
+ }, HOST_START_DEADLINE_MS);
+ this.readyPromise.then(() => clearTimeout(readyDeadline), () => clearTimeout(readyDeadline));
return this.readyPromise;
}
/**
@@ -12310,9 +12321,21 @@
const reconcileBackend = () => {
startup ??= (async () => {
await navigateMain(applicationUrl);
- await backend.start(async () => {
- await Promise.all([manager.applyRelease(), prepareHostEnvironment()]);
- });
+ // The shell page paints its own boot state, so showing it before the Host
+ // answers keeps a stalled Host from turning into a tray-only desktop.
+ if (mainWindow !== void 0 && !mainWindow.isDestroyed()) mainWindow.show();
+ const startedAt = Date.now();
+ const heartbeat = setInterval(() => {
+ console.warn(`dsh desktop host: still starting after ${String(Math.round((Date.now() - startedAt) / 1e3))} s`);
+ updateJournal?.action("host-starting");
+ }, HOST_START_HEARTBEAT_MS);
+ try {
+ await backend.start(async () => {
+ await Promise.all([manager.applyRelease(), prepareHostEnvironment()]);
+ });
+ } finally {
+ clearInterval(heartbeat);
+ }
if (backend.host !== void 0) await openInitialWindow();
if (backend.host !== void 0) updateJournal?.action("workspace-ready");
})().catch((error) => {
@@ -13047,7 +13070,6 @@
});
return;
}
- if (window === mainWindow && !enteredWorkspace) return;
if (window.isMinimized()) window.restore();
window.show();
window.focus();Follow-ups: (a) the Note: this patch is against the bundled |
Uh oh!
There was an error while loading. Please reload this page.
Summary
When the Desktop Host process doesn't send its
readyIPC message, the app runs with no visible window at all. You only get a tray icon, and clicking it does nothing. I couldn't find any startup timeout, splash, or progress UI. From the user's side the app "starts without a window" and there's nothing they can do about it. If the Host does eventually sendfatal, you see the "DeepSeek Harness is unavailable" page, but in my case that took 64 s or never happened.Environment
Steps / observations
.credentials.yaml.lock([Bug] 残留的空 .credentials.yaml.lock 让 web 宿主每次启动都失败:启动读取会话密钥也要拿写锁,而非原子创建留下的空锁不在 master 孤儿锁接管范围内(0.1.7-rc.1 实测,master 477b4f4 核对) #7924).DeepSeek Harness.exeprocesses are running and the Host listens on127.0.0.1:19387, butMainWindowHandleis 0 for all of them.%APPDATA%\@deepseek-ai\dsh-desktop\logswhile it's stalled. I waited several minutes.Why (from
resources/app.asar/lib/main.js)The main window is created with
show: falseand only shown inenterWorkspace(). That runs afterbackend.state.phase === "ready", which in turn waits for the Host'sreadymessage (readyPromise). That wait has no deadline.The tray
clickhandler and the "Open" menu item both callfocusPrimaryWindow(), which contains:So until the workspace has been entered, the tray is a no-op. The comment on the tray class calls it "the always-present way back to a hidden window", but it isn't one during startup.
Suggested fixes
ready.readyhasn't arrived after N seconds (30–60 s), show the existing "unavailable" page with the Host's stderr tail and the list of plugins that haven't activated yet.focusPrimaryWindow()should show the window (or the splash) even beforeenteredWorkspace.crash-*.logis only written when the Host reportsfatalor exits. A stall leaves no trace.dsh desktop host stopped: (node:6280) [DEP0180] DeprecationWarning: fs.Stats constructor is deprecated.The stderr tail used as the error message was just a deprecation warning, which is misleading. Filter outDeprecationWarninglines, or show the last non-warning lines instead.All reactions