@liberseek/boft-cli-win32-arm64 0.6.8 → 0.7.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 (34) hide show
  1. package/README.md +1 -1
  2. package/THIRD_PARTY_NOTICES.txt +16 -0
  3. package/app/codexhost-distribution.json +1 -1
  4. package/app/desktop-controller.mjs +184 -47
  5. package/app/host-runtime.mjs +5449 -4221
  6. package/app/plugins/antigravity/plugin.mjs +70 -61
  7. package/app/plugins/claude-code/plugin.mjs +85 -58
  8. package/app/plugins/codebuddy/plugin.mjs +102 -69
  9. package/app/plugins/cursor-cli/plugin.mjs +69 -50
  10. package/app/plugins/deepseek-harness/plugin.mjs +81 -53
  11. package/app/plugins/enabled.json +3 -1
  12. package/app/plugins/grok/plugin.mjs +94 -61
  13. package/app/plugins/hermes/plugin.mjs +308 -95
  14. package/app/plugins/kiro-cli/plugin.mjs +76 -49
  15. package/app/plugins/muse/plugin.mjs +66 -46
  16. package/app/plugins/omp/plugin.mjs +79 -52
  17. package/app/plugins/opencode/plugin.mjs +118 -92
  18. package/app/plugins/pi/plugin.mjs +79 -52
  19. package/app/plugins/qoder/assets/icon.svg +1 -0
  20. package/app/plugins/qoder/manifest.json +12 -0
  21. package/app/plugins/qoder/plugin.mjs +52290 -0
  22. package/app/plugins/qoder-cn/assets/icon.svg +1 -0
  23. package/app/plugins/qoder-cn/manifest.json +12 -0
  24. package/app/plugins/qoder-cn/plugin.mjs +52288 -0
  25. package/app/renderer-extension.js +3857 -1175
  26. package/bin/boft.exe +0 -0
  27. package/libexec/boft-node-repl.exe +0 -0
  28. package/libexec/boft-shim.exe +0 -0
  29. package/libexec/boft-updater.exe +0 -0
  30. package/licenses/Qoder-Agent-SDK-LICENSE.txt +7 -0
  31. package/licenses/QoderCN-Agent-SDK-LICENSE.txt +7 -0
  32. package/licenses/opencodex-LICENSE.txt +21 -0
  33. package/licenses/tailwindcss-LICENSE.txt +21 -0
  34. package/package.json +1 -1
package/README.md CHANGED
@@ -7,7 +7,7 @@ BOFT CLI runs Pi and other external harnesses inside Codex Desktop.
7
7
  ## Install
8
8
 
9
9
  ```bash
10
- npm install -g @liberseek/boft-cli@0.6.8
10
+ npm install -g @liberseek/boft-cli@0.7.0
11
11
  ```
12
12
 
13
13
  Do not install this package directly. npm selects it through the optional dependencies of `@liberseek/boft-cli`.
@@ -20,6 +20,14 @@ License text: licenses/MCP-SDK-LICENSE.txt
20
20
  License: MIT
21
21
  License text: licenses/OpenCode-SDK-LICENSE.txt
22
22
 
23
+ @qoder-ai/qoder-agent-sdk 1.0.39
24
+ License: SEE LICENSE IN LICENSE
25
+ License text: licenses/Qoder-Agent-SDK-LICENSE.txt
26
+
27
+ @qodercn-ai/qodercn-agent-sdk 1.0.39
28
+ License: SEE LICENSE IN LICENSE
29
+ License text: licenses/QoderCN-Agent-SDK-LICENSE.txt
30
+
23
31
  diff 8.0.2
24
32
  License: BSD-3-Clause
25
33
  License text: licenses/diff-LICENSE.txt
@@ -28,6 +36,10 @@ lucide 1.28.0
28
36
  License: ISC
29
37
  License text: licenses/lucide-LICENSE.txt
30
38
 
39
+ tailwindcss 4.3.3
40
+ License: MIT
41
+ License text: licenses/tailwindcss-LICENSE.txt
42
+
31
43
  ws 8.21.3
32
44
  License: MIT
33
45
  License text: licenses/ws-LICENSE.txt
@@ -35,3 +47,7 @@ License text: licenses/ws-LICENSE.txt
35
47
  zod 4.4.3
36
48
  License: MIT
37
49
  License text: licenses/zod-LICENSE.txt
50
+
51
+ opencodex native profiles (2d4d7a22381a2e497c2442902104619e25f937c7)
52
+ License: MIT
53
+ License text: licenses/opencodex-LICENSE.txt
@@ -1 +1 @@
1
- {"schemaVersion":1,"version":"0.6.8","distribution":"npm","target":"windows-arm64"}
1
+ {"schemaVersion":1,"version":"0.7.0","distribution":"npm","target":"windows-arm64"}
@@ -285,10 +285,99 @@ var CdpClient = class _CdpClient {
285
285
  }
286
286
  };
287
287
 
288
+ // packages/desktop-control/src/renderer-react-ownership.ts
289
+ function committedReactAncestors(value) {
290
+ const MAX_VISITED_FIBERS = 2e4;
291
+ const fiber = (value2) => typeof value2 === "object" && value2 !== null ? value2 : null;
292
+ const first = fiber(value);
293
+ if (!first) return [];
294
+ const previous = [];
295
+ const seen = /* @__PURE__ */ new Set();
296
+ for (let node = first; node; node = fiber(node.return)) {
297
+ if (seen.has(node) || seen.size >= MAX_VISITED_FIBERS) return [];
298
+ seen.add(node);
299
+ previous.push(node);
300
+ }
301
+ const rootState = fiber(previous.at(-1)?.stateNode);
302
+ if (!rootState || !("current" in rootState)) return previous;
303
+ const current = fiber(rootState.current);
304
+ if (!current) return [];
305
+ const stack = [{ node: current, parent: null }];
306
+ const alternate = fiber(first.alternate);
307
+ seen.clear();
308
+ while (stack.length > 0 && seen.size < MAX_VISITED_FIBERS) {
309
+ const entry = stack.pop();
310
+ if (!entry) break;
311
+ if (seen.has(entry.node)) return [];
312
+ seen.add(entry.node);
313
+ if (entry.node === first || entry.node === alternate) {
314
+ const ancestors = [];
315
+ for (let cursor = entry; cursor; cursor = cursor.parent)
316
+ ancestors.push(cursor.node);
317
+ return ancestors;
318
+ }
319
+ const sibling = entry.parent && fiber(entry.node.sibling);
320
+ if (sibling) stack.push({ node: sibling, parent: entry.parent });
321
+ const child = fiber(entry.node.child);
322
+ if (child) stack.push({ node: child, parent: entry });
323
+ }
324
+ return [];
325
+ }
326
+
327
+ // packages/desktop-control/src/renderer-host-response-ownership.ts
328
+ function retainRendererHostResponses(client, hostId, target) {
329
+ if (typeof client.addRequestLifecycleListener !== "function" || typeof target.addEventListener !== "function" || typeof target.removeEventListener !== "function")
330
+ return () => {
331
+ };
332
+ const isRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
333
+ const pending = /* @__PURE__ */ new Set();
334
+ let retired = false;
335
+ let unsubscribe = () => {
336
+ };
337
+ const detach = () => {
338
+ target.removeEventListener?.("message", receive);
339
+ unsubscribe();
340
+ };
341
+ const receive = (event) => {
342
+ const { source, origin, data } = event;
343
+ if (source != null && source !== target) return;
344
+ const ownOrigin = target.location?.origin;
345
+ if (source === target && ownOrigin && ownOrigin !== "null" && origin !== ownOrigin) return;
346
+ if (!isRecord4(data) || data.type !== "mcp-response" || data.hostId !== hostId) return;
347
+ const message = data.message;
348
+ if (!isRecord4(message)) return;
349
+ const id = message.id;
350
+ if (typeof id !== "string" && typeof id !== "number" || !pending.has(id)) return;
351
+ const hasError = isRecord4(message.error);
352
+ if (!hasError && !Object.prototype.hasOwnProperty.call(message, "result")) return;
353
+ queueMicrotask(() => {
354
+ if (!pending.has(id)) return;
355
+ if (hasError) client.onError(id, message.error, data.hostMetrics);
356
+ else client.onResult(id, message.result, data.hostMetrics);
357
+ });
358
+ };
359
+ target.addEventListener("message", receive);
360
+ unsubscribe = client.addRequestLifecycleListener((event) => {
361
+ if (!isRecord4(event) || event.hostId !== hostId) return;
362
+ const id = event.id;
363
+ if (typeof id !== "string" && typeof id !== "number") return;
364
+ if (!retired && event.type === "started" && typeof event.method === "string" && event.method.startsWith("codexhost/"))
365
+ pending.add(id);
366
+ else if (event.type === "completed" || event.type === "failed") {
367
+ pending.delete(id);
368
+ if (retired && pending.size === 0) detach();
369
+ }
370
+ });
371
+ return () => {
372
+ retired = true;
373
+ if (pending.size === 0) detach();
374
+ };
375
+ }
376
+
288
377
  // packages/desktop-control/src/renderer-draft-prewarm-runtime.ts
289
- function installDraftPrewarmPolicyBridge(manager, bridge, hostId, target, prewarmedThreadManager) {
378
+ function installDraftPrewarmPolicyBridge(manager, bridge, hostId, target, prewarmedThreadManager, isCurrentManager, retainResponses = retainRendererHostResponses) {
290
379
  const existing = target.__codexhostDraftPrewarmPolicyV1;
291
- if (existing?.owns?.length === 4 && existing.owns(manager, bridge, hostId, prewarmedThreadManager) === true) {
380
+ if (existing?.owns?.length === 5 && existing.owns(manager, bridge, hostId, prewarmedThreadManager, !!isCurrentManager) === true) {
292
381
  return { state: "ready", reason: "owned-request-bridge" };
293
382
  }
294
383
  existing?.dispose?.();
@@ -297,9 +386,21 @@ function installDraftPrewarmPolicyBridge(manager, bridge, hostId, target, prewar
297
386
  const originalOnNotification = manager.onNotification;
298
387
  const originalDispatchAppServerResponse = manager.dispatchAppServerResponse;
299
388
  let selectedModel = null;
300
- let selectedCodexAccountId = null;
301
389
  const isRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
390
+ const isUnsupportedPosixBridgeSpawn = (value) => {
391
+ const marker = "AbsolutePathBuf deserialized without a base path";
392
+ if (typeof value === "string") {
393
+ return value.startsWith("Invalid request:") && value.includes(marker);
394
+ }
395
+ if (!isRecord4(value)) return false;
396
+ if (typeof value.message === "string" && value.message.includes(marker)) {
397
+ if (value.code === -32600 || value.message.startsWith("Invalid request:")) return true;
398
+ }
399
+ return value.cause !== value && isUnsupportedPosixBridgeSpawn(value.cause);
400
+ };
302
401
  const isRemoteControlHost = hostId.startsWith("remote-control:");
402
+ const retireResponses = isRemoteControlHost ? () => {
403
+ } : retainResponses(bridge, hostId, target);
303
404
  const knownExternalThreadIds = /* @__PURE__ */ new Set();
304
405
  const knownOfficialThreadIds = /* @__PURE__ */ new Set();
305
406
  const threadOwnershipResolutions = /* @__PURE__ */ new Map();
@@ -650,7 +751,7 @@ function installDraftPrewarmPolicyBridge(manager, bridge, hostId, target, prewar
650
751
  if (method.startsWith("codexhost/")) return true;
651
752
  if (method === "thread/list") return true;
652
753
  if (method === "thread/start") {
653
- return isRecord4(parameters) && (typeof parameters.model === "string" && parameters.model.startsWith("codexhost/") || typeof parameters.__codexhostAccountId === "string");
754
+ return isRecord4(parameters) && typeof parameters.model === "string" && parameters.model.startsWith("codexhost/");
654
755
  }
655
756
  const threadId = threadIdFromParameters(parameters);
656
757
  if (threadId && knownExternalThreadIds.has(threadId)) return true;
@@ -661,13 +762,10 @@ function installDraftPrewarmPolicyBridge(manager, bridge, hostId, target, prewar
661
762
  if (!isRecord4(parameters) || parameters.ephemeral === true) {
662
763
  return parameters;
663
764
  }
664
- const routed = {
765
+ return {
665
766
  ...parameters,
666
- ...selectedModel === null ? {} : { model: selectedModel },
667
- ...selectedCodexAccountId === null ? {} : { __codexhostAccountId: selectedCodexAccountId }
767
+ ...selectedModel === null ? {} : { model: selectedModel }
668
768
  };
669
- selectedCodexAccountId = null;
670
- return routed;
671
769
  };
672
770
  const routedSend = (method, parameters, options) => {
673
771
  const routedParameters = method === "thread/start" ? routeThreadStart(parameters) : parameters;
@@ -678,7 +776,17 @@ function installDraftPrewarmPolicyBridge(manager, bridge, hostId, target, prewar
678
776
  const unresolvedThreadId = shouldResolveThreadOwnership(method, routedParameters);
679
777
  if (unresolvedThreadId) {
680
778
  return resolveThreadOwnership(unresolvedThreadId).then(
681
- (owner) => owner === "external" ? sendBridged() : sendDirect()
779
+ (owner) => owner === "external" ? sendBridged() : sendDirect(),
780
+ (error) => {
781
+ if ((method === "thread/read" || method === "thread/resume") && isUnsupportedPosixBridgeSpawn(error)) {
782
+ return Promise.resolve(sendDirect()).then((result) => {
783
+ knownOfficialThreadIds.add(unresolvedThreadId);
784
+ knownExternalThreadIds.delete(unresolvedThreadId);
785
+ return result;
786
+ });
787
+ }
788
+ throw error;
789
+ }
682
790
  );
683
791
  }
684
792
  return shouldUseBridge(method, routedParameters) ? sendBridged() : sendDirect();
@@ -725,10 +833,12 @@ function installDraftPrewarmPolicyBridge(manager, bridge, hostId, target, prewar
725
833
  const policy = Object.freeze({
726
834
  state: "ready",
727
835
  hostId,
728
- owns(candidateManager, candidate, candidateHostId, candidatePrewarmedThreadManager) {
729
- return candidateManager === manager && candidate === bridge && candidateHostId === hostId && candidatePrewarmedThreadManager === prewarmedThreadManager;
836
+ owns(candidateManager, candidate, candidateHostId, candidatePrewarmedThreadManager, requiresCurrentManager) {
837
+ return candidateManager === manager && candidate === bridge && candidateHostId === hostId && candidatePrewarmedThreadManager === prewarmedThreadManager && requiresCurrentManager === !!isCurrentManager;
730
838
  },
731
839
  requestTarget() {
840
+ if (isCurrentManager && !isCurrentManager())
841
+ throw new Error("Renderer request manager is retired");
732
842
  return manager;
733
843
  },
734
844
  select(model) {
@@ -739,19 +849,12 @@ function installDraftPrewarmPolicyBridge(manager, bridge, hostId, target, prewar
739
849
  selectedModel = model;
740
850
  return true;
741
851
  },
742
- selectAccount(accountId) {
743
- if (accountId !== null && !/^[A-Za-z0-9._~-]+$/u.test(accountId)) {
744
- throw new Error("Draft Codex Account ID must be filename-safe");
745
- }
746
- if (selectedCodexAccountId === accountId) return false;
747
- selectedCodexAccountId = accountId;
748
- return true;
749
- },
750
852
  clear() {
751
853
  prewarmedThreadManager.discardAllPrewarmedThreads();
752
854
  return Promise.resolve();
753
855
  },
754
856
  dispose() {
857
+ retireResponses();
755
858
  if (bridge.sendRequest === routedSend) bridge.sendRequest = originalSend;
756
859
  if (bridge.prewarmThreadStart === routedPrewarm) {
757
860
  bridge.prewarmThreadStart = originalPrewarm;
@@ -781,7 +884,6 @@ function installDraftPrewarmPolicyBridge(manager, bridge, hostId, target, prewar
781
884
  knownOfficialThreadIds.clear();
782
885
  threadOwnershipResolutions.clear();
783
886
  selectedModel = null;
784
- selectedCodexAccountId = null;
785
887
  }
786
888
  });
787
889
  Object.defineProperty(target, "__codexhostDraftPrewarmPolicyV1", {
@@ -808,51 +910,70 @@ function selectRendererRequestManager(candidates, activeHostIds) {
808
910
  );
809
911
  return eligible.length === 1 ? eligible[0] ?? null : null;
810
912
  }
811
- function requestManagerFromHookState(value) {
913
+ function requestManagerFromHookState(value, activeHostId) {
812
914
  const matchesRequestManager = (candidate) => {
813
- if (candidate == null || typeof candidate !== "object") return false;
814
- const value2 = candidate;
815
- return value2.requestClient != null && typeof value2.requestClient.prewarmThreadStart === "function" && typeof value2.requestClient.sendRequest === "function" && typeof value2.requestClient.enqueueRequest === "function" && typeof value2.prewarmedThreadManager?.discardAllPrewarmedThreads === "function" && typeof value2.sendRequest === "function";
915
+ if (candidate == null || typeof candidate !== "object" || !("requestClient" in candidate) || !("prewarmedThreadManager" in candidate) || !("sendRequest" in candidate)) {
916
+ return false;
917
+ }
918
+ const requestClient = candidate.requestClient;
919
+ const prewarmedThreadManager = candidate.prewarmedThreadManager;
920
+ return requestClient != null && typeof requestClient === "object" && "prewarmThreadStart" in requestClient && typeof requestClient.prewarmThreadStart === "function" && "sendRequest" in requestClient && typeof requestClient.sendRequest === "function" && "enqueueRequest" in requestClient && typeof requestClient.enqueueRequest === "function" && prewarmedThreadManager != null && typeof prewarmedThreadManager === "object" && "discardAllPrewarmedThreads" in prewarmedThreadManager && typeof prewarmedThreadManager.discardAllPrewarmedThreads === "function" && typeof candidate.sendRequest === "function";
816
921
  };
817
922
  if (matchesRequestManager(value)) return value;
818
- if (value != null && typeof value === "object" && matchesRequestManager(value.manager)) {
923
+ if (value != null && typeof value === "object" && "manager" in value && matchesRequestManager(value.manager)) {
819
924
  return value.manager;
820
925
  }
821
- return null;
926
+ if (typeof activeHostId !== "string" || activeHostId.length === 0) return null;
927
+ if (value == null || typeof value !== "object" || !("addManager" in value) || typeof value.addManager !== "function" || !("getForHostId" in value) || typeof value.getForHostId !== "function" || !("waitForManagerForHostId" in value) || typeof value.waitForManagerForHostId !== "function") {
928
+ return null;
929
+ }
930
+ const manager = value.getForHostId.call(value, activeHostId);
931
+ return matchesRequestManager(manager) ? manager : null;
822
932
  }
823
933
  function isRecord2(value) {
824
934
  return typeof value === "object" && value !== null && !Array.isArray(value);
825
935
  }
826
936
  var FIND_REQUEST_MANAGER_EXPRESSION = `(() => {
827
937
  const requestManagerFromHookState = ${requestManagerFromHookState.toString()};
938
+ const committedReactAncestors = ${committedReactAncestors.toString()};
828
939
  const editors = [...document.querySelectorAll(
829
940
  '[data-codex-composer], [contenteditable="true"][role="textbox"]',
830
941
  )];
831
- if (editors.length !== 1) {
832
- return { candidateCount: 0, hostId: null, sendRequest: null };
942
+ if (editors.length === 0) {
943
+ return { candidateCount: 0, editorCount: editors.length, hostId: null, sendRequest: null };
833
944
  }
834
- let element = editors[0];
835
- let fiber = null;
836
- while (element != null && fiber == null) {
837
- const key = Object.getOwnPropertyNames(element).find((name) =>
838
- name.startsWith('__reactFiber$'),
839
- );
840
- if (key != null) fiber = element[key];
841
- element = element.parentElement;
842
- }
843
- const managers = new Set();
945
+ // Main and side chat can expose multiple editors backed by the same manager.
946
+ // Resolve their combined Host ownership before consulting any Host registry.
947
+ const composerAncestors = new Set();
844
948
  const activeHostIds = new Set();
845
- for (let depth = 0; fiber != null && depth < 200; depth += 1, fiber = fiber.return) {
846
- const props = fiber.memoizedProps;
847
- if (props != null && typeof props === 'object') {
848
- for (const name of ['executionTargetHostId', 'permissionsHostId']) {
849
- const value = props[name];
850
- if (typeof value === 'string' && value.length > 0) activeHostIds.add(value);
949
+ for (const editor of editors) {
950
+ let element = editor;
951
+ let fiber = null;
952
+ while (element != null && fiber == null) {
953
+ const key = Object.getOwnPropertyNames(element).find((name) =>
954
+ name.startsWith('__reactFiber$'),
955
+ );
956
+ if (key != null) fiber = element[key];
957
+ element = element.parentElement;
958
+ }
959
+ for (const current of committedReactAncestors(fiber)) {
960
+ composerAncestors.add(current);
961
+ const props = current.memoizedProps;
962
+ if (props != null && typeof props === 'object') {
963
+ for (const name of ['executionTargetHostId', 'permissionsHostId']) {
964
+ const value = props[name];
965
+ if (typeof value === 'string' && value.length > 0) activeHostIds.add(value);
966
+ }
851
967
  }
852
968
  }
969
+ }
970
+ const activeHostId =
971
+ activeHostIds.size === 1 ? activeHostIds.values().next().value : undefined;
972
+ const managers = new Set();
973
+ for (const fiber of composerAncestors) {
853
974
  let hook = fiber.memoizedState;
854
975
  for (let index = 0; hook != null && index < 120; index += 1, hook = hook.next) {
855
- const manager = requestManagerFromHookState(hook.memoizedState);
976
+ const manager = requestManagerFromHookState(hook.memoizedState, activeHostId);
856
977
  if (manager != null) managers.add(manager);
857
978
  }
858
979
  }
@@ -873,12 +994,20 @@ var FIND_REQUEST_MANAGER_EXPRESSION = `(() => {
873
994
  const selected = (${selectRendererRequestManager.toString()})(candidates, [...activeHostIds]);
874
995
  return {
875
996
  candidateCount: selected == null ? candidates.length : 1,
997
+ editorCount: editors.length,
876
998
  hostId: selected?.hostId ?? null,
877
999
  manager: selected?.manager ?? null,
878
1000
  requestClient: selected?.requestClient ?? null,
879
1001
  prewarmedThreadManager: selected?.prewarmedThreadManager ?? null,
880
1002
  };
881
1003
  })()`;
1004
+ var IS_CURRENT_REQUEST_MANAGER = `function(manager, requestClient, hostId, prewarmedThreadManager) {
1005
+ const current = ${FIND_REQUEST_MANAGER_EXPRESSION};
1006
+ return current.editorCount === 0 || (
1007
+ current.manager === manager && current.requestClient === requestClient &&
1008
+ current.hostId === hostId && current.prewarmedThreadManager === prewarmedThreadManager
1009
+ );
1010
+ }`;
882
1011
  var INSTALL_RENDERER_POLICY_FUNCTION = `function(requestClient, hostId, prewarmedThreadManager) {
883
1012
  return (${installDraftPrewarmPolicyBridge.toString()})(
884
1013
  this,
@@ -886,6 +1015,8 @@ var INSTALL_RENDERER_POLICY_FUNCTION = `function(requestClient, hostId, prewarme
886
1015
  hostId,
887
1016
  window,
888
1017
  prewarmedThreadManager,
1018
+ () => (${IS_CURRENT_REQUEST_MANAGER})(this, requestClient, hostId, prewarmedThreadManager),
1019
+ (${retainRendererHostResponses.toString()}),
889
1020
  );
890
1021
  }`;
891
1022
  var REQUEST_MANAGER_WAIT_TIMEOUT_MS = 6e4;
@@ -911,6 +1042,10 @@ function directRendererInstaller() {
911
1042
  selected.hostId,
912
1043
  window,
913
1044
  selected.prewarmedThreadManager,
1045
+ () => (${IS_CURRENT_REQUEST_MANAGER})(
1046
+ selected.manager, selected.requestClient, selected.hostId, selected.prewarmedThreadManager,
1047
+ ),
1048
+ (${retainRendererHostResponses.toString()}),
914
1049
  );
915
1050
  })()`;
916
1051
  }
@@ -1359,7 +1494,9 @@ ${rendererSource}`,
1359
1494
  "muse",
1360
1495
  "kiro-cli",
1361
1496
  "codebuddy",
1362
- "cursor-cli"
1497
+ "cursor-cli",
1498
+ "qoder",
1499
+ "qoder-cn"
1363
1500
  ],
1364
1501
  timeoutMs: PRODUCTION_INSTALL_TIMEOUT_MS
1365
1502
  },