@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.
- package/README.md +2 -2
- package/THIRD_PARTY_NOTICES.txt +6 -2
- package/app/codexhost-distribution.json +1 -1
- package/app/console-server.mjs +55 -20
- package/app/console-web.js +46 -18
- package/app/desktop-controller.mjs +982 -59
- package/app/host-runtime.mjs +3578 -1900
- package/app/plugins/antigravity/plugin.mjs +62 -9
- package/app/plugins/claude-code/plugin.mjs +12 -6
- package/app/plugins/codebuddy/plugin.mjs +10 -0
- package/app/plugins/cursor-cli/plugin.mjs +28 -8
- package/app/plugins/deepseek-harness/plugin.mjs +459 -46
- package/app/plugins/devin/assets/icon.svg +1 -0
- package/app/plugins/devin/manifest.json +30 -0
- package/app/plugins/devin/plugin.mjs +23363 -0
- package/app/plugins/enabled.json +2 -0
- package/app/plugins/grok/plugin.mjs +472 -391
- package/app/plugins/hermes/plugin.mjs +453 -196
- package/app/plugins/kimi-code/plugin.mjs +50 -3
- package/app/plugins/pi/plugin.mjs +1580 -411
- package/app/plugins/qoder/plugin.mjs +9524 -8654
- package/app/plugins/qoder-cn/plugin.mjs +9524 -8654
- package/app/plugins/qwen-code/assets/icon.svg +1 -0
- package/app/plugins/qwen-code/manifest.json +29 -0
- package/app/plugins/qwen-code/plugin.mjs +29298 -0
- package/app/plugins/workbuddy/plugin.mjs +10 -0
- package/app/plugins/zcode/plugin.mjs +142 -9
- package/app/renderer-extension.js +163 -55
- package/bin/codexhost +0 -0
- package/libexec/codexhost-shim +0 -0
- package/libexec/codexhost-updater +0 -0
- package/licenses/Qwen-Code-SDK-LICENSE.txt +203 -0
- package/package.json +2 -2
|
@@ -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
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 = () =>
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
17949
|
-
|
|
17950
|
-
|
|
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
|
-
|
|
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
|
-
|
|
18023
|
-
|
|
18024
|
-
|
|
18025
|
-
|
|
18026
|
-
|
|
18027
|
-
|
|
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
|
|
18042
|
-
|
|
18043
|
-
|
|
18044
|
-
if (uniqueId)
|
|
18045
|
-
|
|
18046
|
-
|
|
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)
|
|
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
|
|
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;
|