@openclaw/codex 2026.9.5 → 2026.9.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/assets/icon.png +0 -0
- package/dist/.setup/{account-usage-runtime-C2MOIvfq.mjs → account-usage-runtime-DFhbh1zz.mjs} +6 -6
- package/dist/.setup/{apply-CJ0ZfmBG.mjs → apply-D3GcSoSa.mjs} +35 -55
- package/dist/.setup/{attempt-client-cleanup-BpYKdTA0.mjs → attempt-client-cleanup-DOP-cW5j.mjs} +179 -73
- package/dist/.setup/attempt-workspace-context-C5HigshI.mjs +164 -0
- package/dist/.setup/{auth-binding-DhLWa_7K.mjs → auth-binding-BLWz7stm.mjs} +14 -1
- package/dist/.setup/{auth-cache-key-QirmgiCo.mjs → auth-cache-key-Dbvq-QgB.mjs} +41 -111
- package/dist/.setup/{auth-profile-WqZtZfXN.mjs → auth-profile-B0okYl2D.mjs} +1 -2
- package/dist/.setup/auth-profile-health-oHizqgye.mjs +53 -0
- package/dist/.setup/auth-profile-recovery-BREezV0L.mjs +14 -0
- package/dist/.setup/auth-start-options-BPIPeEX8.mjs +44 -0
- package/dist/.setup/{binding-connection-Bm38niE8.mjs → binding-connection-DTtN1KrX.mjs} +2 -2
- package/dist/.setup/{binding-connection.runtime-CnRMC0ta.mjs → binding-connection.runtime-6TpgD1M6.mjs} +5 -5
- package/dist/.setup/{bounded-turn-BtlZcivC.mjs → bounded-turn-CbjoN2OW.mjs} +140 -37
- package/dist/.setup/bounded-turn-isolation-B8K_ylqk.mjs +14 -0
- package/dist/.setup/{build-state-Xx9ybZqa.mjs → build-state-Da1_z0kd.mjs} +1 -1
- package/dist/.setup/{capabilities-_vXcZGSx.mjs → capabilities-B3WEZl4e.mjs} +2 -10
- package/dist/.setup/{client-vXs2929Q.mjs → client-N0JpgSzF.mjs} +635 -872
- package/dist/.setup/client-catalog-response-5HHLdcde.mjs +285 -0
- package/dist/.setup/{command-dispatch-naHIZwwF.mjs → command-dispatch-BeAoaovI.mjs} +9 -8
- package/dist/.setup/{command-formatters-CGEkdawF.mjs → command-formatters-R3ckE3Co.mjs} +36 -64
- package/dist/.setup/{command-handlers-BtAJEW1X.mjs → command-handlers-ylTMS00z.mjs} +301 -488
- package/dist/.setup/{command-rpc-DHFpn4le.mjs → command-rpc-CGJGUQ6Y.mjs} +40 -28
- package/dist/.setup/compact-C2WamavS.mjs +776 -0
- package/dist/.setup/{config-CedDWjM-.mjs → config-DKhXquav.mjs} +26 -28
- package/dist/.setup/{config-options-BsanJ8QG.mjs → config-options-CzyWLTJt.mjs} +68 -65
- package/dist/.setup/{config-parsing-CcB9iPoq.mjs → config-parsing-b088LyhT.mjs} +57 -60
- package/dist/.setup/{config-runtime-CeAhl_h4.mjs → config-runtime-C0NbLms1.mjs} +2 -2
- package/dist/.setup/{config-security-BRQ2mgW9.mjs → config-security-CE-FcGw9.mjs} +51 -215
- package/dist/.setup/{config-utils-DujwEnhg.mjs → config-utils-D0CXecki.mjs} +3 -13
- package/dist/.setup/context-engine-projection-PezSESth.mjs +387 -0
- package/dist/.setup/{conversation-binding-DhzrpTM6.mjs → conversation-binding-3Min8qvP.mjs} +71 -105
- package/dist/.setup/{conversation-binding-data-CrcyZk6O.mjs → conversation-binding-data-C746z5Pn.mjs} +8 -12
- package/dist/.setup/{conversation-control-DN53ns41.mjs → conversation-control-CEP8X5JC.mjs} +30 -69
- package/dist/.setup/{cyber-failover-DYwbmf1o.mjs → cyber-failover-XV0nNRZu.mjs} +1 -1
- package/dist/.setup/{cyber-failover-notice-e9G3J9-e.mjs → cyber-failover-notice-RNpGpTyP.mjs} +1 -1
- package/dist/.setup/{dynamic-tools-D16lOp67.mjs → dynamic-tools-DzlsLUuS.mjs} +3136 -3167
- package/dist/.setup/{effective-mcp-catalog-K6kLCN8X.mjs → effective-mcp-catalog-CxUtC-xG.mjs} +8 -17
- package/dist/.setup/{ephemeral-turn-R1gA8Sn6.mjs → ephemeral-turn-CDsPJOa2.mjs} +9 -6
- package/dist/.setup/event-projector-assistant-message-CigreO4K.mjs +69 -0
- package/dist/.setup/{event-projector-usage-C7Ntzs-f.mjs → event-projector-usage-03R0I2dM.mjs} +4 -26
- package/dist/.setup/event-projector-values-DJSz8BTk.mjs +106 -0
- package/dist/.setup/incognito-session-DWYapfwf.mjs +2 -0
- package/dist/.setup/{inference-context-fulhZuz8.mjs → inference-context-D-9gWlTR.mjs} +16 -18
- package/dist/.setup/inference-dispatch-CMZtjQyz.mjs +359 -0
- package/dist/.setup/inference-metadata-CgIf7sOx.mjs +81 -0
- package/dist/.setup/inference-proxy-DhcXOgUE.mjs +561 -0
- package/dist/.setup/{isolated-completion-B6srt48J.mjs → isolated-completion-Dm3PzxJk.mjs} +15 -11
- package/dist/.setup/launch-args-DbFCehO7.mjs +196 -0
- package/dist/.setup/{managed-binary-DP6Rib3P.mjs → managed-binary-kiWRhNRE.mjs} +16 -9
- package/dist/.setup/{model-catalog-DkvUuBey.mjs → model-catalog-PAuZgJC6.mjs} +14 -14
- package/dist/.setup/model-runtime-BdqzOMkU.mjs +11 -0
- package/dist/.setup/{models-BDFgm_G-.mjs → models-DHXZtVVk.mjs} +9 -18
- package/dist/.setup/{native-auth-BLZGqFjw.mjs → native-auth-CuG53tu4.mjs} +5 -5
- package/dist/.setup/{native-execution-policy-YBMHSzC4.mjs → native-execution-policy-BxZJy5mP.mjs} +6 -31
- package/dist/.setup/{native-subagent-monitor-B1hxzIOy.mjs → native-subagent-monitor-Dpsmf2wz.mjs} +4422 -3808
- package/dist/.setup/native-subagent-pending-assignments-DwkCzLvD.mjs +203 -0
- package/dist/.setup/native-task-assignments-DMQ0g3hu.mjs +194 -0
- package/dist/.setup/{node-cli-sessions-Cl8b2ZF3.mjs → node-cli-sessions-HC4W6FLI.mjs} +99 -111
- package/dist/.setup/node-exec-server.runtime-BgBfWQqo.mjs +244 -0
- package/dist/.setup/{plan-xD7WKYTM.mjs → plan-Y-QIvrKB.mjs} +118 -163
- package/dist/.setup/{plugin-activation-r8nq5Jzp.mjs → plugin-activation-cNHRfaxU.mjs} +10 -47
- package/dist/.setup/{plugin-app-cache-key-BOxKP7db.mjs → plugin-app-cache-key-BL9B5H0L.mjs} +9 -42
- package/dist/.setup/{plugin-inventory-DUle8DLz.mjs → plugin-inventory-Cky2XJUw.mjs} +32 -23
- package/dist/.setup/{plugin-marketplace-discovery-P-Vndfqq.mjs → plugin-marketplace-discovery-D_dV9FXa.mjs} +22 -25
- package/dist/.setup/{plugin-metadata-cache-DsS5buNa.mjs → plugin-metadata-cache-DsjsL1dr.mjs} +328 -318
- package/dist/.setup/protocol-CANUwXJ3.mjs +17 -0
- package/dist/.setup/provider-DH8NSzGt.mjs +51 -0
- package/dist/.setup/{provider-capabilities-B8J4Dy-O.mjs → provider-capabilities-CAxoF-X1.mjs} +35 -12
- package/dist/.setup/{rate-limits-DOEGYRNs.mjs → rate-limits-B7-X2TgG.mjs} +123 -166
- package/dist/.setup/{request-BioXJLYa.mjs → request-BHZ1nz8d.mjs} +25 -16
- package/dist/.setup/responses-oauth-twnuTaAa.mjs +93 -0
- package/dist/.setup/rpc-error-BlD2vuzn.mjs +31 -0
- package/dist/.setup/{run-attempt-rlA07pUv.mjs → run-attempt-D8RZUOzY.mjs} +2046 -1454
- package/dist/.setup/{run-attempt-lifecycle-B7JbY4-F.mjs → run-attempt-lifecycle-C-6O3Exn.mjs} +10 -24
- package/dist/.setup/{runtime-artifact-Dy38Z5iU.mjs → runtime-artifact-DDQ-HGXf.mjs} +43 -47
- package/dist/.setup/runtime-artifact-connection-D68qQn1m.mjs +78 -0
- package/dist/.setup/sandbox-guard-DjCz2eOw.mjs +126 -0
- package/dist/.setup/scope-DOC1Xjc8.mjs +6 -0
- package/dist/.setup/session-binding-DGCYAfvD.mjs +443 -0
- package/dist/.setup/{session-binding-record-TH3xA0zj.mjs → session-binding-record-Oe9L-CNY.mjs} +73 -132
- package/dist/.setup/{session-binding-sidecars-CKYEcfNn.mjs → session-binding-sidecars-jo6H8dFr.mjs} +242 -60
- package/dist/.setup/{session-catalog-fUdWDx-U.mjs → session-catalog-4sCdv5qx.mjs} +598 -452
- package/dist/.setup/{session-catalog-adoption-CR_whkEW.mjs → session-catalog-adoption-BU_pHWG7.mjs} +59 -26
- package/dist/.setup/{session-catalog-archive-CwZaPacf.mjs → session-catalog-archive-spHfihri.mjs} +7 -7
- package/dist/.setup/session-catalog-events-DePDzzjc.mjs +139 -0
- package/dist/.setup/session-catalog-home-id-vlih0B_g.mjs +22 -0
- package/dist/.setup/{session-catalog-index-B141u15s.mjs → session-catalog-index-CZvDzC6z.mjs} +286 -182
- package/dist/.setup/{session-catalog-index-order-Cc5BzlQr.mjs → session-catalog-index-order-BcQpHks3.mjs} +2 -2
- package/dist/.setup/{session-catalog-index-state-BAuDztHN.mjs → session-catalog-index-state-TeO7EyO-.mjs} +6 -2
- package/dist/.setup/session-catalog-limits-DDxOsQeC.mjs +14 -0
- package/dist/.setup/session-catalog-list-request-CvtxrYSe.mjs +170 -0
- package/dist/.setup/session-catalog-native-projection-DjhwGL6x.mjs +178 -0
- package/dist/.setup/{session-catalog-node-adoption-BVRsYOSh.mjs → session-catalog-node-adoption-DgXvSGu0.mjs} +30 -35
- package/dist/.setup/{session-catalog-node-continue-Dowv8osw.mjs → session-catalog-node-continue-DjKXHBbi.mjs} +25 -18
- package/dist/.setup/session-catalog-node-lookup-CtAXI5W5.mjs +56 -0
- package/dist/.setup/{session-catalog-native-projection-ChV3cCtm.mjs → session-catalog-parsing-CPGaPYr-.mjs} +14 -180
- package/dist/.setup/{session-catalog-projection-C1Bj9Jl-.mjs → session-catalog-projection-Cr5qP5Dj.mjs} +15 -5
- package/dist/.setup/session-catalog-provenance-DoAvktcj.mjs +95 -0
- package/dist/.setup/{session-cli-DIj-IE-E.mjs → session-cli-Cn_nCqfq.mjs} +11 -24
- package/dist/.setup/{session-history-C--SrLI8.mjs → session-history-D83lJWHG.mjs} +16 -23
- package/dist/.setup/{session-history-import-JHXT5Xfi.mjs → session-history-import-WhX-X33a.mjs} +7 -10
- package/dist/.setup/session-history-read-Ov3StuL4.mjs +133 -0
- package/dist/.setup/{session-history.worker-CpNj7H_P.mjs → session-history.worker-MnPKncqP.mjs} +14 -23
- package/dist/.setup/session-initialization-6aveB9qb.mjs +22 -0
- package/dist/.setup/{session-permission-policy-DhurXY0l.mjs → session-permission-policy-Ci_fVX6y.mjs} +4 -8
- package/dist/.setup/{session-retirement-CU87AOg9.mjs → session-retirement-qMTxkNx2.mjs} +31 -12
- package/dist/.setup/{settled-turn-context-fmwouT5I.mjs → settled-turn-context-D4yj4rxf.mjs} +1 -1
- package/dist/.setup/{settled-turn-finalizer-CiY2bLFK.mjs → settled-turn-finalizer-BsvEabkw.mjs} +17 -13
- package/dist/.setup/{shared-client-BpTtuLQ5.mjs → shared-client-DqyTMYug.mjs} +826 -485
- package/dist/.setup/shared-client-lifecycle-DJIgqgMw.mjs +153 -0
- package/dist/.setup/{side-question-DSCZyoBD.mjs → side-question-C4kCmQy1.mjs} +206 -334
- package/dist/.setup/{source-Bjp4UQij.mjs → source-CS_7GFJZ.mjs} +82 -139
- package/dist/.setup/spawn-error-CL3n6MAa.mjs +57 -0
- package/dist/.setup/{thread-archive-guard-jmecf6OJ.mjs → thread-archive-guard-C9frICzX.mjs} +10 -3
- package/dist/.setup/thread-lifecycle-DPflntEJ.mjs +2362 -0
- package/dist/.setup/{incognito-session-uhrBF6wJ.mjs → thread-ownership-queue-Dp24d7-F.mjs} +1 -2
- package/dist/.setup/{thread-ownership-skomxnIt.mjs → thread-ownership-roNP0l1c.mjs} +47 -10
- package/dist/.setup/thread-policy-DTd-DtkX.mjs +109 -0
- package/dist/.setup/thread-requests-B_bRnMGN.mjs +2102 -0
- package/dist/.setup/{thread-resume-BkNpj9Pz.mjs → thread-resume-CdDaoc7T.mjs} +6 -6
- package/dist/.setup/timeout-CXOfNoaX.mjs +46 -0
- package/dist/.setup/transcript-history-projection-DRSifI-1.mjs +201 -0
- package/dist/.setup/{transcript-mirror-attestation-CzM-94NC.mjs → transcript-mirror-attestation-YSegaktH.mjs} +3 -4
- package/dist/.setup/{transcript-mirror-D4qp_leP.mjs → transcript-mirror-kxmCYsuF.mjs} +224 -206
- package/dist/.setup/{transport-stdio-Cmx94Oiy.mjs → transport-stdio-Bdegpn2V.mjs} +138 -75
- package/dist/.setup/transport-websocket-BTBE-LD9.mjs +211 -0
- package/dist/.setup/{upstream-prompt-provenance-LphB8slG.mjs → upstream-prompt-provenance-fXkKbPVC.mjs} +3 -9
- package/dist/.setup/{upstream-session-fork-D3UKxgVD.mjs → upstream-session-fork-CBeVjBpT.mjs} +48 -40
- package/dist/.setup/{usage-BOgBEKso.mjs → usage-BMzNxeR_.mjs} +5 -4
- package/dist/.setup/{usage-limit-error-C0ow7DOc.mjs → usage-limit-error-QXerDo3i.mjs} +5 -20
- package/dist/.setup/{web-search-provider.runtime-CTGuJt6i.mjs → web-search-provider.runtime-P77OUeoo.mjs} +10 -20
- package/dist/api.js +25 -16
- 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 +50 -8
- package/dist/harness.js +344 -1
- package/dist/index.js +345 -346
- package/dist/media-understanding-provider.js +9 -22
- package/dist/migration-provider-api.js +1 -1
- package/dist/provider-discovery.js +1 -1
- package/dist/session-history-worker-runtime.js +16 -33
- package/dist/session-history.worker.js +1 -1
- package/openclaw.plugin.json +14 -2
- package/package.json +11 -7
- package/dist/.setup/attempt-context-VXVwTCfS.mjs +0 -636
- package/dist/.setup/compact-C3i3qlzj.mjs +0 -687
- package/dist/.setup/event-projector-assistant-message-DNUR1s0A.mjs +0 -105
- package/dist/.setup/event-projector-items-DyTQ_XqL.mjs +0 -200
- package/dist/.setup/harness-rxaaoN-o.mjs +0 -349
- package/dist/.setup/history-rejection-B4nOXNXF.mjs +0 -13
- package/dist/.setup/image-payload-sanitizer-tupAr-2o.mjs +0 -79
- package/dist/.setup/inference-proxy-CC15HuSi.mjs +0 -311
- package/dist/.setup/launch-args-DnMak49W.mjs +0 -111
- package/dist/.setup/local-runtime-attribution-B_2mnqhb.mjs +0 -19
- package/dist/.setup/native-subagent-history-YXaL6dMd.mjs +0 -135
- package/dist/.setup/native-subagent-task-ids-DsuOonKv.mjs +0 -411
- package/dist/.setup/node-exec-server.runtime-BaViBKNz.mjs +0 -226
- package/dist/.setup/plugin-approval-roundtrip-CjfzafAZ.mjs +0 -122
- package/dist/.setup/provider-fFh_-VR3.mjs +0 -50
- package/dist/.setup/rolldown-runtime-8H4AJuhK.mjs +0 -14
- package/dist/.setup/sandbox-guard-BBP-RbTf.mjs +0 -166
- package/dist/.setup/session-binding-_0W_fHRr.mjs +0 -721
- package/dist/.setup/session-catalog-events-jMcYfQyd.mjs +0 -250
- package/dist/.setup/session-history-read-B3ZfSUbF.mjs +0 -50
- package/dist/.setup/session-initialization-DH1z6fXn.mjs +0 -75
- package/dist/.setup/thread-history-page-BTx-4xsg.mjs +0 -83
- package/dist/.setup/thread-lifecycle-Cik28qWn.mjs +0 -4904
- package/dist/.setup/thread-policy-Cjs4B8xf.mjs +0 -54
- package/dist/.setup/timeout-DZF05XrR.mjs +0 -63
- package/dist/.setup/transcript-history-projection-DHNBDhCU.mjs +0 -243
- package/dist/.setup/version-CoqzXPgK.mjs +0 -12
|
@@ -1,39 +1,236 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { i as
|
|
7
|
-
import "./config-
|
|
8
|
-
import {
|
|
1
|
+
import { a as stringifyCodexAppServerMessage, c as isRpcResponse, i as readCodexCatalogDecodeRoute, n as projectCodexCatalogMessage, o as CodexAppServerMessageDecoder, r as listenCodexAppServerLines, s as redactCodexAppServerLinePreview } from "./client-catalog-response-5HHLdcde.mjs";
|
|
2
|
+
import { i as isJsonObject } from "./protocol-CANUwXJ3.mjs";
|
|
3
|
+
import { c as MIN_SUPPORTED_CODEX_APP_SERVER_VERSION, s as CODEX_APP_SERVER_VERSION } from "./managed-binary-kiWRhNRE.mjs";
|
|
4
|
+
import { a as closeCodexAppServerTransportAndWait, i as closeCodexAppServerTransport, o as hasCodexAppServerNaturalExit, t as createStdioTransport } from "./transport-stdio-Bdegpn2V.mjs";
|
|
5
|
+
import { n as CodexAppServerRpcError, t as CODEX_APP_SERVER_OVERLOADED_ERROR_CODE } from "./rpc-error-BlD2vuzn.mjs";
|
|
6
|
+
import { f as recordCodexCatalogResponseSource, i as reuseCodexCatalogPreview, o as closeCodexCatalogClientSource, s as codexCatalogSourceForClient } from "./session-catalog-native-projection-DjhwGL6x.mjs";
|
|
7
|
+
import { n as resolveCodexAppServerRuntimeOptions } from "./config-runtime-C0NbLms1.mjs";
|
|
8
|
+
import { codexCatalogPageWorkerEntrypoint } from "../catalog-page-worker-entrypoint.js";
|
|
9
|
+
import { t as createWebSocketTransport } from "./transport-websocket-BTBE-LD9.mjs";
|
|
10
|
+
import { t as __exportAll } from "./session-binding-sidecars-jo6H8dFr.mjs";
|
|
9
11
|
import { isRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
10
12
|
import { randomUUID } from "node:crypto";
|
|
11
|
-
import { addSafeTimeoutDelayGraceMs, addTimerTimeoutGraceMs, parseStrictNonNegativeInteger } from "openclaw/plugin-sdk/number-runtime";
|
|
12
13
|
import { normalizeJsonSchemaForTypeBox } from "openclaw/plugin-sdk/json-schema-runtime";
|
|
14
|
+
import { addSafeTimeoutDelayGraceMs, addTimerTimeoutGraceMs, parseStrictNonNegativeInteger } from "openclaw/plugin-sdk/number-runtime";
|
|
13
15
|
import path from "node:path";
|
|
14
|
-
import { EventEmitter } from "node:events";
|
|
15
16
|
import { coerceErrorMessage, toStringifiedError } from "openclaw/plugin-sdk/error-runtime";
|
|
16
17
|
import { sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
18
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
17
19
|
import { hasPendingInternalDiagnosticEvent } from "openclaw/plugin-sdk/diagnostic-runtime";
|
|
18
20
|
import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
|
|
19
21
|
import { OPENCLAW_VERSION, embeddedAgentLog, formatToolExecutionErrorMessage, normalizeQuestionTimeoutSeconds, resolveToolExecutionErrorKind } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
20
|
-
import { createInterface } from "node:readline";
|
|
21
22
|
import { parse } from "semver";
|
|
22
|
-
import {
|
|
23
|
-
import { copyInternalToolResultState } from "openclaw/plugin-sdk/agent-harness-tool-runtime";
|
|
23
|
+
import { AsyncWorkScope } from "openclaw/plugin-sdk/concurrency-runtime";
|
|
24
|
+
import { copyInternalToolResultState, runWithAsyncWorkResources } from "openclaw/plugin-sdk/agent-harness-tool-runtime";
|
|
24
25
|
import { Compile } from "typebox/compile";
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
function
|
|
31
|
-
|
|
26
|
+
//#region extensions/codex/src/app-server/client-catalog-worker.ts
|
|
27
|
+
const INLINE_CATALOG_MAX_BYTES = 65536;
|
|
28
|
+
const CATALOG_WORKER_IDLE_MS = 6e4;
|
|
29
|
+
const runInCatalogWorkerContext = AsyncLocalStorage.snapshot();
|
|
30
|
+
/** Late responses retain their decode route after cancellation removes the waiter. */
|
|
31
|
+
function codexCatalogRequestId(method, params, sequence, catalogPreview) {
|
|
32
|
+
const kind = catalogPreview ? method === "thread/list" ? "list" : method === "thread/read" && isJsonObject(params) && params.includeTurns !== true ? "thread" : void 0 : void 0;
|
|
33
|
+
return kind ? Number.MAX_SAFE_INTEGER - 2 * sequence - (kind === "thread" ? 1 : 0) : sequence;
|
|
34
|
+
}
|
|
35
|
+
/** Each physical client owns one decoder, including incomplete-line recovery state. */
|
|
36
|
+
var CodexCatalogWorker = class {
|
|
37
|
+
constructor() {
|
|
38
|
+
this.setTimeoutFn = setTimeout;
|
|
39
|
+
this.clearTimeoutFn = clearTimeout;
|
|
40
|
+
this.closed = false;
|
|
41
|
+
}
|
|
42
|
+
get continuation() {
|
|
43
|
+
return this.continuationRoute;
|
|
44
|
+
}
|
|
45
|
+
async decode(line, route, attempts, projections) {
|
|
46
|
+
if (this.closed) return;
|
|
47
|
+
if (!this.continuationRoute && route !== "unresolved" && line.byteLength <= INLINE_CATALOG_MAX_BYTES) {
|
|
48
|
+
let parsed;
|
|
49
|
+
try {
|
|
50
|
+
parsed = JSON.parse(line.toString("utf8"));
|
|
51
|
+
} catch {}
|
|
52
|
+
if (parsed !== void 0) {
|
|
53
|
+
await Promise.resolve();
|
|
54
|
+
if (this.closed) return;
|
|
55
|
+
const attempt = attempts.get(route.id);
|
|
56
|
+
const projection = attempt ? projections.get(attempt) : void 0;
|
|
57
|
+
return projectCodexCatalogMessage(parsed, {
|
|
58
|
+
route,
|
|
59
|
+
remainingRows: attempt ? projection?.remainingRows : 0
|
|
60
|
+
}, projection?.preview);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
this.clearTimeoutFn(this.idleTimer);
|
|
64
|
+
this.idleTimer = void 0;
|
|
65
|
+
await this.retirement;
|
|
66
|
+
if (this.closed) return;
|
|
67
|
+
if (!this.pool) {
|
|
68
|
+
const { resolveRuntimeWorkerUrl, WorkerTaskPool } = await import("openclaw/plugin-sdk/process-runtime");
|
|
69
|
+
if (this.closed) return;
|
|
70
|
+
this.pool = new WorkerTaskPool({
|
|
71
|
+
workerUrl: resolveRuntimeWorkerUrl(codexCatalogPageWorkerEntrypoint),
|
|
72
|
+
maxWorkers: 1,
|
|
73
|
+
maxPendingTasks: 1,
|
|
74
|
+
maxPendingBytes: Number.MAX_SAFE_INTEGER,
|
|
75
|
+
idleTimeoutMs: 0,
|
|
76
|
+
restartOnError: false
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
const attempt = route === "unresolved" ? void 0 : attempts.get(route.id);
|
|
80
|
+
const remainingRows = attempt ? projections.get(attempt)?.remainingRows : 0;
|
|
81
|
+
let catalogRows;
|
|
82
|
+
if (route === "unresolved") {
|
|
83
|
+
catalogRows = /* @__PURE__ */ new Map();
|
|
84
|
+
for (const [id, pending] of attempts) {
|
|
85
|
+
const projection = projections.get(pending);
|
|
86
|
+
if (typeof id === "number" && projection) catalogRows.set(id, projection.remainingRows);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const bytes = line.byteOffset === 0 && line.byteLength === line.buffer.byteLength && line.buffer instanceof ArrayBuffer ? new Uint8Array(line.buffer) : Uint8Array.from(line);
|
|
90
|
+
const decoded = await this.pool.run({
|
|
91
|
+
bytes,
|
|
92
|
+
route,
|
|
93
|
+
remainingRows,
|
|
94
|
+
catalogRows
|
|
95
|
+
}, {
|
|
96
|
+
inputBytes: bytes.byteLength,
|
|
97
|
+
transferList: (input) => [input.bytes.buffer]
|
|
98
|
+
});
|
|
99
|
+
if (this.closed) return;
|
|
100
|
+
this.continuationRoute = decoded.pending ? route : void 0;
|
|
101
|
+
if (!decoded.pending) this.armIdleRetirement();
|
|
102
|
+
return decoded;
|
|
103
|
+
}
|
|
104
|
+
armIdleRetirement() {
|
|
105
|
+
this.idleTimer = runInCatalogWorkerContext(() => this.setTimeoutFn(() => {
|
|
106
|
+
this.idleTimer = void 0;
|
|
107
|
+
this.retirement = this.pool?.rotate();
|
|
108
|
+
this.retirement?.catch(() => void 0);
|
|
109
|
+
}, CATALOG_WORKER_IDLE_MS));
|
|
110
|
+
this.idleTimer.unref();
|
|
111
|
+
}
|
|
112
|
+
async close(error) {
|
|
113
|
+
this.closed = true;
|
|
114
|
+
this.clearTimeoutFn(this.idleTimer);
|
|
115
|
+
this.idleTimer = void 0;
|
|
116
|
+
this.continuationRoute = void 0;
|
|
117
|
+
await this.retirement?.catch(() => void 0);
|
|
118
|
+
await this.pool?.close(error);
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
//#endregion
|
|
122
|
+
//#region extensions/codex/src/app-server/client-diagnostics.ts
|
|
123
|
+
function observeCodexAppServerStderr(stderr, consume) {
|
|
124
|
+
stderr.setEncoding("utf8");
|
|
125
|
+
stderr.on("data", (chunk) => {
|
|
126
|
+
const text = consume(chunk).trim();
|
|
127
|
+
if (text) embeddedAgentLog.debug(`codex app-server stderr: ${text}`);
|
|
128
|
+
});
|
|
129
|
+
stderr.on("error", (error) => embeddedAgentLog.warn("codex app-server stderr stream failed", { error }));
|
|
130
|
+
}
|
|
131
|
+
function appendBoundedTail(current, next, maxLength) {
|
|
132
|
+
const combined = `${current}${next}`;
|
|
133
|
+
return combined.length > maxLength ? sliceUtf16Safe(combined, -maxLength) : combined;
|
|
134
|
+
}
|
|
135
|
+
function buildCodexAppServerExitError(code, signal, stderrTail) {
|
|
136
|
+
const stderrPreview = redactCodexAppServerLinePreview(stderrTail);
|
|
137
|
+
const suffix = stderrPreview ? ` stderr=${JSON.stringify(stderrPreview)}` : "";
|
|
138
|
+
return /* @__PURE__ */ new Error(`codex app-server exited: code=${formatExitValue(code)} signal=${formatExitValue(signal)}${suffix}`);
|
|
139
|
+
}
|
|
140
|
+
function logCodexAppServerParseFailure(value, error, fragmentCount) {
|
|
141
|
+
const linePreview = redactCodexAppServerLinePreview(value);
|
|
142
|
+
const suffix = fragmentCount > 1 ? ` fragments=${fragmentCount}` : "";
|
|
143
|
+
embeddedAgentLog.warn("failed to parse codex app-server message", {
|
|
144
|
+
error,
|
|
145
|
+
errorMessage: coerceErrorMessage(error),
|
|
146
|
+
fragmentCount,
|
|
147
|
+
linePreview,
|
|
148
|
+
consoleMessage: `failed to parse codex app-server message${suffix}: preview=${JSON.stringify(linePreview)}`
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
function formatExitValue(value) {
|
|
152
|
+
if (value === null || value === void 0) return "null";
|
|
153
|
+
if (typeof value === "string" || typeof value === "number") return String(value);
|
|
154
|
+
return "unknown";
|
|
155
|
+
}
|
|
156
|
+
//#endregion
|
|
157
|
+
//#region extensions/codex/src/app-server/notification-policy.ts
|
|
158
|
+
const CODEX_APP_SERVER_OPT_OUT_NOTIFICATION_METHODS = [
|
|
159
|
+
"account/login/completed",
|
|
160
|
+
"app/list/updated",
|
|
161
|
+
"command/exec/outputDelta",
|
|
162
|
+
"deprecationNotice",
|
|
163
|
+
"externalAgentConfig/import/completed",
|
|
164
|
+
"externalAgentConfig/import/progress",
|
|
165
|
+
"fs/changed",
|
|
166
|
+
"fuzzyFileSearch/sessionCompleted",
|
|
167
|
+
"fuzzyFileSearch/sessionUpdated",
|
|
168
|
+
"mcpServer/event/stream/notification",
|
|
169
|
+
"mcpServer/oauthLogin/completed",
|
|
170
|
+
"mcpServer/startupStatus/updated",
|
|
171
|
+
"process/exited",
|
|
172
|
+
"process/outputDelta",
|
|
173
|
+
"project/changed",
|
|
174
|
+
"remoteControl/status/changed",
|
|
175
|
+
"thread/environment/connected",
|
|
176
|
+
"thread/environment/disconnected",
|
|
177
|
+
"thread/goal/cleared",
|
|
178
|
+
"thread/project/updated",
|
|
179
|
+
"thread/queue/changed",
|
|
180
|
+
"thread/realtime/closed",
|
|
181
|
+
"thread/realtime/error",
|
|
182
|
+
"thread/realtime/item/completed",
|
|
183
|
+
"thread/realtime/item/started",
|
|
184
|
+
"thread/realtime/item/transcript/delta",
|
|
185
|
+
"thread/realtime/itemAdded",
|
|
186
|
+
"thread/realtime/outputAudio/delta",
|
|
187
|
+
"thread/realtime/sdp",
|
|
188
|
+
"thread/realtime/started",
|
|
189
|
+
"thread/realtime/transcript/delta",
|
|
190
|
+
"thread/realtime/transcript/done",
|
|
191
|
+
"windows/worldWritableWarning",
|
|
192
|
+
"windowsSandbox/setupCompleted",
|
|
193
|
+
"turn/diff/updated",
|
|
194
|
+
"item/fileChange/outputDelta",
|
|
195
|
+
"thread/compacted"
|
|
196
|
+
];
|
|
197
|
+
//#endregion
|
|
198
|
+
//#region extensions/codex/src/app-server/client-initialize.ts
|
|
199
|
+
function buildCodexAppServerInitializeParams() {
|
|
200
|
+
return {
|
|
201
|
+
clientInfo: {
|
|
202
|
+
name: "openclaw",
|
|
203
|
+
title: "OpenClaw",
|
|
204
|
+
version: OPENCLAW_VERSION
|
|
205
|
+
},
|
|
206
|
+
capabilities: {
|
|
207
|
+
experimentalApi: true,
|
|
208
|
+
optOutNotificationMethods: [...CODEX_APP_SERVER_OPT_OUT_NOTIFICATION_METHODS],
|
|
209
|
+
extensions: {
|
|
210
|
+
"openai/standard-form-input": {},
|
|
211
|
+
"openai/form": {},
|
|
212
|
+
"io.modelcontextprotocol/ui": { mimeTypes: ["text/html;profile=mcp-app"] }
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
function buildCodexAppServerRuntimeIdentity(response, serverVersion) {
|
|
218
|
+
const userAgent = normalizeOptionalString(response.userAgent);
|
|
219
|
+
const codexHome = normalizeOptionalString(response.codexHome);
|
|
220
|
+
const platformFamily = normalizeOptionalString(response.platformFamily);
|
|
221
|
+
const platformOs = normalizeOptionalString(response.platformOs);
|
|
222
|
+
return {
|
|
223
|
+
serverVersion,
|
|
224
|
+
...userAgent ? { userAgent } : {},
|
|
225
|
+
...codexHome ? { codexHome } : {},
|
|
226
|
+
...platformFamily ? { platformFamily } : {},
|
|
227
|
+
...platformOs ? { platformOs } : {}
|
|
228
|
+
};
|
|
32
229
|
}
|
|
33
230
|
//#endregion
|
|
34
231
|
//#region extensions/codex/src/app-server/client-response.ts
|
|
35
232
|
/** Settles one wire attempt and reports newly observed native execution. */
|
|
36
|
-
function dispatchCodexAppServerResponse(response, attempts, catalogResponses, source) {
|
|
233
|
+
function dispatchCodexAppServerResponse(response, attempts, catalogResponses, source, previewStates) {
|
|
37
234
|
const pending = attempts.get(response.id);
|
|
38
235
|
if (!pending) return false;
|
|
39
236
|
attempts.delete(response.id);
|
|
@@ -43,112 +240,187 @@ function dispatchCodexAppServerResponse(response, attempts, catalogResponses, so
|
|
|
43
240
|
return false;
|
|
44
241
|
}
|
|
45
242
|
const nativeExecution = pending.method === "thread/backgroundTerminals/list" && isJsonObject(response.result) && Array.isArray(response.result.data) && response.result.data.length > 0;
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
243
|
+
const cache = catalogResponses.get(pending)?.preview;
|
|
244
|
+
if (cache && previewStates && isJsonObject(response.result) && Array.isArray(response.result.data)) try {
|
|
245
|
+
for (const [index, row] of response.result.data.entries()) if (isJsonObject(row) && typeof row.id === "string" && row.ephemeral !== true) {
|
|
246
|
+
const preview = reuseCodexCatalogPreview({
|
|
247
|
+
id: row.id,
|
|
248
|
+
path: typeof row.path === "string" ? row.path : null,
|
|
249
|
+
updatedAt: typeof row.updatedAt === "number" ? row.updatedAt : null,
|
|
250
|
+
recencyAt: typeof row.recencyAt === "number" ? row.recencyAt : null
|
|
251
|
+
}, previewStates[index], cache);
|
|
252
|
+
if (preview !== void 0) row.preview = preview;
|
|
53
253
|
}
|
|
254
|
+
} catch (error) {
|
|
255
|
+
pending.reject(error instanceof Error ? error : new Error("Codex catalog projection failed", { cause: error }), false);
|
|
256
|
+
return false;
|
|
54
257
|
}
|
|
55
258
|
recordCodexCatalogResponseSource(pending.method, response.result, source);
|
|
56
259
|
pending.resolve(response.result);
|
|
57
260
|
return nativeExecution;
|
|
58
261
|
}
|
|
59
262
|
//#endregion
|
|
60
|
-
//#region extensions/codex/src/app-server/
|
|
61
|
-
/**
|
|
62
|
-
function
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
263
|
+
//#region extensions/codex/src/app-server/request-attempt.ts
|
|
264
|
+
/** One caller per wire attempt; local waiter expiry need not imply a native response. */
|
|
265
|
+
function createCodexRequestAttempt(params) {
|
|
266
|
+
let pending = true;
|
|
267
|
+
let mayHaveWritten = false;
|
|
268
|
+
let waiter;
|
|
269
|
+
const diagnostics = params.diagnosticIdentity ? {
|
|
270
|
+
...params.diagnosticIdentity,
|
|
271
|
+
attemptCreatedAtMs: performance.now(),
|
|
272
|
+
firstPossibleWriteAtMs: null,
|
|
273
|
+
wireOutcomeAtWaiterSettlement: "retained-pending",
|
|
274
|
+
wireObservedAtMs: null
|
|
275
|
+
} : void 0;
|
|
276
|
+
const finish = (outcome) => {
|
|
277
|
+
if (!pending) return false;
|
|
278
|
+
pending = false;
|
|
279
|
+
if (diagnostics) {
|
|
280
|
+
diagnostics.wireOutcomeAtWaiterSettlement = outcome;
|
|
281
|
+
diagnostics.wireObservedAtMs = performance.now();
|
|
282
|
+
}
|
|
283
|
+
params.onSettled();
|
|
284
|
+
return true;
|
|
285
|
+
};
|
|
286
|
+
const currentWaiterError = () => {
|
|
287
|
+
if (!params.retainWritten || !waiter) return;
|
|
288
|
+
if (waiter.signal?.aborted) return {
|
|
289
|
+
error: params.cancellationError("aborted", mayHaveWritten, waiter.signal.reason),
|
|
290
|
+
outcome: "aborted"
|
|
291
|
+
};
|
|
292
|
+
if (waiter.deadline !== void 0 && performance.now() >= waiter.deadline) return {
|
|
293
|
+
error: params.cancellationError("timed out", mayHaveWritten),
|
|
294
|
+
outcome: "timed-out"
|
|
295
|
+
};
|
|
296
|
+
};
|
|
297
|
+
return {
|
|
298
|
+
method: params.method,
|
|
299
|
+
get pending() {
|
|
300
|
+
return pending;
|
|
301
|
+
},
|
|
302
|
+
wait(options, deadline) {
|
|
303
|
+
const { timeoutMs, signal, overloadAttemptOrdinal } = options;
|
|
304
|
+
let observe = options.attemptWaiterFinished;
|
|
305
|
+
return new Promise((resolve, reject) => {
|
|
306
|
+
if (!pending) {
|
|
307
|
+
reject(/* @__PURE__ */ new Error("Codex request attempt is already settled"));
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
let timer;
|
|
311
|
+
let removeAbort;
|
|
312
|
+
const waiterAttachedAtMs = diagnostics && observe ? performance.now() : 0;
|
|
313
|
+
const cleanup = () => {
|
|
314
|
+
clearTimeout(timer);
|
|
315
|
+
timer = void 0;
|
|
316
|
+
removeAbort?.();
|
|
317
|
+
removeAbort = void 0;
|
|
318
|
+
};
|
|
319
|
+
const detach = (waiterOutcome) => {
|
|
320
|
+
if (!waiter) return false;
|
|
321
|
+
waiter = void 0;
|
|
322
|
+
cleanup();
|
|
323
|
+
if (!params.retainWritten || !mayHaveWritten) finish(mayHaveWritten ? "correlation-closed" : "not-written");
|
|
324
|
+
const callback = observe;
|
|
325
|
+
observe = void 0;
|
|
326
|
+
if (diagnostics && callback) try {
|
|
327
|
+
callback({
|
|
328
|
+
...diagnostics,
|
|
329
|
+
waiterOrdinal: 1,
|
|
330
|
+
disposition: "new",
|
|
331
|
+
overloadAttemptOrdinal,
|
|
332
|
+
waiterAttachedAtMs,
|
|
333
|
+
waiterSettledAtMs: performance.now(),
|
|
334
|
+
waiterOutcome
|
|
335
|
+
});
|
|
336
|
+
} catch {}
|
|
337
|
+
return true;
|
|
338
|
+
};
|
|
339
|
+
const localWaiter = {
|
|
340
|
+
resolve: (value) => {
|
|
341
|
+
if (!detach("resolved")) return;
|
|
342
|
+
resolve(value);
|
|
343
|
+
},
|
|
344
|
+
reject: (error, outcome) => {
|
|
345
|
+
if (detach(outcome)) reject(error);
|
|
346
|
+
},
|
|
347
|
+
signal,
|
|
348
|
+
deadline
|
|
349
|
+
};
|
|
350
|
+
waiter = localWaiter;
|
|
351
|
+
if (params.retainWritten && deadline !== void 0 && performance.now() >= deadline) {
|
|
352
|
+
localWaiter.reject(params.cancellationError("timed out", mayHaveWritten), "timed-out");
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
if (timeoutMs && Number.isFinite(timeoutMs) && timeoutMs > 0) {
|
|
356
|
+
const remaining = params.retainWritten && deadline !== void 0 ? deadline - performance.now() : timeoutMs;
|
|
357
|
+
timer = setTimeout(() => localWaiter.reject(params.cancellationError("timed out", mayHaveWritten), "timed-out"), Math.max(params.retainWritten ? 1 : 100, remaining));
|
|
358
|
+
timer.unref?.();
|
|
359
|
+
}
|
|
360
|
+
if (signal) {
|
|
361
|
+
const abort = () => localWaiter.reject(params.cancellationError("aborted", mayHaveWritten, signal.reason), "aborted");
|
|
362
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
363
|
+
removeAbort = () => signal.removeEventListener("abort", abort);
|
|
364
|
+
if (signal.aborted) abort();
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
},
|
|
368
|
+
resolve(value) {
|
|
369
|
+
if (!finish("native-ok")) return;
|
|
370
|
+
params.onResponse?.(mayHaveWritten);
|
|
371
|
+
const error = currentWaiterError();
|
|
372
|
+
if (error) waiter?.reject(error.error, error.outcome);
|
|
373
|
+
else waiter?.resolve(value);
|
|
374
|
+
},
|
|
375
|
+
reject(error, definitelyNotEnqueued = false) {
|
|
376
|
+
if (finish(definitelyNotEnqueued ? "ingress-rejected" : "native-error")) {
|
|
377
|
+
if (definitelyNotEnqueued) mayHaveWritten = false;
|
|
378
|
+
params.onResponse?.(mayHaveWritten);
|
|
379
|
+
const current = currentWaiterError();
|
|
380
|
+
waiter?.reject(current?.error ?? params.localError(error, mayHaveWritten), current?.outcome ?? "native-error");
|
|
381
|
+
}
|
|
382
|
+
},
|
|
383
|
+
close(error) {
|
|
384
|
+
if (finish("correlation-closed")) waiter?.reject(params.localError(error, mayHaveWritten), "client-closed");
|
|
385
|
+
},
|
|
386
|
+
failLocal(error) {
|
|
387
|
+
if (!pending) return;
|
|
388
|
+
if (!params.retainWritten || !mayHaveWritten) finish(mayHaveWritten ? "correlation-closed" : "not-written");
|
|
389
|
+
waiter?.reject(params.localError(error, mayHaveWritten), "local-failed");
|
|
100
390
|
},
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
value: state.executionStarted
|
|
391
|
+
markWritten() {
|
|
392
|
+
mayHaveWritten = true;
|
|
393
|
+
if (diagnostics && diagnostics.firstPossibleWriteAtMs === null) diagnostics.firstPossibleWriteAtMs = performance.now();
|
|
105
394
|
}
|
|
106
|
-
}
|
|
107
|
-
return withDynamicToolSideEffectEvidence(response, state.sideEffectEvidence === true);
|
|
108
|
-
}
|
|
109
|
-
function withDynamicToolSideEffectEvidence(response, sideEffectEvidence) {
|
|
110
|
-
if (!sideEffectEvidence) {
|
|
111
|
-
delete response.sideEffectEvidence;
|
|
112
|
-
return response;
|
|
113
|
-
}
|
|
114
|
-
Object.defineProperty(response, "sideEffectEvidence", {
|
|
115
|
-
configurable: true,
|
|
116
|
-
enumerable: false,
|
|
117
|
-
value: true
|
|
118
|
-
});
|
|
119
|
-
return response;
|
|
395
|
+
};
|
|
120
396
|
}
|
|
397
|
+
//#endregion
|
|
398
|
+
//#region extensions/codex/src/app-server/dynamic-tool-response-state.ts
|
|
121
399
|
function createFailedDynamicToolResponse(message, options) {
|
|
122
|
-
|
|
400
|
+
return {
|
|
123
401
|
contentItems: [{
|
|
124
402
|
type: "inputText",
|
|
125
403
|
text: message
|
|
126
404
|
}],
|
|
127
|
-
success: false
|
|
405
|
+
success: false,
|
|
406
|
+
diagnosticTerminalReason: options?.terminalReason ?? "failed",
|
|
407
|
+
diagnosticTerminalType: "error",
|
|
408
|
+
executionStarted: options?.executionStarted,
|
|
409
|
+
executedArguments: options?.executedArguments,
|
|
410
|
+
sideEffectEvidence: options?.sideEffectEvidence === true || void 0
|
|
128
411
|
};
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
412
|
+
}
|
|
413
|
+
function failedToolResult(message, status = "failed") {
|
|
414
|
+
return {
|
|
415
|
+
content: [{
|
|
416
|
+
type: "text",
|
|
417
|
+
text: message
|
|
418
|
+
}],
|
|
419
|
+
details: {
|
|
420
|
+
status,
|
|
421
|
+
error: message
|
|
139
422
|
}
|
|
140
|
-
}
|
|
141
|
-
if (options?.executionStarted !== void 0) Object.defineProperty(response, "executionStarted", {
|
|
142
|
-
configurable: true,
|
|
143
|
-
enumerable: false,
|
|
144
|
-
value: options.executionStarted
|
|
145
|
-
});
|
|
146
|
-
if (options?.executedArguments !== void 0) Object.defineProperty(response, "executedArguments", {
|
|
147
|
-
configurable: true,
|
|
148
|
-
enumerable: false,
|
|
149
|
-
value: options.executedArguments
|
|
150
|
-
});
|
|
151
|
-
return withDynamicToolSideEffectEvidence(response, options?.sideEffectEvidence === true);
|
|
423
|
+
};
|
|
152
424
|
}
|
|
153
425
|
//#endregion
|
|
154
426
|
//#region extensions/codex/src/app-server/tool-abort-terminal-reason.ts
|
|
@@ -178,21 +450,13 @@ function resolveCodexToolAbortTerminalReason(signal) {
|
|
|
178
450
|
}
|
|
179
451
|
//#endregion
|
|
180
452
|
//#region extensions/codex/src/app-server/dynamic-tool-execution.ts
|
|
181
|
-
/**
|
|
182
|
-
* Timeout, terminal-release, and diagnostic helpers for Codex dynamic tool
|
|
183
|
-
* calls.
|
|
184
|
-
*/
|
|
185
|
-
/** Default timeout for Codex dynamic tool calls. */
|
|
186
453
|
const CODEX_DYNAMIC_TOOL_TIMEOUT_MS = 9e4;
|
|
187
|
-
/** Hard cap for ordinary per-call Codex dynamic tool timeout overrides. */
|
|
188
454
|
const CODEX_DYNAMIC_TOOL_MAX_TIMEOUT_MS = 6e5;
|
|
189
455
|
const CODEX_DYNAMIC_TOOL_TIMEOUT_SECONDS_GRACE_MS = 3e4;
|
|
190
456
|
const CODEX_DYNAMIC_IMAGE_GENERATION_TOOL_TIMEOUT_MS = 12e4;
|
|
191
457
|
const CODEX_DYNAMIC_COMPUTER_GATEWAY_TIMEOUT_MS = 3e4;
|
|
192
458
|
const CODEX_DYNAMIC_COMPUTER_COMPLETION_GRACE_MS = 3e4;
|
|
193
|
-
/** Timeout for image-understanding style dynamic tool calls. */
|
|
194
459
|
const CODEX_DYNAMIC_IMAGE_TOOL_TIMEOUT_MS = 6e4;
|
|
195
|
-
/** Timeout for message-delivery dynamic tool calls. */
|
|
196
460
|
const CODEX_DYNAMIC_MESSAGE_TOOL_TIMEOUT_MS = 6e5;
|
|
197
461
|
/** Outer default for collector waits: full swarm budget plus completion grace. */
|
|
198
462
|
const CODEX_DYNAMIC_AGENTS_WAIT_TOOL_TIMEOUT_MS = 63e4;
|
|
@@ -244,11 +508,13 @@ function formatDynamicToolTimeoutDetails(params) {
|
|
|
244
508
|
}
|
|
245
509
|
};
|
|
246
510
|
}
|
|
247
|
-
/**
|
|
248
|
-
* Runs a dynamic tool call with run-abort and the budget prepared by
|
|
249
|
-
* resolveDynamicToolCallTimeoutMs, preserving tool-specific completion grace.
|
|
250
|
-
*/
|
|
251
511
|
async function handleDynamicToolCallWithTimeout(params) {
|
|
512
|
+
return await runWithAsyncWorkResources((onAcquired) => executeDynamicToolCallWithTimeout(params, (release) => onAcquired({
|
|
513
|
+
release,
|
|
514
|
+
releaseBeforeResultWhenIdle: true
|
|
515
|
+
})));
|
|
516
|
+
}
|
|
517
|
+
async function executeDynamicToolCallWithTimeout(params, retainCleanup) {
|
|
252
518
|
let didNotifyAgentToolResult = false;
|
|
253
519
|
const conservativeRaceResponses = /* @__PURE__ */ new WeakSet();
|
|
254
520
|
const finalizeTerminal = (response) => {
|
|
@@ -265,11 +531,18 @@ async function handleDynamicToolCallWithTimeout(params) {
|
|
|
265
531
|
arguments: response.executedArguments ?? executionSnapshot?.executedArguments ?? params.call.arguments,
|
|
266
532
|
...params.toolMeta ? { meta: params.toolMeta } : {},
|
|
267
533
|
...ownerKey ? { ownerMutation: { ownerKey } } : {},
|
|
534
|
+
replaySafe: ownerKey ? false : response.replaySafe,
|
|
268
535
|
...observedExecutionStarted !== void 0 ? { executionStarted: observedExecutionStarted } : {},
|
|
269
536
|
outcome: response.success ? "success" : "failure",
|
|
270
537
|
...!response.success ? { failure: { error: readDynamicToolResponseText(response) } } : {}
|
|
271
538
|
});
|
|
272
|
-
|
|
539
|
+
if (terminalResolution) {
|
|
540
|
+
response.terminalResolution = terminalResolution;
|
|
541
|
+
response.executionStarted = terminalResolution.executionStarted;
|
|
542
|
+
response.executedArguments = terminalResolution.executedArguments ?? response.executedArguments;
|
|
543
|
+
response.sideEffectEvidence = terminalResolution.sideEffectEvidence || void 0;
|
|
544
|
+
}
|
|
545
|
+
return response;
|
|
273
546
|
};
|
|
274
547
|
const createFailedAfterPossibleDispatch = (message, terminalReason) => {
|
|
275
548
|
const response = createFailedDynamicToolResponse(message, {
|
|
@@ -293,16 +566,7 @@ async function handleDynamicToolCallWithTimeout(params) {
|
|
|
293
566
|
const notifyFailedToolResult = (message, terminalReason = "failed") => {
|
|
294
567
|
notifyAgentToolResult({
|
|
295
568
|
toolName: params.call.tool,
|
|
296
|
-
result:
|
|
297
|
-
content: [{
|
|
298
|
-
type: "text",
|
|
299
|
-
text: message
|
|
300
|
-
}],
|
|
301
|
-
details: {
|
|
302
|
-
status: terminalReason,
|
|
303
|
-
error: message
|
|
304
|
-
}
|
|
305
|
-
},
|
|
569
|
+
result: failedToolResult(message, terminalReason),
|
|
306
570
|
isError: true
|
|
307
571
|
});
|
|
308
572
|
};
|
|
@@ -319,15 +583,26 @@ async function handleDynamicToolCallWithTimeout(params) {
|
|
|
319
583
|
const controller = new AbortController();
|
|
320
584
|
let timeout;
|
|
321
585
|
let timedOut = false;
|
|
586
|
+
let toolCallSettled = false;
|
|
587
|
+
let completedSuccessfully = false;
|
|
588
|
+
let operationReleased = false;
|
|
322
589
|
let resolveAbort;
|
|
323
590
|
const abortFromRun = () => {
|
|
324
591
|
const message = "OpenClaw dynamic tool call aborted.";
|
|
325
592
|
const terminalReason = resolveCodexToolAbortTerminalReason(params.signal);
|
|
326
|
-
params.onFallbackSelected?.();
|
|
327
593
|
controller.abort(params.signal.reason ?? /* @__PURE__ */ new Error(message));
|
|
594
|
+
if (toolCallSettled) return;
|
|
595
|
+
params.onFallbackSelected?.();
|
|
328
596
|
notifyFailedToolResult(message, terminalReason);
|
|
329
597
|
resolveAbort?.(createFailedAfterPossibleDispatch(message, terminalReason));
|
|
330
598
|
};
|
|
599
|
+
const releaseOperation = () => {
|
|
600
|
+
if (operationReleased) return;
|
|
601
|
+
operationReleased = true;
|
|
602
|
+
params.signal.removeEventListener("abort", abortFromRun);
|
|
603
|
+
if (!controller.signal.aborted) controller.abort(/* @__PURE__ */ new Error("OpenClaw dynamic tool call finished."));
|
|
604
|
+
};
|
|
605
|
+
retainCleanup(releaseOperation);
|
|
331
606
|
const abortPromise = new Promise((resolve) => {
|
|
332
607
|
resolveAbort = resolve;
|
|
333
608
|
});
|
|
@@ -365,7 +640,9 @@ async function handleDynamicToolCallWithTimeout(params) {
|
|
|
365
640
|
timeoutPromise
|
|
366
641
|
]);
|
|
367
642
|
if (!response.success && !didNotifyAgentToolResult) notifyFailedToolResult(readDynamicToolResponseText(response), response.diagnosticTerminalReason ?? "failed");
|
|
368
|
-
|
|
643
|
+
const terminal = finalizeTerminal(response);
|
|
644
|
+
completedSuccessfully = terminal.success;
|
|
645
|
+
return terminal;
|
|
369
646
|
} catch (error) {
|
|
370
647
|
const terminalReason = params.signal.aborted ? resolveCodexToolAbortTerminalReason(params.signal) : resolveToolExecutionErrorKind(error);
|
|
371
648
|
const message = formatToolExecutionErrorMessage(error, "OpenClaw dynamic tool call failed.");
|
|
@@ -373,9 +650,9 @@ async function handleDynamicToolCallWithTimeout(params) {
|
|
|
373
650
|
return finalizeTerminal(createFailedAfterPossibleDispatch(message, terminalReason));
|
|
374
651
|
} finally {
|
|
375
652
|
if (timeout) clearTimeout(timeout);
|
|
376
|
-
|
|
653
|
+
toolCallSettled = true;
|
|
377
654
|
resolveAbort = void 0;
|
|
378
|
-
if (!timedOut
|
|
655
|
+
if (!completedSuccessfully || timedOut || controller.signal.aborted) releaseOperation();
|
|
379
656
|
}
|
|
380
657
|
}
|
|
381
658
|
function readDynamicToolResponseText(response) {
|
|
@@ -392,38 +669,31 @@ function toCodexDynamicToolProtocolResponse(response) {
|
|
|
392
669
|
function toCodexDynamicToolProgressResponse(response, protocolResponse) {
|
|
393
670
|
const transcriptDetails = isJsonObject(response.transcriptDetails) ? response.transcriptDetails : void 0;
|
|
394
671
|
const mcpAppPreview = isJsonObject(transcriptDetails?.mcpAppPreview) ? transcriptDetails.mcpAppPreview : void 0;
|
|
395
|
-
|
|
396
|
-
if (response.asyncStarted !== true && progressDetails === void 0) return protocolResponse;
|
|
672
|
+
if (response.asyncStarted !== true && !mcpAppPreview) return protocolResponse;
|
|
397
673
|
return {
|
|
398
674
|
...protocolResponse,
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
...progressDetails,
|
|
675
|
+
details: response.asyncStarted === true ? {
|
|
676
|
+
...mcpAppPreview ? { mcpAppPreview } : {},
|
|
402
677
|
async: true,
|
|
403
678
|
status: "started"
|
|
404
|
-
}
|
|
679
|
+
} : { mcpAppPreview }
|
|
405
680
|
};
|
|
406
681
|
}
|
|
407
|
-
/** Decides whether a terminal dynamic tool response can release the Codex turn. */
|
|
408
682
|
function shouldReleaseTurnAfterTerminalDynamicTool(state) {
|
|
409
683
|
return !state.completed && !state.aborted && state.responseSuccess && !state.currentTurnHadNonTerminalDynamicToolResult && state.activeAppServerTurnRequests === 0 && state.activeTurnItemIdsCount === 0 && state.pendingOpenClawDynamicToolCompletionIdsCount === 0;
|
|
410
684
|
}
|
|
411
|
-
/** Returns true when a non-async result should block terminal-release shortcuts. */
|
|
412
685
|
function shouldBlockTerminalReleaseForNonTerminalDynamicToolResult(response) {
|
|
413
686
|
return response.asyncStarted !== true;
|
|
414
687
|
}
|
|
415
|
-
/** Resolves whether terminal diagnostic state should release, wait, or stay idle. */
|
|
416
688
|
function resolveTerminalDynamicToolBatchAction(state) {
|
|
417
689
|
if (state.activeAppServerTurnRequests > 0 || state.activeTurnItemIdsCount > 0 || state.pendingOpenClawDynamicToolCompletionIdsCount > 0) return "wait";
|
|
418
690
|
if (state.currentTurnHadNonTerminalDynamicToolResult) return "clear-nonterminal-batch";
|
|
419
691
|
if (state.hasPendingTerminalDynamicToolRelease) return "release-pending-terminal";
|
|
420
692
|
return "idle";
|
|
421
693
|
}
|
|
422
|
-
/** Returns true for diagnostic events that terminate a dynamic tool call. */
|
|
423
694
|
function isDynamicToolTerminalDiagnosticEvent(event) {
|
|
424
695
|
return event.type === "tool.execution.completed" || event.type === "tool.execution.error" || event.type === "tool.execution.blocked";
|
|
425
696
|
}
|
|
426
|
-
/** Matches terminal diagnostics to a specific dynamic tool call id/name. */
|
|
427
697
|
function isMatchingDynamicToolTerminalDiagnostic(params) {
|
|
428
698
|
if (params.event.toolCallId !== params.call.callId || params.event.toolName !== params.call.tool) return false;
|
|
429
699
|
if (params.runId !== void 0) return params.event.runId === params.runId;
|
|
@@ -431,7 +701,6 @@ function isMatchingDynamicToolTerminalDiagnostic(params) {
|
|
|
431
701
|
if (params.sessionKey !== void 0) return params.event.sessionKey === params.sessionKey;
|
|
432
702
|
return params.event.runId === void 0 && params.event.sessionId === void 0 && params.event.sessionKey === void 0;
|
|
433
703
|
}
|
|
434
|
-
/** Checks pending diagnostics for a terminal event matching a tool call. */
|
|
435
704
|
function hasPendingDynamicToolTerminalDiagnostic(params) {
|
|
436
705
|
return hasPendingInternalDiagnosticEvent((event) => {
|
|
437
706
|
if (!isDynamicToolTerminalDiagnosticEvent(event)) return false;
|
|
@@ -444,7 +713,6 @@ function hasPendingDynamicToolTerminalDiagnostic(params) {
|
|
|
444
713
|
});
|
|
445
714
|
});
|
|
446
715
|
}
|
|
447
|
-
/** Resolves per-tool timeout, applying media/message defaults and hard caps. */
|
|
448
716
|
function resolveDynamicToolCallTimeoutMs(params) {
|
|
449
717
|
const args = isJsonObject(params.call.arguments) ? params.call.arguments : void 0;
|
|
450
718
|
if (params.call.tool === "node_exec") {
|
|
@@ -459,11 +727,8 @@ function resolveDynamicToolCallTimeoutMs(params) {
|
|
|
459
727
|
}
|
|
460
728
|
if (params.call.tool === "computer") return clampDynamicToolTimeoutMs(readComputerToolTimeoutMs(params.call.arguments));
|
|
461
729
|
if (params.call.tool === "message") return CODEX_DYNAMIC_MESSAGE_TOOL_TIMEOUT_MS;
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
return Math.max(1, Math.min(63e4, Math.floor(requestedMs)));
|
|
465
|
-
}
|
|
466
|
-
return clampDynamicToolTimeoutMs(readDynamicToolCallTimeoutMs(params.call.arguments) ?? readConfiguredDynamicToolTimeoutMs(params.call.tool, params.config) ?? CODEX_DYNAMIC_TOOL_TIMEOUT_MS);
|
|
730
|
+
const isCollectorWait = params.call.tool === "agents_wait";
|
|
731
|
+
return clampDynamicToolTimeoutMs(readDynamicToolCallTimeoutMs(params.call.arguments) ?? readConfiguredDynamicToolTimeoutMs(params.call.tool, params.config) ?? (isCollectorWait ? CODEX_DYNAMIC_AGENTS_WAIT_TOOL_TIMEOUT_MS : CODEX_DYNAMIC_TOOL_TIMEOUT_MS), isCollectorWait ? CODEX_DYNAMIC_AGENTS_WAIT_TOOL_TIMEOUT_MS : CODEX_DYNAMIC_TOOL_MAX_TIMEOUT_MS);
|
|
467
732
|
}
|
|
468
733
|
/** Transport guard stays outside the handler's bounded tool wait and completion grace. */
|
|
469
734
|
function resolveDynamicToolServerRequestTimeoutMs(call) {
|
|
@@ -509,8 +774,8 @@ function readDynamicToolTimeoutSecondsAsMs(value) {
|
|
|
509
774
|
function readPositiveFiniteTimeoutMs(value) {
|
|
510
775
|
return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : void 0;
|
|
511
776
|
}
|
|
512
|
-
function clampDynamicToolTimeoutMs(timeoutMs) {
|
|
513
|
-
return Math.max(1, Math.min(
|
|
777
|
+
function clampDynamicToolTimeoutMs(timeoutMs, maximum = CODEX_DYNAMIC_TOOL_MAX_TIMEOUT_MS) {
|
|
778
|
+
return Math.max(1, Math.min(maximum, Math.floor(timeoutMs)));
|
|
514
779
|
}
|
|
515
780
|
//#endregion
|
|
516
781
|
//#region extensions/codex/src/app-server/elicitation-response.ts
|
|
@@ -2792,10 +3057,15 @@ var TurnStartResponse_default = {
|
|
|
2792
3057
|
};
|
|
2793
3058
|
//#endregion
|
|
2794
3059
|
//#region extensions/codex/src/app-server/protocol-validators.ts
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
3060
|
+
function readSupervisionResponseThreadId(value) {
|
|
3061
|
+
const thread = isRecord(value) ? value.thread : void 0;
|
|
3062
|
+
return isRecord(thread) ? thread.id : void 0;
|
|
3063
|
+
}
|
|
3064
|
+
function resolveCodexThreadRolloutPath(thread) {
|
|
3065
|
+
const rolloutPath = thread.path?.trim();
|
|
3066
|
+
if (!rolloutPath || !path.isAbsolute(rolloutPath) || path.extname(rolloutPath) !== ".jsonl" || !path.basename(rolloutPath).includes(thread.id)) return;
|
|
3067
|
+
return rolloutPath;
|
|
3068
|
+
}
|
|
2799
3069
|
const externalDefinitionRefPrefix = "./CodexAppServerProtocolDefinitions.json#/definitions/";
|
|
2800
3070
|
const rootExternalDefinitionRefPrefix = "./v2/CodexAppServerProtocolDefinitions.json#/definitions/";
|
|
2801
3071
|
const localDefinitionRefPrefix = "#/definitions/";
|
|
@@ -2837,17 +3107,12 @@ function rewriteDefinitionRefs(value, externalRefPrefix) {
|
|
|
2837
3107
|
if (!isRecord(value)) return value;
|
|
2838
3108
|
return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, key === "$ref" && typeof entry === "string" && entry.startsWith(externalRefPrefix) ? `${localDefinitionRefPrefix}${entry.slice(externalRefPrefix.length)}` : rewriteDefinitionRefs(entry, externalRefPrefix)]));
|
|
2839
3109
|
}
|
|
2840
|
-
|
|
2841
|
-
const
|
|
2842
|
-
const modelListResponseSchema = materializeCodexSchema(ModelListResponse_default);
|
|
2843
|
-
const threadResumeResponseSchema = materializeCodexSchema(ThreadResumeResponse_default);
|
|
2844
|
-
const threadStartResponseSchema = materializeCodexSchema(ThreadStartResponse_default);
|
|
2845
|
-
const turnCompletedNotificationSchema = materializeCodexSchema(TurnCompletedNotification_default);
|
|
2846
|
-
const turnStartResponseSchema = materializeCodexSchema(TurnStartResponse_default);
|
|
2847
|
-
function compileCodexSchema(schema) {
|
|
3110
|
+
function compileCodexSchema(rawSchema, externalRefPrefix) {
|
|
3111
|
+
const schema = materializeCodexSchema(rawSchema, externalRefPrefix);
|
|
2848
3112
|
if (typeof schema !== "boolean" && !isRecord(schema)) throw new TypeError("Generated Codex schema must be an object or boolean");
|
|
2849
3113
|
const validator = Compile(normalizeJsonSchemaForTypeBox(schema));
|
|
2850
3114
|
return {
|
|
3115
|
+
schema,
|
|
2851
3116
|
check: (value) => validator.Check(value),
|
|
2852
3117
|
errors: (value) => [...validator.Errors(value)]
|
|
2853
3118
|
};
|
|
@@ -2887,10 +3152,7 @@ function applySchemaDefaults(schema, value, root = schema, resolvingRefs = /* @_
|
|
|
2887
3152
|
resolvingRefs.delete(schema.$ref);
|
|
2888
3153
|
}
|
|
2889
3154
|
}
|
|
2890
|
-
for (const
|
|
2891
|
-
const branches = schema[key];
|
|
2892
|
-
if (Array.isArray(branches)) for (const branch of branches) nextValue = applySchemaDefaults(branch, nextValue, root, resolvingRefs);
|
|
2893
|
-
}
|
|
3155
|
+
if (Array.isArray(schema.allOf)) for (const branch of schema.allOf) nextValue = applySchemaDefaults(branch, nextValue, root, resolvingRefs);
|
|
2894
3156
|
if (schemaTypeIncludes(schema, "object") && isRecord(nextValue) && isRecord(schema.properties)) {
|
|
2895
3157
|
for (const [key, propertySchema] of Object.entries(schema.properties)) {
|
|
2896
3158
|
const currentValue = nextValue[key];
|
|
@@ -2909,27 +3171,21 @@ function normalizeWithDefaults(schema, value) {
|
|
|
2909
3171
|
if (value === void 0 || value === null) return value;
|
|
2910
3172
|
return applySchemaDefaults(schema, structuredClone(value));
|
|
2911
3173
|
}
|
|
2912
|
-
const validateDynamicToolCallParams = compileCodexSchema(
|
|
2913
|
-
const validateErrorNotification = compileCodexSchema(
|
|
2914
|
-
const validateModelListResponse = compileCodexSchema(
|
|
2915
|
-
const validateThreadResumeResponse = compileCodexSchema(
|
|
2916
|
-
const validateThreadStartResponse = compileCodexSchema(
|
|
2917
|
-
const validateTurnCompletedNotification = compileCodexSchema(
|
|
2918
|
-
const validateTurnStartResponse = compileCodexSchema(
|
|
2919
|
-
/** Asserts and normalizes a Codex thread/start response. */
|
|
3174
|
+
const validateDynamicToolCallParams = compileCodexSchema(DynamicToolCallParams_default, rootExternalDefinitionRefPrefix);
|
|
3175
|
+
const validateErrorNotification = compileCodexSchema(ErrorNotification_default);
|
|
3176
|
+
const validateModelListResponse = compileCodexSchema(ModelListResponse_default);
|
|
3177
|
+
const validateThreadResumeResponse = compileCodexSchema(ThreadResumeResponse_default);
|
|
3178
|
+
const validateThreadStartResponse = compileCodexSchema(ThreadStartResponse_default);
|
|
3179
|
+
const validateTurnCompletedNotification = compileCodexSchema(TurnCompletedNotification_default);
|
|
3180
|
+
const validateTurnStartResponse = compileCodexSchema(TurnStartResponse_default);
|
|
2920
3181
|
function assertCodexThreadStartResponse(value) {
|
|
2921
|
-
|
|
2922
|
-
return assertCodexShape(validateThreadStartResponse, normalized, "thread/start response");
|
|
3182
|
+
return assertCodexShape(validateThreadStartResponse, value, "thread/start response");
|
|
2923
3183
|
}
|
|
2924
|
-
/** Asserts and normalizes a Codex thread/fork response. */
|
|
2925
3184
|
function assertCodexThreadForkResponse(value) {
|
|
2926
|
-
|
|
2927
|
-
return assertCodexShape(validateThreadStartResponse, normalized, "thread/fork response");
|
|
3185
|
+
return assertCodexShape(validateThreadStartResponse, value, "thread/fork response");
|
|
2928
3186
|
}
|
|
2929
|
-
/** Asserts and normalizes a Codex thread/resume response. */
|
|
2930
3187
|
function assertCodexThreadResumeResponse(value) {
|
|
2931
|
-
|
|
2932
|
-
return assertCodexShape(validateThreadResumeResponse, normalized, "thread/resume response");
|
|
3188
|
+
return assertCodexShape(validateThreadResumeResponse, value, "thread/resume response");
|
|
2933
3189
|
}
|
|
2934
3190
|
var CodexThreadDirectInputError = class extends Error {
|
|
2935
3191
|
constructor(threadId) {
|
|
@@ -2941,16 +3197,15 @@ var CodexThreadDirectInputError = class extends Error {
|
|
|
2941
3197
|
function assertCodexThreadAcceptsDirectInput(thread) {
|
|
2942
3198
|
if (thread.canAcceptDirectInput === false) throw new CodexThreadDirectInputError(thread.id);
|
|
2943
3199
|
}
|
|
2944
|
-
/** Asserts and normalizes a Codex turn/start response. */
|
|
2945
3200
|
function assertCodexTurnStartResponse(value) {
|
|
2946
|
-
|
|
2947
|
-
return assertCodexShape(validateTurnStartResponse, normalized, "turn/start response");
|
|
3201
|
+
return assertCodexShape(validateTurnStartResponse, value, "turn/start response");
|
|
2948
3202
|
}
|
|
2949
|
-
/**
|
|
2950
|
-
function assertCodexPassiveTurnItems(items, prompt, taskLabel) {
|
|
3203
|
+
/** Prompt echoes and attested managed-hook continuations cannot admit native capabilities. */
|
|
3204
|
+
function assertCodexPassiveTurnItems(items, prompt, taskLabel, options = {}) {
|
|
2951
3205
|
let promptEchoSeen = false;
|
|
2952
3206
|
for (const item of items) {
|
|
2953
3207
|
if (item.type === "agentMessage" || item.type === "reasoning") continue;
|
|
3208
|
+
if (item.type === "hookPrompt" && options.allowManagedHookPrompts === true && Array.isArray(item.fragments) && item.fragments.length > 0 && item.fragments.every((fragment) => isJsonObject(fragment) && typeof fragment.text === "string" && typeof fragment.hookRunId === "string" && fragment.hookRunId.trim().length > 0)) continue;
|
|
2954
3209
|
if (item.type === "userMessage" && !promptEchoSeen) {
|
|
2955
3210
|
const content = Array.isArray(item.content) ? item.content : [];
|
|
2956
3211
|
const input = content[0];
|
|
@@ -2962,80 +3217,30 @@ function assertCodexPassiveTurnItems(items, prompt, taskLabel) {
|
|
|
2962
3217
|
throw new Error(`Codex ${taskLabel} returned unexpected native item: ${item.type}`);
|
|
2963
3218
|
}
|
|
2964
3219
|
}
|
|
2965
|
-
/** Reads Codex dynamic-tool call params, returning undefined for invalid payloads. */
|
|
2966
3220
|
function readCodexDynamicToolCallParams(value) {
|
|
2967
|
-
return readCodexShape(validateDynamicToolCallParams,
|
|
3221
|
+
return readCodexShape(validateDynamicToolCallParams, value);
|
|
2968
3222
|
}
|
|
2969
|
-
/** Reads a Codex error notification payload if it matches the protocol schema. */
|
|
2970
3223
|
function readCodexErrorNotification(value) {
|
|
2971
|
-
return readCodexShape(validateErrorNotification,
|
|
3224
|
+
return readCodexShape(validateErrorNotification, value);
|
|
2972
3225
|
}
|
|
2973
|
-
/** Asserts and normalizes a Codex model/list response. */
|
|
2974
3226
|
function assertCodexModelListResponse(value) {
|
|
2975
|
-
return assertCodexShape(validateModelListResponse,
|
|
2976
|
-
}
|
|
2977
|
-
/** Reads and normalizes a Codex turn object. */
|
|
2978
|
-
function readCodexTurn(value) {
|
|
2979
|
-
return readCodexShape(validateTurnStartResponse, normalizeWithDefaults(turnStartResponseSchema, { turn: normalizeTurn(value) }))?.turn;
|
|
3227
|
+
return assertCodexShape(validateModelListResponse, value, "model/list response");
|
|
2980
3228
|
}
|
|
2981
|
-
/** Reads a Codex turn/completed notification payload if it matches the protocol schema. */
|
|
2982
3229
|
function readCodexTurnCompletedNotification(value) {
|
|
2983
|
-
|
|
3230
|
+
const notification = readCodexShape(validateTurnCompletedNotification, value);
|
|
3231
|
+
return notification?.turn.status === "inProgress" ? void 0 : notification;
|
|
3232
|
+
}
|
|
3233
|
+
function assertExactSupervisionModelSelection(value, expected) {
|
|
3234
|
+
if (value.model !== expected.model || value.modelProvider !== expected.modelProvider) throw new Error(`Codex supervision ${expected.operation} changed native model selection: ${value.modelProvider ?? "unknown"}/${value.model ?? "unknown"}`);
|
|
2984
3235
|
}
|
|
2985
3236
|
function assertCodexShape(validate, value, label) {
|
|
2986
|
-
|
|
2987
|
-
|
|
3237
|
+
const normalized = normalizeWithDefaults(validate.schema, value);
|
|
3238
|
+
if (validate.check(normalized)) return normalized;
|
|
3239
|
+
throw new Error(`Invalid Codex app-server ${label}: ${formatValidationErrors(validate, normalized)}`);
|
|
2988
3240
|
}
|
|
2989
3241
|
function readCodexShape(validate, value) {
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
function normalizeTurn(value) {
|
|
2993
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return value;
|
|
2994
|
-
return {
|
|
2995
|
-
error: null,
|
|
2996
|
-
startedAt: null,
|
|
2997
|
-
completedAt: null,
|
|
2998
|
-
durationMs: null,
|
|
2999
|
-
...value,
|
|
3000
|
-
items: Array.isArray(value.items) ? value.items.map(normalizeThreadItem) : []
|
|
3001
|
-
};
|
|
3002
|
-
}
|
|
3003
|
-
function normalizeThreadItem(value) {
|
|
3004
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return value;
|
|
3005
|
-
switch (value.type) {
|
|
3006
|
-
case "agentMessage": return {
|
|
3007
|
-
phase: null,
|
|
3008
|
-
delivery: null,
|
|
3009
|
-
memoryCitation: null,
|
|
3010
|
-
...value
|
|
3011
|
-
};
|
|
3012
|
-
case "plan": return {
|
|
3013
|
-
text: "",
|
|
3014
|
-
...value
|
|
3015
|
-
};
|
|
3016
|
-
case "reasoning": return {
|
|
3017
|
-
summary: [],
|
|
3018
|
-
content: [],
|
|
3019
|
-
...value
|
|
3020
|
-
};
|
|
3021
|
-
case "dynamicToolCall": return {
|
|
3022
|
-
namespace: null,
|
|
3023
|
-
arguments: null,
|
|
3024
|
-
status: "completed",
|
|
3025
|
-
contentItems: null,
|
|
3026
|
-
success: null,
|
|
3027
|
-
durationMs: null,
|
|
3028
|
-
...value
|
|
3029
|
-
};
|
|
3030
|
-
default: return value;
|
|
3031
|
-
}
|
|
3032
|
-
}
|
|
3033
|
-
function normalizeTurnEnvelope(value) {
|
|
3034
|
-
if (!value || typeof value !== "object" || Array.isArray(value) || !("turn" in value)) return value;
|
|
3035
|
-
return {
|
|
3036
|
-
...value,
|
|
3037
|
-
turn: normalizeTurn(value.turn)
|
|
3038
|
-
};
|
|
3242
|
+
const normalized = normalizeWithDefaults(validate.schema, value);
|
|
3243
|
+
return validate.check(normalized) ? normalized : void 0;
|
|
3039
3244
|
}
|
|
3040
3245
|
function formatValidationErrors(validate, value) {
|
|
3041
3246
|
const errors = validate.errors(value);
|
|
@@ -3046,356 +3251,141 @@ function formatValidationErrors(validate, value) {
|
|
|
3046
3251
|
}).join("; ");
|
|
3047
3252
|
}
|
|
3048
3253
|
//#endregion
|
|
3049
|
-
//#region extensions/codex/src/app-server/
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
if (
|
|
3067
|
-
|
|
3068
|
-
|
|
3254
|
+
//#region extensions/codex/src/app-server/server-requests.ts
|
|
3255
|
+
var CodexServerRequestResolvedError = class extends Error {
|
|
3256
|
+
constructor() {
|
|
3257
|
+
super("Codex server request resolved by another client");
|
|
3258
|
+
this.name = "CodexServerRequestResolvedError";
|
|
3259
|
+
}
|
|
3260
|
+
};
|
|
3261
|
+
/** Physical-client owner for inbound requests, cancellation, and response deadlines. */
|
|
3262
|
+
var CodexServerRequests = class {
|
|
3263
|
+
constructor(respond) {
|
|
3264
|
+
this.respond = respond;
|
|
3265
|
+
this.handlers = /* @__PURE__ */ new Set();
|
|
3266
|
+
this.refreshWork = new AsyncWorkScope();
|
|
3267
|
+
this.closed = false;
|
|
3268
|
+
this.active = /* @__PURE__ */ new Map();
|
|
3269
|
+
}
|
|
3270
|
+
resolve(params) {
|
|
3271
|
+
if (!isJsonObject(params) || typeof params.threadId !== "string") return;
|
|
3272
|
+
const id = params.requestId;
|
|
3273
|
+
if (typeof id !== "string" && typeof id !== "number") return;
|
|
3274
|
+
const request = this.active.get(id);
|
|
3275
|
+
if (request?.threadId === params.threadId) {
|
|
3276
|
+
this.active.delete(id);
|
|
3277
|
+
request.controller.abort(new CodexServerRequestResolvedError());
|
|
3069
3278
|
}
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3279
|
+
}
|
|
3280
|
+
close(error) {
|
|
3281
|
+
this.closed = true;
|
|
3282
|
+
this.closing ??= this.refreshWork.drain();
|
|
3283
|
+
const requests = [...this.active.values()];
|
|
3284
|
+
this.active.clear();
|
|
3285
|
+
for (const request of requests) request.controller.abort(error);
|
|
3286
|
+
return this.closing;
|
|
3287
|
+
}
|
|
3288
|
+
async handle(request) {
|
|
3289
|
+
if (this.closed) return;
|
|
3290
|
+
const controller = new AbortController();
|
|
3291
|
+
const entry = {
|
|
3292
|
+
threadId: isJsonObject(request.params) ? request.params.threadId : void 0,
|
|
3293
|
+
controller
|
|
3081
3294
|
};
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3295
|
+
this.active.set(request.id, entry);
|
|
3296
|
+
const deadline = createDeferred();
|
|
3297
|
+
const onAbort = () => deadline.resolve(void 0);
|
|
3298
|
+
controller.signal.addEventListener("abort", onAbort, { once: true });
|
|
3299
|
+
let timeout;
|
|
3300
|
+
let timeoutMs = resolveDynamicToolServerRequestTimeoutMs(readCodexDynamicToolCallParams(request.params));
|
|
3301
|
+
let settled = false;
|
|
3302
|
+
let executionTimeoutResolved = false;
|
|
3303
|
+
const armTimeout = () => {
|
|
3304
|
+
clearTimeout(timeout);
|
|
3305
|
+
timeout = setTimeout(() => {
|
|
3306
|
+
embeddedAgentLog.warn("codex app-server server request timed out", {
|
|
3307
|
+
id: request.id,
|
|
3308
|
+
method: request.method,
|
|
3309
|
+
timeoutMs
|
|
3310
|
+
});
|
|
3311
|
+
deadline.resolve(timeoutServerRequestResponse(timeoutMs));
|
|
3312
|
+
controller.abort(/* @__PURE__ */ new Error("codex app-server server request timed out"));
|
|
3313
|
+
}, timeoutMs);
|
|
3314
|
+
timeout.unref?.();
|
|
3085
3315
|
};
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
outcome: "authority-rejected"
|
|
3092
|
-
};
|
|
3093
|
-
}
|
|
3094
|
-
if (waiter.signal?.aborted) return {
|
|
3095
|
-
error: params.cancellationError("aborted", mayHaveWritten, waiter.signal.reason),
|
|
3096
|
-
outcome: "aborted"
|
|
3316
|
+
const setExecutionTimeoutMs = (executionTimeoutMs) => {
|
|
3317
|
+
if (settled || controller.signal.aborted || executionTimeoutResolved || !Number.isFinite(executionTimeoutMs) || executionTimeoutMs <= 0) return;
|
|
3318
|
+
executionTimeoutResolved = true;
|
|
3319
|
+
timeoutMs = addSafeTimeoutDelayGraceMs(executionTimeoutMs, 3e4);
|
|
3320
|
+
armTimeout();
|
|
3097
3321
|
};
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3322
|
+
const dynamicTool = request.method === "item/tool/call";
|
|
3323
|
+
if (dynamicTool) armTimeout();
|
|
3324
|
+
const run = async () => {
|
|
3325
|
+
for (const handler of this.handlers) {
|
|
3326
|
+
if (controller.signal.aborted) return;
|
|
3327
|
+
const result = await handler(request, controller.signal, dynamicTool ? setExecutionTimeoutMs : void 0);
|
|
3328
|
+
if (result !== void 0) return result;
|
|
3329
|
+
}
|
|
3101
3330
|
};
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
wait(options, deadline) {
|
|
3109
|
-
const { timeoutMs, signal, assertCurrent, disposition, overloadAttemptOrdinal } = options;
|
|
3110
|
-
let observe = options.attemptWaiterFinished;
|
|
3111
|
-
return new Promise((resolve, reject) => {
|
|
3112
|
-
if (!pending) {
|
|
3113
|
-
reject(/* @__PURE__ */ new Error("Codex request attempt is already settled"));
|
|
3114
|
-
return;
|
|
3115
|
-
}
|
|
3116
|
-
let timer;
|
|
3117
|
-
let removeAbort;
|
|
3118
|
-
const waiterOrdinal = diagnostics ? ++diagnostics.waiterOrdinal : 0;
|
|
3119
|
-
const waiterAttachedAtMs = diagnostics && observe ? performance.now() : 0;
|
|
3120
|
-
const cleanup = () => {
|
|
3121
|
-
clearTimeout(timer);
|
|
3122
|
-
timer = void 0;
|
|
3123
|
-
removeAbort?.();
|
|
3124
|
-
removeAbort = void 0;
|
|
3125
|
-
};
|
|
3126
|
-
const detach = (waiterOutcome) => {
|
|
3127
|
-
if (!waiters.delete(waiter)) return false;
|
|
3128
|
-
cleanup();
|
|
3129
|
-
if (waiters.size === 0 && (!params.retainWritten || !mayHaveWritten)) finish(mayHaveWritten ? "correlation-closed" : "not-written");
|
|
3130
|
-
const callback = observe;
|
|
3131
|
-
observe = void 0;
|
|
3132
|
-
if (diagnostics && callback) try {
|
|
3133
|
-
callback({
|
|
3134
|
-
...diagnostics,
|
|
3135
|
-
waiterOrdinal,
|
|
3136
|
-
disposition,
|
|
3137
|
-
overloadAttemptOrdinal,
|
|
3138
|
-
waiterAttachedAtMs,
|
|
3139
|
-
waiterSettledAtMs: performance.now(),
|
|
3140
|
-
waiterOutcome
|
|
3141
|
-
});
|
|
3142
|
-
} catch {}
|
|
3143
|
-
return true;
|
|
3144
|
-
};
|
|
3145
|
-
const waiter = {
|
|
3146
|
-
resolve: (value) => {
|
|
3147
|
-
if (!detach("resolved")) return;
|
|
3148
|
-
resolve(value);
|
|
3149
|
-
},
|
|
3150
|
-
reject: (error, outcome) => {
|
|
3151
|
-
if (detach(outcome)) reject(error);
|
|
3152
|
-
},
|
|
3153
|
-
cleanup,
|
|
3154
|
-
signal,
|
|
3155
|
-
...params.retainWritten ? {
|
|
3156
|
-
deadline,
|
|
3157
|
-
assertCurrent
|
|
3158
|
-
} : {}
|
|
3159
|
-
};
|
|
3160
|
-
waiters.add(waiter);
|
|
3161
|
-
if (params.retainWritten && deadline !== void 0 && performance.now() >= deadline) {
|
|
3162
|
-
waiter.reject(params.cancellationError("timed out", mayHaveWritten), "timed-out");
|
|
3163
|
-
return;
|
|
3164
|
-
}
|
|
3165
|
-
if (timeoutMs && Number.isFinite(timeoutMs) && timeoutMs > 0) {
|
|
3166
|
-
const remaining = params.retainWritten && deadline !== void 0 ? deadline - performance.now() : timeoutMs;
|
|
3167
|
-
timer = setTimeout(() => waiter.reject(params.cancellationError("timed out", mayHaveWritten), "timed-out"), Math.max(params.retainWritten ? 1 : 100, remaining));
|
|
3168
|
-
timer.unref?.();
|
|
3169
|
-
}
|
|
3170
|
-
if (signal) {
|
|
3171
|
-
const abort = () => waiter.reject(params.cancellationError("aborted", mayHaveWritten, signal.reason), "aborted");
|
|
3172
|
-
signal.addEventListener("abort", abort, { once: true });
|
|
3173
|
-
removeAbort = () => signal.removeEventListener("abort", abort);
|
|
3174
|
-
if (signal.aborted) abort();
|
|
3175
|
-
}
|
|
3331
|
+
try {
|
|
3332
|
+
const work = request.method === "account/chatgptAuthTokens/refresh" ? this.refreshWork.track(run) : run();
|
|
3333
|
+
const result = await Promise.race([work, deadline.promise]);
|
|
3334
|
+
if (this.active.get(request.id) === entry) this.respond({
|
|
3335
|
+
id: request.id,
|
|
3336
|
+
result: result === void 0 ? defaultServerRequestResponse(request) : result
|
|
3176
3337
|
});
|
|
3177
|
-
}
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
for (const waiter of waiters) {
|
|
3192
|
-
const current = currentWaiterError(waiter);
|
|
3193
|
-
waiter.reject(current?.error ?? params.localError(error, mayHaveWritten), current?.outcome ?? "native-error");
|
|
3194
|
-
}
|
|
3195
|
-
}
|
|
3196
|
-
},
|
|
3197
|
-
close(error) {
|
|
3198
|
-
if (finish("correlation-closed")) rejectWaiters(params.localError(error, mayHaveWritten), "client-closed");
|
|
3199
|
-
},
|
|
3200
|
-
failLocal(error) {
|
|
3201
|
-
if (!pending) return;
|
|
3202
|
-
if (!params.retainWritten || !mayHaveWritten) finish(mayHaveWritten ? "correlation-closed" : "not-written");
|
|
3203
|
-
rejectWaiters(params.localError(error, mayHaveWritten), "local-failed");
|
|
3204
|
-
},
|
|
3205
|
-
markWritten() {
|
|
3206
|
-
mayHaveWritten = true;
|
|
3207
|
-
if (diagnostics && diagnostics.firstPossibleWriteAtMs === null) diagnostics.firstPossibleWriteAtMs = performance.now();
|
|
3208
|
-
},
|
|
3209
|
-
cleanup() {
|
|
3210
|
-
for (const waiter of waiters) waiter.cleanup();
|
|
3211
|
-
}
|
|
3212
|
-
};
|
|
3213
|
-
}
|
|
3214
|
-
//#endregion
|
|
3215
|
-
//#region extensions/codex/src/app-server/transport-websocket.ts
|
|
3216
|
-
/**
|
|
3217
|
-
* Adapts a remote Codex app-server WebSocket endpoint to the shared stdio-like
|
|
3218
|
-
* transport interface.
|
|
3219
|
-
*/
|
|
3220
|
-
const WEBSOCKET_HANDSHAKE_TIMEOUT_MS = 1e4;
|
|
3221
|
-
const WEBSOCKET_PING_INTERVAL_MS = 2e4;
|
|
3222
|
-
const WEBSOCKET_PONG_TIMEOUT_MS = 2e4;
|
|
3223
|
-
const MAX_CONSECUTIVE_MISSED_WEBSOCKET_PONGS = 5;
|
|
3224
|
-
/** Opens a WebSocket app-server transport and maps newline-delimited frames to stdout/stdin. */
|
|
3225
|
-
function createWebSocketTransport(options) {
|
|
3226
|
-
if (!options.url) throw new Error("codex app-server websocket transport requires plugins.entries.codex.config.appServer.url");
|
|
3227
|
-
const events = new EventEmitter();
|
|
3228
|
-
const stdout = new PassThrough();
|
|
3229
|
-
const stderr = new PassThrough();
|
|
3230
|
-
const websocketOptions = {
|
|
3231
|
-
headers: {
|
|
3232
|
-
...options.headers,
|
|
3233
|
-
...options.authToken ? { Authorization: `Bearer ${options.authToken}` } : {}
|
|
3234
|
-
},
|
|
3235
|
-
perMessageDeflate: false,
|
|
3236
|
-
...options.transport === "websocket" ? { handshakeTimeout: WEBSOCKET_HANDSHAKE_TIMEOUT_MS } : {}
|
|
3237
|
-
};
|
|
3238
|
-
const unixSocketPath = resolveCodexAppServerUnixSocketPath(options);
|
|
3239
|
-
const socket = unixSocketPath ? new WebSocket("ws://localhost/", {
|
|
3240
|
-
...websocketOptions,
|
|
3241
|
-
createConnection: () => connectCodexAppServerUnixSocket(unixSocketPath)
|
|
3242
|
-
}) : new WebSocket(options.url, websocketOptions);
|
|
3243
|
-
const pendingFrames = [];
|
|
3244
|
-
const stdinDecoder = new StringDecoder("utf8");
|
|
3245
|
-
let pendingLine = "";
|
|
3246
|
-
let killed = false;
|
|
3247
|
-
let exitCode = null;
|
|
3248
|
-
let pingTimeout;
|
|
3249
|
-
let pongTimeout;
|
|
3250
|
-
let expectedPong;
|
|
3251
|
-
let consecutiveMissedPongs = 0;
|
|
3252
|
-
let heartbeatSequence = 0;
|
|
3253
|
-
const clearConnectionHealthTimers = () => {
|
|
3254
|
-
if (pingTimeout) {
|
|
3255
|
-
clearTimeout(pingTimeout);
|
|
3256
|
-
pingTimeout = void 0;
|
|
3257
|
-
}
|
|
3258
|
-
if (pongTimeout) {
|
|
3259
|
-
clearTimeout(pongTimeout);
|
|
3260
|
-
pongTimeout = void 0;
|
|
3261
|
-
}
|
|
3262
|
-
expectedPong = void 0;
|
|
3263
|
-
};
|
|
3264
|
-
const sendHeartbeatPing = () => {
|
|
3265
|
-
if (socket.readyState !== WebSocket.OPEN || pongTimeout) return;
|
|
3266
|
-
const payload = Buffer.from(`openclaw-codex-${++heartbeatSequence}`);
|
|
3267
|
-
expectedPong = payload;
|
|
3268
|
-
pongTimeout = setTimeout(() => {
|
|
3269
|
-
pongTimeout = void 0;
|
|
3270
|
-
expectedPong = void 0;
|
|
3271
|
-
consecutiveMissedPongs += 1;
|
|
3272
|
-
if (consecutiveMissedPongs >= MAX_CONSECUTIVE_MISSED_WEBSOCKET_PONGS) {
|
|
3273
|
-
socket.terminate();
|
|
3274
|
-
return;
|
|
3338
|
+
} catch (error) {
|
|
3339
|
+
if (this.active.get(request.id) === entry) {
|
|
3340
|
+
embeddedAgentLog.warn("codex app-server server request handler failed", {
|
|
3341
|
+
id: request.id,
|
|
3342
|
+
method: request.method,
|
|
3343
|
+
error
|
|
3344
|
+
});
|
|
3345
|
+
this.respond({
|
|
3346
|
+
id: request.id,
|
|
3347
|
+
error: {
|
|
3348
|
+
code: -32603,
|
|
3349
|
+
message: coerceErrorMessage(error)
|
|
3350
|
+
}
|
|
3351
|
+
});
|
|
3275
3352
|
}
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
if (
|
|
3281
|
-
});
|
|
3282
|
-
};
|
|
3283
|
-
const scheduleHeartbeatPing = () => {
|
|
3284
|
-
if (options.transport !== "websocket" || socket.readyState !== WebSocket.OPEN || pingTimeout || pongTimeout) return;
|
|
3285
|
-
pingTimeout = setTimeout(() => {
|
|
3286
|
-
pingTimeout = void 0;
|
|
3287
|
-
sendHeartbeatPing();
|
|
3288
|
-
}, WEBSOCKET_PING_INTERVAL_MS);
|
|
3289
|
-
pingTimeout.unref();
|
|
3290
|
-
};
|
|
3291
|
-
const recordConnectionActivity = () => {
|
|
3292
|
-
consecutiveMissedPongs = 0;
|
|
3293
|
-
if (pongTimeout) {
|
|
3294
|
-
clearTimeout(pongTimeout);
|
|
3295
|
-
pongTimeout = void 0;
|
|
3296
|
-
}
|
|
3297
|
-
expectedPong = void 0;
|
|
3298
|
-
scheduleHeartbeatPing();
|
|
3299
|
-
};
|
|
3300
|
-
const sendFrame = (frame) => {
|
|
3301
|
-
const trimmed = frame.trim();
|
|
3302
|
-
if (!trimmed) return;
|
|
3303
|
-
if (socket.readyState === WebSocket.OPEN) {
|
|
3304
|
-
socket.send(trimmed);
|
|
3305
|
-
return;
|
|
3353
|
+
} finally {
|
|
3354
|
+
settled = true;
|
|
3355
|
+
clearTimeout(timeout);
|
|
3356
|
+
controller.signal.removeEventListener("abort", onAbort);
|
|
3357
|
+
if (this.active.get(request.id) === entry) this.active.delete(request.id);
|
|
3306
3358
|
}
|
|
3307
|
-
|
|
3359
|
+
}
|
|
3360
|
+
};
|
|
3361
|
+
function defaultServerRequestResponse(request) {
|
|
3362
|
+
if (request.method === "item/tool/call") return {
|
|
3363
|
+
contentItems: [{
|
|
3364
|
+
type: "inputText",
|
|
3365
|
+
text: "OpenClaw did not register a handler for this app-server tool call."
|
|
3366
|
+
}],
|
|
3367
|
+
success: false
|
|
3308
3368
|
};
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
socket.on("pong", (payload) => {
|
|
3314
|
-
if (expectedPong?.equals(payload)) recordConnectionActivity();
|
|
3315
|
-
});
|
|
3316
|
-
socket.once("error", (error) => {
|
|
3317
|
-
clearConnectionHealthTimers();
|
|
3318
|
-
events.emit("error", error);
|
|
3319
|
-
});
|
|
3320
|
-
socket.once("close", (code, reason) => {
|
|
3321
|
-
clearConnectionHealthTimers();
|
|
3322
|
-
killed = true;
|
|
3323
|
-
exitCode = code;
|
|
3324
|
-
events.emit("exit", code, reason.toString("utf8"));
|
|
3325
|
-
});
|
|
3326
|
-
socket.on("message", (data) => {
|
|
3327
|
-
if (options.transport === "websocket") recordConnectionActivity();
|
|
3328
|
-
const text = websocketFrameToText(data);
|
|
3329
|
-
stdout.write(text.endsWith("\n") ? text : `${text}\n`);
|
|
3330
|
-
});
|
|
3331
|
-
const stdin = new Writable({
|
|
3332
|
-
write(chunk, _encoding, callback) {
|
|
3333
|
-
pendingLine += stdinDecoder.write(chunk);
|
|
3334
|
-
const lines = pendingLine.split("\n");
|
|
3335
|
-
pendingLine = lines.pop() ?? "";
|
|
3336
|
-
for (const frame of lines) sendFrame(frame);
|
|
3337
|
-
callback();
|
|
3338
|
-
},
|
|
3339
|
-
final(callback) {
|
|
3340
|
-
pendingLine += stdinDecoder.end();
|
|
3341
|
-
if (pendingLine) sendFrame(pendingLine);
|
|
3342
|
-
pendingLine = "";
|
|
3343
|
-
callback();
|
|
3344
|
-
}
|
|
3345
|
-
});
|
|
3346
|
-
const closeSocket = () => {
|
|
3347
|
-
if (socket.readyState === WebSocket.CLOSED || socket.readyState === WebSocket.CLOSING) return;
|
|
3348
|
-
socket.close();
|
|
3369
|
+
if (request.method === "item/commandExecution/requestApproval" || request.method === "item/fileChange/requestApproval") return { decision: "decline" };
|
|
3370
|
+
if (request.method === "item/permissions/requestApproval") return {
|
|
3371
|
+
permissions: {},
|
|
3372
|
+
scope: "turn"
|
|
3349
3373
|
};
|
|
3350
|
-
|
|
3351
|
-
|
|
3374
|
+
if (request.method === "item/tool/requestUserInput") return { answers: {} };
|
|
3375
|
+
if (request.method === "mcpServer/elicitation/request") return createCodexElicitationResponse("decline", null, { message: "OpenClaw has no interactive handler for this elicitation." });
|
|
3376
|
+
return {};
|
|
3377
|
+
}
|
|
3378
|
+
function timeoutServerRequestResponse(timeoutMs) {
|
|
3352
3379
|
return {
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
return killed;
|
|
3359
|
-
},
|
|
3360
|
-
get exitCode() {
|
|
3361
|
-
return exitCode;
|
|
3362
|
-
},
|
|
3363
|
-
kill: (signal) => {
|
|
3364
|
-
killed = true;
|
|
3365
|
-
clearConnectionHealthTimers();
|
|
3366
|
-
if (signal === "SIGKILL") socket.terminate();
|
|
3367
|
-
else socket.close();
|
|
3368
|
-
},
|
|
3369
|
-
once: (event, listener) => events.once(event, listener),
|
|
3370
|
-
off: (event, listener) => events.off(event, listener)
|
|
3380
|
+
contentItems: [{
|
|
3381
|
+
type: "inputText",
|
|
3382
|
+
text: `OpenClaw dynamic tool call timed out after ${timeoutMs}ms before sending a response to Codex.`
|
|
3383
|
+
}],
|
|
3384
|
+
success: false
|
|
3371
3385
|
};
|
|
3372
3386
|
}
|
|
3373
|
-
/** Opens the owner-scoped Codex control socket used by the WebSocket upgrade. */
|
|
3374
|
-
function connectCodexAppServerUnixSocket(socketPath) {
|
|
3375
|
-
return net.createConnection(socketPath);
|
|
3376
|
-
}
|
|
3377
|
-
/** Resolves the canonical or explicitly configured Codex control socket. */
|
|
3378
|
-
function resolveCodexAppServerUnixSocketPath(options) {
|
|
3379
|
-
if (options.transport !== "unix") {
|
|
3380
|
-
if (options.url?.startsWith("unix://")) throw new Error("codex app-server unix URL requires unix transport");
|
|
3381
|
-
return;
|
|
3382
|
-
}
|
|
3383
|
-
const url = options.url ?? "unix://";
|
|
3384
|
-
if (!url.startsWith("unix://")) throw new Error("codex app-server unix transport requires a unix:// URL");
|
|
3385
|
-
return url.slice(7) || path.join(resolveCodexAppServerUserHomeDir(options.env ?? process.env), "app-server-control", "app-server-control.sock");
|
|
3386
|
-
}
|
|
3387
|
-
function websocketFrameToText(data) {
|
|
3388
|
-
if (typeof data === "string") return data;
|
|
3389
|
-
if (Buffer.isBuffer(data)) return data.toString("utf8");
|
|
3390
|
-
if (Array.isArray(data)) return Buffer.concat(data).toString("utf8");
|
|
3391
|
-
return Buffer.from(data).toString("utf8");
|
|
3392
|
-
}
|
|
3393
3387
|
//#endregion
|
|
3394
3388
|
//#region extensions/codex/src/app-server/client.ts
|
|
3395
|
-
/**
|
|
3396
|
-
* JSON-RPC client for Codex app-server transports, including request/response
|
|
3397
|
-
* routing, notification fanout, server request handlers, and version checks.
|
|
3398
|
-
*/
|
|
3399
3389
|
var client_exports = /* @__PURE__ */ __exportAll({
|
|
3400
3390
|
CodexAppServerClient: () => CodexAppServerClient,
|
|
3401
3391
|
getCodexAppServerClientInstanceId: () => getCodexAppServerClientInstanceId,
|
|
@@ -3410,15 +3400,11 @@ var client_exports = /* @__PURE__ */ __exportAll({
|
|
|
3410
3400
|
isUnsupportedCodexAppServerVersionError: () => isUnsupportedCodexAppServerVersionError,
|
|
3411
3401
|
resolveCodexAppServerClientInstanceId: () => resolveCodexAppServerClientInstanceId
|
|
3412
3402
|
});
|
|
3413
|
-
const CODEX_APP_SERVER_PARSE_LOG_MAX = 500;
|
|
3414
|
-
const CODEX_APP_SERVER_PARSE_BUFFER_MAX = 8388608;
|
|
3415
|
-
const CODEX_APP_SERVER_PARSE_BUFFER_MAX_LINES = 1e3;
|
|
3416
3403
|
const CODEX_APP_SERVER_STDERR_TAIL_MAX = 2e3;
|
|
3417
3404
|
const CODEX_APP_SERVER_OVERLOAD_MAX_RETRIES = 3;
|
|
3418
3405
|
const CODEX_APP_SERVER_OVERLOAD_RETRY_BASE_MS = 50;
|
|
3419
3406
|
const CODEX_APP_SERVER_PENDING_STARTUP_WARNINGS_MAX = 32;
|
|
3420
3407
|
const CODEX_APP_SERVER_CLIENT_INSTANCE_IDS = /* @__PURE__ */ new WeakMap();
|
|
3421
|
-
const UNPAIRED_SURROGATE_RE = /[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g;
|
|
3422
3408
|
/** Process-local generation fence for bindings tied to one app-server client instance. */
|
|
3423
3409
|
function getCodexAppServerClientInstanceId(client) {
|
|
3424
3410
|
const current = CODEX_APP_SERVER_CLIENT_INSTANCE_IDS.get(client);
|
|
@@ -3477,19 +3463,19 @@ function isCodexAppServerPrewriteRequestCancellationError(error) {
|
|
|
3477
3463
|
function isCodexAppServerIndeterminateTransportError(error) {
|
|
3478
3464
|
return error instanceof Error && "code" in error && error.code === "CODEX_APP_SERVER_REQUEST_TRANSPORT_INDETERMINATE" && "mayHaveWritten" in error && error.mayHaveWritten === true;
|
|
3479
3465
|
}
|
|
3480
|
-
/** Returns true for errors that mean the app-server transport is closed. */
|
|
3481
3466
|
function isCodexAppServerConnectionClosedError(error) {
|
|
3482
3467
|
if (!(error instanceof Error)) return false;
|
|
3483
3468
|
if (isCodexAppServerIndeterminateTransportError(error)) return true;
|
|
3484
3469
|
return error.message === "codex app-server client is closed" || error.message.startsWith("codex app-server exited:");
|
|
3485
3470
|
}
|
|
3486
|
-
/** Stateful app-server JSON-RPC client over stdio or websocket transport. */
|
|
3487
3471
|
var CodexAppServerClient = class CodexAppServerClient {
|
|
3488
3472
|
constructor(child) {
|
|
3489
3473
|
this.instanceId = randomUUID();
|
|
3474
|
+
this.decoder = new CodexAppServerMessageDecoder(logCodexAppServerParseFailure);
|
|
3475
|
+
this.catalogWorker = new CodexCatalogWorker();
|
|
3490
3476
|
this.pending = /* @__PURE__ */ new Map();
|
|
3491
3477
|
this.catalogResponses = /* @__PURE__ */ new WeakMap();
|
|
3492
|
-
this.
|
|
3478
|
+
this.serverRequests = new CodexServerRequests((response) => this.writeMessage(response));
|
|
3493
3479
|
this.notificationHandlers = /* @__PURE__ */ new Set();
|
|
3494
3480
|
this.pendingStartupWarnings = [];
|
|
3495
3481
|
this.closeHandlers = /* @__PURE__ */ new Set();
|
|
@@ -3503,28 +3489,24 @@ var CodexAppServerClient = class CodexAppServerClient {
|
|
|
3503
3489
|
this.privateTransportSecrets = /* @__PURE__ */ new Set();
|
|
3504
3490
|
this.privateStderrPending = "";
|
|
3505
3491
|
this.child = child;
|
|
3506
|
-
this.
|
|
3507
|
-
|
|
3508
|
-
|
|
3492
|
+
this.closeMessageReader = listenCodexAppServerLines(child.stdout, (line) => {
|
|
3493
|
+
const route = this.catalogWorker.continuation ?? (this.decoder.hasPending ? void 0 : readCodexCatalogDecodeRoute(line));
|
|
3494
|
+
if (route) return this.decodeCatalogLine(line, route);
|
|
3495
|
+
return this.handleParsedMessage(this.decoder.parse(line.toString("utf8")));
|
|
3496
|
+
}, (error) => this.closeWithError(toStringifiedError(error)));
|
|
3509
3497
|
child.stdout.on("error", (error) => this.closeWithError(toStringifiedError(error)));
|
|
3510
|
-
child.stderr
|
|
3511
|
-
child.stderr.on("data", (chunk) => {
|
|
3498
|
+
observeCodexAppServerStderr(child.stderr, (chunk) => {
|
|
3512
3499
|
const text = this.redactPrivateStderr(chunk);
|
|
3513
3500
|
this.stderrTail = appendBoundedTail(this.stderrTail, text, CODEX_APP_SERVER_STDERR_TAIL_MAX);
|
|
3514
|
-
|
|
3515
|
-
if (trimmed) embeddedAgentLog.debug(`codex app-server stderr: ${trimmed}`);
|
|
3516
|
-
});
|
|
3517
|
-
child.stderr.on("error", (error) => {
|
|
3518
|
-
embeddedAgentLog.warn("codex app-server stderr stream failed", { error });
|
|
3501
|
+
return text;
|
|
3519
3502
|
});
|
|
3520
3503
|
child.once("error", (error) => this.closeWithError(toStringifiedError(error)));
|
|
3521
3504
|
child.once("exit", (code, signal) => {
|
|
3522
3505
|
this.transportExited = true;
|
|
3523
|
-
this.closeWithError(buildCodexAppServerExitError(code, signal, this.stderrTail));
|
|
3506
|
+
this.closeWithError(child.startupFailure?.error ?? buildCodexAppServerExitError(code, signal, this.stderrTail));
|
|
3524
3507
|
});
|
|
3525
3508
|
child.stdin.on?.("error", (error) => this.closeWithError(toStringifiedError(error)));
|
|
3526
3509
|
}
|
|
3527
|
-
/** Starts a new app-server client using resolved runtime start options. */
|
|
3528
3510
|
static async start(options, assertCurrent) {
|
|
3529
3511
|
const defaults = resolveCodexAppServerRuntimeOptions().start;
|
|
3530
3512
|
const startOptions = {
|
|
@@ -3542,43 +3524,26 @@ var CodexAppServerClient = class CodexAppServerClient {
|
|
|
3542
3524
|
return client;
|
|
3543
3525
|
} catch (error) {
|
|
3544
3526
|
assertCurrent?.();
|
|
3545
|
-
if (client?.transportExited && hasCodexAppServerNaturalExit(client.child)) throw buildCodexAppServerExitError(client.child.exitCode, client.child.signalCode, client.stderrTail);
|
|
3527
|
+
if (client?.transportExited && hasCodexAppServerNaturalExit(client.child)) throw client.child.startupFailure?.error ?? buildCodexAppServerExitError(client.child.exitCode, client.child.signalCode, client.stderrTail);
|
|
3546
3528
|
const stderr = client?.getStderrDiagnostic();
|
|
3547
3529
|
throw stderr ? new Error(`${coerceErrorMessage(error)}; stderr=${JSON.stringify(stderr)}`, { cause: error }) : error;
|
|
3548
3530
|
}
|
|
3549
3531
|
}
|
|
3550
|
-
/** Builds a client around a fake transport for tests. */
|
|
3551
3532
|
static fromTransportForTests(child) {
|
|
3552
3533
|
return new CodexAppServerClient(child);
|
|
3553
3534
|
}
|
|
3554
|
-
/** Performs the app-server initialize handshake and validates protocol version. */
|
|
3555
3535
|
async initialize() {
|
|
3556
3536
|
if (this.initialized) return;
|
|
3557
|
-
const response = await this.request("initialize",
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
version: OPENCLAW_VERSION
|
|
3562
|
-
},
|
|
3563
|
-
capabilities: {
|
|
3564
|
-
experimentalApi: true,
|
|
3565
|
-
extensions: {
|
|
3566
|
-
"openai/standard-form-input": {},
|
|
3567
|
-
"openai/form": {},
|
|
3568
|
-
"io.modelcontextprotocol/ui": { mimeTypes: ["text/html;profile=mcp-app"] }
|
|
3569
|
-
}
|
|
3570
|
-
}
|
|
3571
|
-
});
|
|
3572
|
-
this.serverVersion = assertSupportedCodexAppServerVersion(response);
|
|
3573
|
-
this.runtimeIdentity = buildCodexAppServerRuntimeIdentity(response, this.serverVersion);
|
|
3537
|
+
const response = await this.request("initialize", buildCodexAppServerInitializeParams());
|
|
3538
|
+
this.child.startupFailure?.complete();
|
|
3539
|
+
const serverVersion = assertSupportedCodexAppServerVersion(response);
|
|
3540
|
+
this.runtimeIdentity = buildCodexAppServerRuntimeIdentity(response, serverVersion);
|
|
3574
3541
|
this.notify("initialized");
|
|
3575
3542
|
this.initialized = true;
|
|
3576
3543
|
}
|
|
3577
|
-
/** Returns the version detected during initialize. */
|
|
3578
3544
|
getServerVersion() {
|
|
3579
|
-
return this.serverVersion;
|
|
3545
|
+
return this.runtimeIdentity?.serverVersion;
|
|
3580
3546
|
}
|
|
3581
|
-
/** Returns runtime metadata detected during initialize. */
|
|
3582
3547
|
getRuntimeIdentity() {
|
|
3583
3548
|
return this.runtimeIdentity ? { ...this.runtimeIdentity } : void 0;
|
|
3584
3549
|
}
|
|
@@ -3717,7 +3682,7 @@ var CodexAppServerClient = class CodexAppServerClient {
|
|
|
3717
3682
|
requestOnce(method, params, options, overloadAttemptOrdinal, onWriteStateChange, deadline, onResponse) {
|
|
3718
3683
|
if (this.closed) return Promise.reject(this.closeError ?? /* @__PURE__ */ new Error("codex app-server client is closed"));
|
|
3719
3684
|
if (options.signal?.aborted) return Promise.reject(new CodexAppServerLocalRequestCancellationError(method, "aborted", false, options.signal?.reason));
|
|
3720
|
-
const id = this.nextId
|
|
3685
|
+
const id = codexCatalogRequestId(method, params, this.nextId++, options.catalogPreview);
|
|
3721
3686
|
if (method === "account/login/start" || method === "account/logout" || method === "config/value/write" || method === "config/batchWrite") this.modelCatalogRevision += 1;
|
|
3722
3687
|
const message = {
|
|
3723
3688
|
id,
|
|
@@ -3742,14 +3707,12 @@ var CodexAppServerClient = class CodexAppServerClient {
|
|
|
3742
3707
|
localError: (error, written) => written && !(error instanceof CodexAppServerRpcError) && !isCodexAppServerIndeterminateRequestCancellationError(error) && !isCodexAppServerIndeterminateTransportError(error) ? new CodexAppServerIndeterminateTransportError(method, error) : error
|
|
3743
3708
|
});
|
|
3744
3709
|
this.pending.set(id, attempt);
|
|
3745
|
-
if (options.catalogPreview
|
|
3710
|
+
if (options.catalogPreview) this.catalogResponses.set(attempt, {
|
|
3746
3711
|
preview: options.catalogPreviewCache,
|
|
3747
3712
|
remainingRows: options.catalogRows
|
|
3748
3713
|
});
|
|
3749
3714
|
const result = attempt.wait({
|
|
3750
3715
|
...options,
|
|
3751
|
-
assertCurrent: void 0,
|
|
3752
|
-
disposition: "new",
|
|
3753
3716
|
overloadAttemptOrdinal
|
|
3754
3717
|
}, deadline);
|
|
3755
3718
|
if (!attempt.pending) return result;
|
|
@@ -3764,25 +3727,21 @@ var CodexAppServerClient = class CodexAppServerClient {
|
|
|
3764
3727
|
}
|
|
3765
3728
|
return result;
|
|
3766
3729
|
}
|
|
3767
|
-
/** Sends a fire-and-forget JSON-RPC notification to the app-server. */
|
|
3768
3730
|
notify(method, params) {
|
|
3769
3731
|
this.writeMessage({
|
|
3770
3732
|
method,
|
|
3771
3733
|
params
|
|
3772
3734
|
});
|
|
3773
3735
|
}
|
|
3774
|
-
/** Registers a handler for app-server requests sent back to OpenClaw. */
|
|
3775
3736
|
addRequestHandler(handler) {
|
|
3776
|
-
this.
|
|
3777
|
-
return () => this.
|
|
3737
|
+
this.serverRequests.handlers.add(handler);
|
|
3738
|
+
return () => this.serverRequests.handlers.delete(handler);
|
|
3778
3739
|
}
|
|
3779
|
-
/** Registers a notification handler and returns its disposer. */
|
|
3780
3740
|
addNotificationHandler(handler) {
|
|
3781
3741
|
this.notificationHandlers.add(handler);
|
|
3782
3742
|
for (const notification of this.pendingStartupWarnings.splice(0)) this.handleNotification(notification);
|
|
3783
3743
|
return () => this.notificationHandlers.delete(handler);
|
|
3784
3744
|
}
|
|
3785
|
-
/** Registers a close handler and returns its disposer. */
|
|
3786
3745
|
addCloseHandler(handler) {
|
|
3787
3746
|
this.closeHandlers.add(handler);
|
|
3788
3747
|
return () => this.closeHandlers.delete(handler);
|
|
@@ -3797,33 +3756,26 @@ var CodexAppServerClient = class CodexAppServerClient {
|
|
|
3797
3756
|
this.child.once("exit", onExit);
|
|
3798
3757
|
return () => this.child.off?.("exit", onExit);
|
|
3799
3758
|
}
|
|
3800
|
-
/** Closes the transport without waiting for process/socket shutdown. */
|
|
3801
3759
|
close() {
|
|
3802
|
-
|
|
3803
|
-
closeCodexAppServerTransport(this.child);
|
|
3760
|
+
this.closeWithError(/* @__PURE__ */ new Error("codex app-server client is closed"));
|
|
3804
3761
|
}
|
|
3805
|
-
/** Closes the transport and waits for shutdown according to transport policy. */
|
|
3806
3762
|
async closeAndWait(options) {
|
|
3807
3763
|
this.markClosed(/* @__PURE__ */ new Error("codex app-server client is closed"));
|
|
3808
|
-
const result = await closeCodexAppServerTransportAndWait(this.child, options);
|
|
3764
|
+
const [result] = await Promise.all([closeCodexAppServerTransportAndWait(this.child, options), this.waitForCloseWork()]);
|
|
3809
3765
|
return this.nativeExecutionObserved ? {
|
|
3810
3766
|
...result,
|
|
3811
3767
|
cleanup: "uncertain"
|
|
3812
3768
|
} : result;
|
|
3813
3769
|
}
|
|
3770
|
+
/** Joins local settlement already started by close without changing transport policy. */
|
|
3771
|
+
async waitForCloseWork() {
|
|
3772
|
+
await this.serverRequestsClosed;
|
|
3773
|
+
await this.catalogWorkerClosed;
|
|
3774
|
+
}
|
|
3814
3775
|
/** Closes this transport and runs cleanup only after physical process exit. */
|
|
3815
3776
|
async closeAndRunAfterExit(onExit, operation) {
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
if (settled) return;
|
|
3819
|
-
settled = true;
|
|
3820
|
-
onExit();
|
|
3821
|
-
};
|
|
3822
|
-
if (this.transportExited) {
|
|
3823
|
-
runOnExit();
|
|
3824
|
-
return;
|
|
3825
|
-
}
|
|
3826
|
-
this.child.once("exit", runOnExit);
|
|
3777
|
+
this.addTransportExitHandler(onExit);
|
|
3778
|
+
if (this.transportExited) return;
|
|
3827
3779
|
try {
|
|
3828
3780
|
await this.closeAndWait();
|
|
3829
3781
|
} catch (closeError) {
|
|
@@ -3871,65 +3823,16 @@ var CodexAppServerClient = class CodexAppServerClient {
|
|
|
3871
3823
|
this.privateStderrPending = held ? text.slice(-held) : "";
|
|
3872
3824
|
return held ? text.slice(0, -held) : text;
|
|
3873
3825
|
}
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
if (this.pendingParse) {
|
|
3877
|
-
this.handlePendingParseLine(rawLine);
|
|
3878
|
-
return;
|
|
3879
|
-
}
|
|
3880
|
-
const trimmed = rawLine.trim();
|
|
3881
|
-
if (!trimmed) return;
|
|
3882
|
-
let parsed;
|
|
3883
|
-
try {
|
|
3884
|
-
parsed = JSON.parse(trimmed);
|
|
3885
|
-
} catch (error) {
|
|
3886
|
-
if (shouldBufferCodexAppServerParseFailure(trimmed, error)) {
|
|
3887
|
-
this.pendingParse = {
|
|
3888
|
-
text: trimmed,
|
|
3889
|
-
lineCount: 1,
|
|
3890
|
-
firstError: error
|
|
3891
|
-
};
|
|
3892
|
-
return;
|
|
3893
|
-
}
|
|
3894
|
-
logCodexAppServerParseFailure(trimmed, error, 1);
|
|
3895
|
-
return;
|
|
3896
|
-
}
|
|
3897
|
-
this.handleParsedMessage(parsed);
|
|
3898
|
-
}
|
|
3899
|
-
handlePendingParseLine(line) {
|
|
3900
|
-
const pending = this.pendingParse;
|
|
3901
|
-
if (!pending) return;
|
|
3902
|
-
const candidate = `${pending.text}\\n${line}`;
|
|
3903
|
-
let parsed;
|
|
3904
|
-
try {
|
|
3905
|
-
parsed = JSON.parse(candidate);
|
|
3906
|
-
} catch (error) {
|
|
3907
|
-
const lineCount = pending.lineCount + 1;
|
|
3908
|
-
if (shouldBufferCodexAppServerParseFailure(candidate.trim(), error) && candidate.length <= CODEX_APP_SERVER_PARSE_BUFFER_MAX && lineCount <= CODEX_APP_SERVER_PARSE_BUFFER_MAX_LINES) {
|
|
3909
|
-
this.pendingParse = {
|
|
3910
|
-
text: candidate,
|
|
3911
|
-
lineCount,
|
|
3912
|
-
firstError: pending.firstError
|
|
3913
|
-
};
|
|
3914
|
-
return;
|
|
3915
|
-
}
|
|
3916
|
-
this.pendingParse = void 0;
|
|
3917
|
-
logCodexAppServerParseFailure(candidate, error, lineCount);
|
|
3918
|
-
return;
|
|
3919
|
-
}
|
|
3920
|
-
this.pendingParse = void 0;
|
|
3921
|
-
this.handleParsedMessage(parsed);
|
|
3922
|
-
}
|
|
3923
|
-
handleParsedMessage(parsed) {
|
|
3924
|
-
if (!parsed || typeof parsed !== "object") return;
|
|
3826
|
+
handleParsedMessage(parsed, previewStates) {
|
|
3827
|
+
if (this.closed || !parsed || typeof parsed !== "object") return;
|
|
3925
3828
|
const message = parsed;
|
|
3926
3829
|
if (isRpcResponse(message)) {
|
|
3927
|
-
this.handleResponse(message);
|
|
3830
|
+
this.handleResponse(message, previewStates);
|
|
3928
3831
|
return;
|
|
3929
3832
|
}
|
|
3930
3833
|
if (!("method" in message)) return;
|
|
3931
3834
|
if ("id" in message && message.id !== void 0) {
|
|
3932
|
-
this.
|
|
3835
|
+
this.serverRequests.handle({
|
|
3933
3836
|
id: message.id,
|
|
3934
3837
|
method: message.method,
|
|
3935
3838
|
params: message.params
|
|
@@ -3941,83 +3844,19 @@ var CodexAppServerClient = class CodexAppServerClient {
|
|
|
3941
3844
|
params: message.params
|
|
3942
3845
|
});
|
|
3943
3846
|
}
|
|
3944
|
-
|
|
3945
|
-
|
|
3847
|
+
async decodeCatalogLine(line, route) {
|
|
3848
|
+
const decoded = await this.catalogWorker.decode(line, route, this.pending, this.catalogResponses);
|
|
3849
|
+
if (!decoded || this.closed) return;
|
|
3850
|
+
for (const failure of decoded.failures) logCodexAppServerParseFailure(failure.value, failure.error, failure.fragmentCount);
|
|
3851
|
+
if (decoded.projectionError) this.pending.get(decoded.projectionError.id)?.reject(decoded.projectionError.error, false);
|
|
3852
|
+
else if (decoded.message) this.handleParsedMessage(decoded.message, decoded.previewStates);
|
|
3946
3853
|
}
|
|
3947
|
-
|
|
3948
|
-
|
|
3949
|
-
const result = await this.runServerRequestHandlers(request);
|
|
3950
|
-
if (result !== void 0) {
|
|
3951
|
-
this.writeMessage({
|
|
3952
|
-
id: request.id,
|
|
3953
|
-
result
|
|
3954
|
-
});
|
|
3955
|
-
return;
|
|
3956
|
-
}
|
|
3957
|
-
this.writeMessage({
|
|
3958
|
-
id: request.id,
|
|
3959
|
-
result: defaultServerRequestResponse(request)
|
|
3960
|
-
});
|
|
3961
|
-
} catch (error) {
|
|
3962
|
-
const message = coerceErrorMessage(error);
|
|
3963
|
-
embeddedAgentLog.warn("codex app-server server request handler failed", {
|
|
3964
|
-
id: request.id,
|
|
3965
|
-
method: request.method,
|
|
3966
|
-
error
|
|
3967
|
-
});
|
|
3968
|
-
this.writeMessage({
|
|
3969
|
-
id: request.id,
|
|
3970
|
-
error: {
|
|
3971
|
-
code: -32603,
|
|
3972
|
-
message
|
|
3973
|
-
}
|
|
3974
|
-
});
|
|
3975
|
-
}
|
|
3976
|
-
}
|
|
3977
|
-
async runServerRequestHandlers(request) {
|
|
3978
|
-
const controller = new AbortController();
|
|
3979
|
-
if (request.method !== "item/tool/call") return await this.runServerRequestHandlersWithoutTimeout(request, controller.signal);
|
|
3980
|
-
let timeoutMs = resolveDynamicToolServerRequestTimeoutMs(readCodexDynamicToolCallParams(request.params));
|
|
3981
|
-
const deadline = createDeferred();
|
|
3982
|
-
let timeout;
|
|
3983
|
-
let settled = false;
|
|
3984
|
-
let executionTimeoutResolved = false;
|
|
3985
|
-
const armTimeout = () => {
|
|
3986
|
-
clearTimeout(timeout);
|
|
3987
|
-
timeout = setTimeout(() => {
|
|
3988
|
-
embeddedAgentLog.warn("codex app-server server request timed out", {
|
|
3989
|
-
id: request.id,
|
|
3990
|
-
method: request.method,
|
|
3991
|
-
timeoutMs
|
|
3992
|
-
});
|
|
3993
|
-
controller.abort(/* @__PURE__ */ new Error("codex app-server server request timed out"));
|
|
3994
|
-
deadline.resolve(timeoutServerRequestResponse(timeoutMs));
|
|
3995
|
-
}, timeoutMs);
|
|
3996
|
-
timeout.unref?.();
|
|
3997
|
-
};
|
|
3998
|
-
const setExecutionTimeoutMs = (executionTimeoutMs) => {
|
|
3999
|
-
if (settled || controller.signal.aborted || executionTimeoutResolved || !Number.isFinite(executionTimeoutMs) || executionTimeoutMs <= 0) return;
|
|
4000
|
-
executionTimeoutResolved = true;
|
|
4001
|
-
timeoutMs = addSafeTimeoutDelayGraceMs(executionTimeoutMs, 3e4);
|
|
4002
|
-
armTimeout();
|
|
4003
|
-
};
|
|
4004
|
-
armTimeout();
|
|
4005
|
-
try {
|
|
4006
|
-
return await Promise.race([this.runServerRequestHandlersWithoutTimeout(request, controller.signal, setExecutionTimeoutMs), deadline.promise]);
|
|
4007
|
-
} finally {
|
|
4008
|
-
settled = true;
|
|
4009
|
-
clearTimeout(timeout);
|
|
4010
|
-
}
|
|
4011
|
-
}
|
|
4012
|
-
async runServerRequestHandlersWithoutTimeout(request, signal, setExecutionTimeoutMs) {
|
|
4013
|
-
for (const handler of this.requestHandlers) {
|
|
4014
|
-
if (signal.aborted) return;
|
|
4015
|
-
const result = await handler(request, signal, setExecutionTimeoutMs);
|
|
4016
|
-
if (result !== void 0) return result;
|
|
4017
|
-
}
|
|
3854
|
+
handleResponse(response, previewStates) {
|
|
3855
|
+
this.nativeExecutionObserved = dispatchCodexAppServerResponse(response, this.pending, this.catalogResponses, codexCatalogSourceForClient(this), previewStates) || this.nativeExecutionObserved;
|
|
4018
3856
|
}
|
|
4019
3857
|
handleNotification(notification) {
|
|
4020
3858
|
const params = notification.params;
|
|
3859
|
+
if (notification.method === "serverRequest/resolved") this.serverRequests.resolve(params);
|
|
4021
3860
|
if (notification.method === "item/commandExecution/outputDelta" || notification.method === "item/commandExecution/terminalInteraction" || isJsonObject(params) && (isJsonObject(params.item) && params.item.type === "commandExecution" || isJsonObject(params.turn) && Array.isArray(params.turn.items) && params.turn.items.some((item) => isJsonObject(item) && item.type === "commandExecution"))) this.nativeExecutionObserved = true;
|
|
4022
3861
|
if (notification.method === "account/updated") this.modelCatalogRevision += 1;
|
|
4023
3862
|
if (this.notificationHandlers.size === 0 && notification.method === "configWarning") {
|
|
@@ -4041,15 +3880,18 @@ var CodexAppServerClient = class CodexAppServerClient {
|
|
|
4041
3880
|
this.closed = true;
|
|
4042
3881
|
closeCodexCatalogClientSource(this);
|
|
4043
3882
|
this.closeError = error;
|
|
4044
|
-
this.
|
|
3883
|
+
this.closeMessageReader();
|
|
3884
|
+
this.decoder.clear();
|
|
3885
|
+
this.catalogWorkerClosed = this.catalogWorker.close(error);
|
|
3886
|
+
this.catalogWorkerClosed?.catch((closeError) => {
|
|
3887
|
+
embeddedAgentLog.warn("codex catalog worker shutdown failed", { error: closeError });
|
|
3888
|
+
});
|
|
3889
|
+
this.serverRequestsClosed = this.serverRequests.close(error);
|
|
4045
3890
|
this.rejectPendingRequests(error);
|
|
4046
3891
|
return true;
|
|
4047
3892
|
}
|
|
4048
3893
|
rejectPendingRequests(error) {
|
|
4049
|
-
for (const pending of this.pending.values())
|
|
4050
|
-
pending.cleanup();
|
|
4051
|
-
pending.close(error);
|
|
4052
|
-
}
|
|
3894
|
+
for (const pending of this.pending.values()) pending.close(error);
|
|
4053
3895
|
this.pending.clear();
|
|
4054
3896
|
for (const handler of this.closeHandlers) try {
|
|
4055
3897
|
handler(this);
|
|
@@ -4058,36 +3900,6 @@ var CodexAppServerClient = class CodexAppServerClient {
|
|
|
4058
3900
|
}
|
|
4059
3901
|
}
|
|
4060
3902
|
};
|
|
4061
|
-
function defaultServerRequestResponse(request) {
|
|
4062
|
-
if (request.method === "item/tool/call") return {
|
|
4063
|
-
contentItems: [{
|
|
4064
|
-
type: "inputText",
|
|
4065
|
-
text: "OpenClaw did not register a handler for this app-server tool call."
|
|
4066
|
-
}],
|
|
4067
|
-
success: false
|
|
4068
|
-
};
|
|
4069
|
-
if (request.method === "item/commandExecution/requestApproval" || request.method === "item/fileChange/requestApproval") return { decision: "decline" };
|
|
4070
|
-
if (request.method === "item/permissions/requestApproval") return {
|
|
4071
|
-
permissions: {},
|
|
4072
|
-
scope: "turn"
|
|
4073
|
-
};
|
|
4074
|
-
if (request.method === "item/tool/requestUserInput") return { answers: {} };
|
|
4075
|
-
if (request.method === "mcpServer/elicitation/request") return createCodexElicitationResponse("decline", null, { message: "OpenClaw has no interactive handler for this elicitation." });
|
|
4076
|
-
return {};
|
|
4077
|
-
}
|
|
4078
|
-
function stringifyCodexAppServerMessage(message) {
|
|
4079
|
-
return JSON.stringify(message, (_key, value) => typeof value === "string" ? value.replace(UNPAIRED_SURROGATE_RE, "") : value) ?? "null";
|
|
4080
|
-
}
|
|
4081
|
-
function timeoutServerRequestResponse(timeoutMs) {
|
|
4082
|
-
return {
|
|
4083
|
-
contentItems: [{
|
|
4084
|
-
type: "inputText",
|
|
4085
|
-
text: `OpenClaw dynamic tool call timed out after ${timeoutMs}ms before sending a response to Codex.`
|
|
4086
|
-
}],
|
|
4087
|
-
success: false
|
|
4088
|
-
};
|
|
4089
|
-
}
|
|
4090
|
-
/** Raised when the initialize handshake detects an unsupported app-server version. */
|
|
4091
3903
|
var CodexAppServerVersionError = class extends Error {
|
|
4092
3904
|
constructor(detectedVersion) {
|
|
4093
3905
|
const detected = detectedVersion ? `detected ${detectedVersion}` : "OpenClaw could not determine the running Codex version";
|
|
@@ -4101,7 +3913,7 @@ function assertSupportedCodexAppServerVersion(response) {
|
|
|
4101
3913
|
if (!detectedVersion) throw new CodexAppServerVersionError(detectedVersion);
|
|
4102
3914
|
const detected = parse(detectedVersion);
|
|
4103
3915
|
if (!detected || detected.compare("0.149.0") < 0) throw new CodexAppServerVersionError(detectedVersion);
|
|
4104
|
-
if (detected.compare("0.
|
|
3916
|
+
if (detected.compare("0.158.0") > 0) embeddedAgentLog.warn("codex app-server is newer than OpenClaw's managed runtime; continuing with normal startup validation", {
|
|
4105
3917
|
detectedVersion,
|
|
4106
3918
|
validatedVersion: CODEX_APP_SERVER_VERSION
|
|
4107
3919
|
});
|
|
@@ -4110,65 +3922,16 @@ function assertSupportedCodexAppServerVersion(response) {
|
|
|
4110
3922
|
function isUnsupportedCodexAppServerVersionError(error) {
|
|
4111
3923
|
return error instanceof CodexAppServerVersionError;
|
|
4112
3924
|
}
|
|
4113
|
-
function buildCodexAppServerRuntimeIdentity(response, serverVersion) {
|
|
4114
|
-
const userAgent = normalizeOptionalString(response.userAgent);
|
|
4115
|
-
const codexHome = normalizeOptionalString(response.codexHome);
|
|
4116
|
-
const platformFamily = normalizeOptionalString(response.platformFamily);
|
|
4117
|
-
const platformOs = normalizeOptionalString(response.platformOs);
|
|
4118
|
-
return {
|
|
4119
|
-
serverVersion,
|
|
4120
|
-
...userAgent ? { userAgent } : {},
|
|
4121
|
-
...codexHome ? { codexHome } : {},
|
|
4122
|
-
...platformFamily ? { platformFamily } : {},
|
|
4123
|
-
...platformOs ? { platformOs } : {}
|
|
4124
|
-
};
|
|
4125
|
-
}
|
|
4126
|
-
/** Extracts the Codex version from the app-server initialize user-agent field. */
|
|
4127
3925
|
function readCodexVersionFromUserAgent(userAgent) {
|
|
4128
3926
|
return (userAgent?.match(/^[^/]+\/(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?)(?:[\s(]|$)/))?.[1];
|
|
4129
3927
|
}
|
|
4130
|
-
function redactCodexAppServerLinePreview(value) {
|
|
4131
|
-
const redacted = value.replace(/\s+/g, " ").trim().replace(/(Bearer\s+)[A-Za-z0-9._~+/-]+/gi, "$1<redacted>").replace(/("(?:api_?key|authorization|token|access_token|refresh_token)"\s*:\s*")([^"]+)(")/gi, "$1<redacted>$3").replace(/\b([a-z0-9_]*(?:api_?key|authorization|access_token|refresh_token|token))(\s*=\s*)(["']?)[^\s"']+(\3)/gi, "$1$2$3<redacted>$4");
|
|
4132
|
-
return redacted.length > CODEX_APP_SERVER_PARSE_LOG_MAX ? `${truncateUtf16Safe(redacted, CODEX_APP_SERVER_PARSE_LOG_MAX)}...` : redacted;
|
|
4133
|
-
}
|
|
4134
|
-
function appendBoundedTail(current, next, maxLength) {
|
|
4135
|
-
const combined = `${current}${next}`;
|
|
4136
|
-
return combined.length > maxLength ? sliceUtf16Safe(combined, -maxLength) : combined;
|
|
4137
|
-
}
|
|
4138
|
-
function buildCodexAppServerExitError(code, signal, stderrTail) {
|
|
4139
|
-
const stderrPreview = redactCodexAppServerLinePreview(stderrTail);
|
|
4140
|
-
const suffix = stderrPreview ? ` stderr=${JSON.stringify(stderrPreview)}` : "";
|
|
4141
|
-
return /* @__PURE__ */ new Error(`codex app-server exited: code=${formatExitValue(code)} signal=${formatExitValue(signal)}${suffix}`);
|
|
4142
|
-
}
|
|
4143
|
-
function shouldBufferCodexAppServerParseFailure(value, error) {
|
|
4144
|
-
if (!value.startsWith("{") && !value.startsWith("[")) return false;
|
|
4145
|
-
const message = coerceErrorMessage(error);
|
|
4146
|
-
return message.includes("Unterminated string") || message.includes("Unexpected end of JSON input");
|
|
4147
|
-
}
|
|
4148
|
-
function logCodexAppServerParseFailure(value, error, fragmentCount) {
|
|
4149
|
-
const linePreview = redactCodexAppServerLinePreview(value);
|
|
4150
|
-
const suffix = fragmentCount > 1 ? ` fragments=${fragmentCount}` : "";
|
|
4151
|
-
embeddedAgentLog.warn("failed to parse codex app-server message", {
|
|
4152
|
-
error,
|
|
4153
|
-
errorMessage: coerceErrorMessage(error),
|
|
4154
|
-
fragmentCount,
|
|
4155
|
-
linePreview,
|
|
4156
|
-
consoleMessage: `failed to parse codex app-server message${suffix}: preview=${JSON.stringify(linePreview)}`
|
|
4157
|
-
});
|
|
4158
|
-
}
|
|
4159
3928
|
const CODEX_APP_SERVER_APPROVAL_REQUEST_METHODS = /* @__PURE__ */ new Set([
|
|
4160
3929
|
"item/commandExecution/requestApproval",
|
|
4161
3930
|
"item/fileChange/requestApproval",
|
|
4162
3931
|
"item/permissions/requestApproval"
|
|
4163
3932
|
]);
|
|
4164
|
-
/** Returns true for app-server approval request methods OpenClaw can answer. */
|
|
4165
3933
|
function isCodexAppServerApprovalRequest(method) {
|
|
4166
3934
|
return CODEX_APP_SERVER_APPROVAL_REQUEST_METHODS.has(method);
|
|
4167
3935
|
}
|
|
4168
|
-
function formatExitValue(value) {
|
|
4169
|
-
if (value === null || value === void 0) return "null";
|
|
4170
|
-
if (typeof value === "string" || typeof value === "number") return String(value);
|
|
4171
|
-
return "unknown";
|
|
4172
|
-
}
|
|
4173
3936
|
//#endregion
|
|
4174
|
-
export {
|
|
3937
|
+
export { handleDynamicToolCallWithTimeout as A, resolveCodexToolAbortTerminalReason as B, assertExactSupervisionModelSelection as C, readSupervisionResponseThreadId as D, readCodexTurnCompletedNotification as E, resolveTerminalDynamicToolBatchAction as F, failedToolResult as H, shouldBlockTerminalReleaseForNonTerminalDynamicToolResult as I, shouldReleaseTurnAfterTerminalDynamicTool as L, isDynamicToolTerminalDiagnosticEvent as M, isMatchingDynamicToolTerminalDiagnostic as N, resolveCodexThreadRolloutPath as O, resolveDynamicToolCallTimeoutMs as P, toCodexDynamicToolProgressResponse as R, assertCodexTurnStartResponse as S, readCodexErrorNotification as T, CODEX_APP_SERVER_OPT_OUT_NOTIFICATION_METHODS as U, createFailedDynamicToolResponse as V, assertCodexPassiveTurnItems as _, isCodexAppServerBrokenPipeError as a, assertCodexThreadResumeResponse as b, isCodexAppServerIndeterminateTransportError as c, isCodexAppServerRequestTimeoutError as d, isUnsupportedCodexAppServerVersionError as f, assertCodexModelListResponse as g, CodexThreadDirectInputError as h, isCodexAppServerApprovalRequest as i, hasPendingDynamicToolTerminalDiagnostic as j, createCodexElicitationResponse as k, isCodexAppServerOverloadError as l, CodexServerRequestResolvedError as m, client_exports as n, isCodexAppServerConnectionClosedError as o, resolveCodexAppServerClientInstanceId as p, getCodexAppServerClientInstanceId as r, isCodexAppServerIndeterminateRequestCancellationError as s, CodexAppServerClient as t, isCodexAppServerPrewriteRequestCancellationError as u, assertCodexThreadAcceptsDirectInput as v, readCodexDynamicToolCallParams as w, assertCodexThreadStartResponse as x, assertCodexThreadForkResponse as y, toCodexDynamicToolProtocolResponse as z };
|