@codexhost/cli-darwin-arm64 0.17.0 → 0.17.2

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.
@@ -15780,6 +15780,21 @@ var threadSteeringInspectParamsSchema = external_exports.object({
15780
15780
  /** The text about to be steered; a Harness command always stops and restarts. */
15781
15781
  text: external_exports.string().optional()
15782
15782
  }).strict();
15783
+ var threadSteeringContextSchema = external_exports.object({
15784
+ kind: external_exports.literal("application"),
15785
+ value: external_exports.string().transform((text, context) => {
15786
+ try {
15787
+ return JSON.parse(text);
15788
+ } catch {
15789
+ context.addIssue({ code: "custom", message: "Invalid steering context JSON" });
15790
+ return external_exports.NEVER;
15791
+ }
15792
+ }).pipe(external_exports.object({
15793
+ expectedTurnId: hostTurnIdSchema,
15794
+ clientUserMessageId: external_exports.string().min(1),
15795
+ delivery: external_exports.enum(["newTurn", "activeTurn"])
15796
+ }).strict())
15797
+ }).strict().transform((context) => context.value);
15783
15798
  var threadSteerDeliverySchema = external_exports.enum(["activeTurn", "newTurn"]);
15784
15799
  var threadSteeringInspectResultSchema = external_exports.object({
15785
15800
  delivery: external_exports.enum(["official", "activeTurn", "newTurn"])
@@ -16818,9 +16833,10 @@ function isolateRendererPrewarmConsumption(manager, discardExternal) {
16818
16833
  }
16819
16834
 
16820
16835
  // packages/desktop-control/src/renderer-draft-prewarm-runtime.ts
16821
- function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewarmedThreadManager, isCurrentManager, retainResponses = retainRendererHostResponses, isolateConsumption = isolateRendererPrewarmConsumption) {
16836
+ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewarmedThreadManager, isCurrentManager, retainResponses = retainRendererHostResponses, isolateConsumption = isolateRendererPrewarmConsumption, sendControlRequest) {
16822
16837
  let disposed = false;
16823
16838
  const originalSend = bridge.sendRequest;
16839
+ const controlSend = (method, parameters) => sendControlRequest ? sendControlRequest(method, parameters) : originalSend.call(bridge, method, parameters);
16824
16840
  const originalPrewarm = bridge.prewarmThreadStart;
16825
16841
  const originalOnNotification = manager.onNotification;
16826
16842
  const originalDispatchAppServerResponse = manager.dispatchAppServerResponse;
@@ -16904,7 +16920,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
16904
16920
  bridgeRequests.clear();
16905
16921
  if (isRemoteControlHost && terminate) {
16906
16922
  void Promise.resolve(
16907
- originalSend.call(bridge, "process/kill", { processHandle: failedProcessHandle })
16923
+ controlSend("process/kill", { processHandle: failedProcessHandle })
16908
16924
  ).catch(() => void 0);
16909
16925
  }
16910
16926
  };
@@ -17067,7 +17083,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
17067
17083
  ];
17068
17084
  const startedProcessHandle = bridgeProcessHandle;
17069
17085
  try {
17070
- const started = originalSend.call(bridge, "process/spawn", {
17086
+ const started = controlSend("process/spawn", {
17071
17087
  command,
17072
17088
  processHandle: startedProcessHandle,
17073
17089
  cwd: "C:\\",
@@ -17088,7 +17104,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
17088
17104
  const operation = async () => {
17089
17105
  await startBridge();
17090
17106
  if (bridgeState !== "ready") throw transportError("is not ready");
17091
- await originalSend.call(bridge, "process/writeStdin", {
17107
+ await controlSend("process/writeStdin", {
17092
17108
  processHandle: bridgeProcessHandle,
17093
17109
  deltaBase64: utf8Base64(`${JSON.stringify(value)}
17094
17110
  `)
@@ -17363,7 +17379,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
17363
17379
  bridgeReadyTimeout = null;
17364
17380
  if (isRemoteControlHost && (bridgeState === "starting" || bridgeState === "ready")) {
17365
17381
  void Promise.resolve(
17366
- originalSend.call(bridge, "process/kill", { processHandle: bridgeProcessHandle })
17382
+ controlSend("process/kill", { processHandle: bridgeProcessHandle })
17367
17383
  ).catch(() => void 0);
17368
17384
  }
17369
17385
  bridgeState = "disposed";
@@ -17465,10 +17481,11 @@ function resolveRendererHostManager(discovery, hostId2, managerFrom = requestMan
17465
17481
  }
17466
17482
 
17467
17483
  // packages/desktop-control/src/renderer-host-routing.ts
17468
- function installRendererHostRouting(root, target, discover, resolve, createPolicy) {
17484
+ function installRendererHostRouting(root, target, discover, resolve, createPolicy, readConnection, publishRouting = true) {
17469
17485
  const existing = target.__codexhostHostRoutingV1;
17470
- if (existing) return existing;
17471
- target.__codexhostDraftPrewarmPolicyV1?.dispose?.();
17486
+ if (publishRouting && existing) return existing;
17487
+ if (publishRouting)
17488
+ target.__codexhostDraftPrewarmPolicyV1?.dispose?.();
17472
17489
  let disposed = false;
17473
17490
  let lastDiscovery = null;
17474
17491
  const routes = /* @__PURE__ */ new Map();
@@ -17495,10 +17512,20 @@ function installRendererHostRouting(root, target, discover, resolve, createPolic
17495
17512
  routes.delete(hostId2);
17496
17513
  entry?.route.policy.dispose();
17497
17514
  };
17515
+ const connectionFor = (hostId2) => {
17516
+ if (!hostId2.startsWith("remote-control:")) return void 0;
17517
+ try {
17518
+ return readConnection?.(hostId2);
17519
+ } catch {
17520
+ return null;
17521
+ }
17522
+ };
17523
+ const sameConnection = (expected, current) => expected === void 0 ? current === void 0 : current?.owner === expected.owner && current.revision === expected.revision;
17498
17524
  const routeFor = (hostId2, discovery) => {
17499
17525
  const manager = lookup(hostId2, discovery);
17526
+ const connection = connectionFor(hostId2);
17500
17527
  const previous = routes.get(hostId2);
17501
- if (manager && previous?.route.manager === manager && previous.bridge === manager.requestClient && previous.prewarmed === manager.prewarmedThreadManager && previous.route.policy.owns(
17528
+ if (manager && previous?.route.manager === manager && previous.bridge === manager.requestClient && previous.prewarmed === manager.prewarmedThreadManager && sameConnection(previous.connection, connection) && previous.route.policy.owns(
17502
17529
  manager,
17503
17530
  manager.requestClient,
17504
17531
  hostId2,
@@ -17508,7 +17535,7 @@ function installRendererHostRouting(root, target, discover, resolve, createPolic
17508
17535
  return previous.route;
17509
17536
  }
17510
17537
  retire(hostId2);
17511
- if (!manager) return null;
17538
+ if (!manager || connection === null) return null;
17512
17539
  const bridge = manager.requestClient;
17513
17540
  const prewarmed = manager.prewarmedThreadManager;
17514
17541
  const policy = createPolicy(
@@ -17517,13 +17544,14 @@ function installRendererHostRouting(root, target, discover, resolve, createPolic
17517
17544
  hostId2,
17518
17545
  target,
17519
17546
  prewarmed,
17520
- () => lookup(hostId2) === manager && manager.requestClient === bridge && manager.prewarmedThreadManager === prewarmed
17547
+ () => lookup(hostId2) === manager && sameConnection(connection, connectionFor(hostId2)) && manager.requestClient === bridge && manager.prewarmedThreadManager === prewarmed
17521
17548
  );
17522
17549
  const route = { hostId: hostId2, manager, policy };
17523
- routes.set(hostId2, { route, bridge, prewarmed });
17550
+ routes.set(hostId2, { route, bridge, prewarmed, connection });
17524
17551
  return route;
17525
17552
  };
17526
17553
  const publish = (route) => {
17554
+ if (!publishRouting) return;
17527
17555
  const policy = route?.policy;
17528
17556
  if (target.__codexhostDraftPrewarmPolicyV1 === policy) return;
17529
17557
  Object.defineProperty(target, "__codexhostDraftPrewarmPolicyV1", {
@@ -17576,7 +17604,7 @@ function installRendererHostRouting(root, target, discover, resolve, createPolic
17576
17604
  if (!composer) {
17577
17605
  for (const [hostId3, entry] of routes) {
17578
17606
  const manager = lookup(hostId3, discovery);
17579
- if (manager !== entry.route.manager || manager.requestClient !== entry.bridge || manager.prewarmedThreadManager !== entry.prewarmed)
17607
+ if (manager !== entry.route.manager || manager.requestClient !== entry.bridge || manager.prewarmedThreadManager !== entry.prewarmed || !sameConnection(entry.connection, connectionFor(hostId3)))
17580
17608
  retire(hostId3);
17581
17609
  }
17582
17610
  }
@@ -17596,7 +17624,11 @@ function installRendererHostRouting(root, target, discover, resolve, createPolic
17596
17624
  }
17597
17625
  }
17598
17626
  };
17599
- Object.defineProperty(target, "__codexhostHostRoutingV1", { configurable: true, value: routing });
17627
+ if (publishRouting)
17628
+ Object.defineProperty(target, "__codexhostHostRoutingV1", {
17629
+ configurable: true,
17630
+ value: routing
17631
+ });
17600
17632
  return routing;
17601
17633
  }
17602
17634
 
@@ -17646,7 +17678,8 @@ function findRendererHostRpcFamily(store) {
17646
17678
  if (!record3(definition) || definition.kind !== "signal-family") continue;
17647
17679
  if (!record3(members) || typeof members.get !== "function") continue;
17648
17680
  for (const [hostId2, member] of members) {
17649
- if (typeof hostId2 !== "string" || !record3(member)) continue;
17681
+ if (typeof hostId2 !== "string" || !/^(?:local$|durable$|remote[-:])/u.test(hostId2)) continue;
17682
+ if (!record3(member)) continue;
17650
17683
  const signal = member.value;
17651
17684
  if (!record3(signal) || typeof signal.get !== "function") continue;
17652
17685
  let value;
@@ -17690,17 +17723,38 @@ function installRendererHostRpcRouting(root, target, dependencies) {
17690
17723
  const existing = target.__codexhostHostRoutingV1;
17691
17724
  if (existing) return existing;
17692
17725
  let disposed = false;
17726
+ let nativeRouting = null;
17693
17727
  let discovery = null;
17694
17728
  const routes = /* @__PURE__ */ new Map();
17695
17729
  const read = () => {
17696
17730
  if (disposed) return null;
17697
- if (!discovery) {
17731
+ try {
17698
17732
  const store = dependencies.findStore(root);
17699
- discovery = store ? dependencies.findFamily(store) : null;
17733
+ const bound = store && discovery?.store === store ? [...store.familyBindings.values()].includes(discovery.family) : false;
17734
+ if (!bound) discovery = store ? dependencies.findFamily(store) : null;
17735
+ } catch {
17736
+ discovery = null;
17700
17737
  }
17701
17738
  return discovery;
17702
17739
  };
17703
17740
  if (!read()) return null;
17741
+ const native = () => {
17742
+ if (disposed) return null;
17743
+ try {
17744
+ nativeRouting ??= dependencies.nativeRouting?.() ?? null;
17745
+ } catch {
17746
+ }
17747
+ return nativeRouting;
17748
+ };
17749
+ const connectionFor = (hostId2) => {
17750
+ if (!hostId2.startsWith("remote-control:")) return void 0;
17751
+ try {
17752
+ return dependencies.readConnection?.(hostId2);
17753
+ } catch {
17754
+ return null;
17755
+ }
17756
+ };
17757
+ const sameConnection = (previous, current) => previous === void 0 ? current === void 0 : current?.owner === previous.owner && current.revision === previous.revision;
17704
17758
  const isRecord3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
17705
17759
  const externalDrafts = /* @__PURE__ */ new Map();
17706
17760
  const selectedModels = /* @__PURE__ */ new Map();
@@ -17778,16 +17832,25 @@ function installRendererHostRpcRouting(root, target, dependencies) {
17778
17832
  const postMessage = function(message, ...rest) {
17779
17833
  let routed = message;
17780
17834
  try {
17781
- routed = disposed ? message : routeCreationCall(message);
17835
+ routed = disposed || routes.size === 0 ? message : routeCreationCall(message);
17782
17836
  } catch {
17783
17837
  routed = message;
17784
17838
  }
17785
17839
  return originalPostMessage.call(this, routed, ...rest);
17786
17840
  };
17787
17841
  port.postMessage = postMessage;
17788
- const createRoute = (hostId2, rpc) => {
17842
+ const createRoute = (hostId2, rpc, connection) => {
17789
17843
  let retired = false;
17790
- const isCurrent = () => !retired && !disposed && routes.get(hostId2)?.rpc === rpc;
17844
+ const isCurrent = () => {
17845
+ if (retired || disposed || routes.get(hostId2)?.rpc !== rpc || !sameConnection(connection, connectionFor(hostId2)))
17846
+ return false;
17847
+ try {
17848
+ const current = read();
17849
+ return !!current && dependencies.resolve(current, hostId2) === rpc;
17850
+ } catch {
17851
+ return false;
17852
+ }
17853
+ };
17791
17854
  const manager = Object.freeze({
17792
17855
  kind: "main-process-rpc",
17793
17856
  getHostId: () => hostId2,
@@ -17860,15 +17923,23 @@ function installRendererHostRpcRouting(root, target, dependencies) {
17860
17923
  routes.delete(hostId2);
17861
17924
  entry?.route.policy.dispose();
17862
17925
  };
17863
- const routeFor = (hostId2) => {
17926
+ const routeFor = (hostId2, nativeRoute) => {
17927
+ if (disposed) return null;
17928
+ const connection = connectionFor(hostId2);
17929
+ const preferred = nativeRoute === void 0 ? native()?.forHost(hostId2) : nativeRoute;
17930
+ if (connection === null || preferred) {
17931
+ retire(hostId2);
17932
+ return connection === null ? null : preferred ?? null;
17933
+ }
17864
17934
  const current = read();
17865
17935
  const rpc = current ? dependencies.resolve(current, hostId2) : null;
17866
17936
  const previous = routes.get(hostId2);
17867
- if (rpc && previous?.rpc === rpc) return previous.route;
17937
+ if (rpc && previous?.rpc === rpc && sameConnection(previous.connection, connection))
17938
+ return previous.route;
17868
17939
  retire(hostId2);
17869
17940
  if (!rpc) return null;
17870
- const route = createRoute(hostId2, rpc);
17871
- routes.set(hostId2, { route, rpc });
17941
+ const route = createRoute(hostId2, rpc, connection);
17942
+ routes.set(hostId2, { route, rpc, connection });
17872
17943
  return route;
17873
17944
  };
17874
17945
  const publish = (route) => {
@@ -17883,14 +17954,22 @@ function installRendererHostRpcRouting(root, target, dependencies) {
17883
17954
  }
17884
17955
  };
17885
17956
  const composerHostId = (composer) => {
17957
+ const nativeHostId = native()?.hostIdForComposer(composer);
17958
+ if (nativeHostId) return nativeHostId;
17886
17959
  const hostIds = new Set(dependencies.composerHostIds(composer).hostIds);
17887
17960
  const hostId2 = hostIds.size === 1 ? hostIds.values().next().value : null;
17888
17961
  return typeof hostId2 === "string" && hostId2 ? hostId2 : null;
17889
17962
  };
17890
17963
  const routing = {
17891
17964
  knownHostIds() {
17965
+ if (disposed) return [];
17892
17966
  const current = read();
17893
- return current ? dependencies.hostIds(current) : [];
17967
+ return [
17968
+ .../* @__PURE__ */ new Set([
17969
+ ...current ? dependencies.hostIds(current) : [],
17970
+ ...native()?.knownHostIds?.() ?? []
17971
+ ])
17972
+ ];
17894
17973
  },
17895
17974
  forHost(hostId2) {
17896
17975
  return hostId2 && !disposed ? routeFor(hostId2) : null;
@@ -17906,18 +17985,22 @@ function installRendererHostRpcRouting(root, target, dependencies) {
17906
17985
  forComposer(composer) {
17907
17986
  if (disposed) return null;
17908
17987
  let hostId2;
17988
+ let preferred = null;
17909
17989
  try {
17910
- hostId2 = composerHostId(composer);
17990
+ preferred = native()?.forComposer(composer) ?? null;
17991
+ hostId2 = preferred?.hostId ?? composerHostId(composer);
17911
17992
  } catch {
17912
17993
  hostId2 = null;
17913
17994
  }
17914
- const route = hostId2 ? routeFor(hostId2) : null;
17995
+ const route = hostId2 ? routeFor(hostId2, preferred) : null;
17915
17996
  if (!composer) publish(route);
17916
17997
  return route;
17917
17998
  },
17918
17999
  dispose() {
17919
18000
  if (disposed) return;
17920
18001
  disposed = true;
18002
+ nativeRouting?.dispose();
18003
+ nativeRouting = null;
17921
18004
  for (const hostId2 of [...routes.keys()]) retire(hostId2);
17922
18005
  discovery = null;
17923
18006
  externalDrafts.clear();
@@ -17933,6 +18016,30 @@ function installRendererHostRpcRouting(root, target, dependencies) {
17933
18016
  return routing;
17934
18017
  }
17935
18018
 
18019
+ // packages/desktop-control/src/renderer-connection-generation.ts
18020
+ function readRendererConnectionGeneration(store, hostId2) {
18021
+ if (!store) return void 0;
18022
+ const record3 = (value) => value !== null && typeof value === "object";
18023
+ const candidates = /* @__PURE__ */ new Set();
18024
+ for (const members of store.familyBindings.values()) {
18025
+ const value = members.get(hostId2)?.value;
18026
+ if (record3(value) && record3(value.state$) && record3(value.revision$) && record3(value.appServerVersion$) && typeof value.state$.get === "function" && typeof value.revision$.get === "function")
18027
+ candidates.add(value);
18028
+ }
18029
+ if (!candidates.size) return void 0;
18030
+ if (candidates.size !== 1) return null;
18031
+ const owner = candidates.values().next().value;
18032
+ if (!owner) return null;
18033
+ const state = owner.state$;
18034
+ const revision = owner.revision$;
18035
+ try {
18036
+ const current = revision.get();
18037
+ return state.get() === "connected" && typeof current === "number" && Number.isSafeInteger(current) ? { owner, revision: current } : null;
18038
+ } catch {
18039
+ return null;
18040
+ }
18041
+ }
18042
+
17936
18043
  // packages/desktop-control/src/renderer-draft-prewarm-policy.ts
17937
18044
  var REQUEST_MANAGER_WAIT_TIMEOUT_MS = 6e4;
17938
18045
  var REQUEST_MANAGER_POLL_INTERVAL_MS = 25;
@@ -17945,15 +18052,19 @@ function directRendererInstaller() {
17945
18052
  const retainRendererHostResponses = ${retainRendererHostResponses.toString()};
17946
18053
  const createDraftPrewarmPolicyBridge = ${createDraftPrewarmPolicyBridge.toString()};
17947
18054
  const isolateRendererPrewarmConsumption = ${isolateRendererPrewarmConsumption.toString()};
18055
+ const findRendererAppScopeStore = ${findRendererAppScopeStore.toString()};
18056
+ const readRendererConnectionGeneration = ${readRendererConnectionGeneration.toString()};
17948
18057
  const discover = (root) =>
17949
18058
  discoverRendererHosts(root, committedReactAncestors, requestManagerFromHookState);
17950
- const installNative = () => (${installRendererHostRouting.toString()})(
18059
+ const installNative = (publishRouting = true) => (${installRendererHostRouting.toString()})(
17951
18060
  document, window, discover,
17952
18061
  (discovery, hostId) => resolveRendererHostManager(discovery, hostId, requestManagerFromHookState),
17953
18062
  (manager, bridge, hostId, target, prewarmed, isCurrent) => createDraftPrewarmPolicyBridge(
17954
18063
  manager, bridge, hostId, target, prewarmed, isCurrent, retainRendererHostResponses,
17955
18064
  isolateRendererPrewarmConsumption,
17956
18065
  ),
18066
+ (hostId) => readRendererConnectionGeneration(findRendererAppScopeStore(document), hostId),
18067
+ publishRouting,
17957
18068
  );
17958
18069
  const installRpc = () => typeof MessagePort !== 'function' ? null : (${installRendererHostRpcRouting.toString()})(document, window, {
17959
18070
  findStore: ${findRendererAppScopeStore.toString()},
@@ -17967,14 +18078,21 @@ function directRendererInstaller() {
17967
18078
  return discover(source);
17968
18079
  },
17969
18080
  portPrototype: MessagePort.prototype,
18081
+ nativeRouting: () => {
18082
+ const native = discover(document);
18083
+ return native.managers.length || native.registries.length ? installNative(false) : null;
18084
+ },
18085
+ readConnection: (hostId) => readRendererConnectionGeneration(findRendererAppScopeStore(document), hostId),
17970
18086
  });
17971
18087
  const connected = (routing) => routing.forComposer() !== null ||
17972
18088
  ['local', ...(routing.knownHostIds?.() ?? [])].some((hostId) => routing.forHost(hostId) !== null);
17973
18089
  let nativeReady = false;
17974
- // A legacy registry can remain mounted without a usable native manager.
17975
- // Prefer a ready native route, then try the identified main-process RPC store.
18090
+ // Mixed layouts can expose native managers for only some Hosts. Keep one
18091
+ // router that selects a native owner or the current ready RPC peer per Host.
17976
18092
  const routing = (() => {
17977
18093
  if (window.__codexhostHostRoutingV1) return window.__codexhostHostRoutingV1;
18094
+ const rpc = installRpc();
18095
+ if (rpc) return rpc;
17978
18096
  const native = discover(document);
17979
18097
  if (native.managers.length || native.registries.length) {
17980
18098
  const routing = installNative();
@@ -17984,8 +18102,6 @@ function directRendererInstaller() {
17984
18102
  }
17985
18103
  routing.dispose();
17986
18104
  }
17987
- const rpc = installRpc();
17988
- if (rpc) return rpc;
17989
18105
  throw new Error('Renderer Host request manager is unavailable');
17990
18106
  })();
17991
18107
  // Publish a default draft policy only when its Host is unambiguous. Host
@@ -18145,6 +18261,892 @@ async function installRendererLoadedModules(renderer) {
18145
18261
  }
18146
18262
  }
18147
18263
 
18264
+ // packages/desktop-control/src/renderer-native-rpc-discovery.ts
18265
+ function nativeManagerDependencies(factoryName, callers) {
18266
+ const identifier = "[$A-Z_a-z][$\\w]*";
18267
+ const escaped = factoryName.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
18268
+ const pattern = new RegExp(
18269
+ `${escaped}\\((${identifier}),(${identifier}),\\1\\.get\\((${identifier}),\\2\\),(${identifier})\\.bind\\(null,\\1\\),\\((${identifier}),(${identifier})\\)=>\\5\\((${identifier}),\\6\\)\\)`
18270
+ );
18271
+ const matches = callers.flatMap((source) => {
18272
+ const match = pattern.exec(source);
18273
+ return match?.[3] && match[4] && match[7] ? [
18274
+ {
18275
+ requestDefinition: match[3],
18276
+ isHostForConversation: match[4],
18277
+ imageDefinition: match[7]
18278
+ }
18279
+ ] : [];
18280
+ });
18281
+ return matches.length === 1 ? matches[0] : void 0;
18282
+ }
18283
+ function nativeRpcRole(source) {
18284
+ if (["dispatchMessageFromView", "threadProjectAssignments", "queuedMessageCoordination"].every(
18285
+ (part) => source.includes(part)
18286
+ ))
18287
+ return "createManager";
18288
+ if (["collectAppStateSnapshot", "getReviewPaneSnapshotMetrics", "registerReplayAdmission"].every(
18289
+ (part) => source.includes(part)
18290
+ ))
18291
+ return "createController";
18292
+ if (["getWorkInProgress", "getCachedThreadSearchSnapshot", "registerReplayAdmission"].every(
18293
+ (part) => source.includes(part)
18294
+ ))
18295
+ return "RpcManager";
18296
+ if (["prewarmedThreadManager", "onNotification", "dispatchAppServerResponse"].every(
18297
+ (part) => source.includes(part)
18298
+ ))
18299
+ return "Manager";
18300
+ return void 0;
18301
+ }
18302
+ function nativeRpcObjectShape(value) {
18303
+ if (value === null || typeof value !== "object")
18304
+ return { scope: false, services: false, controller: false };
18305
+ const candidate = value;
18306
+ const own = (keys) => keys.every((key) => Object.hasOwn(candidate, key));
18307
+ const methods = (keys) => keys.every((key) => typeof candidate[key] === "function");
18308
+ return {
18309
+ scope: own(["node", "scope", "get", "set", "watch"]) && methods(["get", "set", "watch"]),
18310
+ services: own(["appServerManagers", "remoteConnections", "applicationMenu"]) && typeof candidate.appServerManagers?.subscribe === "function",
18311
+ controller: own(["forHost", "collectAppStateSnapshot", "getReviewPaneSnapshotMetrics", "dispose"]) && methods(["forHost", "collectAppStateSnapshot", "getReviewPaneSnapshotMetrics", "dispose"])
18312
+ };
18313
+ }
18314
+ async function withNativeRpcComponents(client, install) {
18315
+ const group = `codexhost-native-rpc-${crypto.randomUUID()}`;
18316
+ const command = async (method, params) => client.command(method, params);
18317
+ const evaluate = (expression) => command("Runtime.evaluate", { expression, awaitPromise: true, objectGroup: group });
18318
+ const properties = (objectId) => command("Runtime.getProperties", { objectId, ownProperties: true });
18319
+ const call = (objectId, functionDeclaration, args = []) => command("Runtime.callFunctionOn", {
18320
+ objectId,
18321
+ functionDeclaration,
18322
+ arguments: args,
18323
+ objectGroup: group,
18324
+ returnByValue: true
18325
+ });
18326
+ try {
18327
+ const initial = await evaluate(String.raw`(() => {
18328
+ const catalog = globalThis.__codexhostLoadedModulesV1;
18329
+ if (!catalog?.complete || catalog.documentUrl !== location.href) return null;
18330
+ const urls = catalog.urls.filter(url => /^app:\/\/-\/assets\/(?:renderer-app-server-managers|app-shared)-[^/]+\.js$/.test(url));
18331
+ return { document, urls };
18332
+ })()`);
18333
+ if (!initial.result.objectId) return false;
18334
+ const holder = initial.result.objectId;
18335
+ const catalog = await call(holder, "function(){return this.urls}");
18336
+ const urls = catalog.result.value;
18337
+ if (!Array.isArray(urls) || urls.length !== 2) return false;
18338
+ const managerUrl = urls.find((url2) => url2.includes("renderer-app-server-managers"));
18339
+ const sharedUrl = urls.find((url2) => url2.includes("app-shared"));
18340
+ if (!managerUrl || !sharedUrl) return false;
18341
+ const attach = async (name, objectId) => {
18342
+ const result = await call(
18343
+ holder,
18344
+ "function(name,value){if(this.document!==document)throw Error('Renderer Realm changed');this[name]=value;return true}",
18345
+ [{ value: name }, { objectId }]
18346
+ );
18347
+ if (result.exceptionDetails) throw new Error("Native RPC discovery lost its Renderer Realm");
18348
+ };
18349
+ const imported = await evaluate(`import(${JSON.stringify(managerUrl)})`);
18350
+ if (!imported.result.objectId) return false;
18351
+ const exports = (await properties(imported.result.objectId)).result.filter(
18352
+ (entry) => entry.value?.type === "function"
18353
+ );
18354
+ let bindings = [];
18355
+ for (const entry of exports.slice(0, 3)) {
18356
+ if (!entry.value?.objectId) continue;
18357
+ const scopes = (await properties(entry.value.objectId)).internalProperties?.find(
18358
+ (entry2) => entry2.name === "[[Scopes]]"
18359
+ )?.value?.objectId;
18360
+ if (!scopes) continue;
18361
+ const modules = (await properties(scopes)).result.filter(
18362
+ (entry2) => entry2.value?.description?.startsWith("Module") && entry2.value.objectId
18363
+ );
18364
+ const moduleId = modules[0]?.value?.objectId;
18365
+ if (modules.length !== 1 || !moduleId) continue;
18366
+ bindings = (await properties(moduleId)).result;
18367
+ break;
18368
+ }
18369
+ const functions = bindings.filter((entry) => entry.value?.type === "function");
18370
+ const roles = /* @__PURE__ */ new Map();
18371
+ for (const entry of functions) {
18372
+ const role = nativeRpcRole(entry.value?.description ?? "");
18373
+ if (role) roles.set(role, [...roles.get(role) ?? [], entry]);
18374
+ }
18375
+ if (["createManager", "Manager", "RpcManager", "createController"].some(
18376
+ (role) => roles.get(role)?.length !== 1
18377
+ ))
18378
+ return false;
18379
+ const factory = roles.get("createManager")?.[0];
18380
+ if (!factory) return false;
18381
+ const dependencies = nativeManagerDependencies(
18382
+ factory.name,
18383
+ functions.map((entry) => entry.value?.description ?? "")
18384
+ );
18385
+ if (!dependencies) return false;
18386
+ for (const [role, entries] of roles) {
18387
+ const id = entries[0]?.value?.objectId;
18388
+ if (!id) return false;
18389
+ await attach(role, id);
18390
+ }
18391
+ for (const [role, name] of Object.entries(dependencies)) {
18392
+ const value = bindings.find((entry) => entry.name === name)?.value?.objectId;
18393
+ if (!value) return false;
18394
+ await attach(role, value);
18395
+ }
18396
+ const shared = await evaluate(`import(${JSON.stringify(sharedUrl)})`);
18397
+ if (!shared.result.objectId) return false;
18398
+ const sharedExports = (await properties(shared.result.objectId)).result;
18399
+ const sessions = sharedExports.filter(
18400
+ (entry) => entry.value?.type === "function" && ["getRemoteMain", "getStats", "drain", "getMainImport"].every(
18401
+ (word) => entry.value?.description?.includes(word)
18402
+ )
18403
+ );
18404
+ const sessionId = sessions[0]?.value?.objectId;
18405
+ if (sessions.length !== 1 || !sessionId) return false;
18406
+ await attach("RpcSession", sessionId);
18407
+ const serviceMatches = await command("Runtime.callFunctionOn", {
18408
+ objectId: shared.result.objectId,
18409
+ functionDeclaration: `function(){return [...new Set(Object.values(this).filter(value => (${nativeRpcObjectShape.toString()})(value).services))]}`,
18410
+ objectGroup: group
18411
+ });
18412
+ if (!serviceMatches.result.objectId) return false;
18413
+ const services = (await properties(serviceMatches.result.objectId)).result.flatMap(
18414
+ (entry) => entry.value?.type === "object" && entry.value.objectId ? [entry.value.objectId] : []
18415
+ );
18416
+ const serviceId = services[0];
18417
+ if (services.length !== 1 || !serviceId) return false;
18418
+ await attach("services", serviceId);
18419
+ const prototype = await evaluate("Object.getPrototypeOf(async function(){})");
18420
+ if (!prototype.result.objectId) return false;
18421
+ const objects = await command("Runtime.queryObjects", {
18422
+ prototypeObjectId: prototype.result.objectId,
18423
+ objectGroup: group
18424
+ });
18425
+ if (!objects.objects.objectId) return false;
18426
+ const filtered = await command("Runtime.callFunctionOn", {
18427
+ objectId: objects.objects.objectId,
18428
+ functionDeclaration: 'function(){return this.filter(fn=>fn.name==="collectAppStateSnapshot"&&String(fn).includes("collectSnapshot")).slice(0,9)}',
18429
+ objectGroup: group
18430
+ });
18431
+ if (!filtered.result.objectId) return false;
18432
+ const snapshots = (await properties(filtered.result.objectId)).result.filter(
18433
+ (entry) => entry.value?.type === "function"
18434
+ );
18435
+ if (snapshots.length > 8) return false;
18436
+ const owners = [];
18437
+ for (const snapshot of snapshots) {
18438
+ const fn = snapshot.value?.objectId;
18439
+ if (!fn) continue;
18440
+ const scopes = (await properties(fn)).internalProperties?.find(
18441
+ (entry) => entry.name === "[[Scopes]]"
18442
+ )?.value?.objectId;
18443
+ if (!scopes) continue;
18444
+ for (const scope of (await properties(scopes)).result) {
18445
+ if (!scope.value?.description?.startsWith("Closure") || !scope.value.objectId) continue;
18446
+ const candidates = (await properties(scope.value.objectId)).result;
18447
+ const controllers = [], handles = [];
18448
+ for (const binding of candidates) {
18449
+ if (binding.value?.type !== "object" || !binding.value.objectId) continue;
18450
+ const id = binding.value.objectId;
18451
+ const response = await call(
18452
+ id,
18453
+ `function(){return (${nativeRpcObjectShape.toString()})(this)}`
18454
+ );
18455
+ const shape = response.result.value;
18456
+ if (shape?.scope) handles.push(id);
18457
+ if (shape?.controller && (await call(id, "function(fn){return this.collectAppStateSnapshot===fn}", [
18458
+ { objectId: fn }
18459
+ ])).result.value === true)
18460
+ controllers.push(id);
18461
+ }
18462
+ const controller = controllers[0], handle = handles[0];
18463
+ if (controllers.length === 1 && handles.length === 1 && controller && handle)
18464
+ owners.push({ controller, scope: handle });
18465
+ }
18466
+ }
18467
+ const owner = owners[0];
18468
+ if (owners.length !== 1 || !owner) return false;
18469
+ await attach("controller", owner.controller);
18470
+ await attach("scope", owner.scope);
18471
+ return await install(holder);
18472
+ } finally {
18473
+ await client.command("Runtime.releaseObjectGroup", { objectGroup: group }).catch(() => void 0);
18474
+ }
18475
+ }
18476
+
18477
+ // packages/desktop-control/src/renderer-native-rpc-runtime.ts
18478
+ function installNativeRpcRemoteControl(components, target, dependencies) {
18479
+ if (target.__codexhostNativeRpcRemoteControlV1) return true;
18480
+ const routing = target.__codexhostHostRoutingV1;
18481
+ if (!routing) return false;
18482
+ const adapted = dependencies.createService(
18483
+ components,
18484
+ (hostId2, upstream) => dependencies.createManager(
18485
+ components,
18486
+ hostId2,
18487
+ upstream,
18488
+ target,
18489
+ dependencies.createPolicy,
18490
+ dependencies.createChannel,
18491
+ dependencies.retainInteractions
18492
+ )
18493
+ );
18494
+ const controller = components.controller;
18495
+ const originalHost = routing.forHost, originalComposer = routing.forComposer, originalDispose = routing.dispose;
18496
+ controller.dispose();
18497
+ let replacement;
18498
+ try {
18499
+ replacement = components.createController(components.scope, adapted.service);
18500
+ } catch (error51) {
18501
+ replacement = components.createController(
18502
+ components.scope,
18503
+ components.services.appServerManagers
18504
+ );
18505
+ throw error51;
18506
+ } finally {
18507
+ adapted.service[Symbol.dispose]();
18508
+ controller.forHost = (hostId2) => replacement.forHost(hostId2);
18509
+ controller.collectAppStateSnapshot = (hostId2, options) => replacement.collectAppStateSnapshot(hostId2, options);
18510
+ controller.getReviewPaneSnapshotMetrics = (hostId2) => replacement.getReviewPaneSnapshotMetrics(hostId2);
18511
+ controller.dispose = () => replacement.dispose();
18512
+ }
18513
+ const forHost = (hostId2) => {
18514
+ const route = adapted.route(hostId2);
18515
+ return route === void 0 ? originalHost.call(routing, hostId2) : route;
18516
+ };
18517
+ const forComposer = (composer) => {
18518
+ const hostId2 = routing.hostIdForComposer(composer);
18519
+ return hostId2 ? forHost(hostId2) : originalComposer.call(routing, composer);
18520
+ };
18521
+ routing.forHost = forHost;
18522
+ routing.forComposer = forComposer;
18523
+ const installation = {
18524
+ dispose() {
18525
+ if (target.__codexhostNativeRpcRemoteControlV1 !== installation) return;
18526
+ delete target.__codexhostNativeRpcRemoteControlV1;
18527
+ replacement.dispose();
18528
+ replacement = components.createController(
18529
+ components.scope,
18530
+ components.services.appServerManagers
18531
+ );
18532
+ if (routing.forHost === forHost) routing.forHost = originalHost;
18533
+ if (routing.forComposer === forComposer) routing.forComposer = originalComposer;
18534
+ routing.dispose = originalDispose;
18535
+ }
18536
+ };
18537
+ routing.dispose = () => {
18538
+ installation.dispose();
18539
+ originalDispose.call(routing);
18540
+ };
18541
+ target.__codexhostNativeRpcRemoteControlV1 = installation;
18542
+ return true;
18543
+ }
18544
+
18545
+ // packages/desktop-control/src/renderer-native-remote-manager.ts
18546
+ function createNativeRemoteManager(components, hostId2, original, target, createPolicy, createChannel, retainInteractions) {
18547
+ const source = components.scope.get(components.requestDefinition, hostId2);
18548
+ const upstream = original.dup();
18549
+ let manager;
18550
+ let policy;
18551
+ let interactions;
18552
+ let disposed = false;
18553
+ const pending = /* @__PURE__ */ new Set();
18554
+ const send = (method, params, options) => {
18555
+ const request = upstream.sendRequest(method, params, options);
18556
+ const result = Promise.resolve(request).finally(() => {
18557
+ request[Symbol.dispose]();
18558
+ pending.delete(result);
18559
+ });
18560
+ pending.add(result);
18561
+ return result;
18562
+ };
18563
+ const record3 = (value) => value !== null && typeof value === "object";
18564
+ const dispatch = (type, payload) => {
18565
+ if ((type === "mcp-request" || type === "thread-prewarm-start") && record3(payload) && record3(payload.request)) {
18566
+ const request = payload.request;
18567
+ const options = {};
18568
+ for (const key of ["priority", "timeoutMs", "source", "trace", "threadAccess"])
18569
+ if (payload[key] !== void 0) options[key] = payload[key];
18570
+ void send(String(request.method), request.params, options).then(
18571
+ (result) => {
18572
+ if (!disposed) client.onResult(request.id, result);
18573
+ },
18574
+ (error51) => {
18575
+ if (!disposed)
18576
+ client.onError(request.id, {
18577
+ code: record3(error51) ? error51.jsonRpcCode ?? error51.code ?? -32603 : -32603,
18578
+ message: error51 instanceof Error ? error51.message : String(error51)
18579
+ });
18580
+ }
18581
+ );
18582
+ return;
18583
+ }
18584
+ return source.dispatchMessage(type, payload);
18585
+ };
18586
+ const Constructor = source.constructor;
18587
+ let client;
18588
+ try {
18589
+ client = new Constructor(
18590
+ hostId2,
18591
+ dispatch,
18592
+ false,
18593
+ (id) => manager?.getConversation(id)?.threadAccess
18594
+ );
18595
+ client.setAppServerVersion(source.getAppServerVersion());
18596
+ manager = components.createManager(
18597
+ components.scope,
18598
+ hostId2,
18599
+ client,
18600
+ components.isHostForConversation.bind(null, components.scope),
18601
+ (get, id) => get(components.imageDefinition, id),
18602
+ { dispatchMessageFromView: dispatch }
18603
+ );
18604
+ manager.dispatchAppServerResponse = manager.sendAppServerResponse;
18605
+ const owned = manager;
18606
+ const ownedPolicy = createPolicy(
18607
+ owned,
18608
+ client,
18609
+ hostId2,
18610
+ target,
18611
+ owned.prewarmedThreadManager,
18612
+ () => !disposed,
18613
+ void 0,
18614
+ void 0,
18615
+ (method, params) => send(method, params, { priority: "critical" })
18616
+ );
18617
+ policy = ownedPolicy;
18618
+ owned.sendAppServerResponse = (...args) => owned.dispatchAppServerResponse(...args);
18619
+ const channel = createChannel(components, owned);
18620
+ const nativeInteractions = retainInteractions(upstream, owned, hostId2);
18621
+ interactions = nativeInteractions;
18622
+ const notify = (event) => {
18623
+ const { data, source: source2, origin } = event;
18624
+ if (disposed || source2 != null && source2 !== target || !record3(data) || data.hostId !== hostId2)
18625
+ return;
18626
+ const ownOrigin = record3(target.location) ? target.location.origin : void 0;
18627
+ if (source2 === target && ownOrigin && ownOrigin !== "null" && origin !== ownOrigin) return;
18628
+ if (data.type === "mcp-notification" && typeof data.method === "string" && !data.method.startsWith("process/"))
18629
+ owned.onNotification(data.method, data.params);
18630
+ if (data.type === "mcp-request") owned.onRequest(record3(data.request) ? data.request : data);
18631
+ };
18632
+ target.addEventListener?.("message", notify);
18633
+ return {
18634
+ route: { hostId: hostId2, manager: owned, policy: ownedPolicy },
18635
+ rpc: channel.rpc,
18636
+ ready: nativeInteractions.ready,
18637
+ dispose() {
18638
+ if (disposed) return;
18639
+ disposed = true;
18640
+ target.removeEventListener?.("message", notify);
18641
+ nativeInteractions.dispose();
18642
+ ownedPolicy.dispose();
18643
+ client.queuedRequests.length = 0;
18644
+ for (const id of [...client.requestPromises.keys()])
18645
+ client.onError(id, new Error("Remote Control connection retired"));
18646
+ channel.dispose();
18647
+ components.Manager.dispose(owned);
18648
+ void Promise.allSettled([...pending]).then(() => upstream[Symbol.dispose]());
18649
+ }
18650
+ };
18651
+ } catch (error51) {
18652
+ interactions?.dispose();
18653
+ policy?.dispose();
18654
+ if (manager) components.Manager.dispose(manager);
18655
+ upstream[Symbol.dispose]();
18656
+ throw error51;
18657
+ }
18658
+ }
18659
+
18660
+ // packages/desktop-control/src/renderer-native-rpc-channel.ts
18661
+ function createNativeRpcChannel(components, manager) {
18662
+ const channel = new MessageChannel();
18663
+ const transports = [];
18664
+ const transport = (port) => {
18665
+ const values = [];
18666
+ const readers = [];
18667
+ let closed = false;
18668
+ let failure;
18669
+ port.addEventListener("message", (event) => {
18670
+ const value = JSON.stringify(event.data);
18671
+ const reader = readers.shift();
18672
+ if (reader) reader.resolve(value);
18673
+ else values.push(value);
18674
+ });
18675
+ port.start();
18676
+ const result = {
18677
+ send(message) {
18678
+ if (closed) throw failure;
18679
+ port.postMessage(JSON.parse(message));
18680
+ },
18681
+ receive() {
18682
+ if (closed) return Promise.reject(failure);
18683
+ const value = values.shift();
18684
+ return value !== void 0 ? Promise.resolve(value) : new Promise((resolve, reject) => readers.push({ resolve, reject }));
18685
+ },
18686
+ abort(error51) {
18687
+ if (closed) return;
18688
+ closed = true;
18689
+ failure = error51 ?? new Error("Remote Control RPC manager retired");
18690
+ values.length = 0;
18691
+ for (const reader of readers.splice(0)) reader.reject(failure);
18692
+ port.close();
18693
+ }
18694
+ };
18695
+ transports.push(result);
18696
+ return result;
18697
+ };
18698
+ try {
18699
+ new components.RpcSession(transport(channel.port1), new components.RpcManager(() => manager));
18700
+ const session = new components.RpcSession(transport(channel.port2));
18701
+ const rpc = session.getRemoteMain();
18702
+ return {
18703
+ rpc,
18704
+ dispose() {
18705
+ rpc[Symbol.dispose]();
18706
+ for (const transport2 of transports) transport2.abort();
18707
+ }
18708
+ };
18709
+ } catch (error51) {
18710
+ for (const transport2 of transports) transport2.abort(error51);
18711
+ channel.port1.close();
18712
+ channel.port2.close();
18713
+ throw error51;
18714
+ }
18715
+ }
18716
+
18717
+ // packages/desktop-control/src/renderer-native-rpc-service.ts
18718
+ function createNativeRpcService(components, createRemote) {
18719
+ const source = components.services.appServerManagers.dup();
18720
+ const routes = /* @__PURE__ */ new Map();
18721
+ const subscriptions = /* @__PURE__ */ new Set();
18722
+ let refs = 1;
18723
+ const record3 = (value) => value !== null && typeof value === "object";
18724
+ const connectionSignals = (hostId2) => {
18725
+ let node = components.scope.node;
18726
+ const seen = /* @__PURE__ */ new Set();
18727
+ while (node.parent && !seen.has(node.parent) && seen.size < 100) {
18728
+ seen.add(node);
18729
+ node = node.parent;
18730
+ }
18731
+ const found = [];
18732
+ for (const members of node.familyBindings.values()) {
18733
+ const value = members.get(hostId2)?.value;
18734
+ if (record3(value) && Object.hasOwn(value, "state$") && Object.hasOwn(value, "revision$") && Object.hasOwn(value, "appServerVersion$"))
18735
+ found.push({ state$: value.state$, revision$: value.revision$ });
18736
+ }
18737
+ return found.length === 1 ? found[0] : void 0;
18738
+ };
18739
+ const service = {
18740
+ dup() {
18741
+ refs++;
18742
+ return service;
18743
+ },
18744
+ onRpcBroken(listener) {
18745
+ source.onRpcBroken(listener);
18746
+ },
18747
+ openAccount(hostId2) {
18748
+ return source.openAccount(hostId2);
18749
+ },
18750
+ subscribe(hostId2, listener) {
18751
+ if (!hostId2.startsWith("remote-control:")) return source.subscribe(hostId2, listener);
18752
+ let active = true;
18753
+ let generation = 0;
18754
+ let upstream;
18755
+ let platformRequest;
18756
+ let remote;
18757
+ let stopWatch;
18758
+ let previousRevision;
18759
+ let previousState;
18760
+ const retire = () => {
18761
+ generation++;
18762
+ platformRequest?.[Symbol.dispose]();
18763
+ platformRequest = void 0;
18764
+ remote?.dispose();
18765
+ remote = void 0;
18766
+ routes.set(hostId2, null);
18767
+ };
18768
+ const cleanup = () => {
18769
+ if (!active) return;
18770
+ active = false;
18771
+ stopWatch?.();
18772
+ retire();
18773
+ upstream?.[Symbol.dispose]();
18774
+ upstream = void 0;
18775
+ routes.delete(hostId2);
18776
+ subscriptions.delete(cleanup);
18777
+ };
18778
+ subscriptions.add(cleanup);
18779
+ const publish = async () => {
18780
+ const owner = upstream;
18781
+ const current = generation;
18782
+ if (!owner || !active) return;
18783
+ let request;
18784
+ try {
18785
+ request = owner.getCodexHome();
18786
+ platformRequest = request;
18787
+ const home = await request;
18788
+ if (!active || current !== generation || owner !== upstream) return;
18789
+ if (!/^(?:[A-Za-z]:[\\/]|\\\\)/u.test(home)) {
18790
+ routes.delete(hostId2);
18791
+ listener({ status: "ready", manager: owner });
18792
+ return;
18793
+ }
18794
+ const created = createRemote(hostId2, owner);
18795
+ remote = created;
18796
+ await created.ready;
18797
+ if (!active || current !== generation || owner !== upstream) return;
18798
+ routes.set(hostId2, created.route);
18799
+ listener({ status: "ready", manager: created.rpc });
18800
+ } catch {
18801
+ if (active && current === generation) {
18802
+ remote?.dispose();
18803
+ remote = void 0;
18804
+ routes.delete(hostId2);
18805
+ listener({ status: "ready", manager: owner });
18806
+ }
18807
+ } finally {
18808
+ if (platformRequest === request) {
18809
+ platformRequest = void 0;
18810
+ request?.[Symbol.dispose]();
18811
+ }
18812
+ }
18813
+ };
18814
+ const changed = (state) => {
18815
+ if (!active) return;
18816
+ stopWatch?.();
18817
+ stopWatch = void 0;
18818
+ retire();
18819
+ upstream?.[Symbol.dispose]();
18820
+ upstream = void 0;
18821
+ if (state.status !== "ready") {
18822
+ listener(state);
18823
+ return;
18824
+ }
18825
+ upstream = state.manager.dup();
18826
+ listener({ status: "connecting" });
18827
+ const signals = connectionSignals(hostId2);
18828
+ if (!signals) {
18829
+ void publish();
18830
+ return;
18831
+ }
18832
+ previousState = void 0;
18833
+ previousRevision = void 0;
18834
+ stopWatch = components.scope.watch(({ get }) => {
18835
+ const connection = get(signals.state$), revision = get(signals.revision$);
18836
+ if (connection === previousState && revision === previousRevision) return;
18837
+ previousState = connection;
18838
+ previousRevision = revision;
18839
+ retire();
18840
+ listener({ status: connection === "connected" ? "connecting" : "disconnected" });
18841
+ if (connection === "connected") void publish();
18842
+ });
18843
+ };
18844
+ const original = source.subscribe(hostId2, changed);
18845
+ const result = original.then((lease) => {
18846
+ if (!active) lease[Symbol.dispose]();
18847
+ return {
18848
+ onRpcBroken: (listener2) => lease.onRpcBroken(listener2),
18849
+ [Symbol.dispose]() {
18850
+ cleanup();
18851
+ lease[Symbol.dispose]();
18852
+ }
18853
+ };
18854
+ });
18855
+ Object.assign(result, {
18856
+ onRpcBroken: (listener2) => original.onRpcBroken(listener2),
18857
+ [Symbol.dispose]() {
18858
+ cleanup();
18859
+ original[Symbol.dispose]();
18860
+ }
18861
+ });
18862
+ return result;
18863
+ },
18864
+ [Symbol.dispose]() {
18865
+ if (--refs !== 0) return;
18866
+ for (const cleanup of [...subscriptions]) cleanup();
18867
+ source[Symbol.dispose]();
18868
+ }
18869
+ };
18870
+ return { service, route: (hostId2) => routes.get(hostId2) };
18871
+ }
18872
+
18873
+ // packages/desktop-control/src/renderer-native-rpc-interactions.ts
18874
+ function retainNativeRpcInteractions(upstream, manager, hostId2) {
18875
+ let disposed = false;
18876
+ const retained = /* @__PURE__ */ new Set();
18877
+ const requests = /* @__PURE__ */ new Map();
18878
+ const reads = /* @__PURE__ */ new Map();
18879
+ const record3 = (value) => value !== null && typeof value === "object";
18880
+ const read = (threadId) => {
18881
+ const existing = reads.get(threadId);
18882
+ if (existing) {
18883
+ existing.dirty = true;
18884
+ return existing.promise;
18885
+ }
18886
+ const entry = { promise: Promise.resolve(), dirty: false };
18887
+ reads.set(threadId, entry);
18888
+ entry.promise = Promise.resolve().then(async () => {
18889
+ do {
18890
+ if (disposed) break;
18891
+ entry.dirty = false;
18892
+ const pending = upstream.getConversation(threadId);
18893
+ retained.add(pending);
18894
+ try {
18895
+ const conversation = await pending;
18896
+ if (disposed || entry.dirty || !record3(conversation) || !Array.isArray(conversation.requests))
18897
+ continue;
18898
+ const previous = requests.get(threadId) ?? /* @__PURE__ */ new Set();
18899
+ const next = /* @__PURE__ */ new Set();
18900
+ for (const request of conversation.requests) {
18901
+ 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")
18902
+ continue;
18903
+ next.add(request.id);
18904
+ if (!previous.has(request.id)) manager.onRequest(request);
18905
+ }
18906
+ if (next.size) requests.set(threadId, next);
18907
+ else requests.delete(threadId);
18908
+ } finally {
18909
+ if (retained.delete(pending)) pending[Symbol.dispose]();
18910
+ }
18911
+ } while (!disposed && entry.dirty);
18912
+ }).finally(() => {
18913
+ reads.delete(threadId);
18914
+ });
18915
+ return entry.promise;
18916
+ };
18917
+ const event = (value) => {
18918
+ if (disposed || !record3(value) || typeof value.conversationId !== "string") return;
18919
+ void read(value.conversationId).catch(() => void 0);
18920
+ };
18921
+ const subscribe = (input) => {
18922
+ const pending = upstream.subscribe(input);
18923
+ retained.add(pending);
18924
+ return Promise.resolve(pending).then((lease) => {
18925
+ if (disposed) lease[Symbol.dispose]();
18926
+ else retained.add(lease);
18927
+ });
18928
+ };
18929
+ const subscriptions = [
18930
+ "approval-request",
18931
+ "user-input-request",
18932
+ "mcp-elicitation-request",
18933
+ "approval-resolved"
18934
+ ].map((name) => subscribe({ type: "event", key: { hostId: hostId2 }, event: name, listener: event }));
18935
+ subscriptions.push(
18936
+ subscribe({
18937
+ type: "notification",
18938
+ key: { hostId: hostId2 },
18939
+ methods: ["serverRequest/resolved"],
18940
+ listener(value) {
18941
+ if (record3(value) && record3(value.params) && typeof value.params.threadId === "string")
18942
+ event({ conversationId: value.params.threadId });
18943
+ }
18944
+ })
18945
+ );
18946
+ const ready = Promise.all(subscriptions).then(async () => {
18947
+ if (disposed) return;
18948
+ const pending = upstream.getWorkInProgress();
18949
+ retained.add(pending);
18950
+ try {
18951
+ const work = await pending;
18952
+ if (disposed) return;
18953
+ if (!Array.isArray(work)) throw new Error("Native RPC interaction snapshot is unavailable");
18954
+ const threadIds = new Set(
18955
+ work.flatMap(
18956
+ (item) => record3(item) && typeof item.conversationId === "string" ? [item.conversationId] : []
18957
+ )
18958
+ );
18959
+ await Promise.all([...threadIds].map(read));
18960
+ } finally {
18961
+ if (retained.delete(pending)) pending[Symbol.dispose]();
18962
+ }
18963
+ });
18964
+ return {
18965
+ ready,
18966
+ dispose() {
18967
+ if (disposed) return;
18968
+ disposed = true;
18969
+ for (const lease of retained) lease[Symbol.dispose]();
18970
+ retained.clear();
18971
+ requests.clear();
18972
+ }
18973
+ };
18974
+ }
18975
+
18976
+ // packages/desktop-control/src/renderer-native-rpc-install.ts
18977
+ async function installNativeRpcRemoteControlDirect(renderer) {
18978
+ let attempt;
18979
+ const probeId = crypto.randomUUID();
18980
+ try {
18981
+ attempt = await renderer.evaluate(`(() => {
18982
+ if (window.__codexhostNativeRpcRemoteControlV1) return null;
18983
+ const routing = window.__codexhostHostRoutingV1;
18984
+ const owner = routing?.forHost('local')?.manager;
18985
+ if (owner?.kind !== 'main-process-rpc') return null;
18986
+ const catalog = window.__codexhostLoadedModulesV1;
18987
+ if (!catalog?.complete) return null;
18988
+ const key = JSON.stringify([catalog.owner, catalog.urls.filter(url => /renderer-app-server-managers|app-shared/.test(url)).sort()]);
18989
+ const previous = window.__codexhostNativeRpcDiscoveryV1;
18990
+ const sameOwner = previous?.key === key && previous.owner === owner;
18991
+ if (sameOwner && (previous.state !== 'unavailable' || previous.attempts >= 3 || Date.now() < previous.nextRetryAt)) return null;
18992
+ const token = ${JSON.stringify(probeId)};
18993
+ window.__codexhostNativeRpcDiscoveryV1 = {
18994
+ key, owner, token, state: 'discovering', attempts: sameOwner ? previous.attempts + 1 : 1,
18995
+ };
18996
+ return token;
18997
+ })()`);
18998
+ } catch {
18999
+ return false;
19000
+ }
19001
+ if (attempt === null) return false;
19002
+ let installed = false;
19003
+ try {
19004
+ installed = await withNativeRpcComponents(renderer, async (objectId) => {
19005
+ const result = await renderer.command("Runtime.callFunctionOn", {
19006
+ objectId,
19007
+ functionDeclaration: `function() {
19008
+ if (this.document !== document) return false;
19009
+ const retainRendererHostResponses = ${retainRendererHostResponses.toString()};
19010
+ const isolateRendererPrewarmConsumption = ${isolateRendererPrewarmConsumption.toString()};
19011
+ return (${installNativeRpcRemoteControl.toString()})(this, window, {
19012
+ createPolicy: ${createDraftPrewarmPolicyBridge.toString()},
19013
+ createManager: ${createNativeRemoteManager.toString()},
19014
+ createChannel: ${createNativeRpcChannel.toString()},
19015
+ createService: ${createNativeRpcService.toString()},
19016
+ retainInteractions: ${retainNativeRpcInteractions.toString()},
19017
+ });
19018
+ }`,
19019
+ returnByValue: true
19020
+ });
19021
+ return !result.exceptionDetails && result.result?.value === true;
19022
+ });
19023
+ return installed;
19024
+ } catch {
19025
+ return false;
19026
+ } finally {
19027
+ await renderer.evaluate(
19028
+ `(() => {
19029
+ const status = window.__codexhostNativeRpcDiscoveryV1;
19030
+ if (status?.token === ${JSON.stringify(attempt)}) {
19031
+ status.state = ${JSON.stringify(installed ? "ready" : "unavailable")};
19032
+ status.nextRetryAt = Date.now() + 5000 * 2 ** (status.attempts - 1);
19033
+ }
19034
+ })()`
19035
+ ).catch(() => void 0);
19036
+ }
19037
+ }
19038
+
19039
+ // packages/desktop-control/src/renderer-rpc-steering.ts
19040
+ var RETRY_BASE_MS = 5e3;
19041
+ var RETRY_MAX_MS = 3e5;
19042
+ var retries = /* @__PURE__ */ new WeakMap();
19043
+ async function installRendererRpcSteeringDirect(client, now = Date.now) {
19044
+ try {
19045
+ const needed = await client.evaluate(`(() => {
19046
+ const steering = window.__codexhostRpcSteeringV1;
19047
+ if (steering && steering.controller.forHost === steering.forHost) return false;
19048
+ steering?.release();
19049
+ const routing=window.__codexhostHostRoutingV1;
19050
+ return ['local', ...(routing?.knownHostIds?.() ?? [])].some(id => routing?.forHost(id)?.manager.kind === 'main-process-rpc');
19051
+ })()`);
19052
+ if (!needed) return false;
19053
+ const retry = retries.get(client);
19054
+ if (retry && now() < retry.nextAt) return false;
19055
+ try {
19056
+ await discoverAndInstall(client);
19057
+ retries.delete(client);
19058
+ return true;
19059
+ } catch (error51) {
19060
+ const attempts = (retry?.attempts ?? 0) + 1;
19061
+ const delay = Math.min(RETRY_BASE_MS * 2 ** (attempts - 1), RETRY_MAX_MS);
19062
+ retries.set(client, { attempts, nextAt: now() + delay });
19063
+ console.error(
19064
+ `codexhost native steering discovery failed (attempt ${attempts}):`,
19065
+ error51 instanceof Error ? error51.message : String(error51)
19066
+ );
19067
+ return false;
19068
+ }
19069
+ } catch {
19070
+ return false;
19071
+ }
19072
+ }
19073
+ async function discoverAndInstall(client) {
19074
+ const group = `codexhost-rpc-steering-${crypto.randomUUID()}`;
19075
+ const command = (method, params) => client.command(method, params);
19076
+ const properties = (objectId) => command("Runtime.getProperties", { objectId, ownProperties: true });
19077
+ const call = (objectId, functionDeclaration, args = []) => command("Runtime.callFunctionOn", {
19078
+ objectId,
19079
+ functionDeclaration,
19080
+ arguments: args,
19081
+ objectGroup: group,
19082
+ returnByValue: true
19083
+ });
19084
+ try {
19085
+ const proto = await command("Runtime.evaluate", {
19086
+ expression: "Object.getPrototypeOf(async function(){})",
19087
+ objectGroup: group
19088
+ });
19089
+ if (!proto.result.objectId) throw new Error("Native RPC steering discovery is unavailable");
19090
+ const objects = await command("Runtime.queryObjects", {
19091
+ prototypeObjectId: proto.result.objectId,
19092
+ objectGroup: group
19093
+ });
19094
+ if (!objects.objects.objectId) throw new Error("Native RPC steering discovery is unavailable");
19095
+ const filtered = await command("Runtime.callFunctionOn", {
19096
+ objectId: objects.objects.objectId,
19097
+ functionDeclaration: 'function(){return this.filter(fn=>fn.name==="collectAppStateSnapshot"&&String(fn).includes("collectSnapshot")).slice(0,9)}',
19098
+ objectGroup: group
19099
+ });
19100
+ if (!filtered.result.objectId) throw new Error("Native RPC Controller is unavailable");
19101
+ const snapshots = (await properties(filtered.result.objectId)).result.flatMap(
19102
+ (entry) => entry.value?.type === "function" && entry.value.objectId ? [entry.value.objectId] : []
19103
+ );
19104
+ if (snapshots.length > 8) throw new Error("Native RPC Controller is ambiguous");
19105
+ const controllers = [];
19106
+ for (const snapshot of snapshots) {
19107
+ const scopes = (await properties(snapshot)).internalProperties?.find(
19108
+ (entry) => entry.name === "[[Scopes]]"
19109
+ )?.value?.objectId;
19110
+ if (!scopes) continue;
19111
+ for (const scope of (await properties(scopes)).result) {
19112
+ if (!scope.value?.objectId || !scope.value.description?.startsWith("Closure")) continue;
19113
+ const bindings = (await properties(scope.value.objectId)).result;
19114
+ const owners = [];
19115
+ let rootScope;
19116
+ for (const binding of bindings) {
19117
+ if (binding.value?.type !== "object" || !binding.value.objectId) continue;
19118
+ const id = binding.value.objectId;
19119
+ const result2 = await call(
19120
+ id,
19121
+ `function(){return (${nativeRpcObjectShape.toString()})(this)}`
19122
+ );
19123
+ const shape = result2.result.value;
19124
+ if (shape?.scope) rootScope = id;
19125
+ if (shape?.controller && (await call(id, "function(fn){return this.collectAppStateSnapshot===fn}", [
19126
+ { objectId: snapshot }
19127
+ ])).result.value === true)
19128
+ owners.push(id);
19129
+ }
19130
+ if (owners.length !== 1 || !rootScope) continue;
19131
+ const root = await call(
19132
+ rootScope,
19133
+ `function(){let node=this.node;const seen=new Set();while(node?.parent&&!seen.has(node.parent)&&seen.size<100){seen.add(node);node=node.parent}return (${findRendererAppScopeStore.toString()})(document)===node}`
19134
+ );
19135
+ if (root.result.value === true) controllers.push(owners[0]);
19136
+ }
19137
+ }
19138
+ if (controllers.length !== 1) throw new Error("Native RPC Controller is missing or ambiguous");
19139
+ const result = await call(
19140
+ controllers[0],
19141
+ "function(){return window.__codexhostInstallRpcSteeringV1?.(this) === true}"
19142
+ );
19143
+ if (result.exceptionDetails || result.result.value !== true)
19144
+ throw new Error("Native RPC steering installation failed");
19145
+ } finally {
19146
+ await client.command("Runtime.releaseObjectGroup", { objectGroup: group }).catch(() => void 0);
19147
+ }
19148
+ }
19149
+
18148
19150
  // packages/desktop-control/src/renderer-cdp-control-session.ts
18149
19151
  function isRecord2(value) {
18150
19152
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -18402,7 +19404,12 @@ var InstalledRendererCdpControlSession = class {
18402
19404
  var defaultOperations = {
18403
19405
  listTargets: (endpoint, signal) => listCdpTargets(endpoint, fetch, signal),
18404
19406
  connect: (webSocketDebuggerUrl) => CdpClient.connect(webSocketDebuggerUrl),
18405
- installDraftPrewarmPolicy: installRendererDraftPrewarmPolicyDirect
19407
+ async installDraftPrewarmPolicy(renderer) {
19408
+ const status = await installRendererDraftPrewarmPolicyDirect(renderer);
19409
+ await installNativeRpcRemoteControlDirect(renderer);
19410
+ await installRendererRpcSteeringDirect(renderer);
19411
+ return status;
19412
+ }
18406
19413
  };
18407
19414
  async function createRendererCdpControlSession(options) {
18408
19415
  const enabledAgents = options.enabledAgents;