agl 41.0.0 → 41.1.0

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 (82) hide show
  1. package/changelog.md +18 -0
  2. package/dist_serve/bundle.js +881 -881
  3. package/dist_serve/bundle.js.map +2 -2
  4. package/dist_ts/00_commitinfo_data.js +1 -1
  5. package/dist_ts/aglapi/aglapisurface.document.js +6 -2
  6. package/dist_ts/classes.authmodels.d.ts +15 -0
  7. package/dist_ts/classes.authmodels.js +78 -7
  8. package/dist_ts/classes.authstore.js +23 -6
  9. package/dist_ts/classes.cli.js +8 -3
  10. package/dist_ts/classes.controller.d.ts +13 -0
  11. package/dist_ts/classes.controller.js +52 -15
  12. package/dist_ts/classes.controllermanagement.d.ts +53 -6
  13. package/dist_ts/classes.controllermanagement.js +180 -72
  14. package/dist_ts/classes.inferencegateway.d.ts +6 -6
  15. package/dist_ts/classes.inferencegateway.js +25 -13
  16. package/dist_ts/classes.mcpreexec.js +4 -4
  17. package/dist_ts/classes.processinspection.d.ts +3 -1
  18. package/dist_ts/classes.processinspection.js +4 -2
  19. package/dist_ts/classes.proxycontrol.d.ts +22 -7
  20. package/dist_ts/classes.proxycontrol.js +5 -3
  21. package/dist_ts/classes.proxycontrolclient.d.ts +4 -3
  22. package/dist_ts/classes.proxycontrolclient.js +7 -5
  23. package/dist_ts/classes.proxydaemon.d.ts +6 -4
  24. package/dist_ts/classes.proxydaemon.js +42 -17
  25. package/dist_ts/classes.proxyleaseholder.d.ts +11 -2
  26. package/dist_ts/classes.proxyleaseholder.js +25 -2
  27. package/dist_ts/classes.proxystore.d.ts +3 -2
  28. package/dist_ts/classes.proxystore.js +5 -2
  29. package/dist_ts/classes.upgradecoordinator.d.ts +2 -1
  30. package/dist_ts/classes.upgradecoordinator.js +13 -10
  31. package/dist_ts/classes.upgradetransaction.d.ts +6 -0
  32. package/dist_ts/classes.upgradetransaction.js +38 -13
  33. package/dist_ts/classes.workercallers.d.ts +2 -0
  34. package/dist_ts/classes.workercallers.js +11 -8
  35. package/dist_ts/functions.controllermanagementsurface.d.ts +37 -0
  36. package/dist_ts/functions.controllermanagementsurface.js +110 -0
  37. package/dist_ts/functions.inferencecli.d.ts +6 -3
  38. package/dist_ts/functions.inferencecli.js +9 -5
  39. package/dist_ts/functions.inferencecliarguments.d.ts +1 -1
  40. package/dist_ts/functions.inferencecliarguments.js +19 -7
  41. package/dist_ts/functions.inferencelaunch.d.ts +30 -9
  42. package/dist_ts/functions.inferencelaunch.js +49 -23
  43. package/dist_ts/functions.workerprocessproof.d.ts +12 -3
  44. package/dist_ts/functions.workerprocessproof.js +17 -6
  45. package/dist_ts/interfaces.auth.d.ts +14 -3
  46. package/dist_ts/interfaces.auth.js +4 -3
  47. package/dist_ts_interfaces/index.d.ts +1 -0
  48. package/dist_ts_interfaces/index.js +2 -1
  49. package/dist_ts_interfaces/interfaces.d.ts +5 -0
  50. package/dist_ts_interfaces/interfaces.js +1 -1
  51. package/dist_ts_interfaces/management.d.ts +33 -0
  52. package/dist_ts_interfaces/management.js +35 -0
  53. package/package.json +2 -1
  54. package/readme.md +118 -31
  55. package/ts/00_commitinfo_data.ts +1 -1
  56. package/ts/aglapi/aglapisurface.document.ts +5 -1
  57. package/ts/classes.authmodels.ts +74 -5
  58. package/ts/classes.authstore.ts +24 -4
  59. package/ts/classes.cli.ts +9 -2
  60. package/ts/classes.controller.ts +99 -60
  61. package/ts/classes.controllermanagement.ts +284 -107
  62. package/ts/classes.inferencegateway.ts +28 -17
  63. package/ts/classes.mcpreexec.ts +3 -3
  64. package/ts/classes.processinspection.ts +2 -1
  65. package/ts/classes.proxycontrol.ts +25 -9
  66. package/ts/classes.proxycontrolclient.ts +7 -4
  67. package/ts/classes.proxydaemon.ts +43 -17
  68. package/ts/classes.proxyleaseholder.ts +36 -7
  69. package/ts/classes.proxystore.ts +8 -3
  70. package/ts/classes.upgradecoordinator.ts +20 -11
  71. package/ts/classes.upgradetransaction.ts +53 -2
  72. package/ts/classes.workercallers.ts +12 -7
  73. package/ts/functions.controllermanagementsurface.ts +149 -0
  74. package/ts/functions.inferencecli.ts +15 -7
  75. package/ts/functions.inferencecliarguments.ts +16 -6
  76. package/ts/functions.inferencelaunch.ts +57 -23
  77. package/ts/functions.workerprocessproof.ts +17 -3
  78. package/ts/interfaces.auth.ts +14 -3
  79. package/ts_interfaces/index.ts +1 -0
  80. package/ts_interfaces/interfaces.ts +5 -0
  81. package/ts_interfaces/management.ts +52 -0
  82. package/ts_web/00_commitinfo_data.ts +1 -1
@@ -44,6 +44,7 @@ import {
44
44
  import {
45
45
  ControllerAuditEventModel,
46
46
  ControllerAuthModel,
47
+ ControllerRuntimeConfigFromLaterReleaseError,
47
48
  ControllerPendingPromptModel,
48
49
  ControllerProjectModel,
49
50
  ControllerResourceModel,
@@ -202,6 +203,24 @@ const auditPruneMaxBatchesPerSweep = 50;
202
203
  const auditCountPruneMaxBatchesPerSweep = 250;
203
204
  const auditPruneIntervalMs = 30 * 60 * 1000;
204
205
 
206
+ /**
207
+ * The stored authentication document of `controllerIdArg`. A runtime configuration only a later release writes is
208
+ * refused with its own reason (`ControllerRuntimeConfigFromLaterReleaseError`), not the client's generic assertion
209
+ * failure, so the operator reads the remedy.
210
+ */
211
+ const findStoredAuthDocument = async (
212
+ controllerIdArg: string,
213
+ ): Promise<plugins.nosqldb.TStoredDocument<IControllerAuthDocument> | null> => {
214
+ try {
215
+ return await ControllerAuthModel.exact.findStoredOne({ id: controllerIdArg });
216
+ } catch (errorArg) {
217
+ if (errorArg instanceof Error && errorArg.cause instanceof ControllerRuntimeConfigFromLaterReleaseError) {
218
+ throw errorArg.cause;
219
+ }
220
+ throw errorArg;
221
+ }
222
+ };
223
+
205
224
  /** A concurrent prune that removed an event first leaves nothing to do for it. */
206
225
  const deleteStoredAuditEvents = async (
207
226
  eventsArg: Array<plugins.nosqldb.TStoredDocument<IControllerAuditEvent>>,
@@ -1306,7 +1325,7 @@ export class SmartDataAuthStore implements IAuthStore, IAuthStoreSessionIdentity
1306
1325
  throw new Error('controllerPort must be an integer between 1 and 65535.');
1307
1326
  }
1308
1327
  this.controllerId = `controller:${controllerPortArg}`;
1309
- const stored = await ControllerAuthModel.exact.findStoredOne({ id: this.controllerId });
1328
+ const stored = await findStoredAuthDocument(this.controllerId);
1310
1329
  if (!stored) return undefined;
1311
1330
  return cloneRuntimeConfig(ControllerAuthModel.exact.toPersisted(stored).config);
1312
1331
  }
@@ -1336,7 +1355,7 @@ export class SmartDataAuthStore implements IAuthStore, IAuthStoreSessionIdentity
1336
1355
  }
1337
1356
  const controllerId = `controller:${runtimeConfigArg.controllerPort}`;
1338
1357
  this.controllerId = controllerId;
1339
- const existing = await ControllerAuthModel.exact.findStoredOne({ id: controllerId });
1358
+ const existing = await findStoredAuthDocument(controllerId);
1340
1359
  if (existing) {
1341
1360
  const document = ControllerAuthModel.exact.toPersisted(existing);
1342
1361
  return this.finalizeRuntimeConfigDocument(document, runtimeConfigArg);
@@ -1356,7 +1375,7 @@ export class SmartDataAuthStore implements IAuthStore, IAuthStoreSessionIdentity
1356
1375
  return this.finalizeRuntimeConfigDocument(document, runtimeConfigArg);
1357
1376
  } catch (errorArg) {
1358
1377
  if (!isAmbiguousWrite(errorArg)) throw errorArg;
1359
- const reconciled = await ControllerAuthModel.exact.findStoredOne({ id: controllerId });
1378
+ const reconciled = await findStoredAuthDocument(controllerId);
1360
1379
  if (!reconciled) {
1361
1380
  throw new AuthError(
1362
1381
  'ambiguous_write',
@@ -2326,7 +2345,7 @@ export class SmartDataAuthStore implements IAuthStore, IAuthStoreSessionIdentity
2326
2345
  if (!this.controllerId) {
2327
2346
  throw new AuthError('not_initialized', 'The controller runtime configuration is unresolved.');
2328
2347
  }
2329
- const stored = await ControllerAuthModel.exact.findStoredOne({ id: this.controllerId });
2348
+ const stored = await findStoredAuthDocument(this.controllerId);
2330
2349
  if (!stored) {
2331
2350
  throw new AuthError('not_initialized', 'The controller authentication document is missing.');
2332
2351
  }
@@ -5297,6 +5316,7 @@ export class SmartDataAuthStore implements IAuthStore, IAuthStoreSessionIdentity
5297
5316
  && leftArg.credentialId === rightArg.credentialId
5298
5317
  && leftArg.senderLabel === rightArg.senderLabel
5299
5318
  && JSON.stringify(leftArg.localCli) === JSON.stringify(rightArg.localCli)
5319
+ && JSON.stringify(leftArg.details) === JSON.stringify(rightArg.details)
5300
5320
  && (
5301
5321
  leftArg.sessionId === undefined
5302
5322
  ? rightArg.sessionId === undefined
package/ts/classes.cli.ts CHANGED
@@ -6,6 +6,7 @@ import {
6
6
  controllerProtocolVersion,
7
7
  controllerServiceUnitName,
8
8
  controllerUpgradeManagementVersion,
9
+ controllerManagementProtocolVersion,
9
10
  configurationOwnerTokenEnvironmentVariable,
10
11
  describeBrowserPaintAvailability,
11
12
  type IControllerStatus,
@@ -39,6 +40,7 @@ import {
39
40
  stopRunningController,
40
41
  tryQueryControllerStatus as tryQueryManagedControllerStatus,
41
42
  waitUntilControllerExited,
43
+ type IControllerStatusQuery,
42
44
  } from './classes.controllermanagement.js';
43
45
  import {
44
46
  inspectControllerProcess,
@@ -409,11 +411,16 @@ export const parseRuntimeOverrides = (
409
411
  };
410
412
  };
411
413
 
412
- const currentStatusExpectation = {
414
+ /**
415
+ * The CLI manages the controller of its own package, so it reads that controller's status over the transport its own
416
+ * `package.json` declares (`controllerManagementProtocolVersion`, which this build's constant equals).
417
+ */
418
+ const currentStatusExpectation: IControllerStatusQuery = {
413
419
  packageName: controllerPackageName,
414
420
  packageVersion: commitinfo.version,
415
421
  protocolVersion: controllerProtocolVersion,
416
422
  upgradeManagementVersion: controllerUpgradeManagementVersion,
423
+ managementProtocolVersion: controllerManagementProtocolVersion,
417
424
  };
418
425
 
419
426
  const assertStatus = (statusArg: unknown): IControllerStatus => assertControllerStatus(
@@ -1780,7 +1787,7 @@ const upgradeController = async (argvArg: TParsedArguments): Promise<void> => {
1780
1787
  controller: payload.expectedController!,
1781
1788
  });
1782
1789
  try {
1783
- const launched = await requestControllerUpgradeLaunch(port, payload.token);
1790
+ const launched = await requestControllerUpgradeLaunch(port, status, payload.token);
1784
1791
  worker = {
1785
1792
  pid: launched.workerPid,
1786
1793
  cliPath: installation.cliPath,
@@ -17,6 +17,7 @@ import { ControllerBrowserPaintTransport } from './classes.browserpainttransport
17
17
  import { ControllerBrowserAudioTransport } from './classes.browseraudiotransport.js';
18
18
  import { createBrowserDevToolsAssets, createBrowserDevToolsSurface } from './functions.browserdevtools.js';
19
19
  import { createControllerSecurityHeaders } from './functions.controllersecurityheaders.js';
20
+ import { createControllerManagementSurface } from './functions.controllermanagementsurface.js';
20
21
  import { createMonacoAssetsSurface } from './functions.monacoassets.js';
21
22
  import * as devToolsProtocol from '../ts_interfaces/devtools.js';
22
23
  import type {
@@ -120,6 +121,7 @@ import {
120
121
  controllerLiveToolExecutionIsCovered,
121
122
  controllerProtocolVersion,
122
123
  controllerUpgradeManagementVersion,
124
+ controllerManagementProtocolVersion,
123
125
  controllerLayoutItemRefKey,
124
126
  controllerRuntimeIdKey,
125
127
  controllerAgentMessageMaxTextBytes,
@@ -4169,6 +4171,7 @@ export class OpenCodeController {
4169
4171
  packageVersion: commitinfo.version,
4170
4172
  protocolVersion: controllerProtocolVersion,
4171
4173
  upgradeManagementVersion: controllerUpgradeManagementVersion,
4174
+ managementProtocolVersion: controllerManagementProtocolVersion,
4172
4175
  controllerPid: process.pid,
4173
4176
  processGroupId: this.processGroupId,
4174
4177
  processFingerprint: this.processFingerprint,
@@ -10151,6 +10154,11 @@ export class OpenCodeController {
10151
10154
  ),
10152
10155
  },
10153
10156
  surfaces: [
10157
+ // The CLI's and the upgrade worker's management calls: loopback HTTP, independent of the browser's socket.
10158
+ createControllerManagementSurface({
10159
+ port: runtimeConfig.controllerPort,
10160
+ router: this.createManagementRouter(),
10161
+ }),
10154
10162
  createBrowserDevToolsSurface(hostnames, browserDevToolsAssets),
10155
10163
  createMonacoAssetsSurface(hostnames, securityHeaders),
10156
10164
  ...browserViewerAssets.surfaces(hostnames, securityHeaders),
@@ -10624,7 +10632,7 @@ export class OpenCodeController {
10624
10632
  }
10625
10633
  const lifecycleGeneration = plugins.crypto.randomBytes(24).toString('base64url');
10626
10634
  const workerCallers = new ControllerWorkerCallers({ controllerGeneration: lifecycleGeneration,
10627
- registry: this.mcpCallerRegistry,
10635
+ controllerPort: runtimeConfig.controllerPort, registry: this.mcpCallerRegistry,
10628
10636
  readMaster: async () => {
10629
10637
  const resource = await configurationAuthority.getResource();
10630
10638
  return (await configurationAuthority.getMaster({ resourceId: resource.resourceId })).master;
@@ -13590,13 +13598,7 @@ export class OpenCodeController {
13590
13598
 
13591
13599
  /** Public scope: a browser reads the status before it holds a passkey session. */
13592
13600
  private registerStatusHandlers(publicRouterArg: plugins.typedrequest.TypedRouter): void {
13593
- publicRouterArg.addTypedHandler(new plugins.typedrequest.TypedHandler<IReq_ControllerStatus>(
13594
- 'controller.status',
13595
- async (requestArg) => {
13596
- validateRequest(() => assertEmptyRequest(requestArg));
13597
- return this.statusForPrincipal('browser');
13598
- },
13599
- ));
13601
+ publicRouterArg.addTypedHandler(this.createStatusHandler());
13600
13602
  }
13601
13603
 
13602
13604
  /**
@@ -13604,7 +13606,39 @@ export class OpenCodeController {
13604
13606
  * Every handler here authorises itself against the upgrade token it is handed.
13605
13607
  */
13606
13608
  private registerUpgradeHandlers(publicRouterArg: plugins.typedrequest.TypedRouter): void {
13607
- publicRouterArg.addTypedHandler(new plugins.typedrequest.TypedHandler<IReq_ControllerUpgradeLaunch>(
13609
+ publicRouterArg.addTypedHandler(this.createUpgradeLaunchHandler());
13610
+ publicRouterArg.addTypedHandler(this.createUpgradePrepareHandler());
13611
+ publicRouterArg.addTypedHandler(this.createUpgradePrepareBeginHandler());
13612
+ publicRouterArg.addTypedHandler(this.createUpgradeFinalizeHandler());
13613
+ }
13614
+
13615
+ /**
13616
+ * The router of the loopback management endpoint (`controllerManagementMethods`): the status read and the upgrade
13617
+ * methods the CLI and an upgrade worker of this or another release call. Each handler comes from the factory its
13618
+ * controller socket handler comes from, so it authorises itself exactly as it does there; the endpoint's admission
13619
+ * grants a request only its own peer. No other method is reachable through it.
13620
+ */
13621
+ private createManagementRouter(): plugins.typedrequest.TypedRouter {
13622
+ const router = new plugins.typedrequest.TypedRouter();
13623
+ router.addTypedHandler(this.createStatusHandler());
13624
+ router.addTypedHandler(this.createUpgradeLaunchHandler());
13625
+ router.addTypedHandler(this.createUpgradePrepareBeginHandler());
13626
+ router.addTypedHandler(this.createUpgradeFinalizeHandler());
13627
+ return router;
13628
+ }
13629
+
13630
+ private createStatusHandler(): plugins.typedrequest.TypedHandler<IReq_ControllerStatus> {
13631
+ return new plugins.typedrequest.TypedHandler<IReq_ControllerStatus>(
13632
+ 'controller.status',
13633
+ async (requestArg) => {
13634
+ validateRequest(() => assertEmptyRequest(requestArg));
13635
+ return this.statusForPrincipal('browser');
13636
+ },
13637
+ );
13638
+ }
13639
+
13640
+ private createUpgradeLaunchHandler(): plugins.typedrequest.TypedHandler<IReq_ControllerUpgradeLaunch> {
13641
+ return new plugins.typedrequest.TypedHandler<IReq_ControllerUpgradeLaunch>(
13608
13642
  'controller.upgrade.launch',
13609
13643
  async (requestArg, toolsArg) => {
13610
13644
  const peer = peerFromLocalData(toolsArg?.localData);
@@ -13690,9 +13724,12 @@ export class OpenCodeController {
13690
13724
  }
13691
13725
  });
13692
13726
  },
13693
- ));
13727
+ );
13728
+ }
13694
13729
 
13695
- publicRouterArg.addTypedHandler(new plugins.typedrequest.TypedHandler<IReq_ControllerUpgradePrepare>(
13730
+ /** The synchronous preparation an upgrade worker of an earlier release asks for; served on the socket only. */
13731
+ private createUpgradePrepareHandler(): plugins.typedrequest.TypedHandler<IReq_ControllerUpgradePrepare> {
13732
+ return new plugins.typedrequest.TypedHandler<IReq_ControllerUpgradePrepare>(
13696
13733
  'controller.upgrade.prepare',
13697
13734
  async (requestArg, toolsArg) => {
13698
13735
  const peer = peerFromLocalData(toolsArg?.localData);
@@ -13733,59 +13770,61 @@ export class OpenCodeController {
13733
13770
  })
13734
13771
  ));
13735
13772
  },
13736
- ));
13773
+ );
13774
+ }
13737
13775
 
13738
- publicRouterArg.addTypedHandler(
13739
- new plugins.typedrequest.TypedHandler<IReq_ControllerUpgradePrepareBegin>(
13740
- 'controller.upgrade.prepare.begin',
13741
- async (requestArg, toolsArg) => {
13742
- const peer = peerFromLocalData(toolsArg?.localData);
13743
- this.recordUnauthenticatedPreflightOperation(peer.id);
13744
- assertControllerUpgradePreparationRequest(requestArg);
13745
- return this.runOperation(peer, async () => (
13746
- this.runUpgradePreparationAdmission(async () => {
13747
- const installation = await resolveCurrentPnpmGlobalInstallation();
13748
- const coordinator = this.coordinatorForUpgradeToken(
13749
- requestArg.token,
13750
- installation.globalRoot,
13751
- );
13752
- if (await this.upgradePreparationReplayIsAccepted(
13753
- coordinator,
13754
- requestArg.token,
13755
- requestArg.targetVersion,
13756
- requestArg.gracePeriodMs,
13757
- )) return { accepted: true as const };
13758
- const status = this.getStatus();
13759
- await coordinator.consumeControllerActionGrant({
13760
- token: requestArg.token,
13761
- action: 'prepare',
13762
- packageVersion: commitinfo.version,
13763
- controller: {
13764
- pid: status.controllerPid,
13765
- processGroupId: status.processGroupId,
13766
- processFingerprint: status.processFingerprint,
13767
- },
13768
- });
13769
- await coordinator.recordController(requestArg.token, {
13776
+ private createUpgradePrepareBeginHandler(): plugins.typedrequest.TypedHandler<IReq_ControllerUpgradePrepareBegin> {
13777
+ return new plugins.typedrequest.TypedHandler<IReq_ControllerUpgradePrepareBegin>(
13778
+ 'controller.upgrade.prepare.begin',
13779
+ async (requestArg, toolsArg) => {
13780
+ const peer = peerFromLocalData(toolsArg?.localData);
13781
+ this.recordUnauthenticatedPreflightOperation(peer.id);
13782
+ assertControllerUpgradePreparationRequest(requestArg);
13783
+ return this.runOperation(peer, async () => (
13784
+ this.runUpgradePreparationAdmission(async () => {
13785
+ const installation = await resolveCurrentPnpmGlobalInstallation();
13786
+ const coordinator = this.coordinatorForUpgradeToken(
13787
+ requestArg.token,
13788
+ installation.globalRoot,
13789
+ );
13790
+ if (await this.upgradePreparationReplayIsAccepted(
13791
+ coordinator,
13792
+ requestArg.token,
13793
+ requestArg.targetVersion,
13794
+ requestArg.gracePeriodMs,
13795
+ )) return { accepted: true as const };
13796
+ const status = this.getStatus();
13797
+ await coordinator.consumeControllerActionGrant({
13798
+ token: requestArg.token,
13799
+ action: 'prepare',
13800
+ packageVersion: commitinfo.version,
13801
+ controller: {
13770
13802
  pid: status.controllerPid,
13771
13803
  processGroupId: status.processGroupId,
13772
- fingerprint: status.processFingerprint,
13773
- cliPath: installation.cliPath,
13774
- command: this.options.processMode === 'detached' ? '__serve' : 'foreground',
13775
- });
13776
- return await this.beginUpgradePreparation(
13777
- coordinator,
13778
- requestArg.token,
13779
- requestArg.targetVersion,
13780
- requestArg.gracePeriodMs,
13781
- );
13782
- })
13783
- ));
13784
- },
13785
- ),
13804
+ processFingerprint: status.processFingerprint,
13805
+ },
13806
+ });
13807
+ await coordinator.recordController(requestArg.token, {
13808
+ pid: status.controllerPid,
13809
+ processGroupId: status.processGroupId,
13810
+ fingerprint: status.processFingerprint,
13811
+ cliPath: installation.cliPath,
13812
+ command: this.options.processMode === 'detached' ? '__serve' : 'foreground',
13813
+ });
13814
+ return await this.beginUpgradePreparation(
13815
+ coordinator,
13816
+ requestArg.token,
13817
+ requestArg.targetVersion,
13818
+ requestArg.gracePeriodMs,
13819
+ );
13820
+ })
13821
+ ));
13822
+ },
13786
13823
  );
13824
+ }
13787
13825
 
13788
- publicRouterArg.addTypedHandler(new plugins.typedrequest.TypedHandler<IReq_ControllerUpgradeFinalize>(
13826
+ private createUpgradeFinalizeHandler(): plugins.typedrequest.TypedHandler<IReq_ControllerUpgradeFinalize> {
13827
+ return new plugins.typedrequest.TypedHandler<IReq_ControllerUpgradeFinalize>(
13789
13828
  'controller.upgrade.finalize',
13790
13829
  async (requestArg, toolsArg) => {
13791
13830
  const peer = peerFromLocalData(toolsArg?.localData);
@@ -13826,7 +13865,7 @@ export class OpenCodeController {
13826
13865
  return await this.finalizeUpgrade(coordinator, requestArg.token, requestArg.mode);
13827
13866
  });
13828
13867
  },
13829
- ));
13868
+ );
13830
13869
  }
13831
13870
 
13832
13871
  /**