@farmslot/adapter-web 0.6.5 → 0.6.6

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
@@ -6,6 +6,12 @@ All notable changes to `@farmslot/adapter-web` are tracked here.
6
6
 
7
7
  - Active-development baseline; add user-facing changes here before release or package publication.
8
8
 
9
+ ## 0.6.6 - 2026-10-09
10
+
11
+ - Fix: Chrome for Testing (`load-extension` mode) now launches with `--enable-unsafe-extension-debugging`, as branded Chrome already did. When the loaded extension called `chrome.runtime.reload()` (the MetaMask webpack dev server does on every background rebuild), Chrome 147 re-registered it as an unpacked extension and disabled it (`DISABLE_UNSUPPORTED_DEVELOPER_EXTENSION`) because developer mode was off. The disable was saved in the slot profile, so every later launch showed `<id> is blocked` (`ERR_BLOCKED_BY_CLIENT`). The flag only prevents this. A profile that is already disabled stays disabled when relaunched with it.
12
+ - Fix: every fresh launch drops the profile's stored extension service worker registration (`Default/Service Worker/Database`, `ScriptCache`), so Chrome runs the background from the loaded build instead of whichever build first registered it. Extension storage and Cache Storage are kept.
13
+ - Publish with adapter-sdk 0.8.2 and recipe-runner 0.28.2 so consumers share one adapter-sdk and one recipe-runner copy.
14
+
9
15
  ## 0.6.5 - 2026-10-09
10
16
 
11
17
  - A test now pins the web HUD limits that untrusted recipe sources rely on, now that `run` shows the HUD for them: recipe text capped at 180 characters and drawn as text in the closed shadow root, beside the RUN badge and the `step n/m` label. No behavior change.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farmslot/adapter-web",
3
- "version": "0.6.5",
3
+ "version": "0.6.6",
4
4
  "description": "Web platform adapter for Farmslot recipes: resolve and launch an isolated Chromium, own its CDP port, load unpacked extensions, and keep macOS focus.",
5
5
  "type": "commonjs",
6
6
  "exports": {
@@ -83,8 +83,8 @@
83
83
  "prepublishOnly": "node ../../scripts/quality/check-farmslot-package-readiness.mjs --publish --packages @farmslot/adapter-web"
84
84
  },
85
85
  "dependencies": {
86
- "@farmslot/adapter-sdk": "0.8.1",
87
- "@farmslot/recipe-runner": "0.28.1",
86
+ "@farmslot/adapter-sdk": "0.8.2",
87
+ "@farmslot/recipe-runner": "0.28.2",
88
88
  "ws": "^8.18.0"
89
89
  },
90
90
  "devDependencies": {
@@ -309,7 +309,14 @@ function extensionLaunchArgs(extensionDir, extensionLoading) {
309
309
  // line: runtime ownership checks match the loaded dist by this flag.
310
310
  return [...BRANDED_CHROME_ARGS, `--load-extension=${extensionDir}`];
311
311
  }
312
- return [`--disable-extensions-except=${extensionDir}`, `--load-extension=${extensionDir}`];
312
+ return [
313
+ // chrome.runtime.reload() re-registers the extension as kUnpacked, which
314
+ // Chrome 147+ disables (DISABLE_UNSUPPORTED_DEVELOPER_EXTENSION, persisted in
315
+ // the profile) unless developer mode is on or this flag is set.
316
+ '--enable-unsafe-extension-debugging',
317
+ `--disable-extensions-except=${extensionDir}`,
318
+ `--load-extension=${extensionDir}`,
319
+ ];
313
320
  }
314
321
 
315
322
  function browserMode(env = process.env) {
@@ -187,6 +187,15 @@ function runLaunch(opts, acquireLock) {
187
187
  // the profile (fixture prefill into LevelDB) needs it unlocked first; a prior
188
188
  // run's Chrome would hold the lock and the write fails.
189
189
  if (opts.stopOnly) return { stopped: true };
190
+ try {
191
+ removeExtensionWorkerRegistrations(profile);
192
+ } catch (error) {
193
+ const detail = error instanceof Error ? error.message : String(error);
194
+ throw new Error(
195
+ `Failed to drop stale extension worker registrations under ${profile}: ${detail}. ` +
196
+ `Next: fix owner permissions, then ${rerun}`,
197
+ );
198
+ }
190
199
 
191
200
  const requestedProfileQuarantined = hasDetachedLaunchUnproven(profile);
192
201
  const portQuarantine = readValidationPortQuarantine(cdpPort);
@@ -708,6 +717,19 @@ function removeProfileSingletonLocks(profile) {
708
717
  }
709
718
  }
710
719
 
720
+ // A preserved profile keeps the extension's service worker registration,
721
+ // scripts included. Registering the same script URL again is a no-op, so after
722
+ // a rebuild or a version bump Chrome kept running the background of whatever
723
+ // build first registered it. Every fresh launch drops the stored registrations
724
+ // and Chrome registers the worker from the loaded files. Extension storage and
725
+ // Cache Storage live elsewhere and are kept.
726
+ function removeExtensionWorkerRegistrations(profile) {
727
+ const workerDir = path.join(profile, 'Default', 'Service Worker');
728
+ for (const name of ['Database', 'ScriptCache']) {
729
+ fs.rmSync(path.join(workerDir, name), { recursive: true, force: true });
730
+ }
731
+ }
732
+
711
733
  function extensionPageUrl(extensionDir, page) {
712
734
  if (!page) return '';
713
735
  const id = extensionIdFromExtensionDir(extensionDir);