@openclaw/codex 2026.9.4 → 2026.9.6
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/assets/activity.svg +30 -0
- package/assets/icon.png +0 -0
- package/dist/.setup/account-usage-runtime-Eem_WGqY.mjs +75 -0
- package/dist/{apply-CvT8tW5i.js → .setup/apply-DDOi8uNx.mjs} +24 -30
- package/dist/.setup/async-questions-DdhOCwGi.mjs +27 -0
- package/dist/{attempt-client-cleanup-DKHzbwt5.js → .setup/attempt-client-cleanup-CEv1cKwF.mjs} +79 -49
- package/dist/.setup/attempt-terminal-gZrxQ35N.mjs +5 -0
- package/dist/.setup/attempt-workspace-context-DUVEn_CS.mjs +331 -0
- package/dist/{auth-binding-CWlKVccJ.js → .setup/auth-binding-DhLWa_7K.mjs} +1 -1
- package/dist/{auth-cache-key-7orQae_j.js → .setup/auth-cache-key-B2mpaI9D.mjs} +9 -81
- package/dist/{auth-profile-CwzO4_RG.js → .setup/auth-profile-WqZtZfXN.mjs} +1 -1
- package/dist/.setup/auth-profile-health-oHizqgye.mjs +53 -0
- package/dist/.setup/auth-profile-recovery-BREezV0L.mjs +14 -0
- package/dist/.setup/binding-connection-ThoatDcb.mjs +50 -0
- package/dist/.setup/binding-connection.runtime-yoHrABt-.mjs +48 -0
- package/dist/{bounded-turn-C_Hneydj.js → .setup/bounded-turn-B2HScEgT.mjs} +143 -32
- package/dist/{build-state-BCmg9-5p.js → .setup/build-state-C7EnDVgr.mjs} +1 -1
- package/dist/{capabilities-8vx68WLH.js → .setup/capabilities-CDXOOFdZ.mjs} +1 -1
- package/dist/{client-B57KWPQx.js → .setup/client-Cs08OXVQ.mjs} +705 -512
- package/dist/.setup/client-catalog-response-BMgt_4q4.mjs +285 -0
- package/dist/{command-dispatch-BpduNGVf.js → .setup/command-dispatch-B4JuOsOk.mjs} +8 -4
- package/dist/{command-formatters-lxlkNZgU.js → .setup/command-formatters-Bmqvr9tO.mjs} +8 -4
- package/dist/{command-handlers-tiL9iWj7.js → .setup/command-handlers-DW7Lx9oH.mjs} +137 -186
- package/dist/{command-rpc-CR5EOEZX.js → .setup/command-rpc-DixIj3HW.mjs} +47 -23
- package/dist/{compact-B_H3AOd7.js → .setup/compact-Du5UvtxA.mjs} +29 -51
- package/dist/{config-oIORaQ5T.js → .setup/config-BoTP_mrL.mjs} +5 -4
- package/dist/{config-options-CXMq1T-C.js → .setup/config-options-BvaRs51b.mjs} +50 -446
- package/dist/{protocol-5bh1G-H7.js → .setup/config-parsing-CcB9iPoq.mjs} +9 -51
- package/dist/{config-runtime-D0zGNIHu.js → .setup/config-runtime-C8Rw1m1m.mjs} +2 -2
- package/dist/.setup/config-security-BEReZ6go.mjs +380 -0
- package/dist/{conversation-binding-DsB4-O7U.js → .setup/conversation-binding-DP-gMrBP.mjs} +29 -38
- package/dist/{conversation-binding-data-BiodpIzq.js → .setup/conversation-binding-data-CrcyZk6O.mjs} +1 -1
- package/dist/{conversation-control-CtUu1b3m.js → .setup/conversation-control-uK9Jomlc.mjs} +32 -67
- package/dist/.setup/cyber-failover-DYwbmf1o.mjs +123 -0
- package/dist/.setup/cyber-failover-notice-e9G3J9-e.mjs +17 -0
- package/dist/{dynamic-tools-CmN5RAip.js → .setup/dynamic-tools-BDXl-8Cw.mjs} +936 -620
- package/dist/{effective-mcp-catalog-Bd73bqA8.js → .setup/effective-mcp-catalog-CvnvnGIe.mjs} +3 -3
- package/dist/{ephemeral-turn-D78_VmzO.js → .setup/ephemeral-turn-poidXgek.mjs} +9 -7
- package/dist/{event-projector-assistant-message-BmBM4qBV.js → .setup/event-projector-assistant-message-BsruvNrH.mjs} +8 -7
- package/dist/{event-projector-items-5VhsECCO.js → .setup/event-projector-items-C6L_5ZiT.mjs} +42 -8
- package/dist/{attempt-notifications-C9XufG6l.js → .setup/event-projector-usage-CnBS8Wa3.mjs} +102 -9
- package/dist/{harness-C7rRa7bm.js → .setup/harness-a_MsE4-_.mjs} +81 -21
- package/dist/{inference-context-Dr_mzvk4.js → .setup/inference-context-D96l9-ew.mjs} +1 -1
- package/dist/.setup/inference-proxy-b-aJMSxm.mjs +601 -0
- package/dist/{isolated-completion-DWVb5U2J.js → .setup/isolated-completion-BIZFhTNG.mjs} +18 -11
- package/dist/.setup/launch-args-DbFCehO7.mjs +196 -0
- package/dist/{managed-binary-D22rNEcR.js → .setup/managed-binary-BnshlFag.mjs} +14 -3
- package/dist/{managed-thread-store-D1t5jh3G.js → .setup/managed-thread-store-BMqgThVL.mjs} +48 -14
- package/dist/{model-catalog-Dq2n8f_p.js → .setup/model-catalog-CfXJf9Ay.mjs} +36 -12
- package/dist/{models-PCKOim-h.js → .setup/models-KnqBv0hE.mjs} +3 -3
- package/dist/.setup/native-auth-rWbGbMn3.mjs +57 -0
- package/dist/{native-subagent-history-DjtPloaU.js → .setup/native-subagent-history-0nYYgo0k.mjs} +43 -35
- package/dist/.setup/native-subagent-monitor-D3filLY2.mjs +4859 -0
- package/dist/{native-subagent-task-ids-BzTdT0Uw.js → .setup/native-subagent-task-ids-wb8CKZGN.mjs} +98 -44
- package/dist/{node-cli-sessions-DKaOmVUh.js → .setup/node-cli-sessions-r3avj02l.mjs} +86 -68
- package/dist/.setup/node-exec-server.runtime-BDwWXVpK.mjs +247 -0
- package/dist/{plan-7uG-Fp36.js → .setup/plan-CN3VwfNU.mjs} +133 -119
- package/dist/{plugin-activation-BYQculil.js → .setup/plugin-activation-DT3MNtqj.mjs} +7 -16
- package/dist/{plugin-app-cache-key-d0eKxy7b.js → .setup/plugin-app-cache-key-B2CsSdnV.mjs} +32 -44
- package/dist/{plugin-approval-roundtrip-Bz3FT8W5.js → .setup/plugin-approval-roundtrip-C0MZzCuP.mjs} +1 -1
- package/dist/{plugin-inventory-oL4Na1ZG.js → .setup/plugin-inventory-BoRei8Z4.mjs} +21 -11
- package/dist/{plugin-marketplace-discovery-P-Vndfqq.js → .setup/plugin-marketplace-discovery-CDOi8IFs.mjs} +4 -1
- package/dist/{plugin-metadata-cache-ClPJpRio.js → .setup/plugin-metadata-cache-Ctmo83k_.mjs} +226 -141
- package/dist/.setup/protocol-CANUwXJ3.mjs +17 -0
- package/dist/{provider-MQ8PVkuE.js → .setup/provider-BOsxQHOM.mjs} +9 -5
- package/dist/{provider-capabilities-BvCUL69A.js → .setup/provider-capabilities-BfE88FZ5.mjs} +31 -3
- package/dist/{rate-limits-CBMmWBr9.js → .setup/rate-limits-CMU3DUD0.mjs} +174 -151
- package/dist/{request-B7hEkBGq.js → .setup/request-D2L0zMrq.mjs} +130 -42
- package/dist/{run-attempt-CvsAAGa0.js → .setup/run-attempt-BHu11r7h.mjs} +1628 -966
- package/dist/.setup/run-attempt-lifecycle-B7JbY4-F.mjs +71 -0
- package/dist/{runtime-artifact-BJ0rXBZ_.js → .setup/runtime-artifact-CLZ8udh-.mjs} +29 -45
- package/dist/{sandbox-guard-BxgyoM8M.js → .setup/sandbox-guard-C2sRMOEY.mjs} +3 -3
- package/dist/{session-binding-CI8UuilT.js → .setup/session-binding-Cm0apEbd.mjs} +36 -83
- package/dist/{session-binding-record-Bcvslnhf.js → .setup/session-binding-record-BGoz8wOK.mjs} +202 -5
- package/dist/.setup/session-binding-sidecars-BlB5EvIS.mjs +546 -0
- package/dist/.setup/session-catalog-Pno1xGcl.mjs +2764 -0
- package/dist/{session-catalog-adoption-tcZi1IfX.js → .setup/session-catalog-adoption-BI6UTDZT.mjs} +58 -26
- package/dist/{session-catalog-archive-CwKg8Xz2.js → .setup/session-catalog-archive-lHBqzhaO.mjs} +6 -6
- package/dist/.setup/session-catalog-events-Bj6j94E_.mjs +347 -0
- package/dist/.setup/session-catalog-index-B9_VQIUz.mjs +1170 -0
- package/dist/.setup/session-catalog-index-order-hcdz07yN.mjs +48 -0
- package/dist/.setup/session-catalog-index-state-Dgh8ORJm.mjs +183 -0
- package/dist/{thread-history-page-D0JIp48V.js → .setup/session-catalog-native-projection-DowriLid.mjs} +223 -95
- package/dist/{session-catalog-node-adoption-B1tgDW-m.js → .setup/session-catalog-node-adoption-ITddWx_X.mjs} +25 -13
- package/dist/{session-catalog-node-continue-Ci-DXyJP.js → .setup/session-catalog-node-continue-6g6qi4A9.mjs} +24 -15
- package/dist/.setup/session-catalog-projection-zK_PUsiE.mjs +422 -0
- package/dist/{session-cli-DNN_jhGc.js → .setup/session-cli-irrD-uo7.mjs} +3 -3
- package/dist/{session-history-Cz-tOOYj.js → .setup/session-history-BrqhSCf9.mjs} +19 -19
- package/dist/{session-history-import-DwyijFI6.js → .setup/session-history-import-D-3wAgOP.mjs} +4 -4
- package/dist/{session-history-read-cxPUxyVV.js → .setup/session-history-read-B3ZfSUbF.mjs} +2 -2
- package/dist/{session-history.worker-BeK1YOyT.js → .setup/session-history.worker-CaCh0xF_.mjs} +10 -24
- package/dist/{session-initialization-Ct0_Hzmg.js → .setup/session-initialization-rcgbZiid.mjs} +2 -2
- package/dist/{session-permission-policy-BBmXA8Eg.js → .setup/session-permission-policy-BI1QK_98.mjs} +2 -2
- package/dist/{session-retirement-B2YfbAAT.js → .setup/session-retirement-BH-S6qkJ.mjs} +26 -7
- package/dist/{settled-turn-context-Du6gdUDd.js → .setup/settled-turn-context-fmwouT5I.mjs} +2 -2
- package/dist/{settled-turn-finalizer-Dn91stmc.js → .setup/settled-turn-finalizer-DiAi6Kx6.mjs} +12 -12
- package/dist/{shared-client-CscigXXL.js → .setup/shared-client-DA4VR4Eb.mjs} +332 -221
- package/dist/{side-question-BGMJQf4U.js → .setup/side-question-BJ1wSDcB.mjs} +183 -230
- package/dist/{source-CElXU0Oy.js → .setup/source-CUzJq5WN.mjs} +11 -10
- package/dist/.setup/spawn-error-CL3n6MAa.mjs +57 -0
- package/dist/{thread-archive-guard-DfpBr-Sz.js → .setup/thread-archive-guard-C9frICzX.mjs} +10 -3
- package/dist/.setup/thread-history-page-DoVpnHim.mjs +83 -0
- package/dist/{thread-lifecycle-DXl1-I6b.js → .setup/thread-lifecycle-B3mfz1TG.mjs} +347 -2318
- package/dist/{thread-ownership-BsDRTsyp.js → .setup/thread-ownership-DcTtAcXj.mjs} +6 -4
- package/dist/{thread-policy-BuEQfE0g.js → .setup/thread-policy-DGuQsuFC.mjs} +19 -3
- package/dist/.setup/thread-requests-BLvGkP2R.mjs +2205 -0
- package/dist/{thread-resume-DsDOZpFg.js → .setup/thread-resume-DIBXwOpE.mjs} +8 -5
- package/dist/.setup/timeout-C910MdAB.mjs +80 -0
- package/dist/{transcript-history-projection-v17wXgdK.js → .setup/transcript-history-projection-ZZpkFkJ_.mjs} +96 -61
- package/dist/{transcript-mirror-C5CKgNy6.js → .setup/transcript-mirror-BtHDBp1G.mjs} +224 -195
- package/dist/{transcript-mirror-attestation-DibE0krH.js → .setup/transcript-mirror-attestation-CzM-94NC.mjs} +4 -1
- package/dist/{transport-stdio-BGjHoYLr.js → .setup/transport-stdio-h2VHOskC.mjs} +274 -89
- package/dist/{upstream-session-fork-BZerMte_.js → .setup/upstream-session-fork-BUr4OUbC.mjs} +51 -42
- package/dist/{usage-tCk-mg_x.js → .setup/usage-BML0r-ua.mjs} +5 -4
- package/dist/.setup/usage-limit-error-DUMbefVY.mjs +166 -0
- package/dist/{web-search-provider.runtime-B7bGbGWq.js → .setup/web-search-provider.runtime-CDKlN-Rv.mjs} +4 -3
- package/dist/api.js +23 -12
- package/dist/catalog-page-worker-entrypoint.js +12 -0
- package/dist/catalog-page.worker.js +9 -0
- package/dist/cli-metadata.js +1 -1
- package/dist/doctor-contract-api.js +8 -528
- package/dist/harness.js +1 -1
- package/dist/index.js +306 -215
- package/dist/media-understanding-provider.js +3 -3
- package/dist/migration-provider-api.js +1 -1
- package/dist/native-tool-policy.js +12 -0
- package/dist/provider-discovery.js +18 -0
- package/dist/session-history-worker-runtime.js +36 -35
- package/dist/session-history.worker.js +2 -2
- package/dist/web-search-contract-api.js +1 -1
- package/openclaw.plugin.json +354 -69
- package/package.json +14 -8
- package/dist/attempt-context-D44yeDII.js +0 -636
- package/dist/binding-connection-D3udKbIE.js +0 -60
- package/dist/event-projector-usage-BfXmpOec.js +0 -102
- package/dist/inference-proxy-HGXKUIre.js +0 -311
- package/dist/launch-args-RXQwn8zV.js +0 -90
- package/dist/native-subagent-history-owner-Pcp7JuVF.js +0 -34
- package/dist/native-subagent-monitor-fQ7eIXEf.js +0 -2978
- package/dist/node-exec-server.runtime-Cl2vapEi.js +0 -226
- package/dist/rpc-error-ttN_QjEm.js +0 -30
- package/dist/session-catalog-ct-AH01I.js +0 -1477
- package/dist/session-catalog-home-id-CwhLdC03.js +0 -18
- package/dist/session-catalog-provenance-D-dIfRAH.js +0 -96
- package/dist/timeout-BVw8aaM1.js +0 -33
- package/dist/version-omm6IPI3.js +0 -12
- /package/dist/{auth-profile-selection-DFu9e167.js → .setup/auth-profile-selection-DFu9e167.mjs} +0 -0
- /package/dist/{config-utils-DujwEnhg.js → .setup/config-utils-DujwEnhg.mjs} +0 -0
- /package/dist/{context-compaction-activity-CMla5FPJ.js → .setup/context-compaction-activity-CMla5FPJ.mjs} +0 -0
- /package/dist/{elicitation-input-DPoK8F7w.js → .setup/elicitation-input-DPoK8F7w.mjs} +0 -0
- /package/dist/{history-rejection-B4nOXNXF.js → .setup/history-rejection-B4nOXNXF.mjs} +0 -0
- /package/dist/{image-payload-sanitizer-tupAr-2o.js → .setup/image-payload-sanitizer-tupAr-2o.mjs} +0 -0
- /package/dist/{incognito-session-uhrBF6wJ.js → .setup/incognito-session-uhrBF6wJ.mjs} +0 -0
- /package/dist/{local-runtime-attribution-B_2mnqhb.js → .setup/local-runtime-attribution-B_2mnqhb.mjs} +0 -0
- /package/dist/{native-execution-policy-umd0tgh4.js → .setup/native-execution-policy-umd0tgh4.mjs} +0 -0
- /package/dist/{rolldown-runtime-8H4AJuhK.js → .setup/rolldown-runtime-8H4AJuhK.mjs} +0 -0
- /package/dist/{session-binding-meta-B7aEMU7g.js → .setup/session-binding-meta-B7aEMU7g.mjs} +0 -0
- /package/dist/{session-upstream-marker-D15C9NHp.js → .setup/session-upstream-marker-D15C9NHp.mjs} +0 -0
- /package/dist/{upstream-prompt-provenance-LphB8slG.js → .setup/upstream-prompt-provenance-LphB8slG.mjs} +0 -0
- /package/dist/{web-search-provider.shared-BrZmlqyR.js → .setup/web-search-provider.shared-BrZmlqyR.mjs} +0 -0
|
@@ -0,0 +1,601 @@
|
|
|
1
|
+
import { i as isJsonObject } from "./protocol-CANUwXJ3.mjs";
|
|
2
|
+
import { n as createCodexInferenceContext } from "./inference-context-D96l9-ew.mjs";
|
|
3
|
+
import { promisify } from "node:util";
|
|
4
|
+
import { zstdCompress, zstdDecompress } from "node:zlib";
|
|
5
|
+
import { Writable, getDefaultHighWaterMark } from "node:stream";
|
|
6
|
+
import { WebSocket, WebSocketServer, rejectWebSocketUpgrade } from "openclaw/plugin-sdk/websocket-runtime";
|
|
7
|
+
import { createServer } from "node:http";
|
|
8
|
+
import { createPermitPool } from "openclaw/plugin-sdk/concurrency-runtime";
|
|
9
|
+
import { createNodeProxyAgent } from "openclaw/plugin-sdk/fetch-runtime";
|
|
10
|
+
import { generateSecureToken } from "openclaw/plugin-sdk/secure-random-runtime";
|
|
11
|
+
import { fetchWithSsrFGuard, isBlockedHostnameOrIp, resolvePinnedHostnameWithPolicy } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
12
|
+
//#region extensions/codex/src/app-server/inference-upload.ts
|
|
13
|
+
const MAX_BODY_BYTES = 33554432;
|
|
14
|
+
function createUploadAdmission() {
|
|
15
|
+
const permits = createPermitPool(16);
|
|
16
|
+
let outstanding = 0;
|
|
17
|
+
let queuedBytes = 0;
|
|
18
|
+
return async (signal, deadlineAtMs, bytes = 0) => {
|
|
19
|
+
const queued = outstanding >= 16;
|
|
20
|
+
if (outstanding >= 32 || queued && queuedBytes + bytes > 33554432) return null;
|
|
21
|
+
outstanding++;
|
|
22
|
+
if (queued) queuedBytes += bytes;
|
|
23
|
+
const releasePermit = await permits.acquire({
|
|
24
|
+
signal,
|
|
25
|
+
deadlineAtMs
|
|
26
|
+
});
|
|
27
|
+
if (queued) queuedBytes -= bytes;
|
|
28
|
+
let released = false;
|
|
29
|
+
const release = () => {
|
|
30
|
+
if (released) return;
|
|
31
|
+
released = true;
|
|
32
|
+
outstanding--;
|
|
33
|
+
releasePermit?.();
|
|
34
|
+
};
|
|
35
|
+
if (!releasePermit || signal.aborted) {
|
|
36
|
+
release();
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
return release;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function createUploadBody(bytes, signal, release) {
|
|
43
|
+
const length = bytes.length;
|
|
44
|
+
const chunkSize = getDefaultHighWaterMark(false);
|
|
45
|
+
let remaining = bytes;
|
|
46
|
+
let offset = 0;
|
|
47
|
+
const settle = () => {
|
|
48
|
+
remaining = void 0;
|
|
49
|
+
signal.removeEventListener("abort", settle);
|
|
50
|
+
release();
|
|
51
|
+
};
|
|
52
|
+
signal.addEventListener("abort", settle, { once: true });
|
|
53
|
+
if (signal.aborted) settle();
|
|
54
|
+
return {
|
|
55
|
+
body: new ReadableStream({
|
|
56
|
+
pull(controller) {
|
|
57
|
+
signal.throwIfAborted();
|
|
58
|
+
if (!remaining || offset === length) {
|
|
59
|
+
settle();
|
|
60
|
+
controller.close();
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const end = Math.min(offset + chunkSize, length);
|
|
64
|
+
controller.enqueue(Uint8Array.from(remaining.subarray(offset, end)));
|
|
65
|
+
offset = end;
|
|
66
|
+
},
|
|
67
|
+
cancel: settle
|
|
68
|
+
}, { highWaterMark: 0 }),
|
|
69
|
+
length,
|
|
70
|
+
settle
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region extensions/codex/src/app-server/inference-proxy.ts
|
|
75
|
+
const MAX_ERROR_BODY_BYTES = 1048576;
|
|
76
|
+
const MAX_WEBSOCKETS = 64;
|
|
77
|
+
const MAX_RESIDENTS = 80;
|
|
78
|
+
const REQUEST_TIMEOUT_MS = 3e4;
|
|
79
|
+
const HANDSHAKE_TIMEOUT_MS = 1e4;
|
|
80
|
+
const IDLE_WEBSOCKET_MS = 6e4;
|
|
81
|
+
const OVERLOADED = "Codex inference relay is busy; retry on a fresh connection.";
|
|
82
|
+
const OVERLOAD_HEADERS = {
|
|
83
|
+
"content-type": "application/json",
|
|
84
|
+
"retry-after": "1"
|
|
85
|
+
};
|
|
86
|
+
const OVERLOAD_BODY = JSON.stringify({
|
|
87
|
+
type: "error",
|
|
88
|
+
status: 503,
|
|
89
|
+
error: {
|
|
90
|
+
type: "server_error",
|
|
91
|
+
code: "inference_relay_busy",
|
|
92
|
+
message: OVERLOADED
|
|
93
|
+
},
|
|
94
|
+
headers: { "retry-after": "1" }
|
|
95
|
+
});
|
|
96
|
+
const compress = promisify(zstdCompress);
|
|
97
|
+
const decompress = promisify(zstdDecompress);
|
|
98
|
+
const HOP_HEADERS = /* @__PURE__ */ new Set([
|
|
99
|
+
"connection",
|
|
100
|
+
"keep-alive",
|
|
101
|
+
"proxy-authenticate",
|
|
102
|
+
"proxy-authorization",
|
|
103
|
+
"te",
|
|
104
|
+
"trailer",
|
|
105
|
+
"transfer-encoding",
|
|
106
|
+
"upgrade",
|
|
107
|
+
"host",
|
|
108
|
+
"content-length"
|
|
109
|
+
]);
|
|
110
|
+
const FAILURE = "Codex parent-local inference transport failed; retry on a fresh connection.";
|
|
111
|
+
/** Private, fixed-destination relay. No upstream credentials or model content are retained. */
|
|
112
|
+
async function createCodexInferenceProxy(params) {
|
|
113
|
+
const upstream = new URL(params.upstream);
|
|
114
|
+
if (upstream.protocol !== "https:" || upstream.username || upstream.password || upstream.hash) throw new Error("Codex inference requires a credential-free HTTPS upstream URL");
|
|
115
|
+
const lifetime = new AbortController();
|
|
116
|
+
const assertCurrent = () => {
|
|
117
|
+
lifetime.signal.throwIfAborted();
|
|
118
|
+
params.assertCurrent();
|
|
119
|
+
};
|
|
120
|
+
const context = createCodexInferenceContext(assertCurrent);
|
|
121
|
+
const pathPrefix = "/" + generateSecureToken({
|
|
122
|
+
bytes: 32,
|
|
123
|
+
redact: true
|
|
124
|
+
}) + upstream.pathname.replace(/\/$/, "");
|
|
125
|
+
const acquireUpload = createUploadAdmission();
|
|
126
|
+
const connections = /* @__PURE__ */ new Set();
|
|
127
|
+
const idleConnections = /* @__PURE__ */ new Set();
|
|
128
|
+
const residents = createPermitPool(MAX_RESIDENTS);
|
|
129
|
+
const tickets = /* @__PURE__ */ new Set();
|
|
130
|
+
const reclaimIdle = () => {
|
|
131
|
+
if (tickets.size < MAX_RESIDENTS || idleConnections.size === 0) return;
|
|
132
|
+
let acquired = 0;
|
|
133
|
+
let waiting = false;
|
|
134
|
+
let retiring = false;
|
|
135
|
+
for (const ticket of tickets) {
|
|
136
|
+
retiring ||= ticket.retiring;
|
|
137
|
+
if (ticket.release) acquired++;
|
|
138
|
+
else if (ticket.pending && !ticket.signal.aborted && Date.now() < ticket.deadlineAtMs) waiting = true;
|
|
139
|
+
}
|
|
140
|
+
if (!retiring && acquired === MAX_RESIDENTS && waiting) idleConnections.values().next().value?.();
|
|
141
|
+
};
|
|
142
|
+
const reserveResident = (socket, signal, deadlineAtMs) => {
|
|
143
|
+
if (tickets.size >= 96) return null;
|
|
144
|
+
const ticket = {
|
|
145
|
+
signal,
|
|
146
|
+
deadlineAtMs,
|
|
147
|
+
pending: true,
|
|
148
|
+
release: null,
|
|
149
|
+
retiring: false
|
|
150
|
+
};
|
|
151
|
+
tickets.add(ticket);
|
|
152
|
+
let finished = false;
|
|
153
|
+
const settle = () => {
|
|
154
|
+
if (!finished || !socket.closed || ticket.pending || !tickets.delete(ticket)) return;
|
|
155
|
+
socket.off("close", settle);
|
|
156
|
+
ticket.release?.();
|
|
157
|
+
ticket.release = null;
|
|
158
|
+
reclaimIdle();
|
|
159
|
+
};
|
|
160
|
+
socket.once("close", settle);
|
|
161
|
+
const ready = residents.acquire({
|
|
162
|
+
signal,
|
|
163
|
+
deadlineAtMs
|
|
164
|
+
}).then((release) => {
|
|
165
|
+
ticket.pending = false;
|
|
166
|
+
if (release && signal.aborted) release();
|
|
167
|
+
else ticket.release = release;
|
|
168
|
+
settle();
|
|
169
|
+
reclaimIdle();
|
|
170
|
+
return ticket.release !== null;
|
|
171
|
+
});
|
|
172
|
+
reclaimIdle();
|
|
173
|
+
return {
|
|
174
|
+
ready,
|
|
175
|
+
retireIdle() {
|
|
176
|
+
ticket.retiring = true;
|
|
177
|
+
},
|
|
178
|
+
finish() {
|
|
179
|
+
finished = true;
|
|
180
|
+
settle();
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
};
|
|
184
|
+
const wss = new WebSocketServer({
|
|
185
|
+
noServer: true,
|
|
186
|
+
maxPayload: MAX_BODY_BYTES,
|
|
187
|
+
perMessageDeflate: false
|
|
188
|
+
});
|
|
189
|
+
const handshakeHeaders = /* @__PURE__ */ new WeakMap();
|
|
190
|
+
wss.on("headers", (headers, request) => {
|
|
191
|
+
for (const [key, value] of Object.entries(handshakeHeaders.get(request) ?? {})) if (!key.startsWith("sec-websocket-")) headers.push(key + ": " + value);
|
|
192
|
+
handshakeHeaders.delete(request);
|
|
193
|
+
});
|
|
194
|
+
const resolveTarget = (request) => {
|
|
195
|
+
assertCurrent();
|
|
196
|
+
if (request.headers.origin || !request.url?.startsWith(pathPrefix + "/") || isBlockedHostnameOrIp(upstream.hostname)) throw new Error(FAILURE);
|
|
197
|
+
const suffix = request.url.slice(pathPrefix.length);
|
|
198
|
+
if (suffix.startsWith("//") || suffix.includes("\\") || /%2e|%2f|%5c|(?:^|\/)\.\.?(?:\/|\?|$)/i.test(suffix)) throw new Error(FAILURE);
|
|
199
|
+
const target = new URL(upstream);
|
|
200
|
+
const incoming = new URL(suffix, "http://localhost");
|
|
201
|
+
target.pathname = upstream.pathname.replace(/\/$/, "") + incoming.pathname;
|
|
202
|
+
for (const [key, value] of incoming.searchParams) target.searchParams.append(key, value);
|
|
203
|
+
return {
|
|
204
|
+
target,
|
|
205
|
+
sampling: incoming.pathname === "/responses"
|
|
206
|
+
};
|
|
207
|
+
};
|
|
208
|
+
const prepare = (bytes, sampling) => {
|
|
209
|
+
assertCurrent();
|
|
210
|
+
if (!sampling) return {
|
|
211
|
+
bytes,
|
|
212
|
+
assertCurrent,
|
|
213
|
+
signal: void 0
|
|
214
|
+
};
|
|
215
|
+
const value = JSON.parse(bytes.toString("utf8"));
|
|
216
|
+
if (!isJsonObject(value)) throw new Error(FAILURE);
|
|
217
|
+
const prepared = context.prepare(value);
|
|
218
|
+
const rewritten = Buffer.from(JSON.stringify(prepared.body));
|
|
219
|
+
if (rewritten.length > 33554432) throw new Error(FAILURE);
|
|
220
|
+
return {
|
|
221
|
+
bytes: rewritten,
|
|
222
|
+
assertCurrent: prepared.assertCurrent,
|
|
223
|
+
signal: prepared.signal
|
|
224
|
+
};
|
|
225
|
+
};
|
|
226
|
+
const prepareHttp = async (req, sampling, signal, release) => {
|
|
227
|
+
const wire = await readProxyBody(req, MAX_BODY_BYTES);
|
|
228
|
+
const encoding = req.headers["content-encoding"];
|
|
229
|
+
if (encoding && encoding !== "identity" && encoding !== "zstd") throw new Error(FAILURE);
|
|
230
|
+
const decoded = encoding === "zstd" ? await decompress(wire, { maxOutputLength: MAX_BODY_BYTES }) : wire;
|
|
231
|
+
signal.throwIfAborted();
|
|
232
|
+
const prepared = prepare(decoded, sampling);
|
|
233
|
+
const body = encoding === "zstd" ? await compress(prepared.bytes) : prepared.bytes;
|
|
234
|
+
prepared.assertCurrent();
|
|
235
|
+
const requestSignal = AbortSignal.any([signal, ...prepared.signal ? [prepared.signal] : []]);
|
|
236
|
+
return {
|
|
237
|
+
...createUploadBody(body, requestSignal, release),
|
|
238
|
+
assertCurrent: prepared.assertCurrent,
|
|
239
|
+
signal: requestSignal
|
|
240
|
+
};
|
|
241
|
+
};
|
|
242
|
+
const server = createServer((req, res) => {
|
|
243
|
+
const socket = req.socket;
|
|
244
|
+
res.setHeader("Connection", "close");
|
|
245
|
+
const controller = new AbortController();
|
|
246
|
+
const signal = AbortSignal.any([lifetime.signal, controller.signal]);
|
|
247
|
+
const deadlineAtMs = Date.now() + REQUEST_TIMEOUT_MS;
|
|
248
|
+
let releasePermit = null;
|
|
249
|
+
let resident = null;
|
|
250
|
+
let upload;
|
|
251
|
+
let guarded;
|
|
252
|
+
const abort = () => controller.abort();
|
|
253
|
+
req.once("aborted", abort);
|
|
254
|
+
res.once("close", abort);
|
|
255
|
+
(async () => {
|
|
256
|
+
try {
|
|
257
|
+
const { target, sampling } = resolveTarget(req);
|
|
258
|
+
if (req.method !== "POST") throw new Error(FAILURE);
|
|
259
|
+
resident = reserveResident(socket, signal, deadlineAtMs);
|
|
260
|
+
const admitted = resident && await resident.ready;
|
|
261
|
+
signal.throwIfAborted();
|
|
262
|
+
assertCurrent();
|
|
263
|
+
if (!admitted) {
|
|
264
|
+
res.writeHead(503, OVERLOAD_HEADERS).end(OVERLOAD_BODY);
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
releasePermit = await acquireUpload(signal, deadlineAtMs);
|
|
268
|
+
signal.throwIfAborted();
|
|
269
|
+
assertCurrent();
|
|
270
|
+
if (!releasePermit) {
|
|
271
|
+
res.writeHead(503, OVERLOAD_HEADERS).end(OVERLOAD_BODY);
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
upload = await prepareHttp(req, sampling, signal, releasePermit);
|
|
275
|
+
const init = {
|
|
276
|
+
method: "POST",
|
|
277
|
+
headers: {
|
|
278
|
+
...relayHeaders(req.headers),
|
|
279
|
+
"content-length": String(upload.length)
|
|
280
|
+
},
|
|
281
|
+
body: upload.body,
|
|
282
|
+
signal: upload.signal,
|
|
283
|
+
duplex: "half"
|
|
284
|
+
};
|
|
285
|
+
guarded = await fetchWithSsrFGuard({
|
|
286
|
+
url: target.toString(),
|
|
287
|
+
init,
|
|
288
|
+
signal: upload.signal,
|
|
289
|
+
beforeRequest: upload.assertCurrent,
|
|
290
|
+
requireHttps: true,
|
|
291
|
+
maxRedirects: 0,
|
|
292
|
+
capture: false,
|
|
293
|
+
mode: "trusted_env_proxy",
|
|
294
|
+
auditContext: "codex-parent-local-inference"
|
|
295
|
+
});
|
|
296
|
+
upload.assertCurrent();
|
|
297
|
+
const headers = Object.fromEntries(guarded.response.headers);
|
|
298
|
+
delete headers["content-encoding"];
|
|
299
|
+
res.writeHead(guarded.response.status, relayHeaders(headers));
|
|
300
|
+
if (!guarded.response.body) res.end();
|
|
301
|
+
else await guarded.response.body.pipeTo(Writable.toWeb(res), { signal: upload.signal });
|
|
302
|
+
} catch {
|
|
303
|
+
if (!res.headersSent && !res.destroyed) res.writeHead(502, { "content-type": "text/plain" }).end(FAILURE);
|
|
304
|
+
else res.destroy();
|
|
305
|
+
} finally {
|
|
306
|
+
upload?.settle();
|
|
307
|
+
releasePermit?.();
|
|
308
|
+
req.off("aborted", abort);
|
|
309
|
+
res.off("close", abort);
|
|
310
|
+
await guarded?.release().catch(() => void 0);
|
|
311
|
+
resident?.finish();
|
|
312
|
+
}
|
|
313
|
+
})();
|
|
314
|
+
});
|
|
315
|
+
server.maxConnections = 128;
|
|
316
|
+
server.requestTimeout = REQUEST_TIMEOUT_MS;
|
|
317
|
+
server.headersTimeout = HANDSHAKE_TIMEOUT_MS;
|
|
318
|
+
server.on("upgrade", (req, socket, head) => {
|
|
319
|
+
(async () => {
|
|
320
|
+
let remote;
|
|
321
|
+
let local;
|
|
322
|
+
let proxyAgent;
|
|
323
|
+
let upstreamClosed = Promise.resolve();
|
|
324
|
+
let finishSetup = () => {};
|
|
325
|
+
const setupSettled = new Promise((resolve) => {
|
|
326
|
+
finishSetup = resolve;
|
|
327
|
+
});
|
|
328
|
+
let resident = null;
|
|
329
|
+
const controller = new AbortController();
|
|
330
|
+
const deadlineAtMs = Date.now() + HANDSHAKE_TIMEOUT_MS;
|
|
331
|
+
let releasePermit = null;
|
|
332
|
+
let framePending = false;
|
|
333
|
+
let idleTimer;
|
|
334
|
+
let handshakeTimer;
|
|
335
|
+
let closing = false;
|
|
336
|
+
const close = () => {
|
|
337
|
+
if (closing) return;
|
|
338
|
+
closing = true;
|
|
339
|
+
if (idleConnections.has(close)) resident?.retireIdle();
|
|
340
|
+
clearTimeout(idleTimer);
|
|
341
|
+
clearTimeout(handshakeTimer);
|
|
342
|
+
socket.off("end", close);
|
|
343
|
+
connections.delete(close);
|
|
344
|
+
idleConnections.delete(close);
|
|
345
|
+
controller.abort();
|
|
346
|
+
remote?.terminate();
|
|
347
|
+
local?.terminate();
|
|
348
|
+
proxyAgent?.destroy();
|
|
349
|
+
socket.destroy();
|
|
350
|
+
setupSettled.then(() => upstreamClosed).then(() => {
|
|
351
|
+
releasePermit?.();
|
|
352
|
+
releasePermit = null;
|
|
353
|
+
resident?.finish();
|
|
354
|
+
});
|
|
355
|
+
};
|
|
356
|
+
try {
|
|
357
|
+
const { target, sampling } = resolveTarget(req);
|
|
358
|
+
if (!sampling) throw new Error(FAILURE);
|
|
359
|
+
if (connections.size >= MAX_WEBSOCKETS) idleConnections.values().next().value?.();
|
|
360
|
+
if (connections.size >= MAX_WEBSOCKETS) {
|
|
361
|
+
rejectBusyUpgrade(socket);
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
connections.add(close);
|
|
365
|
+
socket.once("close", close);
|
|
366
|
+
socket.once("error", close);
|
|
367
|
+
socket.once("end", close);
|
|
368
|
+
const signal = AbortSignal.any([lifetime.signal, controller.signal]);
|
|
369
|
+
resident = reserveResident(socket, signal, deadlineAtMs);
|
|
370
|
+
const admitted = resident && await resident.ready;
|
|
371
|
+
signal.throwIfAborted();
|
|
372
|
+
assertCurrent();
|
|
373
|
+
if (!admitted) {
|
|
374
|
+
rejectBusyUpgrade(socket);
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
releasePermit = await acquireUpload(signal, deadlineAtMs);
|
|
378
|
+
signal.throwIfAborted();
|
|
379
|
+
assertCurrent();
|
|
380
|
+
if (!releasePermit) {
|
|
381
|
+
rejectBusyUpgrade(socket);
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
handshakeTimer = setTimeout(close, Math.max(1, deadlineAtMs - Date.now()));
|
|
385
|
+
handshakeTimer.unref();
|
|
386
|
+
const assertHandshakeCurrent = () => {
|
|
387
|
+
assertCurrent();
|
|
388
|
+
signal.throwIfAborted();
|
|
389
|
+
if (Date.now() >= deadlineAtMs) throw new Error(FAILURE);
|
|
390
|
+
};
|
|
391
|
+
proxyAgent = createNodeProxyAgent({
|
|
392
|
+
mode: "env",
|
|
393
|
+
targetUrl: target.href
|
|
394
|
+
});
|
|
395
|
+
const lookup = proxyAgent ? void 0 : (await resolvePinnedHostnameWithPolicy(target.hostname, { signal })).lookup;
|
|
396
|
+
assertHandshakeCurrent();
|
|
397
|
+
target.protocol = "wss:";
|
|
398
|
+
const headers = relayHeaders(req.headers);
|
|
399
|
+
for (const key of Object.keys(headers)) if (key.startsWith("sec-websocket-")) delete headers[key];
|
|
400
|
+
remote = new WebSocket(target, {
|
|
401
|
+
headers,
|
|
402
|
+
...proxyAgent ? { agent: proxyAgent } : { lookup },
|
|
403
|
+
followRedirects: false,
|
|
404
|
+
perMessageDeflate: false,
|
|
405
|
+
maxPayload: MAX_BODY_BYTES,
|
|
406
|
+
handshakeTimeout: Math.max(1, deadlineAtMs - Date.now()),
|
|
407
|
+
finishRequest(request) {
|
|
408
|
+
let socketClosed = Promise.resolve();
|
|
409
|
+
request.once("socket", (upstreamSocket) => {
|
|
410
|
+
socketClosed = new Promise((resolve) => {
|
|
411
|
+
upstreamSocket.once("close", () => resolve());
|
|
412
|
+
});
|
|
413
|
+
});
|
|
414
|
+
upstreamClosed = new Promise((resolve) => {
|
|
415
|
+
request.once("close", () => {
|
|
416
|
+
socketClosed.then(resolve);
|
|
417
|
+
});
|
|
418
|
+
});
|
|
419
|
+
request.end();
|
|
420
|
+
}
|
|
421
|
+
});
|
|
422
|
+
remote.once("upgrade", (response) => {
|
|
423
|
+
handshakeHeaders.set(req, relayHeaders(response.headers));
|
|
424
|
+
});
|
|
425
|
+
remote.once("error", close);
|
|
426
|
+
remote.once("close", close);
|
|
427
|
+
remote.once("unexpected-response", (_request, response) => {
|
|
428
|
+
(async () => {
|
|
429
|
+
try {
|
|
430
|
+
const body = await readProxyBody(response, MAX_ERROR_BODY_BYTES);
|
|
431
|
+
assertCurrent();
|
|
432
|
+
signal.throwIfAborted();
|
|
433
|
+
const failureHeaders = Object.entries(relayHeaders(response.headers)).map(([key, value]) => key + ": " + value);
|
|
434
|
+
failureHeaders.push("Connection: close", "Content-Length: " + body.length);
|
|
435
|
+
const status = "HTTP/1.1 " + response.statusCode + " " + (response.statusMessage ?? "Upstream refused");
|
|
436
|
+
socket.end(Buffer.concat([Buffer.from(status + "\r\n" + failureHeaders.join("\r\n") + "\r\n\r\n"), body]), close);
|
|
437
|
+
} catch {
|
|
438
|
+
close();
|
|
439
|
+
}
|
|
440
|
+
})();
|
|
441
|
+
});
|
|
442
|
+
remote.once("open", () => {
|
|
443
|
+
try {
|
|
444
|
+
assertHandshakeCurrent();
|
|
445
|
+
wss.handleUpgrade(req, socket, head, (accepted) => {
|
|
446
|
+
clearTimeout(handshakeTimer);
|
|
447
|
+
socket.off("end", close);
|
|
448
|
+
local = accepted;
|
|
449
|
+
accepted.once("error", close);
|
|
450
|
+
accepted.once("close", close);
|
|
451
|
+
let releaseFrame = () => {};
|
|
452
|
+
const idle = (reclaimable = true) => {
|
|
453
|
+
framePending = false;
|
|
454
|
+
idleConnections.delete(close);
|
|
455
|
+
if (reclaimable) idleConnections.add(close);
|
|
456
|
+
clearTimeout(idleTimer);
|
|
457
|
+
idleTimer = setTimeout(close, IDLE_WEBSOCKET_MS);
|
|
458
|
+
idleTimer.unref();
|
|
459
|
+
reclaimIdle();
|
|
460
|
+
};
|
|
461
|
+
releasePermit?.();
|
|
462
|
+
releasePermit = null;
|
|
463
|
+
idle(false);
|
|
464
|
+
const forward = async (prepared) => {
|
|
465
|
+
let releaseUpload = null;
|
|
466
|
+
try {
|
|
467
|
+
const requestSignal = AbortSignal.any([signal, ...prepared.signal ? [prepared.signal] : []]);
|
|
468
|
+
releaseUpload = await acquireUpload(requestSignal, Date.now() + REQUEST_TIMEOUT_MS, prepared.bytes.length);
|
|
469
|
+
requestSignal.throwIfAborted();
|
|
470
|
+
prepared.assertCurrent();
|
|
471
|
+
if (!releaseUpload) {
|
|
472
|
+
accepted.send(OVERLOAD_BODY, { binary: false }, close);
|
|
473
|
+
return;
|
|
474
|
+
}
|
|
475
|
+
if (!remote || remote.readyState !== WebSocket.OPEN || remote.bufferedAmount + prepared.bytes.length > 33554432) throw new Error(FAILURE);
|
|
476
|
+
const release = releaseUpload;
|
|
477
|
+
remote.send(prepared.bytes, { binary: false }, (error) => {
|
|
478
|
+
release();
|
|
479
|
+
if (error) close();
|
|
480
|
+
});
|
|
481
|
+
} catch {
|
|
482
|
+
releaseUpload?.();
|
|
483
|
+
close();
|
|
484
|
+
}
|
|
485
|
+
};
|
|
486
|
+
accepted.on("message", (data, binary) => {
|
|
487
|
+
try {
|
|
488
|
+
if (binary) throw new Error(FAILURE);
|
|
489
|
+
const prepared = prepare(rawBytes(data), true);
|
|
490
|
+
prepared.assertCurrent();
|
|
491
|
+
if (framePending) throw new Error(FAILURE);
|
|
492
|
+
framePending = true;
|
|
493
|
+
clearTimeout(idleTimer);
|
|
494
|
+
idleConnections.delete(close);
|
|
495
|
+
releaseFrame();
|
|
496
|
+
const onAbort = () => close();
|
|
497
|
+
const frameSignal = prepared.signal;
|
|
498
|
+
frameSignal?.addEventListener("abort", onAbort, { once: true });
|
|
499
|
+
releaseFrame = () => frameSignal?.removeEventListener("abort", onAbort);
|
|
500
|
+
forward(prepared);
|
|
501
|
+
} catch {
|
|
502
|
+
close();
|
|
503
|
+
}
|
|
504
|
+
});
|
|
505
|
+
accepted.once("close", () => releaseFrame());
|
|
506
|
+
remote.on("message", (data, binary) => {
|
|
507
|
+
if (accepted.readyState !== WebSocket.OPEN || accepted.bufferedAmount + rawBytes(data).length > 33554432) {
|
|
508
|
+
close();
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
511
|
+
const terminal = !binary && isTerminalResponse(rawBytes(data));
|
|
512
|
+
accepted.send(data, { binary }, (error) => {
|
|
513
|
+
if (error) close();
|
|
514
|
+
else if (terminal && connections.has(close)) idle();
|
|
515
|
+
});
|
|
516
|
+
});
|
|
517
|
+
});
|
|
518
|
+
} catch {
|
|
519
|
+
close();
|
|
520
|
+
}
|
|
521
|
+
});
|
|
522
|
+
} catch {
|
|
523
|
+
close();
|
|
524
|
+
} finally {
|
|
525
|
+
finishSetup();
|
|
526
|
+
}
|
|
527
|
+
})();
|
|
528
|
+
});
|
|
529
|
+
const close = () => {
|
|
530
|
+
lifetime.abort();
|
|
531
|
+
context.close();
|
|
532
|
+
for (const closeConnection of connections) closeConnection();
|
|
533
|
+
server.close();
|
|
534
|
+
server.closeAllConnections();
|
|
535
|
+
wss.close();
|
|
536
|
+
};
|
|
537
|
+
try {
|
|
538
|
+
await new Promise((resolve, reject) => {
|
|
539
|
+
server.once("error", reject);
|
|
540
|
+
server.listen(0, "127.0.0.1", () => {
|
|
541
|
+
server.off("error", reject);
|
|
542
|
+
resolve();
|
|
543
|
+
});
|
|
544
|
+
});
|
|
545
|
+
assertCurrent();
|
|
546
|
+
server.on("error", close);
|
|
547
|
+
const address = server.address();
|
|
548
|
+
if (!address || typeof address === "string") throw new Error(FAILURE);
|
|
549
|
+
return {
|
|
550
|
+
context,
|
|
551
|
+
upstream: upstream.toString(),
|
|
552
|
+
baseUrl: "http://127.0.0.1:" + address.port + pathPrefix,
|
|
553
|
+
assertCurrent,
|
|
554
|
+
close
|
|
555
|
+
};
|
|
556
|
+
} catch (error) {
|
|
557
|
+
close();
|
|
558
|
+
throw error;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
function rejectBusyUpgrade(socket) {
|
|
562
|
+
rejectWebSocketUpgrade(socket, {
|
|
563
|
+
status: 503,
|
|
564
|
+
headers: { "Retry-After": "1" },
|
|
565
|
+
body: {
|
|
566
|
+
contentType: "application/json",
|
|
567
|
+
text: OVERLOAD_BODY
|
|
568
|
+
}
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
function isTerminalResponse(bytes) {
|
|
572
|
+
try {
|
|
573
|
+
const event = JSON.parse(bytes.toString("utf8"));
|
|
574
|
+
return isJsonObject(event) && (event.type === "response.failed" || event.type === "response.incomplete" || event.type === "response.completed" && isJsonObject(event.response) && typeof event.response.id === "string");
|
|
575
|
+
} catch {
|
|
576
|
+
return false;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
async function readProxyBody(stream, maxBytes) {
|
|
580
|
+
const chunks = [];
|
|
581
|
+
let size = 0;
|
|
582
|
+
for await (const chunk of stream) {
|
|
583
|
+
const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
584
|
+
size += bytes.length;
|
|
585
|
+
if (size > maxBytes) throw new Error(FAILURE);
|
|
586
|
+
chunks.push(bytes);
|
|
587
|
+
}
|
|
588
|
+
return Buffer.concat(chunks);
|
|
589
|
+
}
|
|
590
|
+
function rawBytes(data) {
|
|
591
|
+
return Array.isArray(data) ? Buffer.concat(data) : Buffer.isBuffer(data) ? data : Buffer.from(data);
|
|
592
|
+
}
|
|
593
|
+
function relayHeaders(input) {
|
|
594
|
+
const excluded = new Set(HOP_HEADERS);
|
|
595
|
+
for (const token of (input.connection ?? "").split(",")) excluded.add(token.trim().toLowerCase());
|
|
596
|
+
const output = {};
|
|
597
|
+
for (const [key, value] of Object.entries(input)) if (value !== void 0 && !excluded.has(key.toLowerCase())) output[key.toLowerCase()] = Array.isArray(value) ? value.join(", ") : value;
|
|
598
|
+
return output;
|
|
599
|
+
}
|
|
600
|
+
//#endregion
|
|
601
|
+
export { createCodexInferenceProxy };
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import "./config-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
1
|
+
import { d as readCodexPluginConfig } from "./config-parsing-CcB9iPoq.mjs";
|
|
2
|
+
import { n as isCodexAppServerProxyLaunch } from "./launch-args-DbFCehO7.mjs";
|
|
3
|
+
import { i as resolveCodexAppServerHomeScope } from "./config-options-BvaRs51b.mjs";
|
|
4
|
+
import "./config-BoTP_mrL.mjs";
|
|
5
|
+
import { n as resolveCodexAppServerRuntimeOptions } from "./config-runtime-C8Rw1m1m.mjs";
|
|
6
|
+
import { Z as resolveCodexAppServerPreparedAuthHandoff } from "./shared-client-DA4VR4Eb.mjs";
|
|
7
|
+
import { _ as assertCodexPassiveTurnItems } from "./client-Cs08OXVQ.mjs";
|
|
8
|
+
import { runBoundedCodexAppServerTurn } from "./bounded-turn-B2HScEgT.mjs";
|
|
9
|
+
import { a as createAttributedCodexAssistantMessage } from "./event-projector-assistant-message-BsruvNrH.mjs";
|
|
8
10
|
//#region extensions/codex/src/app-server/isolated-completion.ts
|
|
9
11
|
/** Runs prompt-only Codex inference on an ephemeral, ring-zero native thread. */
|
|
10
12
|
async function runCodexIsolatedCompletion(params, options) {
|
|
@@ -12,13 +14,16 @@ async function runCodexIsolatedCompletion(params, options) {
|
|
|
12
14
|
const authorization = params.authorization;
|
|
13
15
|
if (authorization.owner !== "harness") throw new Error("Codex native isolated completion requires harness-owned authorization.");
|
|
14
16
|
const pluginConfig = readCodexPluginConfig(options.pluginConfig);
|
|
17
|
+
const homeScope = resolveCodexAppServerHomeScope({ appServer: pluginConfig.appServer });
|
|
18
|
+
const { start } = resolveCodexAppServerRuntimeOptions({ pluginConfig: options.pluginConfig });
|
|
19
|
+
const privateStdio = start.transport === "stdio" && homeScope === "agent" && !isCodexAppServerProxyLaunch(start.args);
|
|
15
20
|
const authRequirement = authorization.plan.modelRoute?.authRequirement;
|
|
16
21
|
const authHandoff = await resolveCodexAppServerPreparedAuthHandoff({
|
|
17
22
|
authRequirement,
|
|
18
23
|
authProfileId: authorization.plan.forwardedAuthProfileId,
|
|
19
24
|
authProfileStore: authorization.authProfileStore,
|
|
20
25
|
agentDir: params.agentDir,
|
|
21
|
-
homeScope
|
|
26
|
+
homeScope,
|
|
22
27
|
config: params.config,
|
|
23
28
|
subscriptionProfileRequiredError: "Prepared Codex subscription route requires a scoped native OAuth or token profile.",
|
|
24
29
|
subscriptionProfileUnusableError: `Prepared Codex auth profile "${authorization.plan.forwardedAuthProfileId}" is unusable.`
|
|
@@ -34,6 +39,7 @@ async function runCodexIsolatedCompletion(params, options) {
|
|
|
34
39
|
...authSelection,
|
|
35
40
|
authRequirement,
|
|
36
41
|
timeoutMs: params.timeoutMs,
|
|
42
|
+
thinkLevel: params.thinkLevel,
|
|
37
43
|
signal: params.abortSignal,
|
|
38
44
|
assertCurrent: params.assertCurrent,
|
|
39
45
|
agentDir: params.agentDir,
|
|
@@ -47,11 +53,12 @@ async function runCodexIsolatedCompletion(params, options) {
|
|
|
47
53
|
text_elements: []
|
|
48
54
|
}],
|
|
49
55
|
requiredModalities: ["text"],
|
|
50
|
-
isolation: "configured-transport",
|
|
51
|
-
requireNoExternalCapabilities: true
|
|
56
|
+
isolation: privateStdio ? "private-stdio" : "configured-transport",
|
|
57
|
+
requireNoExternalCapabilities: true,
|
|
58
|
+
allowEmptyText: params.outputTextPolicy === "strict-visible"
|
|
52
59
|
});
|
|
53
60
|
params.assertCurrent?.();
|
|
54
|
-
assertCodexPassiveTurnItems(result.items, params.prompt, "isolated completion");
|
|
61
|
+
assertCodexPassiveTurnItems(result.items, params.prompt, "isolated completion", { allowManagedHookPrompts: result.managedHooksEnabled });
|
|
55
62
|
return { assistant: createAttributedCodexAssistantMessage({
|
|
56
63
|
api: "openai-chatgpt-responses",
|
|
57
64
|
provider: params.provider,
|