@codexhost/cli-darwin-arm64 0.16.1 → 0.17.1

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.
@@ -227,13 +227,32 @@ var CdpClient = class _CdpClient {
227
227
  returnByValue: true
228
228
  });
229
229
  if (!isRecord(response)) throw new Error("Runtime.evaluate returned an invalid result");
230
- if (isRecord(response.exceptionDetails)) {
231
- throw new Error(cdpExceptionMessage(response.exceptionDetails, "Renderer evaluation failed"));
232
- }
233
- if (!isRecord(response.result) || !("value" in response.result)) {
234
- throw new Error("Runtime.evaluate did not return a value");
230
+ try {
231
+ if (isRecord(response.exceptionDetails)) {
232
+ throw new Error(
233
+ cdpExceptionMessage(response.exceptionDetails, "Renderer evaluation failed")
234
+ );
235
+ }
236
+ if (!isRecord(response.result) || !("value" in response.result)) {
237
+ throw new Error("Runtime.evaluate did not return a value");
238
+ }
239
+ return response.result.value;
240
+ } finally {
241
+ const objects = [
242
+ response.result,
243
+ isRecord(response.exceptionDetails) ? response.exceptionDetails.exception : void 0
244
+ ];
245
+ const ids = new Set(
246
+ objects.flatMap(
247
+ (object2) => isRecord(object2) && typeof object2.objectId === "string" ? [object2.objectId] : []
248
+ )
249
+ );
250
+ await Promise.all(
251
+ [...ids].map(
252
+ (objectId) => this.command("Runtime.releaseObject", { objectId }).catch(() => void 0)
253
+ )
254
+ );
235
255
  }
236
- return response.result.value;
237
256
  }
238
257
  close() {
239
258
  if (this.#closed) return;
@@ -16799,9 +16818,10 @@ function isolateRendererPrewarmConsumption(manager, discardExternal) {
16799
16818
  }
16800
16819
 
16801
16820
  // packages/desktop-control/src/renderer-draft-prewarm-runtime.ts
16802
- function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewarmedThreadManager, isCurrentManager, retainResponses = retainRendererHostResponses, isolateConsumption = isolateRendererPrewarmConsumption) {
16821
+ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewarmedThreadManager, isCurrentManager, retainResponses = retainRendererHostResponses, isolateConsumption = isolateRendererPrewarmConsumption, sendControlRequest) {
16803
16822
  let disposed = false;
16804
16823
  const originalSend = bridge.sendRequest;
16824
+ const controlSend = (method, parameters) => sendControlRequest ? sendControlRequest(method, parameters) : originalSend.call(bridge, method, parameters);
16805
16825
  const originalPrewarm = bridge.prewarmThreadStart;
16806
16826
  const originalOnNotification = manager.onNotification;
16807
16827
  const originalDispatchAppServerResponse = manager.dispatchAppServerResponse;
@@ -16885,7 +16905,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
16885
16905
  bridgeRequests.clear();
16886
16906
  if (isRemoteControlHost && terminate) {
16887
16907
  void Promise.resolve(
16888
- originalSend.call(bridge, "process/kill", { processHandle: failedProcessHandle })
16908
+ controlSend("process/kill", { processHandle: failedProcessHandle })
16889
16909
  ).catch(() => void 0);
16890
16910
  }
16891
16911
  };
@@ -17048,7 +17068,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
17048
17068
  ];
17049
17069
  const startedProcessHandle = bridgeProcessHandle;
17050
17070
  try {
17051
- const started = originalSend.call(bridge, "process/spawn", {
17071
+ const started = controlSend("process/spawn", {
17052
17072
  command,
17053
17073
  processHandle: startedProcessHandle,
17054
17074
  cwd: "C:\\",
@@ -17069,7 +17089,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
17069
17089
  const operation = async () => {
17070
17090
  await startBridge();
17071
17091
  if (bridgeState !== "ready") throw transportError("is not ready");
17072
- await originalSend.call(bridge, "process/writeStdin", {
17092
+ await controlSend("process/writeStdin", {
17073
17093
  processHandle: bridgeProcessHandle,
17074
17094
  deltaBase64: utf8Base64(`${JSON.stringify(value)}
17075
17095
  `)
@@ -17344,7 +17364,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
17344
17364
  bridgeReadyTimeout = null;
17345
17365
  if (isRemoteControlHost && (bridgeState === "starting" || bridgeState === "ready")) {
17346
17366
  void Promise.resolve(
17347
- originalSend.call(bridge, "process/kill", { processHandle: bridgeProcessHandle })
17367
+ controlSend("process/kill", { processHandle: bridgeProcessHandle })
17348
17368
  ).catch(() => void 0);
17349
17369
  }
17350
17370
  bridgeState = "disposed";
@@ -17446,10 +17466,11 @@ function resolveRendererHostManager(discovery, hostId2, managerFrom = requestMan
17446
17466
  }
17447
17467
 
17448
17468
  // packages/desktop-control/src/renderer-host-routing.ts
17449
- function installRendererHostRouting(root, target, discover, resolve, createPolicy) {
17469
+ function installRendererHostRouting(root, target, discover, resolve, createPolicy, readConnection, publishRouting = true) {
17450
17470
  const existing = target.__codexhostHostRoutingV1;
17451
- if (existing) return existing;
17452
- target.__codexhostDraftPrewarmPolicyV1?.dispose?.();
17471
+ if (publishRouting && existing) return existing;
17472
+ if (publishRouting)
17473
+ target.__codexhostDraftPrewarmPolicyV1?.dispose?.();
17453
17474
  let disposed = false;
17454
17475
  let lastDiscovery = null;
17455
17476
  const routes = /* @__PURE__ */ new Map();
@@ -17476,10 +17497,20 @@ function installRendererHostRouting(root, target, discover, resolve, createPolic
17476
17497
  routes.delete(hostId2);
17477
17498
  entry?.route.policy.dispose();
17478
17499
  };
17500
+ const connectionFor = (hostId2) => {
17501
+ if (!hostId2.startsWith("remote-control:")) return void 0;
17502
+ try {
17503
+ return readConnection?.(hostId2);
17504
+ } catch {
17505
+ return null;
17506
+ }
17507
+ };
17508
+ const sameConnection = (expected, current) => expected === void 0 ? current === void 0 : current?.owner === expected.owner && current.revision === expected.revision;
17479
17509
  const routeFor = (hostId2, discovery) => {
17480
17510
  const manager = lookup(hostId2, discovery);
17511
+ const connection = connectionFor(hostId2);
17481
17512
  const previous = routes.get(hostId2);
17482
- if (manager && previous?.route.manager === manager && previous.bridge === manager.requestClient && previous.prewarmed === manager.prewarmedThreadManager && previous.route.policy.owns(
17513
+ if (manager && previous?.route.manager === manager && previous.bridge === manager.requestClient && previous.prewarmed === manager.prewarmedThreadManager && sameConnection(previous.connection, connection) && previous.route.policy.owns(
17483
17514
  manager,
17484
17515
  manager.requestClient,
17485
17516
  hostId2,
@@ -17489,7 +17520,7 @@ function installRendererHostRouting(root, target, discover, resolve, createPolic
17489
17520
  return previous.route;
17490
17521
  }
17491
17522
  retire(hostId2);
17492
- if (!manager) return null;
17523
+ if (!manager || connection === null) return null;
17493
17524
  const bridge = manager.requestClient;
17494
17525
  const prewarmed = manager.prewarmedThreadManager;
17495
17526
  const policy = createPolicy(
@@ -17498,13 +17529,14 @@ function installRendererHostRouting(root, target, discover, resolve, createPolic
17498
17529
  hostId2,
17499
17530
  target,
17500
17531
  prewarmed,
17501
- () => lookup(hostId2) === manager && manager.requestClient === bridge && manager.prewarmedThreadManager === prewarmed
17532
+ () => lookup(hostId2) === manager && sameConnection(connection, connectionFor(hostId2)) && manager.requestClient === bridge && manager.prewarmedThreadManager === prewarmed
17502
17533
  );
17503
17534
  const route = { hostId: hostId2, manager, policy };
17504
- routes.set(hostId2, { route, bridge, prewarmed });
17535
+ routes.set(hostId2, { route, bridge, prewarmed, connection });
17505
17536
  return route;
17506
17537
  };
17507
17538
  const publish = (route) => {
17539
+ if (!publishRouting) return;
17508
17540
  const policy = route?.policy;
17509
17541
  if (target.__codexhostDraftPrewarmPolicyV1 === policy) return;
17510
17542
  Object.defineProperty(target, "__codexhostDraftPrewarmPolicyV1", {
@@ -17557,7 +17589,7 @@ function installRendererHostRouting(root, target, discover, resolve, createPolic
17557
17589
  if (!composer) {
17558
17590
  for (const [hostId3, entry] of routes) {
17559
17591
  const manager = lookup(hostId3, discovery);
17560
- if (manager !== entry.route.manager || manager.requestClient !== entry.bridge || manager.prewarmedThreadManager !== entry.prewarmed)
17592
+ if (manager !== entry.route.manager || manager.requestClient !== entry.bridge || manager.prewarmedThreadManager !== entry.prewarmed || !sameConnection(entry.connection, connectionFor(hostId3)))
17561
17593
  retire(hostId3);
17562
17594
  }
17563
17595
  }
@@ -17577,7 +17609,11 @@ function installRendererHostRouting(root, target, discover, resolve, createPolic
17577
17609
  }
17578
17610
  }
17579
17611
  };
17580
- Object.defineProperty(target, "__codexhostHostRoutingV1", { configurable: true, value: routing });
17612
+ if (publishRouting)
17613
+ Object.defineProperty(target, "__codexhostHostRoutingV1", {
17614
+ configurable: true,
17615
+ value: routing
17616
+ });
17581
17617
  return routing;
17582
17618
  }
17583
17619
 
@@ -17671,17 +17707,37 @@ function installRendererHostRpcRouting(root, target, dependencies) {
17671
17707
  const existing = target.__codexhostHostRoutingV1;
17672
17708
  if (existing) return existing;
17673
17709
  let disposed = false;
17710
+ let nativeRouting = null;
17674
17711
  let discovery = null;
17675
17712
  const routes = /* @__PURE__ */ new Map();
17676
17713
  const read = () => {
17677
17714
  if (disposed) return null;
17678
- if (!discovery) {
17715
+ try {
17679
17716
  const store = dependencies.findStore(root);
17680
17717
  discovery = store ? dependencies.findFamily(store) : null;
17718
+ } catch {
17719
+ discovery = null;
17681
17720
  }
17682
17721
  return discovery;
17683
17722
  };
17684
17723
  if (!read()) return null;
17724
+ const native = () => {
17725
+ if (disposed) return null;
17726
+ try {
17727
+ nativeRouting ??= dependencies.nativeRouting?.() ?? null;
17728
+ } catch {
17729
+ }
17730
+ return nativeRouting;
17731
+ };
17732
+ const connectionFor = (hostId2) => {
17733
+ if (!hostId2.startsWith("remote-control:")) return void 0;
17734
+ try {
17735
+ return dependencies.readConnection?.(hostId2);
17736
+ } catch {
17737
+ return null;
17738
+ }
17739
+ };
17740
+ const sameConnection = (previous, current) => previous === void 0 ? current === void 0 : current?.owner === previous.owner && current.revision === previous.revision;
17685
17741
  const isRecord3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
17686
17742
  const externalDrafts = /* @__PURE__ */ new Map();
17687
17743
  const selectedModels = /* @__PURE__ */ new Map();
@@ -17724,16 +17780,20 @@ function installRendererHostRpcRouting(root, target, dependencies) {
17724
17780
  if (!isRecord3(input) || !isRecord3(input.collaborationMode)) return message;
17725
17781
  const settings = input.collaborationMode.settings;
17726
17782
  if (!isRecord3(settings)) return message;
17783
+ const nativeModel = typeof settings.model === "string" ? settings.model : null;
17727
17784
  let model2 = null;
17728
17785
  if (path3[0] === "startConversation") {
17729
17786
  const draftId = isRecord3(options) ? options.clientThreadId : null;
17730
17787
  model2 = typeof draftId === "string" ? externalDrafts.get(draftId)?.model ?? null : null;
17731
17788
  } else if (path3[0] === "prewarmConversation") {
17732
17789
  if (input.ephemeral !== true) publishDraftWorkspace("local", input.cwd);
17733
- const selected = selectedModels.get("local");
17734
- model2 = selected ? prewarmCarrier(selected) : null;
17790
+ const selected = selectedModels.get("local") ?? null;
17791
+ const carrier = nativeModel?.startsWith("codexhost/") ? nativeModel : selected;
17792
+ model2 = carrier ? prewarmCarrier(carrier) : null;
17735
17793
  }
17736
17794
  if (!model2) return message;
17795
+ if (path3[0] === "startConversation" && nativeModel?.startsWith("codexhost/") && nativeModel !== model2)
17796
+ return message;
17737
17797
  return [
17738
17798
  "push",
17739
17799
  [
@@ -17755,16 +17815,25 @@ function installRendererHostRpcRouting(root, target, dependencies) {
17755
17815
  const postMessage = function(message, ...rest) {
17756
17816
  let routed = message;
17757
17817
  try {
17758
- routed = disposed ? message : routeCreationCall(message);
17818
+ routed = disposed || routes.size === 0 ? message : routeCreationCall(message);
17759
17819
  } catch {
17760
17820
  routed = message;
17761
17821
  }
17762
17822
  return originalPostMessage.call(this, routed, ...rest);
17763
17823
  };
17764
17824
  port.postMessage = postMessage;
17765
- const createRoute = (hostId2, rpc) => {
17825
+ const createRoute = (hostId2, rpc, connection) => {
17766
17826
  let retired = false;
17767
- const isCurrent = () => !retired && !disposed && routes.get(hostId2)?.rpc === rpc;
17827
+ const isCurrent = () => {
17828
+ if (retired || disposed || routes.get(hostId2)?.rpc !== rpc || !sameConnection(connection, connectionFor(hostId2)))
17829
+ return false;
17830
+ try {
17831
+ const current = read();
17832
+ return !!current && dependencies.resolve(current, hostId2) === rpc;
17833
+ } catch {
17834
+ return false;
17835
+ }
17836
+ };
17768
17837
  const manager = Object.freeze({
17769
17838
  kind: "main-process-rpc",
17770
17839
  getHostId: () => hostId2,
@@ -17837,15 +17906,23 @@ function installRendererHostRpcRouting(root, target, dependencies) {
17837
17906
  routes.delete(hostId2);
17838
17907
  entry?.route.policy.dispose();
17839
17908
  };
17840
- const routeFor = (hostId2) => {
17909
+ const routeFor = (hostId2, nativeRoute) => {
17910
+ if (disposed) return null;
17911
+ const connection = connectionFor(hostId2);
17912
+ const preferred = nativeRoute === void 0 ? native()?.forHost(hostId2) : nativeRoute;
17913
+ if (connection === null || preferred) {
17914
+ retire(hostId2);
17915
+ return connection === null ? null : preferred ?? null;
17916
+ }
17841
17917
  const current = read();
17842
17918
  const rpc = current ? dependencies.resolve(current, hostId2) : null;
17843
17919
  const previous = routes.get(hostId2);
17844
- if (rpc && previous?.rpc === rpc) return previous.route;
17920
+ if (rpc && previous?.rpc === rpc && sameConnection(previous.connection, connection))
17921
+ return previous.route;
17845
17922
  retire(hostId2);
17846
17923
  if (!rpc) return null;
17847
- const route = createRoute(hostId2, rpc);
17848
- routes.set(hostId2, { route, rpc });
17924
+ const route = createRoute(hostId2, rpc, connection);
17925
+ routes.set(hostId2, { route, rpc, connection });
17849
17926
  return route;
17850
17927
  };
17851
17928
  const publish = (route) => {
@@ -17860,14 +17937,22 @@ function installRendererHostRpcRouting(root, target, dependencies) {
17860
17937
  }
17861
17938
  };
17862
17939
  const composerHostId = (composer) => {
17940
+ const nativeHostId = native()?.hostIdForComposer(composer);
17941
+ if (nativeHostId) return nativeHostId;
17863
17942
  const hostIds = new Set(dependencies.composerHostIds(composer).hostIds);
17864
17943
  const hostId2 = hostIds.size === 1 ? hostIds.values().next().value : null;
17865
17944
  return typeof hostId2 === "string" && hostId2 ? hostId2 : null;
17866
17945
  };
17867
17946
  const routing = {
17868
17947
  knownHostIds() {
17948
+ if (disposed) return [];
17869
17949
  const current = read();
17870
- return current ? dependencies.hostIds(current) : [];
17950
+ return [
17951
+ .../* @__PURE__ */ new Set([
17952
+ ...current ? dependencies.hostIds(current) : [],
17953
+ ...native()?.knownHostIds?.() ?? []
17954
+ ])
17955
+ ];
17871
17956
  },
17872
17957
  forHost(hostId2) {
17873
17958
  return hostId2 && !disposed ? routeFor(hostId2) : null;
@@ -17883,18 +17968,22 @@ function installRendererHostRpcRouting(root, target, dependencies) {
17883
17968
  forComposer(composer) {
17884
17969
  if (disposed) return null;
17885
17970
  let hostId2;
17971
+ let preferred = null;
17886
17972
  try {
17887
- hostId2 = composerHostId(composer);
17973
+ preferred = native()?.forComposer(composer) ?? null;
17974
+ hostId2 = preferred?.hostId ?? composerHostId(composer);
17888
17975
  } catch {
17889
17976
  hostId2 = null;
17890
17977
  }
17891
- const route = hostId2 ? routeFor(hostId2) : null;
17978
+ const route = hostId2 ? routeFor(hostId2, preferred) : null;
17892
17979
  if (!composer) publish(route);
17893
17980
  return route;
17894
17981
  },
17895
17982
  dispose() {
17896
17983
  if (disposed) return;
17897
17984
  disposed = true;
17985
+ nativeRouting?.dispose();
17986
+ nativeRouting = null;
17898
17987
  for (const hostId2 of [...routes.keys()]) retire(hostId2);
17899
17988
  discovery = null;
17900
17989
  externalDrafts.clear();
@@ -17910,6 +17999,30 @@ function installRendererHostRpcRouting(root, target, dependencies) {
17910
17999
  return routing;
17911
18000
  }
17912
18001
 
18002
+ // packages/desktop-control/src/renderer-connection-generation.ts
18003
+ function readRendererConnectionGeneration(store, hostId2) {
18004
+ if (!store) return void 0;
18005
+ const record3 = (value) => value !== null && typeof value === "object";
18006
+ const candidates = /* @__PURE__ */ new Set();
18007
+ for (const members of store.familyBindings.values()) {
18008
+ const value = members.get(hostId2)?.value;
18009
+ if (record3(value) && record3(value.state$) && record3(value.revision$) && record3(value.appServerVersion$) && typeof value.state$.get === "function" && typeof value.revision$.get === "function")
18010
+ candidates.add(value);
18011
+ }
18012
+ if (!candidates.size) return void 0;
18013
+ if (candidates.size !== 1) return null;
18014
+ const owner = candidates.values().next().value;
18015
+ if (!owner) return null;
18016
+ const state = owner.state$;
18017
+ const revision = owner.revision$;
18018
+ try {
18019
+ const current = revision.get();
18020
+ return state.get() === "connected" && typeof current === "number" && Number.isSafeInteger(current) ? { owner, revision: current } : null;
18021
+ } catch {
18022
+ return null;
18023
+ }
18024
+ }
18025
+
17913
18026
  // packages/desktop-control/src/renderer-draft-prewarm-policy.ts
17914
18027
  var REQUEST_MANAGER_WAIT_TIMEOUT_MS = 6e4;
17915
18028
  var REQUEST_MANAGER_POLL_INTERVAL_MS = 25;
@@ -17922,15 +18035,19 @@ function directRendererInstaller() {
17922
18035
  const retainRendererHostResponses = ${retainRendererHostResponses.toString()};
17923
18036
  const createDraftPrewarmPolicyBridge = ${createDraftPrewarmPolicyBridge.toString()};
17924
18037
  const isolateRendererPrewarmConsumption = ${isolateRendererPrewarmConsumption.toString()};
18038
+ const findRendererAppScopeStore = ${findRendererAppScopeStore.toString()};
18039
+ const readRendererConnectionGeneration = ${readRendererConnectionGeneration.toString()};
17925
18040
  const discover = (root) =>
17926
18041
  discoverRendererHosts(root, committedReactAncestors, requestManagerFromHookState);
17927
- const installNative = () => (${installRendererHostRouting.toString()})(
18042
+ const installNative = (publishRouting = true) => (${installRendererHostRouting.toString()})(
17928
18043
  document, window, discover,
17929
18044
  (discovery, hostId) => resolveRendererHostManager(discovery, hostId, requestManagerFromHookState),
17930
18045
  (manager, bridge, hostId, target, prewarmed, isCurrent) => createDraftPrewarmPolicyBridge(
17931
18046
  manager, bridge, hostId, target, prewarmed, isCurrent, retainRendererHostResponses,
17932
18047
  isolateRendererPrewarmConsumption,
17933
18048
  ),
18049
+ (hostId) => readRendererConnectionGeneration(findRendererAppScopeStore(document), hostId),
18050
+ publishRouting,
17934
18051
  );
17935
18052
  const installRpc = () => typeof MessagePort !== 'function' ? null : (${installRendererHostRpcRouting.toString()})(document, window, {
17936
18053
  findStore: ${findRendererAppScopeStore.toString()},
@@ -17944,24 +18061,35 @@ function directRendererInstaller() {
17944
18061
  return discover(source);
17945
18062
  },
17946
18063
  portPrototype: MessagePort.prototype,
18064
+ nativeRouting: () => {
18065
+ const native = discover(document);
18066
+ return native.managers.length || native.registries.length ? installNative(false) : null;
18067
+ },
18068
+ readConnection: (hostId) => readRendererConnectionGeneration(findRendererAppScopeStore(document), hostId),
17947
18069
  });
17948
- // Desktop 26.1027 moved AppServerManagers to the main process. Older builds
17949
- // expose native managers in Renderer hook state; the main-process mode only
17950
- // applies when none is visible and its per-Host RPC store is identified.
18070
+ const connected = (routing) => routing.forComposer() !== null ||
18071
+ ['local', ...(routing.knownHostIds?.() ?? [])].some((hostId) => routing.forHost(hostId) !== null);
18072
+ let nativeReady = false;
18073
+ // Mixed layouts can expose native managers for only some Hosts. Keep one
18074
+ // router that selects a native owner or the current ready RPC peer per Host.
17951
18075
  const routing = (() => {
17952
18076
  if (window.__codexhostHostRoutingV1) return window.__codexhostHostRoutingV1;
17953
- const native = discover(document);
17954
- if (native.managers.length || native.registries.length) return installNative();
17955
18077
  const rpc = installRpc();
17956
18078
  if (rpc) return rpc;
18079
+ const native = discover(document);
18080
+ if (native.managers.length || native.registries.length) {
18081
+ const routing = installNative();
18082
+ if (connected(routing)) {
18083
+ nativeReady = true;
18084
+ return routing;
18085
+ }
18086
+ routing.dispose();
18087
+ }
17957
18088
  throw new Error('Renderer Host request manager is unavailable');
17958
18089
  })();
17959
18090
  // Publish a default draft policy only when its Host is unambiguous. Host
17960
18091
  // connections can be ready even when multiple Composers coexist.
17961
- const composerRoute = routing.forComposer();
17962
- const connected = composerRoute !== null ||
17963
- ['local', ...(routing.knownHostIds?.() ?? [])].some((hostId) => routing.forHost(hostId) !== null);
17964
- if (!connected) throw new Error('Renderer Host request manager is unavailable');
18092
+ if (!nativeReady && !connected(routing)) throw new Error('Renderer Host request manager is unavailable');
17965
18093
  return { state: 'ready', reason: 'owned-request-bridge' };
17966
18094
  })()`;
17967
18095
  }
@@ -17995,6 +18123,10 @@ function installRendererDraftPrewarmPolicyDirect(renderer) {
17995
18123
  // packages/desktop-control/src/renderer-loaded-modules.ts
17996
18124
  var record2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
17997
18125
  var MAX_MODULES = 4096;
18126
+ var STALE_CONTEXT_ERROR = /uniqueContextId not found|Cannot find context with specified id|Execution context was destroyed|Cannot find default execution context/i;
18127
+ function isStaleContextError(error51) {
18128
+ return error51 instanceof Error && STALE_CONTEXT_ERROR.test(error51.message);
18129
+ }
17998
18130
  function nativeModuleCatalogExpression(urls, complete, owner) {
17999
18131
  return `Object.defineProperty(globalThis, '__codexhostLoadedModulesV1', {
18000
18132
  configurable: true,
@@ -18016,16 +18148,27 @@ async function installRendererLoadedModules(renderer) {
18016
18148
  const pending = [...dirty];
18017
18149
  dirty.clear();
18018
18150
  publishing = publishing.catch(() => void 0).then(async () => {
18151
+ let failure;
18019
18152
  for (const uniqueId of pending) {
18020
18153
  const context = contexts.get(uniqueId);
18021
18154
  if (!context || disposed) continue;
18022
- const response = await renderer.command("Runtime.evaluate", {
18023
- expression: nativeModuleCatalogExpression([...context.urls], context.complete, owner),
18024
- uniqueContextId: uniqueId
18025
- });
18026
- if (record2(response) && record2(response.exceptionDetails))
18027
- throw new Error("Loaded Renderer module catalog publication failed");
18155
+ try {
18156
+ const response = await renderer.command("Runtime.evaluate", {
18157
+ expression: nativeModuleCatalogExpression([...context.urls], context.complete, owner),
18158
+ uniqueContextId: uniqueId
18159
+ });
18160
+ if (record2(response) && record2(response.exceptionDetails))
18161
+ throw new Error("Loaded Renderer module catalog publication failed");
18162
+ } catch (error51) {
18163
+ if (contexts.get(uniqueId) !== context) continue;
18164
+ if (isStaleContextError(error51)) {
18165
+ forget(uniqueId);
18166
+ continue;
18167
+ }
18168
+ failure ??= error51;
18169
+ }
18028
18170
  }
18171
+ if (failure !== void 0) throw failure;
18029
18172
  });
18030
18173
  return publishing;
18031
18174
  };
@@ -18038,13 +18181,15 @@ async function installRendererLoadedModules(renderer) {
18038
18181
  });
18039
18182
  }, 10);
18040
18183
  };
18041
- const remove = (id) => {
18042
- const uniqueId = contextIds.get(id);
18043
- contextIds.delete(id);
18044
- if (uniqueId) {
18045
- contexts.delete(uniqueId);
18046
- dirty.delete(uniqueId);
18047
- }
18184
+ const forget = (uniqueId) => {
18185
+ contexts.delete(uniqueId);
18186
+ dirty.delete(uniqueId);
18187
+ for (const [id, value] of contextIds) if (value === uniqueId) contextIds.delete(id);
18188
+ };
18189
+ const remove = (params) => {
18190
+ const byId = typeof params.executionContextId === "number" ? contextIds.get(params.executionContextId) : void 0;
18191
+ const uniqueId = typeof params.executionContextUniqueId === "string" ? params.executionContextUniqueId : byId;
18192
+ if (uniqueId) forget(uniqueId);
18048
18193
  };
18049
18194
  const listeners = [
18050
18195
  renderer.on("Runtime.executionContextCreated", (params) => {
@@ -18056,8 +18201,7 @@ async function installRendererLoadedModules(renderer) {
18056
18201
  schedule(context.uniqueId);
18057
18202
  }),
18058
18203
  renderer.on("Runtime.executionContextDestroyed", (params) => {
18059
- if (record2(params) && typeof params.executionContextId === "number")
18060
- remove(params.executionContextId);
18204
+ if (record2(params)) remove(params);
18061
18205
  }),
18062
18206
  renderer.on("Runtime.executionContextsCleared", () => {
18063
18207
  contextIds.clear();
@@ -18100,6 +18244,781 @@ async function installRendererLoadedModules(renderer) {
18100
18244
  }
18101
18245
  }
18102
18246
 
18247
+ // packages/desktop-control/src/renderer-native-rpc-discovery.ts
18248
+ function nativeManagerDependencies(factoryName, callers) {
18249
+ const identifier = "[$A-Z_a-z][$\\w]*";
18250
+ const escaped = factoryName.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
18251
+ const pattern = new RegExp(
18252
+ `${escaped}\\((${identifier}),(${identifier}),\\1\\.get\\((${identifier}),\\2\\),(${identifier})\\.bind\\(null,\\1\\),\\((${identifier}),(${identifier})\\)=>\\5\\((${identifier}),\\6\\)\\)`
18253
+ );
18254
+ const matches = callers.flatMap((source) => {
18255
+ const match = pattern.exec(source);
18256
+ return match?.[3] && match[4] && match[7] ? [
18257
+ {
18258
+ requestDefinition: match[3],
18259
+ isHostForConversation: match[4],
18260
+ imageDefinition: match[7]
18261
+ }
18262
+ ] : [];
18263
+ });
18264
+ return matches.length === 1 ? matches[0] : void 0;
18265
+ }
18266
+ function nativeRpcRole(source) {
18267
+ if (["dispatchMessageFromView", "threadProjectAssignments", "queuedMessageCoordination"].every(
18268
+ (part) => source.includes(part)
18269
+ ))
18270
+ return "createManager";
18271
+ if (["collectAppStateSnapshot", "getReviewPaneSnapshotMetrics", "registerReplayAdmission"].every(
18272
+ (part) => source.includes(part)
18273
+ ))
18274
+ return "createController";
18275
+ if (["getWorkInProgress", "getCachedThreadSearchSnapshot", "registerReplayAdmission"].every(
18276
+ (part) => source.includes(part)
18277
+ ))
18278
+ return "RpcManager";
18279
+ if (["prewarmedThreadManager", "onNotification", "dispatchAppServerResponse"].every(
18280
+ (part) => source.includes(part)
18281
+ ))
18282
+ return "Manager";
18283
+ return void 0;
18284
+ }
18285
+ function nativeRpcObjectShape(value) {
18286
+ if (value === null || typeof value !== "object")
18287
+ return { scope: false, services: false, controller: false };
18288
+ const candidate = value;
18289
+ const own = (keys) => keys.every((key) => Object.hasOwn(candidate, key));
18290
+ const methods = (keys) => keys.every((key) => typeof candidate[key] === "function");
18291
+ return {
18292
+ scope: own(["node", "scope", "get", "set", "watch"]) && methods(["get", "set", "watch"]),
18293
+ services: own(["appServerManagers", "remoteConnections", "applicationMenu"]) && typeof candidate.appServerManagers?.subscribe === "function",
18294
+ controller: own(["forHost", "collectAppStateSnapshot", "getReviewPaneSnapshotMetrics", "dispose"]) && methods(["forHost", "collectAppStateSnapshot", "getReviewPaneSnapshotMetrics", "dispose"])
18295
+ };
18296
+ }
18297
+ async function withNativeRpcComponents(client, install) {
18298
+ const group = `codexhost-native-rpc-${crypto.randomUUID()}`;
18299
+ const command = async (method, params) => client.command(method, params);
18300
+ const evaluate = (expression) => command("Runtime.evaluate", { expression, awaitPromise: true, objectGroup: group });
18301
+ const properties = (objectId) => command("Runtime.getProperties", { objectId, ownProperties: true });
18302
+ const call = (objectId, functionDeclaration, args = []) => command("Runtime.callFunctionOn", {
18303
+ objectId,
18304
+ functionDeclaration,
18305
+ arguments: args,
18306
+ objectGroup: group,
18307
+ returnByValue: true
18308
+ });
18309
+ try {
18310
+ const initial = await evaluate(String.raw`(() => {
18311
+ const catalog = globalThis.__codexhostLoadedModulesV1;
18312
+ if (!catalog?.complete || catalog.documentUrl !== location.href) return null;
18313
+ const urls = catalog.urls.filter(url => /^app:\/\/-\/assets\/(?:renderer-app-server-managers|app-shared)-[^/]+\.js$/.test(url));
18314
+ return { document, urls };
18315
+ })()`);
18316
+ if (!initial.result.objectId) return false;
18317
+ const holder = initial.result.objectId;
18318
+ const catalog = await call(holder, "function(){return this.urls}");
18319
+ const urls = catalog.result.value;
18320
+ if (!Array.isArray(urls) || urls.length !== 2) return false;
18321
+ const managerUrl = urls.find((url2) => url2.includes("renderer-app-server-managers"));
18322
+ const sharedUrl = urls.find((url2) => url2.includes("app-shared"));
18323
+ if (!managerUrl || !sharedUrl) return false;
18324
+ const attach = async (name, objectId) => {
18325
+ const result = await call(
18326
+ holder,
18327
+ "function(name,value){if(this.document!==document)throw Error('Renderer Realm changed');this[name]=value;return true}",
18328
+ [{ value: name }, { objectId }]
18329
+ );
18330
+ if (result.exceptionDetails) throw new Error("Native RPC discovery lost its Renderer Realm");
18331
+ };
18332
+ const imported = await evaluate(`import(${JSON.stringify(managerUrl)})`);
18333
+ if (!imported.result.objectId) return false;
18334
+ const exports = (await properties(imported.result.objectId)).result.filter(
18335
+ (entry) => entry.value?.type === "function"
18336
+ );
18337
+ let bindings = [];
18338
+ for (const entry of exports.slice(0, 3)) {
18339
+ if (!entry.value?.objectId) continue;
18340
+ const scopes = (await properties(entry.value.objectId)).internalProperties?.find(
18341
+ (entry2) => entry2.name === "[[Scopes]]"
18342
+ )?.value?.objectId;
18343
+ if (!scopes) continue;
18344
+ const modules = (await properties(scopes)).result.filter(
18345
+ (entry2) => entry2.value?.description?.startsWith("Module") && entry2.value.objectId
18346
+ );
18347
+ const moduleId = modules[0]?.value?.objectId;
18348
+ if (modules.length !== 1 || !moduleId) continue;
18349
+ bindings = (await properties(moduleId)).result;
18350
+ break;
18351
+ }
18352
+ const functions = bindings.filter((entry) => entry.value?.type === "function");
18353
+ const roles = /* @__PURE__ */ new Map();
18354
+ for (const entry of functions) {
18355
+ const role = nativeRpcRole(entry.value?.description ?? "");
18356
+ if (role) roles.set(role, [...roles.get(role) ?? [], entry]);
18357
+ }
18358
+ if (["createManager", "Manager", "RpcManager", "createController"].some(
18359
+ (role) => roles.get(role)?.length !== 1
18360
+ ))
18361
+ return false;
18362
+ const factory = roles.get("createManager")?.[0];
18363
+ if (!factory) return false;
18364
+ const dependencies = nativeManagerDependencies(
18365
+ factory.name,
18366
+ functions.map((entry) => entry.value?.description ?? "")
18367
+ );
18368
+ if (!dependencies) return false;
18369
+ for (const [role, entries] of roles) {
18370
+ const id = entries[0]?.value?.objectId;
18371
+ if (!id) return false;
18372
+ await attach(role, id);
18373
+ }
18374
+ for (const [role, name] of Object.entries(dependencies)) {
18375
+ const value = bindings.find((entry) => entry.name === name)?.value?.objectId;
18376
+ if (!value) return false;
18377
+ await attach(role, value);
18378
+ }
18379
+ const shared = await evaluate(`import(${JSON.stringify(sharedUrl)})`);
18380
+ if (!shared.result.objectId) return false;
18381
+ const sharedExports = (await properties(shared.result.objectId)).result;
18382
+ const sessions = sharedExports.filter(
18383
+ (entry) => entry.value?.type === "function" && ["getRemoteMain", "getStats", "drain", "getMainImport"].every(
18384
+ (word) => entry.value?.description?.includes(word)
18385
+ )
18386
+ );
18387
+ const sessionId = sessions[0]?.value?.objectId;
18388
+ if (sessions.length !== 1 || !sessionId) return false;
18389
+ await attach("RpcSession", sessionId);
18390
+ const serviceMatches = await command("Runtime.callFunctionOn", {
18391
+ objectId: shared.result.objectId,
18392
+ functionDeclaration: `function(){return [...new Set(Object.values(this).filter(value => (${nativeRpcObjectShape.toString()})(value).services))]}`,
18393
+ objectGroup: group
18394
+ });
18395
+ if (!serviceMatches.result.objectId) return false;
18396
+ const services = (await properties(serviceMatches.result.objectId)).result.flatMap(
18397
+ (entry) => entry.value?.type === "object" && entry.value.objectId ? [entry.value.objectId] : []
18398
+ );
18399
+ const serviceId = services[0];
18400
+ if (services.length !== 1 || !serviceId) return false;
18401
+ await attach("services", serviceId);
18402
+ const prototype = await evaluate("Object.getPrototypeOf(async function(){})");
18403
+ if (!prototype.result.objectId) return false;
18404
+ const objects = await command("Runtime.queryObjects", {
18405
+ prototypeObjectId: prototype.result.objectId,
18406
+ objectGroup: group
18407
+ });
18408
+ if (!objects.objects.objectId) return false;
18409
+ const filtered = await command("Runtime.callFunctionOn", {
18410
+ objectId: objects.objects.objectId,
18411
+ functionDeclaration: 'function(){return this.filter(fn=>fn.name==="collectAppStateSnapshot"&&String(fn).includes("collectSnapshot")).slice(0,9)}',
18412
+ objectGroup: group
18413
+ });
18414
+ if (!filtered.result.objectId) return false;
18415
+ const snapshots = (await properties(filtered.result.objectId)).result.filter(
18416
+ (entry) => entry.value?.type === "function"
18417
+ );
18418
+ if (snapshots.length > 8) return false;
18419
+ const owners = [];
18420
+ for (const snapshot of snapshots) {
18421
+ const fn = snapshot.value?.objectId;
18422
+ if (!fn) continue;
18423
+ const scopes = (await properties(fn)).internalProperties?.find(
18424
+ (entry) => entry.name === "[[Scopes]]"
18425
+ )?.value?.objectId;
18426
+ if (!scopes) continue;
18427
+ for (const scope of (await properties(scopes)).result) {
18428
+ if (!scope.value?.description?.startsWith("Closure") || !scope.value.objectId) continue;
18429
+ const candidates = (await properties(scope.value.objectId)).result;
18430
+ const controllers = [], handles = [];
18431
+ for (const binding of candidates) {
18432
+ if (binding.value?.type !== "object" || !binding.value.objectId) continue;
18433
+ const id = binding.value.objectId;
18434
+ const response = await call(
18435
+ id,
18436
+ `function(){return (${nativeRpcObjectShape.toString()})(this)}`
18437
+ );
18438
+ const shape = response.result.value;
18439
+ if (shape?.scope) handles.push(id);
18440
+ if (shape?.controller && (await call(id, "function(fn){return this.collectAppStateSnapshot===fn}", [
18441
+ { objectId: fn }
18442
+ ])).result.value === true)
18443
+ controllers.push(id);
18444
+ }
18445
+ const controller = controllers[0], handle = handles[0];
18446
+ if (controllers.length === 1 && handles.length === 1 && controller && handle)
18447
+ owners.push({ controller, scope: handle });
18448
+ }
18449
+ }
18450
+ const owner = owners[0];
18451
+ if (owners.length !== 1 || !owner) return false;
18452
+ await attach("controller", owner.controller);
18453
+ await attach("scope", owner.scope);
18454
+ return await install(holder);
18455
+ } finally {
18456
+ await client.command("Runtime.releaseObjectGroup", { objectGroup: group }).catch(() => void 0);
18457
+ }
18458
+ }
18459
+
18460
+ // packages/desktop-control/src/renderer-native-rpc-runtime.ts
18461
+ function installNativeRpcRemoteControl(components, target, dependencies) {
18462
+ if (target.__codexhostNativeRpcRemoteControlV1) return true;
18463
+ const routing = target.__codexhostHostRoutingV1;
18464
+ if (!routing) return false;
18465
+ const adapted = dependencies.createService(
18466
+ components,
18467
+ (hostId2, upstream) => dependencies.createManager(
18468
+ components,
18469
+ hostId2,
18470
+ upstream,
18471
+ target,
18472
+ dependencies.createPolicy,
18473
+ dependencies.createChannel,
18474
+ dependencies.retainInteractions
18475
+ )
18476
+ );
18477
+ const controller = components.controller;
18478
+ const originalHost = routing.forHost, originalComposer = routing.forComposer, originalDispose = routing.dispose;
18479
+ controller.dispose();
18480
+ let replacement;
18481
+ try {
18482
+ replacement = components.createController(components.scope, adapted.service);
18483
+ } catch (error51) {
18484
+ replacement = components.createController(
18485
+ components.scope,
18486
+ components.services.appServerManagers
18487
+ );
18488
+ throw error51;
18489
+ } finally {
18490
+ adapted.service[Symbol.dispose]();
18491
+ controller.forHost = (hostId2) => replacement.forHost(hostId2);
18492
+ controller.collectAppStateSnapshot = (hostId2, options) => replacement.collectAppStateSnapshot(hostId2, options);
18493
+ controller.getReviewPaneSnapshotMetrics = (hostId2) => replacement.getReviewPaneSnapshotMetrics(hostId2);
18494
+ controller.dispose = () => replacement.dispose();
18495
+ }
18496
+ const forHost = (hostId2) => {
18497
+ const route = adapted.route(hostId2);
18498
+ return route === void 0 ? originalHost.call(routing, hostId2) : route;
18499
+ };
18500
+ const forComposer = (composer) => {
18501
+ const hostId2 = routing.hostIdForComposer(composer);
18502
+ return hostId2 ? forHost(hostId2) : originalComposer.call(routing, composer);
18503
+ };
18504
+ routing.forHost = forHost;
18505
+ routing.forComposer = forComposer;
18506
+ const installation = {
18507
+ dispose() {
18508
+ if (target.__codexhostNativeRpcRemoteControlV1 !== installation) return;
18509
+ delete target.__codexhostNativeRpcRemoteControlV1;
18510
+ replacement.dispose();
18511
+ replacement = components.createController(
18512
+ components.scope,
18513
+ components.services.appServerManagers
18514
+ );
18515
+ if (routing.forHost === forHost) routing.forHost = originalHost;
18516
+ if (routing.forComposer === forComposer) routing.forComposer = originalComposer;
18517
+ routing.dispose = originalDispose;
18518
+ }
18519
+ };
18520
+ routing.dispose = () => {
18521
+ installation.dispose();
18522
+ originalDispose.call(routing);
18523
+ };
18524
+ target.__codexhostNativeRpcRemoteControlV1 = installation;
18525
+ return true;
18526
+ }
18527
+
18528
+ // packages/desktop-control/src/renderer-native-remote-manager.ts
18529
+ function createNativeRemoteManager(components, hostId2, original, target, createPolicy, createChannel, retainInteractions) {
18530
+ const source = components.scope.get(components.requestDefinition, hostId2);
18531
+ const upstream = original.dup();
18532
+ let manager;
18533
+ let policy;
18534
+ let interactions;
18535
+ let disposed = false;
18536
+ const pending = /* @__PURE__ */ new Set();
18537
+ const send = (method, params, options) => {
18538
+ const request = upstream.sendRequest(method, params, options);
18539
+ const result = Promise.resolve(request).finally(() => {
18540
+ request[Symbol.dispose]();
18541
+ pending.delete(result);
18542
+ });
18543
+ pending.add(result);
18544
+ return result;
18545
+ };
18546
+ const record3 = (value) => value !== null && typeof value === "object";
18547
+ const dispatch = (type, payload) => {
18548
+ if ((type === "mcp-request" || type === "thread-prewarm-start") && record3(payload) && record3(payload.request)) {
18549
+ const request = payload.request;
18550
+ const options = {};
18551
+ for (const key of ["priority", "timeoutMs", "source", "trace", "threadAccess"])
18552
+ if (payload[key] !== void 0) options[key] = payload[key];
18553
+ void send(String(request.method), request.params, options).then(
18554
+ (result) => {
18555
+ if (!disposed) client.onResult(request.id, result);
18556
+ },
18557
+ (error51) => {
18558
+ if (!disposed)
18559
+ client.onError(request.id, {
18560
+ code: record3(error51) ? error51.jsonRpcCode ?? error51.code ?? -32603 : -32603,
18561
+ message: error51 instanceof Error ? error51.message : String(error51)
18562
+ });
18563
+ }
18564
+ );
18565
+ return;
18566
+ }
18567
+ return source.dispatchMessage(type, payload);
18568
+ };
18569
+ const Constructor = source.constructor;
18570
+ let client;
18571
+ try {
18572
+ client = new Constructor(
18573
+ hostId2,
18574
+ dispatch,
18575
+ false,
18576
+ (id) => manager?.getConversation(id)?.threadAccess
18577
+ );
18578
+ client.setAppServerVersion(source.getAppServerVersion());
18579
+ manager = components.createManager(
18580
+ components.scope,
18581
+ hostId2,
18582
+ client,
18583
+ components.isHostForConversation.bind(null, components.scope),
18584
+ (get, id) => get(components.imageDefinition, id),
18585
+ { dispatchMessageFromView: dispatch }
18586
+ );
18587
+ manager.dispatchAppServerResponse = manager.sendAppServerResponse;
18588
+ const owned = manager;
18589
+ const ownedPolicy = createPolicy(
18590
+ owned,
18591
+ client,
18592
+ hostId2,
18593
+ target,
18594
+ owned.prewarmedThreadManager,
18595
+ () => !disposed,
18596
+ void 0,
18597
+ void 0,
18598
+ (method, params) => send(method, params, { priority: "critical" })
18599
+ );
18600
+ policy = ownedPolicy;
18601
+ owned.sendAppServerResponse = (...args) => owned.dispatchAppServerResponse(...args);
18602
+ const channel = createChannel(components, owned);
18603
+ const nativeInteractions = retainInteractions(upstream, owned, hostId2);
18604
+ interactions = nativeInteractions;
18605
+ const notify = (event) => {
18606
+ const { data, source: source2, origin } = event;
18607
+ if (disposed || source2 != null && source2 !== target || !record3(data) || data.hostId !== hostId2)
18608
+ return;
18609
+ const ownOrigin = record3(target.location) ? target.location.origin : void 0;
18610
+ if (source2 === target && ownOrigin && ownOrigin !== "null" && origin !== ownOrigin) return;
18611
+ if (data.type === "mcp-notification" && typeof data.method === "string" && !data.method.startsWith("process/"))
18612
+ owned.onNotification(data.method, data.params);
18613
+ if (data.type === "mcp-request") owned.onRequest(record3(data.request) ? data.request : data);
18614
+ };
18615
+ target.addEventListener?.("message", notify);
18616
+ return {
18617
+ route: { hostId: hostId2, manager: owned, policy: ownedPolicy },
18618
+ rpc: channel.rpc,
18619
+ ready: nativeInteractions.ready,
18620
+ dispose() {
18621
+ if (disposed) return;
18622
+ disposed = true;
18623
+ target.removeEventListener?.("message", notify);
18624
+ nativeInteractions.dispose();
18625
+ ownedPolicy.dispose();
18626
+ client.queuedRequests.length = 0;
18627
+ for (const id of [...client.requestPromises.keys()])
18628
+ client.onError(id, new Error("Remote Control connection retired"));
18629
+ channel.dispose();
18630
+ components.Manager.dispose(owned);
18631
+ void Promise.allSettled([...pending]).then(() => upstream[Symbol.dispose]());
18632
+ }
18633
+ };
18634
+ } catch (error51) {
18635
+ interactions?.dispose();
18636
+ policy?.dispose();
18637
+ if (manager) components.Manager.dispose(manager);
18638
+ upstream[Symbol.dispose]();
18639
+ throw error51;
18640
+ }
18641
+ }
18642
+
18643
+ // packages/desktop-control/src/renderer-native-rpc-channel.ts
18644
+ function createNativeRpcChannel(components, manager) {
18645
+ const channel = new MessageChannel();
18646
+ const transports = [];
18647
+ const transport = (port) => {
18648
+ const values = [];
18649
+ const readers = [];
18650
+ let closed = false;
18651
+ let failure;
18652
+ port.addEventListener("message", (event) => {
18653
+ const value = JSON.stringify(event.data);
18654
+ const reader = readers.shift();
18655
+ if (reader) reader.resolve(value);
18656
+ else values.push(value);
18657
+ });
18658
+ port.start();
18659
+ const result = {
18660
+ send(message) {
18661
+ if (closed) throw failure;
18662
+ port.postMessage(JSON.parse(message));
18663
+ },
18664
+ receive() {
18665
+ if (closed) return Promise.reject(failure);
18666
+ const value = values.shift();
18667
+ return value !== void 0 ? Promise.resolve(value) : new Promise((resolve, reject) => readers.push({ resolve, reject }));
18668
+ },
18669
+ abort(error51) {
18670
+ if (closed) return;
18671
+ closed = true;
18672
+ failure = error51 ?? new Error("Remote Control RPC manager retired");
18673
+ values.length = 0;
18674
+ for (const reader of readers.splice(0)) reader.reject(failure);
18675
+ port.close();
18676
+ }
18677
+ };
18678
+ transports.push(result);
18679
+ return result;
18680
+ };
18681
+ try {
18682
+ new components.RpcSession(transport(channel.port1), new components.RpcManager(() => manager));
18683
+ const session = new components.RpcSession(transport(channel.port2));
18684
+ const rpc = session.getRemoteMain();
18685
+ return {
18686
+ rpc,
18687
+ dispose() {
18688
+ rpc[Symbol.dispose]();
18689
+ for (const transport2 of transports) transport2.abort();
18690
+ }
18691
+ };
18692
+ } catch (error51) {
18693
+ for (const transport2 of transports) transport2.abort(error51);
18694
+ channel.port1.close();
18695
+ channel.port2.close();
18696
+ throw error51;
18697
+ }
18698
+ }
18699
+
18700
+ // packages/desktop-control/src/renderer-native-rpc-service.ts
18701
+ function createNativeRpcService(components, createRemote) {
18702
+ const source = components.services.appServerManagers.dup();
18703
+ const routes = /* @__PURE__ */ new Map();
18704
+ const subscriptions = /* @__PURE__ */ new Set();
18705
+ let refs = 1;
18706
+ const record3 = (value) => value !== null && typeof value === "object";
18707
+ const connectionSignals = (hostId2) => {
18708
+ let node = components.scope.node;
18709
+ const seen = /* @__PURE__ */ new Set();
18710
+ while (node.parent && !seen.has(node.parent) && seen.size < 100) {
18711
+ seen.add(node);
18712
+ node = node.parent;
18713
+ }
18714
+ const found = [];
18715
+ for (const members of node.familyBindings.values()) {
18716
+ const value = members.get(hostId2)?.value;
18717
+ if (record3(value) && Object.hasOwn(value, "state$") && Object.hasOwn(value, "revision$") && Object.hasOwn(value, "appServerVersion$"))
18718
+ found.push({ state$: value.state$, revision$: value.revision$ });
18719
+ }
18720
+ return found.length === 1 ? found[0] : void 0;
18721
+ };
18722
+ const service = {
18723
+ dup() {
18724
+ refs++;
18725
+ return service;
18726
+ },
18727
+ onRpcBroken(listener) {
18728
+ source.onRpcBroken(listener);
18729
+ },
18730
+ openAccount(hostId2) {
18731
+ return source.openAccount(hostId2);
18732
+ },
18733
+ subscribe(hostId2, listener) {
18734
+ if (!hostId2.startsWith("remote-control:")) return source.subscribe(hostId2, listener);
18735
+ let active = true;
18736
+ let generation = 0;
18737
+ let upstream;
18738
+ let platformRequest;
18739
+ let remote;
18740
+ let stopWatch;
18741
+ let previousRevision;
18742
+ let previousState;
18743
+ const retire = () => {
18744
+ generation++;
18745
+ platformRequest?.[Symbol.dispose]();
18746
+ platformRequest = void 0;
18747
+ remote?.dispose();
18748
+ remote = void 0;
18749
+ routes.set(hostId2, null);
18750
+ };
18751
+ const cleanup = () => {
18752
+ if (!active) return;
18753
+ active = false;
18754
+ stopWatch?.();
18755
+ retire();
18756
+ upstream?.[Symbol.dispose]();
18757
+ upstream = void 0;
18758
+ routes.delete(hostId2);
18759
+ subscriptions.delete(cleanup);
18760
+ };
18761
+ subscriptions.add(cleanup);
18762
+ const publish = async () => {
18763
+ const owner = upstream;
18764
+ const current = generation;
18765
+ if (!owner || !active) return;
18766
+ let request;
18767
+ try {
18768
+ request = owner.getCodexHome();
18769
+ platformRequest = request;
18770
+ const home = await request;
18771
+ if (!active || current !== generation || owner !== upstream) return;
18772
+ if (!/^(?:[A-Za-z]:[\\/]|\\\\)/u.test(home)) {
18773
+ routes.delete(hostId2);
18774
+ listener({ status: "ready", manager: owner });
18775
+ return;
18776
+ }
18777
+ const created = createRemote(hostId2, owner);
18778
+ remote = created;
18779
+ await created.ready;
18780
+ if (!active || current !== generation || owner !== upstream) return;
18781
+ routes.set(hostId2, created.route);
18782
+ listener({ status: "ready", manager: created.rpc });
18783
+ } catch {
18784
+ if (active && current === generation) {
18785
+ remote?.dispose();
18786
+ remote = void 0;
18787
+ routes.delete(hostId2);
18788
+ listener({ status: "ready", manager: owner });
18789
+ }
18790
+ } finally {
18791
+ if (platformRequest === request) {
18792
+ platformRequest = void 0;
18793
+ request?.[Symbol.dispose]();
18794
+ }
18795
+ }
18796
+ };
18797
+ const changed = (state) => {
18798
+ if (!active) return;
18799
+ stopWatch?.();
18800
+ stopWatch = void 0;
18801
+ retire();
18802
+ upstream?.[Symbol.dispose]();
18803
+ upstream = void 0;
18804
+ if (state.status !== "ready") {
18805
+ listener(state);
18806
+ return;
18807
+ }
18808
+ upstream = state.manager.dup();
18809
+ listener({ status: "connecting" });
18810
+ const signals = connectionSignals(hostId2);
18811
+ if (!signals) {
18812
+ void publish();
18813
+ return;
18814
+ }
18815
+ previousState = void 0;
18816
+ previousRevision = void 0;
18817
+ stopWatch = components.scope.watch(({ get }) => {
18818
+ const connection = get(signals.state$), revision = get(signals.revision$);
18819
+ if (connection === previousState && revision === previousRevision) return;
18820
+ previousState = connection;
18821
+ previousRevision = revision;
18822
+ retire();
18823
+ listener({ status: connection === "connected" ? "connecting" : "disconnected" });
18824
+ if (connection === "connected") void publish();
18825
+ });
18826
+ };
18827
+ const original = source.subscribe(hostId2, changed);
18828
+ const result = original.then((lease) => {
18829
+ if (!active) lease[Symbol.dispose]();
18830
+ return {
18831
+ onRpcBroken: (listener2) => lease.onRpcBroken(listener2),
18832
+ [Symbol.dispose]() {
18833
+ cleanup();
18834
+ lease[Symbol.dispose]();
18835
+ }
18836
+ };
18837
+ });
18838
+ Object.assign(result, {
18839
+ onRpcBroken: (listener2) => original.onRpcBroken(listener2),
18840
+ [Symbol.dispose]() {
18841
+ cleanup();
18842
+ original[Symbol.dispose]();
18843
+ }
18844
+ });
18845
+ return result;
18846
+ },
18847
+ [Symbol.dispose]() {
18848
+ if (--refs !== 0) return;
18849
+ for (const cleanup of [...subscriptions]) cleanup();
18850
+ source[Symbol.dispose]();
18851
+ }
18852
+ };
18853
+ return { service, route: (hostId2) => routes.get(hostId2) };
18854
+ }
18855
+
18856
+ // packages/desktop-control/src/renderer-native-rpc-interactions.ts
18857
+ function retainNativeRpcInteractions(upstream, manager, hostId2) {
18858
+ let disposed = false;
18859
+ const retained = /* @__PURE__ */ new Set();
18860
+ const requests = /* @__PURE__ */ new Map();
18861
+ const reads = /* @__PURE__ */ new Map();
18862
+ const record3 = (value) => value !== null && typeof value === "object";
18863
+ const read = (threadId) => {
18864
+ const existing = reads.get(threadId);
18865
+ if (existing) {
18866
+ existing.dirty = true;
18867
+ return existing.promise;
18868
+ }
18869
+ const entry = { promise: Promise.resolve(), dirty: false };
18870
+ reads.set(threadId, entry);
18871
+ entry.promise = Promise.resolve().then(async () => {
18872
+ do {
18873
+ if (disposed) break;
18874
+ entry.dirty = false;
18875
+ const pending = upstream.getConversation(threadId);
18876
+ retained.add(pending);
18877
+ try {
18878
+ const conversation = await pending;
18879
+ if (disposed || entry.dirty || !record3(conversation) || !Array.isArray(conversation.requests))
18880
+ continue;
18881
+ const previous = requests.get(threadId) ?? /* @__PURE__ */ new Set();
18882
+ const next = /* @__PURE__ */ new Set();
18883
+ for (const request of conversation.requests) {
18884
+ if (!record3(request) || typeof request.method !== "string" || !record3(request.params) || (request.params.threadId ?? request.params.conversationId) !== threadId || typeof request.id !== "string" && typeof request.id !== "number")
18885
+ continue;
18886
+ next.add(request.id);
18887
+ if (!previous.has(request.id)) manager.onRequest(request);
18888
+ }
18889
+ if (next.size) requests.set(threadId, next);
18890
+ else requests.delete(threadId);
18891
+ } finally {
18892
+ if (retained.delete(pending)) pending[Symbol.dispose]();
18893
+ }
18894
+ } while (!disposed && entry.dirty);
18895
+ }).finally(() => {
18896
+ reads.delete(threadId);
18897
+ });
18898
+ return entry.promise;
18899
+ };
18900
+ const event = (value) => {
18901
+ if (disposed || !record3(value) || typeof value.conversationId !== "string") return;
18902
+ void read(value.conversationId).catch(() => void 0);
18903
+ };
18904
+ const subscribe = (input) => {
18905
+ const pending = upstream.subscribe(input);
18906
+ retained.add(pending);
18907
+ return Promise.resolve(pending).then((lease) => {
18908
+ if (disposed) lease[Symbol.dispose]();
18909
+ else retained.add(lease);
18910
+ });
18911
+ };
18912
+ const subscriptions = [
18913
+ "approval-request",
18914
+ "user-input-request",
18915
+ "mcp-elicitation-request",
18916
+ "approval-resolved"
18917
+ ].map((name) => subscribe({ type: "event", key: { hostId: hostId2 }, event: name, listener: event }));
18918
+ subscriptions.push(
18919
+ subscribe({
18920
+ type: "notification",
18921
+ key: { hostId: hostId2 },
18922
+ methods: ["serverRequest/resolved"],
18923
+ listener(value) {
18924
+ if (record3(value) && record3(value.params) && typeof value.params.threadId === "string")
18925
+ event({ conversationId: value.params.threadId });
18926
+ }
18927
+ })
18928
+ );
18929
+ const ready = Promise.all(subscriptions).then(async () => {
18930
+ if (disposed) return;
18931
+ const pending = upstream.getWorkInProgress();
18932
+ retained.add(pending);
18933
+ try {
18934
+ const work = await pending;
18935
+ if (disposed) return;
18936
+ if (!Array.isArray(work)) throw new Error("Native RPC interaction snapshot is unavailable");
18937
+ const threadIds = new Set(
18938
+ work.flatMap(
18939
+ (item) => record3(item) && typeof item.conversationId === "string" ? [item.conversationId] : []
18940
+ )
18941
+ );
18942
+ await Promise.all([...threadIds].map(read));
18943
+ } finally {
18944
+ if (retained.delete(pending)) pending[Symbol.dispose]();
18945
+ }
18946
+ });
18947
+ return {
18948
+ ready,
18949
+ dispose() {
18950
+ if (disposed) return;
18951
+ disposed = true;
18952
+ for (const lease of retained) lease[Symbol.dispose]();
18953
+ retained.clear();
18954
+ requests.clear();
18955
+ }
18956
+ };
18957
+ }
18958
+
18959
+ // packages/desktop-control/src/renderer-native-rpc-install.ts
18960
+ async function installNativeRpcRemoteControlDirect(renderer) {
18961
+ let attempt;
18962
+ const probeId = crypto.randomUUID();
18963
+ try {
18964
+ attempt = await renderer.evaluate(`(() => {
18965
+ if (window.__codexhostNativeRpcRemoteControlV1) return null;
18966
+ const routing = window.__codexhostHostRoutingV1;
18967
+ const owner = routing?.forHost('local')?.manager;
18968
+ if (owner?.kind !== 'main-process-rpc') return null;
18969
+ const catalog = window.__codexhostLoadedModulesV1;
18970
+ if (!catalog?.complete) return null;
18971
+ const key = JSON.stringify([catalog.owner, catalog.urls.filter(url => /renderer-app-server-managers|app-shared/.test(url)).sort()]);
18972
+ const previous = window.__codexhostNativeRpcDiscoveryV1;
18973
+ const sameOwner = previous?.key === key && previous.owner === owner;
18974
+ if (sameOwner && (previous.state !== 'unavailable' || previous.attempts >= 3 || Date.now() < previous.nextRetryAt)) return null;
18975
+ const token = ${JSON.stringify(probeId)};
18976
+ window.__codexhostNativeRpcDiscoveryV1 = {
18977
+ key, owner, token, state: 'discovering', attempts: sameOwner ? previous.attempts + 1 : 1,
18978
+ };
18979
+ return token;
18980
+ })()`);
18981
+ } catch {
18982
+ return false;
18983
+ }
18984
+ if (attempt === null) return false;
18985
+ let installed = false;
18986
+ try {
18987
+ installed = await withNativeRpcComponents(renderer, async (objectId) => {
18988
+ const result = await renderer.command("Runtime.callFunctionOn", {
18989
+ objectId,
18990
+ functionDeclaration: `function() {
18991
+ if (this.document !== document) return false;
18992
+ const retainRendererHostResponses = ${retainRendererHostResponses.toString()};
18993
+ const isolateRendererPrewarmConsumption = ${isolateRendererPrewarmConsumption.toString()};
18994
+ return (${installNativeRpcRemoteControl.toString()})(this, window, {
18995
+ createPolicy: ${createDraftPrewarmPolicyBridge.toString()},
18996
+ createManager: ${createNativeRemoteManager.toString()},
18997
+ createChannel: ${createNativeRpcChannel.toString()},
18998
+ createService: ${createNativeRpcService.toString()},
18999
+ retainInteractions: ${retainNativeRpcInteractions.toString()},
19000
+ });
19001
+ }`,
19002
+ returnByValue: true
19003
+ });
19004
+ return !result.exceptionDetails && result.result?.value === true;
19005
+ });
19006
+ return installed;
19007
+ } catch {
19008
+ return false;
19009
+ } finally {
19010
+ await renderer.evaluate(
19011
+ `(() => {
19012
+ const status = window.__codexhostNativeRpcDiscoveryV1;
19013
+ if (status?.token === ${JSON.stringify(attempt)}) {
19014
+ status.state = ${JSON.stringify(installed ? "ready" : "unavailable")};
19015
+ status.nextRetryAt = Date.now() + 5000 * 2 ** (status.attempts - 1);
19016
+ }
19017
+ })()`
19018
+ ).catch(() => void 0);
19019
+ }
19020
+ }
19021
+
18103
19022
  // packages/desktop-control/src/renderer-cdp-control-session.ts
18104
19023
  function isRecord2(value) {
18105
19024
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -18357,7 +19276,11 @@ var InstalledRendererCdpControlSession = class {
18357
19276
  var defaultOperations = {
18358
19277
  listTargets: (endpoint, signal) => listCdpTargets(endpoint, fetch, signal),
18359
19278
  connect: (webSocketDebuggerUrl) => CdpClient.connect(webSocketDebuggerUrl),
18360
- installDraftPrewarmPolicy: installRendererDraftPrewarmPolicyDirect
19279
+ async installDraftPrewarmPolicy(renderer) {
19280
+ const status = await installRendererDraftPrewarmPolicyDirect(renderer);
19281
+ await installNativeRpcRemoteControlDirect(renderer);
19282
+ return status;
19283
+ }
18361
19284
  };
18362
19285
  async function createRendererCdpControlSession(options) {
18363
19286
  const enabledAgents = options.enabledAgents;