@wrongstack/desktop 0.308.7 → 0.309.1
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 +56 -36
- package/dist/main/main.js.map +3 -3
- package/package.json +6 -6
package/dist/main/main.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/main/main.ts
|
|
2
|
-
import * as
|
|
2
|
+
import * as path6 from "node:path";
|
|
3
3
|
import { installCrashShield, resolveWstackPaths as resolveWstackPaths3 } from "@wrongstack/core/utils";
|
|
4
4
|
import {
|
|
5
5
|
app as app2,
|
|
@@ -40,9 +40,9 @@ function handleFileOpen(filePath) {
|
|
|
40
40
|
}
|
|
41
41
|
var pendingOpenFilePath = null;
|
|
42
42
|
function drainPendingOpenFilePath() {
|
|
43
|
-
const
|
|
43
|
+
const path7 = pendingOpenFilePath;
|
|
44
44
|
pendingOpenFilePath = null;
|
|
45
|
-
return
|
|
45
|
+
return path7;
|
|
46
46
|
}
|
|
47
47
|
function firstOpenFileArg(argv) {
|
|
48
48
|
if (process.platform !== "darwin") return null;
|
|
@@ -147,7 +147,7 @@ var DesktopAgentBridge = class extends EventEmitter {
|
|
|
147
147
|
conversation.error = void 0;
|
|
148
148
|
this.emitChanged(conversation);
|
|
149
149
|
this.emitReconnectEvent(conversation, "connecting");
|
|
150
|
-
const promise = new Promise((
|
|
150
|
+
const promise = new Promise((resolve4, reject) => {
|
|
151
151
|
const ws = new WebSocket(wsUrl);
|
|
152
152
|
conversation.ws = ws;
|
|
153
153
|
const myGeneration = ++conversation.socketGeneration;
|
|
@@ -172,7 +172,7 @@ var DesktopAgentBridge = class extends EventEmitter {
|
|
|
172
172
|
conversation.connectionState = markConnectionOpen(conversation.connectionState);
|
|
173
173
|
this.emitChanged(conversation);
|
|
174
174
|
this.emitReconnectEvent(conversation, "connected");
|
|
175
|
-
|
|
175
|
+
resolve4();
|
|
176
176
|
});
|
|
177
177
|
ws.once("error", (err) => {
|
|
178
178
|
clearTimeout(timeout);
|
|
@@ -1445,14 +1445,14 @@ function hasChildExited(child) {
|
|
|
1445
1445
|
}
|
|
1446
1446
|
function waitForChildExit(child, timeoutMs) {
|
|
1447
1447
|
if (hasChildExited(child)) return Promise.resolve(true);
|
|
1448
|
-
return new Promise((
|
|
1448
|
+
return new Promise((resolve4) => {
|
|
1449
1449
|
let settled = false;
|
|
1450
1450
|
const finish = (exited) => {
|
|
1451
1451
|
if (settled) return;
|
|
1452
1452
|
settled = true;
|
|
1453
1453
|
clearTimeout(timer);
|
|
1454
1454
|
child.off("exit", onExit);
|
|
1455
|
-
|
|
1455
|
+
resolve4(exited);
|
|
1456
1456
|
};
|
|
1457
1457
|
const onExit = () => finish(true);
|
|
1458
1458
|
const timer = setTimeout(() => finish(hasChildExited(child)), timeoutMs);
|
|
@@ -1478,12 +1478,12 @@ async function terminateProcessTree(child) {
|
|
|
1478
1478
|
}
|
|
1479
1479
|
return;
|
|
1480
1480
|
}
|
|
1481
|
-
await new Promise((
|
|
1481
|
+
await new Promise((resolve4) => {
|
|
1482
1482
|
let settled = false;
|
|
1483
1483
|
const finish = () => {
|
|
1484
1484
|
if (settled) return;
|
|
1485
1485
|
settled = true;
|
|
1486
|
-
|
|
1486
|
+
resolve4();
|
|
1487
1487
|
};
|
|
1488
1488
|
const timer = setTimeout(finish, 3e3);
|
|
1489
1489
|
timer.unref?.();
|
|
@@ -1628,11 +1628,11 @@ async function findFreePort(startPort, exclude) {
|
|
|
1628
1628
|
throw new Error(`No free local port found near ${startPort}`);
|
|
1629
1629
|
}
|
|
1630
1630
|
function isPortFree(port) {
|
|
1631
|
-
return new Promise((
|
|
1631
|
+
return new Promise((resolve4) => {
|
|
1632
1632
|
const server = net.createServer();
|
|
1633
|
-
server.once("error", () =>
|
|
1633
|
+
server.once("error", () => resolve4(false));
|
|
1634
1634
|
server.once("listening", () => {
|
|
1635
|
-
server.close(() =>
|
|
1635
|
+
server.close(() => resolve4(true));
|
|
1636
1636
|
});
|
|
1637
1637
|
server.listen(port, "127.0.0.1");
|
|
1638
1638
|
});
|
|
@@ -1642,7 +1642,7 @@ function waitForHttpReady(baseUrl, token, timeoutMs) {
|
|
|
1642
1642
|
const url = new URL(baseUrl);
|
|
1643
1643
|
url.searchParams.set("token", token);
|
|
1644
1644
|
url.searchParams.set("shell", "desktop");
|
|
1645
|
-
return new Promise((
|
|
1645
|
+
return new Promise((resolve4, reject) => {
|
|
1646
1646
|
let probeTimer;
|
|
1647
1647
|
const cleanup = () => {
|
|
1648
1648
|
if (probeTimer) {
|
|
@@ -1667,7 +1667,7 @@ function waitForHttpReady(baseUrl, token, timeoutMs) {
|
|
|
1667
1667
|
if (!done) {
|
|
1668
1668
|
done = true;
|
|
1669
1669
|
cleanup();
|
|
1670
|
-
|
|
1670
|
+
resolve4();
|
|
1671
1671
|
}
|
|
1672
1672
|
return;
|
|
1673
1673
|
}
|
|
@@ -2185,14 +2185,14 @@ var DesktopWebuiController = class {
|
|
|
2185
2185
|
if (this.views.get(entry.runtimeId) !== entry || !entry.url) return Promise.resolve(false);
|
|
2186
2186
|
const requestId = `${entry.runtimeId}:${Date.now()}:${++this.commandSequence}`;
|
|
2187
2187
|
const outbound = { ...command, requestId };
|
|
2188
|
-
return new Promise((
|
|
2188
|
+
return new Promise((resolve4) => {
|
|
2189
2189
|
const fallbackTimer = setTimeout(() => {
|
|
2190
2190
|
if (!this.pendingAcks.has(requestId)) return;
|
|
2191
2191
|
if (this.views.get(entry.runtimeId) !== entry || entry.view.webContents.isDestroyed()) return;
|
|
2192
2192
|
void entry.view.webContents.executeJavaScript(buildWebuiCommandFallbackScript(outbound), true).catch(() => void 0);
|
|
2193
2193
|
}, WEBUI_COMMAND_FALLBACK_MS);
|
|
2194
2194
|
const timer = setTimeout(() => this.settleAck(requestId, false), WEBUI_COMMAND_ACK_TIMEOUT_MS);
|
|
2195
|
-
this.pendingAcks.set(requestId, { runtimeId: entry.runtimeId, timer, fallbackTimer, resolve:
|
|
2195
|
+
this.pendingAcks.set(requestId, { runtimeId: entry.runtimeId, timer, fallbackTimer, resolve: resolve4 });
|
|
2196
2196
|
try {
|
|
2197
2197
|
entry.view.webContents.send(IPC.webuiCommand, outbound);
|
|
2198
2198
|
if (this.activeRuntimeId === entry.runtimeId) entry.view.webContents.focus();
|
|
@@ -2772,10 +2772,24 @@ function createValidationLogger(prefix) {
|
|
|
2772
2772
|
}
|
|
2773
2773
|
|
|
2774
2774
|
// src/main/validation/schemas.ts
|
|
2775
|
+
import { statSync } from "node:fs";
|
|
2776
|
+
import * as path5 from "node:path";
|
|
2775
2777
|
import { z } from "zod";
|
|
2776
2778
|
var RUNTIME_ID_PATTERN = /^[a-zA-Z0-9._:-]{3,120}$/;
|
|
2777
2779
|
var runtimeIdSchema = z.string().regex(RUNTIME_ID_PATTERN, "Invalid runtime ID format");
|
|
2778
2780
|
var pathSchema = z.string().min(1).max(1e4);
|
|
2781
|
+
var projectRootSchema = pathSchema.refine((value) => !value.includes("\0"), {
|
|
2782
|
+
message: "path must not contain a NUL byte"
|
|
2783
|
+
}).refine(
|
|
2784
|
+
(value) => {
|
|
2785
|
+
try {
|
|
2786
|
+
return statSync(path5.resolve(value)).isDirectory();
|
|
2787
|
+
} catch {
|
|
2788
|
+
return false;
|
|
2789
|
+
}
|
|
2790
|
+
},
|
|
2791
|
+
{ message: "path must be an existing directory" }
|
|
2792
|
+
);
|
|
2779
2793
|
var booleanSchema = z.boolean();
|
|
2780
2794
|
var numberSchema = z.number().int().finite();
|
|
2781
2795
|
var openProjectSchema = z.object({
|
|
@@ -2861,11 +2875,11 @@ function registerIpcHandlers(ctx) {
|
|
|
2861
2875
|
return ctx.openProjectSession(validated);
|
|
2862
2876
|
});
|
|
2863
2877
|
ipcMain.handle(IPC.openProject, async (_event, requestedRoot) => {
|
|
2864
|
-
const validated = validateOptional(
|
|
2878
|
+
const validated = validateOptional(projectRootSchema, requestedRoot);
|
|
2865
2879
|
return ctx.openProject(validated);
|
|
2866
2880
|
});
|
|
2867
2881
|
ipcMain.handle(IPC.registerProject, async (_event, requestedRoot) => {
|
|
2868
|
-
const validated = validateOptional(
|
|
2882
|
+
const validated = validateOptional(projectRootSchema, requestedRoot);
|
|
2869
2883
|
return ctx.registerProject(validated);
|
|
2870
2884
|
});
|
|
2871
2885
|
ipcMain.handle(IPC.unregisterProject, async (_event, root) => {
|
|
@@ -2898,7 +2912,10 @@ function registerIpcHandlers(ctx) {
|
|
|
2898
2912
|
validationLogger.log(`sendMessage (id): ${idResult.error}`);
|
|
2899
2913
|
return ctx.sendMessage("", "", "");
|
|
2900
2914
|
}
|
|
2901
|
-
const contentResult = validate(
|
|
2915
|
+
const contentResult = validate(
|
|
2916
|
+
pathSchema.transform(() => String(content ?? "")),
|
|
2917
|
+
content
|
|
2918
|
+
);
|
|
2902
2919
|
const safeContent = contentResult.success ? contentResult.data : String(content ?? "");
|
|
2903
2920
|
return ctx.sendMessage(
|
|
2904
2921
|
idResult.data,
|
|
@@ -2957,22 +2974,25 @@ function registerIpcHandlers(ctx) {
|
|
|
2957
2974
|
prefs: { ...entry.status.prefs ?? {}, ...sanitized }
|
|
2958
2975
|
});
|
|
2959
2976
|
});
|
|
2960
|
-
ipcMain.on(
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2977
|
+
ipcMain.on(
|
|
2978
|
+
IPC.webuiCommandAck,
|
|
2979
|
+
(event, requestId, handled, _message) => {
|
|
2980
|
+
const entry = ctx.findWebuiEntryBySenderId(event.sender.id);
|
|
2981
|
+
if (!entry) return;
|
|
2982
|
+
const result = validate(webuiCommandAckSchema, {
|
|
2983
|
+
requestId,
|
|
2984
|
+
handled,
|
|
2985
|
+
message: _message
|
|
2986
|
+
});
|
|
2987
|
+
if (!result.success) {
|
|
2988
|
+
validationLogger.log(`webuiCommandAck: ${result.error}`);
|
|
2989
|
+
return;
|
|
2990
|
+
}
|
|
2991
|
+
const pending = ctx.getPendingWebuiCommandAcks().get(result.data.requestId);
|
|
2992
|
+
if (!pending || pending.runtimeId !== entry.runtimeId) return;
|
|
2993
|
+
ctx.settlePendingWebuiCommandAck(result.data.requestId, result.data.handled);
|
|
2971
2994
|
}
|
|
2972
|
-
|
|
2973
|
-
if (!pending || pending.runtimeId !== entry.runtimeId) return;
|
|
2974
|
-
ctx.settlePendingWebuiCommandAck(result.data.requestId, result.data.handled);
|
|
2975
|
-
});
|
|
2995
|
+
);
|
|
2976
2996
|
ipcMain.on(IPC.setLocale, (_event, locale) => {
|
|
2977
2997
|
const result = validate(setLocaleSchema, { locale });
|
|
2978
2998
|
if (!result.success) {
|
|
@@ -3011,7 +3031,7 @@ if (process.platform === "win32") {
|
|
|
3011
3031
|
}
|
|
3012
3032
|
app2.setPath(
|
|
3013
3033
|
"userData",
|
|
3014
|
-
|
|
3034
|
+
path6.join(
|
|
3015
3035
|
resolveWstackPaths3({ projectRoot: process.cwd() }).configDir,
|
|
3016
3036
|
"desktop",
|
|
3017
3037
|
"electron-profile"
|
|
@@ -3065,7 +3085,7 @@ function revealInExplorer(root) {
|
|
|
3065
3085
|
if (!authorization.allowed) return;
|
|
3066
3086
|
return shell2.openPath(root).catch((err) => {
|
|
3067
3087
|
if (process.platform === "darwin") {
|
|
3068
|
-
void shell2.openPath(
|
|
3088
|
+
void shell2.openPath(path6.dirname(root)).catch(() => void 0);
|
|
3069
3089
|
}
|
|
3070
3090
|
console.error(
|
|
3071
3091
|
JSON.stringify({
|