@wrongstack/desktop 0.286.0 → 0.289.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/dist/main/main.js +492 -137
- package/dist/main/main.js.map +4 -4
- package/dist/preload/preload.cjs +5 -1
- package/dist/preload/preload.cjs.map +2 -2
- package/dist/preload/webui-preload.cjs +5 -1
- package/dist/preload/webui-preload.cjs.map +2 -2
- package/dist/renderer/assets/{index-cpNF4AJ5.js → index-Bih3lXdg.js} +166 -166
- package/dist/renderer/assets/index-Bih3lXdg.js.map +1 -0
- package/dist/renderer/index.html +5 -1
- package/package.json +4 -4
- package/dist/renderer/assets/index-cpNF4AJ5.js.map +0 -1
package/dist/main/main.js
CHANGED
|
@@ -1,17 +1,64 @@
|
|
|
1
1
|
// src/main/main.ts
|
|
2
|
-
import * as
|
|
2
|
+
import * as path4 from "node:path";
|
|
3
3
|
import * as fs3 from "node:fs/promises";
|
|
4
4
|
import { wstackGlobalRoot as wstackGlobalRoot3 } from "@wrongstack/core/utils";
|
|
5
5
|
import {
|
|
6
|
-
app,
|
|
6
|
+
app as app2,
|
|
7
7
|
BaseWindow,
|
|
8
8
|
dialog,
|
|
9
|
-
ipcMain,
|
|
9
|
+
ipcMain as ipcMain2,
|
|
10
|
+
nativeImage,
|
|
10
11
|
screen,
|
|
11
12
|
shell,
|
|
12
13
|
WebContentsView
|
|
13
14
|
} from "electron";
|
|
14
15
|
|
|
16
|
+
// src/main/macos-platform.ts
|
|
17
|
+
import { app, Menu } from "electron";
|
|
18
|
+
function initMacOS() {
|
|
19
|
+
if (process.platform !== "darwin") return;
|
|
20
|
+
app.setActivationPolicy("regular");
|
|
21
|
+
app.on("open-file", (_event, filePath) => {
|
|
22
|
+
if (app.isReady()) {
|
|
23
|
+
handleFileOpen(filePath);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
app.dock?.setMenu(
|
|
27
|
+
Menu.buildFromTemplate([
|
|
28
|
+
{
|
|
29
|
+
label: "New Window",
|
|
30
|
+
click: () => {
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
])
|
|
34
|
+
);
|
|
35
|
+
app.setAboutPanelOptions({
|
|
36
|
+
applicationName: "WrongStack Desktop",
|
|
37
|
+
applicationVersion: app.getVersion(),
|
|
38
|
+
version: process.versions.electron ? `Electron ${process.versions.electron}` : ""
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
function handleFileOpen(filePath) {
|
|
42
|
+
pendingOpenFilePath = filePath;
|
|
43
|
+
}
|
|
44
|
+
var pendingOpenFilePath = null;
|
|
45
|
+
function drainPendingOpenFilePath() {
|
|
46
|
+
const path5 = pendingOpenFilePath;
|
|
47
|
+
pendingOpenFilePath = null;
|
|
48
|
+
return path5;
|
|
49
|
+
}
|
|
50
|
+
function firstOpenFileArg(argv) {
|
|
51
|
+
if (process.platform !== "darwin") return null;
|
|
52
|
+
for (let index = 1; index < argv.length; index++) {
|
|
53
|
+
const arg = argv[index];
|
|
54
|
+
if (arg == null) continue;
|
|
55
|
+
if (arg.startsWith("-")) continue;
|
|
56
|
+
if (arg === "." || arg === "--") continue;
|
|
57
|
+
return arg;
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
|
|
15
62
|
// src/main/agent-bridge.ts
|
|
16
63
|
import { randomUUID } from "node:crypto";
|
|
17
64
|
import { EventEmitter } from "node:events";
|
|
@@ -397,7 +444,11 @@ var IPC = {
|
|
|
397
444
|
// Embedded WebUI view side — the desktop shell pushes locale changes here
|
|
398
445
|
// so the React WebUI inside Electron can swap i18n instantly, without waiting
|
|
399
446
|
// for the config-file watcher → WS prefs.updated round-trip.
|
|
400
|
-
webuiLocaleChanged: "desktop:webui-locale-changed"
|
|
447
|
+
webuiLocaleChanged: "desktop:webui-locale-changed",
|
|
448
|
+
// macOS open-file event forwarded from main process to shell renderer.
|
|
449
|
+
// The shell uses this to decide whether to open a dragged/double-clicked
|
|
450
|
+
// path as a project directory.
|
|
451
|
+
openFile: "desktop:open-file"
|
|
401
452
|
};
|
|
402
453
|
|
|
403
454
|
// src/main/i18n-main.ts
|
|
@@ -874,8 +925,8 @@ var DesktopRuntimeManager = class extends EventEmitter2 {
|
|
|
874
925
|
}
|
|
875
926
|
async openProject(projectRoot, options = {}) {
|
|
876
927
|
const resolved = path2.resolve(projectRoot);
|
|
877
|
-
const
|
|
878
|
-
if (!
|
|
928
|
+
const stat3 = await fs2.stat(resolved).catch(() => null);
|
|
929
|
+
if (!stat3?.isDirectory()) throw new Error(`Not a directory: ${resolved}`);
|
|
879
930
|
const kind = options.kind ?? "project";
|
|
880
931
|
const touchRecent = options.touchRecent ?? kind === "project";
|
|
881
932
|
const forceNew = options.forceNew === true;
|
|
@@ -1049,8 +1100,8 @@ var DesktopRuntimeManager = class extends EventEmitter2 {
|
|
|
1049
1100
|
}
|
|
1050
1101
|
async registerProject(projectRoot) {
|
|
1051
1102
|
const resolved = path2.resolve(projectRoot);
|
|
1052
|
-
const
|
|
1053
|
-
if (!
|
|
1103
|
+
const stat3 = await fs2.stat(resolved).catch(() => null);
|
|
1104
|
+
if (!stat3?.isDirectory()) throw new Error(`Not a directory: ${resolved}`);
|
|
1054
1105
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1055
1106
|
const entry = {
|
|
1056
1107
|
name: path2.basename(resolved) || resolved,
|
|
@@ -1186,6 +1237,26 @@ async function terminateProcessTree(child) {
|
|
|
1186
1237
|
if (!child || child.killed || !child.pid) return;
|
|
1187
1238
|
if (process.platform !== "win32") {
|
|
1188
1239
|
child.kill("SIGTERM");
|
|
1240
|
+
const deadline = Date.now() + 5e3;
|
|
1241
|
+
await new Promise((resolve2) => {
|
|
1242
|
+
const check = () => {
|
|
1243
|
+
if (child.killed || !child.pid) {
|
|
1244
|
+
resolve2();
|
|
1245
|
+
return;
|
|
1246
|
+
}
|
|
1247
|
+
if (Date.now() >= deadline) {
|
|
1248
|
+
try {
|
|
1249
|
+
process.kill(-child.pid, "SIGKILL");
|
|
1250
|
+
} catch {
|
|
1251
|
+
child.kill("SIGKILL");
|
|
1252
|
+
}
|
|
1253
|
+
resolve2();
|
|
1254
|
+
return;
|
|
1255
|
+
}
|
|
1256
|
+
setTimeout(check, 100);
|
|
1257
|
+
};
|
|
1258
|
+
check();
|
|
1259
|
+
});
|
|
1189
1260
|
return;
|
|
1190
1261
|
}
|
|
1191
1262
|
await new Promise((resolve2) => {
|
|
@@ -1389,16 +1460,16 @@ function resolveWebUiEntry() {
|
|
|
1389
1460
|
if (existsSync(candidate)) return candidate;
|
|
1390
1461
|
} catch {
|
|
1391
1462
|
}
|
|
1392
|
-
const serverIndex = require2.resolve("@wrongstack/webui
|
|
1393
|
-
return path2.join(path2.dirname(serverIndex), "entry.js");
|
|
1463
|
+
const serverIndex = require2.resolve("@wrongstack/webui-server");
|
|
1464
|
+
return path2.join(path2.dirname(serverIndex), "server", "entry.js");
|
|
1394
1465
|
}
|
|
1395
1466
|
function resolveWebUiDistDir() {
|
|
1396
1467
|
if (process.env["WRONGSTACK_WEBUI_DIST"]) {
|
|
1397
1468
|
return path2.resolve(process.env["WRONGSTACK_WEBUI_DIST"]);
|
|
1398
1469
|
}
|
|
1399
1470
|
const require2 = createRequire(import.meta.url);
|
|
1400
|
-
const
|
|
1401
|
-
const candidate = path2.
|
|
1471
|
+
const serverEntry = require2.resolve("@wrongstack/webui");
|
|
1472
|
+
const candidate = path2.dirname(serverEntry);
|
|
1402
1473
|
if (existsSync(candidate)) return candidate;
|
|
1403
1474
|
throw new Error(
|
|
1404
1475
|
`WebUI frontend assets not found at ${candidate}. Build @wrongstack/webui or set WRONGSTACK_WEBUI_DIST.`
|
|
@@ -1525,7 +1596,7 @@ var DESKTOP_WEBUI_ACTIONS = /* @__PURE__ */ new Set([
|
|
|
1525
1596
|
var DESKTOP_WEBUI_VIEWS = /* @__PURE__ */ new Set([
|
|
1526
1597
|
"chat",
|
|
1527
1598
|
"settings",
|
|
1528
|
-
"
|
|
1599
|
+
"goal",
|
|
1529
1600
|
"specs",
|
|
1530
1601
|
"sddboard",
|
|
1531
1602
|
"sddwizard",
|
|
@@ -1560,7 +1631,6 @@ var DESKTOP_WEBUI_OVERLAYS = /* @__PURE__ */ new Set([
|
|
|
1560
1631
|
"queue"
|
|
1561
1632
|
]);
|
|
1562
1633
|
var DESKTOP_WEBUI_DOCKS = /* @__PURE__ */ new Set([
|
|
1563
|
-
"autophase",
|
|
1564
1634
|
"goal",
|
|
1565
1635
|
"fleet",
|
|
1566
1636
|
"work",
|
|
@@ -1663,10 +1733,17 @@ function isRecord(value) {
|
|
|
1663
1733
|
}
|
|
1664
1734
|
|
|
1665
1735
|
// src/main/state/constants.ts
|
|
1736
|
+
var OPEN_EXTERNAL_ALLOWED_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:", "mailto:"]);
|
|
1666
1737
|
var SIDEBAR_WIDTH_WIDE = 292;
|
|
1667
1738
|
var SIDEBAR_WIDTH_MEDIUM = 276;
|
|
1668
1739
|
var SIDEBAR_WIDTH_NARROW = 252;
|
|
1669
1740
|
var SIDEBAR_WIDTH_COLLAPSED = 56;
|
|
1741
|
+
var MIN_WINDOW_WIDTH2 = 760;
|
|
1742
|
+
var MIN_WINDOW_HEIGHT2 = 520;
|
|
1743
|
+
var MAX_PENDING_WEBUI_COMMANDS = 50;
|
|
1744
|
+
var MAX_PENDING_FLUSH_ATTEMPTS = 80;
|
|
1745
|
+
var WEBUI_COMMAND_FALLBACK_MS = 350;
|
|
1746
|
+
var WEBUI_COMMAND_ACK_TIMEOUT_MS = 2e3;
|
|
1670
1747
|
|
|
1671
1748
|
// src/main/layout/sidebar.ts
|
|
1672
1749
|
function getSidebarWidth(windowWidth, collapsed) {
|
|
@@ -1677,10 +1754,10 @@ function getSidebarWidth(windowWidth, collapsed) {
|
|
|
1677
1754
|
}
|
|
1678
1755
|
|
|
1679
1756
|
// src/main/menu/index.ts
|
|
1680
|
-
import { Menu } from "electron";
|
|
1757
|
+
import { Menu as Menu2 } from "electron";
|
|
1681
1758
|
|
|
1682
1759
|
// src/main/menu/projects-menu.ts
|
|
1683
|
-
|
|
1760
|
+
import path3 from "node:path";
|
|
1684
1761
|
function buildProjectsMenu(runtimes, actions, t) {
|
|
1685
1762
|
const projectGroups = groupProjectRuntimesForMenu(runtimes);
|
|
1686
1763
|
const menu = [
|
|
@@ -1688,9 +1765,11 @@ function buildProjectsMenu(runtimes, actions, t) {
|
|
|
1688
1765
|
label: t("openProjectEllipsis"),
|
|
1689
1766
|
accelerator: "CmdOrCtrl+O",
|
|
1690
1767
|
click: () => actions.newSession("")
|
|
1691
|
-
// Will open dialog
|
|
1692
1768
|
},
|
|
1693
|
-
{
|
|
1769
|
+
{
|
|
1770
|
+
label: t("registerProjectEllipsis"),
|
|
1771
|
+
click: () => actions.registerProject?.()
|
|
1772
|
+
},
|
|
1694
1773
|
{ type: "separator" }
|
|
1695
1774
|
];
|
|
1696
1775
|
if (projectGroups.length === 0) {
|
|
@@ -1812,7 +1891,7 @@ function groupProjectRuntimesForMenu(runtimes) {
|
|
|
1812
1891
|
}
|
|
1813
1892
|
groups.set(key, {
|
|
1814
1893
|
key,
|
|
1815
|
-
name:
|
|
1894
|
+
name: path3.basename(runtime.root) || runtime.name,
|
|
1816
1895
|
root: runtime.root,
|
|
1817
1896
|
sessions: [runtime]
|
|
1818
1897
|
});
|
|
@@ -1983,6 +2062,7 @@ function configureApplicationMenu(ctx) {
|
|
|
1983
2062
|
const actions = {
|
|
1984
2063
|
activate: (runtimeId) => void ctx.activateRuntime(runtimeId),
|
|
1985
2064
|
activateAndNavigate,
|
|
2065
|
+
registerProject: () => void ctx.registerProject(),
|
|
1986
2066
|
newSession: (runtimeId) => {
|
|
1987
2067
|
if (runtimeId) void ctx.openProjectSession(runtimeId);
|
|
1988
2068
|
else void ctx.openProject();
|
|
@@ -2007,19 +2087,301 @@ function configureApplicationMenu(ctx) {
|
|
|
2007
2087
|
buildWorkspaceMenu(ctx, actions, hasActiveWebui, activeWebuiPrefs, navigate),
|
|
2008
2088
|
buildViewMenu(ctx)
|
|
2009
2089
|
];
|
|
2010
|
-
|
|
2090
|
+
Menu2.setApplicationMenu(Menu2.buildFromTemplate(template));
|
|
2091
|
+
}
|
|
2092
|
+
|
|
2093
|
+
// src/main/ipc-handlers/index.ts
|
|
2094
|
+
import { ipcMain } from "electron";
|
|
2095
|
+
|
|
2096
|
+
// src/main/validation/index.ts
|
|
2097
|
+
function validate(schema, data) {
|
|
2098
|
+
try {
|
|
2099
|
+
const result = schema.safeParse(data);
|
|
2100
|
+
if (result.success) {
|
|
2101
|
+
return { success: true, data: result.data };
|
|
2102
|
+
}
|
|
2103
|
+
return { success: false, error: formatZodError(result.error) };
|
|
2104
|
+
} catch (err) {
|
|
2105
|
+
return { success: false, error: String(err) };
|
|
2106
|
+
}
|
|
2107
|
+
}
|
|
2108
|
+
function validateOrDefault(schema, data, defaultValue) {
|
|
2109
|
+
const result = validate(schema, data);
|
|
2110
|
+
return result.success ? result.data : defaultValue;
|
|
2111
|
+
}
|
|
2112
|
+
function formatZodError(error) {
|
|
2113
|
+
return error.issues.map((e) => `${e.path.join(".")}: ${e.message}`).join("; ");
|
|
2114
|
+
}
|
|
2115
|
+
function createValidationLogger(prefix) {
|
|
2116
|
+
const loggedErrors = /* @__PURE__ */ new Set();
|
|
2117
|
+
const maxErrors = 100;
|
|
2118
|
+
return {
|
|
2119
|
+
log(error) {
|
|
2120
|
+
if (loggedErrors.size >= maxErrors) return;
|
|
2121
|
+
const key = `${prefix}:${error}`;
|
|
2122
|
+
if (!loggedErrors.has(key)) {
|
|
2123
|
+
loggedErrors.add(key);
|
|
2124
|
+
console.warn(
|
|
2125
|
+
JSON.stringify({
|
|
2126
|
+
level: "warn",
|
|
2127
|
+
event: "desktop.validation_error",
|
|
2128
|
+
prefix,
|
|
2129
|
+
message: error,
|
|
2130
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2131
|
+
})
|
|
2132
|
+
);
|
|
2133
|
+
}
|
|
2134
|
+
},
|
|
2135
|
+
reset() {
|
|
2136
|
+
loggedErrors.clear();
|
|
2137
|
+
}
|
|
2138
|
+
};
|
|
2139
|
+
}
|
|
2140
|
+
|
|
2141
|
+
// src/main/validation/schemas.ts
|
|
2142
|
+
import { z } from "zod";
|
|
2143
|
+
var RUNTIME_ID_PATTERN = /^[a-zA-Z0-9._:-]{3,120}$/;
|
|
2144
|
+
var runtimeIdSchema = z.string().regex(RUNTIME_ID_PATTERN, "Invalid runtime ID format");
|
|
2145
|
+
var pathSchema = z.string().min(1).max(1e4);
|
|
2146
|
+
var nonEmptyStringSchema = z.string().min(1);
|
|
2147
|
+
var booleanSchema = z.boolean();
|
|
2148
|
+
var numberSchema = z.number().int().finite();
|
|
2149
|
+
var openProjectSchema = z.object({
|
|
2150
|
+
requestedRoot: pathSchema.optional()
|
|
2151
|
+
});
|
|
2152
|
+
var registerProjectSchema = z.object({
|
|
2153
|
+
requestedRoot: pathSchema.optional()
|
|
2154
|
+
});
|
|
2155
|
+
var unregisterProjectSchema = z.object({
|
|
2156
|
+
root: pathSchema
|
|
2157
|
+
});
|
|
2158
|
+
var openProjectSessionSchema = z.object({
|
|
2159
|
+
runtimeId: runtimeIdSchema.optional()
|
|
2160
|
+
});
|
|
2161
|
+
var activateRuntimeSchema = z.object({
|
|
2162
|
+
id: runtimeIdSchema
|
|
2163
|
+
});
|
|
2164
|
+
var closeRuntimeSchema = z.object({
|
|
2165
|
+
id: runtimeIdSchema
|
|
2166
|
+
});
|
|
2167
|
+
var sendMessageSchema = z.object({
|
|
2168
|
+
id: runtimeIdSchema,
|
|
2169
|
+
content: z.string()
|
|
2170
|
+
});
|
|
2171
|
+
var abortRuntimeSchema = z.object({
|
|
2172
|
+
id: runtimeIdSchema
|
|
2173
|
+
});
|
|
2174
|
+
var openRuntimeInBrowserSchema = z.object({
|
|
2175
|
+
id: runtimeIdSchema
|
|
2176
|
+
});
|
|
2177
|
+
var revealRuntimeRootSchema = z.object({
|
|
2178
|
+
id: runtimeIdSchema
|
|
2179
|
+
});
|
|
2180
|
+
var setShellSidebarCollapsedSchema = z.object({
|
|
2181
|
+
collapsed: booleanSchema
|
|
2182
|
+
});
|
|
2183
|
+
var navigateWebuiSchema = z.object({
|
|
2184
|
+
command: z.unknown()
|
|
2185
|
+
});
|
|
2186
|
+
var getConversationSchema = z.object({
|
|
2187
|
+
runtimeId: runtimeIdSchema
|
|
2188
|
+
});
|
|
2189
|
+
var webuiReadyChangedSchema = z.object({
|
|
2190
|
+
ready: booleanSchema
|
|
2191
|
+
});
|
|
2192
|
+
var webuiPrefsChangedSchema = z.object({
|
|
2193
|
+
prefs: z.record(z.string(), z.unknown())
|
|
2194
|
+
});
|
|
2195
|
+
var webuiCommandAckSchema = z.object({
|
|
2196
|
+
requestId: z.string(),
|
|
2197
|
+
handled: z.boolean(),
|
|
2198
|
+
message: z.string().optional()
|
|
2199
|
+
});
|
|
2200
|
+
var setLocaleSchema = z.object({
|
|
2201
|
+
locale: z.string().min(2).max(10)
|
|
2202
|
+
});
|
|
2203
|
+
|
|
2204
|
+
// src/main/ipc-handlers/index.ts
|
|
2205
|
+
var validationLogger = createValidationLogger("IPC");
|
|
2206
|
+
function registerIpcHandlers(ctx) {
|
|
2207
|
+
ipcMain.handle(IPC.getState, () => ctx.getRuntimeManager().snapshot());
|
|
2208
|
+
ipcMain.handle(IPC.getConversation, (_event, runtimeId) => {
|
|
2209
|
+
const result = validate(runtimeIdSchema, runtimeId);
|
|
2210
|
+
if (!result.success) {
|
|
2211
|
+
validationLogger.log(`getConversation: ${result.error}`);
|
|
2212
|
+
return ctx.getAgentBridge().snapshot("");
|
|
2213
|
+
}
|
|
2214
|
+
return ctx.getAgentBridge().snapshot(result.data);
|
|
2215
|
+
});
|
|
2216
|
+
ipcMain.handle(IPC.getWebuiStatus, () => ctx.getWebuiStatus());
|
|
2217
|
+
ipcMain.handle(IPC.navigateWebui, async (_event, command) => {
|
|
2218
|
+
return ctx.dispatchWebuiCommand(command);
|
|
2219
|
+
});
|
|
2220
|
+
ipcMain.handle(IPC.reloadWebui, async () => ctx.reloadActiveWebuiView());
|
|
2221
|
+
ipcMain.handle(IPC.setShellSidebarCollapsed, (_event, collapsed) => {
|
|
2222
|
+
const result = validateOrDefault(
|
|
2223
|
+
pathSchema.transform(() => collapsed === true),
|
|
2224
|
+
collapsed,
|
|
2225
|
+
true
|
|
2226
|
+
);
|
|
2227
|
+
ctx.setShellSidebarCollapsed(result);
|
|
2228
|
+
return true;
|
|
2229
|
+
});
|
|
2230
|
+
ipcMain.handle(IPC.openSettings, async () => ctx.openSettings());
|
|
2231
|
+
ipcMain.handle(IPC.openProjectSession, async (_event, runtimeId) => {
|
|
2232
|
+
const validated = validateOptional(runtimeIdSchema, runtimeId);
|
|
2233
|
+
return ctx.openProjectSession(validated);
|
|
2234
|
+
});
|
|
2235
|
+
ipcMain.handle(IPC.openProject, async (_event, requestedRoot) => {
|
|
2236
|
+
const validated = validateOptional(pathSchema, requestedRoot);
|
|
2237
|
+
return ctx.openProject(validated);
|
|
2238
|
+
});
|
|
2239
|
+
ipcMain.handle(IPC.registerProject, async (_event, requestedRoot) => {
|
|
2240
|
+
const validated = validateOptional(pathSchema, requestedRoot);
|
|
2241
|
+
return ctx.registerProject(validated);
|
|
2242
|
+
});
|
|
2243
|
+
ipcMain.handle(IPC.unregisterProject, async (_event, root) => {
|
|
2244
|
+
const result = validate(pathSchema, root);
|
|
2245
|
+
if (!result.success) {
|
|
2246
|
+
validationLogger.log(`unregisterProject: ${result.error}`);
|
|
2247
|
+
return ctx.getRuntimeManager().snapshot();
|
|
2248
|
+
}
|
|
2249
|
+
return ctx.unregisterProject(result.data);
|
|
2250
|
+
});
|
|
2251
|
+
ipcMain.handle(IPC.activateRuntime, async (_event, id) => {
|
|
2252
|
+
const result = validate(runtimeIdSchema, id);
|
|
2253
|
+
if (!result.success) {
|
|
2254
|
+
validationLogger.log(`activateRuntime: ${result.error}`);
|
|
2255
|
+
return ctx.getRuntimeManager().snapshot();
|
|
2256
|
+
}
|
|
2257
|
+
return ctx.activateRuntime(result.data);
|
|
2258
|
+
});
|
|
2259
|
+
ipcMain.handle(IPC.closeRuntime, async (_event, id) => {
|
|
2260
|
+
const result = validate(runtimeIdSchema, id);
|
|
2261
|
+
if (!result.success) {
|
|
2262
|
+
validationLogger.log(`closeRuntime: ${result.error}`);
|
|
2263
|
+
return ctx.getRuntimeManager().snapshot();
|
|
2264
|
+
}
|
|
2265
|
+
return ctx.closeRuntime(result.data);
|
|
2266
|
+
});
|
|
2267
|
+
ipcMain.handle(IPC.sendMessage, async (_event, id, content) => {
|
|
2268
|
+
const idResult = validate(runtimeIdSchema, id);
|
|
2269
|
+
if (!idResult.success) {
|
|
2270
|
+
validationLogger.log(`sendMessage (id): ${idResult.error}`);
|
|
2271
|
+
return ctx.sendMessage("", "", "");
|
|
2272
|
+
}
|
|
2273
|
+
const contentResult = validate(pathSchema.transform(() => String(content ?? "")), content);
|
|
2274
|
+
const safeContent = contentResult.success ? contentResult.data : String(content ?? "");
|
|
2275
|
+
return ctx.sendMessage(
|
|
2276
|
+
idResult.data,
|
|
2277
|
+
ctx.getRuntimeManager().getRuntimeWsUrlWithToken(idResult.data) ?? "",
|
|
2278
|
+
safeContent
|
|
2279
|
+
);
|
|
2280
|
+
});
|
|
2281
|
+
ipcMain.handle(IPC.abortRuntime, async (_event, id) => {
|
|
2282
|
+
const result = validate(runtimeIdSchema, id);
|
|
2283
|
+
if (!result.success) {
|
|
2284
|
+
validationLogger.log(`abortRuntime: ${result.error}`);
|
|
2285
|
+
return ctx.abortRuntime("", "");
|
|
2286
|
+
}
|
|
2287
|
+
return ctx.abortRuntime(
|
|
2288
|
+
result.data,
|
|
2289
|
+
ctx.getRuntimeManager().getRuntimeWsUrlWithToken(result.data) ?? ""
|
|
2290
|
+
);
|
|
2291
|
+
});
|
|
2292
|
+
ipcMain.handle(IPC.openRuntimeInBrowser, async (_event, id) => {
|
|
2293
|
+
const result = validate(runtimeIdSchema, id);
|
|
2294
|
+
if (!result.success) {
|
|
2295
|
+
validationLogger.log(`openRuntimeInBrowser: ${result.error}`);
|
|
2296
|
+
return;
|
|
2297
|
+
}
|
|
2298
|
+
const url = ctx.getRuntimeManager().getRuntimeUrlWithToken(result.data);
|
|
2299
|
+
if (url) ctx.openExternal(url);
|
|
2300
|
+
});
|
|
2301
|
+
ipcMain.handle(IPC.revealRuntimeRoot, async (_event, id) => {
|
|
2302
|
+
const result = validate(runtimeIdSchema, id);
|
|
2303
|
+
if (!result.success) {
|
|
2304
|
+
validationLogger.log(`revealRuntimeRoot: ${result.error}`);
|
|
2305
|
+
return;
|
|
2306
|
+
}
|
|
2307
|
+
const runtime = ctx.getRuntimeManager().getRuntime(result.data);
|
|
2308
|
+
if (runtime) ctx.revealInExplorer(runtime.root);
|
|
2309
|
+
});
|
|
2310
|
+
ipcMain.on(IPC.webuiReadyChanged, (event, ready) => {
|
|
2311
|
+
const entry = ctx.findWebuiEntryBySenderId(event.sender.id);
|
|
2312
|
+
if (!entry) return;
|
|
2313
|
+
const isReady = ready === true;
|
|
2314
|
+
entry.bridgeReady = isReady;
|
|
2315
|
+
if (entry.bridgeReady) {
|
|
2316
|
+
ctx.setEntryWebuiStatus(entry, { ...entry.status, status: "ready" });
|
|
2317
|
+
ctx.schedulePendingWebuiFlush(entry);
|
|
2318
|
+
} else if (entry.status.status === "ready") {
|
|
2319
|
+
ctx.setEntryWebuiStatus(entry, { ...entry.status, status: "loading" });
|
|
2320
|
+
}
|
|
2321
|
+
});
|
|
2322
|
+
ipcMain.on(IPC.webuiPrefsChanged, (event, prefs) => {
|
|
2323
|
+
const entry = ctx.findWebuiEntryBySenderId(event.sender.id);
|
|
2324
|
+
if (!entry) return;
|
|
2325
|
+
const sanitized = sanitizeWebuiPrefs(prefs);
|
|
2326
|
+
if (Object.keys(sanitized).length === 0) return;
|
|
2327
|
+
ctx.setEntryWebuiStatus(entry, {
|
|
2328
|
+
...entry.status,
|
|
2329
|
+
prefs: { ...entry.status.prefs ?? {}, ...sanitized }
|
|
2330
|
+
});
|
|
2331
|
+
});
|
|
2332
|
+
ipcMain.on(IPC.webuiCommandAck, (event, requestId, handled, _message) => {
|
|
2333
|
+
const entry = ctx.findWebuiEntryBySenderId(event.sender.id);
|
|
2334
|
+
if (!entry) return;
|
|
2335
|
+
const result = validate(webuiCommandAckSchema, {
|
|
2336
|
+
requestId,
|
|
2337
|
+
handled,
|
|
2338
|
+
message: _message
|
|
2339
|
+
});
|
|
2340
|
+
if (!result.success) {
|
|
2341
|
+
validationLogger.log(`webuiCommandAck: ${result.error}`);
|
|
2342
|
+
return;
|
|
2343
|
+
}
|
|
2344
|
+
const pending = ctx.getPendingWebuiCommandAcks().get(result.data.requestId);
|
|
2345
|
+
if (!pending || pending.runtimeId !== entry.runtimeId) return;
|
|
2346
|
+
ctx.settlePendingWebuiCommandAck(result.data.requestId, result.data.handled);
|
|
2347
|
+
});
|
|
2348
|
+
ipcMain.on(IPC.setLocale, (_event, locale) => {
|
|
2349
|
+
const result = validate(setLocaleSchema, { locale });
|
|
2350
|
+
if (!result.success) {
|
|
2351
|
+
validationLogger.log(`setLocale: ${result.error}`);
|
|
2352
|
+
return;
|
|
2353
|
+
}
|
|
2354
|
+
ctx.getI18n().setMainLocale(result.data.locale);
|
|
2355
|
+
ctx.configureApplicationMenu();
|
|
2356
|
+
ctx.broadcastLocaleToEmbeddedWebuis(result.data.locale);
|
|
2357
|
+
void ctx.getConfigIo().writeUiLocale(result.data.locale);
|
|
2358
|
+
});
|
|
2359
|
+
}
|
|
2360
|
+
function validateOptional(schema, value) {
|
|
2361
|
+
if (value === void 0 || value === null) return void 0;
|
|
2362
|
+
const result = schema.safeParse(value);
|
|
2363
|
+
return result.success ? result.data : void 0;
|
|
2364
|
+
}
|
|
2365
|
+
function sanitizeWebuiPrefs(prefs) {
|
|
2366
|
+
const next = {};
|
|
2367
|
+
if (!isRecord2(prefs)) return next;
|
|
2368
|
+
if (typeof prefs["yolo"] === "boolean") next.yolo = prefs["yolo"];
|
|
2369
|
+
if (typeof prefs["nextPrediction"] === "boolean") next.nextPrediction = prefs["nextPrediction"];
|
|
2370
|
+
if (typeof prefs["contextAutoCompact"] === "boolean") {
|
|
2371
|
+
next.contextAutoCompact = prefs["contextAutoCompact"];
|
|
2372
|
+
}
|
|
2373
|
+
return next;
|
|
2374
|
+
}
|
|
2375
|
+
function isRecord2(value) {
|
|
2376
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
2011
2377
|
}
|
|
2012
2378
|
|
|
2013
2379
|
// src/main/main.ts
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
var WEBUI_COMMAND_FALLBACK_MS = 350;
|
|
2020
|
-
var WEBUI_COMMAND_ACK_TIMEOUT_MS = 2e3;
|
|
2021
|
-
app.setAppUserModelId("com.wrongstack.desktop");
|
|
2022
|
-
app.setPath("userData", path3.join(wstackGlobalRoot3(), "desktop", "electron-profile"));
|
|
2380
|
+
initMacOS();
|
|
2381
|
+
if (process.platform === "win32") {
|
|
2382
|
+
app2.setAppUserModelId("com.wrongstack.desktop");
|
|
2383
|
+
}
|
|
2384
|
+
app2.setPath("userData", path4.join(wstackGlobalRoot3(), "desktop", "electron-profile"));
|
|
2023
2385
|
var manager = new DesktopRuntimeManager();
|
|
2024
2386
|
var bridge = new DesktopAgentBridge();
|
|
2025
2387
|
var mainWindow = null;
|
|
@@ -2051,13 +2413,21 @@ function sameOrigin(candidate, base) {
|
|
|
2051
2413
|
return false;
|
|
2052
2414
|
}
|
|
2053
2415
|
}
|
|
2054
|
-
function
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2416
|
+
function revealInExplorer(root) {
|
|
2417
|
+
shell.openPath(root).catch((err) => {
|
|
2418
|
+
if (process.platform === "darwin") {
|
|
2419
|
+
void shell.openPath(path4.dirname(root)).catch(() => void 0);
|
|
2420
|
+
}
|
|
2421
|
+
console.error(
|
|
2422
|
+
JSON.stringify({
|
|
2423
|
+
level: "warn",
|
|
2424
|
+
event: "desktop.reveal_in_explorer_failed",
|
|
2425
|
+
root,
|
|
2426
|
+
message: err instanceof Error ? err.message : String(err),
|
|
2427
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2428
|
+
})
|
|
2429
|
+
);
|
|
2430
|
+
});
|
|
2061
2431
|
}
|
|
2062
2432
|
function setShellSidebarCollapsed(collapsed) {
|
|
2063
2433
|
shellSidebarCollapsed = collapsed;
|
|
@@ -2603,105 +2973,51 @@ function createMenuContext() {
|
|
|
2603
2973
|
shell.openExternal(url);
|
|
2604
2974
|
},
|
|
2605
2975
|
revealInExplorer: (root) => {
|
|
2606
|
-
|
|
2976
|
+
revealInExplorer(root);
|
|
2607
2977
|
}
|
|
2608
2978
|
};
|
|
2609
2979
|
}
|
|
2610
2980
|
function configureApplicationMenu2() {
|
|
2611
2981
|
configureApplicationMenu(createMenuContext());
|
|
2612
2982
|
}
|
|
2613
|
-
function
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
(
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
async (_event, id) => bridge.abort(id, runtimeWsUrlOrThrow(id))
|
|
2652
|
-
);
|
|
2653
|
-
ipcMain.handle(IPC.openRuntimeInBrowser, async (_event, id) => {
|
|
2654
|
-
const url = manager.getRuntimeUrlWithToken(id);
|
|
2655
|
-
if (url) safeOpenExternal(url);
|
|
2656
|
-
});
|
|
2657
|
-
ipcMain.handle(IPC.revealRuntimeRoot, async (_event, id) => {
|
|
2658
|
-
const runtime = manager.getRuntime(id);
|
|
2659
|
-
if (runtime) void shell.openPath(runtime.root);
|
|
2660
|
-
});
|
|
2661
|
-
ipcMain.on(IPC.webuiReadyChanged, (event, ready) => {
|
|
2662
|
-
const entry = findWebuiEntryBySenderId(event.sender.id);
|
|
2663
|
-
if (!entry) return;
|
|
2664
|
-
entry.bridgeReady = ready === true;
|
|
2665
|
-
if (entry.bridgeReady) {
|
|
2666
|
-
setEntryWebuiStatus(entry, { ...entry.status, status: "ready" });
|
|
2667
|
-
schedulePendingWebuiFlush(entry);
|
|
2668
|
-
} else if (entry.status.status === "ready") {
|
|
2669
|
-
setEntryWebuiStatus(entry, { ...entry.status, status: "loading" });
|
|
2670
|
-
}
|
|
2671
|
-
});
|
|
2672
|
-
ipcMain.on(IPC.webuiPrefsChanged, (event, prefs) => {
|
|
2673
|
-
const entry = findWebuiEntryBySenderId(event.sender.id);
|
|
2674
|
-
if (!entry) return;
|
|
2675
|
-
const next = {};
|
|
2676
|
-
if (isRecord2(prefs) && typeof prefs["yolo"] === "boolean") next.yolo = prefs["yolo"];
|
|
2677
|
-
if (isRecord2(prefs) && typeof prefs["nextPrediction"] === "boolean") {
|
|
2678
|
-
next.nextPrediction = prefs["nextPrediction"];
|
|
2679
|
-
}
|
|
2680
|
-
if (isRecord2(prefs) && typeof prefs["contextAutoCompact"] === "boolean") {
|
|
2681
|
-
next.contextAutoCompact = prefs["contextAutoCompact"];
|
|
2682
|
-
}
|
|
2683
|
-
if (Object.keys(next).length === 0) return;
|
|
2684
|
-
setEntryWebuiStatus(entry, {
|
|
2685
|
-
...entry.status,
|
|
2686
|
-
prefs: { ...entry.status.prefs ?? {}, ...next }
|
|
2687
|
-
});
|
|
2688
|
-
});
|
|
2689
|
-
ipcMain.on(
|
|
2690
|
-
IPC.webuiCommandAck,
|
|
2691
|
-
(event, requestId, handled, _message) => {
|
|
2692
|
-
const entry = findWebuiEntryBySenderId(event.sender.id);
|
|
2693
|
-
if (!entry || typeof requestId !== "string") return;
|
|
2694
|
-
const pending = pendingWebuiCommandAcks.get(requestId);
|
|
2695
|
-
if (!pending || pending.runtimeId !== entry.runtimeId) return;
|
|
2696
|
-
settlePendingWebuiCommandAck(requestId, handled === true);
|
|
2697
|
-
}
|
|
2698
|
-
);
|
|
2699
|
-
ipcMain.on(IPC.setLocale, (_event, locale) => {
|
|
2700
|
-
setMainLocale(locale);
|
|
2701
|
-
configureApplicationMenu2();
|
|
2702
|
-
broadcastLocaleToEmbeddedWebuis(locale);
|
|
2703
|
-
void writeUiLocale(locale);
|
|
2704
|
-
});
|
|
2983
|
+
function buildIpcHandlerContext() {
|
|
2984
|
+
return {
|
|
2985
|
+
getMainWindow: () => mainWindow,
|
|
2986
|
+
getShellView: () => shellView,
|
|
2987
|
+
getWebuiViews: () => webuiViews,
|
|
2988
|
+
getWebuiStatus: () => webuiStatus,
|
|
2989
|
+
getRuntimeManager: () => manager,
|
|
2990
|
+
getAgentBridge: () => bridge,
|
|
2991
|
+
getI18n: () => ({ getMainLocale, setMainLocale, tMain }),
|
|
2992
|
+
getConfigIo: () => ({ desktopConfigPaths, readUiLocale, writeUiLocale }),
|
|
2993
|
+
getShellSidebarCollapsed: () => shellSidebarCollapsed,
|
|
2994
|
+
setShellSidebarCollapsed: (collapsed) => setShellSidebarCollapsed(collapsed),
|
|
2995
|
+
broadcastState: () => broadcastState(),
|
|
2996
|
+
publishWebuiStatus: (next) => publishWebuiStatus(next),
|
|
2997
|
+
syncActiveWebuiView: () => syncActiveWebuiView(),
|
|
2998
|
+
configureApplicationMenu: () => configureApplicationMenu2(),
|
|
2999
|
+
broadcastLocaleToEmbeddedWebuis: (locale) => broadcastLocaleToEmbeddedWebuis(locale),
|
|
3000
|
+
dispatchWebuiCommand: (command) => dispatchWebuiCommand(command),
|
|
3001
|
+
reloadActiveWebuiView: () => reloadActiveWebuiView(),
|
|
3002
|
+
openProject: (root) => openProject(root),
|
|
3003
|
+
registerProject: (root) => registerProject(root),
|
|
3004
|
+
unregisterProject: (root) => unregisterProject(root),
|
|
3005
|
+
openProjectSession: (id) => openProjectSession(id),
|
|
3006
|
+
activateRuntime: (id) => activateRuntime(id),
|
|
3007
|
+
closeRuntime: (id) => closeRuntime(id),
|
|
3008
|
+
openSettings: () => openSettings(),
|
|
3009
|
+
sendMessage: (id, wsUrl, content) => bridge.sendMessage(id, wsUrl, content),
|
|
3010
|
+
abortRuntime: (id, wsUrl) => bridge.abort(id, wsUrl),
|
|
3011
|
+
openExternal: (url) => safeOpenExternal(url),
|
|
3012
|
+
revealInExplorer: (root) => {
|
|
3013
|
+
revealInExplorer(root);
|
|
3014
|
+
},
|
|
3015
|
+
findWebuiEntryBySenderId: (senderId) => findWebuiEntryBySenderId(senderId),
|
|
3016
|
+
getPendingWebuiCommandAcks: () => pendingWebuiCommandAcks,
|
|
3017
|
+
settlePendingWebuiCommandAck: (requestId, handled) => settlePendingWebuiCommandAck(requestId, handled),
|
|
3018
|
+
setEntryWebuiStatus: (entry, next) => setEntryWebuiStatus(entry, next),
|
|
3019
|
+
schedulePendingWebuiFlush: (entry) => schedulePendingWebuiFlush(entry)
|
|
3020
|
+
};
|
|
2705
3021
|
}
|
|
2706
3022
|
async function boot() {
|
|
2707
3023
|
const locale = await readUiLocale();
|
|
@@ -2719,18 +3035,44 @@ async function boot() {
|
|
|
2719
3035
|
safeOpenExternal(url);
|
|
2720
3036
|
return { action: "deny" };
|
|
2721
3037
|
});
|
|
2722
|
-
registerIpcHandlers();
|
|
3038
|
+
registerIpcHandlers(buildIpcHandlerContext());
|
|
2723
3039
|
await shellView.webContents.loadURL(shellUrl);
|
|
2724
3040
|
const prevState = validatedWindowState(manager.getWindowState());
|
|
2725
3041
|
const defaultWidth = 1180;
|
|
2726
3042
|
const defaultHeight = 720;
|
|
3043
|
+
let appIcon;
|
|
3044
|
+
if (process.platform !== "darwin") {
|
|
3045
|
+
try {
|
|
3046
|
+
const iconPath = new URL("../../assets/icon.svg", import.meta.url).pathname;
|
|
3047
|
+
await fs3.stat(iconPath);
|
|
3048
|
+
appIcon = nativeImage.createFromPath(iconPath);
|
|
3049
|
+
if (appIcon.isEmpty()) appIcon = void 0;
|
|
3050
|
+
} catch {
|
|
3051
|
+
}
|
|
3052
|
+
} else {
|
|
3053
|
+
try {
|
|
3054
|
+
const pngPath = new URL("../../assets/icon.png", import.meta.url).pathname;
|
|
3055
|
+
await fs3.stat(pngPath);
|
|
3056
|
+
appIcon = nativeImage.createFromPath(pngPath);
|
|
3057
|
+
if (appIcon.isEmpty()) appIcon = void 0;
|
|
3058
|
+
} catch {
|
|
3059
|
+
try {
|
|
3060
|
+
const icnsPath = new URL("../../assets/icon.icns", import.meta.url).pathname;
|
|
3061
|
+
await fs3.stat(icnsPath);
|
|
3062
|
+
appIcon = nativeImage.createFromPath(icnsPath);
|
|
3063
|
+
if (appIcon.isEmpty()) appIcon = void 0;
|
|
3064
|
+
} catch {
|
|
3065
|
+
}
|
|
3066
|
+
}
|
|
3067
|
+
}
|
|
2727
3068
|
const winOptions = {
|
|
2728
3069
|
width: prevState?.width ?? defaultWidth,
|
|
2729
3070
|
height: prevState?.height ?? defaultHeight,
|
|
2730
3071
|
show: false,
|
|
2731
3072
|
minWidth: MIN_WINDOW_WIDTH2,
|
|
2732
3073
|
minHeight: MIN_WINDOW_HEIGHT2,
|
|
2733
|
-
title: tMain("windowTitle")
|
|
3074
|
+
title: tMain("windowTitle"),
|
|
3075
|
+
...appIcon ? { icon: appIcon } : {}
|
|
2734
3076
|
};
|
|
2735
3077
|
if (prevState) {
|
|
2736
3078
|
if (prevState.x !== void 0) winOptions.x = prevState.x;
|
|
@@ -2757,6 +3099,11 @@ async function boot() {
|
|
|
2757
3099
|
configureApplicationMenu2();
|
|
2758
3100
|
broadcastState();
|
|
2759
3101
|
});
|
|
3102
|
+
app2.on("open-file", (_event, filePath) => {
|
|
3103
|
+
if (shellView && !shellView.webContents.isDestroyed()) {
|
|
3104
|
+
shellView.webContents.send(IPC.openFile, filePath);
|
|
3105
|
+
}
|
|
3106
|
+
});
|
|
2760
3107
|
let lastWatchedLocale;
|
|
2761
3108
|
watchProviderConfig(
|
|
2762
3109
|
desktopConfigPaths.globalConfigPath,
|
|
@@ -2780,17 +3127,25 @@ async function boot() {
|
|
|
2780
3127
|
disposeAllWebuiEntries();
|
|
2781
3128
|
void saveWindowState();
|
|
2782
3129
|
quittingAfterCleanup = true;
|
|
2783
|
-
|
|
3130
|
+
app2.exit(0);
|
|
2784
3131
|
});
|
|
2785
3132
|
await restoreLastWorkspace();
|
|
3133
|
+
const argvOpenPath = firstOpenFileArg(process.argv);
|
|
3134
|
+
const queuedOpenPath = drainPendingOpenFilePath();
|
|
3135
|
+
const openPath = argvOpenPath ?? queuedOpenPath;
|
|
3136
|
+
if (openPath && shellView && !shellView.webContents.isDestroyed()) {
|
|
3137
|
+
shellView.webContents.send(IPC.openFile, openPath);
|
|
3138
|
+
}
|
|
2786
3139
|
mainWindow.show();
|
|
2787
3140
|
shellView.webContents.focus();
|
|
2788
3141
|
}
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
3142
|
+
app2.whenReady().then(boot);
|
|
3143
|
+
app2.on("window-all-closed", () => {
|
|
3144
|
+
if (process.platform !== "darwin") {
|
|
3145
|
+
app2.quit();
|
|
3146
|
+
}
|
|
2792
3147
|
});
|
|
2793
|
-
|
|
3148
|
+
app2.on("before-quit", () => {
|
|
2794
3149
|
if (mainWindow) {
|
|
2795
3150
|
mainWindow.removeAllListeners("close");
|
|
2796
3151
|
void saveWindowState();
|
|
@@ -2798,7 +3153,7 @@ app.on("before-quit", () => {
|
|
|
2798
3153
|
bridge.closeAll();
|
|
2799
3154
|
disposeAllWebuiEntries();
|
|
2800
3155
|
});
|
|
2801
|
-
|
|
3156
|
+
app2.on("activate", () => {
|
|
2802
3157
|
if (!mainWindow) return;
|
|
2803
3158
|
mainWindow.show();
|
|
2804
3159
|
shellView?.webContents.focus();
|