@wrongstack/desktop 0.309.0 → 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 CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/main/main.ts
2
- import * as path5 from "node:path";
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 path6 = pendingOpenFilePath;
43
+ const path7 = pendingOpenFilePath;
44
44
  pendingOpenFilePath = null;
45
- return path6;
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((resolve3, reject) => {
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
- resolve3();
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((resolve3) => {
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
- resolve3(exited);
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((resolve3) => {
1481
+ await new Promise((resolve4) => {
1482
1482
  let settled = false;
1483
1483
  const finish = () => {
1484
1484
  if (settled) return;
1485
1485
  settled = true;
1486
- resolve3();
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((resolve3) => {
1631
+ return new Promise((resolve4) => {
1632
1632
  const server = net.createServer();
1633
- server.once("error", () => resolve3(false));
1633
+ server.once("error", () => resolve4(false));
1634
1634
  server.once("listening", () => {
1635
- server.close(() => resolve3(true));
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((resolve3, reject) => {
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
- resolve3();
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((resolve3) => {
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: resolve3 });
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(pathSchema, requestedRoot);
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(pathSchema, requestedRoot);
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(pathSchema.transform(() => String(content ?? "")), content);
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(IPC.webuiCommandAck, (event, requestId, handled, _message) => {
2961
- const entry = ctx.findWebuiEntryBySenderId(event.sender.id);
2962
- if (!entry) return;
2963
- const result = validate(webuiCommandAckSchema, {
2964
- requestId,
2965
- handled,
2966
- message: _message
2967
- });
2968
- if (!result.success) {
2969
- validationLogger.log(`webuiCommandAck: ${result.error}`);
2970
- return;
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
- const pending = ctx.getPendingWebuiCommandAcks().get(result.data.requestId);
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
- path5.join(
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(path5.dirname(root)).catch(() => void 0);
3088
+ void shell2.openPath(path6.dirname(root)).catch(() => void 0);
3069
3089
  }
3070
3090
  console.error(
3071
3091
  JSON.stringify({