@evomap/evolver-proxy 2.0.0-beta.19 → 2.0.0-beta.22

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 (43) hide show
  1. package/dist/bin/evolver-proxy.d.ts +12 -0
  2. package/dist/bin/evolver-proxy.js +257 -56
  3. package/dist/daemon/proxyDaemon.d.ts +12 -0
  4. package/dist/daemon/proxyDaemon.js +313 -18
  5. package/dist/daemon/systemdNotifier.d.ts +2 -0
  6. package/dist/daemon/systemdNotifier.js +11 -1
  7. package/dist/llm/upstream.js +54 -7
  8. package/dist/private/accountAssetCompatibility.d.ts +1 -0
  9. package/dist/private/accountAssetCompatibility.js +3 -3
  10. package/dist/private/adapterLoader.js +4 -3
  11. package/dist/router/messagesRoute.js +9 -3
  12. package/dist/router/providerRoutes.js +7 -3
  13. package/dist/selfUpdate/bootstrap.d.ts +162 -0
  14. package/dist/selfUpdate/bootstrap.js +3524 -0
  15. package/dist/selfUpdate/bootstrapReadiness.d.ts +9 -0
  16. package/dist/selfUpdate/bootstrapReadiness.js +153 -0
  17. package/dist/selfUpdate/builtinKey.d.ts +4 -0
  18. package/dist/selfUpdate/builtinKey.js +16 -0
  19. package/dist/selfUpdate/controllerLifecycleAuthority.d.ts +45 -0
  20. package/dist/selfUpdate/controllerLifecycleAuthority.js +61 -0
  21. package/dist/selfUpdate/executor.d.ts +18 -7
  22. package/dist/selfUpdate/executor.js +159 -59
  23. package/dist/selfUpdate/failureCodes.d.ts +4 -0
  24. package/dist/selfUpdate/failureCodes.js +7 -0
  25. package/dist/selfUpdate/index.d.ts +2 -1
  26. package/dist/selfUpdate/index.js +2 -1
  27. package/dist/selfUpdate/migration.d.ts +158 -0
  28. package/dist/selfUpdate/migration.js +2672 -0
  29. package/dist/selfUpdate/policy.d.ts +19 -2
  30. package/dist/selfUpdate/policy.js +76 -2
  31. package/dist/selfUpdate/recoveryChildStartGate.d.ts +29 -0
  32. package/dist/selfUpdate/recoveryChildStartGate.js +319 -0
  33. package/dist/selfUpdate/releaseBinary.d.ts +3 -0
  34. package/dist/selfUpdate/releaseBinary.js +50 -4
  35. package/dist/selfUpdate/transaction.d.ts +8 -0
  36. package/dist/selfUpdate/transaction.js +166 -18
  37. package/dist/selfUpdate/unixController.d.ts +8 -0
  38. package/dist/selfUpdate/unixController.js +366 -38
  39. package/dist/selfUpdate/windowsController.d.ts +14 -2
  40. package/dist/selfUpdate/windowsController.js +484 -103
  41. package/dist/selfUpdate/windowsUpdater.d.ts +25 -0
  42. package/dist/selfUpdate/windowsUpdater.js +174 -7
  43. package/package.json +3 -3
@@ -38,6 +38,22 @@ export interface ApplyWindowsUpdaterOptions {
38
38
  workerExecPath?: string;
39
39
  platform?: NodeJS.Platform;
40
40
  renameFn?: typeof rename;
41
+ /** Test seam; production always evaluates the native Windows owner/writer policy. */
42
+ assertHelperTrust?: WindowsUpdaterHelperTrust;
43
+ }
44
+ export interface WindowsUpdaterHelperTrustPaths {
45
+ stateDir: string;
46
+ directory: string;
47
+ helperPath: string;
48
+ pendingPath: string;
49
+ }
50
+ export type WindowsUpdaterHelperTrust = (paths: WindowsUpdaterHelperTrustPaths) => void | Promise<void>;
51
+ export interface RevalidateWindowsUpdaterHelperOptions {
52
+ stateDir: string;
53
+ helperPath?: string;
54
+ platform?: NodeJS.Platform;
55
+ /** Test seam; production always evaluates the native Windows owner/writer policy. */
56
+ assertHelperTrust?: WindowsUpdaterHelperTrust;
41
57
  }
42
58
  export interface BindWindowsManagedExecutableOptions {
43
59
  stateDir: string;
@@ -55,6 +71,12 @@ export interface BoundWindowsManagedExecutable {
55
71
  export declare function resolveWindowsUpdaterPaths(stateDirInput: string): WindowsUpdaterPaths;
56
72
  /** Bind a fixed executable below the private state root without following directory links. */
57
73
  export declare function bindWindowsManagedExecutable(options: BindWindowsManagedExecutableOptions): Promise<BoundWindowsManagedExecutable>;
74
+ /**
75
+ * Bind the fixed helper and verify the persisted executable generation before
76
+ * the lifecycle owner creates a worker process. The worker repeats this check
77
+ * after consuming fd4 and before any target mutation.
78
+ */
79
+ export declare function revalidatePendingWindowsUpdaterHelper(options: RevalidateWindowsUpdaterHelperOptions): Promise<BoundWindowsManagedExecutable>;
58
80
  /**
59
81
  * Prepare a launcher-consumed update descriptor. This function never mutates
60
82
  * the live executable and never spawns a competing relaunch process.
@@ -76,4 +98,7 @@ export declare function maybeRunWindowsUpdaterWorkerFromArgv(options?: {
76
98
  env?: NodeJS.ProcessEnv;
77
99
  platform?: NodeJS.Platform;
78
100
  processExecPath?: string;
101
+ startupGateConsumed?: boolean;
102
+ /** Test seam; production always evaluates the native Windows owner/writer policy. */
103
+ assertHelperTrust?: WindowsUpdaterHelperTrust;
79
104
  }): Promise<number | undefined>;
@@ -1,7 +1,8 @@
1
+ import { execFileSync } from 'node:child_process';
1
2
  import { createHash, randomBytes, timingSafeEqual } from 'node:crypto';
2
3
  import { constants } from 'node:fs';
3
4
  import { link, lstat, mkdir, open, realpath, rename, rm, } from 'node:fs/promises';
4
- import { basename, dirname, isAbsolute, join, parse, relative, resolve } from 'node:path';
5
+ import { basename, dirname, isAbsolute, join, parse, relative, resolve, win32 } from 'node:path';
5
6
  import { SELF_UPDATE_FAILURE_CODES, SelfUpdateFailureError, selfUpdateFailure, } from './failureCodes.js';
6
7
  export const WINDOWS_UPDATER_WORKER_ARG = '--evolver-windows-updater-worker';
7
8
  const WORK_ITEM_SCHEMA_VERSION = 1;
@@ -9,6 +10,7 @@ const RESULT_SCHEMA_VERSION = 1;
9
10
  const MAX_WORK_ITEM_BYTES = 64 * 1024;
10
11
  const COPY_BUFFER_BYTES = 1024 * 1024;
11
12
  const OPERATION_ID_PATTERN = /^[0-9a-f]{32}$/;
13
+ const HOST_WINDOWS_SYSTEM_ROOT = process.env['SystemRoot']?.trim() || 'C:\\Windows';
12
14
  /** Paths are fixed so the stable controller never consumes descriptor-supplied executable paths. */
13
15
  export function resolveWindowsUpdaterPaths(stateDirInput) {
14
16
  const stateDir = assertAbsoluteCleanPath(stateDirInput, 'state_dir');
@@ -37,6 +39,28 @@ export async function bindWindowsManagedExecutable(options) {
37
39
  }
38
40
  return { stateDir, executablePath };
39
41
  }
42
+ /**
43
+ * Bind the fixed helper and verify the persisted executable generation before
44
+ * the lifecycle owner creates a worker process. The worker repeats this check
45
+ * after consuming fd4 and before any target mutation.
46
+ */
47
+ export async function revalidatePendingWindowsUpdaterHelper(options) {
48
+ assertWindowsPlatform(options.platform ?? process.platform);
49
+ const requestedPaths = resolveWindowsUpdaterPaths(options.stateDir);
50
+ const bound = await bindWindowsManagedExecutable({
51
+ stateDir: options.stateDir,
52
+ executablePath: options.helperPath ?? requestedPaths.helperPath,
53
+ relativePath: ['windows-updater', 'updater.exe'],
54
+ label: 'helper_revalidation',
55
+ mismatchLabel: 'helper',
56
+ platform: options.platform,
57
+ });
58
+ const paths = resolveWindowsUpdaterPaths(bound.stateDir);
59
+ const workItem = await readWorkItem(paths.pendingPath);
60
+ await assertWindowsUpdaterHelperTrust({ ...paths, stateDir: bound.stateDir }, options.assertHelperTrust);
61
+ await assertHelperLaunchSnapshot(bound.executablePath, workItem.helper_identity);
62
+ return bound;
63
+ }
40
64
  /**
41
65
  * Prepare a launcher-consumed update descriptor. This function never mutates
42
66
  * the live executable and never spawns a competing relaunch process.
@@ -99,6 +123,9 @@ export async function prepareWindowsExecutableSwap(options) {
99
123
  });
100
124
  }
101
125
  const helperIdentity = await snapshotRegularFile(paths.helperPath, 'helper');
126
+ if (helperIdentity.nlink !== '1') {
127
+ throw selfUpdateFailure(SELF_UPDATE_FAILURE_CODES.COPY_FAILED, 'windows_updater_helper_unsafe');
128
+ }
102
129
  if (!safeDigestEqual(helperIdentity.sha256, helperSourceIdentity.sha256)) {
103
130
  throw selfUpdateFailure(SELF_UPDATE_FAILURE_CODES.COPY_FAILED, 'windows_updater_helper_digest_mismatch');
104
131
  }
@@ -150,7 +177,7 @@ export async function applyPendingWindowsExecutableSwap(options = {}) {
150
177
  let workItem;
151
178
  try {
152
179
  workItem = await readWorkItem(paths.pendingPath);
153
- await validateWorkItem(workItem, paths, stateDir);
180
+ await validateWorkItem(workItem, paths, stateDir, options.assertHelperTrust);
154
181
  }
155
182
  catch (error) {
156
183
  const result = {
@@ -219,11 +246,14 @@ export async function maybeRunWindowsUpdaterWorkerFromArgv(options = {}) {
219
246
  return 64;
220
247
  if (argv.length !== 2 || argv[0] !== 'proxy' || argv[1] !== WINDOWS_UPDATER_WORKER_ARG)
221
248
  return 64;
249
+ if (options.startupGateConsumed !== true)
250
+ return 64;
222
251
  try {
223
252
  const result = await applyPendingWindowsExecutableSwap({
224
253
  stateDir: options.env?.['EVOLVER_SELF_UPDATE_STATE_DIR']?.trim() || undefined,
225
254
  platform: options.platform,
226
255
  workerExecPath: options.processExecPath,
256
+ ...(options.assertHelperTrust ? { assertHelperTrust: options.assertHelperTrust } : {}),
227
257
  });
228
258
  return result.status === 'completed' ? 0 : 1;
229
259
  }
@@ -250,7 +280,7 @@ async function commitPreparedHelper(helperTempPath, helperPath, sourceIdentity)
250
280
  }
251
281
  await rename(helperTempPath, helperPath);
252
282
  }
253
- async function validateWorkItem(workItem, paths, stateDir) {
283
+ async function validateWorkItem(workItem, paths, stateDir, assertHelperTrust) {
254
284
  if (!OPERATION_ID_PATTERN.test(workItem.operation_id)) {
255
285
  throw selfUpdateFailure(SELF_UPDATE_FAILURE_CODES.REPLACE_FAILED, 'windows_updater_operation_id_invalid');
256
286
  }
@@ -276,7 +306,8 @@ async function validateWorkItem(workItem, paths, stateDir) {
276
306
  workItem.target_path = targetPath;
277
307
  workItem.backup_path = backupPath;
278
308
  workItem.source_path = sourcePath;
279
- await assertSnapshot(paths.helperPath, workItem.helper_identity, 'helper');
309
+ await assertWindowsUpdaterHelperTrust({ ...paths, stateDir }, assertHelperTrust);
310
+ await assertHelperLaunchSnapshot(paths.helperPath, workItem.helper_identity);
280
311
  await assertSnapshot(backupPath, workItem.backup_identity, 'backup');
281
312
  await assertSnapshot(sourcePath, workItem.source_identity, 'source');
282
313
  }
@@ -344,6 +375,16 @@ function parseIdentity(value) {
344
375
  ctime_ns: requireString(value, 'ctime_ns'),
345
376
  sha256: requireString(value, 'sha256'),
346
377
  };
378
+ const generationKeys = ['birthtime_ns', 'nlink', 'mode'];
379
+ const suppliedGenerationKeys = generationKeys.filter((key) => value[key] !== undefined);
380
+ if (suppliedGenerationKeys.length !== 0 && suppliedGenerationKeys.length !== generationKeys.length) {
381
+ throw new Error('identity_generation');
382
+ }
383
+ if (suppliedGenerationKeys.length === generationKeys.length) {
384
+ identity.birthtime_ns = requireString(value, 'birthtime_ns');
385
+ identity.nlink = requireString(value, 'nlink');
386
+ identity.mode = requireString(value, 'mode');
387
+ }
347
388
  assertSha256(identity.sha256, 'identity_sha256');
348
389
  return identity;
349
390
  }
@@ -379,6 +420,12 @@ async function assertSnapshot(path, expected, label) {
379
420
  throw selfUpdateFailure(SELF_UPDATE_FAILURE_CODES.REPLACE_FAILED, `windows_updater_${label}_changed`);
380
421
  }
381
422
  }
423
+ async function assertHelperLaunchSnapshot(path, expected) {
424
+ const actual = await snapshotRegularFile(path, 'helper');
425
+ if (actual.nlink !== '1' || !sameHelperLaunchIdentity(actual, expected)) {
426
+ throw selfUpdateFailure(SELF_UPDATE_FAILURE_CODES.REPLACE_FAILED, 'windows_updater_helper_changed');
427
+ }
428
+ }
382
429
  async function copyRegularFileExclusive(sourcePath, destinationPath, expectedSource, mode) {
383
430
  const source = await openNoFollow(sourcePath, constants.O_RDONLY);
384
431
  let destination;
@@ -540,6 +587,88 @@ async function assertNoSymlinkedParent(path, label) {
540
587
  }
541
588
  }
542
589
  }
590
+ async function assertWindowsUpdaterHelperTrust(paths, override) {
591
+ const pending = await lstat(paths.pendingPath, { bigint: true }).catch((error) => {
592
+ throw selfUpdateFailure(SELF_UPDATE_FAILURE_CODES.REPLACE_FAILED, 'windows_updater_pending_unreadable', {
593
+ cause: error,
594
+ });
595
+ });
596
+ if (!pending.isFile() || pending.isSymbolicLink() || pending.nlink !== 1n) {
597
+ throw selfUpdateFailure(SELF_UPDATE_FAILURE_CODES.REPLACE_FAILED, 'windows_updater_pending_unsafe');
598
+ }
599
+ try {
600
+ await (override ?? assertNativeWindowsUpdaterHelperTrust)(paths);
601
+ }
602
+ catch (error) {
603
+ if (error instanceof SelfUpdateFailureError)
604
+ throw error;
605
+ throw selfUpdateFailure(SELF_UPDATE_FAILURE_CODES.REPLACE_FAILED, 'windows_updater_helper_acl_untrusted', {
606
+ cause: error,
607
+ });
608
+ }
609
+ }
610
+ function assertNativeWindowsUpdaterHelperTrust(paths) {
611
+ if (process.platform !== 'win32')
612
+ return;
613
+ const checks = [
614
+ { path: paths.helperPath, parentOnly: false },
615
+ { path: paths.pendingPath, parentOnly: false },
616
+ ];
617
+ const root = parse(paths.directory).root;
618
+ let current = paths.directory;
619
+ let leaf = true;
620
+ for (;;) {
621
+ checks.push({ path: current, parentOnly: !leaf });
622
+ leaf = false;
623
+ if (samePath(current, root))
624
+ break;
625
+ current = dirname(current);
626
+ }
627
+ try {
628
+ execFileSync(trustedWindowsSystemExecutable('WindowsPowerShell\\v1.0\\powershell.exe'), ['-NoProfile', '-NonInteractive', '-Command', windowsUpdaterAclScript(checks)], { stdio: 'ignore', timeout: 10_000, windowsHide: true });
629
+ }
630
+ catch (error) {
631
+ throw selfUpdateFailure(SELF_UPDATE_FAILURE_CODES.REPLACE_FAILED, 'windows_updater_helper_acl_untrusted', {
632
+ cause: error,
633
+ });
634
+ }
635
+ }
636
+ function windowsUpdaterAclScript(checks) {
637
+ const encodedChecks = Buffer.from(JSON.stringify(checks), 'utf8').toString('base64');
638
+ const d = String.fromCharCode(36);
639
+ return [
640
+ `${d}ErrorActionPreference = 'Stop'`,
641
+ 'try {',
642
+ ` ${d}json = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('${encodedChecks}'))`,
643
+ ` ${d}checks = ${d}json | ConvertFrom-Json`,
644
+ ` ${d}userSid = [System.Security.Principal.WindowsIdentity]::GetCurrent().User.Value`,
645
+ ` ${d}trustedInstaller = 'S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464'`,
646
+ ` ${d}trustedOwners = @(${d}userSid, 'S-1-5-18', 'S-1-5-32-544', ${d}trustedInstaller)`,
647
+ ` ${d}trustedWriters = @(${d}userSid, 'S-1-5-18', 'S-1-5-32-544', ${d}trustedInstaller, 'S-1-3-0', 'S-1-3-4')`,
648
+ ` ${d}parentDanger = [System.Security.AccessControl.FileSystemRights]::Delete -bor [System.Security.AccessControl.FileSystemRights]::DeleteSubdirectoriesAndFiles -bor [System.Security.AccessControl.FileSystemRights]::ChangePermissions -bor [System.Security.AccessControl.FileSystemRights]::TakeOwnership`,
649
+ ` ${d}contentDanger = [System.Security.AccessControl.FileSystemRights]::WriteData -bor [System.Security.AccessControl.FileSystemRights]::AppendData -bor [System.Security.AccessControl.FileSystemRights]::CreateFiles -bor [System.Security.AccessControl.FileSystemRights]::CreateDirectories`,
650
+ ` foreach (${d}check in @(${d}checks)) {`,
651
+ ` ${d}acl = Get-Acl -LiteralPath ${d}check.path`,
652
+ ` ${d}owner = ${d}acl.GetOwner([System.Security.Principal.SecurityIdentifier]).Value`,
653
+ ` if (${d}trustedOwners -notcontains ${d}owner) { exit 21 }`,
654
+ ` ${d}danger = if (${d}check.parentOnly) { ${d}parentDanger } else { ${d}parentDanger -bor ${d}contentDanger }`,
655
+ ` foreach (${d}rule in @(${d}acl.Access)) {`,
656
+ ` if (${d}rule.AccessControlType -ne [System.Security.AccessControl.AccessControlType]::Allow) { continue }`,
657
+ ` if ((${d}rule.PropagationFlags -band [System.Security.AccessControl.PropagationFlags]::InheritOnly) -ne 0) { continue }`,
658
+ ` if ((${d}rule.FileSystemRights -band ${d}danger) -eq 0) { continue }`,
659
+ ` try { ${d}sid = ${d}rule.IdentityReference.Translate([System.Security.Principal.SecurityIdentifier]).Value } catch { exit 22 }`,
660
+ ` if (${d}trustedWriters -notcontains ${d}sid) { exit 23 }`,
661
+ ' }',
662
+ ' }',
663
+ '} catch { exit 24 }',
664
+ ].join('; ');
665
+ }
666
+ function trustedWindowsSystemExecutable(name) {
667
+ if (!win32.isAbsolute(HOST_WINDOWS_SYSTEM_ROOT) || /[\r\n\0]/.test(HOST_WINDOWS_SYSTEM_ROOT)) {
668
+ throw selfUpdateFailure(SELF_UPDATE_FAILURE_CODES.REPLACE_FAILED, 'windows_updater_system_root_untrusted');
669
+ }
670
+ return win32.join(HOST_WINDOWS_SYSTEM_ROOT, 'System32', name);
671
+ }
543
672
  function symlinkTraversalRoot(path) {
544
673
  const parsedRoot = parse(path).root;
545
674
  if (process.platform !== 'win32')
@@ -564,7 +693,10 @@ function assertStatIdentity(left, right, label) {
564
693
  || left.ino !== right.ino
565
694
  || left.size !== right.size
566
695
  || left.mtimeNs !== right.mtimeNs
567
- || left.ctimeNs !== right.ctimeNs) {
696
+ || left.ctimeNs !== right.ctimeNs
697
+ || left.birthtimeNs !== right.birthtimeNs
698
+ || left.nlink !== right.nlink
699
+ || left.mode !== right.mode) {
568
700
  throw selfUpdateFailure(SELF_UPDATE_FAILURE_CODES.REPLACE_FAILED, `windows_updater_${label}`);
569
701
  }
570
702
  }
@@ -577,11 +709,13 @@ function assertDirectoryIdentity(left, right, label) {
577
709
  }
578
710
  }
579
711
  function sameStatIdentity(stat, identity) {
580
- return stat.dev.toString() === identity.dev
712
+ const strictLegacyIdentity = stat.dev.toString() === identity.dev
581
713
  && stat.ino.toString() === identity.ino
582
714
  && stat.size.toString() === identity.size
583
715
  && stat.mtimeNs.toString() === identity.mtime_ns
584
716
  && stat.ctimeNs.toString() === identity.ctime_ns;
717
+ return strictLegacyIdentity
718
+ && (!hasStrongGeneration(identity) || statMatchesStrongGeneration(stat, identity));
585
719
  }
586
720
  function identityFromStat(stat, digest) {
587
721
  return {
@@ -590,15 +724,48 @@ function identityFromStat(stat, digest) {
590
724
  size: stat.size.toString(),
591
725
  mtime_ns: stat.mtimeNs.toString(),
592
726
  ctime_ns: stat.ctimeNs.toString(),
727
+ birthtime_ns: stat.birthtimeNs.toString(),
728
+ nlink: stat.nlink.toString(),
729
+ mode: stat.mode.toString(),
593
730
  sha256: digest,
594
731
  };
595
732
  }
596
733
  function sameIdentity(left, right) {
597
- return sameContent(left, right)
734
+ const strictLegacyIdentity = sameContent(left, right)
598
735
  && left.dev === right.dev
599
736
  && left.ino === right.ino
600
737
  && left.mtime_ns === right.mtime_ns
601
738
  && left.ctime_ns === right.ctime_ns;
739
+ return strictLegacyIdentity
740
+ && (!hasStrongGeneration(right) || sameStrongGeneration(left, right));
741
+ }
742
+ function sameHelperLaunchIdentity(actual, expected) {
743
+ if (!hasStrongGeneration(expected))
744
+ return sameIdentity(actual, expected);
745
+ return expected.nlink === '1'
746
+ && sameContent(actual, expected)
747
+ && actual.dev === expected.dev
748
+ && actual.ino === expected.ino
749
+ && actual.mtime_ns === expected.mtime_ns
750
+ && sameStrongGeneration(actual, expected);
751
+ }
752
+ function hasStrongGeneration(identity) {
753
+ return identity.birthtime_ns !== undefined
754
+ && identity.nlink !== undefined
755
+ && identity.mode !== undefined;
756
+ }
757
+ function sameStrongGeneration(left, right) {
758
+ return hasStrongGeneration(left)
759
+ && hasStrongGeneration(right)
760
+ && left.birthtime_ns === right.birthtime_ns
761
+ && left.nlink === right.nlink
762
+ && left.mode === right.mode;
763
+ }
764
+ function statMatchesStrongGeneration(stat, identity) {
765
+ return hasStrongGeneration(identity)
766
+ && stat.birthtimeNs.toString() === identity.birthtime_ns
767
+ && stat.nlink.toString() === identity.nlink
768
+ && stat.mode.toString() === identity.mode;
602
769
  }
603
770
  function sameContent(left, right) {
604
771
  return left.size === right.size && safeDigestEqual(left.sha256, right.sha256);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evomap/evolver-proxy",
3
- "version": "2.0.0-beta.19",
3
+ "version": "2.0.0-beta.22",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "engines": {
@@ -29,8 +29,8 @@
29
29
  },
30
30
  "dependencies": {
31
31
  "@aws-sdk/client-bedrock-runtime": "^3.1053.0",
32
- "@evomap/evolver-adapter-public": "2.0.0-beta.19",
33
- "@evomap/evolver-core": "2.0.0-beta.19"
32
+ "@evomap/evolver-adapter-public": "2.0.0-beta.22",
33
+ "@evomap/evolver-core": "2.0.0-beta.22"
34
34
  },
35
35
  "repository": {
36
36
  "type": "git",