@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.
- package/README.md +1 -1
- package/app/codexhost-distribution.json +1 -1
- package/app/console-server.mjs +15 -0
- package/app/console-web.js +16 -1
- package/app/desktop-controller.mjs +1040 -33
- package/app/host-runtime.mjs +1104 -43
- package/app/plugins/antigravity/plugin.mjs +42 -7
- package/app/plugins/claude-code/plugin.mjs +15 -0
- package/app/plugins/codebuddy/plugin.mjs +15 -0
- package/app/plugins/codex-usage/plugin.mjs +15 -0
- package/app/plugins/copilot/plugin.mjs +15 -0
- package/app/plugins/cursor-cli/plugin.mjs +34 -3
- package/app/plugins/deepseek-harness/plugin.mjs +15 -0
- package/app/plugins/devin/plugin.mjs +15 -0
- package/app/plugins/grok/plugin.mjs +15 -0
- package/app/plugins/hermes/plugin.mjs +15 -0
- package/app/plugins/kimi-code/plugin.mjs +65 -3
- package/app/plugins/kiro-cli/plugin.mjs +15 -0
- package/app/plugins/omp/plugin.mjs +15 -0
- package/app/plugins/opencode/plugin.mjs +15 -0
- package/app/plugins/pi/plugin.mjs +223 -88
- package/app/plugins/qoder/plugin.mjs +15 -0
- package/app/plugins/qoder-cn/plugin.mjs +15 -0
- package/app/plugins/qwen-code/plugin.mjs +15 -0
- package/app/plugins/workbuddy/plugin.mjs +15 -0
- package/app/plugins/zcode/plugin.mjs +157 -9
- package/app/renderer-extension.js +559 -216
- package/bin/codexhost +0 -0
- package/libexec/codexhost-shim +0 -0
- package/libexec/codexhost-updater +0 -0
- package/package.json +1 -1
package/app/host-runtime.mjs
CHANGED
|
@@ -21005,6 +21005,22 @@ var threadSteeringInspectParamsSchema = external_exports.object({
|
|
|
21005
21005
|
text: external_exports.string().optional()
|
|
21006
21006
|
}).strict();
|
|
21007
21007
|
var THREAD_STEER_DELIVERY_PARAM = "codexhostSteerDelivery";
|
|
21008
|
+
var THREAD_STEERING_CONTEXT_PARAM = "codexhost_external_steering";
|
|
21009
|
+
var threadSteeringContextSchema = external_exports.object({
|
|
21010
|
+
kind: external_exports.literal("application"),
|
|
21011
|
+
value: external_exports.string().transform((text, context) => {
|
|
21012
|
+
try {
|
|
21013
|
+
return JSON.parse(text);
|
|
21014
|
+
} catch {
|
|
21015
|
+
context.addIssue({ code: "custom", message: "Invalid steering context JSON" });
|
|
21016
|
+
return external_exports.NEVER;
|
|
21017
|
+
}
|
|
21018
|
+
}).pipe(external_exports.object({
|
|
21019
|
+
expectedTurnId: hostTurnIdSchema,
|
|
21020
|
+
clientUserMessageId: external_exports.string().min(1),
|
|
21021
|
+
delivery: external_exports.enum(["newTurn", "activeTurn"])
|
|
21022
|
+
}).strict())
|
|
21023
|
+
}).strict().transform((context) => context.value);
|
|
21008
21024
|
var threadSteerDeliverySchema = external_exports.enum(["activeTurn", "newTurn"]);
|
|
21009
21025
|
var threadSteeringInspectResultSchema = external_exports.object({
|
|
21010
21026
|
delivery: external_exports.enum(["official", "activeTurn", "newTurn"])
|
|
@@ -22685,9 +22701,10 @@ function isolateRendererPrewarmConsumption(manager, discardExternal) {
|
|
|
22685
22701
|
}
|
|
22686
22702
|
|
|
22687
22703
|
// packages/desktop-control/dist/renderer-draft-prewarm-runtime.js
|
|
22688
|
-
function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewarmedThreadManager, isCurrentManager, retainResponses = retainRendererHostResponses, isolateConsumption = isolateRendererPrewarmConsumption) {
|
|
22704
|
+
function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewarmedThreadManager, isCurrentManager, retainResponses = retainRendererHostResponses, isolateConsumption = isolateRendererPrewarmConsumption, sendControlRequest) {
|
|
22689
22705
|
let disposed = false;
|
|
22690
22706
|
const originalSend = bridge.sendRequest;
|
|
22707
|
+
const controlSend = (method, parameters) => sendControlRequest ? sendControlRequest(method, parameters) : originalSend.call(bridge, method, parameters);
|
|
22691
22708
|
const originalPrewarm = bridge.prewarmThreadStart;
|
|
22692
22709
|
const originalOnNotification = manager.onNotification;
|
|
22693
22710
|
const originalDispatchAppServerResponse = manager.dispatchAppServerResponse;
|
|
@@ -22773,7 +22790,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
|
|
|
22773
22790
|
bridge.onError(requestId, error51);
|
|
22774
22791
|
bridgeRequests.clear();
|
|
22775
22792
|
if (isRemoteControlHost && terminate) {
|
|
22776
|
-
void Promise.resolve(
|
|
22793
|
+
void Promise.resolve(controlSend("process/kill", { processHandle: failedProcessHandle })).catch(() => void 0);
|
|
22777
22794
|
}
|
|
22778
22795
|
};
|
|
22779
22796
|
const resetFailedBridge = () => {
|
|
@@ -22936,7 +22953,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
|
|
|
22936
22953
|
];
|
|
22937
22954
|
const startedProcessHandle = bridgeProcessHandle;
|
|
22938
22955
|
try {
|
|
22939
|
-
const started =
|
|
22956
|
+
const started = controlSend("process/spawn", {
|
|
22940
22957
|
command,
|
|
22941
22958
|
processHandle: startedProcessHandle,
|
|
22942
22959
|
cwd: "C:\\",
|
|
@@ -22959,7 +22976,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
|
|
|
22959
22976
|
await startBridge();
|
|
22960
22977
|
if (bridgeState !== "ready")
|
|
22961
22978
|
throw transportError("is not ready");
|
|
22962
|
-
await
|
|
22979
|
+
await controlSend("process/writeStdin", {
|
|
22963
22980
|
processHandle: bridgeProcessHandle,
|
|
22964
22981
|
deltaBase64: utf8Base64(`${JSON.stringify(value2)}
|
|
22965
22982
|
`)
|
|
@@ -23240,7 +23257,7 @@ function createDraftPrewarmPolicyBridge(manager, bridge, hostId2, target, prewar
|
|
|
23240
23257
|
globalThis.clearTimeout(bridgeReadyTimeout);
|
|
23241
23258
|
bridgeReadyTimeout = null;
|
|
23242
23259
|
if (isRemoteControlHost && (bridgeState === "starting" || bridgeState === "ready")) {
|
|
23243
|
-
void Promise.resolve(
|
|
23260
|
+
void Promise.resolve(controlSend("process/kill", { processHandle: bridgeProcessHandle })).catch(() => void 0);
|
|
23244
23261
|
}
|
|
23245
23262
|
bridgeState = "disposed";
|
|
23246
23263
|
const disposedError = transportError("was disposed");
|
|
@@ -23342,11 +23359,12 @@ function resolveRendererHostManager(discovery, hostId2, managerFrom = requestMan
|
|
|
23342
23359
|
}
|
|
23343
23360
|
|
|
23344
23361
|
// packages/desktop-control/dist/renderer-host-routing.js
|
|
23345
|
-
function installRendererHostRouting(root, target, discover, resolve, createPolicy) {
|
|
23362
|
+
function installRendererHostRouting(root, target, discover, resolve, createPolicy, readConnection, publishRouting = true) {
|
|
23346
23363
|
const existing = target.__codexhostHostRoutingV1;
|
|
23347
|
-
if (existing)
|
|
23364
|
+
if (publishRouting && existing)
|
|
23348
23365
|
return existing;
|
|
23349
|
-
|
|
23366
|
+
if (publishRouting)
|
|
23367
|
+
target.__codexhostDraftPrewarmPolicyV1?.dispose?.();
|
|
23350
23368
|
let disposed = false;
|
|
23351
23369
|
let lastDiscovery = null;
|
|
23352
23370
|
const routes = /* @__PURE__ */ new Map();
|
|
@@ -23374,23 +23392,36 @@ function installRendererHostRouting(root, target, discover, resolve, createPolic
|
|
|
23374
23392
|
routes.delete(hostId2);
|
|
23375
23393
|
entry?.route.policy.dispose();
|
|
23376
23394
|
};
|
|
23395
|
+
const connectionFor = (hostId2) => {
|
|
23396
|
+
if (!hostId2.startsWith("remote-control:"))
|
|
23397
|
+
return void 0;
|
|
23398
|
+
try {
|
|
23399
|
+
return readConnection?.(hostId2);
|
|
23400
|
+
} catch {
|
|
23401
|
+
return null;
|
|
23402
|
+
}
|
|
23403
|
+
};
|
|
23404
|
+
const sameConnection = (expected, current) => expected === void 0 ? current === void 0 : current?.owner === expected.owner && current.revision === expected.revision;
|
|
23377
23405
|
const routeFor = (hostId2, discovery) => {
|
|
23378
23406
|
const manager = lookup(hostId2, discovery);
|
|
23407
|
+
const connection = connectionFor(hostId2);
|
|
23379
23408
|
const previous = routes.get(hostId2);
|
|
23380
|
-
if (manager && previous?.route.manager === manager && previous.bridge === manager.requestClient && previous.prewarmed === manager.prewarmedThreadManager && previous.route.policy.owns(manager, manager.requestClient, hostId2, manager.prewarmedThreadManager, true)) {
|
|
23409
|
+
if (manager && previous?.route.manager === manager && previous.bridge === manager.requestClient && previous.prewarmed === manager.prewarmedThreadManager && sameConnection(previous.connection, connection) && previous.route.policy.owns(manager, manager.requestClient, hostId2, manager.prewarmedThreadManager, true)) {
|
|
23381
23410
|
return previous.route;
|
|
23382
23411
|
}
|
|
23383
23412
|
retire(hostId2);
|
|
23384
|
-
if (!manager)
|
|
23413
|
+
if (!manager || connection === null)
|
|
23385
23414
|
return null;
|
|
23386
23415
|
const bridge = manager.requestClient;
|
|
23387
23416
|
const prewarmed = manager.prewarmedThreadManager;
|
|
23388
|
-
const policy = createPolicy(manager, bridge, hostId2, target, prewarmed, () => lookup(hostId2) === manager && manager.requestClient === bridge && manager.prewarmedThreadManager === prewarmed);
|
|
23417
|
+
const policy = createPolicy(manager, bridge, hostId2, target, prewarmed, () => lookup(hostId2) === manager && sameConnection(connection, connectionFor(hostId2)) && manager.requestClient === bridge && manager.prewarmedThreadManager === prewarmed);
|
|
23389
23418
|
const route = { hostId: hostId2, manager, policy };
|
|
23390
|
-
routes.set(hostId2, { route, bridge, prewarmed });
|
|
23419
|
+
routes.set(hostId2, { route, bridge, prewarmed, connection });
|
|
23391
23420
|
return route;
|
|
23392
23421
|
};
|
|
23393
23422
|
const publish = (route) => {
|
|
23423
|
+
if (!publishRouting)
|
|
23424
|
+
return;
|
|
23394
23425
|
const policy = route?.policy;
|
|
23395
23426
|
if (target.__codexhostDraftPrewarmPolicyV1 === policy)
|
|
23396
23427
|
return;
|
|
@@ -23444,7 +23475,7 @@ function installRendererHostRouting(root, target, discover, resolve, createPolic
|
|
|
23444
23475
|
if (!composer) {
|
|
23445
23476
|
for (const [hostId3, entry] of routes) {
|
|
23446
23477
|
const manager = lookup(hostId3, discovery);
|
|
23447
|
-
if (manager !== entry.route.manager || manager.requestClient !== entry.bridge || manager.prewarmedThreadManager !== entry.prewarmed)
|
|
23478
|
+
if (manager !== entry.route.manager || manager.requestClient !== entry.bridge || manager.prewarmedThreadManager !== entry.prewarmed || !sameConnection(entry.connection, connectionFor(hostId3)))
|
|
23448
23479
|
retire(hostId3);
|
|
23449
23480
|
}
|
|
23450
23481
|
}
|
|
@@ -23467,7 +23498,11 @@ function installRendererHostRouting(root, target, discover, resolve, createPolic
|
|
|
23467
23498
|
}
|
|
23468
23499
|
}
|
|
23469
23500
|
};
|
|
23470
|
-
|
|
23501
|
+
if (publishRouting)
|
|
23502
|
+
Object.defineProperty(target, "__codexhostHostRoutingV1", {
|
|
23503
|
+
configurable: true,
|
|
23504
|
+
value: routing
|
|
23505
|
+
});
|
|
23471
23506
|
return routing;
|
|
23472
23507
|
}
|
|
23473
23508
|
|
|
@@ -23522,7 +23557,9 @@ function findRendererHostRpcFamily(store) {
|
|
|
23522
23557
|
if (!record6(members) || typeof members.get !== "function")
|
|
23523
23558
|
continue;
|
|
23524
23559
|
for (const [hostId2, member] of members) {
|
|
23525
|
-
if (typeof hostId2 !== "string" ||
|
|
23560
|
+
if (typeof hostId2 !== "string" || !/^(?:local$|durable$|remote[-:])/u.test(hostId2))
|
|
23561
|
+
continue;
|
|
23562
|
+
if (!record6(member))
|
|
23526
23563
|
continue;
|
|
23527
23564
|
const signal = member.value;
|
|
23528
23565
|
if (!record6(signal) || typeof signal.get !== "function")
|
|
@@ -23569,19 +23606,43 @@ function installRendererHostRpcRouting(root, target, dependencies2) {
|
|
|
23569
23606
|
if (existing)
|
|
23570
23607
|
return existing;
|
|
23571
23608
|
let disposed = false;
|
|
23609
|
+
let nativeRouting = null;
|
|
23572
23610
|
let discovery = null;
|
|
23573
23611
|
const routes = /* @__PURE__ */ new Map();
|
|
23574
23612
|
const read = () => {
|
|
23575
23613
|
if (disposed)
|
|
23576
23614
|
return null;
|
|
23577
|
-
|
|
23615
|
+
try {
|
|
23578
23616
|
const store = dependencies2.findStore(root);
|
|
23579
|
-
|
|
23617
|
+
const bound = store && discovery?.store === store ? [...store.familyBindings.values()].includes(discovery.family) : false;
|
|
23618
|
+
if (!bound)
|
|
23619
|
+
discovery = store ? dependencies2.findFamily(store) : null;
|
|
23620
|
+
} catch {
|
|
23621
|
+
discovery = null;
|
|
23580
23622
|
}
|
|
23581
23623
|
return discovery;
|
|
23582
23624
|
};
|
|
23583
23625
|
if (!read())
|
|
23584
23626
|
return null;
|
|
23627
|
+
const native = () => {
|
|
23628
|
+
if (disposed)
|
|
23629
|
+
return null;
|
|
23630
|
+
try {
|
|
23631
|
+
nativeRouting ??= dependencies2.nativeRouting?.() ?? null;
|
|
23632
|
+
} catch {
|
|
23633
|
+
}
|
|
23634
|
+
return nativeRouting;
|
|
23635
|
+
};
|
|
23636
|
+
const connectionFor = (hostId2) => {
|
|
23637
|
+
if (!hostId2.startsWith("remote-control:"))
|
|
23638
|
+
return void 0;
|
|
23639
|
+
try {
|
|
23640
|
+
return dependencies2.readConnection?.(hostId2);
|
|
23641
|
+
} catch {
|
|
23642
|
+
return null;
|
|
23643
|
+
}
|
|
23644
|
+
};
|
|
23645
|
+
const sameConnection = (previous, current) => previous === void 0 ? current === void 0 : current?.owner === previous.owner && current.revision === previous.revision;
|
|
23585
23646
|
const isRecord19 = (value2) => typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
23586
23647
|
const externalDrafts = /* @__PURE__ */ new Map();
|
|
23587
23648
|
const selectedModels = /* @__PURE__ */ new Map();
|
|
@@ -23667,16 +23728,25 @@ function installRendererHostRpcRouting(root, target, dependencies2) {
|
|
|
23667
23728
|
const postMessage = function(message2, ...rest) {
|
|
23668
23729
|
let routed = message2;
|
|
23669
23730
|
try {
|
|
23670
|
-
routed = disposed ? message2 : routeCreationCall(message2);
|
|
23731
|
+
routed = disposed || routes.size === 0 ? message2 : routeCreationCall(message2);
|
|
23671
23732
|
} catch {
|
|
23672
23733
|
routed = message2;
|
|
23673
23734
|
}
|
|
23674
23735
|
return originalPostMessage.call(this, routed, ...rest);
|
|
23675
23736
|
};
|
|
23676
23737
|
port.postMessage = postMessage;
|
|
23677
|
-
const createRoute = (hostId2, rpc) => {
|
|
23738
|
+
const createRoute = (hostId2, rpc, connection) => {
|
|
23678
23739
|
let retired = false;
|
|
23679
|
-
const isCurrent = () =>
|
|
23740
|
+
const isCurrent = () => {
|
|
23741
|
+
if (retired || disposed || routes.get(hostId2)?.rpc !== rpc || !sameConnection(connection, connectionFor(hostId2)))
|
|
23742
|
+
return false;
|
|
23743
|
+
try {
|
|
23744
|
+
const current = read();
|
|
23745
|
+
return !!current && dependencies2.resolve(current, hostId2) === rpc;
|
|
23746
|
+
} catch {
|
|
23747
|
+
return false;
|
|
23748
|
+
}
|
|
23749
|
+
};
|
|
23680
23750
|
const manager = Object.freeze({
|
|
23681
23751
|
kind: "main-process-rpc",
|
|
23682
23752
|
getHostId: () => hostId2,
|
|
@@ -23759,17 +23829,25 @@ function installRendererHostRpcRouting(root, target, dependencies2) {
|
|
|
23759
23829
|
routes.delete(hostId2);
|
|
23760
23830
|
entry?.route.policy.dispose();
|
|
23761
23831
|
};
|
|
23762
|
-
const routeFor = (hostId2) => {
|
|
23832
|
+
const routeFor = (hostId2, nativeRoute) => {
|
|
23833
|
+
if (disposed)
|
|
23834
|
+
return null;
|
|
23835
|
+
const connection = connectionFor(hostId2);
|
|
23836
|
+
const preferred = nativeRoute === void 0 ? native()?.forHost(hostId2) : nativeRoute;
|
|
23837
|
+
if (connection === null || preferred) {
|
|
23838
|
+
retire(hostId2);
|
|
23839
|
+
return connection === null ? null : preferred ?? null;
|
|
23840
|
+
}
|
|
23763
23841
|
const current = read();
|
|
23764
23842
|
const rpc = current ? dependencies2.resolve(current, hostId2) : null;
|
|
23765
23843
|
const previous = routes.get(hostId2);
|
|
23766
|
-
if (rpc && previous?.rpc === rpc)
|
|
23844
|
+
if (rpc && previous?.rpc === rpc && sameConnection(previous.connection, connection))
|
|
23767
23845
|
return previous.route;
|
|
23768
23846
|
retire(hostId2);
|
|
23769
23847
|
if (!rpc)
|
|
23770
23848
|
return null;
|
|
23771
|
-
const route = createRoute(hostId2, rpc);
|
|
23772
|
-
routes.set(hostId2, { route, rpc });
|
|
23849
|
+
const route = createRoute(hostId2, rpc, connection);
|
|
23850
|
+
routes.set(hostId2, { route, rpc, connection });
|
|
23773
23851
|
return route;
|
|
23774
23852
|
};
|
|
23775
23853
|
const publish = (route) => {
|
|
@@ -23785,14 +23863,24 @@ function installRendererHostRpcRouting(root, target, dependencies2) {
|
|
|
23785
23863
|
}
|
|
23786
23864
|
};
|
|
23787
23865
|
const composerHostId = (composer) => {
|
|
23866
|
+
const nativeHostId = native()?.hostIdForComposer(composer);
|
|
23867
|
+
if (nativeHostId)
|
|
23868
|
+
return nativeHostId;
|
|
23788
23869
|
const hostIds = new Set(dependencies2.composerHostIds(composer).hostIds);
|
|
23789
23870
|
const hostId2 = hostIds.size === 1 ? hostIds.values().next().value : null;
|
|
23790
23871
|
return typeof hostId2 === "string" && hostId2 ? hostId2 : null;
|
|
23791
23872
|
};
|
|
23792
23873
|
const routing = {
|
|
23793
23874
|
knownHostIds() {
|
|
23875
|
+
if (disposed)
|
|
23876
|
+
return [];
|
|
23794
23877
|
const current = read();
|
|
23795
|
-
return
|
|
23878
|
+
return [
|
|
23879
|
+
.../* @__PURE__ */ new Set([
|
|
23880
|
+
...current ? dependencies2.hostIds(current) : [],
|
|
23881
|
+
...native()?.knownHostIds?.() ?? []
|
|
23882
|
+
])
|
|
23883
|
+
];
|
|
23796
23884
|
},
|
|
23797
23885
|
forHost(hostId2) {
|
|
23798
23886
|
return hostId2 && !disposed ? routeFor(hostId2) : null;
|
|
@@ -23810,12 +23898,14 @@ function installRendererHostRpcRouting(root, target, dependencies2) {
|
|
|
23810
23898
|
if (disposed)
|
|
23811
23899
|
return null;
|
|
23812
23900
|
let hostId2;
|
|
23901
|
+
let preferred = null;
|
|
23813
23902
|
try {
|
|
23814
|
-
|
|
23903
|
+
preferred = native()?.forComposer(composer) ?? null;
|
|
23904
|
+
hostId2 = preferred?.hostId ?? composerHostId(composer);
|
|
23815
23905
|
} catch {
|
|
23816
23906
|
hostId2 = null;
|
|
23817
23907
|
}
|
|
23818
|
-
const route = hostId2 ? routeFor(hostId2) : null;
|
|
23908
|
+
const route = hostId2 ? routeFor(hostId2, preferred) : null;
|
|
23819
23909
|
if (!composer)
|
|
23820
23910
|
publish(route);
|
|
23821
23911
|
return route;
|
|
@@ -23824,6 +23914,8 @@ function installRendererHostRpcRouting(root, target, dependencies2) {
|
|
|
23824
23914
|
if (disposed)
|
|
23825
23915
|
return;
|
|
23826
23916
|
disposed = true;
|
|
23917
|
+
nativeRouting?.dispose();
|
|
23918
|
+
nativeRouting = null;
|
|
23827
23919
|
for (const hostId2 of [...routes.keys()])
|
|
23828
23920
|
retire(hostId2);
|
|
23829
23921
|
discovery = null;
|
|
@@ -23841,6 +23933,34 @@ function installRendererHostRpcRouting(root, target, dependencies2) {
|
|
|
23841
23933
|
return routing;
|
|
23842
23934
|
}
|
|
23843
23935
|
|
|
23936
|
+
// packages/desktop-control/dist/renderer-connection-generation.js
|
|
23937
|
+
function readRendererConnectionGeneration(store, hostId2) {
|
|
23938
|
+
if (!store)
|
|
23939
|
+
return void 0;
|
|
23940
|
+
const record6 = (value2) => value2 !== null && typeof value2 === "object";
|
|
23941
|
+
const candidates = /* @__PURE__ */ new Set();
|
|
23942
|
+
for (const members of store.familyBindings.values()) {
|
|
23943
|
+
const value2 = members.get(hostId2)?.value;
|
|
23944
|
+
if (record6(value2) && record6(value2.state$) && record6(value2.revision$) && record6(value2.appServerVersion$) && typeof value2.state$.get === "function" && typeof value2.revision$.get === "function")
|
|
23945
|
+
candidates.add(value2);
|
|
23946
|
+
}
|
|
23947
|
+
if (!candidates.size)
|
|
23948
|
+
return void 0;
|
|
23949
|
+
if (candidates.size !== 1)
|
|
23950
|
+
return null;
|
|
23951
|
+
const owner = candidates.values().next().value;
|
|
23952
|
+
if (!owner)
|
|
23953
|
+
return null;
|
|
23954
|
+
const state = owner.state$;
|
|
23955
|
+
const revision = owner.revision$;
|
|
23956
|
+
try {
|
|
23957
|
+
const current = revision.get();
|
|
23958
|
+
return state.get() === "connected" && typeof current === "number" && Number.isSafeInteger(current) ? { owner, revision: current } : null;
|
|
23959
|
+
} catch {
|
|
23960
|
+
return null;
|
|
23961
|
+
}
|
|
23962
|
+
}
|
|
23963
|
+
|
|
23844
23964
|
// packages/desktop-control/dist/renderer-draft-prewarm-policy.js
|
|
23845
23965
|
var REQUEST_MANAGER_WAIT_TIMEOUT_MS = 6e4;
|
|
23846
23966
|
var REQUEST_MANAGER_POLL_INTERVAL_MS = 25;
|
|
@@ -23853,15 +23973,19 @@ function directRendererInstaller() {
|
|
|
23853
23973
|
const retainRendererHostResponses = ${retainRendererHostResponses.toString()};
|
|
23854
23974
|
const createDraftPrewarmPolicyBridge = ${createDraftPrewarmPolicyBridge.toString()};
|
|
23855
23975
|
const isolateRendererPrewarmConsumption = ${isolateRendererPrewarmConsumption.toString()};
|
|
23976
|
+
const findRendererAppScopeStore = ${findRendererAppScopeStore.toString()};
|
|
23977
|
+
const readRendererConnectionGeneration = ${readRendererConnectionGeneration.toString()};
|
|
23856
23978
|
const discover = (root) =>
|
|
23857
23979
|
discoverRendererHosts(root, committedReactAncestors, requestManagerFromHookState);
|
|
23858
|
-
const installNative = () => (${installRendererHostRouting.toString()})(
|
|
23980
|
+
const installNative = (publishRouting = true) => (${installRendererHostRouting.toString()})(
|
|
23859
23981
|
document, window, discover,
|
|
23860
23982
|
(discovery, hostId) => resolveRendererHostManager(discovery, hostId, requestManagerFromHookState),
|
|
23861
23983
|
(manager, bridge, hostId, target, prewarmed, isCurrent) => createDraftPrewarmPolicyBridge(
|
|
23862
23984
|
manager, bridge, hostId, target, prewarmed, isCurrent, retainRendererHostResponses,
|
|
23863
23985
|
isolateRendererPrewarmConsumption,
|
|
23864
23986
|
),
|
|
23987
|
+
(hostId) => readRendererConnectionGeneration(findRendererAppScopeStore(document), hostId),
|
|
23988
|
+
publishRouting,
|
|
23865
23989
|
);
|
|
23866
23990
|
const installRpc = () => typeof MessagePort !== 'function' ? null : (${installRendererHostRpcRouting.toString()})(document, window, {
|
|
23867
23991
|
findStore: ${findRendererAppScopeStore.toString()},
|
|
@@ -23875,14 +23999,21 @@ function directRendererInstaller() {
|
|
|
23875
23999
|
return discover(source);
|
|
23876
24000
|
},
|
|
23877
24001
|
portPrototype: MessagePort.prototype,
|
|
24002
|
+
nativeRouting: () => {
|
|
24003
|
+
const native = discover(document);
|
|
24004
|
+
return native.managers.length || native.registries.length ? installNative(false) : null;
|
|
24005
|
+
},
|
|
24006
|
+
readConnection: (hostId) => readRendererConnectionGeneration(findRendererAppScopeStore(document), hostId),
|
|
23878
24007
|
});
|
|
23879
24008
|
const connected = (routing) => routing.forComposer() !== null ||
|
|
23880
24009
|
['local', ...(routing.knownHostIds?.() ?? [])].some((hostId) => routing.forHost(hostId) !== null);
|
|
23881
24010
|
let nativeReady = false;
|
|
23882
|
-
//
|
|
23883
|
-
//
|
|
24011
|
+
// Mixed layouts can expose native managers for only some Hosts. Keep one
|
|
24012
|
+
// router that selects a native owner or the current ready RPC peer per Host.
|
|
23884
24013
|
const routing = (() => {
|
|
23885
24014
|
if (window.__codexhostHostRoutingV1) return window.__codexhostHostRoutingV1;
|
|
24015
|
+
const rpc = installRpc();
|
|
24016
|
+
if (rpc) return rpc;
|
|
23886
24017
|
const native = discover(document);
|
|
23887
24018
|
if (native.managers.length || native.registries.length) {
|
|
23888
24019
|
const routing = installNative();
|
|
@@ -23892,8 +24023,6 @@ function directRendererInstaller() {
|
|
|
23892
24023
|
}
|
|
23893
24024
|
routing.dispose();
|
|
23894
24025
|
}
|
|
23895
|
-
const rpc = installRpc();
|
|
23896
|
-
if (rpc) return rpc;
|
|
23897
24026
|
throw new Error('Renderer Host request manager is unavailable');
|
|
23898
24027
|
})();
|
|
23899
24028
|
// Publish a default draft policy only when its Host is unambiguous. Host
|
|
@@ -24062,6 +24191,873 @@ async function installRendererLoadedModules(renderer) {
|
|
|
24062
24191
|
}
|
|
24063
24192
|
}
|
|
24064
24193
|
|
|
24194
|
+
// packages/desktop-control/dist/renderer-native-rpc-discovery.js
|
|
24195
|
+
function nativeManagerDependencies(factoryName, callers) {
|
|
24196
|
+
const identifier = "[$A-Z_a-z][$\\w]*";
|
|
24197
|
+
const escaped = factoryName.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
|
|
24198
|
+
const pattern = new RegExp(`${escaped}\\((${identifier}),(${identifier}),\\1\\.get\\((${identifier}),\\2\\),(${identifier})\\.bind\\(null,\\1\\),\\((${identifier}),(${identifier})\\)=>\\5\\((${identifier}),\\6\\)\\)`);
|
|
24199
|
+
const matches = callers.flatMap((source) => {
|
|
24200
|
+
const match = pattern.exec(source);
|
|
24201
|
+
return match?.[3] && match[4] && match[7] ? [
|
|
24202
|
+
{
|
|
24203
|
+
requestDefinition: match[3],
|
|
24204
|
+
isHostForConversation: match[4],
|
|
24205
|
+
imageDefinition: match[7]
|
|
24206
|
+
}
|
|
24207
|
+
] : [];
|
|
24208
|
+
});
|
|
24209
|
+
return matches.length === 1 ? matches[0] : void 0;
|
|
24210
|
+
}
|
|
24211
|
+
function nativeRpcRole(source) {
|
|
24212
|
+
if (["dispatchMessageFromView", "threadProjectAssignments", "queuedMessageCoordination"].every((part) => source.includes(part)))
|
|
24213
|
+
return "createManager";
|
|
24214
|
+
if (["collectAppStateSnapshot", "getReviewPaneSnapshotMetrics", "registerReplayAdmission"].every((part) => source.includes(part)))
|
|
24215
|
+
return "createController";
|
|
24216
|
+
if (["getWorkInProgress", "getCachedThreadSearchSnapshot", "registerReplayAdmission"].every((part) => source.includes(part)))
|
|
24217
|
+
return "RpcManager";
|
|
24218
|
+
if (["prewarmedThreadManager", "onNotification", "dispatchAppServerResponse"].every((part) => source.includes(part)))
|
|
24219
|
+
return "Manager";
|
|
24220
|
+
return void 0;
|
|
24221
|
+
}
|
|
24222
|
+
function nativeRpcObjectShape(value2) {
|
|
24223
|
+
if (value2 === null || typeof value2 !== "object")
|
|
24224
|
+
return { scope: false, services: false, controller: false };
|
|
24225
|
+
const candidate = value2;
|
|
24226
|
+
const own = (keys) => keys.every((key) => Object.hasOwn(candidate, key));
|
|
24227
|
+
const methods = (keys) => keys.every((key) => typeof candidate[key] === "function");
|
|
24228
|
+
return {
|
|
24229
|
+
scope: own(["node", "scope", "get", "set", "watch"]) && methods(["get", "set", "watch"]),
|
|
24230
|
+
services: own(["appServerManagers", "remoteConnections", "applicationMenu"]) && typeof candidate.appServerManagers?.subscribe === "function",
|
|
24231
|
+
controller: own(["forHost", "collectAppStateSnapshot", "getReviewPaneSnapshotMetrics", "dispose"]) && methods(["forHost", "collectAppStateSnapshot", "getReviewPaneSnapshotMetrics", "dispose"])
|
|
24232
|
+
};
|
|
24233
|
+
}
|
|
24234
|
+
async function withNativeRpcComponents(client, install) {
|
|
24235
|
+
const group = `codexhost-native-rpc-${crypto.randomUUID()}`;
|
|
24236
|
+
const command = async (method, params) => client.command(method, params);
|
|
24237
|
+
const evaluate = (expression) => command("Runtime.evaluate", { expression, awaitPromise: true, objectGroup: group });
|
|
24238
|
+
const properties = (objectId) => command("Runtime.getProperties", { objectId, ownProperties: true });
|
|
24239
|
+
const call = (objectId, functionDeclaration, args = []) => command("Runtime.callFunctionOn", {
|
|
24240
|
+
objectId,
|
|
24241
|
+
functionDeclaration,
|
|
24242
|
+
arguments: args,
|
|
24243
|
+
objectGroup: group,
|
|
24244
|
+
returnByValue: true
|
|
24245
|
+
});
|
|
24246
|
+
try {
|
|
24247
|
+
const initial = await evaluate(String.raw`(() => {
|
|
24248
|
+
const catalog = globalThis.__codexhostLoadedModulesV1;
|
|
24249
|
+
if (!catalog?.complete || catalog.documentUrl !== location.href) return null;
|
|
24250
|
+
const urls = catalog.urls.filter(url => /^app:\/\/-\/assets\/(?:renderer-app-server-managers|app-shared)-[^/]+\.js$/.test(url));
|
|
24251
|
+
return { document, urls };
|
|
24252
|
+
})()`);
|
|
24253
|
+
if (!initial.result.objectId)
|
|
24254
|
+
return false;
|
|
24255
|
+
const holder = initial.result.objectId;
|
|
24256
|
+
const catalog = await call(holder, "function(){return this.urls}");
|
|
24257
|
+
const urls = catalog.result.value;
|
|
24258
|
+
if (!Array.isArray(urls) || urls.length !== 2)
|
|
24259
|
+
return false;
|
|
24260
|
+
const managerUrl = urls.find((url2) => url2.includes("renderer-app-server-managers"));
|
|
24261
|
+
const sharedUrl = urls.find((url2) => url2.includes("app-shared"));
|
|
24262
|
+
if (!managerUrl || !sharedUrl)
|
|
24263
|
+
return false;
|
|
24264
|
+
const attach = async (name, objectId) => {
|
|
24265
|
+
const result = await call(holder, "function(name,value){if(this.document!==document)throw Error('Renderer Realm changed');this[name]=value;return true}", [{ value: name }, { objectId }]);
|
|
24266
|
+
if (result.exceptionDetails)
|
|
24267
|
+
throw new Error("Native RPC discovery lost its Renderer Realm");
|
|
24268
|
+
};
|
|
24269
|
+
const imported = await evaluate(`import(${JSON.stringify(managerUrl)})`);
|
|
24270
|
+
if (!imported.result.objectId)
|
|
24271
|
+
return false;
|
|
24272
|
+
const exports = (await properties(imported.result.objectId)).result.filter((entry) => entry.value?.type === "function");
|
|
24273
|
+
let bindings = [];
|
|
24274
|
+
for (const entry of exports.slice(0, 3)) {
|
|
24275
|
+
if (!entry.value?.objectId)
|
|
24276
|
+
continue;
|
|
24277
|
+
const scopes = (await properties(entry.value.objectId)).internalProperties?.find((entry2) => entry2.name === "[[Scopes]]")?.value?.objectId;
|
|
24278
|
+
if (!scopes)
|
|
24279
|
+
continue;
|
|
24280
|
+
const modules = (await properties(scopes)).result.filter((entry2) => entry2.value?.description?.startsWith("Module") && entry2.value.objectId);
|
|
24281
|
+
const moduleId = modules[0]?.value?.objectId;
|
|
24282
|
+
if (modules.length !== 1 || !moduleId)
|
|
24283
|
+
continue;
|
|
24284
|
+
bindings = (await properties(moduleId)).result;
|
|
24285
|
+
break;
|
|
24286
|
+
}
|
|
24287
|
+
const functions = bindings.filter((entry) => entry.value?.type === "function");
|
|
24288
|
+
const roles = /* @__PURE__ */ new Map();
|
|
24289
|
+
for (const entry of functions) {
|
|
24290
|
+
const role = nativeRpcRole(entry.value?.description ?? "");
|
|
24291
|
+
if (role)
|
|
24292
|
+
roles.set(role, [...roles.get(role) ?? [], entry]);
|
|
24293
|
+
}
|
|
24294
|
+
if (["createManager", "Manager", "RpcManager", "createController"].some((role) => roles.get(role)?.length !== 1))
|
|
24295
|
+
return false;
|
|
24296
|
+
const factory = roles.get("createManager")?.[0];
|
|
24297
|
+
if (!factory)
|
|
24298
|
+
return false;
|
|
24299
|
+
const dependencies2 = nativeManagerDependencies(factory.name, functions.map((entry) => entry.value?.description ?? ""));
|
|
24300
|
+
if (!dependencies2)
|
|
24301
|
+
return false;
|
|
24302
|
+
for (const [role, entries] of roles) {
|
|
24303
|
+
const id2 = entries[0]?.value?.objectId;
|
|
24304
|
+
if (!id2)
|
|
24305
|
+
return false;
|
|
24306
|
+
await attach(role, id2);
|
|
24307
|
+
}
|
|
24308
|
+
for (const [role, name] of Object.entries(dependencies2)) {
|
|
24309
|
+
const value2 = bindings.find((entry) => entry.name === name)?.value?.objectId;
|
|
24310
|
+
if (!value2)
|
|
24311
|
+
return false;
|
|
24312
|
+
await attach(role, value2);
|
|
24313
|
+
}
|
|
24314
|
+
const shared = await evaluate(`import(${JSON.stringify(sharedUrl)})`);
|
|
24315
|
+
if (!shared.result.objectId)
|
|
24316
|
+
return false;
|
|
24317
|
+
const sharedExports = (await properties(shared.result.objectId)).result;
|
|
24318
|
+
const sessions = sharedExports.filter((entry) => entry.value?.type === "function" && ["getRemoteMain", "getStats", "drain", "getMainImport"].every((word) => entry.value?.description?.includes(word)));
|
|
24319
|
+
const sessionId = sessions[0]?.value?.objectId;
|
|
24320
|
+
if (sessions.length !== 1 || !sessionId)
|
|
24321
|
+
return false;
|
|
24322
|
+
await attach("RpcSession", sessionId);
|
|
24323
|
+
const serviceMatches = await command("Runtime.callFunctionOn", {
|
|
24324
|
+
objectId: shared.result.objectId,
|
|
24325
|
+
functionDeclaration: `function(){return [...new Set(Object.values(this).filter(value => (${nativeRpcObjectShape.toString()})(value).services))]}`,
|
|
24326
|
+
objectGroup: group
|
|
24327
|
+
});
|
|
24328
|
+
if (!serviceMatches.result.objectId)
|
|
24329
|
+
return false;
|
|
24330
|
+
const services = (await properties(serviceMatches.result.objectId)).result.flatMap((entry) => entry.value?.type === "object" && entry.value.objectId ? [entry.value.objectId] : []);
|
|
24331
|
+
const serviceId = services[0];
|
|
24332
|
+
if (services.length !== 1 || !serviceId)
|
|
24333
|
+
return false;
|
|
24334
|
+
await attach("services", serviceId);
|
|
24335
|
+
const prototype = await evaluate("Object.getPrototypeOf(async function(){})");
|
|
24336
|
+
if (!prototype.result.objectId)
|
|
24337
|
+
return false;
|
|
24338
|
+
const objects = await command("Runtime.queryObjects", {
|
|
24339
|
+
prototypeObjectId: prototype.result.objectId,
|
|
24340
|
+
objectGroup: group
|
|
24341
|
+
});
|
|
24342
|
+
if (!objects.objects.objectId)
|
|
24343
|
+
return false;
|
|
24344
|
+
const filtered = await command("Runtime.callFunctionOn", {
|
|
24345
|
+
objectId: objects.objects.objectId,
|
|
24346
|
+
functionDeclaration: 'function(){return this.filter(fn=>fn.name==="collectAppStateSnapshot"&&String(fn).includes("collectSnapshot")).slice(0,9)}',
|
|
24347
|
+
objectGroup: group
|
|
24348
|
+
});
|
|
24349
|
+
if (!filtered.result.objectId)
|
|
24350
|
+
return false;
|
|
24351
|
+
const snapshots = (await properties(filtered.result.objectId)).result.filter((entry) => entry.value?.type === "function");
|
|
24352
|
+
if (snapshots.length > 8)
|
|
24353
|
+
return false;
|
|
24354
|
+
const owners = [];
|
|
24355
|
+
for (const snapshot2 of snapshots) {
|
|
24356
|
+
const fn = snapshot2.value?.objectId;
|
|
24357
|
+
if (!fn)
|
|
24358
|
+
continue;
|
|
24359
|
+
const scopes = (await properties(fn)).internalProperties?.find((entry) => entry.name === "[[Scopes]]")?.value?.objectId;
|
|
24360
|
+
if (!scopes)
|
|
24361
|
+
continue;
|
|
24362
|
+
for (const scope of (await properties(scopes)).result) {
|
|
24363
|
+
if (!scope.value?.description?.startsWith("Closure") || !scope.value.objectId)
|
|
24364
|
+
continue;
|
|
24365
|
+
const candidates = (await properties(scope.value.objectId)).result;
|
|
24366
|
+
const controllers = [], handles = [];
|
|
24367
|
+
for (const binding of candidates) {
|
|
24368
|
+
if (binding.value?.type !== "object" || !binding.value.objectId)
|
|
24369
|
+
continue;
|
|
24370
|
+
const id2 = binding.value.objectId;
|
|
24371
|
+
const response = await call(id2, `function(){return (${nativeRpcObjectShape.toString()})(this)}`);
|
|
24372
|
+
const shape = response.result.value;
|
|
24373
|
+
if (shape?.scope)
|
|
24374
|
+
handles.push(id2);
|
|
24375
|
+
if (shape?.controller && (await call(id2, "function(fn){return this.collectAppStateSnapshot===fn}", [
|
|
24376
|
+
{ objectId: fn }
|
|
24377
|
+
])).result.value === true)
|
|
24378
|
+
controllers.push(id2);
|
|
24379
|
+
}
|
|
24380
|
+
const controller = controllers[0], handle = handles[0];
|
|
24381
|
+
if (controllers.length === 1 && handles.length === 1 && controller && handle)
|
|
24382
|
+
owners.push({ controller, scope: handle });
|
|
24383
|
+
}
|
|
24384
|
+
}
|
|
24385
|
+
const owner = owners[0];
|
|
24386
|
+
if (owners.length !== 1 || !owner)
|
|
24387
|
+
return false;
|
|
24388
|
+
await attach("controller", owner.controller);
|
|
24389
|
+
await attach("scope", owner.scope);
|
|
24390
|
+
return await install(holder);
|
|
24391
|
+
} finally {
|
|
24392
|
+
await client.command("Runtime.releaseObjectGroup", { objectGroup: group }).catch(() => void 0);
|
|
24393
|
+
}
|
|
24394
|
+
}
|
|
24395
|
+
|
|
24396
|
+
// packages/desktop-control/dist/renderer-native-rpc-runtime.js
|
|
24397
|
+
function installNativeRpcRemoteControl(components, target, dependencies2) {
|
|
24398
|
+
if (target.__codexhostNativeRpcRemoteControlV1)
|
|
24399
|
+
return true;
|
|
24400
|
+
const routing = target.__codexhostHostRoutingV1;
|
|
24401
|
+
if (!routing)
|
|
24402
|
+
return false;
|
|
24403
|
+
const adapted = dependencies2.createService(components, (hostId2, upstream) => dependencies2.createManager(components, hostId2, upstream, target, dependencies2.createPolicy, dependencies2.createChannel, dependencies2.retainInteractions));
|
|
24404
|
+
const controller = components.controller;
|
|
24405
|
+
const originalHost = routing.forHost, originalComposer = routing.forComposer, originalDispose = routing.dispose;
|
|
24406
|
+
controller.dispose();
|
|
24407
|
+
let replacement;
|
|
24408
|
+
try {
|
|
24409
|
+
replacement = components.createController(components.scope, adapted.service);
|
|
24410
|
+
} catch (error51) {
|
|
24411
|
+
replacement = components.createController(components.scope, components.services.appServerManagers);
|
|
24412
|
+
throw error51;
|
|
24413
|
+
} finally {
|
|
24414
|
+
adapted.service[Symbol.dispose]();
|
|
24415
|
+
controller.forHost = (hostId2) => replacement.forHost(hostId2);
|
|
24416
|
+
controller.collectAppStateSnapshot = (hostId2, options) => replacement.collectAppStateSnapshot(hostId2, options);
|
|
24417
|
+
controller.getReviewPaneSnapshotMetrics = (hostId2) => replacement.getReviewPaneSnapshotMetrics(hostId2);
|
|
24418
|
+
controller.dispose = () => replacement.dispose();
|
|
24419
|
+
}
|
|
24420
|
+
const forHost = (hostId2) => {
|
|
24421
|
+
const route = adapted.route(hostId2);
|
|
24422
|
+
return route === void 0 ? originalHost.call(routing, hostId2) : route;
|
|
24423
|
+
};
|
|
24424
|
+
const forComposer = (composer) => {
|
|
24425
|
+
const hostId2 = routing.hostIdForComposer(composer);
|
|
24426
|
+
return hostId2 ? forHost(hostId2) : originalComposer.call(routing, composer);
|
|
24427
|
+
};
|
|
24428
|
+
routing.forHost = forHost;
|
|
24429
|
+
routing.forComposer = forComposer;
|
|
24430
|
+
const installation2 = {
|
|
24431
|
+
dispose() {
|
|
24432
|
+
if (target.__codexhostNativeRpcRemoteControlV1 !== installation2)
|
|
24433
|
+
return;
|
|
24434
|
+
delete target.__codexhostNativeRpcRemoteControlV1;
|
|
24435
|
+
replacement.dispose();
|
|
24436
|
+
replacement = components.createController(components.scope, components.services.appServerManagers);
|
|
24437
|
+
if (routing.forHost === forHost)
|
|
24438
|
+
routing.forHost = originalHost;
|
|
24439
|
+
if (routing.forComposer === forComposer)
|
|
24440
|
+
routing.forComposer = originalComposer;
|
|
24441
|
+
routing.dispose = originalDispose;
|
|
24442
|
+
}
|
|
24443
|
+
};
|
|
24444
|
+
routing.dispose = () => {
|
|
24445
|
+
installation2.dispose();
|
|
24446
|
+
originalDispose.call(routing);
|
|
24447
|
+
};
|
|
24448
|
+
target.__codexhostNativeRpcRemoteControlV1 = installation2;
|
|
24449
|
+
return true;
|
|
24450
|
+
}
|
|
24451
|
+
|
|
24452
|
+
// packages/desktop-control/dist/renderer-native-remote-manager.js
|
|
24453
|
+
function createNativeRemoteManager(components, hostId2, original, target, createPolicy, createChannel, retainInteractions) {
|
|
24454
|
+
const source = components.scope.get(components.requestDefinition, hostId2);
|
|
24455
|
+
const upstream = original.dup();
|
|
24456
|
+
let manager;
|
|
24457
|
+
let policy;
|
|
24458
|
+
let interactions;
|
|
24459
|
+
let disposed = false;
|
|
24460
|
+
const pending = /* @__PURE__ */ new Set();
|
|
24461
|
+
const send = (method, params, options) => {
|
|
24462
|
+
const request = upstream.sendRequest(method, params, options);
|
|
24463
|
+
const result = Promise.resolve(request).finally(() => {
|
|
24464
|
+
request[Symbol.dispose]();
|
|
24465
|
+
pending.delete(result);
|
|
24466
|
+
});
|
|
24467
|
+
pending.add(result);
|
|
24468
|
+
return result;
|
|
24469
|
+
};
|
|
24470
|
+
const record6 = (value2) => value2 !== null && typeof value2 === "object";
|
|
24471
|
+
const dispatch = (type, payload) => {
|
|
24472
|
+
if ((type === "mcp-request" || type === "thread-prewarm-start") && record6(payload) && record6(payload.request)) {
|
|
24473
|
+
const request = payload.request;
|
|
24474
|
+
const options = {};
|
|
24475
|
+
for (const key of ["priority", "timeoutMs", "source", "trace", "threadAccess"])
|
|
24476
|
+
if (payload[key] !== void 0)
|
|
24477
|
+
options[key] = payload[key];
|
|
24478
|
+
void send(String(request.method), request.params, options).then((result) => {
|
|
24479
|
+
if (!disposed)
|
|
24480
|
+
client.onResult(request.id, result);
|
|
24481
|
+
}, (error51) => {
|
|
24482
|
+
if (!disposed)
|
|
24483
|
+
client.onError(request.id, {
|
|
24484
|
+
code: record6(error51) ? error51.jsonRpcCode ?? error51.code ?? -32603 : -32603,
|
|
24485
|
+
message: error51 instanceof Error ? error51.message : String(error51)
|
|
24486
|
+
});
|
|
24487
|
+
});
|
|
24488
|
+
return;
|
|
24489
|
+
}
|
|
24490
|
+
return source.dispatchMessage(type, payload);
|
|
24491
|
+
};
|
|
24492
|
+
const Constructor = source.constructor;
|
|
24493
|
+
let client;
|
|
24494
|
+
try {
|
|
24495
|
+
client = new Constructor(hostId2, dispatch, false, (id2) => manager?.getConversation(id2)?.threadAccess);
|
|
24496
|
+
client.setAppServerVersion(source.getAppServerVersion());
|
|
24497
|
+
manager = components.createManager(components.scope, hostId2, client, components.isHostForConversation.bind(null, components.scope), (get, id2) => get(components.imageDefinition, id2), { dispatchMessageFromView: dispatch });
|
|
24498
|
+
manager.dispatchAppServerResponse = manager.sendAppServerResponse;
|
|
24499
|
+
const owned = manager;
|
|
24500
|
+
const ownedPolicy = createPolicy(owned, client, hostId2, target, owned.prewarmedThreadManager, () => !disposed, void 0, void 0, (method, params) => send(method, params, { priority: "critical" }));
|
|
24501
|
+
policy = ownedPolicy;
|
|
24502
|
+
owned.sendAppServerResponse = (...args) => owned.dispatchAppServerResponse(...args);
|
|
24503
|
+
const channel = createChannel(components, owned);
|
|
24504
|
+
const nativeInteractions = retainInteractions(upstream, owned, hostId2);
|
|
24505
|
+
interactions = nativeInteractions;
|
|
24506
|
+
const notify = (event) => {
|
|
24507
|
+
const { data, source: source2, origin } = event;
|
|
24508
|
+
if (disposed || source2 != null && source2 !== target || !record6(data) || data.hostId !== hostId2)
|
|
24509
|
+
return;
|
|
24510
|
+
const ownOrigin = record6(target.location) ? target.location.origin : void 0;
|
|
24511
|
+
if (source2 === target && ownOrigin && ownOrigin !== "null" && origin !== ownOrigin)
|
|
24512
|
+
return;
|
|
24513
|
+
if (data.type === "mcp-notification" && typeof data.method === "string" && !data.method.startsWith("process/"))
|
|
24514
|
+
owned.onNotification(data.method, data.params);
|
|
24515
|
+
if (data.type === "mcp-request")
|
|
24516
|
+
owned.onRequest(record6(data.request) ? data.request : data);
|
|
24517
|
+
};
|
|
24518
|
+
target.addEventListener?.("message", notify);
|
|
24519
|
+
return {
|
|
24520
|
+
route: { hostId: hostId2, manager: owned, policy: ownedPolicy },
|
|
24521
|
+
rpc: channel.rpc,
|
|
24522
|
+
ready: nativeInteractions.ready,
|
|
24523
|
+
dispose() {
|
|
24524
|
+
if (disposed)
|
|
24525
|
+
return;
|
|
24526
|
+
disposed = true;
|
|
24527
|
+
target.removeEventListener?.("message", notify);
|
|
24528
|
+
nativeInteractions.dispose();
|
|
24529
|
+
ownedPolicy.dispose();
|
|
24530
|
+
client.queuedRequests.length = 0;
|
|
24531
|
+
for (const id2 of [...client.requestPromises.keys()])
|
|
24532
|
+
client.onError(id2, new Error("Remote Control connection retired"));
|
|
24533
|
+
channel.dispose();
|
|
24534
|
+
components.Manager.dispose(owned);
|
|
24535
|
+
void Promise.allSettled([...pending]).then(() => upstream[Symbol.dispose]());
|
|
24536
|
+
}
|
|
24537
|
+
};
|
|
24538
|
+
} catch (error51) {
|
|
24539
|
+
interactions?.dispose();
|
|
24540
|
+
policy?.dispose();
|
|
24541
|
+
if (manager)
|
|
24542
|
+
components.Manager.dispose(manager);
|
|
24543
|
+
upstream[Symbol.dispose]();
|
|
24544
|
+
throw error51;
|
|
24545
|
+
}
|
|
24546
|
+
}
|
|
24547
|
+
|
|
24548
|
+
// packages/desktop-control/dist/renderer-native-rpc-channel.js
|
|
24549
|
+
function createNativeRpcChannel(components, manager) {
|
|
24550
|
+
const channel = new MessageChannel();
|
|
24551
|
+
const transports = [];
|
|
24552
|
+
const transport = (port) => {
|
|
24553
|
+
const values = [];
|
|
24554
|
+
const readers = [];
|
|
24555
|
+
let closed = false;
|
|
24556
|
+
let failure;
|
|
24557
|
+
port.addEventListener("message", (event) => {
|
|
24558
|
+
const value2 = JSON.stringify(event.data);
|
|
24559
|
+
const reader = readers.shift();
|
|
24560
|
+
if (reader)
|
|
24561
|
+
reader.resolve(value2);
|
|
24562
|
+
else
|
|
24563
|
+
values.push(value2);
|
|
24564
|
+
});
|
|
24565
|
+
port.start();
|
|
24566
|
+
const result = {
|
|
24567
|
+
send(message2) {
|
|
24568
|
+
if (closed)
|
|
24569
|
+
throw failure;
|
|
24570
|
+
port.postMessage(JSON.parse(message2));
|
|
24571
|
+
},
|
|
24572
|
+
receive() {
|
|
24573
|
+
if (closed)
|
|
24574
|
+
return Promise.reject(failure);
|
|
24575
|
+
const value2 = values.shift();
|
|
24576
|
+
return value2 !== void 0 ? Promise.resolve(value2) : new Promise((resolve, reject) => readers.push({ resolve, reject }));
|
|
24577
|
+
},
|
|
24578
|
+
abort(error51) {
|
|
24579
|
+
if (closed)
|
|
24580
|
+
return;
|
|
24581
|
+
closed = true;
|
|
24582
|
+
failure = error51 ?? new Error("Remote Control RPC manager retired");
|
|
24583
|
+
values.length = 0;
|
|
24584
|
+
for (const reader of readers.splice(0))
|
|
24585
|
+
reader.reject(failure);
|
|
24586
|
+
port.close();
|
|
24587
|
+
}
|
|
24588
|
+
};
|
|
24589
|
+
transports.push(result);
|
|
24590
|
+
return result;
|
|
24591
|
+
};
|
|
24592
|
+
try {
|
|
24593
|
+
new components.RpcSession(transport(channel.port1), new components.RpcManager(() => manager));
|
|
24594
|
+
const session = new components.RpcSession(transport(channel.port2));
|
|
24595
|
+
const rpc = session.getRemoteMain();
|
|
24596
|
+
return {
|
|
24597
|
+
rpc,
|
|
24598
|
+
dispose() {
|
|
24599
|
+
rpc[Symbol.dispose]();
|
|
24600
|
+
for (const transport2 of transports)
|
|
24601
|
+
transport2.abort();
|
|
24602
|
+
}
|
|
24603
|
+
};
|
|
24604
|
+
} catch (error51) {
|
|
24605
|
+
for (const transport2 of transports)
|
|
24606
|
+
transport2.abort(error51);
|
|
24607
|
+
channel.port1.close();
|
|
24608
|
+
channel.port2.close();
|
|
24609
|
+
throw error51;
|
|
24610
|
+
}
|
|
24611
|
+
}
|
|
24612
|
+
|
|
24613
|
+
// packages/desktop-control/dist/renderer-native-rpc-service.js
|
|
24614
|
+
function createNativeRpcService(components, createRemote) {
|
|
24615
|
+
const source = components.services.appServerManagers.dup();
|
|
24616
|
+
const routes = /* @__PURE__ */ new Map();
|
|
24617
|
+
const subscriptions = /* @__PURE__ */ new Set();
|
|
24618
|
+
let refs = 1;
|
|
24619
|
+
const record6 = (value2) => value2 !== null && typeof value2 === "object";
|
|
24620
|
+
const connectionSignals = (hostId2) => {
|
|
24621
|
+
let node = components.scope.node;
|
|
24622
|
+
const seen = /* @__PURE__ */ new Set();
|
|
24623
|
+
while (node.parent && !seen.has(node.parent) && seen.size < 100) {
|
|
24624
|
+
seen.add(node);
|
|
24625
|
+
node = node.parent;
|
|
24626
|
+
}
|
|
24627
|
+
const found = [];
|
|
24628
|
+
for (const members of node.familyBindings.values()) {
|
|
24629
|
+
const value2 = members.get(hostId2)?.value;
|
|
24630
|
+
if (record6(value2) && Object.hasOwn(value2, "state$") && Object.hasOwn(value2, "revision$") && Object.hasOwn(value2, "appServerVersion$"))
|
|
24631
|
+
found.push({ state$: value2.state$, revision$: value2.revision$ });
|
|
24632
|
+
}
|
|
24633
|
+
return found.length === 1 ? found[0] : void 0;
|
|
24634
|
+
};
|
|
24635
|
+
const service = {
|
|
24636
|
+
dup() {
|
|
24637
|
+
refs++;
|
|
24638
|
+
return service;
|
|
24639
|
+
},
|
|
24640
|
+
onRpcBroken(listener) {
|
|
24641
|
+
source.onRpcBroken(listener);
|
|
24642
|
+
},
|
|
24643
|
+
openAccount(hostId2) {
|
|
24644
|
+
return source.openAccount(hostId2);
|
|
24645
|
+
},
|
|
24646
|
+
subscribe(hostId2, listener) {
|
|
24647
|
+
if (!hostId2.startsWith("remote-control:"))
|
|
24648
|
+
return source.subscribe(hostId2, listener);
|
|
24649
|
+
let active = true;
|
|
24650
|
+
let generation = 0;
|
|
24651
|
+
let upstream;
|
|
24652
|
+
let platformRequest;
|
|
24653
|
+
let remote;
|
|
24654
|
+
let stopWatch;
|
|
24655
|
+
let previousRevision;
|
|
24656
|
+
let previousState;
|
|
24657
|
+
const retire = () => {
|
|
24658
|
+
generation++;
|
|
24659
|
+
platformRequest?.[Symbol.dispose]();
|
|
24660
|
+
platformRequest = void 0;
|
|
24661
|
+
remote?.dispose();
|
|
24662
|
+
remote = void 0;
|
|
24663
|
+
routes.set(hostId2, null);
|
|
24664
|
+
};
|
|
24665
|
+
const cleanup = () => {
|
|
24666
|
+
if (!active)
|
|
24667
|
+
return;
|
|
24668
|
+
active = false;
|
|
24669
|
+
stopWatch?.();
|
|
24670
|
+
retire();
|
|
24671
|
+
upstream?.[Symbol.dispose]();
|
|
24672
|
+
upstream = void 0;
|
|
24673
|
+
routes.delete(hostId2);
|
|
24674
|
+
subscriptions.delete(cleanup);
|
|
24675
|
+
};
|
|
24676
|
+
subscriptions.add(cleanup);
|
|
24677
|
+
const publish = async () => {
|
|
24678
|
+
const owner = upstream;
|
|
24679
|
+
const current = generation;
|
|
24680
|
+
if (!owner || !active)
|
|
24681
|
+
return;
|
|
24682
|
+
let request;
|
|
24683
|
+
try {
|
|
24684
|
+
request = owner.getCodexHome();
|
|
24685
|
+
platformRequest = request;
|
|
24686
|
+
const home = await request;
|
|
24687
|
+
if (!active || current !== generation || owner !== upstream)
|
|
24688
|
+
return;
|
|
24689
|
+
if (!/^(?:[A-Za-z]:[\\/]|\\\\)/u.test(home)) {
|
|
24690
|
+
routes.delete(hostId2);
|
|
24691
|
+
listener({ status: "ready", manager: owner });
|
|
24692
|
+
return;
|
|
24693
|
+
}
|
|
24694
|
+
const created = createRemote(hostId2, owner);
|
|
24695
|
+
remote = created;
|
|
24696
|
+
await created.ready;
|
|
24697
|
+
if (!active || current !== generation || owner !== upstream)
|
|
24698
|
+
return;
|
|
24699
|
+
routes.set(hostId2, created.route);
|
|
24700
|
+
listener({ status: "ready", manager: created.rpc });
|
|
24701
|
+
} catch {
|
|
24702
|
+
if (active && current === generation) {
|
|
24703
|
+
remote?.dispose();
|
|
24704
|
+
remote = void 0;
|
|
24705
|
+
routes.delete(hostId2);
|
|
24706
|
+
listener({ status: "ready", manager: owner });
|
|
24707
|
+
}
|
|
24708
|
+
} finally {
|
|
24709
|
+
if (platformRequest === request) {
|
|
24710
|
+
platformRequest = void 0;
|
|
24711
|
+
request?.[Symbol.dispose]();
|
|
24712
|
+
}
|
|
24713
|
+
}
|
|
24714
|
+
};
|
|
24715
|
+
const changed = (state) => {
|
|
24716
|
+
if (!active)
|
|
24717
|
+
return;
|
|
24718
|
+
stopWatch?.();
|
|
24719
|
+
stopWatch = void 0;
|
|
24720
|
+
retire();
|
|
24721
|
+
upstream?.[Symbol.dispose]();
|
|
24722
|
+
upstream = void 0;
|
|
24723
|
+
if (state.status !== "ready") {
|
|
24724
|
+
listener(state);
|
|
24725
|
+
return;
|
|
24726
|
+
}
|
|
24727
|
+
upstream = state.manager.dup();
|
|
24728
|
+
listener({ status: "connecting" });
|
|
24729
|
+
const signals = connectionSignals(hostId2);
|
|
24730
|
+
if (!signals) {
|
|
24731
|
+
void publish();
|
|
24732
|
+
return;
|
|
24733
|
+
}
|
|
24734
|
+
previousState = void 0;
|
|
24735
|
+
previousRevision = void 0;
|
|
24736
|
+
stopWatch = components.scope.watch(({ get }) => {
|
|
24737
|
+
const connection = get(signals.state$), revision = get(signals.revision$);
|
|
24738
|
+
if (connection === previousState && revision === previousRevision)
|
|
24739
|
+
return;
|
|
24740
|
+
previousState = connection;
|
|
24741
|
+
previousRevision = revision;
|
|
24742
|
+
retire();
|
|
24743
|
+
listener({ status: connection === "connected" ? "connecting" : "disconnected" });
|
|
24744
|
+
if (connection === "connected")
|
|
24745
|
+
void publish();
|
|
24746
|
+
});
|
|
24747
|
+
};
|
|
24748
|
+
const original = source.subscribe(hostId2, changed);
|
|
24749
|
+
const result = original.then((lease) => {
|
|
24750
|
+
if (!active)
|
|
24751
|
+
lease[Symbol.dispose]();
|
|
24752
|
+
return {
|
|
24753
|
+
onRpcBroken: (listener2) => lease.onRpcBroken(listener2),
|
|
24754
|
+
[Symbol.dispose]() {
|
|
24755
|
+
cleanup();
|
|
24756
|
+
lease[Symbol.dispose]();
|
|
24757
|
+
}
|
|
24758
|
+
};
|
|
24759
|
+
});
|
|
24760
|
+
Object.assign(result, {
|
|
24761
|
+
onRpcBroken: (listener2) => original.onRpcBroken(listener2),
|
|
24762
|
+
[Symbol.dispose]() {
|
|
24763
|
+
cleanup();
|
|
24764
|
+
original[Symbol.dispose]();
|
|
24765
|
+
}
|
|
24766
|
+
});
|
|
24767
|
+
return result;
|
|
24768
|
+
},
|
|
24769
|
+
[Symbol.dispose]() {
|
|
24770
|
+
if (--refs !== 0)
|
|
24771
|
+
return;
|
|
24772
|
+
for (const cleanup of [...subscriptions])
|
|
24773
|
+
cleanup();
|
|
24774
|
+
source[Symbol.dispose]();
|
|
24775
|
+
}
|
|
24776
|
+
};
|
|
24777
|
+
return { service, route: (hostId2) => routes.get(hostId2) };
|
|
24778
|
+
}
|
|
24779
|
+
|
|
24780
|
+
// packages/desktop-control/dist/renderer-native-rpc-interactions.js
|
|
24781
|
+
function retainNativeRpcInteractions(upstream, manager, hostId2) {
|
|
24782
|
+
let disposed = false;
|
|
24783
|
+
const retained = /* @__PURE__ */ new Set();
|
|
24784
|
+
const requests = /* @__PURE__ */ new Map();
|
|
24785
|
+
const reads = /* @__PURE__ */ new Map();
|
|
24786
|
+
const record6 = (value2) => value2 !== null && typeof value2 === "object";
|
|
24787
|
+
const read = (threadId2) => {
|
|
24788
|
+
const existing = reads.get(threadId2);
|
|
24789
|
+
if (existing) {
|
|
24790
|
+
existing.dirty = true;
|
|
24791
|
+
return existing.promise;
|
|
24792
|
+
}
|
|
24793
|
+
const entry = { promise: Promise.resolve(), dirty: false };
|
|
24794
|
+
reads.set(threadId2, entry);
|
|
24795
|
+
entry.promise = Promise.resolve().then(async () => {
|
|
24796
|
+
do {
|
|
24797
|
+
if (disposed)
|
|
24798
|
+
break;
|
|
24799
|
+
entry.dirty = false;
|
|
24800
|
+
const pending = upstream.getConversation(threadId2);
|
|
24801
|
+
retained.add(pending);
|
|
24802
|
+
try {
|
|
24803
|
+
const conversation = await pending;
|
|
24804
|
+
if (disposed || entry.dirty || !record6(conversation) || !Array.isArray(conversation.requests))
|
|
24805
|
+
continue;
|
|
24806
|
+
const previous = requests.get(threadId2) ?? /* @__PURE__ */ new Set();
|
|
24807
|
+
const next = /* @__PURE__ */ new Set();
|
|
24808
|
+
for (const request of conversation.requests) {
|
|
24809
|
+
if (!record6(request) || typeof request.method !== "string" || !record6(request.params) || (request.params.threadId ?? request.params.conversationId) !== threadId2 || typeof request.id !== "string" && typeof request.id !== "number")
|
|
24810
|
+
continue;
|
|
24811
|
+
next.add(request.id);
|
|
24812
|
+
if (!previous.has(request.id))
|
|
24813
|
+
manager.onRequest(request);
|
|
24814
|
+
}
|
|
24815
|
+
if (next.size)
|
|
24816
|
+
requests.set(threadId2, next);
|
|
24817
|
+
else
|
|
24818
|
+
requests.delete(threadId2);
|
|
24819
|
+
} finally {
|
|
24820
|
+
if (retained.delete(pending))
|
|
24821
|
+
pending[Symbol.dispose]();
|
|
24822
|
+
}
|
|
24823
|
+
} while (!disposed && entry.dirty);
|
|
24824
|
+
}).finally(() => {
|
|
24825
|
+
reads.delete(threadId2);
|
|
24826
|
+
});
|
|
24827
|
+
return entry.promise;
|
|
24828
|
+
};
|
|
24829
|
+
const event = (value2) => {
|
|
24830
|
+
if (disposed || !record6(value2) || typeof value2.conversationId !== "string")
|
|
24831
|
+
return;
|
|
24832
|
+
void read(value2.conversationId).catch(() => void 0);
|
|
24833
|
+
};
|
|
24834
|
+
const subscribe = (input) => {
|
|
24835
|
+
const pending = upstream.subscribe(input);
|
|
24836
|
+
retained.add(pending);
|
|
24837
|
+
return Promise.resolve(pending).then((lease) => {
|
|
24838
|
+
if (disposed)
|
|
24839
|
+
lease[Symbol.dispose]();
|
|
24840
|
+
else
|
|
24841
|
+
retained.add(lease);
|
|
24842
|
+
});
|
|
24843
|
+
};
|
|
24844
|
+
const subscriptions = [
|
|
24845
|
+
"approval-request",
|
|
24846
|
+
"user-input-request",
|
|
24847
|
+
"mcp-elicitation-request",
|
|
24848
|
+
"approval-resolved"
|
|
24849
|
+
].map((name) => subscribe({ type: "event", key: { hostId: hostId2 }, event: name, listener: event }));
|
|
24850
|
+
subscriptions.push(subscribe({
|
|
24851
|
+
type: "notification",
|
|
24852
|
+
key: { hostId: hostId2 },
|
|
24853
|
+
methods: ["serverRequest/resolved"],
|
|
24854
|
+
listener(value2) {
|
|
24855
|
+
if (record6(value2) && record6(value2.params) && typeof value2.params.threadId === "string")
|
|
24856
|
+
event({ conversationId: value2.params.threadId });
|
|
24857
|
+
}
|
|
24858
|
+
}));
|
|
24859
|
+
const ready = Promise.all(subscriptions).then(async () => {
|
|
24860
|
+
if (disposed)
|
|
24861
|
+
return;
|
|
24862
|
+
const pending = upstream.getWorkInProgress();
|
|
24863
|
+
retained.add(pending);
|
|
24864
|
+
try {
|
|
24865
|
+
const work = await pending;
|
|
24866
|
+
if (disposed)
|
|
24867
|
+
return;
|
|
24868
|
+
if (!Array.isArray(work))
|
|
24869
|
+
throw new Error("Native RPC interaction snapshot is unavailable");
|
|
24870
|
+
const threadIds = new Set(work.flatMap((item) => record6(item) && typeof item.conversationId === "string" ? [item.conversationId] : []));
|
|
24871
|
+
await Promise.all([...threadIds].map(read));
|
|
24872
|
+
} finally {
|
|
24873
|
+
if (retained.delete(pending))
|
|
24874
|
+
pending[Symbol.dispose]();
|
|
24875
|
+
}
|
|
24876
|
+
});
|
|
24877
|
+
return {
|
|
24878
|
+
ready,
|
|
24879
|
+
dispose() {
|
|
24880
|
+
if (disposed)
|
|
24881
|
+
return;
|
|
24882
|
+
disposed = true;
|
|
24883
|
+
for (const lease of retained)
|
|
24884
|
+
lease[Symbol.dispose]();
|
|
24885
|
+
retained.clear();
|
|
24886
|
+
requests.clear();
|
|
24887
|
+
}
|
|
24888
|
+
};
|
|
24889
|
+
}
|
|
24890
|
+
|
|
24891
|
+
// packages/desktop-control/dist/renderer-native-rpc-install.js
|
|
24892
|
+
async function installNativeRpcRemoteControlDirect(renderer) {
|
|
24893
|
+
let attempt;
|
|
24894
|
+
const probeId = crypto.randomUUID();
|
|
24895
|
+
try {
|
|
24896
|
+
attempt = await renderer.evaluate(`(() => {
|
|
24897
|
+
if (window.__codexhostNativeRpcRemoteControlV1) return null;
|
|
24898
|
+
const routing = window.__codexhostHostRoutingV1;
|
|
24899
|
+
const owner = routing?.forHost('local')?.manager;
|
|
24900
|
+
if (owner?.kind !== 'main-process-rpc') return null;
|
|
24901
|
+
const catalog = window.__codexhostLoadedModulesV1;
|
|
24902
|
+
if (!catalog?.complete) return null;
|
|
24903
|
+
const key = JSON.stringify([catalog.owner, catalog.urls.filter(url => /renderer-app-server-managers|app-shared/.test(url)).sort()]);
|
|
24904
|
+
const previous = window.__codexhostNativeRpcDiscoveryV1;
|
|
24905
|
+
const sameOwner = previous?.key === key && previous.owner === owner;
|
|
24906
|
+
if (sameOwner && (previous.state !== 'unavailable' || previous.attempts >= 3 || Date.now() < previous.nextRetryAt)) return null;
|
|
24907
|
+
const token = ${JSON.stringify(probeId)};
|
|
24908
|
+
window.__codexhostNativeRpcDiscoveryV1 = {
|
|
24909
|
+
key, owner, token, state: 'discovering', attempts: sameOwner ? previous.attempts + 1 : 1,
|
|
24910
|
+
};
|
|
24911
|
+
return token;
|
|
24912
|
+
})()`);
|
|
24913
|
+
} catch {
|
|
24914
|
+
return false;
|
|
24915
|
+
}
|
|
24916
|
+
if (attempt === null)
|
|
24917
|
+
return false;
|
|
24918
|
+
let installed = false;
|
|
24919
|
+
try {
|
|
24920
|
+
installed = await withNativeRpcComponents(renderer, async (objectId) => {
|
|
24921
|
+
const result = await renderer.command("Runtime.callFunctionOn", {
|
|
24922
|
+
objectId,
|
|
24923
|
+
functionDeclaration: `function() {
|
|
24924
|
+
if (this.document !== document) return false;
|
|
24925
|
+
const retainRendererHostResponses = ${retainRendererHostResponses.toString()};
|
|
24926
|
+
const isolateRendererPrewarmConsumption = ${isolateRendererPrewarmConsumption.toString()};
|
|
24927
|
+
return (${installNativeRpcRemoteControl.toString()})(this, window, {
|
|
24928
|
+
createPolicy: ${createDraftPrewarmPolicyBridge.toString()},
|
|
24929
|
+
createManager: ${createNativeRemoteManager.toString()},
|
|
24930
|
+
createChannel: ${createNativeRpcChannel.toString()},
|
|
24931
|
+
createService: ${createNativeRpcService.toString()},
|
|
24932
|
+
retainInteractions: ${retainNativeRpcInteractions.toString()},
|
|
24933
|
+
});
|
|
24934
|
+
}`,
|
|
24935
|
+
returnByValue: true
|
|
24936
|
+
});
|
|
24937
|
+
return !result.exceptionDetails && result.result?.value === true;
|
|
24938
|
+
});
|
|
24939
|
+
return installed;
|
|
24940
|
+
} catch {
|
|
24941
|
+
return false;
|
|
24942
|
+
} finally {
|
|
24943
|
+
await renderer.evaluate(`(() => {
|
|
24944
|
+
const status = window.__codexhostNativeRpcDiscoveryV1;
|
|
24945
|
+
if (status?.token === ${JSON.stringify(attempt)}) {
|
|
24946
|
+
status.state = ${JSON.stringify(installed ? "ready" : "unavailable")};
|
|
24947
|
+
status.nextRetryAt = Date.now() + 5000 * 2 ** (status.attempts - 1);
|
|
24948
|
+
}
|
|
24949
|
+
})()`).catch(() => void 0);
|
|
24950
|
+
}
|
|
24951
|
+
}
|
|
24952
|
+
|
|
24953
|
+
// packages/desktop-control/dist/renderer-rpc-steering.js
|
|
24954
|
+
var RETRY_BASE_MS = 5e3;
|
|
24955
|
+
var RETRY_MAX_MS = 3e5;
|
|
24956
|
+
var retries = /* @__PURE__ */ new WeakMap();
|
|
24957
|
+
async function installRendererRpcSteeringDirect(client, now = Date.now) {
|
|
24958
|
+
try {
|
|
24959
|
+
const needed = await client.evaluate(`(() => {
|
|
24960
|
+
const steering = window.__codexhostRpcSteeringV1;
|
|
24961
|
+
if (steering && steering.controller.forHost === steering.forHost) return false;
|
|
24962
|
+
steering?.release();
|
|
24963
|
+
const routing=window.__codexhostHostRoutingV1;
|
|
24964
|
+
return ['local', ...(routing?.knownHostIds?.() ?? [])].some(id => routing?.forHost(id)?.manager.kind === 'main-process-rpc');
|
|
24965
|
+
})()`);
|
|
24966
|
+
if (!needed)
|
|
24967
|
+
return false;
|
|
24968
|
+
const retry = retries.get(client);
|
|
24969
|
+
if (retry && now() < retry.nextAt)
|
|
24970
|
+
return false;
|
|
24971
|
+
try {
|
|
24972
|
+
await discoverAndInstall(client);
|
|
24973
|
+
retries.delete(client);
|
|
24974
|
+
return true;
|
|
24975
|
+
} catch (error51) {
|
|
24976
|
+
const attempts = (retry?.attempts ?? 0) + 1;
|
|
24977
|
+
const delay7 = Math.min(RETRY_BASE_MS * 2 ** (attempts - 1), RETRY_MAX_MS);
|
|
24978
|
+
retries.set(client, { attempts, nextAt: now() + delay7 });
|
|
24979
|
+
console.error(`codexhost native steering discovery failed (attempt ${attempts}):`, error51 instanceof Error ? error51.message : String(error51));
|
|
24980
|
+
return false;
|
|
24981
|
+
}
|
|
24982
|
+
} catch {
|
|
24983
|
+
return false;
|
|
24984
|
+
}
|
|
24985
|
+
}
|
|
24986
|
+
async function discoverAndInstall(client) {
|
|
24987
|
+
const group = `codexhost-rpc-steering-${crypto.randomUUID()}`;
|
|
24988
|
+
const command = (method, params) => client.command(method, params);
|
|
24989
|
+
const properties = (objectId) => command("Runtime.getProperties", { objectId, ownProperties: true });
|
|
24990
|
+
const call = (objectId, functionDeclaration, args = []) => command("Runtime.callFunctionOn", {
|
|
24991
|
+
objectId,
|
|
24992
|
+
functionDeclaration,
|
|
24993
|
+
arguments: args,
|
|
24994
|
+
objectGroup: group,
|
|
24995
|
+
returnByValue: true
|
|
24996
|
+
});
|
|
24997
|
+
try {
|
|
24998
|
+
const proto = await command("Runtime.evaluate", {
|
|
24999
|
+
expression: "Object.getPrototypeOf(async function(){})",
|
|
25000
|
+
objectGroup: group
|
|
25001
|
+
});
|
|
25002
|
+
if (!proto.result.objectId)
|
|
25003
|
+
throw new Error("Native RPC steering discovery is unavailable");
|
|
25004
|
+
const objects = await command("Runtime.queryObjects", {
|
|
25005
|
+
prototypeObjectId: proto.result.objectId,
|
|
25006
|
+
objectGroup: group
|
|
25007
|
+
});
|
|
25008
|
+
if (!objects.objects.objectId)
|
|
25009
|
+
throw new Error("Native RPC steering discovery is unavailable");
|
|
25010
|
+
const filtered = await command("Runtime.callFunctionOn", {
|
|
25011
|
+
objectId: objects.objects.objectId,
|
|
25012
|
+
functionDeclaration: 'function(){return this.filter(fn=>fn.name==="collectAppStateSnapshot"&&String(fn).includes("collectSnapshot")).slice(0,9)}',
|
|
25013
|
+
objectGroup: group
|
|
25014
|
+
});
|
|
25015
|
+
if (!filtered.result.objectId)
|
|
25016
|
+
throw new Error("Native RPC Controller is unavailable");
|
|
25017
|
+
const snapshots = (await properties(filtered.result.objectId)).result.flatMap((entry) => entry.value?.type === "function" && entry.value.objectId ? [entry.value.objectId] : []);
|
|
25018
|
+
if (snapshots.length > 8)
|
|
25019
|
+
throw new Error("Native RPC Controller is ambiguous");
|
|
25020
|
+
const controllers = [];
|
|
25021
|
+
for (const snapshot2 of snapshots) {
|
|
25022
|
+
const scopes = (await properties(snapshot2)).internalProperties?.find((entry) => entry.name === "[[Scopes]]")?.value?.objectId;
|
|
25023
|
+
if (!scopes)
|
|
25024
|
+
continue;
|
|
25025
|
+
for (const scope of (await properties(scopes)).result) {
|
|
25026
|
+
if (!scope.value?.objectId || !scope.value.description?.startsWith("Closure"))
|
|
25027
|
+
continue;
|
|
25028
|
+
const bindings = (await properties(scope.value.objectId)).result;
|
|
25029
|
+
const owners = [];
|
|
25030
|
+
let rootScope;
|
|
25031
|
+
for (const binding of bindings) {
|
|
25032
|
+
if (binding.value?.type !== "object" || !binding.value.objectId)
|
|
25033
|
+
continue;
|
|
25034
|
+
const id2 = binding.value.objectId;
|
|
25035
|
+
const result2 = await call(id2, `function(){return (${nativeRpcObjectShape.toString()})(this)}`);
|
|
25036
|
+
const shape = result2.result.value;
|
|
25037
|
+
if (shape?.scope)
|
|
25038
|
+
rootScope = id2;
|
|
25039
|
+
if (shape?.controller && (await call(id2, "function(fn){return this.collectAppStateSnapshot===fn}", [
|
|
25040
|
+
{ objectId: snapshot2 }
|
|
25041
|
+
])).result.value === true)
|
|
25042
|
+
owners.push(id2);
|
|
25043
|
+
}
|
|
25044
|
+
if (owners.length !== 1 || !rootScope)
|
|
25045
|
+
continue;
|
|
25046
|
+
const root = await call(rootScope, `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}`);
|
|
25047
|
+
if (root.result.value === true)
|
|
25048
|
+
controllers.push(owners[0]);
|
|
25049
|
+
}
|
|
25050
|
+
}
|
|
25051
|
+
if (controllers.length !== 1)
|
|
25052
|
+
throw new Error("Native RPC Controller is missing or ambiguous");
|
|
25053
|
+
const result = await call(controllers[0], "function(){return window.__codexhostInstallRpcSteeringV1?.(this) === true}");
|
|
25054
|
+
if (result.exceptionDetails || result.result.value !== true)
|
|
25055
|
+
throw new Error("Native RPC steering installation failed");
|
|
25056
|
+
} finally {
|
|
25057
|
+
await client.command("Runtime.releaseObjectGroup", { objectGroup: group }).catch(() => void 0);
|
|
25058
|
+
}
|
|
25059
|
+
}
|
|
25060
|
+
|
|
24065
25061
|
// packages/desktop-control/dist/renderer-cdp-control-session.js
|
|
24066
25062
|
function isRecord2(value2) {
|
|
24067
25063
|
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
@@ -24289,7 +25285,12 @@ var InstalledRendererCdpControlSession = class {
|
|
|
24289
25285
|
var defaultOperations = {
|
|
24290
25286
|
listTargets: (endpoint, signal) => listCdpTargets(endpoint, fetch, signal),
|
|
24291
25287
|
connect: (webSocketDebuggerUrl) => CdpClient.connect(webSocketDebuggerUrl),
|
|
24292
|
-
installDraftPrewarmPolicy
|
|
25288
|
+
async installDraftPrewarmPolicy(renderer) {
|
|
25289
|
+
const status2 = await installRendererDraftPrewarmPolicyDirect(renderer);
|
|
25290
|
+
await installNativeRpcRemoteControlDirect(renderer);
|
|
25291
|
+
await installRendererRpcSteeringDirect(renderer);
|
|
25292
|
+
return status2;
|
|
25293
|
+
}
|
|
24293
25294
|
};
|
|
24294
25295
|
async function createRendererCdpControlSession(options) {
|
|
24295
25296
|
const enabledAgents = options.enabledAgents;
|
|
@@ -34263,12 +35264,13 @@ var ExternalThreadRuntime = class {
|
|
|
34263
35264
|
}
|
|
34264
35265
|
try {
|
|
34265
35266
|
const aligned = await this.#repository.alignSnapshot(thread.record, snapshot2.value);
|
|
35267
|
+
const turns = aligned.record.state === "creating" && !aligned.record.nativeSessionRef && snapshot2.value.turns.length === 0 ? thread.turns : aligned.turns;
|
|
34266
35268
|
thread.record = aligned.record;
|
|
34267
|
-
thread.turns =
|
|
35269
|
+
thread.turns = turns;
|
|
34268
35270
|
thread.historyHydrated = true;
|
|
34269
35271
|
thread.thread = externalThreadValue({
|
|
34270
35272
|
record: aligned.record,
|
|
34271
|
-
turns
|
|
35273
|
+
turns,
|
|
34272
35274
|
sessionId: thread.sessionId,
|
|
34273
35275
|
running: thread.running
|
|
34274
35276
|
});
|
|
@@ -34559,6 +35561,7 @@ var publicSubmission = ({
|
|
|
34559
35561
|
var DEFAULT_PAGE_SIZE3 = 50;
|
|
34560
35562
|
var ExternalThreadQueue = class {
|
|
34561
35563
|
#queues = /* @__PURE__ */ new Map();
|
|
35564
|
+
#acceptedSteers = /* @__PURE__ */ new Map();
|
|
34562
35565
|
#notifyChanged;
|
|
34563
35566
|
#createId;
|
|
34564
35567
|
constructor(options) {
|
|
@@ -34600,7 +35603,7 @@ var ExternalThreadQueue = class {
|
|
|
34600
35603
|
async delete(threadId2, id2) {
|
|
34601
35604
|
const items = this.#queues.get(threadId2);
|
|
34602
35605
|
const index = items?.findIndex((item) => item.id === id2) ?? -1;
|
|
34603
|
-
if (!items || index === -1) return
|
|
35606
|
+
if (!items || index === -1) return this.#acceptedSteers.get(id2) === threadId2;
|
|
34604
35607
|
items.splice(index, 1);
|
|
34605
35608
|
this.#prune(threadId2);
|
|
34606
35609
|
await this.#notifyChanged(threadId2);
|
|
@@ -34633,6 +35636,26 @@ var ExternalThreadQueue = class {
|
|
|
34633
35636
|
index
|
|
34634
35637
|
};
|
|
34635
35638
|
}
|
|
35639
|
+
/** Reserve the exact queued input before steering can finish a replacement Turn.
|
|
35640
|
+
* Otherwise automatic queue advancement can deliver that input a second time. */
|
|
35641
|
+
takeSteered(threadId2, clientUserMessageId, input) {
|
|
35642
|
+
if (typeof clientUserMessageId !== "string") return;
|
|
35643
|
+
const matches = (this.#queues.get(threadId2) ?? []).filter(
|
|
35644
|
+
(item2) => item2.clientUserMessageId === clientUserMessageId
|
|
35645
|
+
);
|
|
35646
|
+
if (matches.length === 0) return;
|
|
35647
|
+
const item = matches[0];
|
|
35648
|
+
if (matches.length !== 1 || externalTurnInputText(item.input) !== externalTurnInputText(input))
|
|
35649
|
+
throw new ExternalQueueError(-32602, "Queued steering input changed before delivery");
|
|
35650
|
+
return this.take(threadId2, item.id);
|
|
35651
|
+
}
|
|
35652
|
+
async acceptSteered(threadId2, taken) {
|
|
35653
|
+
this.#acceptedSteers.set(taken.submission.id, threadId2);
|
|
35654
|
+
while (this.#acceptedSteers.size > 128) {
|
|
35655
|
+
this.#acceptedSteers.delete(this.#acceptedSteers.keys().next().value);
|
|
35656
|
+
}
|
|
35657
|
+
await this.#notifyChanged(threadId2);
|
|
35658
|
+
}
|
|
34636
35659
|
restore(threadId2, taken) {
|
|
34637
35660
|
const items = this.#items(threadId2);
|
|
34638
35661
|
if (items.some((item) => item.id === taken.submission.id)) return;
|
|
@@ -34646,6 +35669,9 @@ var ExternalThreadQueue = class {
|
|
|
34646
35669
|
}
|
|
34647
35670
|
forget(threadId2) {
|
|
34648
35671
|
this.#queues.delete(threadId2);
|
|
35672
|
+
for (const [id2, owner] of this.#acceptedSteers) {
|
|
35673
|
+
if (owner === threadId2) this.#acceptedSteers.delete(id2);
|
|
35674
|
+
}
|
|
34649
35675
|
}
|
|
34650
35676
|
#items(threadId2) {
|
|
34651
35677
|
let items = this.#queues.get(threadId2);
|
|
@@ -42058,7 +43084,10 @@ var AppServerHost = class {
|
|
|
42058
43084
|
request,
|
|
42059
43085
|
location,
|
|
42060
43086
|
(hostThreadId) => this.#repository.setArchived(hostThreadId, archived),
|
|
42061
|
-
"External Thread archive state could not be persisted"
|
|
43087
|
+
"External Thread archive state could not be persisted",
|
|
43088
|
+
// A loaded Thread whose deferred native Session never arrived (its first Turn
|
|
43089
|
+
// failed first) is still on Desktop's list and must remain archivable.
|
|
43090
|
+
true
|
|
42062
43091
|
);
|
|
42063
43092
|
if (!updated) return;
|
|
42064
43093
|
await this.#writer.json(
|
|
@@ -42648,7 +43677,7 @@ var AppServerHost = class {
|
|
|
42648
43677
|
...arguments_2 ? { arguments: arguments_2 } : {}
|
|
42649
43678
|
});
|
|
42650
43679
|
if (!result.ok) throw new ExternalCommandError(-32073, result.error.message);
|
|
42651
|
-
return { turnId
|
|
43680
|
+
return { turnId, turn: projection.projector.pendingTurn(), gate };
|
|
42652
43681
|
} catch (error51) {
|
|
42653
43682
|
restoreExecutionHost();
|
|
42654
43683
|
thread.running = false;
|
|
@@ -43430,6 +44459,11 @@ var AppServerHost = class {
|
|
|
43430
44459
|
}
|
|
43431
44460
|
}
|
|
43432
44461
|
async #startExternalTurn(request, thread) {
|
|
44462
|
+
const context = routingParams(request).additionalContext;
|
|
44463
|
+
if (isRecord18(context) && Object.hasOwn(context, THREAD_STEERING_CONTEXT_PARAM)) {
|
|
44464
|
+
await this.#steerExternalTurn(request, thread, true);
|
|
44465
|
+
return;
|
|
44466
|
+
}
|
|
43433
44467
|
if (this.#externalThreadBusy(thread) || this.#pendingExternalCommandRequests.has(thread.id)) {
|
|
43434
44468
|
await this.#writer.json(
|
|
43435
44469
|
rpcError(request, -32072, "External Thread already has an active Turn")
|
|
@@ -43601,34 +44635,61 @@ var AppServerHost = class {
|
|
|
43601
44635
|
this.#diagnose(error51);
|
|
43602
44636
|
}
|
|
43603
44637
|
}
|
|
43604
|
-
async #steerExternalTurn(request, thread) {
|
|
44638
|
+
async #steerExternalTurn(request, thread, asStart = false) {
|
|
44639
|
+
let queued;
|
|
44640
|
+
let accepted = false;
|
|
43605
44641
|
try {
|
|
44642
|
+
let params = requestObject(request);
|
|
44643
|
+
const context = params.additionalContext;
|
|
44644
|
+
if (isRecord18(context) && Object.hasOwn(context, THREAD_STEERING_CONTEXT_PARAM)) {
|
|
44645
|
+
const marker = threadSteeringContextSchema.safeParse(
|
|
44646
|
+
context[THREAD_STEERING_CONTEXT_PARAM]
|
|
44647
|
+
);
|
|
44648
|
+
if (!marker.success || marker.data.clientUserMessageId !== params.clientUserMessageId || asStart && marker.data.delivery !== "newTurn")
|
|
44649
|
+
throw new ExternalSteerError(-32602, "Invalid native steering preparation context");
|
|
44650
|
+
if (!asStart && params.expectedTurnId !== marker.data.expectedTurnId)
|
|
44651
|
+
throw new ExternalSteerError(-32074, "Native steering target changed before submission");
|
|
44652
|
+
params = {
|
|
44653
|
+
...params,
|
|
44654
|
+
expectedTurnId: marker.data.expectedTurnId,
|
|
44655
|
+
[THREAD_STEER_DELIVERY_PARAM]: marker.data.delivery
|
|
44656
|
+
};
|
|
44657
|
+
}
|
|
44658
|
+
queued = this.#externalQueue.takeSteered(thread.id, params.clientUserMessageId, params.input);
|
|
43606
44659
|
const started = await this.#externalSteering.run(
|
|
43607
44660
|
thread,
|
|
43608
|
-
|
|
44661
|
+
params,
|
|
43609
44662
|
(text, assertActive) => this.#beginExternalInputTurn(
|
|
43610
44663
|
thread,
|
|
43611
44664
|
text,
|
|
43612
44665
|
assertActive,
|
|
43613
44666
|
typeof requestObject(request).clientUserMessageId === "string" ? requestObject(request).clientUserMessageId : void 0,
|
|
43614
|
-
requestObject(request)[THREAD_REFERENCE_SOURCE_HOST_PARAM]
|
|
44667
|
+
queued ? queued.sourceHostId : requestObject(request)[THREAD_REFERENCE_SOURCE_HOST_PARAM]
|
|
43615
44668
|
),
|
|
43616
44669
|
(input) => this.#insertExternalInput(thread, input)
|
|
43617
44670
|
);
|
|
44671
|
+
accepted = true;
|
|
44672
|
+
if (queued) {
|
|
44673
|
+
await this.#externalQueue.acceptSteered(thread.id, queued).catch((error51) => this.#diagnose(error51));
|
|
44674
|
+
}
|
|
43618
44675
|
try {
|
|
43619
44676
|
await this.#writer.json(
|
|
43620
44677
|
rpcEnvelope(request, {
|
|
43621
|
-
result: { turnId: started.turnId, delivery: started.delivery }
|
|
44678
|
+
result: asStart ? { turn: this.#projectedTurn(thread, started.turnId).projector.pendingTurn() } : { turnId: started.turnId, delivery: started.delivery }
|
|
43622
44679
|
})
|
|
43623
44680
|
);
|
|
43624
44681
|
} finally {
|
|
43625
44682
|
started.gate.resolve();
|
|
43626
44683
|
}
|
|
43627
44684
|
} catch (error51) {
|
|
44685
|
+
if (queued && !accepted) {
|
|
44686
|
+
this.#externalQueue.restore(thread.id, queued);
|
|
44687
|
+
await this.#externalQueue.notifyChanged(thread.id).catch((failure) => this.#diagnose(failure));
|
|
44688
|
+
}
|
|
43628
44689
|
await this.#writer.json(
|
|
43629
44690
|
rpcError(
|
|
43630
44691
|
request,
|
|
43631
|
-
error51 instanceof ExternalSteerError || error51 instanceof ExternalCommandError ? error51.code : -32074,
|
|
44692
|
+
error51 instanceof ExternalSteerError || error51 instanceof ExternalCommandError || error51 instanceof ExternalQueueError ? error51.code : -32074,
|
|
43632
44693
|
errorMessage4(error51)
|
|
43633
44694
|
)
|
|
43634
44695
|
);
|