@love-moon/conductor-cli 0.13.2 → 0.13.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @love-moon/conductor-cli
2
2
 
3
+ ## 0.13.3
4
+
5
+ ### Patch Changes
6
+
7
+ - 9858ad5: Fix Update daemon deleting the running install when the upgrade failed. Any
8
+ failed `npm install -g` (a timeout on a slow registry, a node-gyp error) used to
9
+ trigger an uninstall plus `rm -rf` of the global package before one retry. When
10
+ the retry also failed, the daemon kept running with its files gone and every new
11
+ task died at Fire launch with `MODULE_NOT_FOUND`. The clear-and-retry now only
12
+ runs on `ENOTEMPTY`, and it moves the old install aside and restores it if the
13
+ retry fails.
14
+ - Updated dependencies [0859251]
15
+ - Updated dependencies [c1b66d1]
16
+ - Updated dependencies [f6dbd6b]
17
+ - @love-moon/ai-sdk@0.13.3
18
+ - @love-moon/conductor-sdk@0.13.3
19
+
3
20
  ## 0.13.2
4
21
 
5
22
  ### Patch Changes
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@love-moon/conductor-cli",
3
- "version": "0.13.2",
4
- "gitCommitId": "d60a6a2",
3
+ "version": "0.13.3",
4
+ "gitCommitId": "d61c070",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/lovemoon-ai/conductor.git"
@@ -24,8 +24,8 @@
24
24
  "test": "node --test test/*.test.js"
25
25
  },
26
26
  "dependencies": {
27
- "@love-moon/ai-sdk": "0.13.2",
28
- "@love-moon/conductor-sdk": "0.13.2",
27
+ "@love-moon/ai-sdk": "0.13.3",
28
+ "@love-moon/conductor-sdk": "0.13.3",
29
29
  "@github/copilot-sdk": "^0.3.0",
30
30
  "chrome-launcher": "^1.2.1",
31
31
  "chrome-remote-interface": "^0.33.0",
@@ -38,7 +38,7 @@
38
38
  },
39
39
  "optionalDependencies": {
40
40
  "@roamhq/wrtc": "^0.10.0",
41
- "@love-moon/chat-web": "0.13.2"
41
+ "@love-moon/chat-web": "0.13.3"
42
42
  },
43
43
  "pnpm": {
44
44
  "onlyBuiltDependencies": [
@@ -272,17 +272,6 @@ function buildInstallCommand(packageManager, pkgSpec) {
272
272
  }
273
273
  }
274
274
 
275
- function buildUninstallCommand(packageManager, packageName) {
276
- switch (packageManager) {
277
- case "pnpm":
278
- return { command: "pnpm", args: ["remove", "-g", packageName] };
279
- case "yarn":
280
- return { command: "yarn", args: ["global", "remove", packageName] };
281
- default:
282
- return { command: "npm", args: ["uninstall", "-g", packageName] };
283
- }
284
- }
285
-
286
275
  /**
287
276
  * `npm install -g` targets whichever npm wins the PATH lookup, which is not
288
277
  * necessarily the one that installed us. Pin it to the prefix the running
@@ -320,6 +309,7 @@ export async function runDaemonUpdate(params = {}, deps = {}) {
320
309
  const killFn = deps.kill || process.kill.bind(process);
321
310
  const readFileSync = deps.readFileSync || fs.readFileSync;
322
311
  const rmSync = deps.rmSync || fs.rmSync;
312
+ const renameSync = deps.renameSync || fs.renameSync;
323
313
  const sleep = deps.sleep || ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
324
314
  const now = deps.now || (() => Date.now());
325
315
  const writeStatus = deps.writeStatus || writeDaemonUpdateStatus;
@@ -422,25 +412,43 @@ export async function runDaemonUpdate(params = {}, deps = {}) {
422
412
 
423
413
  log(`${install.command} ${install.args.join(" ")}`);
424
414
  let installResult = await runInstall();
425
- if (!installResult.success) {
426
- // A half-removed global install makes npm fail with ENOTEMPTY forever.
427
- // Clear it out and try once more before giving up.
428
- log(`install failed (exit ${installResult.code}); removing the broken install and retrying`);
415
+ // A half-removed global install makes npm fail with ENOTEMPTY forever. Move
416
+ // it aside and try once more. Any other failure (timeout, network, build)
417
+ // leaves the install untouched: the daemon and every fire it spawns run
418
+ // from that directory.
419
+ if (!installResult.success && /ENOTEMPTY/.test(`${installResult.stderr}${installResult.stdout}`)) {
420
+ log(`install failed (exit ${installResult.code}); moving the broken install aside and retrying`);
429
421
  log(String(installResult.stderr || installResult.stdout || "").trim().slice(-800));
430
- const uninstall = buildUninstallCommand(packageManager, packageName);
431
- await runCommand(uninstall.command, uninstall.args, { env: installEnv, timeoutMs: INSTALL_TIMEOUT_MS });
422
+ let packageDirectory = null;
423
+ let backupDirectory = null;
432
424
  try {
433
- const packageDirectory = await resolveGlobalPackageDirectory({
425
+ packageDirectory = await resolveGlobalPackageDirectory({
434
426
  packageManager,
435
427
  packageName,
436
428
  runCommand: (command, args, options) => runCommand(command, args, { env: installEnv, ...options }),
437
429
  });
438
- rmSync(packageDirectory, { recursive: true, force: true });
439
- log(`removed ${packageDirectory}`);
430
+ const backup = path.join(path.dirname(packageDirectory), `.${path.basename(packageDirectory)}-update-backup`);
431
+ rmSync(backup, { recursive: true, force: true });
432
+ renameSync(packageDirectory, backup);
433
+ backupDirectory = backup;
434
+ log(`moved ${packageDirectory} aside`);
440
435
  } catch (error) {
441
- log(`could not remove the global package directory: ${error?.message || error}`);
436
+ log(`could not move the global package directory aside: ${error?.message || error}`);
442
437
  }
443
438
  installResult = await runInstall();
439
+ if (backupDirectory) {
440
+ try {
441
+ if (installResult.success) {
442
+ rmSync(backupDirectory, { recursive: true, force: true });
443
+ } else {
444
+ rmSync(packageDirectory, { recursive: true, force: true });
445
+ renameSync(backupDirectory, packageDirectory);
446
+ log(`restored ${packageDirectory}`);
447
+ }
448
+ } catch (error) {
449
+ log(`could not clean up ${backupDirectory}: ${error?.message || error}`);
450
+ }
451
+ }
444
452
  }
445
453
  if (!installResult.success) {
446
454
  return fail(