@openclaw/codex 2026.9.3 → 2026.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/activity.svg +30 -0
- package/assets/icon.png +0 -0
- package/dist/.setup/account-usage-runtime-C2MOIvfq.mjs +75 -0
- package/dist/{apply-B6el6hdO.js → .setup/apply-CJ0ZfmBG.mjs} +12 -13
- package/dist/.setup/async-questions-DdhOCwGi.mjs +27 -0
- package/dist/{attempt-client-cleanup-D6cR54TV.js → .setup/attempt-client-cleanup-BpYKdTA0.mjs} +30 -211
- package/dist/{attempt-context-AO4DSjE0.js → .setup/attempt-context-VXVwTCfS.mjs} +6 -6
- package/dist/.setup/attempt-terminal-gZrxQ35N.mjs +5 -0
- package/dist/{auth-binding-Co2Vfcf_.js → .setup/auth-binding-DhLWa_7K.mjs} +2 -2
- package/dist/{auth-cache-key-Kq6oerr6.js → .setup/auth-cache-key-QirmgiCo.mjs} +3 -3
- package/dist/{auth-profile-CwzO4_RG.js → .setup/auth-profile-WqZtZfXN.mjs} +1 -1
- package/dist/.setup/binding-connection-Bm38niE8.mjs +50 -0
- package/dist/.setup/binding-connection.runtime-CnRMC0ta.mjs +48 -0
- package/dist/{bounded-turn-lRpmZHFv.js → .setup/bounded-turn-BtlZcivC.mjs} +19 -14
- package/dist/{build-state-6RL6qohz.js → .setup/build-state-Xx9ybZqa.mjs} +1 -1
- package/dist/{capabilities-BeqLPbtM.js → .setup/capabilities-_vXcZGSx.mjs} +1 -1
- package/dist/{client-BEKu4yDx.js → .setup/client-vXs2929Q.mjs} +355 -164
- package/dist/{command-dispatch-CisT9Jqq.js → .setup/command-dispatch-naHIZwwF.mjs} +3 -3
- package/dist/{command-formatters-DeTfrapr.js → .setup/command-formatters-CGEkdawF.mjs} +4 -3
- package/dist/{command-handlers-BfIsJEuA.js → .setup/command-handlers-BtAJEW1X.mjs} +812 -152
- package/dist/{command-rpc-BMqRQOFX.js → .setup/command-rpc-DHFpn4le.mjs} +37 -21
- package/dist/{compact-CGJZ2rlb.js → .setup/compact-C3i3qlzj.mjs} +28 -43
- package/dist/{config-JDfTI4VI.js → .setup/config-CedDWjM-.mjs} +5 -4
- package/dist/{config-options-jnIFvwxD.js → .setup/config-options-BsanJ8QG.mjs} +9 -421
- package/dist/{protocol-CAAcVIKF.js → .setup/config-parsing-CcB9iPoq.mjs} +9 -51
- package/dist/{config-runtime-BWf6JLWG.js → .setup/config-runtime-CeAhl_h4.mjs} +2 -2
- package/dist/.setup/config-security-BRQ2mgW9.mjs +465 -0
- package/dist/{config-utils-C57JiJrU.js → .setup/config-utils-DujwEnhg.mjs} +2 -4
- package/dist/{conversation-binding-CxOlHiix.js → .setup/conversation-binding-DhzrpTM6.mjs} +60 -47
- package/dist/{conversation-binding-data-BiodpIzq.js → .setup/conversation-binding-data-CrcyZk6O.mjs} +1 -1
- package/dist/{conversation-control-CUCrSIQI.js → .setup/conversation-control-DN53ns41.mjs} +17 -13
- package/dist/.setup/cyber-failover-DYwbmf1o.mjs +123 -0
- package/dist/.setup/cyber-failover-notice-e9G3J9-e.mjs +17 -0
- package/dist/{dynamic-tools-D-JBoaLt.js → .setup/dynamic-tools-D16lOp67.mjs} +168 -61
- package/dist/{effective-mcp-catalog-J_5Ep5Um.js → .setup/effective-mcp-catalog-K6kLCN8X.mjs} +3 -3
- package/dist/{ephemeral-turn-DSwzP8YY.js → .setup/ephemeral-turn-R1gA8Sn6.mjs} +4 -5
- package/dist/{event-projector-assistant-message-BmBM4qBV.js → .setup/event-projector-assistant-message-DNUR1s0A.mjs} +6 -3
- package/dist/.setup/event-projector-items-DyTQ_XqL.mjs +200 -0
- package/dist/{attempt-notifications--H8zXR5-.js → .setup/event-projector-usage-C7Ntzs-f.mjs} +102 -9
- package/dist/{harness-FR6eQgyO.js → .setup/harness-rxaaoN-o.mjs} +90 -19
- package/dist/.setup/inference-context-fulhZuz8.mjs +94 -0
- package/dist/.setup/inference-proxy-CC15HuSi.mjs +311 -0
- package/dist/{isolated-completion-DHBefrzg.js → .setup/isolated-completion-B6srt48J.mjs} +7 -7
- package/dist/{launch-args-RXQwn8zV.js → .setup/launch-args-DnMak49W.mjs} +22 -1
- package/dist/{managed-binary-DrjjRRUD.js → .setup/managed-binary-DP6Rib3P.mjs} +11 -2
- package/dist/{managed-thread-store-D1t5jh3G.js → .setup/managed-thread-store-BMqgThVL.mjs} +48 -14
- package/dist/{model-catalog-B_6M04Wo.js → .setup/model-catalog-DkvUuBey.mjs} +35 -10
- package/dist/{models-P9k2qAof.js → .setup/models-BDFgm_G-.mjs} +3 -3
- package/dist/.setup/native-auth-BLZGqFjw.mjs +57 -0
- package/dist/.setup/native-subagent-history-YXaL6dMd.mjs +135 -0
- package/dist/.setup/native-subagent-monitor-B1hxzIOy.mjs +5031 -0
- package/dist/.setup/native-subagent-task-ids-DsuOonKv.mjs +411 -0
- package/dist/{node-cli-sessions-rj0ysJwM.js → .setup/node-cli-sessions-Cl8b2ZF3.mjs} +1 -1
- package/dist/{node-exec-server.runtime-BY_ctYnT.js → .setup/node-exec-server.runtime-BaViBKNz.mjs} +5 -5
- package/dist/{plan-BMJdMOEF.js → .setup/plan-xD7WKYTM.mjs} +331 -79
- package/dist/{plugin-activation-BQK-f5sV.js → .setup/plugin-activation-r8nq5Jzp.mjs} +24 -19
- package/dist/{plugin-app-cache-key-CdSQzWyX.js → .setup/plugin-app-cache-key-BOxKP7db.mjs} +29 -25
- package/dist/{plugin-approval-roundtrip-DeW95wB5.js → .setup/plugin-approval-roundtrip-CjfzafAZ.mjs} +1 -1
- package/dist/{plugin-inventory-CoRCzWW4.js → .setup/plugin-inventory-DUle8DLz.mjs} +12 -8
- package/dist/{plugin-marketplace-discovery-3akBizzF.js → .setup/plugin-marketplace-discovery-P-Vndfqq.mjs} +18 -15
- package/dist/{plugin-metadata-cache-DgNfRAGA.js → .setup/plugin-metadata-cache-DsS5buNa.mjs} +33 -14
- package/dist/{provider-capabilities-W4tfK5Y5.js → .setup/provider-capabilities-B8J4Dy-O.mjs} +2 -2
- package/dist/.setup/provider-fFh_-VR3.mjs +50 -0
- package/dist/{rate-limits-Bqnx1N4z.js → .setup/rate-limits-DOEGYRNs.mjs} +90 -46
- package/dist/.setup/request-BioXJLYa.mjs +292 -0
- package/dist/.setup/run-attempt-lifecycle-B7JbY4-F.mjs +71 -0
- package/dist/{run-attempt-DwKds3DN.js → .setup/run-attempt-rlA07pUv.mjs} +644 -491
- package/dist/{runtime-artifact-T-NwqeSH.js → .setup/runtime-artifact-Dy38Z5iU.mjs} +2 -2
- package/dist/{sandbox-guard-BcT66fWy.js → .setup/sandbox-guard-BBP-RbTf.mjs} +4 -3
- package/dist/{session-binding-CKSepwIC.js → .setup/session-binding-_0W_fHRr.mjs} +45 -63
- package/dist/{session-binding-record-CaZjYwNS.js → .setup/session-binding-record-TH3xA0zj.mjs} +181 -3
- package/dist/.setup/session-binding-sidecars-CKYEcfNn.mjs +543 -0
- package/dist/{session-catalog-adoption-BKLtSrwi.js → .setup/session-catalog-adoption-CR_whkEW.mjs} +6 -6
- package/dist/{session-catalog-archive-D0i2pGj2.js → .setup/session-catalog-archive-CwZaPacf.mjs} +6 -6
- package/dist/.setup/session-catalog-events-jMcYfQyd.mjs +250 -0
- package/dist/.setup/session-catalog-fUdWDx-U.mjs +2464 -0
- package/dist/.setup/session-catalog-index-B141u15s.mjs +1070 -0
- package/dist/.setup/session-catalog-index-order-Cc5BzlQr.mjs +48 -0
- package/dist/.setup/session-catalog-index-state-BAuDztHN.mjs +180 -0
- package/dist/{session-catalog-parsing-CdD3JhdM.js → .setup/session-catalog-native-projection-ChV3cCtm.mjs} +213 -21
- package/dist/{session-catalog-node-adoption-BUuDYY8R.js → .setup/session-catalog-node-adoption-BVRsYOSh.mjs} +3 -3
- package/dist/{session-catalog-node-continue-CBtc4wkI.js → .setup/session-catalog-node-continue-Dowv8osw.mjs} +7 -7
- package/dist/.setup/session-catalog-projection-C1Bj9Jl-.mjs +414 -0
- package/dist/{session-cli-CbgaHh0f.js → .setup/session-cli-DIj-IE-E.mjs} +4 -4
- package/dist/{session-history-Cz-tOOYj.js → .setup/session-history-C--SrLI8.mjs} +10 -5
- package/dist/{session-history-import-DFN7sWRU.js → .setup/session-history-import-JHXT5Xfi.mjs} +4 -4
- package/dist/{session-history-read-cxPUxyVV.js → .setup/session-history-read-B3ZfSUbF.mjs} +2 -2
- package/dist/{session-history.worker-CNEvGaU5.js → .setup/session-history.worker-CpNj7H_P.mjs} +192 -89
- package/dist/{session-initialization-Jo86C60I.js → .setup/session-initialization-DH1z6fXn.mjs} +2 -2
- package/dist/{session-permission-policy-B22InTp_.js → .setup/session-permission-policy-DhurXY0l.mjs} +2 -2
- package/dist/{session-retirement-BSNG_mhf.js → .setup/session-retirement-CU87AOg9.mjs} +6 -6
- package/dist/{settled-turn-context-Du6gdUDd.js → .setup/settled-turn-context-fmwouT5I.mjs} +2 -2
- package/dist/{settled-turn-finalizer-BuLUrZl2.js → .setup/settled-turn-finalizer-CiY2bLFK.mjs} +10 -10
- package/dist/{shared-client-CVhez2Uo.js → .setup/shared-client-BpTtuLQ5.mjs} +495 -156
- package/dist/{side-question-DLbr2vUU.js → .setup/side-question-DSCZyoBD.mjs} +64 -47
- package/dist/{source-Da-h6f7e.js → .setup/source-Bjp4UQij.mjs} +15 -14
- package/dist/{thread-archive-guard-D1bP04Tf.js → .setup/thread-archive-guard-jmecf6OJ.mjs} +1 -1
- package/dist/.setup/thread-history-page-BTx-4xsg.mjs +83 -0
- package/dist/{thread-lifecycle-D1pzRwHB.js → .setup/thread-lifecycle-Cik28qWn.mjs} +330 -150
- package/dist/{thread-ownership-D6oASVRu.js → .setup/thread-ownership-skomxnIt.mjs} +4 -4
- package/dist/{thread-policy-D8kI7yAO.js → .setup/thread-policy-Cjs4B8xf.mjs} +3 -3
- package/dist/{thread-resume-T5cveyxA.js → .setup/thread-resume-BkNpj9Pz.mjs} +8 -5
- package/dist/.setup/timeout-DZF05XrR.mjs +63 -0
- package/dist/{session-catalog-home-id-D7-aLiNt.js → .setup/transcript-history-projection-DHNBDhCU.mjs} +73 -20
- package/dist/{transcript-mirror-t5TOccct.js → .setup/transcript-mirror-D4qp_leP.mjs} +15 -6
- package/dist/{transcript-mirror-attestation-DibE0krH.js → .setup/transcript-mirror-attestation-CzM-94NC.mjs} +4 -1
- package/dist/{transport-stdio-BGjHoYLr.js → .setup/transport-stdio-Cmx94Oiy.mjs} +149 -44
- package/dist/{upstream-session-fork-De-sLJ2r.js → .setup/upstream-session-fork-D3UKxgVD.mjs} +27 -26
- package/dist/{usage-CPPTmBvZ.js → .setup/usage-BOgBEKso.mjs} +4 -4
- package/dist/.setup/usage-limit-error-C0ow7DOc.mjs +166 -0
- package/dist/{version-omm6IPI3.js → .setup/version-CoqzXPgK.mjs} +1 -1
- package/dist/{web-search-provider.runtime-CSVgQL0w.js → .setup/web-search-provider.runtime-CTGuJt6i.mjs} +3 -3
- package/dist/api.js +28 -20
- package/dist/cli-metadata.js +1 -1
- package/dist/doctor-contract-api.js +8 -528
- package/dist/harness.js +1 -1
- package/dist/index.js +130 -135
- package/dist/media-understanding-provider.js +3 -3
- package/dist/migration-provider-api.js +2 -0
- package/dist/native-tool-policy.js +12 -0
- package/dist/provider-discovery.js +18 -0
- package/dist/session-history-worker-runtime.js +23 -5
- package/dist/session-history.worker.js +2 -2
- package/dist/web-search-contract-api.js +1 -1
- package/openclaw.plugin.json +354 -68
- package/package.json +11 -8
- package/dist/binding-connection-QqgcPCgk.js +0 -60
- package/dist/event-projector-usage-CIyrYYid.js +0 -102
- package/dist/native-subagent-monitor-BbCUKRwC.js +0 -3350
- package/dist/request-CGvGOpeR.js +0 -198
- package/dist/session-catalog-HaDcp7Sv.js +0 -1533
- package/dist/session-catalog-provenance-DkJHo735.js +0 -124
- package/dist/timeout-BVw8aaM1.js +0 -33
- package/dist/{auth-profile-selection-DFu9e167.js → .setup/auth-profile-selection-DFu9e167.mjs} +0 -0
- package/dist/{context-compaction-activity-CMla5FPJ.js → .setup/context-compaction-activity-CMla5FPJ.mjs} +0 -0
- package/dist/{elicitation-input-DPoK8F7w.js → .setup/elicitation-input-DPoK8F7w.mjs} +0 -0
- package/dist/{history-rejection-B4nOXNXF.js → .setup/history-rejection-B4nOXNXF.mjs} +0 -0
- package/dist/{image-payload-sanitizer-tupAr-2o.js → .setup/image-payload-sanitizer-tupAr-2o.mjs} +0 -0
- package/dist/{incognito-session-uhrBF6wJ.js → .setup/incognito-session-uhrBF6wJ.mjs} +0 -0
- package/dist/{local-runtime-attribution-B_2mnqhb.js → .setup/local-runtime-attribution-B_2mnqhb.mjs} +0 -0
- package/dist/{native-execution-policy-umd0tgh4.js → .setup/native-execution-policy-YBMHSzC4.mjs} +1 -1
- /package/dist/{rolldown-runtime-8H4AJuhK.js → .setup/rolldown-runtime-8H4AJuhK.mjs} +0 -0
- /package/dist/{session-binding-meta-B7aEMU7g.js → .setup/session-binding-meta-B7aEMU7g.mjs} +0 -0
- /package/dist/{session-upstream-marker-D15C9NHp.js → .setup/session-upstream-marker-D15C9NHp.mjs} +0 -0
- /package/dist/{upstream-prompt-provenance-LphB8slG.js → .setup/upstream-prompt-provenance-LphB8slG.mjs} +0 -0
- /package/dist/{web-search-provider.shared-BrZmlqyR.js → .setup/web-search-provider.shared-BrZmlqyR.mjs} +0 -0
|
@@ -1,33 +1,107 @@
|
|
|
1
|
-
import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.
|
|
2
|
-
import { t as codexBuildSymbol } from "./build-state-
|
|
3
|
-
import { t as CODEX_APP_SERVER_AUTH_PROVIDER } from "./auth-profile-selection-DFu9e167.
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { t as
|
|
7
|
-
import {
|
|
8
|
-
import { c as
|
|
9
|
-
import { _ as isCodexDesktopGenerationCurrent, a as readCodexCliAuthFileApiKey, c as resolveCodexAppServerPreparedApiKeyCacheKey, d as createCodexAppServerStartupLifetime, f as getCurrentSharedClientEntry, i as fingerprintTokenAuthProfileCacheKey, l as closeRetiredSharedClientEntry, m as retireSharedCodexAppServerClientIfCurrent, n as CODEX_AUTH_JSON_FILENAME, o as readFirstNonEmptyEnv, p as getSharedCodexAppServerClientState, r as fingerprintApiKeyAuthProfileCacheKey, s as resolveCodexAppServerFallbackApiKeyCacheKey, t as CODEX_APP_SERVER_API_KEY_ENV_VARS, u as closeRetiredSharedClientEntryIfIdle, v as waitForCodexDesktopGeneration } from "./auth-cache-key-
|
|
10
|
-
import { n as resolveCodexAppServerSpawnEnv } from "./transport-stdio-
|
|
11
|
-
import { n as
|
|
12
|
-
import { n as
|
|
13
|
-
import { n as resolveCodexAppServerRuntimeOptions } from "./config-runtime-
|
|
14
|
-
import { a as resolveCodexAppServerAuthProfileStore, i as resolveCodexAppServerAuthProfileIdForAgent, r as resolveCodexAppServerAuthProfileId, t as isCodexAppServerNativeAuthProfile } from "./auth-profile-
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.mjs";
|
|
2
|
+
import { n as defineCodexBuildState, t as codexBuildSymbol } from "./build-state-Xx9ybZqa.mjs";
|
|
3
|
+
import { t as CODEX_APP_SERVER_AUTH_PROVIDER } from "./auth-profile-selection-DFu9e167.mjs";
|
|
4
|
+
import { _ as resolveCodexAppServerUserHomeDir, g as resolveCodexAppServerLocalHomeDir, h as resolveCodexAppServerHomeDir, m as isJsonObject, v as withEphemeralCodexAuthStore } from "./config-security-BRQ2mgW9.mjs";
|
|
5
|
+
import { n as isCodexAppServerProxyLaunch } from "./launch-args-DnMak49W.mjs";
|
|
6
|
+
import { f as isUnsupportedCodexAppServerVersionError, t as CodexAppServerClient } from "./client-vXs2929Q.mjs";
|
|
7
|
+
import { a as resolveCodexAppServerStartOptionsForAgent, d as readCodexEffectiveConfig, o as resolveCodexComputerUseConfig, t as codexAppServerStartOptionsKey, u as CODEX_SESSION_OVERRIDABLE_LAYER_TYPES } from "./config-options-BsanJ8QG.mjs";
|
|
8
|
+
import { c as resolveMacOSDesktopCodexAppPathCandidates, i as resolveManagedCodexNativeCommand, l as resolveMacOSDesktopCodexBundledMarketplaceCandidates, r as resolveManagedCodexAppServerStartOptions, s as resolveFirstExistingMacOSDesktopCodexBundledMarketplacePath, t as isManagedCodexDesktopCommand, u as resolveMacOSDesktopCodexComputerUseServiceAppCandidates } from "./managed-binary-DP6Rib3P.mjs";
|
|
9
|
+
import { _ as isCodexDesktopGenerationCurrent, a as readCodexCliAuthFileApiKey, c as resolveCodexAppServerPreparedApiKeyCacheKey, d as createCodexAppServerStartupLifetime, f as getCurrentSharedClientEntry, i as fingerprintTokenAuthProfileCacheKey, l as closeRetiredSharedClientEntry, m as retireSharedCodexAppServerClientIfCurrent, n as CODEX_AUTH_JSON_FILENAME, o as readFirstNonEmptyEnv, p as getSharedCodexAppServerClientState, r as fingerprintApiKeyAuthProfileCacheKey, s as resolveCodexAppServerFallbackApiKeyCacheKey, t as CODEX_APP_SERVER_API_KEY_ENV_VARS, u as closeRetiredSharedClientEntryIfIdle, v as waitForCodexDesktopGeneration } from "./auth-cache-key-QirmgiCo.mjs";
|
|
10
|
+
import { n as resolveCodexAppServerSpawnEnv } from "./transport-stdio-Cmx94Oiy.mjs";
|
|
11
|
+
import { n as withTimeout } from "./timeout-DZF05XrR.mjs";
|
|
12
|
+
import { c as readCodexSessionMeta, n as observeCodexCatalogClient } from "./session-catalog-events-jMcYfQyd.mjs";
|
|
13
|
+
import { n as resolveCodexAppServerRuntimeOptions } from "./config-runtime-CeAhl_h4.mjs";
|
|
14
|
+
import { a as resolveCodexAppServerAuthProfileStore, i as resolveCodexAppServerAuthProfileIdForAgent, r as resolveCodexAppServerAuthProfileId, t as isCodexAppServerNativeAuthProfile } from "./auth-profile-WqZtZfXN.mjs";
|
|
15
15
|
import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
16
16
|
import { createHash } from "node:crypto";
|
|
17
|
+
import { isDeepStrictEqual } from "node:util";
|
|
17
18
|
import { AgentHarnessPreflightError, resolveDefaultAgentDir } from "openclaw/plugin-sdk/agent-harness-registration";
|
|
18
19
|
import { addTimerTimeoutGraceMs, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
|
|
19
20
|
import { runExec } from "openclaw/plugin-sdk/process-runtime";
|
|
20
21
|
import fs, { constants } from "node:fs";
|
|
21
22
|
import path from "node:path";
|
|
22
23
|
import fs$1 from "node:fs/promises";
|
|
23
|
-
import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
|
|
24
24
|
import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
|
|
25
|
-
import {
|
|
26
|
-
import { ensureAuthProfileStore, findPersistedAuthProfileCredential, loadAuthProfileStoreForSecretsRuntime, refreshOAuthCredentialForRuntime, resolveApiKeyForProfile, resolvePersistedAuthProfileOwnerAgentDir } from "openclaw/plugin-sdk/agent-runtime";
|
|
25
|
+
import { ensureAuthProfileStore, findPersistedAuthProfileCredential, refreshOAuthCredentialForRuntime, resolveApiKeyForProfile, resolvePersistedAuthProfileOwnerAgentDir } from "openclaw/plugin-sdk/agent-runtime";
|
|
27
26
|
import { AgentHarnessPreflightError as AgentHarnessPreflightError$1, embeddedAgentLog as embeddedAgentLog$1, formatErrorMessage } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
28
|
-
import { resolveProviderIdForAuth } from "openclaw/plugin-sdk/provider-auth-aliases";
|
|
29
|
-
import { assertNoSymlinkParents } from "openclaw/plugin-sdk/security-runtime";
|
|
30
27
|
import { hasUsableOAuthCredential, resolveOpenAICodexAuthIdentity } from "openclaw/plugin-sdk/provider-auth";
|
|
28
|
+
import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
|
|
29
|
+
import { assertNoSymlinkParents } from "openclaw/plugin-sdk/security-runtime";
|
|
30
|
+
//#region extensions/codex/src/app-server/attempt-timeouts.ts
|
|
31
|
+
/**
|
|
32
|
+
* Timeout defaults and normalizers for Codex app-server startup and turn
|
|
33
|
+
* liveness watches.
|
|
34
|
+
*/
|
|
35
|
+
/** Minimum startup timeout accepted by the Codex app-server harness. */
|
|
36
|
+
const CODEX_APP_SERVER_STARTUP_TIMEOUT_FLOOR_MS = 100;
|
|
37
|
+
const TURN_TERMINAL_SETTLEMENT_TIMEOUT_MS = 12e4;
|
|
38
|
+
const TURN_FINALIZE_DRAIN_ABORT_GRACE_MS = 5e3;
|
|
39
|
+
var CodexAppServerStartupError = class extends Error {
|
|
40
|
+
constructor(reason, message = reason === "timed_out" ? "codex app-server startup timed out" : "codex app-server startup aborted") {
|
|
41
|
+
super(message);
|
|
42
|
+
this.reason = reason;
|
|
43
|
+
this.code = "CODEX_APP_SERVER_STARTUP_CANCELLED";
|
|
44
|
+
this.name = "CodexAppServerStartupError";
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
function isCodexAppServerStartupError(error, reason) {
|
|
48
|
+
return error instanceof Error && "code" in error && error.code === "CODEX_APP_SERVER_STARTUP_CANCELLED" && "reason" in error && (error.reason === "aborted" || error.reason === "timed_out") && (reason === void 0 || error.reason === reason);
|
|
49
|
+
}
|
|
50
|
+
function resolvePositiveIntegerTimeoutMs(value, fallbackMs) {
|
|
51
|
+
const fallback = resolveTimerTimeoutMs(fallbackMs, 1);
|
|
52
|
+
return resolveTimerTimeoutMs(value, fallback);
|
|
53
|
+
}
|
|
54
|
+
/** Runs startup work with abort and timeout handling plus optional cleanup. */
|
|
55
|
+
async function withCodexStartupTimeout(params) {
|
|
56
|
+
if (params.signal.aborted) throw new CodexAppServerStartupError("aborted");
|
|
57
|
+
let timeout;
|
|
58
|
+
let abortCleanup;
|
|
59
|
+
let timeoutError;
|
|
60
|
+
let timeoutCleanup;
|
|
61
|
+
try {
|
|
62
|
+
return await Promise.race([params.operation(), new Promise((_, reject) => {
|
|
63
|
+
const rejectOnce = (error) => {
|
|
64
|
+
if (timeout) {
|
|
65
|
+
clearTimeout(timeout);
|
|
66
|
+
timeout = void 0;
|
|
67
|
+
}
|
|
68
|
+
reject(error);
|
|
69
|
+
};
|
|
70
|
+
timeout = setTimeout(() => {
|
|
71
|
+
timeoutError = new CodexAppServerStartupError("timed_out");
|
|
72
|
+
timeoutCleanup = Promise.resolve(params.onTimeout?.()).then(() => void 0, () => void 0);
|
|
73
|
+
timeoutCleanup.finally(() => {
|
|
74
|
+
rejectOnce(timeoutError);
|
|
75
|
+
});
|
|
76
|
+
}, params.timeoutMs);
|
|
77
|
+
const abortListener = () => rejectOnce(new CodexAppServerStartupError("aborted"));
|
|
78
|
+
params.signal.addEventListener("abort", abortListener, { once: true });
|
|
79
|
+
abortCleanup = () => params.signal.removeEventListener("abort", abortListener);
|
|
80
|
+
})]);
|
|
81
|
+
} catch (error) {
|
|
82
|
+
if (timeoutError) {
|
|
83
|
+
await timeoutCleanup;
|
|
84
|
+
throw timeoutError;
|
|
85
|
+
}
|
|
86
|
+
throw error;
|
|
87
|
+
} finally {
|
|
88
|
+
if (timeout) clearTimeout(timeout);
|
|
89
|
+
abortCleanup?.();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/** Resolves startup timeout while honoring the configured floor. */
|
|
93
|
+
function resolveCodexStartupTimeoutMs(params) {
|
|
94
|
+
const timeoutFloorMs = resolvePositiveIntegerTimeoutMs(params.timeoutFloorMs, CODEX_APP_SERVER_STARTUP_TIMEOUT_FLOOR_MS);
|
|
95
|
+
const timeoutMs = resolvePositiveIntegerTimeoutMs(params.timeoutMs, timeoutFloorMs);
|
|
96
|
+
return Math.max(timeoutFloorMs, timeoutMs);
|
|
97
|
+
}
|
|
98
|
+
/** Adds gateway grace time to a caller timeout without overflowing invalid values. */
|
|
99
|
+
function resolveCodexGatewayTimeoutWithGraceMs(timeoutMs, graceMs = 1e4) {
|
|
100
|
+
const timeout = resolvePositiveIntegerTimeoutMs(timeoutMs, 1);
|
|
101
|
+
const grace = resolveTimerTimeoutMs(graceMs, 0, 0);
|
|
102
|
+
return addTimerTimeoutGraceMs(timeout, grace) ?? timeout;
|
|
103
|
+
}
|
|
104
|
+
//#endregion
|
|
31
105
|
//#region extensions/codex/src/app-server/computer-use-service-path.ts
|
|
32
106
|
/** Filesystem ownership guards for isolated Computer Use service provisioning. */
|
|
33
107
|
async function assertOwnedServicePath(params) {
|
|
@@ -239,6 +313,7 @@ async function ensureRealDirectoryCopy(cachePath, sourcePluginRoot, version, bou
|
|
|
239
313
|
let backupCreated = false;
|
|
240
314
|
try {
|
|
241
315
|
await fs$1.cp(sourcePluginRoot, stagedPath, { recursive: true });
|
|
316
|
+
await waitForCodexDesktopGeneration();
|
|
242
317
|
if (ownedParent) await assertDirectoryIdentityStable(ownedParent, "Computer Use plugin cache parent");
|
|
243
318
|
if (stat) {
|
|
244
319
|
boundary.assertCurrent?.();
|
|
@@ -524,7 +599,9 @@ async function ensureCodexComputerUseServiceAppOnce(params) {
|
|
|
524
599
|
if (!stagedIdentity || !identitiesMatch(stagedIdentity, sourceIdentity)) throw new Error(`Copied Computer Use service app at ${stagedPath} does not match its selected signed source.`);
|
|
525
600
|
const stagedSnapshot = await readServiceAppSnapshot(stagedPath, inspectServiceApp);
|
|
526
601
|
const currentSourceIdentity = await inspectServiceApp(sourcePath);
|
|
602
|
+
await waitForCodexDesktopGeneration();
|
|
527
603
|
await assertOwnedServiceParentStable(ownedParent);
|
|
604
|
+
await assertDirectoryIdentityStable(stagingRootIdentity, "Computer Use service staging directory");
|
|
528
605
|
if (!currentSourceIdentity || !identitiesMatch(currentSourceIdentity, sourceIdentity)) throw new Error("Selected Computer Use service source changed during refresh.");
|
|
529
606
|
await assertNotSymlink(operationTargetPath, "Computer Use service target");
|
|
530
607
|
if (await pathExists$1(operationTargetPath)) {
|
|
@@ -1017,7 +1094,9 @@ async function reconcileCodexComputerUseStartArtifactsOnce(params) {
|
|
|
1017
1094
|
const computerUseConfig = resolveCodexComputerUseConfig({ pluginConfig: params.pluginConfig });
|
|
1018
1095
|
const ownsIsolatedCodexHome = params.ownsIsolatedCodexHome ?? (params.startOptions.homeScope !== "user" && !params.startOptions.env?.[CODEX_HOME_ENV_VAR]?.trim());
|
|
1019
1096
|
const shouldProvisionComputerUse = computerUseConfig.enabled && computerUseConfig.autoInstall && ownsIsolatedCodexHome;
|
|
1020
|
-
|
|
1097
|
+
const provisioningAgentDir = shouldProvisionComputerUse ? params.agentDir : void 0;
|
|
1098
|
+
if (shouldProvisionComputerUse && !provisioningAgentDir) throw new Error("Managed Codex Computer Use requires an OpenClaw agent directory");
|
|
1099
|
+
if (provisioningAgentDir) await ensureOwnedCodexHome(codexHome, provisioningAgentDir);
|
|
1021
1100
|
else await fs$1.mkdir(codexHome, { recursive: true });
|
|
1022
1101
|
const desktopCandidates = resolveMacOSDesktopCodexAppPathCandidates();
|
|
1023
1102
|
const exactDesktopCandidate = desktopCandidates.find((candidate) => path.resolve(candidate.appServerCommandPath) === path.resolve(params.startOptions.command));
|
|
@@ -1028,12 +1107,12 @@ async function reconcileCodexComputerUseStartArtifactsOnce(params) {
|
|
|
1028
1107
|
needsBundledMarketplace
|
|
1029
1108
|
}) : exactDesktopCandidate;
|
|
1030
1109
|
params.assertCurrent();
|
|
1031
|
-
if (
|
|
1110
|
+
if (provisioningAgentDir) {
|
|
1032
1111
|
if (desktopCandidates.length > 0 && !artifactCandidate) throw new CodexComputerUseCandidateArtifactsUnavailableError();
|
|
1033
1112
|
try {
|
|
1034
1113
|
const marketplacePath = usesManagedBundledMarketplace ? await ensureCodexManagedBundledMarketplace({
|
|
1035
1114
|
codexHome,
|
|
1036
|
-
ownershipRoot:
|
|
1115
|
+
ownershipRoot: provisioningAgentDir,
|
|
1037
1116
|
...artifactCandidate ? {
|
|
1038
1117
|
appServerCommand: artifactCandidate.appServerCommandPath,
|
|
1039
1118
|
candidates: [artifactCandidate],
|
|
@@ -1112,11 +1191,12 @@ async function applyCodexAppServerAuthProfile(params) {
|
|
|
1112
1191
|
await assertNativeCodexAccountMatchesRoute(params.client, params.authRequirement, params.assertCurrent);
|
|
1113
1192
|
return;
|
|
1114
1193
|
}
|
|
1194
|
+
const agentDir = params.agentDir ?? resolveDefaultAgentDir(params.config ?? {});
|
|
1115
1195
|
let loginParams = params.preparedAuth?.kind === "profile" ? params.preparedAuth.snapshot.loginParams : params.preparedAuth?.kind === "api-key" ? {
|
|
1116
1196
|
type: "apiKey",
|
|
1117
1197
|
apiKey: params.preparedAuth.apiKey
|
|
1118
1198
|
} : await resolveCodexAppServerAuthProfileLoginParams({
|
|
1119
|
-
agentDir
|
|
1199
|
+
agentDir,
|
|
1120
1200
|
authProfileId: params.authProfileId ?? void 0,
|
|
1121
1201
|
authProfileStore: params.authProfileStore,
|
|
1122
1202
|
config: params.config
|
|
@@ -1131,7 +1211,16 @@ async function applyCodexAppServerAuthProfile(params) {
|
|
|
1131
1211
|
assertCurrent: params.assertCurrent
|
|
1132
1212
|
});
|
|
1133
1213
|
}
|
|
1134
|
-
if (loginParams)
|
|
1214
|
+
if (loginParams) {
|
|
1215
|
+
await params.client.request("account/login/start", loginParams, { assertCurrent: params.assertCurrent });
|
|
1216
|
+
if (loginParams.type === "chatgptAuthTokens") {
|
|
1217
|
+
params.assertCurrent?.();
|
|
1218
|
+
return {
|
|
1219
|
+
accessFingerprint: fingerprintTokenAuthProfileCacheKey(loginParams.accessToken),
|
|
1220
|
+
chatgptAccountId: loginParams.chatgptAccountId
|
|
1221
|
+
};
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1135
1224
|
}
|
|
1136
1225
|
/**
|
|
1137
1226
|
* Native-home connections are verified, never logged into. Both directions of the
|
|
@@ -1178,6 +1267,8 @@ async function resolveCodexAppServerAuthProfileLoginParams(params) {
|
|
|
1178
1267
|
}
|
|
1179
1268
|
async function refreshCodexAppServerAuthTokens(params) {
|
|
1180
1269
|
const previousAccountId = params.previousAccountId?.trim();
|
|
1270
|
+
const handoffAccountId = params.authHandoff?.chatgptAccountId.trim();
|
|
1271
|
+
if (previousAccountId && handoffAccountId && previousAccountId !== handoffAccountId) throw new Error("ChatGPT workspace changed before Codex token refresh. Retry to start a client for the selected workspace.");
|
|
1181
1272
|
if (previousAccountId) {
|
|
1182
1273
|
const store = resolveCodexAppServerAuthProfileStore(params);
|
|
1183
1274
|
const profileId = resolveCodexAppServerAuthProfileId({
|
|
@@ -1195,6 +1286,7 @@ async function refreshCodexAppServerAuthTokens(params) {
|
|
|
1195
1286
|
});
|
|
1196
1287
|
if (!loginParams || loginParams.type !== "chatgptAuthTokens") throw new Error("Codex app-server ChatGPT token refresh requires an OAuth auth profile. Sign in with `openclaw models auth login --provider openai`, select that profile, then retry.");
|
|
1197
1288
|
if (previousAccountId && loginParams.chatgptAccountId !== previousAccountId) throw new Error("ChatGPT workspace changed during Codex token refresh. Retry to start a client for the selected workspace.");
|
|
1289
|
+
if (params.authHandoff && loginParams.chatgptAccountId !== params.authHandoff.chatgptAccountId) throw new Error("ChatGPT workspace changed during Codex token refresh. Retry to start a client for the selected workspace.");
|
|
1198
1290
|
return {
|
|
1199
1291
|
accessToken: loginParams.accessToken,
|
|
1200
1292
|
chatgptAccountId: loginParams.chatgptAccountId,
|
|
@@ -1222,6 +1314,8 @@ async function resolveCodexAppServerAuthProfileLoginParamsInternal(params) {
|
|
|
1222
1314
|
store,
|
|
1223
1315
|
preferStoreCredential: Boolean(params.authProfileStore?.profiles[profileId]),
|
|
1224
1316
|
forceOAuthRefresh: params.forceOAuthRefresh === true,
|
|
1317
|
+
authHandoff: params.authHandoff,
|
|
1318
|
+
previousAccountId: params.previousAccountId,
|
|
1225
1319
|
config: params.config
|
|
1226
1320
|
});
|
|
1227
1321
|
if (!loginParams) throw new CodexAppServerAuthProfileUnavailableError(`Codex app-server auth profile "${profileId}" does not contain usable credentials. Repair or replace the selected OpenAI credential, then retry.`);
|
|
@@ -1268,6 +1362,8 @@ async function resolveLoginParamsForCredential(profileId, credential, params) {
|
|
|
1268
1362
|
store: params.store,
|
|
1269
1363
|
preferStoreCredential: params.preferStoreCredential,
|
|
1270
1364
|
forceRefresh: params.forceOAuthRefresh,
|
|
1365
|
+
authHandoff: params.authHandoff,
|
|
1366
|
+
previousAccountId: params.previousAccountId,
|
|
1271
1367
|
config: params.config
|
|
1272
1368
|
});
|
|
1273
1369
|
const accessToken = resolvedCredential.access?.trim();
|
|
@@ -1286,9 +1382,9 @@ async function resolveOAuthCredentialForCodexAppServer(profileId, credential, pa
|
|
|
1286
1382
|
store: params.store,
|
|
1287
1383
|
profileId,
|
|
1288
1384
|
persistedCredential,
|
|
1289
|
-
suppliedCredential: credential
|
|
1290
|
-
config: params.config
|
|
1385
|
+
suppliedCredential: credential
|
|
1291
1386
|
});
|
|
1387
|
+
if (params.preferStoreCredential && params.store.runtimePersistedProfileIds?.includes(profileId) && (persistedCredential?.type !== "oauth" || !isCodexAppServerAuthProvider(persistedCredential.provider))) throw new CodexAppServerAuthProfileUnavailableError(`Codex app-server auth profile "${profileId}" is no longer available. Sign in again with OpenClaw, then retry.`);
|
|
1292
1388
|
const store = useScopedCredential ? params.store : resolveCodexAppServerAuthProfileStore({
|
|
1293
1389
|
agentDir: ownerAgentDir,
|
|
1294
1390
|
authProfileId: profileId,
|
|
@@ -1297,15 +1393,28 @@ async function resolveOAuthCredentialForCodexAppServer(profileId, credential, pa
|
|
|
1297
1393
|
const persistedOAuthCredential = !useScopedCredential && persistedCredential?.type === "oauth" && isCodexAppServerAuthProvider(persistedCredential.provider) ? persistedCredential : void 0;
|
|
1298
1394
|
const ownerCredential = store.profiles[profileId];
|
|
1299
1395
|
const overlaidOAuthCredential = ownerCredential?.type === "oauth" && isCodexAppServerAuthProvider(ownerCredential.provider) ? ownerCredential : void 0;
|
|
1396
|
+
const currentCredential = useScopedCredential || !persistedOAuthCredential ? overlaidOAuthCredential : persistedOAuthCredential;
|
|
1397
|
+
const reuseCompletedRotation = params.forceRefresh && (Boolean(persistedOAuthCredential) || params.preferStoreCredential) && shouldReuseCompletedCodexOAuthRotation({
|
|
1398
|
+
credential: currentCredential,
|
|
1399
|
+
authHandoff: params.authHandoff,
|
|
1400
|
+
previousAccountId: params.previousAccountId
|
|
1401
|
+
});
|
|
1402
|
+
const selectedAccountId = currentCredential ? resolveOpenAICodexAuthIdentity(currentCredential).accountId?.trim() : void 0;
|
|
1403
|
+
const callbackAccountId = params.authHandoff?.chatgptAccountId.trim() ?? params.previousAccountId?.trim() ?? void 0;
|
|
1404
|
+
if (callbackAccountId && selectedAccountId && callbackAccountId !== selectedAccountId) throw new Error("ChatGPT workspace changed before Codex token refresh. Retry to start a client for the selected workspace.");
|
|
1405
|
+
const expectedAccountId = callbackAccountId ?? selectedAccountId;
|
|
1300
1406
|
if (useScopedCredential && overlaidOAuthCredential) return await resolveScopedOAuthCredential({
|
|
1301
1407
|
store,
|
|
1302
1408
|
profileId,
|
|
1303
1409
|
credential: overlaidOAuthCredential,
|
|
1304
|
-
forceRefresh: params.forceRefresh
|
|
1410
|
+
forceRefresh: params.forceRefresh && !reuseCompletedRotation,
|
|
1411
|
+
expectedAccountId
|
|
1305
1412
|
});
|
|
1306
1413
|
if (params.forceRefresh && !persistedOAuthCredential && overlaidOAuthCredential) {
|
|
1414
|
+
if (reuseCompletedRotation) return overlaidOAuthCredential;
|
|
1307
1415
|
const refreshedRuntimeCredential = await refreshOAuthCredentialForRuntime({ credential: overlaidOAuthCredential });
|
|
1308
1416
|
if (!refreshedRuntimeCredential?.access?.trim()) throw new Error(`Codex app-server auth profile "${profileId}" could not refresh. Sign in again with OpenClaw, then retry.`);
|
|
1417
|
+
assertCodexOAuthRefreshWorkspace(profileId, refreshedRuntimeCredential, expectedAccountId);
|
|
1309
1418
|
store.profiles[profileId] = refreshedRuntimeCredential;
|
|
1310
1419
|
return refreshedRuntimeCredential;
|
|
1311
1420
|
}
|
|
@@ -1313,23 +1422,30 @@ async function resolveOAuthCredentialForCodexAppServer(profileId, credential, pa
|
|
|
1313
1422
|
store,
|
|
1314
1423
|
profileId,
|
|
1315
1424
|
agentDir: ownerAgentDir,
|
|
1316
|
-
forceRefresh: params.forceRefresh && Boolean(persistedOAuthCredential)
|
|
1425
|
+
forceRefresh: params.forceRefresh && Boolean(persistedOAuthCredential) && !reuseCompletedRotation,
|
|
1426
|
+
allowProfileFallback: false,
|
|
1427
|
+
...expectedAccountId ? { validateOAuthCredential: (candidate) => assertCodexOAuthRefreshWorkspace(profileId, candidate, expectedAccountId) } : {}
|
|
1317
1428
|
});
|
|
1318
|
-
|
|
1319
|
-
const
|
|
1320
|
-
|
|
1321
|
-
const storedCredential = store.profiles[profileId];
|
|
1322
|
-
const candidate = refreshedOAuthCredential ? refreshedOAuthCredential : storedCredential?.type === "oauth" && isCodexAppServerAuthProvider(storedCredential.provider) ? storedCredential : credential;
|
|
1323
|
-
return resolved?.apiKey ? {
|
|
1324
|
-
...candidate,
|
|
1429
|
+
if (!resolved || resolved.credential?.type !== "oauth" || !isCodexAppServerAuthProvider(resolved.credential.provider) || !resolved.apiKey.trim()) throw new CodexAppServerAuthProfileUnavailableError(`Codex app-server auth profile "${profileId}" is no longer available. Sign in again with OpenClaw, then retry.`);
|
|
1430
|
+
const candidate = {
|
|
1431
|
+
...resolved.credential,
|
|
1325
1432
|
access: resolved.apiKey
|
|
1326
|
-
}
|
|
1433
|
+
};
|
|
1434
|
+
if (isDeepStrictEqual(params.store.profiles[profileId], credential)) params.store.profiles[profileId] = candidate;
|
|
1435
|
+
return candidate;
|
|
1436
|
+
}
|
|
1437
|
+
function shouldReuseCompletedCodexOAuthRotation(params) {
|
|
1438
|
+
const handoff = params.authHandoff;
|
|
1439
|
+
const credential = params.credential;
|
|
1440
|
+
if (!handoff || !credential || !hasUsableOAuthCredential(credential) || fingerprintTokenAuthProfileCacheKey(credential.access.trim()) === handoff.accessFingerprint) return false;
|
|
1441
|
+
const accountId = resolveOpenAICodexAuthIdentity(credential).accountId?.trim();
|
|
1442
|
+
const previousAccountId = params.previousAccountId?.trim();
|
|
1443
|
+
return accountId === handoff.chatgptAccountId && (!previousAccountId || previousAccountId === handoff.chatgptAccountId);
|
|
1327
1444
|
}
|
|
1328
1445
|
function shouldUseScopedOAuthCredential(params) {
|
|
1329
1446
|
if (!params.store.runtimePersistedProfileIds?.includes(params.profileId)) return true;
|
|
1330
1447
|
const persisted = params.persistedCredential;
|
|
1331
|
-
if (persisted?.type !== "oauth") return
|
|
1332
|
-
if (resolveProviderIdForAuth(persisted.provider, { config: params.config }) !== resolveProviderIdForAuth(params.suppliedCredential.provider, { config: params.config })) return true;
|
|
1448
|
+
if (persisted?.type !== "oauth" || !isCodexAppServerAuthProvider(persisted.provider)) return false;
|
|
1333
1449
|
return !isDeepStrictEqual(persisted, params.suppliedCredential) && !hasMatchingOAuthIdentity(persisted, params.suppliedCredential);
|
|
1334
1450
|
}
|
|
1335
1451
|
function hasMatchingOAuthIdentity(persisted, supplied) {
|
|
@@ -1342,7 +1458,11 @@ function hasMatchingOAuthIdentity(persisted, supplied) {
|
|
|
1342
1458
|
}
|
|
1343
1459
|
async function resolveScopedOAuthCredential(params) {
|
|
1344
1460
|
const existingRefresh = scopedOAuthRefreshQueues.get(params.store)?.get(params.profileId);
|
|
1345
|
-
if (existingRefresh)
|
|
1461
|
+
if (existingRefresh) {
|
|
1462
|
+
const refreshed = await existingRefresh;
|
|
1463
|
+
assertCodexOAuthRefreshWorkspace(params.profileId, refreshed, params.expectedAccountId);
|
|
1464
|
+
return refreshed;
|
|
1465
|
+
}
|
|
1346
1466
|
if (!params.forceRefresh && hasUsableOAuthCredential(params.credential)) return params.credential;
|
|
1347
1467
|
const storeRefreshes = scopedOAuthRefreshQueues.get(params.store) ?? /* @__PURE__ */ new Map();
|
|
1348
1468
|
scopedOAuthRefreshQueues.set(params.store, storeRefreshes);
|
|
@@ -1352,6 +1472,7 @@ async function resolveScopedOAuthCredential(params) {
|
|
|
1352
1472
|
if (!params.forceRefresh && hasUsableOAuthCredential(credential)) return credential;
|
|
1353
1473
|
const refreshed = await refreshOAuthCredentialForRuntime({ credential });
|
|
1354
1474
|
if (!refreshed?.access?.trim()) throw new Error(`Codex app-server auth profile "${params.profileId}" could not refresh. Sign in again with OpenClaw, then retry.`);
|
|
1475
|
+
assertCodexOAuthRefreshWorkspace(params.profileId, refreshed, params.expectedAccountId);
|
|
1355
1476
|
if (!isDeepStrictEqual(params.store.profiles[params.profileId], credential)) throw new Error(`Codex app-server auth profile "${params.profileId}" changed while refreshing. Retry with the newly selected OpenAI profile.`);
|
|
1356
1477
|
params.store.profiles[params.profileId] = refreshed;
|
|
1357
1478
|
return refreshed;
|
|
@@ -1363,6 +1484,11 @@ async function resolveScopedOAuthCredential(params) {
|
|
|
1363
1484
|
if (storeRefreshes.get(params.profileId) === refresh) storeRefreshes.delete(params.profileId);
|
|
1364
1485
|
}
|
|
1365
1486
|
}
|
|
1487
|
+
function assertCodexOAuthRefreshWorkspace(profileId, credential, expectedAccountId) {
|
|
1488
|
+
if (!expectedAccountId) return;
|
|
1489
|
+
const loginParams = buildChatgptAuthTokensParams(profileId, credential, credential.access.trim());
|
|
1490
|
+
if (loginParams.type !== "chatgptAuthTokens" || loginParams.chatgptAccountId !== expectedAccountId) throw new Error("ChatGPT workspace changed during Codex token refresh. Retry to start a client for the selected workspace.");
|
|
1491
|
+
}
|
|
1366
1492
|
function isCodexAppServerAuthProvider(provider) {
|
|
1367
1493
|
return provider.trim().toLowerCase() === CODEX_APP_SERVER_AUTH_PROVIDER;
|
|
1368
1494
|
}
|
|
@@ -1417,6 +1543,65 @@ function resolveExplicitChatgptAccountId(credential) {
|
|
|
1417
1543
|
}
|
|
1418
1544
|
}
|
|
1419
1545
|
//#endregion
|
|
1546
|
+
//#region extensions/codex/src/app-server/client-thread-owner.ts
|
|
1547
|
+
function createThreadOwnerToken(threadId, onInvalidated) {
|
|
1548
|
+
const owner = {
|
|
1549
|
+
invalidated: false,
|
|
1550
|
+
invalidate: () => {
|
|
1551
|
+
if (owner.invalidated) return;
|
|
1552
|
+
owner.invalidated = true;
|
|
1553
|
+
try {
|
|
1554
|
+
onInvalidated?.();
|
|
1555
|
+
} catch (error) {
|
|
1556
|
+
embeddedAgentLog$1.warn("codex thread ownership invalidation failed", {
|
|
1557
|
+
threadId,
|
|
1558
|
+
reason: formatErrorMessage(error)
|
|
1559
|
+
});
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
};
|
|
1563
|
+
return owner;
|
|
1564
|
+
}
|
|
1565
|
+
function hasThreadOwnership(runtime, threadId) {
|
|
1566
|
+
return runtime !== void 0 && !runtime.closed && (runtime.retainedThreads.get(threadId) !== void 0 || runtime.releasingThreads.get(threadId) !== void 0 || runtime.claimedThreads.get(threadId) !== void 0);
|
|
1567
|
+
}
|
|
1568
|
+
function hasSiblingThreadWork(runtime, threadId) {
|
|
1569
|
+
if (!runtime || runtime.closed) return false;
|
|
1570
|
+
if (runtime.protectedThreads.size > 0) return true;
|
|
1571
|
+
for (const [retainedThreadId, retained] of runtime.retainedThreads) if (retainedThreadId !== threadId && retained.ephemeralPolicy !== void 0) return true;
|
|
1572
|
+
for (const claimedThreadId of runtime.claimedThreads.keys()) if (claimedThreadId !== threadId) return true;
|
|
1573
|
+
return false;
|
|
1574
|
+
}
|
|
1575
|
+
function invalidateThreadOwnership(runtime, threadId) {
|
|
1576
|
+
const retainedOwner = runtime.retainedThreads.get(threadId)?.ownerToken;
|
|
1577
|
+
const claimedOwner = runtime.claimedThreads.get(threadId);
|
|
1578
|
+
const releasing = runtime.releasingThreads.get(threadId);
|
|
1579
|
+
if (releasing) releasing.invalidated = true;
|
|
1580
|
+
runtime.retainedThreads.delete(threadId);
|
|
1581
|
+
runtime.claimedThreads.delete(threadId);
|
|
1582
|
+
retainedOwner?.invalidate();
|
|
1583
|
+
claimedOwner?.invalidate();
|
|
1584
|
+
releasing?.retainedOwnerToken?.invalidate();
|
|
1585
|
+
}
|
|
1586
|
+
function forgetThreadOwnership(runtime, threadId, owner) {
|
|
1587
|
+
let forgotten = false;
|
|
1588
|
+
if (runtime.claimedThreads.get(threadId) === owner) {
|
|
1589
|
+
runtime.claimedThreads.delete(threadId);
|
|
1590
|
+
forgotten = true;
|
|
1591
|
+
}
|
|
1592
|
+
if (runtime.retainedThreads.get(threadId)?.ownerToken === owner) {
|
|
1593
|
+
runtime.retainedThreads.delete(threadId);
|
|
1594
|
+
forgotten = true;
|
|
1595
|
+
}
|
|
1596
|
+
const releasing = runtime.releasingThreads.get(threadId);
|
|
1597
|
+
if (releasing?.retainedOwnerToken === owner) {
|
|
1598
|
+
releasing.invalidated = true;
|
|
1599
|
+
forgotten = true;
|
|
1600
|
+
}
|
|
1601
|
+
if (forgotten) owner.invalidate();
|
|
1602
|
+
return forgotten;
|
|
1603
|
+
}
|
|
1604
|
+
//#endregion
|
|
1420
1605
|
//#region extensions/codex/src/app-server/rate-limit-cache.ts
|
|
1421
1606
|
const DEFAULT_CODEX_RATE_LIMIT_CACHE_MAX_AGE_MS = 6e5;
|
|
1422
1607
|
const SPARSE_ACCOUNT_METADATA_KEYS = [
|
|
@@ -1531,6 +1716,10 @@ function isCodexAppServerClientRuntimeLive(client) {
|
|
|
1531
1716
|
const runtime = configuredClients.get(client);
|
|
1532
1717
|
return runtime !== void 0 && !runtime.closed;
|
|
1533
1718
|
}
|
|
1719
|
+
function recordCodexAppServerAuthHandoff(client, handoff) {
|
|
1720
|
+
const runtime = configuredClients.get(client);
|
|
1721
|
+
if (runtime && !runtime.closed && handoff) runtime.authHandoff = handoff;
|
|
1722
|
+
}
|
|
1534
1723
|
/** Reference history is only trusted while this native subscription stays warm. */
|
|
1535
1724
|
function forgetCodexWorkspaceReferences(client, threadId) {
|
|
1536
1725
|
configuredClients.get(client)?.workspaceReferences.delete(threadId);
|
|
@@ -1606,8 +1795,11 @@ function ensureCodexAppServerClientRuntime(client, context) {
|
|
|
1606
1795
|
clearTimeout(runtime.evictionTimer);
|
|
1607
1796
|
runtime.evictionTimer = void 0;
|
|
1608
1797
|
}
|
|
1609
|
-
|
|
1610
|
-
|
|
1798
|
+
for (const threadId of /* @__PURE__ */ new Set([
|
|
1799
|
+
...runtime.retainedThreads.keys(),
|
|
1800
|
+
...runtime.claimedThreads.keys(),
|
|
1801
|
+
...runtime.releasingThreads.keys()
|
|
1802
|
+
])) invalidateThreadOwnership(runtime, threadId);
|
|
1611
1803
|
runtime.protectedThreads.clear();
|
|
1612
1804
|
runtime.sessionMetadata.clear();
|
|
1613
1805
|
runtime.workspaceReferences.clear();
|
|
@@ -1615,16 +1807,24 @@ function ensureCodexAppServerClientRuntime(client, context) {
|
|
|
1615
1807
|
client.addRequestHandler(async (request) => {
|
|
1616
1808
|
if (request.method !== "account/chatgptAuthTokens/refresh") return;
|
|
1617
1809
|
if (runtime.context.authMode === "prepared-api-key") throw new Error("ChatGPT token refresh is unavailable for prepared Codex API-key auth.");
|
|
1810
|
+
if (!runtime.context.agentDir) throw new Error("ChatGPT token refresh requires an OpenClaw-owned auth profile.");
|
|
1618
1811
|
const previousAccountId = isJsonObject(request.params) && typeof request.params.previousAccountId === "string" ? request.params.previousAccountId.trim() || void 0 : void 0;
|
|
1812
|
+
const authHandoff = runtime.authHandoff;
|
|
1619
1813
|
try {
|
|
1620
1814
|
const tokens = await withTimeout(refreshCodexAppServerAuthTokens({
|
|
1621
1815
|
agentDir: runtime.context.agentDir,
|
|
1622
1816
|
authProfileId: runtime.context.authProfileId,
|
|
1817
|
+
...authHandoff ? { authHandoff } : {},
|
|
1623
1818
|
...previousAccountId ? { previousAccountId } : {},
|
|
1624
1819
|
...runtime.context.authProfileStore ? { authProfileStore: runtime.context.authProfileStore } : {},
|
|
1625
1820
|
config: runtime.context.config
|
|
1626
1821
|
}), CODEX_EXTERNAL_AUTH_REFRESH_TIMEOUT_MS, "Codex app-server ChatGPT token refresh timed out before its external-auth deadline. Retry the request; if it persists, sign in again with OpenClaw.");
|
|
1627
1822
|
if (previousAccountId && tokens.chatgptAccountId !== previousAccountId) throw new Error("ChatGPT workspace changed during Codex token refresh. Retry to start a client for the selected workspace.");
|
|
1823
|
+
if (runtime.closed) throw new Error("Codex app-server client closed during ChatGPT token refresh.");
|
|
1824
|
+
runtime.authHandoff = {
|
|
1825
|
+
accessFingerprint: fingerprintTokenAuthProfileCacheKey(tokens.accessToken),
|
|
1826
|
+
chatgptAccountId: tokens.chatgptAccountId
|
|
1827
|
+
};
|
|
1628
1828
|
return { ...tokens };
|
|
1629
1829
|
} catch (error) {
|
|
1630
1830
|
runtime.context.onAuthRefreshFailure?.();
|
|
@@ -1647,10 +1847,7 @@ function ensureCodexAppServerClientRuntime(client, context) {
|
|
|
1647
1847
|
if (notification.method === "thread/archived" || notification.method === "thread/deleted" || notification.method === "thread/closed") {
|
|
1648
1848
|
const threadId = notification.params?.threadId;
|
|
1649
1849
|
if (typeof threadId === "string") {
|
|
1650
|
-
|
|
1651
|
-
if (releasing) releasing.invalidated = true;
|
|
1652
|
-
runtime.retainedThreads.delete(threadId);
|
|
1653
|
-
runtime.claimedThreads.delete(threadId);
|
|
1850
|
+
invalidateThreadOwnership(runtime, threadId);
|
|
1654
1851
|
runtime.sessionMetadata.delete(threadId);
|
|
1655
1852
|
runtime.workspaceReferences.delete(threadId);
|
|
1656
1853
|
scheduleRetainedThreadEviction(client, runtime);
|
|
@@ -1691,14 +1888,18 @@ async function releaseRetainedThread(client, runtime, threadId, assertCurrent) {
|
|
|
1691
1888
|
}
|
|
1692
1889
|
runtime.retainedThreads.delete(threadId);
|
|
1693
1890
|
scheduleRetainedThreadEviction(client, runtime);
|
|
1694
|
-
const transition = {
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1891
|
+
const transition = {
|
|
1892
|
+
retainedOwnerToken: retained.ownerToken,
|
|
1893
|
+
completion: Promise.resolve().then(() => {
|
|
1894
|
+
assertCurrent?.();
|
|
1895
|
+
return assertCurrent ? retained.release(threadId, assertCurrent) : retained.release(threadId);
|
|
1896
|
+
})
|
|
1897
|
+
};
|
|
1698
1898
|
runtime.releasingThreads.set(threadId, transition);
|
|
1699
1899
|
try {
|
|
1700
1900
|
await transition.completion;
|
|
1701
1901
|
runtime.workspaceReferences.delete(threadId);
|
|
1902
|
+
retained.ownerToken?.invalidate();
|
|
1702
1903
|
return true;
|
|
1703
1904
|
} catch (error) {
|
|
1704
1905
|
if (!runtime.closed && !transition.invalidated && runtime.releasingThreads.get(threadId) === transition && !runtime.retainedThreads.has(threadId) && !runtime.claimedThreads.has(threadId)) {
|
|
@@ -1732,14 +1933,17 @@ async function retainCodexAppServerLiveThread(client, threadId, releaseThread, c
|
|
|
1732
1933
|
const runtime = configuredClients.get(client);
|
|
1733
1934
|
if (!runtime || runtime.closed) return false;
|
|
1734
1935
|
const claimed = runtime.claimedThreads.get(threadId);
|
|
1735
|
-
|
|
1936
|
+
const ownerToken = releaseThread ? claimedThreadReleaseTokens.get(releaseThread) : void 0;
|
|
1937
|
+
if (claimed !== ownerToken || ownerToken?.invalidated) return false;
|
|
1736
1938
|
const pendingRelease = runtime.releasingThreads.get(threadId);
|
|
1737
1939
|
if (pendingRelease) {
|
|
1738
1940
|
await pendingRelease.completion;
|
|
1739
1941
|
return false;
|
|
1740
1942
|
}
|
|
1943
|
+
const previousOwner = runtime.retainedThreads.get(threadId)?.ownerToken;
|
|
1741
1944
|
runtime.retainedThreads.delete(threadId);
|
|
1742
1945
|
const retained = {
|
|
1946
|
+
ownerToken,
|
|
1743
1947
|
configFingerprint,
|
|
1744
1948
|
ephemeralPolicy,
|
|
1745
1949
|
serviceTier,
|
|
@@ -1749,6 +1953,7 @@ async function retainCodexAppServerLiveThread(client, threadId, releaseThread, c
|
|
|
1749
1953
|
})
|
|
1750
1954
|
};
|
|
1751
1955
|
runtime.retainedThreads.set(threadId, retained);
|
|
1956
|
+
if (previousOwner !== ownerToken) previousOwner?.invalidate();
|
|
1752
1957
|
try {
|
|
1753
1958
|
await evictExcessIdleThreads(client, runtime);
|
|
1754
1959
|
} catch (error) {
|
|
@@ -1778,8 +1983,8 @@ async function consumeCodexAppServerLiveThread(client, threadId, configFingerpri
|
|
|
1778
1983
|
if (!retained || configFingerprint !== void 0 && retained.configFingerprint !== configFingerprint) return;
|
|
1779
1984
|
return claimCodexAppServerThreadOwnership(client, runtime, threadId, retained);
|
|
1780
1985
|
}
|
|
1781
|
-
/** Claims an
|
|
1782
|
-
async function claimCodexAppServerLiveThread(client, threadId) {
|
|
1986
|
+
/** Claims an auto-subscription; invalidation ends the handle after replacement or release. */
|
|
1987
|
+
async function claimCodexAppServerLiveThread(client, threadId, onInvalidated) {
|
|
1783
1988
|
const runtime = configuredClients.get(client);
|
|
1784
1989
|
if (!runtime || runtime.closed || runtime.claimedThreads.has(threadId)) return;
|
|
1785
1990
|
const pendingRelease = runtime.releasingThreads.get(threadId);
|
|
@@ -1792,21 +1997,33 @@ async function claimCodexAppServerLiveThread(client, threadId) {
|
|
|
1792
1997
|
release: async (releasedThreadId, assertCurrent) => {
|
|
1793
1998
|
await unsubscribeCodexAppServerLiveThread(client, releasedThreadId, 5e3, assertCurrent);
|
|
1794
1999
|
}
|
|
1795
|
-
});
|
|
2000
|
+
}, onInvalidated);
|
|
1796
2001
|
}
|
|
1797
|
-
function claimCodexAppServerThreadOwnership(client, runtime, threadId, retained) {
|
|
2002
|
+
function claimCodexAppServerThreadOwnership(client, runtime, threadId, retained, onInvalidated) {
|
|
2003
|
+
const previousClaim = runtime.claimedThreads.get(threadId);
|
|
1798
2004
|
runtime.retainedThreads.delete(threadId);
|
|
1799
|
-
const claimed =
|
|
2005
|
+
const claimed = createThreadOwnerToken(threadId, onInvalidated);
|
|
1800
2006
|
runtime.claimedThreads.set(threadId, claimed);
|
|
2007
|
+
previousClaim?.invalidate();
|
|
2008
|
+
retained.ownerToken?.invalidate();
|
|
1801
2009
|
scheduleRetainedThreadEviction(client, runtime);
|
|
1802
2010
|
const assertCurrent = () => {
|
|
1803
|
-
if (runtime.closed || runtime.claimedThreads.get(threadId) !== claimed) throw new Error(`Codex thread subscription ownership changed: ${threadId}`);
|
|
2011
|
+
if (claimed.invalidated || runtime.closed || runtime.claimedThreads.get(threadId) !== claimed) throw new Error(`Codex thread subscription ownership changed: ${threadId}`);
|
|
1804
2012
|
};
|
|
1805
2013
|
const release = async (releasedThreadId, assertReleaseCurrent) => {
|
|
1806
|
-
if (releasedThreadId !== threadId ||
|
|
2014
|
+
if (releasedThreadId !== threadId || claimed.invalidated) {
|
|
1807
2015
|
assertReleaseCurrent?.();
|
|
1808
2016
|
return;
|
|
1809
2017
|
}
|
|
2018
|
+
if (runtime.claimedThreads.get(threadId) !== claimed) {
|
|
2019
|
+
if (runtime.retainedThreads.get(threadId)?.ownerToken === claimed) await releaseRetainedThread(client, runtime, threadId, assertReleaseCurrent);
|
|
2020
|
+
else {
|
|
2021
|
+
const pendingRelease = runtime.releasingThreads.get(threadId);
|
|
2022
|
+
if (pendingRelease?.retainedOwnerToken === claimed) await pendingRelease.completion;
|
|
2023
|
+
assertReleaseCurrent?.();
|
|
2024
|
+
}
|
|
2025
|
+
return;
|
|
2026
|
+
}
|
|
1810
2027
|
const pendingRelease = runtime.releasingThreads.get(threadId);
|
|
1811
2028
|
if (pendingRelease) {
|
|
1812
2029
|
await pendingRelease.completion;
|
|
@@ -1826,6 +2043,7 @@ function claimCodexAppServerThreadOwnership(client, runtime, threadId, retained)
|
|
|
1826
2043
|
if (runtime.claimedThreads.get(threadId) === claimed) {
|
|
1827
2044
|
runtime.claimedThreads.delete(threadId);
|
|
1828
2045
|
runtime.workspaceReferences.delete(threadId);
|
|
2046
|
+
claimed.invalidate();
|
|
1829
2047
|
}
|
|
1830
2048
|
} finally {
|
|
1831
2049
|
if (runtime.releasingThreads.get(threadId) === transition) runtime.releasingThreads.delete(threadId);
|
|
@@ -1838,18 +2056,26 @@ function claimCodexAppServerThreadOwnership(client, runtime, threadId, retained)
|
|
|
1838
2056
|
configFingerprint: retained.configFingerprint,
|
|
1839
2057
|
ephemeralPolicy: retained.ephemeralPolicy,
|
|
1840
2058
|
serviceTier: retained.serviceTier,
|
|
1841
|
-
release
|
|
2059
|
+
release,
|
|
2060
|
+
forget: () => {
|
|
2061
|
+
if (forgetThreadOwnership(runtime, threadId, claimed)) {
|
|
2062
|
+
runtime.workspaceReferences.delete(threadId);
|
|
2063
|
+
scheduleRetainedThreadEviction(client, runtime);
|
|
2064
|
+
}
|
|
2065
|
+
}
|
|
1842
2066
|
};
|
|
1843
2067
|
}
|
|
1844
2068
|
/** Distinguish active claimed ownership from an already-evicted idle subscription. */
|
|
1845
2069
|
function hasCodexAppServerLiveThread(client, threadId) {
|
|
1846
|
-
|
|
1847
|
-
return runtime !== void 0 && !runtime.closed && (runtime.retainedThreads.has(threadId) || runtime.releasingThreads.has(threadId) || runtime.claimedThreads.has(threadId));
|
|
2070
|
+
return hasThreadOwnership(configuredClients.get(client), threadId);
|
|
1848
2071
|
}
|
|
1849
2072
|
function isCodexAppServerLiveThreadClaimed(client, threadId) {
|
|
1850
2073
|
const runtime = configuredClients.get(client);
|
|
1851
2074
|
return runtime !== void 0 && !runtime.closed && runtime.claimedThreads.has(threadId);
|
|
1852
2075
|
}
|
|
2076
|
+
function hasCodexAppServerSiblingThreadWork(client, threadId) {
|
|
2077
|
+
return hasSiblingThreadWork(configuredClients.get(client), threadId);
|
|
2078
|
+
}
|
|
1853
2079
|
/** Release the exact physical subscription and finish only its observed ownership generation. */
|
|
1854
2080
|
async function unsubscribeCodexAppServerLiveThread(client, threadId, timeoutMs, assertCurrent) {
|
|
1855
2081
|
const runtime = configuredClients.get(client);
|
|
@@ -1887,9 +2113,13 @@ async function unsubscribeCodexAppServerLiveThread(client, threadId, timeoutMs,
|
|
|
1887
2113
|
await physicalRelease;
|
|
1888
2114
|
if (retained !== void 0 && runtime?.retainedThreads.get(threadId) === retained) {
|
|
1889
2115
|
runtime.retainedThreads.delete(threadId);
|
|
2116
|
+
retained.ownerToken?.invalidate();
|
|
1890
2117
|
scheduleRetainedThreadEviction(client, runtime);
|
|
1891
2118
|
}
|
|
1892
|
-
if (claimed !== void 0 && runtime?.claimedThreads.get(threadId) === claimed)
|
|
2119
|
+
if (claimed !== void 0 && runtime?.claimedThreads.get(threadId) === claimed) {
|
|
2120
|
+
runtime.claimedThreads.delete(threadId);
|
|
2121
|
+
claimed.invalidate();
|
|
2122
|
+
}
|
|
1893
2123
|
} finally {
|
|
1894
2124
|
if (ownsTransition && runtime.releasingThreads.get(threadId) === transition) runtime.releasingThreads.delete(threadId);
|
|
1895
2125
|
}
|
|
@@ -1930,79 +2160,144 @@ function protectCodexAppServerLiveThread(client, threadId) {
|
|
|
1930
2160
|
};
|
|
1931
2161
|
}
|
|
1932
2162
|
//#endregion
|
|
1933
|
-
//#region extensions/codex/src/app-server/
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
*/
|
|
1938
|
-
/**
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
const
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
}
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
2163
|
+
//#region extensions/codex/src/app-server/inference-routing.ts
|
|
2164
|
+
const owners = defineCodexBuildState("openclaw.codexAppServerInferenceOwners", () => /* @__PURE__ */ new WeakMap())();
|
|
2165
|
+
const MAX_ROUTES = 8;
|
|
2166
|
+
const MAX_THREADS = 256;
|
|
2167
|
+
const NATIVE_OPENAI_UPSTREAMS = /* @__PURE__ */ new Set(["https://api.openai.com/v1", "https://chatgpt.com/backend-api/codex"]);
|
|
2168
|
+
/** Only managed native stdio startup calls this; locality or metadata cannot opt a client in. */
|
|
2169
|
+
function ownCodexInferenceClient(client) {
|
|
2170
|
+
if (owners.has(client)) return;
|
|
2171
|
+
const owner = {
|
|
2172
|
+
closed: false,
|
|
2173
|
+
routes: /* @__PURE__ */ new Map(),
|
|
2174
|
+
threads: /* @__PURE__ */ new Map(),
|
|
2175
|
+
handles: /* @__PURE__ */ new Set()
|
|
2176
|
+
};
|
|
2177
|
+
owners.set(client, owner);
|
|
2178
|
+
const close = () => {
|
|
2179
|
+
owner.closed = true;
|
|
2180
|
+
owner.threads.clear();
|
|
2181
|
+
owner.handles.clear();
|
|
2182
|
+
for (const pending of owner.routes.values()) pending.then((route) => route.close(), () => {});
|
|
2183
|
+
owner.routes.clear();
|
|
2184
|
+
};
|
|
2185
|
+
client.addCloseHandler(close);
|
|
2186
|
+
client.addNotificationHandler((notification) => {
|
|
2187
|
+
if (notification.method === "thread/closed" && isJsonObject(notification.params) && typeof notification.params.threadId === "string") owner.threads.delete(notification.params.threadId);
|
|
2188
|
+
if (notification.method !== "account/updated" || !owner.authRoute) return;
|
|
2189
|
+
const mode = isJsonObject(notification.params) ? notification.params.authMode : void 0;
|
|
2190
|
+
if ((mode === "apiKey" ? "apiKey" : mode === "chatgpt" || mode === "chatgptAuthTokens" ? "chatgpt" : void 0) !== owner.authRoute) close();
|
|
2191
|
+
});
|
|
1956
2192
|
}
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
if (
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
params.signal.addEventListener("abort", abortListener, { once: true });
|
|
1982
|
-
abortCleanup = () => params.signal.removeEventListener("abort", abortListener);
|
|
1983
|
-
})]);
|
|
1984
|
-
} catch (error) {
|
|
1985
|
-
if (timeoutError) {
|
|
1986
|
-
await timeoutCleanup;
|
|
1987
|
-
throw timeoutError;
|
|
2193
|
+
async function prepareCodexInferenceRoute(params) {
|
|
2194
|
+
const owner = owners.get(params.client);
|
|
2195
|
+
if (!owner) return;
|
|
2196
|
+
const assertClient = () => {
|
|
2197
|
+
if (owner.closed || owners.get(params.client) !== owner) throw new Error("Codex inference route ownership changed; reconnect before retrying");
|
|
2198
|
+
};
|
|
2199
|
+
const assertCurrent = () => {
|
|
2200
|
+
assertClient();
|
|
2201
|
+
params.signal?.throwIfAborted();
|
|
2202
|
+
params.assertCurrent();
|
|
2203
|
+
};
|
|
2204
|
+
assertCurrent();
|
|
2205
|
+
const snapshot = params.effectiveConfig ?? await readCodexEffectiveConfig(params.client, params.cwd, { signal: params.signal });
|
|
2206
|
+
assertCurrent();
|
|
2207
|
+
if (snapshot.config.model_provider != null && snapshot.config.model_provider !== "openai") return;
|
|
2208
|
+
if (isJsonObject(snapshot.config.features) && snapshot.config.features.respect_system_proxy === true) return;
|
|
2209
|
+
const configured = snapshot.config.openai_base_url;
|
|
2210
|
+
if (configured != null && typeof configured !== "string") throw new Error("Codex inference upstream configuration is invalid");
|
|
2211
|
+
if (configured) {
|
|
2212
|
+
let target;
|
|
2213
|
+
try {
|
|
2214
|
+
target = new URL(configured);
|
|
2215
|
+
} catch {
|
|
2216
|
+
return;
|
|
1988
2217
|
}
|
|
1989
|
-
|
|
1990
|
-
} finally {
|
|
1991
|
-
if (timeout) clearTimeout(timeout);
|
|
1992
|
-
abortCleanup?.();
|
|
2218
|
+
if (!NATIVE_OPENAI_UPSTREAMS.has(target.href.replace(/\/$/, ""))) return;
|
|
1993
2219
|
}
|
|
2220
|
+
const origin = snapshot.origins?.openai_base_url;
|
|
2221
|
+
if (origin && !CODEX_SESSION_OVERRIDABLE_LAYER_TYPES.has(origin.name.type)) return;
|
|
2222
|
+
const account = await params.client.request("account/read", { refreshToken: false }, {
|
|
2223
|
+
signal: params.signal,
|
|
2224
|
+
assertCurrent
|
|
2225
|
+
});
|
|
2226
|
+
assertCurrent();
|
|
2227
|
+
const type = isJsonObject(account.account) ? account.account.type : void 0;
|
|
2228
|
+
if (type !== "apiKey" && type !== "chatgpt") return;
|
|
2229
|
+
if (owner.authRoute && owner.authRoute !== type) throw new Error("Codex native account route changed; reconnect before retrying");
|
|
2230
|
+
owner.authRoute = type;
|
|
2231
|
+
const target = new URL(configured || (type === "apiKey" ? "https://api.openai.com/v1" : "https://chatgpt.com/backend-api/codex"));
|
|
2232
|
+
const key = target.toString();
|
|
2233
|
+
let pending = owner.routes.get(key);
|
|
2234
|
+
if (!pending) {
|
|
2235
|
+
if (owner.routes.size >= MAX_ROUTES) throw new Error("Codex inference route limit reached");
|
|
2236
|
+
pending = import("./inference-proxy-CC15HuSi.mjs").then(({ createCodexInferenceProxy }) => {
|
|
2237
|
+
assertClient();
|
|
2238
|
+
return createCodexInferenceProxy({
|
|
2239
|
+
upstream: target,
|
|
2240
|
+
assertCurrent: assertClient
|
|
2241
|
+
});
|
|
2242
|
+
});
|
|
2243
|
+
owner.routes.set(key, pending);
|
|
2244
|
+
}
|
|
2245
|
+
const route = await pending;
|
|
2246
|
+
assertCurrent();
|
|
2247
|
+
route.assertCurrent();
|
|
2248
|
+
params.client.protectPrivateTransportSecret(new URL(route.baseUrl).pathname.split("/")[1] ?? "");
|
|
2249
|
+
owner.handles.add(route);
|
|
2250
|
+
return route;
|
|
2251
|
+
}
|
|
2252
|
+
/** Prepare a managed thread without changing an attached or unsupported native profile. */
|
|
2253
|
+
async function prepareCodexInferenceThreadConfig(params) {
|
|
2254
|
+
const { binding } = params;
|
|
2255
|
+
if (binding?.connectionScope === "supervision" || binding?.preserveNativeModel === true) return;
|
|
2256
|
+
const route = await prepareCodexInferenceRoute(params);
|
|
2257
|
+
if (!route) return;
|
|
2258
|
+
if (binding?.clientId === params.clientId && !getCodexInferenceThread(params.client, binding.threadId)) {
|
|
2259
|
+
const { thread } = await params.client.request("thread/read", {
|
|
2260
|
+
threadId: binding.threadId,
|
|
2261
|
+
includeTurns: false
|
|
2262
|
+
}, {
|
|
2263
|
+
signal: params.signal,
|
|
2264
|
+
assertCurrent: params.assertCurrent
|
|
2265
|
+
});
|
|
2266
|
+
params.assertCurrent();
|
|
2267
|
+
if (thread.id !== binding.threadId || thread.status?.type !== "notLoaded") throw new Error("Codex loaded thread has no owned inference route; reconnect before retrying");
|
|
2268
|
+
}
|
|
2269
|
+
if (params.config?.openai_base_url !== void 0 && params.config.openai_base_url !== route.upstream) throw new Error("Codex thread configuration conflicts with its trusted inference upstream");
|
|
2270
|
+
return {
|
|
2271
|
+
route,
|
|
2272
|
+
config: {
|
|
2273
|
+
...params.config,
|
|
2274
|
+
openai_base_url: route.baseUrl
|
|
2275
|
+
}
|
|
2276
|
+
};
|
|
1994
2277
|
}
|
|
1995
|
-
/**
|
|
1996
|
-
function
|
|
1997
|
-
|
|
1998
|
-
const
|
|
1999
|
-
|
|
2278
|
+
/** Validate the exact private handle and unchanged upstream, not a localhost string exception. */
|
|
2279
|
+
function assertCodexInferenceRouteConfig(client, route, config) {
|
|
2280
|
+
if (!route) return;
|
|
2281
|
+
const owner = owners.get(client);
|
|
2282
|
+
if (!owner || owner.closed || !owner.handles.has(route) || config?.openai_base_url !== route.baseUrl) throw new Error("Codex parent-local inference route was overridden; no turn was sent");
|
|
2283
|
+
route.assertCurrent();
|
|
2284
|
+
}
|
|
2285
|
+
function bindCodexInferenceThread(client, threadId, route) {
|
|
2286
|
+
const owner = owners.get(client);
|
|
2287
|
+
if (!owner && !route) return;
|
|
2288
|
+
if (!owner || owner.closed) throw new Error("Codex inference client is closed");
|
|
2289
|
+
if (!route) {
|
|
2290
|
+
owner.threads.delete(threadId);
|
|
2291
|
+
return;
|
|
2292
|
+
}
|
|
2293
|
+
route.assertCurrent();
|
|
2294
|
+
if (!owner.threads.has(threadId) && owner.threads.size >= MAX_THREADS) throw new Error("Codex inference thread limit reached; reconnect before retrying");
|
|
2295
|
+
owner.threads.set(threadId, route);
|
|
2000
2296
|
}
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
return addTimerTimeoutGraceMs(timeout, grace) ?? timeout;
|
|
2297
|
+
function getCodexInferenceThread(client, threadId) {
|
|
2298
|
+
const owner = owners.get(client);
|
|
2299
|
+
if (owner?.closed) throw new Error("Codex inference client is closed");
|
|
2300
|
+
return owner?.threads.get(threadId);
|
|
2006
2301
|
}
|
|
2007
2302
|
//#endregion
|
|
2008
2303
|
//#region extensions/codex/src/app-server/native-config-fence.ts
|
|
@@ -2067,6 +2362,50 @@ async function waitForPreviousFence(previous, options) {
|
|
|
2067
2362
|
});
|
|
2068
2363
|
}
|
|
2069
2364
|
//#endregion
|
|
2365
|
+
//#region extensions/codex/src/app-server/native-hook-relay-state.ts
|
|
2366
|
+
const pending = /* @__PURE__ */ new Set();
|
|
2367
|
+
const closing = /* @__PURE__ */ new Set();
|
|
2368
|
+
/** Owns delayed hook-relay cleanup across runtime scheduling and test teardown. */
|
|
2369
|
+
const nativeHookRelayUnregisterQueue = {
|
|
2370
|
+
add(entry) {
|
|
2371
|
+
pending.add(entry);
|
|
2372
|
+
},
|
|
2373
|
+
delete(entry) {
|
|
2374
|
+
return pending.delete(entry);
|
|
2375
|
+
},
|
|
2376
|
+
track(operation) {
|
|
2377
|
+
closing.add(operation);
|
|
2378
|
+
operation.then(() => closing.delete(operation), () => closing.delete(operation));
|
|
2379
|
+
},
|
|
2380
|
+
async flush() {
|
|
2381
|
+
while (pending.size > 0) {
|
|
2382
|
+
const entry = pending.values().next().value;
|
|
2383
|
+
if (!entry) break;
|
|
2384
|
+
clearTimeout(entry.timeout);
|
|
2385
|
+
entry.unregister();
|
|
2386
|
+
}
|
|
2387
|
+
while (closing.size > 0) await Promise.allSettled(closing);
|
|
2388
|
+
},
|
|
2389
|
+
async clear() {
|
|
2390
|
+
for (const entry of pending) clearTimeout(entry.timeout);
|
|
2391
|
+
pending.clear();
|
|
2392
|
+
while (closing.size > 0) await Promise.allSettled(closing);
|
|
2393
|
+
}
|
|
2394
|
+
};
|
|
2395
|
+
//#endregion
|
|
2396
|
+
//#region extensions/codex/src/app-server/spawn-identity.ts
|
|
2397
|
+
/** Resolves non-secret spawn identity before startup; argv is represented only by its hash. */
|
|
2398
|
+
function resolveCodexAppServerSpawnIdentity(startOptions, resolvedNativeCommand) {
|
|
2399
|
+
const nativeCommand = resolvedNativeCommand ?? (startOptions.commandSource === "resolved-managed" ? resolveManagedCodexNativeCommand(startOptions.command) : void 0);
|
|
2400
|
+
return {
|
|
2401
|
+
command: startOptions.command,
|
|
2402
|
+
argsFingerprint: createHash("sha256").update(JSON.stringify(startOptions.args)).digest("hex"),
|
|
2403
|
+
...startOptions.commandSource ? { commandSource: startOptions.commandSource } : {},
|
|
2404
|
+
...startOptions.managedCommandOrder ? { managedCommandOrder: startOptions.managedCommandOrder } : {},
|
|
2405
|
+
...nativeCommand ? { nativeCommand } : {}
|
|
2406
|
+
};
|
|
2407
|
+
}
|
|
2408
|
+
//#endregion
|
|
2070
2409
|
//#region extensions/codex/src/app-server/thread-lifecycle-errors.ts
|
|
2071
2410
|
var CodexThreadStartRequestError = class extends Error {
|
|
2072
2411
|
constructor(cause) {
|
|
@@ -2074,6 +2413,12 @@ var CodexThreadStartRequestError = class extends Error {
|
|
|
2074
2413
|
this.name = "CodexThreadStartRequestError";
|
|
2075
2414
|
}
|
|
2076
2415
|
};
|
|
2416
|
+
var CodexThreadClientReplacementError = class extends AgentHarnessPreflightError$1 {
|
|
2417
|
+
constructor() {
|
|
2418
|
+
super("Codex did not confirm unloading its previous configuration after a settled failure; a fresh client is required.");
|
|
2419
|
+
this.name = "CodexThreadClientReplacementError";
|
|
2420
|
+
}
|
|
2421
|
+
};
|
|
2077
2422
|
var CodexThreadBindingConflictError = class extends Error {
|
|
2078
2423
|
constructor(threadId, operation) {
|
|
2079
2424
|
super(`Codex thread binding changed while ${operation}: ${threadId}`);
|
|
@@ -2109,7 +2454,6 @@ var shared_client_exports = /* @__PURE__ */ __exportAll({
|
|
|
2109
2454
|
readCodexAppServerClientProcessIdentity: () => readCodexAppServerClientProcessIdentity,
|
|
2110
2455
|
releaseCodexAppServerClientLease: () => releaseCodexAppServerClientLease,
|
|
2111
2456
|
releaseLeasedSharedCodexAppServerClient: () => releaseLeasedSharedCodexAppServerClient,
|
|
2112
|
-
resolveCodexAppServerSpawnIdentity: () => resolveCodexAppServerSpawnIdentity,
|
|
2113
2457
|
resolveCodexNativeConfigFenceKey: () => resolveCodexNativeConfigFenceKey,
|
|
2114
2458
|
retainSharedCodexAppServerClientByInstanceId: () => retainSharedCodexAppServerClientByInstanceId,
|
|
2115
2459
|
retainSharedCodexAppServerClientIfCurrent: () => retainSharedCodexAppServerClientIfCurrent,
|
|
@@ -2132,7 +2476,7 @@ async function prepareCodexAppServerClient(options) {
|
|
|
2132
2476
|
if (abandonSignal.aborted) throw new CodexAppServerStartupError("aborted", "codex app-server initialize aborted");
|
|
2133
2477
|
};
|
|
2134
2478
|
assertCurrent();
|
|
2135
|
-
const startedAt =
|
|
2479
|
+
const startedAt = performance.now();
|
|
2136
2480
|
return {
|
|
2137
2481
|
context: await withCodexAppServerAcquireDeadline(options?.timeoutMs ?? 0, ownCodexStartup(lifetime, resolveCodexAppServerClientStartContext(options)), abandonSignal),
|
|
2138
2482
|
lifetime,
|
|
@@ -2176,17 +2520,6 @@ async function waitForCodexAppServerClientDesktopGenerationDrain(params) {
|
|
|
2176
2520
|
drain.cancel();
|
|
2177
2521
|
}
|
|
2178
2522
|
}
|
|
2179
|
-
/** Resolves non-secret spawn identity before startup; argv is represented only by its hash. */
|
|
2180
|
-
function resolveCodexAppServerSpawnIdentity(startOptions, resolvedNativeCommand) {
|
|
2181
|
-
const nativeCommand = resolvedNativeCommand ?? (startOptions.commandSource === "resolved-managed" ? resolveManagedCodexNativeCommand(startOptions.command) : void 0);
|
|
2182
|
-
return {
|
|
2183
|
-
command: startOptions.command,
|
|
2184
|
-
argsFingerprint: createHash("sha256").update(JSON.stringify(startOptions.args)).digest("hex"),
|
|
2185
|
-
...startOptions.commandSource ? { commandSource: startOptions.commandSource } : {},
|
|
2186
|
-
...startOptions.managedCommandOrder ? { managedCommandOrder: startOptions.managedCommandOrder } : {},
|
|
2187
|
-
...nativeCommand ? { nativeCommand } : {}
|
|
2188
|
-
};
|
|
2189
|
-
}
|
|
2190
2523
|
var CodexAppServerStartSelectionChangedError = class extends Error {
|
|
2191
2524
|
constructor() {
|
|
2192
2525
|
super("Codex app-server managed executable selection changed during startup");
|
|
@@ -2221,8 +2554,7 @@ function resolveCodexNativeConfigFenceKey(params) {
|
|
|
2221
2554
|
const startOptions = metadata?.startOptions ?? params.startOptions;
|
|
2222
2555
|
if (!startOptions || startOptions.transport !== "stdio") return;
|
|
2223
2556
|
const configuredHome = startOptions.env?.CODEX_HOME?.trim();
|
|
2224
|
-
const
|
|
2225
|
-
const codexHome = configuredHome ? configuredHome : startOptions.homeScope === "user" ? resolveCodexAppServerUserHomeDir() : agentDir ? resolveCodexAppServerHomeDir(agentDir) : void 0;
|
|
2557
|
+
const codexHome = configuredHome ? configuredHome : startOptions.homeScope === "user" ? resolveCodexAppServerUserHomeDir() : resolveCodexAppServerHomeDir(params.agentDir ?? metadata?.agentDir ?? resolveDefaultAgentDir(params.config ?? {}));
|
|
2226
2558
|
return codexHome ? `codex-home:${path.resolve(codexHome)}` : void 0;
|
|
2227
2559
|
}
|
|
2228
2560
|
function inferAuthRequirement(preparedAuth) {
|
|
@@ -2230,8 +2562,8 @@ function inferAuthRequirement(preparedAuth) {
|
|
|
2230
2562
|
return preparedAuth?.kind === "profile" ? "subscription" : void 0;
|
|
2231
2563
|
}
|
|
2232
2564
|
async function resolveCodexAppServerClientStartContext(options) {
|
|
2233
|
-
const
|
|
2234
|
-
const
|
|
2565
|
+
const requestedStartOptions = options?.startOptions ?? resolveCodexAppServerRuntimeOptions({ pluginConfig: options?.pluginConfig }).start;
|
|
2566
|
+
const agentDir = options?.agentDir ?? (requestedStartOptions.homeScope === "user" ? void 0 : resolveDefaultAgentDir(options?.config ?? {}));
|
|
2235
2567
|
const desktopGeneration = shouldTrackDesktopGeneration(requestedStartOptions, options?.pluginConfig) ? await waitForCodexDesktopGeneration() : void 0;
|
|
2236
2568
|
const preparedAuth = options?.preparedAuth;
|
|
2237
2569
|
const preparedApiKey = preparedAuth?.kind === "api-key" ? preparedAuth.apiKey.trim() : void 0;
|
|
@@ -2331,11 +2663,11 @@ async function withLeasedCodexAppServerClientStartSelectionRetry(params) {
|
|
|
2331
2663
|
let client = params.lease.client;
|
|
2332
2664
|
if (!client) throw new Error("Codex app-server selection retry requires an active client lease");
|
|
2333
2665
|
const timeoutMs = params.options?.timeoutMs ?? 6e4;
|
|
2334
|
-
const deadline =
|
|
2666
|
+
const deadline = performance.now() + timeoutMs;
|
|
2335
2667
|
const signal = params.signal ?? params.options?.abandonSignal;
|
|
2336
2668
|
const requestOptions = () => {
|
|
2337
2669
|
if (signal?.aborted) throw new CodexAppServerStartupError("aborted", "Codex app-server selection retry aborted");
|
|
2338
|
-
const remainingTimeoutMs = deadline -
|
|
2670
|
+
const remainingTimeoutMs = deadline - performance.now();
|
|
2339
2671
|
if (remainingTimeoutMs <= 0) throw new CodexAppServerStartupError("timed_out", "Codex app-server selection retry timed out");
|
|
2340
2672
|
return {
|
|
2341
2673
|
timeoutMs: remainingTimeoutMs,
|
|
@@ -2484,7 +2816,7 @@ function buildCodexAppServerInitializeTimeoutError(client) {
|
|
|
2484
2816
|
}
|
|
2485
2817
|
function resolveRemainingAcquireTimeout(timeoutMs, startedAt) {
|
|
2486
2818
|
if (!(timeoutMs > 0)) return timeoutMs;
|
|
2487
|
-
const remaining = timeoutMs - (
|
|
2819
|
+
const remaining = timeoutMs - (performance.now() - startedAt);
|
|
2488
2820
|
if (remaining <= 0) throw new CodexAppServerStartupError("timed_out", "codex app-server initialize timed out");
|
|
2489
2821
|
return remaining;
|
|
2490
2822
|
}
|
|
@@ -2564,7 +2896,7 @@ function trackIsolatedCodexAppServerClient(client) {
|
|
|
2564
2896
|
});
|
|
2565
2897
|
}
|
|
2566
2898
|
async function startInitializedCodexAppServerClient(params) {
|
|
2567
|
-
const acquireStartedAt =
|
|
2899
|
+
const acquireStartedAt = performance.now();
|
|
2568
2900
|
const timeoutMs = params.timeoutMs ?? 0;
|
|
2569
2901
|
const abandonSignal = params.abandonSignal ? AbortSignal.any([params.lifetime.controller.signal, params.abandonSignal]) : params.lifetime.controller.signal;
|
|
2570
2902
|
const waitForStartup = (operation, timeoutMessage = CODEX_APP_SERVER_INITIALIZE_TIMEOUT_MESSAGE, timeoutErrorFactory) => {
|
|
@@ -2609,7 +2941,7 @@ async function startInitializedCodexAppServerClient(params) {
|
|
|
2609
2941
|
} finally {
|
|
2610
2942
|
artifactDrain?.cancel();
|
|
2611
2943
|
}
|
|
2612
|
-
const runtimeArtifactModule = params.runtimeArtifactMode ? await import("./runtime-artifact-
|
|
2944
|
+
const runtimeArtifactModule = params.runtimeArtifactMode ? await import("./runtime-artifact-Dy38Z5iU.mjs") : void 0;
|
|
2613
2945
|
const runtimeArtifactBeforeStart = runtimeArtifactModule ? await runtimeArtifactModule.captureCodexAppServerRuntimeArtifactBeforeStart({
|
|
2614
2946
|
startOptions,
|
|
2615
2947
|
spawnIdentity: resolveCodexAppServerSpawnIdentity(startOptions),
|
|
@@ -2651,6 +2983,10 @@ async function startInitializedCodexAppServerClient(params) {
|
|
|
2651
2983
|
}
|
|
2652
2984
|
assertStartupCurrent();
|
|
2653
2985
|
params.onInitializedClient?.();
|
|
2986
|
+
await waitForStartup(() => observeCodexCatalogClient(client, {
|
|
2987
|
+
startOptions: params.requestedStartOptions,
|
|
2988
|
+
agentDir: params.agentDir
|
|
2989
|
+
}));
|
|
2654
2990
|
let runtimeArtifact;
|
|
2655
2991
|
if (runtimeArtifactModule && runtimeArtifactBeforeStart) {
|
|
2656
2992
|
runtimeArtifact = await runtimeArtifactModule.finalizeCodexAppServerRuntimeArtifact({
|
|
@@ -2671,7 +3007,7 @@ async function startInitializedCodexAppServerClient(params) {
|
|
|
2671
3007
|
onAuthRefreshFailure: () => retireSharedCodexAppServerClientIfCurrent(client)
|
|
2672
3008
|
});
|
|
2673
3009
|
assertStartupCurrent();
|
|
2674
|
-
await waitForStartup(() => applyCodexAppServerAuthProfile({
|
|
3010
|
+
const authHandoff = await waitForStartup(() => applyCodexAppServerAuthProfile({
|
|
2675
3011
|
client,
|
|
2676
3012
|
agentDir: params.agentDir,
|
|
2677
3013
|
authProfileId: params.authProfileId,
|
|
@@ -2682,6 +3018,8 @@ async function startInitializedCodexAppServerClient(params) {
|
|
|
2682
3018
|
assertCurrent: assertStartupCurrent,
|
|
2683
3019
|
...params.authProfileStore ? { authProfileStore: params.authProfileStore } : {}
|
|
2684
3020
|
}));
|
|
3021
|
+
if (startOptions.transport === "stdio" && nativeCommandAtStart && !desktopGeneration && !isManagedCodexDesktopCommand(startOptions.command) && !isCodexAppServerProxyLaunch(startOptions.args)) ownCodexInferenceClient(client);
|
|
3022
|
+
recordCodexAppServerAuthHandoff(client, authHandoff);
|
|
2685
3023
|
if (runtimeArtifactModule && runtimeArtifact) runtimeArtifactModule.bindCodexAppServerRuntimeArtifact(client, runtimeArtifact);
|
|
2686
3024
|
assertStartupCurrent();
|
|
2687
3025
|
const fenceKey = resolveCodexNativeConfigFenceKey({ client });
|
|
@@ -2694,7 +3032,7 @@ async function startInitializedCodexAppServerClient(params) {
|
|
|
2694
3032
|
release();
|
|
2695
3033
|
throw error;
|
|
2696
3034
|
}
|
|
2697
|
-
});
|
|
3035
|
+
}, () => Boolean(retireSharedCodexAppServerClientIfCurrent(client)));
|
|
2698
3036
|
ready = true;
|
|
2699
3037
|
return client;
|
|
2700
3038
|
} finally {
|
|
@@ -2769,8 +3107,8 @@ function retainSharedCodexAppServerClientByInstanceId(clientId) {
|
|
|
2769
3107
|
function captureCodexAppServerClientLifetime(client, requiredOwnership) {
|
|
2770
3108
|
const state = getSharedCodexAppServerClientState();
|
|
2771
3109
|
const start = state.startMetadata.get(client)?.startOptions;
|
|
2772
|
-
if (requiredOwnership === "native-process" && (start?.transport !== "stdio" || isCodexAppServerProxyLaunch(start.args))) throw new AgentHarnessPreflightError("Codex
|
|
2773
|
-
const isCurrent = requiredOwnership
|
|
3110
|
+
if (requiredOwnership === "native-process" && (start?.transport !== "stdio" || isCodexAppServerProxyLaunch(start.args))) throw new AgentHarnessPreflightError("Codex manual thread adoption requires an OpenClaw-managed local stdio process, not an external socket or app-server proxy. No turn was sent; reconnect through managed local stdio before continuing.");
|
|
3111
|
+
const isCurrent = requiredOwnership !== "connection" && state.isolatedClients.has(client) ? () => state.isolatedClients.has(client) && !client.getCloseError() : captureSharedClientRegistration(client);
|
|
2774
3112
|
const assertCurrent = () => {
|
|
2775
3113
|
if (!isCurrent()) throw new CodexAdoptedThreadActiveError("Codex app-server connection changed during thread preparation; reconnect before continuing");
|
|
2776
3114
|
assertCodexAppServerClientStartSelectionCurrent({ client });
|
|
@@ -2846,6 +3184,7 @@ async function clearSharedCodexAppServerClientAndWait(options) {
|
|
|
2846
3184
|
try {
|
|
2847
3185
|
while (lifetime.pending.size > 0) await Promise.allSettled(lifetime.pending);
|
|
2848
3186
|
await closing;
|
|
3187
|
+
await nativeHookRelayUnregisterQueue.flush();
|
|
2849
3188
|
} finally {
|
|
2850
3189
|
if (state.startup === lifetime) state.startup = createCodexAppServerStartupLifetime();
|
|
2851
3190
|
}
|
|
@@ -2908,4 +3247,4 @@ function retirePendingSharedClientEntryIfUnclaimed(entry) {
|
|
|
2908
3247
|
closeRetiredSharedClientEntry(entry);
|
|
2909
3248
|
}
|
|
2910
3249
|
//#endregion
|
|
2911
|
-
export { assertNotSymlink as $,
|
|
3250
|
+
export { assertNotSymlink as $, getCodexInferenceThread as A, prepareCodexWorkspaceReferences as B, CodexThreadBindingConflictError as C, acquireCodexNativeConfigFence as D, nativeHookRelayUnregisterQueue as E, forgetCodexWorkspaceReferences as F, unsubscribeCodexAppServerLiveThread as G, readCodexClientSessionMeta as H, hasCodexAppServerLiveThread as I, rememberCodexRateLimitsRead as J, readCodexRateLimitsRevision as K, hasCodexAppServerSiblingThreadWork as L, claimCodexAppServerLiveThread as M, consumeCodexAppServerLiveThread as N, assertCodexInferenceRouteConfig as O, ensureCodexAppServerClientRuntime as P, resolveCodexManagedBundledMarketplacePath as Q, isCodexAppServerClientRuntimeLive as R, CodexAdoptedThreadActiveError as S, CodexThreadStartRequestError as T, releaseCodexAppServerLiveThread as U, protectCodexAppServerLiveThread as V, retainCodexAppServerLiveThread as W, resolveCodexAppServerAuthAccountCacheKey as X, reconcileCodexComputerUseStartArtifacts as Y, resolveCodexAppServerPreparedAuthHandoff as Z, retainSharedCodexAppServerClientByInstanceId as _, clearSharedCodexAppServerClientIfCurrentAndUnclaimed as a, resolveCodexStartupTimeoutMs as at, waitForCodexAppServerClientDesktopGenerationDrain as b, getLeasedSharedCodexAppServerClient as c, readCodexAppServerClientDesktopGeneration as d, CodexAppServerStartupError as et, readCodexAppServerClientDesktopGenerationFingerprint as f, resolveCodexNativeConfigFenceKey as g, releaseLeasedSharedCodexAppServerClient as h, clearSharedCodexAppServerClientIfCurrent as i, resolveCodexGatewayTimeoutWithGraceMs as it, prepareCodexInferenceThreadConfig as j, bindCodexInferenceThread as k, getSharedCodexAppServerClient as l, releaseCodexAppServerClientLease as m, captureCodexAppServerClientLifetime as n, TURN_TERMINAL_SETTLEMENT_TIMEOUT_MS as nt, clearSharedCodexAppServerClientIfCurrentAndWait as o, withCodexStartupTimeout as ot, readCodexAppServerClientProcessIdentity as p, readRecentCodexRateLimits as q, captureSharedCodexAppServerCatalogLifetime as r, isCodexAppServerStartupError as rt, createIsolatedCodexAppServerClient as s, assertCodexAppServerClientStartSelectionCurrent as t, TURN_FINALIZE_DRAIN_ABORT_GRACE_MS as tt, isCodexAppServerStartSelectionChangedError as u, retainSharedCodexAppServerClientIfCurrent as v, CodexThreadClientReplacementError as w, withLeasedCodexAppServerClientStartSelectionRetry as x, shared_client_exports as y, isCodexAppServerLiveThreadClaimed as z };
|