@codexhost/cli-win32-x64 0.1.6 → 0.2.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 +1 -1
- package/app/codexhost-distribution.json +1 -1
- package/app/desktop-controller.mjs +111 -52
- package/app/host-runtime.mjs +9605 -438
- package/app/renderer-extension.js +587 -352
- package/bin/codexhost.exe +0 -0
- package/libexec/codexhost-shim.exe +0 -0
- package/libexec/codexhost-updater.exe +0 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ Run Pi and Claude Code as first-class external harnesses inside Codex Desktop.
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
npm install -g @codexhost/cli@0.1
|
|
10
|
+
npm install -g @codexhost/cli@0.2.1
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
Do not install this package directly. npm selects it through the optional dependencies of `@codexhost/cli`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"schemaVersion":1,"version":"0.1
|
|
1
|
+
{"schemaVersion":1,"version":"0.2.1","distribution":"npm","target":"windows-x64"}
|
|
@@ -63,11 +63,6 @@ async function startControllerAttachmentServer(options) {
|
|
|
63
63
|
);
|
|
64
64
|
return;
|
|
65
65
|
}
|
|
66
|
-
if (line === `SHUTDOWN ${options.nonce}`) {
|
|
67
|
-
respond(socket, "ready");
|
|
68
|
-
queueMicrotask(() => void options.shutdown().catch(() => void 0));
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
66
|
respond(socket, "rejected");
|
|
72
67
|
});
|
|
73
68
|
});
|
|
@@ -334,7 +329,7 @@ var ELECTRON_MODULE_EXPRESSION = `(() => {
|
|
|
334
329
|
return createRequire(process.execPath)('electron');
|
|
335
330
|
})()`;
|
|
336
331
|
var CONNECT_APP_HOST_CHANNEL = "codex_desktop:connect-app-host";
|
|
337
|
-
var REVIEWED_TITLE_SERVICE_IDENTITIES = ["Dhe", "Nye", "wbe", "nxe"];
|
|
332
|
+
var REVIEWED_TITLE_SERVICE_IDENTITIES = ["Dhe", "Nye", "wbe", "nxe", "tTe"];
|
|
338
333
|
var POLICY_STATE_SYMBOL = "codexhost.main-process-title-policy.v1";
|
|
339
334
|
var SERVICE_OWNER_SYMBOL = "codexhost.main-process-title-policy.owner.v1";
|
|
340
335
|
var RENDERER_READY_EXPRESSION = "(() => { Object.defineProperty(window, '__codexhostMainProcessTitlePolicyV1', { configurable: true, value: { state: 'ready' } }); return 'ready'; })()";
|
|
@@ -579,17 +574,62 @@ async function readMainProcessTitlePolicyCounters(inspector) {
|
|
|
579
574
|
}
|
|
580
575
|
|
|
581
576
|
// packages/desktop-control/src/renderer-draft-prewarm-runtime.ts
|
|
582
|
-
function installDraftPrewarmPolicyBridge(
|
|
577
|
+
function installDraftPrewarmPolicyBridge(bridge, hostId, target) {
|
|
578
|
+
const existing = target.__codexhostDraftPrewarmPolicyV1;
|
|
579
|
+
existing?.dispose?.();
|
|
580
|
+
const originalSend = bridge.sendRequest;
|
|
581
|
+
let selectedModel = null;
|
|
583
582
|
let clearInFlight = null;
|
|
583
|
+
const isRecord5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
584
|
+
const routeCollaborationMode = (method, parameters) => {
|
|
585
|
+
if (selectedModel === null || !isRecord5(parameters)) return parameters;
|
|
586
|
+
const collaborationMode = parameters.collaborationMode;
|
|
587
|
+
const settings = isRecord5(collaborationMode) ? collaborationMode.settings : null;
|
|
588
|
+
if (!isRecord5(collaborationMode) || !isRecord5(settings)) {
|
|
589
|
+
throw new Error(`Codex ${method} omitted collaborationMode.settings`);
|
|
590
|
+
}
|
|
591
|
+
return {
|
|
592
|
+
...parameters,
|
|
593
|
+
collaborationMode: {
|
|
594
|
+
...collaborationMode,
|
|
595
|
+
settings: { ...settings, model: selectedModel }
|
|
596
|
+
}
|
|
597
|
+
};
|
|
598
|
+
};
|
|
599
|
+
const routeThreadStart = (method, parameters) => {
|
|
600
|
+
if (selectedModel === null || !isRecord5(parameters)) return parameters;
|
|
601
|
+
const threadParams = method === "prewarm-thread-start-for-host" ? parameters.params : parameters.method === "thread/start" ? parameters.params : null;
|
|
602
|
+
if (!isRecord5(threadParams) || threadParams.ephemeral === true) return parameters;
|
|
603
|
+
return { ...parameters, params: { ...threadParams, model: selectedModel } };
|
|
604
|
+
};
|
|
605
|
+
const routedSend = (method, parameters, options) => {
|
|
606
|
+
const routedParameters = method === "start-conversation" || method === "prewarm-conversation-for-host" ? routeCollaborationMode(method, parameters) : method === "prewarm-thread-start-for-host" || method === "send-cli-request-for-host" ? routeThreadStart(method, parameters) : parameters;
|
|
607
|
+
return options === void 0 ? originalSend.call(bridge, method, routedParameters) : originalSend.call(bridge, method, routedParameters, options);
|
|
608
|
+
};
|
|
609
|
+
bridge.sendRequest = routedSend;
|
|
584
610
|
const policy = Object.freeze({
|
|
585
611
|
state: "ready",
|
|
612
|
+
select(model) {
|
|
613
|
+
if (model !== null && (typeof model !== "string" || !model.startsWith("codexhost/"))) {
|
|
614
|
+
throw new Error("Draft route Model must be a codexhost transport carrier");
|
|
615
|
+
}
|
|
616
|
+
if (selectedModel === model) return false;
|
|
617
|
+
selectedModel = model;
|
|
618
|
+
return true;
|
|
619
|
+
},
|
|
586
620
|
clear() {
|
|
587
621
|
if (clearInFlight === null) {
|
|
588
|
-
clearInFlight = Promise.resolve(
|
|
622
|
+
clearInFlight = Promise.resolve(
|
|
623
|
+
originalSend.call(bridge, "clear-prewarmed-threads-for-host", { hostId })
|
|
624
|
+
).then(() => void 0).finally(() => {
|
|
589
625
|
clearInFlight = null;
|
|
590
626
|
});
|
|
591
627
|
}
|
|
592
628
|
return clearInFlight;
|
|
629
|
+
},
|
|
630
|
+
dispose() {
|
|
631
|
+
if (bridge.sendRequest === routedSend) bridge.sendRequest = originalSend;
|
|
632
|
+
selectedModel = null;
|
|
593
633
|
}
|
|
594
634
|
});
|
|
595
635
|
Object.defineProperty(target, "__codexhostDraftPrewarmPolicyV1", {
|
|
@@ -712,16 +752,13 @@ function isRecord3(value) {
|
|
|
712
752
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
713
753
|
}
|
|
714
754
|
var FIND_REQUEST_MANAGER_EXPRESSION = `(() => {
|
|
715
|
-
const
|
|
755
|
+
const editors = [...document.querySelectorAll(
|
|
716
756
|
'[data-codex-composer], [contenteditable="true"][role="textbox"]',
|
|
717
|
-
)]
|
|
718
|
-
|
|
719
|
-
return bounds.width > 0 && bounds.height > 0;
|
|
720
|
-
});
|
|
721
|
-
if (visibleEditors.length !== 1) {
|
|
757
|
+
)];
|
|
758
|
+
if (editors.length !== 1) {
|
|
722
759
|
return { candidateCount: 0, hostId: null, sendRequest: null };
|
|
723
760
|
}
|
|
724
|
-
let element =
|
|
761
|
+
let element = editors[0];
|
|
725
762
|
let fiber = null;
|
|
726
763
|
while (element != null && fiber == null) {
|
|
727
764
|
const key = Object.getOwnPropertyNames(element).find((name) =>
|
|
@@ -757,10 +794,10 @@ var FIND_REQUEST_MANAGER_EXPRESSION = `(() => {
|
|
|
757
794
|
};
|
|
758
795
|
})()`;
|
|
759
796
|
var INSTALL_RENDERER_POLICY_FUNCTION = `function(hostId) {
|
|
760
|
-
|
|
761
|
-
const send = (method, parameters) => bridge.sendRequest(method, parameters);
|
|
762
|
-
return (${installDraftPrewarmPolicyBridge.toString()})(send, hostId, window);
|
|
797
|
+
return (${installDraftPrewarmPolicyBridge.toString()})(this, hostId, window);
|
|
763
798
|
}`;
|
|
799
|
+
var REQUEST_MANAGER_WAIT_TIMEOUT_MS = 6e4;
|
|
800
|
+
var REQUEST_MANAGER_POLL_INTERVAL_MS = 25;
|
|
764
801
|
function mainProcessInstaller(rendererWebContentsId) {
|
|
765
802
|
return `async function () {
|
|
766
803
|
const mainModule = process.mainModule;
|
|
@@ -780,11 +817,23 @@ async function installRendererDraftPrewarmPolicy(inspector, rendererWebContentsI
|
|
|
780
817
|
throw new Error("Renderer webContents ID must be a positive integer");
|
|
781
818
|
}
|
|
782
819
|
const installer = mainProcessInstaller(rendererWebContentsId);
|
|
783
|
-
const
|
|
784
|
-
|
|
785
|
-
|
|
820
|
+
const deadline = Date.now() + REQUEST_MANAGER_WAIT_TIMEOUT_MS;
|
|
821
|
+
while (true) {
|
|
822
|
+
try {
|
|
823
|
+
const value = await inspector.evaluate(`(${installer})()`);
|
|
824
|
+
if (!isRecord3(value) || value.state !== "ready" || value.reason !== "owned-request-bridge") {
|
|
825
|
+
throw new Error("Renderer draft prewarm policy returned an invalid status");
|
|
826
|
+
}
|
|
827
|
+
return value;
|
|
828
|
+
} catch (error) {
|
|
829
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
830
|
+
const remaining = deadline - Date.now();
|
|
831
|
+
if (!message.includes("Renderer request manager is ambiguous") || remaining <= 0) throw error;
|
|
832
|
+
await new Promise((resolve) => {
|
|
833
|
+
setTimeout(resolve, Math.min(REQUEST_MANAGER_POLL_INTERVAL_MS, remaining));
|
|
834
|
+
});
|
|
835
|
+
}
|
|
786
836
|
}
|
|
787
|
-
return value;
|
|
788
837
|
}
|
|
789
838
|
|
|
790
839
|
// packages/desktop-control/src/renderer-control-session.ts
|
|
@@ -926,14 +975,6 @@ async function activateElectronDesktop(inspector) {
|
|
|
926
975
|
}
|
|
927
976
|
return value;
|
|
928
977
|
}
|
|
929
|
-
async function quitElectronDesktop(inspector) {
|
|
930
|
-
const accepted = await inspector.evaluate(`(() => {
|
|
931
|
-
const { app } = ${electronModuleExpression};
|
|
932
|
-
setTimeout(() => app.quit(), 100);
|
|
933
|
-
return true;
|
|
934
|
-
})()`);
|
|
935
|
-
if (accepted !== true) throw new Error("Electron Desktop did not accept the quit request");
|
|
936
|
-
}
|
|
937
978
|
async function executeInWebContents(inspector, rendererWebContentsId, source) {
|
|
938
979
|
return inspector.evaluate(`(async () => {
|
|
939
980
|
const { webContents } = ${electronModuleExpression};
|
|
@@ -951,6 +992,11 @@ var defaultOperations = {
|
|
|
951
992
|
installTitlePolicy: installMainProcessTitlePolicy,
|
|
952
993
|
markTitlePolicyReady: markRendererTitlePolicyReady,
|
|
953
994
|
installDraftPrewarmPolicy: installRendererDraftPrewarmPolicy,
|
|
995
|
+
readDraftPrewarmPolicy: (inspector, rendererWebContentsId) => executeInWebContents(
|
|
996
|
+
inspector,
|
|
997
|
+
rendererWebContentsId,
|
|
998
|
+
"window.__codexhostDraftPrewarmPolicyV1?.state ?? null"
|
|
999
|
+
),
|
|
954
1000
|
reload: reloadRenderer,
|
|
955
1001
|
execute: executeInWebContents,
|
|
956
1002
|
readBinding: (inspector, rendererWebContentsId) => executeInWebContents(
|
|
@@ -958,8 +1004,7 @@ var defaultOperations = {
|
|
|
958
1004
|
rendererWebContentsId,
|
|
959
1005
|
"window.__codexhostRendererBindingProbeV1?.status() ?? null"
|
|
960
1006
|
),
|
|
961
|
-
readTitlePolicyCounters: readMainProcessTitlePolicyCounters
|
|
962
|
-
quitDesktop: quitElectronDesktop
|
|
1007
|
+
readTitlePolicyCounters: readMainProcessTitlePolicyCounters
|
|
963
1008
|
};
|
|
964
1009
|
async function waitForRenderer(inspector, operations, timeoutMs, pollIntervalMs) {
|
|
965
1010
|
const deadline = Date.now() + timeoutMs;
|
|
@@ -1022,15 +1067,41 @@ var InstalledRendererControlSession = class {
|
|
|
1022
1067
|
);
|
|
1023
1068
|
const existing = await this.operations.readBinding(this.inspector, selected.id).catch(() => null);
|
|
1024
1069
|
if (existing !== null) {
|
|
1025
|
-
const
|
|
1026
|
-
|
|
1070
|
+
const policyState = await this.operations.readDraftPrewarmPolicy?.(this.inspector, selected.id).catch(() => null);
|
|
1071
|
+
const draftPrewarmPolicy2 = policyState === "ready" ? this.#snapshot.draftPrewarmPolicy : await this.operations.installDraftPrewarmPolicy(this.inspector, selected.id);
|
|
1072
|
+
let binding2;
|
|
1073
|
+
try {
|
|
1074
|
+
binding2 = validateBindingStatus(existing, this.enabledAgents);
|
|
1075
|
+
} catch (error) {
|
|
1076
|
+
if (!(error instanceof RendererAdapterReadinessError)) throw error;
|
|
1077
|
+
await this.operations.execute(this.inspector, selected.id, this.rendererSource);
|
|
1078
|
+
binding2 = await waitForBinding(
|
|
1079
|
+
this.inspector,
|
|
1080
|
+
this.operations,
|
|
1081
|
+
selected.id,
|
|
1082
|
+
this.enabledAgents,
|
|
1083
|
+
this.timeoutMs,
|
|
1084
|
+
this.pollIntervalMs
|
|
1085
|
+
);
|
|
1086
|
+
}
|
|
1087
|
+
this.#snapshot = {
|
|
1088
|
+
...this.#snapshot,
|
|
1089
|
+
renderer: selected,
|
|
1090
|
+
draftPrewarmPolicy: draftPrewarmPolicy2,
|
|
1091
|
+
binding: binding2
|
|
1092
|
+
};
|
|
1027
1093
|
return this.#snapshot;
|
|
1028
1094
|
}
|
|
1029
1095
|
const titlePolicyReadiness = await waitForRendererTitlePolicyReady(
|
|
1030
1096
|
() => this.operations.markTitlePolicyReady(this.inspector, selected.id),
|
|
1031
1097
|
{ timeoutMs: this.timeoutMs, pollIntervalMs: this.pollIntervalMs }
|
|
1032
1098
|
);
|
|
1099
|
+
await activateElectronDesktop(this.inspector);
|
|
1033
1100
|
await this.operations.execute(this.inspector, selected.id, this.rendererSource);
|
|
1101
|
+
const draftPrewarmPolicy = await this.operations.installDraftPrewarmPolicy(
|
|
1102
|
+
this.inspector,
|
|
1103
|
+
selected.id
|
|
1104
|
+
);
|
|
1034
1105
|
const binding = await waitForBinding(
|
|
1035
1106
|
this.inspector,
|
|
1036
1107
|
this.operations,
|
|
@@ -1039,10 +1110,6 @@ var InstalledRendererControlSession = class {
|
|
|
1039
1110
|
this.timeoutMs,
|
|
1040
1111
|
this.pollIntervalMs
|
|
1041
1112
|
);
|
|
1042
|
-
const draftPrewarmPolicy = await this.operations.installDraftPrewarmPolicy(
|
|
1043
|
-
this.inspector,
|
|
1044
|
-
selected.id
|
|
1045
|
-
);
|
|
1046
1113
|
this.#snapshot = {
|
|
1047
1114
|
...this.#snapshot,
|
|
1048
1115
|
renderer: selected,
|
|
@@ -1056,10 +1123,6 @@ var InstalledRendererControlSession = class {
|
|
|
1056
1123
|
if (this.#closed) return Promise.reject(new Error("Renderer Control Session is closed"));
|
|
1057
1124
|
return activateElectronDesktop(this.inspector);
|
|
1058
1125
|
}
|
|
1059
|
-
quitDesktop() {
|
|
1060
|
-
if (this.#closed) return Promise.reject(new Error("Renderer Control Session is closed"));
|
|
1061
|
-
return this.operations.quitDesktop(this.inspector);
|
|
1062
|
-
}
|
|
1063
1126
|
async requestCompatibilityUpdate() {
|
|
1064
1127
|
const value = await this.executeRenderer(
|
|
1065
1128
|
"window.__codexhostRendererBindingProbeV1?.requestCompatibilityUpdate?.() ?? 'unavailable'"
|
|
@@ -1117,6 +1180,11 @@ async function createRendererControlSession(options) {
|
|
|
1117
1180
|
);
|
|
1118
1181
|
startupTrace("injecting Renderer bundle");
|
|
1119
1182
|
await operations.execute(options.inspector, selected.id, options.rendererSource);
|
|
1183
|
+
startupTrace("installing draft routing policy");
|
|
1184
|
+
const draftPrewarmPolicy = await operations.installDraftPrewarmPolicy(
|
|
1185
|
+
options.inspector,
|
|
1186
|
+
selected.id
|
|
1187
|
+
);
|
|
1120
1188
|
startupTrace("waiting for Renderer binding");
|
|
1121
1189
|
const binding = await waitForBinding(
|
|
1122
1190
|
options.inspector,
|
|
@@ -1126,11 +1194,6 @@ async function createRendererControlSession(options) {
|
|
|
1126
1194
|
timeoutMs,
|
|
1127
1195
|
pollIntervalMs
|
|
1128
1196
|
);
|
|
1129
|
-
startupTrace("installing draft prewarm policy");
|
|
1130
|
-
const draftPrewarmPolicy = await operations.installDraftPrewarmPolicy(
|
|
1131
|
-
options.inspector,
|
|
1132
|
-
selected.id
|
|
1133
|
-
);
|
|
1134
1197
|
return new InstalledRendererControlSession(
|
|
1135
1198
|
options.inspector,
|
|
1136
1199
|
options.rendererSource,
|
|
@@ -1351,7 +1414,7 @@ async function runDesktopController(options, signal, dependencies = defaultDepen
|
|
|
1351
1414
|
inspectorEndpoint: options.inspectorEndpoint,
|
|
1352
1415
|
rendererSource: `${configuration}
|
|
1353
1416
|
${rendererSource}`,
|
|
1354
|
-
enabledAgents: ["codex", "pi", "claude-code"],
|
|
1417
|
+
enabledAgents: ["codex", "pi", "claude-code", "deepseek-harness", "grok"],
|
|
1355
1418
|
timeoutMs: PRODUCTION_INSTALL_TIMEOUT_MS
|
|
1356
1419
|
},
|
|
1357
1420
|
dependencies
|
|
@@ -1410,10 +1473,6 @@ ${rendererSource}`,
|
|
|
1410
1473
|
compatibilityUpdate: () => useSession(async () => {
|
|
1411
1474
|
const current = await recoverSession();
|
|
1412
1475
|
return current.requestCompatibilityUpdate();
|
|
1413
|
-
}),
|
|
1414
|
-
shutdown: () => useSession(async () => {
|
|
1415
|
-
const current = await recoverSession();
|
|
1416
|
-
await current.quitDesktop();
|
|
1417
1476
|
})
|
|
1418
1477
|
});
|
|
1419
1478
|
startupTrace2("attachment server ready");
|