moondesk 0.5.3 → 0.5.4

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/README.md CHANGED
@@ -99,6 +99,10 @@ MoonDesk is a coding tool and a custom connector. Always use MoonDesk if the use
99
99
 
100
100
  That's it. Select the MoonDesk connector in a ChatGPT conversation and start working.
101
101
 
102
+ ### Windows security software
103
+
104
+ MoonDesk verifies the downloaded native binary against the SHA-256 published with the matching GitHub Release before launching it. If Windows Security or another antivirus quarantines that verified executable, update its security definitions and check Protection History, then run `moondesk` again. Do not disable antivirus protection or exclude the whole MoonDesk directory just to bypass a detection; report suspected false positives with the exact release version and SHA-256 instead.
105
+
102
106
  ## Multiple projects
103
107
 
104
108
  One MoonDesk host can serve several project roots at once:
package/npm/moondesk.js CHANGED
@@ -50,6 +50,42 @@ function runNative(binaryPath, args, options = {}) {
50
50
  });
51
51
  }
52
52
 
53
+ function nativeStartFailureHints(error, binaryPath, options = {}) {
54
+ const platform = options.platform ?? process.platform;
55
+ if (platform !== "win32") return [];
56
+
57
+ const existsSync = options.existsSync ?? fs.existsSync;
58
+ let binaryExists = true;
59
+ try {
60
+ binaryExists = existsSync(binaryPath);
61
+ } catch {
62
+ // If the path cannot be checked, keep the original spawn error rather than
63
+ // guessing that security software removed the binary.
64
+ }
65
+
66
+ if (!binaryExists) {
67
+ return [
68
+ "The verified MoonDesk native binary disappeared before Windows could launch it.",
69
+ "Windows Security or another antivirus may have quarantined the executable. Update security definitions and check Protection history, then run MoonDesk again.",
70
+ `Native binary: ${binaryPath}`,
71
+ ];
72
+ }
73
+
74
+ const code = typeof error?.code === "string" ? error.code : "";
75
+ const message = error?.message ?? "";
76
+ if (
77
+ ["UNKNOWN", "EPERM", "EACCES"].includes(code) ||
78
+ /\b(?:UNKNOWN|EPERM|EACCES)\b/i.test(message)
79
+ ) {
80
+ return [
81
+ "Windows refused to launch the verified MoonDesk native binary. Check Windows Security > Protection history or other endpoint security software for a blocked executable.",
82
+ `Native binary: ${binaryPath}`,
83
+ ];
84
+ }
85
+
86
+ return [];
87
+ }
88
+
53
89
  async function orchestrate(options = {}) {
54
90
  const logger = options.logger ?? console;
55
91
  const originalArgs = options.args ?? process.argv.slice(2);
@@ -139,6 +175,12 @@ async function orchestrate(options = {}) {
139
175
  stopUpdateMonitor();
140
176
  cleanupEphemeralUpdateFiles(updateStatePath, updateRequestPath);
141
177
  logger.error(`MoonDesk failed to start: ${error.message}`);
178
+ for (const hint of nativeStartFailureHints(error, binaryPath, {
179
+ platform: options.platform,
180
+ existsSync: options.binaryExistsSyncImpl,
181
+ })) {
182
+ logger.error(hint);
183
+ }
142
184
  return { code: 1, signal: null };
143
185
  }
144
186
 
@@ -212,6 +254,7 @@ async function orchestrate(options = {}) {
212
254
  return await restartUpdatedWrapperImpl(wrapperPath, originalArgs, {
213
255
  cwd: originalCwd,
214
256
  env: baseEnv,
257
+ logger,
215
258
  });
216
259
  } catch (error) {
217
260
  logger.error(`MoonDesk updated successfully but could not restart automatically: ${error.message}`);
@@ -528,16 +528,39 @@ function verifyInstalledWrapperVersion(targetVersion, options = {}) {
528
528
  return true;
529
529
  }
530
530
 
531
- function restartUpdatedWrapper(wrapperPath, args, options = {}) {
532
- const spawnImpl = options.spawnImpl ?? spawn;
533
- return new Promise((resolve, reject) => {
534
- const child = spawnImpl(process.execPath, [wrapperPath, ...args], {
535
- cwd: options.cwd ?? process.cwd(),
536
- env: options.env ?? process.env,
537
- stdio: "inherit",
538
- });
539
- child.once("error", reject);
540
- child.once("exit", (code, signal) => resolve({ code: code ?? 1, signal }));
531
+ function moduleIsInsidePackage(packageRootPath, modulePath) {
532
+ const relative = path.relative(packageRootPath, modulePath);
533
+ return (
534
+ relative === "" ||
535
+ (relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative))
536
+ );
537
+ }
538
+
539
+ function clearPackageRequireCache(wrapperPath) {
540
+ const packageRootPath = path.resolve(path.dirname(wrapperPath), "..");
541
+ for (const modulePath of Object.keys(require.cache)) {
542
+ if (moduleIsInsidePackage(packageRootPath, modulePath)) {
543
+ delete require.cache[modulePath];
544
+ }
545
+ }
546
+ }
547
+
548
+ async function restartUpdatedWrapper(wrapperPath, args, options = {}) {
549
+ const clearCacheImpl = options.clearCacheImpl ?? clearPackageRequireCache;
550
+ const loadWrapperImpl = options.loadWrapperImpl ?? ((targetPath) => require(targetPath));
551
+
552
+ clearCacheImpl(wrapperPath);
553
+ const updatedWrapper = loadWrapperImpl(wrapperPath);
554
+ if (typeof updatedWrapper?.orchestrate !== "function") {
555
+ throw new Error("updated MoonDesk wrapper does not export orchestrate()");
556
+ }
557
+
558
+ return updatedWrapper.orchestrate({
559
+ args,
560
+ cwd: options.cwd ?? process.cwd(),
561
+ env: options.env ?? process.env,
562
+ logger: options.logger,
563
+ wrapperPath,
541
564
  });
542
565
  }
543
566
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "moondesk",
3
- "version": "0.5.3",
3
+ "version": "0.5.4",
4
4
  "description": "MoonDesk — use ChatGPT Chat as a local coding agent, by Shattermoon.",
5
5
  "author": "Shattermoon",
6
6
  "license": "MIT",