返回 DeepSeek-Reasonix
failurePage.ts
根目录 / desktop / electron / src / main / failurePage.ts
1 import type { HandshakeFailure } from "./handshake.js";
2
3 export const SHELL_ACTION_PREFIX = "reasonix://app/__shell/";
4
5 export type ShellAction = "open-logs" | "restart" | "quit";
6
7 export function shellActionFromURL(url: string): ShellAction | null {
8 if (!url.startsWith(SHELL_ACTION_PREFIX)) return null;
9 const action = url.slice(SHELL_ACTION_PREFIX.length).replace(/[?#].*$/, "");
10 return action === "open-logs" || action === "restart" || action === "quit" ? action : null;
11 }
12
13 function escapeHTML(value: string): string {
14 return value.replace(/[&<>"']/g, (char) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" })[char] as string);
15 }
16
17 export function renderFailurePage(failure: HandshakeFailure, logsPath: string): string {
18 const code = failure.code === null ? failure.name : `${failure.name} (${failure.code})`;
19 return `<!doctype html>
20 <html lang="en">
21 <head>
22 <meta charset="utf-8">
23 <meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'">
24 <title>${failure.name === "starting" ? "Reasonix is starting" : "Reasonix cannot start"}</title>
25 <style>
26 html, body { margin: 0; height: 100%; background: #1a1a2e; color: #f4f4f3; font: 14px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; }
27 main { max-width: 640px; margin: 0 auto; padding: 64px 32px; }
28 h1 { font-size: 20px; margin: 0 0 12px; }
29 .code { color: #b8b8c8; font-size: 12px; margin-bottom: 20px; }
30 pre { white-space: pre-wrap; word-break: break-word; background: #11111f; border: 1px solid #2c2c48; border-radius: 8px; padding: 12px 14px; margin: 0 0 20px; }
31 .actions { display: flex; gap: 10px; flex-wrap: wrap; }
32 a { display: inline-block; padding: 8px 14px; border-radius: 8px; background: #2c2c48; color: inherit; text-decoration: none; }
33 a.primary { background: #e58a3a; color: #111214; }
34 .logs { color: #8f8fa8; font-size: 12px; margin-top: 20px; }
35 </style>
36 </head>
37 <body>
38 <main>
39 <h1>${escapeHTML(failure.title)}</h1>
40 <div class="code">${escapeHTML(code)}</div>
41 <pre>${escapeHTML(failure.detail)}</pre>
42 <div class="actions">
43 ${failure.name === "starting" ? "" : failure.name === "build_mismatch" || failure.name === "contract_mismatch" ? '<p>Install the full Reasonix package to repair this installation. / 请安装完整包恢复启动,无需清理会话。</p>' : `<a class="primary" href="${SHELL_ACTION_PREFIX}restart">Retry / 重试</a>`}
44 <a href="${SHELL_ACTION_PREFIX}open-logs">Open logs folder</a>
45 <a href="${SHELL_ACTION_PREFIX}quit">Quit</a>
46 </div>
47 <div class="logs">Logs: ${escapeHTML(logsPath)}</div>
48 </main>
49 </body>
50 </html>`;
51 }
52
52 lines TYPESCRIPT