@ai-agent-forge/agent-forge 0.88.5 → 0.88.7

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.
Files changed (202) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/bundled-plugins/agent-loop-policy/agent-forge.json +1 -1
  3. package/bundled-plugins/agent-loop-policy/plugin.json +1 -1
  4. package/bundled-plugins/alignment/agent-forge.json +19 -0
  5. package/bundled-plugins/alignment/dist/baseline.d.ts +12 -0
  6. package/bundled-plugins/alignment/dist/baseline.d.ts.map +1 -0
  7. package/bundled-plugins/alignment/dist/baseline.js +68 -0
  8. package/bundled-plugins/alignment/dist/baseline.js.map +1 -0
  9. package/bundled-plugins/alignment/dist/engine.d.ts +102 -0
  10. package/bundled-plugins/alignment/dist/engine.d.ts.map +1 -0
  11. package/bundled-plugins/alignment/dist/engine.js +654 -0
  12. package/bundled-plugins/alignment/dist/engine.js.map +1 -0
  13. package/bundled-plugins/alignment/dist/entry.d.ts +14 -0
  14. package/bundled-plugins/alignment/dist/entry.d.ts.map +1 -0
  15. package/bundled-plugins/alignment/dist/entry.js +23 -0
  16. package/bundled-plugins/alignment/dist/entry.js.map +1 -0
  17. package/bundled-plugins/alignment/dist/export.d.ts +15 -0
  18. package/bundled-plugins/alignment/dist/export.d.ts.map +1 -0
  19. package/bundled-plugins/alignment/dist/export.js +122 -0
  20. package/bundled-plugins/alignment/dist/export.js.map +1 -0
  21. package/bundled-plugins/alignment/dist/http-server.d.ts +33 -0
  22. package/bundled-plugins/alignment/dist/http-server.d.ts.map +1 -0
  23. package/bundled-plugins/alignment/dist/http-server.js +119 -0
  24. package/bundled-plugins/alignment/dist/http-server.js.map +1 -0
  25. package/bundled-plugins/alignment/dist/index.d.ts +24 -0
  26. package/bundled-plugins/alignment/dist/index.d.ts.map +1 -0
  27. package/bundled-plugins/alignment/dist/index.js +719 -0
  28. package/bundled-plugins/alignment/dist/index.js.map +1 -0
  29. package/bundled-plugins/alignment/dist/page.d.ts +15 -0
  30. package/bundled-plugins/alignment/dist/page.d.ts.map +1 -0
  31. package/bundled-plugins/alignment/dist/page.js +857 -0
  32. package/bundled-plugins/alignment/dist/page.js.map +1 -0
  33. package/bundled-plugins/alignment/dist/render.d.ts +40 -0
  34. package/bundled-plugins/alignment/dist/render.d.ts.map +1 -0
  35. package/bundled-plugins/alignment/dist/render.js +194 -0
  36. package/bundled-plugins/alignment/dist/render.js.map +1 -0
  37. package/bundled-plugins/alignment/dist/types.d.ts +217 -0
  38. package/bundled-plugins/alignment/dist/types.d.ts.map +1 -0
  39. package/bundled-plugins/alignment/dist/types.js +30 -0
  40. package/bundled-plugins/alignment/dist/types.js.map +1 -0
  41. package/bundled-plugins/alignment/plugin.json +12 -0
  42. package/bundled-plugins/browser-playwright/MANUAL.md +60 -0
  43. package/bundled-plugins/browser-playwright/agent-forge.json +25 -0
  44. package/bundled-plugins/browser-playwright/dist/capability.d.ts +25 -0
  45. package/bundled-plugins/browser-playwright/dist/capability.d.ts.map +1 -0
  46. package/bundled-plugins/browser-playwright/dist/capability.js +612 -0
  47. package/bundled-plugins/browser-playwright/dist/capability.js.map +1 -0
  48. package/bundled-plugins/browser-playwright/dist/entry.d.ts +13 -0
  49. package/bundled-plugins/browser-playwright/dist/entry.d.ts.map +1 -0
  50. package/bundled-plugins/browser-playwright/dist/entry.js +14 -0
  51. package/bundled-plugins/browser-playwright/dist/entry.js.map +1 -0
  52. package/bundled-plugins/browser-playwright/dist/index.d.ts +7 -0
  53. package/bundled-plugins/browser-playwright/dist/index.d.ts.map +1 -0
  54. package/bundled-plugins/browser-playwright/dist/index.js +5 -0
  55. package/bundled-plugins/browser-playwright/dist/index.js.map +1 -0
  56. package/bundled-plugins/browser-playwright/dist/operations.d.ts +69 -0
  57. package/bundled-plugins/browser-playwright/dist/operations.d.ts.map +1 -0
  58. package/bundled-plugins/browser-playwright/dist/operations.js +149 -0
  59. package/bundled-plugins/browser-playwright/dist/operations.js.map +1 -0
  60. package/bundled-plugins/browser-playwright/dist/playwright-driver.d.ts +275 -0
  61. package/bundled-plugins/browser-playwright/dist/playwright-driver.d.ts.map +1 -0
  62. package/bundled-plugins/browser-playwright/dist/playwright-driver.js +953 -0
  63. package/bundled-plugins/browser-playwright/dist/playwright-driver.js.map +1 -0
  64. package/bundled-plugins/browser-playwright/dist/setup.d.ts +88 -0
  65. package/bundled-plugins/browser-playwright/dist/setup.d.ts.map +1 -0
  66. package/bundled-plugins/browser-playwright/dist/setup.js +252 -0
  67. package/bundled-plugins/browser-playwright/dist/setup.js.map +1 -0
  68. package/bundled-plugins/browser-playwright/dist/types.d.ts +270 -0
  69. package/bundled-plugins/browser-playwright/dist/types.d.ts.map +1 -0
  70. package/bundled-plugins/browser-playwright/dist/types.js +2 -0
  71. package/bundled-plugins/browser-playwright/dist/types.js.map +1 -0
  72. package/bundled-plugins/browser-playwright/plugin.json +20 -0
  73. package/bundled-plugins/coding-tools/agent-forge.json +1 -1
  74. package/bundled-plugins/coding-tools/dist/bash.d.ts +2 -7
  75. package/bundled-plugins/coding-tools/dist/bash.d.ts.map +1 -1
  76. package/bundled-plugins/coding-tools/dist/bash.js +2 -34
  77. package/bundled-plugins/coding-tools/dist/bash.js.map +1 -1
  78. package/bundled-plugins/coding-tools/dist/read.d.ts +2 -0
  79. package/bundled-plugins/coding-tools/dist/read.d.ts.map +1 -1
  80. package/bundled-plugins/coding-tools/dist/read.js +11 -0
  81. package/bundled-plugins/coding-tools/dist/read.js.map +1 -1
  82. package/bundled-plugins/coding-tools/plugin.json +1 -1
  83. package/bundled-plugins/compaction-policy/agent-forge.json +1 -1
  84. package/bundled-plugins/compaction-policy/plugin.json +1 -1
  85. package/bundled-plugins/mcp-http/dist/mcp-http.d.ts.map +1 -1
  86. package/bundled-plugins/mcp-http/dist/mcp-http.js +84 -31
  87. package/bundled-plugins/mcp-http/dist/mcp-http.js.map +1 -1
  88. package/bundled-plugins/overflow-policy/agent-forge.json +1 -1
  89. package/bundled-plugins/overflow-policy/plugin.json +1 -1
  90. package/bundled-plugins/provider-failover/agent-forge.json +1 -1
  91. package/bundled-plugins/provider-failover/plugin.json +1 -1
  92. package/bundled-plugins/retry-policy/agent-forge.json +1 -1
  93. package/bundled-plugins/retry-policy/plugin.json +1 -1
  94. package/dist/bundle/.build-manifest.json +60 -58
  95. package/dist/bundle/chunks/{anthropic-messages-3FJHRAJL.js → anthropic-messages-NL4Y6WPB.js} +1 -1
  96. package/dist/bundle/chunks/{azure-openai-responses-GCL47IDS.js → azure-openai-responses-CPXC42HO.js} +1 -1
  97. package/dist/bundle/chunks/bedrock-converse-stream.js +1 -1
  98. package/dist/bundle/chunks/chunk-5LRQFZFE.js +2 -0
  99. package/dist/bundle/chunks/{chunk-HTEVUY7F.js → chunk-7HSJPQKN.js} +1 -1
  100. package/dist/bundle/chunks/{chunk-AC2FIS4G.js → chunk-EDO7Q6XR.js} +1 -1
  101. package/dist/bundle/chunks/{chunk-755VNWIF.js → chunk-ISLHFRER.js} +6 -6
  102. package/dist/bundle/chunks/{chunk-HV64ASMT.js → chunk-K3S6GTL7.js} +1 -1
  103. package/dist/bundle/chunks/{chunk-HEL6TAWE.js → chunk-L2SXIPI5.js} +37 -36
  104. package/dist/bundle/chunks/{chunk-V3ACW7VD.js → chunk-WJSKB3FC.js} +1 -1
  105. package/dist/bundle/chunks/{chunk-32YDZI4J.js → chunk-ZS5JEI76.js} +1 -1
  106. package/dist/bundle/chunks/{google-generative-ai-6BMXWA44.js → google-generative-ai-UMZ53EFA.js} +1 -1
  107. package/dist/bundle/chunks/{google-vertex-6H7NLRTK.js → google-vertex-ZNR5NS6H.js} +1 -1
  108. package/dist/bundle/chunks/image-resize-worker.js +1 -1
  109. package/dist/bundle/chunks/{mistral-conversations-IXUHSFSJ.js → mistral-conversations-IT66WUNN.js} +1 -1
  110. package/dist/bundle/chunks/{openai-codex-responses-YHUAEVCM.js → openai-codex-responses-FOVCVG6I.js} +1 -1
  111. package/dist/bundle/chunks/{openai-completions-ULQCFC72.js → openai-completions-FLQ7CBOL.js} +1 -1
  112. package/dist/bundle/chunks/{openai-responses-NLLAJDPS.js → openai-responses-ABGYHS2T.js} +1 -1
  113. package/dist/bundle/chunks/{pi-messages-EJTI2EJ3.js → pi-messages-6K5W6LUN.js} +1 -1
  114. package/dist/bundle/chunks/{virtual-modules-TQWEGNNZ.js → virtual-modules-2QGILFV7.js} +1 -1
  115. package/dist/bundle/cli.js +1 -1
  116. package/dist/bundle/client.js +1 -1
  117. package/dist/bundle/index.js +1 -1
  118. package/dist/bundle/rpc-entry.js +1 -1
  119. package/dist/client/remote-session.d.ts.map +1 -1
  120. package/dist/client/remote-session.js +65 -6
  121. package/dist/client/remote-session.js.map +1 -1
  122. package/dist/core/agent-session-store.d.ts.map +1 -1
  123. package/dist/core/agent-session-store.js +20 -3
  124. package/dist/core/agent-session-store.js.map +1 -1
  125. package/dist/core/extensions/agent-composition.d.ts.map +1 -1
  126. package/dist/core/extensions/agent-composition.js +20 -1
  127. package/dist/core/extensions/agent-composition.js.map +1 -1
  128. package/dist/core/i18n/locales/zh-cn/core-errors.d.ts.map +1 -1
  129. package/dist/core/i18n/locales/zh-cn/core-errors.js +1 -0
  130. package/dist/core/i18n/locales/zh-cn/core-errors.js.map +1 -1
  131. package/dist/core/i18n/locales/zh-cn/interactive-mode.d.ts.map +1 -1
  132. package/dist/core/i18n/locales/zh-cn/interactive-mode.js +10 -3
  133. package/dist/core/i18n/locales/zh-cn/interactive-mode.js.map +1 -1
  134. package/dist/core/keybindings.d.ts +35 -0
  135. package/dist/core/keybindings.d.ts.map +1 -1
  136. package/dist/core/keybindings.js +34 -0
  137. package/dist/core/keybindings.js.map +1 -1
  138. package/dist/core/sdk.d.ts.map +1 -1
  139. package/dist/core/sdk.js +62 -15
  140. package/dist/core/sdk.js.map +1 -1
  141. package/dist/core/session-manager.d.ts.map +1 -1
  142. package/dist/core/session-manager.js +11 -3
  143. package/dist/core/session-manager.js.map +1 -1
  144. package/dist/core/system-prompt.d.ts.map +1 -1
  145. package/dist/core/system-prompt.js +2 -2
  146. package/dist/core/system-prompt.js.map +1 -1
  147. package/dist/core/tools/capability-mount.d.ts.map +1 -1
  148. package/dist/core/tools/capability-mount.js +4 -21
  149. package/dist/core/tools/capability-mount.js.map +1 -1
  150. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  151. package/dist/modes/interactive/components/assistant-message.js +2 -2
  152. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  153. package/dist/modes/interactive/components/bash-execution.d.ts +2 -0
  154. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  155. package/dist/modes/interactive/components/bash-execution.js +25 -0
  156. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  157. package/dist/modes/interactive/components/changelog-pager.d.ts +53 -0
  158. package/dist/modes/interactive/components/changelog-pager.d.ts.map +1 -0
  159. package/dist/modes/interactive/components/changelog-pager.js +239 -0
  160. package/dist/modes/interactive/components/changelog-pager.js.map +1 -0
  161. package/dist/modes/interactive/components/tool-execution.d.ts +6 -0
  162. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  163. package/dist/modes/interactive/components/tool-execution.js +12 -0
  164. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  165. package/dist/modes/interactive/components/tool-run-group.d.ts +41 -11
  166. package/dist/modes/interactive/components/tool-run-group.d.ts.map +1 -1
  167. package/dist/modes/interactive/components/tool-run-group.js +126 -14
  168. package/dist/modes/interactive/components/tool-run-group.js.map +1 -1
  169. package/dist/modes/interactive/interactive-commands.d.ts.map +1 -1
  170. package/dist/modes/interactive/interactive-commands.js +23 -13
  171. package/dist/modes/interactive/interactive-commands.js.map +1 -1
  172. package/dist/modes/interactive/interactive-events.d.ts +14 -4
  173. package/dist/modes/interactive/interactive-events.d.ts.map +1 -1
  174. package/dist/modes/interactive/interactive-events.js +94 -12
  175. package/dist/modes/interactive/interactive-events.js.map +1 -1
  176. package/dist/modes/interactive/interactive-mode.d.ts +6 -1
  177. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  178. package/dist/modes/interactive/interactive-mode.js +21 -5
  179. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  180. package/dist/plugins/ecosystem/node-local-package-source.d.ts +2 -1
  181. package/dist/plugins/ecosystem/node-local-package-source.d.ts.map +1 -1
  182. package/dist/plugins/ecosystem/node-local-package-source.js +110 -4
  183. package/dist/plugins/ecosystem/node-local-package-source.js.map +1 -1
  184. package/dist/plugins/ecosystem/node-package-install-host.d.ts.map +1 -1
  185. package/dist/plugins/ecosystem/node-package-install-host.js +106 -39
  186. package/dist/plugins/ecosystem/node-package-install-host.js.map +1 -1
  187. package/dist/plugins/ecosystem/node-plugin-bootstrap.d.ts.map +1 -1
  188. package/dist/plugins/ecosystem/node-plugin-bootstrap.js +85 -2
  189. package/dist/plugins/ecosystem/node-plugin-bootstrap.js.map +1 -1
  190. package/dist/suites/builtin-suites.d.ts.map +1 -1
  191. package/dist/suites/builtin-suites.js +2 -2
  192. package/dist/suites/builtin-suites.js.map +1 -1
  193. package/dist/utils/changelog.d.ts +27 -0
  194. package/dist/utils/changelog.d.ts.map +1 -1
  195. package/dist/utils/changelog.js +110 -0
  196. package/dist/utils/changelog.js.map +1 -1
  197. package/docs/keybindings.md +14 -0
  198. package/examples/extensions/with-deps/package-lock.json +2 -2
  199. package/examples/extensions/with-deps/package.json +1 -1
  200. package/examples/extensions/with-deps/plugin.json +1 -1
  201. package/package.json +1 -1
  202. package/dist/bundle/chunks/chunk-A3JYRWB6.js +0 -2
@@ -447,8 +447,10 @@ async function installStagingRuntimeDependencies(staging, entries, signal) {
447
447
  manifest = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(packageEntry.bytes));
448
448
  }
449
449
  catch {
450
- // Package identity is already fully validated by the two manifests;
451
- // a package without a parseable package.json installs unchanged.
450
+ // Unlike the two manifests, a package.json with parse errors is not
451
+ // part of install validation: the package installs unchanged and the
452
+ // missing runtime dependencies surface later as module-not-found at
453
+ // plugin load (registered boundary in the distribution design).
452
454
  return;
453
455
  }
454
456
  if (typeof manifest !== "object" || manifest === null || Array.isArray(manifest))
@@ -546,6 +548,20 @@ export async function createNodePackageInstallHostV1(options) {
546
548
  let closed = false;
547
549
  const activeOperations = new Set();
548
550
  const runtimeHandles = new Map();
551
+ // Activation serialization: NodePackageInstallHostV1 is a public API and
552
+ // third-party callers may activate the same installation key concurrently.
553
+ // Two interleaved activations can both pass the state guard and overwrite
554
+ // each other's runtimeHandles entry — the losing dispose stops its own
555
+ // handle while the ledger still reads "active", silently leaking the
556
+ // surviving runtime, because the persistence layer only serializes
557
+ // commits and not this in-memory path. Each activation chains onto the
558
+ // previous one for its key, preserving the existing success semantics: a
559
+ // queued activation starts only after the previous one settles and is
560
+ // then rejected by the state guard like any sequential re-activation.
561
+ // rollback/uninstall stay unchained; their interleavings with activate
562
+ // are tolerated by the persistence snapshot and the ENOENT handling in
563
+ // uninstall.
564
+ const activationChains = new Map();
549
565
  const applyPersistentSnapshot = (snapshot) => {
550
566
  records.clear();
551
567
  activeByKey.clear();
@@ -616,6 +632,28 @@ export async function createNodePackageInstallHostV1(options) {
616
632
  await Promise.resolve(handle.dispose());
617
633
  runtimeHandles.delete(installationRef);
618
634
  };
635
+ // A dispose that throws keeps its entry in runtimeHandles (disposeRuntime
636
+ // deletes only after a successful dispose), so re-registering the same
637
+ // installation ref must not silently overwrite the stale leftover: the
638
+ // combined handle releases the new runtime first and the stale one in
639
+ // `finally`, so a failure on either side still reclaims the other.
640
+ const registerRuntimeHandle = (installationRef, handle) => {
641
+ const existing = runtimeHandles.get(installationRef);
642
+ if (existing === undefined) {
643
+ runtimeHandles.set(installationRef, handle);
644
+ return;
645
+ }
646
+ runtimeHandles.set(installationRef, {
647
+ dispose: async () => {
648
+ try {
649
+ await Promise.resolve(handle.dispose?.());
650
+ }
651
+ finally {
652
+ await Promise.resolve(existing.dispose?.());
653
+ }
654
+ },
655
+ });
656
+ };
619
657
  const loadRuntime = async (installation, record, directory, signal) => {
620
658
  if (options.loadPlugin === undefined)
621
659
  return undefined;
@@ -744,47 +782,76 @@ export async function createNodePackageInstallHostV1(options) {
744
782
  }
745
783
  },
746
784
  async activate(input) {
747
- const operation = begin(input.signal);
748
- let candidate;
749
- try {
750
- const scopeRef = opaqueScope(input.scopeRef);
751
- const record = getRecord(input.installation, input.record, input.scope, scopeRef);
752
- if (record.state !== "installed")
753
- throw new NodePackageInstallErrorV1("installation_identity_mismatch");
754
- candidate = await loadRuntime(input.installation, input.record, record.directory, operation.signal);
755
- const key = installationKey(input.scope, scopeRef, input.record.pluginId);
756
- const previousRef = activeByKey.get(key);
757
- if (previousRef !== undefined) {
758
- const previous = records.get(previousRef);
759
- if (previous !== undefined) {
760
- await disposeRuntime(previousRef);
761
- }
762
- }
763
- await commitRecords((values) => {
764
- const candidateRecord = values.get(input.installation.installationRef);
765
- if (candidateRecord === undefined)
785
+ // Validate before queueing: a malformed request fails at call time
786
+ // instead of waiting behind pending activations.
787
+ const key = installationKey(input.scope, opaqueScope(input.scopeRef), input.record.pluginId);
788
+ const activateBody = async () => {
789
+ const operation = begin(input.signal);
790
+ let candidate;
791
+ try {
792
+ const scopeRef = opaqueScope(input.scopeRef);
793
+ const record = getRecord(input.installation, input.record, input.scope, scopeRef);
794
+ if (record.state !== "installed")
766
795
  throw new NodePackageInstallErrorV1("installation_identity_mismatch");
796
+ candidate = await loadRuntime(input.installation, input.record, record.directory, operation.signal);
797
+ const previousRef = activeByKey.get(key);
798
+ // Commit the persisted ledger before stopping the previous
799
+ // runtime: if the commit fails, the old runtime is still
800
+ // running and still matches the ledger, so the caller can
801
+ // retry or roll back from a consistent state. Between the
802
+ // commit and the dispose below the old and new runtimes
803
+ // coexist briefly — the previous plugin keeps serving until
804
+ // it is replaced here, which is the correct activation
805
+ // window. The new handle is registered before the old
806
+ // runtime is disposed, so even if disposeRuntime propagates
807
+ // a failing old-runtime dispose, the committed new version
808
+ // stays live and the error surfaces through the catch below.
809
+ await commitRecords((values) => {
810
+ const candidateRecord = values.get(input.installation.installationRef);
811
+ if (candidateRecord === undefined)
812
+ throw new NodePackageInstallErrorV1("installation_identity_mismatch");
813
+ if (previousRef !== undefined) {
814
+ const previousRecord = values.get(previousRef);
815
+ if (previousRecord !== undefined)
816
+ values.set(previousRef, { ...previousRecord, state: "retained" });
817
+ }
818
+ values.set(input.installation.installationRef, { ...candidateRecord, state: "active" });
819
+ });
820
+ activeByKey.set(key, input.installation.installationRef);
821
+ if (candidate !== undefined)
822
+ registerRuntimeHandle(input.installation.installationRef, candidate);
823
+ candidate = undefined;
767
824
  if (previousRef !== undefined) {
768
- const previousRecord = values.get(previousRef);
769
- if (previousRecord !== undefined)
770
- values.set(previousRef, { ...previousRecord, state: "retained" });
825
+ const previous = records.get(previousRef);
826
+ if (previous !== undefined) {
827
+ await disposeRuntime(previousRef);
828
+ }
771
829
  }
772
- values.set(input.installation.installationRef, { ...candidateRecord, state: "active" });
773
- });
774
- activeByKey.set(key, input.installation.installationRef);
775
- if (candidate !== undefined)
776
- runtimeHandles.set(input.installation.installationRef, candidate);
777
- candidate = undefined;
778
- }
779
- catch (error) {
780
- if (candidate?.dispose !== undefined)
781
- await Promise.resolve(candidate.dispose()).catch(() => undefined);
782
- if (error instanceof NodePackageInstallErrorV1)
783
- throw error;
784
- throw new NodePackageInstallErrorV1("installation_io_failed");
830
+ }
831
+ catch (error) {
832
+ if (candidate?.dispose !== undefined)
833
+ await Promise.resolve(candidate.dispose()).catch(() => undefined);
834
+ if (error instanceof NodePackageInstallErrorV1)
835
+ throw error;
836
+ throw new NodePackageInstallErrorV1("installation_io_failed");
837
+ }
838
+ finally {
839
+ end(operation.controller);
840
+ }
841
+ };
842
+ // Chain onto the previous activation for this key; the queued body
843
+ // runs only after it settles, whatever its outcome.
844
+ const queued = activationChains.get(key) ?? Promise.resolve();
845
+ const run = queued.catch(() => undefined).then(() => activateBody());
846
+ activationChains.set(key, run);
847
+ try {
848
+ await run;
785
849
  }
786
850
  finally {
787
- end(operation.controller);
851
+ // Drop the chain entry only while it is still the newest run, so
852
+ // a queued successor keeps later arrivals chained onto it.
853
+ if (activationChains.get(key) === run)
854
+ activationChains.delete(key);
788
855
  }
789
856
  },
790
857
  async rollback(input) {
@@ -835,7 +902,7 @@ export async function createNodePackageInstallHostV1(options) {
835
902
  });
836
903
  activeByKey.set(installationKey(input.scope, scopeRef, failed.pluginId), input.previous.installationRef);
837
904
  if (candidate !== undefined)
838
- runtimeHandles.set(input.previous.installationRef, candidate);
905
+ registerRuntimeHandle(input.previous.installationRef, candidate);
839
906
  candidate = undefined;
840
907
  }
841
908
  catch (error) {