@openclaw/codex 2026.10.5-beta.4 → 2026.10.10-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -3
- package/dist/.setup/{account-usage-runtime-CoVpNIlD.mjs → account-usage-runtime-BVO-lpvn.mjs} +15 -9
- package/dist/.setup/{app-server-policy-D_zv8J7V.mjs → app-server-policy-Cog6mm2i.mjs} +1 -1
- package/dist/.setup/{apply-BXDMd05l.mjs → apply-tJl5mopa.mjs} +11 -11
- package/dist/.setup/{attempt-client-cleanup-zNuNTKVr.mjs → attempt-client-cleanup-DMJWXGxM.mjs} +14 -8
- package/dist/.setup/attempt-terminal-sZutF0WY.mjs +1 -0
- package/dist/.setup/{attempt-workspace-context-CcwP3DA3.mjs → attempt-workspace-context-GYPLawX6.mjs} +2 -2
- package/dist/.setup/{auth-binding-BaxlhaNx.mjs → auth-binding-830RLAJW.mjs} +2 -2
- package/dist/.setup/{auth-cache-key-f8ODJ_OX.mjs → auth-cache-key-BW1YeaIk.mjs} +92 -80
- package/dist/.setup/{auth-profile-CgHQ8Vot.mjs → auth-profile-auwzSwwy.mjs} +14 -8
- package/dist/.setup/{auth-profile-health-oHizqgye.mjs → auth-profile-health-BVPZU9I8.mjs} +15 -8
- package/dist/.setup/{auth-profile-selection-hr8ocLtz.mjs → auth-profile-selection-Bp5PDk3W.mjs} +24 -7
- package/dist/.setup/{binding-connection-B7HAAZSI.mjs → binding-connection-GTgUj9pi.mjs} +2 -2
- package/dist/.setup/{binding-connection.runtime-DAXn7iFl.mjs → binding-connection.runtime-RcWR3vQu.mjs} +4 -3
- package/dist/.setup/{bounded-turn-DfIJtRlv.mjs → bounded-turn-BQkmyyjB.mjs} +18 -22
- package/dist/.setup/{bounded-turn-isolation-BfDAo-qZ.mjs → bounded-turn-isolation-D8CDrAVX.mjs} +3 -3
- package/dist/.setup/{build-state-Ds14X10-.mjs → build-state-CjLCC0wm.mjs} +1 -1
- package/dist/.setup/{capabilities-DbOzOglY.mjs → capabilities-DAS-JX1z.mjs} +1 -1
- package/dist/.setup/{client-D93nbdB8.mjs → client--P8jwXvA.mjs} +47 -317
- package/dist/.setup/{client-catalog-response-CuVLp4I0.mjs → client-catalog-response-CsDxVVOZ.mjs} +2 -2
- package/dist/.setup/client-initialize-CjgZcX61.mjs +165 -0
- package/dist/.setup/{command-dispatch-DxdH5a9-.mjs → command-dispatch-DqaVBeR3.mjs} +3 -3
- package/dist/.setup/{command-formatters-xW9KpoSZ.mjs → command-formatters-B_7-QZ1c.mjs} +2 -2
- package/dist/.setup/{command-handlers-fiYvYYq0.mjs → command-handlers-i6mEjvfo.mjs} +539 -406
- package/dist/.setup/command-rpc-B65jEc0r.mjs +296 -0
- package/dist/.setup/compact-AO2H4RJe.mjs +823 -0
- package/dist/.setup/{computer-use-DL2v3Kxq.mjs → computer-use-YUnu0JVx.mjs} +21 -68
- package/dist/.setup/{config-C1YVVLEA.mjs → config-BfrAlTMT.mjs} +3 -3
- package/dist/.setup/{config-options-DDzeNQ8m.mjs → config-options-DMFZkd3X.mjs} +1 -1
- package/dist/.setup/{config-runtime-DWzK-k0n.mjs → config-runtime-BZRizyuG.mjs} +2 -2
- package/dist/.setup/{context-engine-projection-ps-yn_ci.mjs → context-engine-projection-PIeLSnR-.mjs} +16 -30
- package/dist/.setup/{conversation-binding-BieJZRRV.mjs → conversation-binding-CfnUR-IM.mjs} +228 -116
- package/dist/.setup/{conversation-binding-data-UgLuTSQT.mjs → conversation-binding-data-khgW0n-o.mjs} +4 -2
- package/dist/.setup/{conversation-control-GXM3unE4.mjs → conversation-control-B2EpVZEb.mjs} +53 -23
- package/dist/.setup/{cyber-failover-D4dgNfFf.mjs → cyber-failover-CqEZoQsj.mjs} +1 -1
- package/dist/.setup/{cyber-failover-notice-ljgGGL0s.mjs → cyber-failover-notice-poL3Advd.mjs} +1 -1
- package/dist/.setup/{doctor-start-options-JjTAl-q_.mjs → doctor-start-options-8uIBXIzR.mjs} +8 -5
- package/dist/.setup/{dynamic-tool-build-DcaPmBlE.mjs → dynamic-tool-build-DOub3CB5.mjs} +208 -218
- package/dist/.setup/{dynamic-tools-CnQFnNKH.mjs → dynamic-tools-Us5mvq_N.mjs} +344 -118
- package/dist/.setup/{effective-mcp-catalog-B5HKFZNK.mjs → effective-mcp-catalog-DfUUoeeM.mjs} +11 -9
- package/dist/.setup/{ephemeral-turn-De3qb8EQ.mjs → ephemeral-turn-B2z0RIeF.mjs} +5 -4
- package/dist/.setup/{event-projector-assistant-message-CLMKN4x-.mjs → event-projector-assistant-message-ChOAY7rW.mjs} +16 -11
- package/dist/.setup/{event-projector-usage-BpKfdoTm.mjs → event-projector-usage-CBY0Hkga.mjs} +2 -2
- package/dist/.setup/{event-projector-values-CLvG1Hil.mjs → event-projector-values-yf4us9Pf.mjs} +1 -1
- package/dist/.setup/experimental-features-uGnVDtp-.mjs +19 -0
- package/dist/.setup/inference-context-HRw3PDwn.mjs +209 -0
- package/dist/.setup/{inference-dispatch-CO6tTs4q.mjs → inference-dispatch-C2zVSnrr.mjs} +2 -2
- package/dist/.setup/{inference-metadata-DCvcG_N_.mjs → inference-metadata-CYFWLHVk.mjs} +3 -1
- package/dist/.setup/{inference-proxy-BDWV0djM.mjs → inference-proxy-CiLbHMLf.mjs} +8 -8
- package/dist/.setup/installed-probe-lVC1X5ve.mjs +185 -0
- package/dist/.setup/{isolated-completion-BPJdvk5F.mjs → isolated-completion-CybgD6uU.mjs} +7 -7
- package/dist/.setup/managed-binary-DbKvGXKl.mjs +395 -0
- package/dist/.setup/{mcp-app-session-preparation-Dz2GOwyE.mjs → mcp-app-session-preparation-zUgpDLWR.mjs} +18 -14
- package/dist/.setup/{model-catalog-ZNwltCKl.mjs → model-catalog-CWY3wo0B.mjs} +28 -17
- package/dist/.setup/{models-BHpbAuz8.mjs → models-CmOBxsKF.mjs} +3 -3
- package/dist/.setup/{native-auth-esN5MdIv.mjs → native-auth-DpZIaY8N.mjs} +7 -4
- package/dist/.setup/native-execution-policy-D09tLP-u.mjs +152 -0
- package/dist/.setup/{native-hook-relay-wq7jrNLk.mjs → native-hook-relay-CocOW9YS.mjs} +45 -10
- package/dist/.setup/{native-mcp-app-DX3nyTtc.mjs → native-mcp-app-DrQeLxXj.mjs} +5 -5
- package/dist/.setup/{native-skill-isolation-DSBeF-Yy.mjs → native-skill-isolation-DL4-PQa4.mjs} +7 -7
- package/dist/.setup/{native-subagent-monitor-DOLEIf9r.mjs → native-subagent-monitor-C3CIIaZG.mjs} +485 -239
- package/dist/.setup/{native-subagent-pending-assignments-DmVhedNs.mjs → native-subagent-pending-assignments-CTinVtjo.mjs} +1 -1
- package/dist/.setup/{native-task-assignments-DimsQ9Qa.mjs → native-task-assignments-YJopbaVO.mjs} +9 -5
- package/dist/.setup/{node-cli-sessions-CzKg2nGq.mjs → node-cli-sessions-BuJnBnEq.mjs} +7 -4
- package/dist/.setup/{node-exec-server.runtime-BWkULhBM.mjs → node-exec-server.runtime-CP7RC1Nd.mjs} +3 -3
- package/dist/.setup/{plan-41-YOBMq.mjs → plan-Bqj6VQvQ.mjs} +7 -20
- package/dist/.setup/{plugin-activation-D7WkJMvU.mjs → plugin-activation-CXPWe-hl.mjs} +4 -4
- package/dist/.setup/{plugin-app-cache-key-Bg9DbDI6.mjs → plugin-app-cache-key-DRb-niJc.mjs} +17 -55
- package/dist/.setup/{plugin-approval-roundtrip-CD88q3yx.mjs → plugin-approval-roundtrip-CGEiG7hG.mjs} +1 -1
- package/dist/.setup/{plugin-inventory-CYgdo14P.mjs → plugin-inventory-DE9wcaeH.mjs} +2 -2
- package/dist/.setup/{plugin-metadata-cache-Bi8TAPwX.mjs → plugin-metadata-cache-BqC-a6Fb.mjs} +2 -15
- package/dist/.setup/{project-doc-thread-config-BVcvnps8.mjs → project-doc-thread-config-B0UI3f1D.mjs} +6 -6
- package/dist/.setup/protocol-CaPAVwe9.mjs +12 -0
- package/dist/.setup/{provider-LWKll6dV.mjs → provider-C_1fMsyD.mjs} +4 -4
- package/dist/.setup/{provider-capabilities-Dn2WwH4P.mjs → provider-capabilities-C7pYYpvh.mjs} +1 -1
- package/dist/.setup/{rate-limits-CI8pTPqL.mjs → rate-limits-BpfURnuy.mjs} +1 -1
- package/dist/.setup/{request-Bo0kKABI.mjs → request-C6U8q2uz.mjs} +132 -136
- package/dist/.setup/{responses-oauth-twnuTaAa.mjs → responses-oauth-CCV7aVYF.mjs} +6 -6
- package/dist/.setup/{rpc-error-C98SHchT.mjs → rpc-error-DemqqaxE.mjs} +7 -3
- package/dist/.setup/{run-attempt-ClU8MxhZ.mjs → run-attempt-BhuXanLv.mjs} +595 -426
- package/dist/.setup/{run-attempt-lifecycle-KN4oh-7O.mjs → run-attempt-lifecycle-DN-ATDp9.mjs} +1 -1
- package/dist/.setup/{runtime-artifact-C13pR7tD.mjs → runtime-artifact-CmLWeyJB.mjs} +3 -3
- package/dist/.setup/{runtime-artifact-connection-jS5DeCok.mjs → runtime-artifact-connection-DpWlZ02e.mjs} +3 -3
- package/dist/.setup/{sandbox-guard-DIImwCy1.mjs → sandbox-guard-DneAfNye.mjs} +70 -30
- package/dist/.setup/{session-binding-JEHNMPsr.mjs → session-binding-BgsWcbdY.mjs} +25 -23
- package/dist/.setup/{session-binding-record-DU_0biMD.mjs → session-binding-record-C_THntMe.mjs} +27 -12
- package/dist/.setup/{session-binding-record-codec-BpH8u_G9.mjs → session-binding-record-codec-DvmOI7g_.mjs} +1 -0
- package/dist/.setup/{session-binding-sidecars-DD-enC8w.mjs → session-binding-sidecars-BNSS6WL4.mjs} +55 -63
- package/dist/.setup/session-cancellation-DCN1FcBZ.mjs +43 -0
- package/dist/.setup/{session-catalog-adoption-Ca3OYGYM.mjs → session-catalog-adoption-ppsLlVLB.mjs} +24 -38
- package/dist/.setup/{session-catalog-archive-Bv6gV7x9.mjs → session-catalog-archive-CqLRHJ6z.mjs} +11 -13
- package/dist/.setup/{session-catalog-events-kR2Ot6nX.mjs → session-catalog-events-CEi6SuLQ.mjs} +5 -5
- package/dist/.setup/{session-catalog-index-order-CTfoefow.mjs → session-catalog-index-order-0Zqng2u8.mjs} +1 -1
- package/dist/.setup/{session-catalog-index-CrnfVEnT.mjs → session-catalog-index-qt4UWBua.mjs} +96 -271
- package/dist/.setup/{session-catalog-limits-BynIoOYm.mjs → session-catalog-limits-Dc6E0BZz.mjs} +1 -1
- package/dist/.setup/{session-catalog-list-request-D4MYNgDB.mjs → session-catalog-list-request-CAjoWjaH.mjs} +3 -4
- package/dist/.setup/{session-catalog-native-projection-CWqCU1I_.mjs → session-catalog-native-projection-BqBYi6kV.mjs} +5 -5
- package/dist/.setup/{session-catalog-node-adoption-BdP9Zjqo.mjs → session-catalog-node-adoption-e9v8mGgx.mjs} +5 -5
- package/dist/.setup/{session-catalog-node-continue-CNJibO4_.mjs → session-catalog-node-continue-H7nrzcUD.mjs} +5 -5
- package/dist/.setup/{session-catalog-node-lookup-BH_DBGa9.mjs → session-catalog-node-lookup-BrZfDkA8.mjs} +2 -2
- package/dist/.setup/{session-catalog-parsing-DkeoVn60.mjs → session-catalog-parsing-V6jyFg9g.mjs} +2 -2
- package/dist/.setup/{session-catalog-projection-BzHiV818.mjs → session-catalog-projection-CNyhjZze.mjs} +8 -7
- package/dist/.setup/{session-catalog-provenance-CmsOE5mh.mjs → session-catalog-provenance-Dg9s12z-.mjs} +50 -30
- package/dist/.setup/{session-catalog-source-DGuRdGvM.mjs → session-catalog-source-z_mNyQdX.mjs} +2 -6
- package/dist/.setup/{session-cli-GwU0izn-.mjs → session-cli-CBGKiqdv.mjs} +1 -1
- package/dist/.setup/{session-history-BO6i_pfk.mjs → session-history-7W0cgTXF.mjs} +11 -9
- package/dist/.setup/{session-history-import-CaO8s6ta.mjs → session-history-import-BwPKwcNi.mjs} +4 -4
- package/dist/.setup/{session-initialization-Bi_2DKhc.mjs → session-initialization-Dn3vveGv.mjs} +2 -2
- package/dist/.setup/{session-retirement-B3U5hpGJ.mjs → session-retirement-RZStisKb.mjs} +8 -8
- package/dist/.setup/{session-history.worker-DJQfek5p.mjs → settled-turn-evidence--tRW6fSm.mjs} +2 -18
- package/dist/.setup/{settled-turn-finalizer-CYCVpTv2.mjs → settled-turn-finalizer-gioXygEX.mjs} +8 -8
- package/dist/.setup/{shared-client-BCx1wbyA.mjs → shared-client-CkyTrNB8.mjs} +380 -557
- package/dist/.setup/side-question-DHPWKgO3.mjs +998 -0
- package/dist/.setup/{source-DipMO9hL.mjs → source-63MLSmLJ.mjs} +5 -5
- package/dist/.setup/{thread-archive-guard-LKdwQKyr.mjs → thread-archive-guard-BWjSsA92.mjs} +1 -1
- package/dist/.setup/{thread-lifecycle-run-C_aYiYqk.mjs → thread-lifecycle-run-zCXYFW8W.mjs} +172 -75
- package/dist/.setup/{thread-model-selection-DcVebr8N.mjs → thread-model-selection-DxposL4X.mjs} +9 -9
- package/dist/.setup/{thread-ownership-BoUd0i6L.mjs → thread-ownership-Bmk5a2Gu.mjs} +7 -7
- package/dist/.setup/{thread-policy-B3wBRNph.mjs → thread-policy-DYtvZ5Ay.mjs} +6 -6
- package/dist/.setup/{thread-requests-BgzJwJtS.mjs → thread-requests-BjawdIVV.mjs} +14 -14
- package/dist/.setup/{thread-resume-D-3bsr1j.mjs → thread-resume-vBShG3-o.mjs} +6 -6
- package/dist/.setup/{transcript-history-projection-DfKcoZCB.mjs → transcript-history-projection-i-FVpyha.mjs} +1 -1
- package/dist/.setup/{transcript-mirror-Bee2o6jj.mjs → transcript-mirror-CEQJZlF3.mjs} +6 -9
- package/dist/.setup/{transport-stdio-CRWTkKOn.mjs → transport-stdio-Bq160Dhv.mjs} +63 -64
- package/dist/.setup/{transport-websocket-DIyPfkHo.mjs → transport-websocket-0YqiI_MH.mjs} +1 -1
- package/dist/.setup/{turn-router-DBVMToGo.mjs → turn-router-BGj67FMK.mjs} +2 -2
- package/dist/.setup/{upstream-session-fork-p5fwKi7w.mjs → upstream-session-fork-CWKjpdtW.mjs} +46 -219
- package/dist/.setup/{usage-C2Kq7oej.mjs → usage-AhrLFxZP.mjs} +4 -4
- package/dist/.setup/{usage-limit-error-BQX8RHAd.mjs → usage-limit-error-BdNbGJC3.mjs} +4 -4
- package/dist/.setup/{web-search-item-CvokaZOo.mjs → web-search-item-DHVuNSqk.mjs} +1 -1
- package/dist/.setup/{web-search-provider.runtime-D89djc7e.mjs → web-search-provider.runtime-Yk6lnJBG.mjs} +3 -3
- package/dist/.setup/{workspace-write-sandbox-probe-BDWO2Qkh.mjs → workspace-write-sandbox-probe-DJxOXcF3.mjs} +2 -2
- package/dist/api.js +7 -28
- package/dist/catalog-page.worker.js +1 -1
- package/dist/cli-metadata.js +1 -1
- package/dist/client-version-api.js +25 -0
- package/dist/doctor-contract-api.js +5 -5
- package/dist/harness.js +59 -36
- package/dist/index.js +259 -295
- package/dist/media-understanding-provider.js +2 -2
- package/dist/migration-provider-api.js +1 -2
- package/dist/native-session-binding-api.js +1 -2
- package/dist/provider-discovery.js +1 -1
- package/dist/session-history-worker-entrypoint.js +12 -0
- package/dist/session-history-worker-runtime.js +7 -18
- package/dist/session-history.worker.js +18 -2
- package/openclaw.plugin.json +1 -1
- package/package.json +6 -6
- package/dist/.setup/attempt-terminal-jO5IMj9K.mjs +0 -2
- package/dist/.setup/command-rpc-HIvsy3wS.mjs +0 -247
- package/dist/.setup/compact-ClZ7Ar7L.mjs +0 -808
- package/dist/.setup/inference-context-DNlGwzwy.mjs +0 -91
- package/dist/.setup/managed-binary-BtIjV7yN.mjs +0 -175
- package/dist/.setup/native-execution-policy-MXEe7PB3.mjs +0 -75
- package/dist/.setup/protocol-CANUwXJ3.mjs +0 -17
- package/dist/.setup/side-question-Bz2UQW0l.mjs +0 -826
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as defineCodexBuildState, t as codexBuildSymbol } from "./build-state-
|
|
3
|
-
import { t as CODEX_APP_SERVER_AUTH_PROVIDER } from "./auth-profile-selection-
|
|
1
|
+
import { r as isJsonObject } from "./protocol-CaPAVwe9.mjs";
|
|
2
|
+
import { n as defineCodexBuildState, t as codexBuildSymbol } from "./build-state-CjLCC0wm.mjs";
|
|
3
|
+
import { t as CODEX_APP_SERVER_AUTH_PROVIDER } from "./auth-profile-selection-Bp5PDk3W.mjs";
|
|
4
4
|
import { n as isCodexAppServerProxyLaunch } from "./launch-args-DbFCehO7.mjs";
|
|
5
|
-
import { a as withEphemeralCodexAuthStore, i as withClearedEnvironmentVariables, n as resolveCodexAppServerLocalHomeDir,
|
|
6
|
-
import { a as resolveCodexAppServerStartOptionsForAgent, d as readCodexEffectiveConfig, o as resolveCodexComputerUseConfig, t as codexAppServerStartOptionsKey, u as CODEX_SESSION_OVERRIDABLE_LAYER_TYPES } from "./config-options-
|
|
7
|
-
import {
|
|
8
|
-
import { A as
|
|
9
|
-
import { n as resolveCodexAppServerSpawnEnv } from "./transport-stdio-
|
|
5
|
+
import { a as withEphemeralCodexAuthStore, i as withClearedEnvironmentVariables, n as resolveCodexAppServerLocalHomeDir, t as resolveCodexAppServerHomeDir } from "./auth-start-options-BPIPeEX8.mjs";
|
|
6
|
+
import { a as resolveCodexAppServerStartOptionsForAgent, d as readCodexEffectiveConfig, o as resolveCodexComputerUseConfig, t as codexAppServerStartOptionsKey, u as CODEX_SESSION_OVERRIDABLE_LAYER_TYPES } from "./config-options-DMFZkd3X.mjs";
|
|
7
|
+
import { a as isManagedCodexDesktopCommand, b as resolveMacOSDesktopCodexBundledMarketplaceCandidates, c as readInstalledCodexAppServerStatus, f as resolveManagedCodexNativeCommand, i as assertInstalledCodexAppServerVersion, l as rejectInstalledCodexAppServer, r as INSTALLED_CODEX_START_TIMEOUT_MS, u as resolveManagedCodexAppServerStartOptions, v as resolveFirstExistingMacOSDesktopCodexBundledMarketplacePath, x as resolveMacOSDesktopCodexComputerUseServiceAppCandidates, y as resolveMacOSDesktopCodexAppPathCandidates } from "./managed-binary-DbKvGXKl.mjs";
|
|
8
|
+
import { A as waitForUnclaimedSharedClientStartup, C as releaseSharedClientEntry, D as retireSharedCodexAppServerClientIfCurrent, E as retirePendingSharedClientEntryIfUnclaimed, M as waitForCodexDesktopGeneration, N as readCodexDesktopArtifactTreeFingerprint, S as rekeySharedClientEntry, _ as observeAcquire, a as readCodexCliAuthFileApiKey, b as recordSharedClientAcquireBoundary, c as resolveCodexAppServerPreparedApiKeyCacheKey, d as createCodexAppServerStartupLifetime, f as getCurrentSharedClientEntry, g as isSharedCodexFallbackJoinError, i as fingerprintTokenAuthProfileCacheKey, l as SharedCodexFallbackJoinError, m as getSharedCodexAppServerClientState, n as CODEX_AUTH_JSON_FILENAME, o as readFirstNonEmptyEnv, p as getOrCreateSharedClientEntry, r as fingerprintApiKeyAuthProfileCacheKey, s as resolveCodexAppServerFallbackApiKeyCacheKey, t as CODEX_APP_SERVER_API_KEY_ENV_VARS, u as closeSharedClientEntryIfUnclaimed, v as observeSharedClientAcquire, w as retainSharedClientEntry, x as refreshSharedClientIdleRetirement, y as ownCodexStartup } from "./auth-cache-key-BW1YeaIk.mjs";
|
|
9
|
+
import { n as resolveCodexAppServerSpawnEnv } from "./transport-stdio-Bq160Dhv.mjs";
|
|
10
10
|
import { n as CodexAppServerAuthProfileUnavailableError, r as formatCodexAuthProfileUnavailableMessage } from "./auth-profile-recovery-BREezV0L.mjs";
|
|
11
|
-
import { a as codexPrewriteRejectionCause } from "./rpc-error-
|
|
11
|
+
import { a as codexPrewriteRejectionCause } from "./rpc-error-DemqqaxE.mjs";
|
|
12
12
|
import { i as withTimeout } from "./timeout-D0mEWSGG.mjs";
|
|
13
|
-
import { n as readCodexSessionMeta } from "./session-catalog-provenance-
|
|
14
|
-
import { n as observeCodexCatalogClient } from "./session-catalog-events-
|
|
15
|
-
import { n as resolveCodexAppServerRuntimeOptions } from "./config-runtime-
|
|
16
|
-
import { a as resolveCodexAppServerAuthProfileStore, i as resolveCodexAppServerAuthProfileIdForAgent, r as resolveCodexAppServerAuthProfileId, t as isCodexAppServerNativeAuthProfile } from "./auth-profile-
|
|
17
|
-
import { i as isCodexResponsesOAuthCredential, n as createCodexResponsesOAuth, o as resolveCodexResponsesOAuthProfileFingerprint, r as isCodexResponsesOAuth, t as CODEX_RESPONSES_OAUTH_PROVIDER } from "./responses-oauth-
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
13
|
+
import { n as readCodexSessionMeta } from "./session-catalog-provenance-Dg9s12z-.mjs";
|
|
14
|
+
import { n as observeCodexCatalogClient } from "./session-catalog-events-CEi6SuLQ.mjs";
|
|
15
|
+
import { n as resolveCodexAppServerRuntimeOptions } from "./config-runtime-BZRizyuG.mjs";
|
|
16
|
+
import { a as resolveCodexAppServerAuthProfileStore, i as resolveCodexAppServerAuthProfileIdForAgent, r as resolveCodexAppServerAuthProfileId, t as isCodexAppServerNativeAuthProfile } from "./auth-profile-auwzSwwy.mjs";
|
|
17
|
+
import { i as isCodexResponsesOAuthCredential, n as createCodexResponsesOAuth, o as resolveCodexResponsesOAuthProfileFingerprint, r as isCodexResponsesOAuth, t as CODEX_RESPONSES_OAUTH_PROVIDER } from "./responses-oauth-CCV7aVYF.mjs";
|
|
18
|
+
import { t as CodexAppServerClient } from "./client--P8jwXvA.mjs";
|
|
19
|
+
import { a as isUnsupportedCodexAppServerVersionError } from "./client-initialize-CjgZcX61.mjs";
|
|
20
|
+
import { n as isCodexWebSocketOpenFailure } from "./transport-websocket-0YqiI_MH.mjs";
|
|
21
|
+
import { t as __exportAll } from "./session-binding-sidecars-BNSS6WL4.mjs";
|
|
21
22
|
import { asOptionalRecord, isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
22
23
|
import { createHash, randomUUID } from "node:crypto";
|
|
23
24
|
import { isDeepStrictEqual } from "node:util";
|
|
24
25
|
import { AgentHarnessPreflightError, resolveDefaultAgentDir } from "openclaw/plugin-sdk/agent-harness-registration";
|
|
25
26
|
import { addTimerTimeoutGraceMs, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
|
|
26
|
-
import { resolveGlobalMap } from "openclaw/plugin-sdk/global-singleton";
|
|
27
27
|
import { runExec } from "openclaw/plugin-sdk/process-runtime";
|
|
28
28
|
import fs, { constants, existsSync } from "node:fs";
|
|
29
29
|
import path from "node:path";
|
|
30
30
|
import fs$1 from "node:fs/promises";
|
|
31
31
|
import { extractErrorCode } from "openclaw/plugin-sdk/error-runtime";
|
|
32
32
|
import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
|
|
33
|
-
import {
|
|
33
|
+
import { ensureAuthProfileStoreAsync, findPersistedAuthProfileCredentialAsync, refreshOAuthCredentialForRuntime, resolveApiKeyForProfile, resolvePersistedAuthProfileOwnerAgentDirAsync } from "openclaw/plugin-sdk/agent-runtime";
|
|
34
34
|
import { AgentHarnessPreflightError as AgentHarnessPreflightError$1, embeddedAgentLog as embeddedAgentLog$1, formatErrorMessage as formatErrorMessage$1 } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
35
35
|
import { hasUsableOAuthCredential, resolveOpenAICodexAuthIdentity } from "openclaw/plugin-sdk/provider-auth";
|
|
36
36
|
import { assertDirectoryIdentitySync, readDirectoryIdentity } from "@openclaw/fs-safe/advanced";
|
|
@@ -42,6 +42,7 @@ const CODEX_APP_SERVER_STARTUP_TIMEOUT_FLOOR_MS = 100;
|
|
|
42
42
|
const CODEX_APP_SERVER_STARTUP_REQUEST_TIMEOUT_MULTIPLE = 10;
|
|
43
43
|
const TURN_TERMINAL_SETTLEMENT_TIMEOUT_MS = 12e4;
|
|
44
44
|
const TURN_FINALIZE_DRAIN_ABORT_GRACE_MS = 5e3;
|
|
45
|
+
const CODEX_APP_SERVER_INITIALIZE_TIMEOUT_MESSAGE = "codex app-server initialize timed out";
|
|
45
46
|
var CodexAppServerStartupError = class extends Error {
|
|
46
47
|
constructor(reason, message = reason === "timed_out" ? "codex app-server startup timed out" : "codex app-server startup aborted") {
|
|
47
48
|
super(message);
|
|
@@ -50,6 +51,10 @@ var CodexAppServerStartupError = class extends Error {
|
|
|
50
51
|
this.name = "CodexAppServerStartupError";
|
|
51
52
|
}
|
|
52
53
|
};
|
|
54
|
+
function buildCodexAppServerInitializeTimeoutError(client) {
|
|
55
|
+
const stderr = client?.getStderrDiagnostic();
|
|
56
|
+
return new CodexAppServerStartupError("timed_out", stderr ? `${CODEX_APP_SERVER_INITIALIZE_TIMEOUT_MESSAGE}; stderr=${JSON.stringify(stderr)}` : CODEX_APP_SERVER_INITIALIZE_TIMEOUT_MESSAGE);
|
|
57
|
+
}
|
|
53
58
|
function isCodexAppServerStartupError(error, reason) {
|
|
54
59
|
const cause = codexPrewriteRejectionCause(error);
|
|
55
60
|
return cause instanceof Error && "code" in cause && cause.code === "CODEX_APP_SERVER_STARTUP_CANCELLED" && "reason" in cause && (cause.reason === "aborted" || cause.reason === "timed_out") && (reason === void 0 || cause.reason === reason);
|
|
@@ -141,7 +146,7 @@ async function prepareOwnedServiceParent(params) {
|
|
|
141
146
|
await ensureRealDirectoryTree(params.ownershipRoot, params.targetParent, "Computer Use service parent");
|
|
142
147
|
await assertServicePathParents(params.ownershipRoot, params.targetParent, false);
|
|
143
148
|
const [rootIdentity, parentIdentity] = await Promise.all([readRealDirectoryIdentity(params.ownershipRoot, "Computer Use ownership root"), readRealDirectoryIdentity(params.targetParent, "Computer Use service parent")]);
|
|
144
|
-
assertPathAtOrInside(rootIdentity.realPath, parentIdentity.realPath, "
|
|
149
|
+
assertPathAtOrInside(rootIdentity.realPath, parentIdentity.realPath, "resolved Computer Use service parent");
|
|
145
150
|
return parentIdentity;
|
|
146
151
|
}
|
|
147
152
|
async function assertOwnedCodexHomePath(params) {
|
|
@@ -238,39 +243,20 @@ async function ensureCodexComputerUseSharedPluginCache(params) {
|
|
|
238
243
|
const physicalCacheRoot = path.dirname(physicalCachePath);
|
|
239
244
|
const stagingRoot = await fs$1.mkdtemp(path.join(physicalCacheRoot, `.${cacheName}.staging-`));
|
|
240
245
|
const stagedPath = path.join(stagingRoot, cacheName);
|
|
241
|
-
const backupPath = path.join(physicalCacheRoot, `.${cacheName}.backup-${process.pid}-${Date.now()}`);
|
|
242
|
-
let backupCreated = false;
|
|
243
246
|
try {
|
|
244
247
|
const physicalSourceRoot = await fs$1.realpath(sourcePluginRoot);
|
|
245
248
|
await fs$1.cp(physicalSourceRoot, stagedPath, { recursive: true });
|
|
246
|
-
await waitForCodexDesktopGeneration();
|
|
247
249
|
if (ownedParent) await assertDirectoryIdentityStable(ownedParent, "Computer Use plugin cache parent");
|
|
248
250
|
if (stat) {
|
|
249
251
|
params.assertCurrent?.();
|
|
250
|
-
await fs$1.
|
|
251
|
-
backupCreated = true;
|
|
252
|
-
}
|
|
253
|
-
try {
|
|
254
|
-
if (ownedParent) await assertDirectoryIdentityStable(ownedParent, "Computer Use plugin cache parent");
|
|
255
|
-
params.assertCurrent?.();
|
|
256
|
-
await fs$1.rename(stagedPath, physicalCachePath);
|
|
257
|
-
} catch (error) {
|
|
258
|
-
if (backupCreated) try {
|
|
259
|
-
if (ownedParent) await assertDirectoryIdentityStable(ownedParent, "Computer Use plugin cache parent");
|
|
260
|
-
await fs$1.rename(backupPath, physicalCachePath);
|
|
261
|
-
backupCreated = false;
|
|
262
|
-
} catch (restoreError) {
|
|
263
|
-
throw new Error(`Failed to install Computer Use cache ${cachePath} and restore its prior copy: ${String(error)}`, { cause: restoreError });
|
|
264
|
-
}
|
|
265
|
-
throw error;
|
|
266
|
-
}
|
|
267
|
-
if (backupCreated) {
|
|
268
|
-
if (ownedParent) await assertDirectoryIdentityStable(ownedParent, "Computer Use plugin cache parent");
|
|
269
|
-
await fs$1.rm(backupPath, {
|
|
252
|
+
await fs$1.rm(physicalCachePath, {
|
|
270
253
|
recursive: true,
|
|
271
254
|
force: true
|
|
272
255
|
});
|
|
256
|
+
if (ownedParent) await assertDirectoryIdentityStable(ownedParent, "Computer Use plugin cache parent");
|
|
273
257
|
}
|
|
258
|
+
params.assertCurrent?.();
|
|
259
|
+
await fs$1.rename(stagedPath, physicalCachePath);
|
|
274
260
|
} finally {
|
|
275
261
|
if (!ownedParent || await directoryIdentityIsStable(ownedParent)) await fs$1.rm(stagingRoot, {
|
|
276
262
|
recursive: true,
|
|
@@ -456,11 +442,7 @@ async function ensureCodexManagedBundledMarketplace(params) {
|
|
|
456
442
|
const physicalTargetPath = path.join(parent.realPath, MARKETPLACE_NAME);
|
|
457
443
|
await assertNotSymlink(physicalTargetPath, "managed bundled marketplace");
|
|
458
444
|
const active = activeInstalls$1.get(physicalTargetPath);
|
|
459
|
-
if (active)
|
|
460
|
-
if (active.sourcePath === source.bundledMarketplacePath) return await active.promise;
|
|
461
|
-
await active.promise.catch(() => void 0);
|
|
462
|
-
return await ensureCodexManagedBundledMarketplace(params);
|
|
463
|
-
}
|
|
445
|
+
if (active) return await active;
|
|
464
446
|
const install = publishManagedWrapper({
|
|
465
447
|
parent,
|
|
466
448
|
physicalTargetPath,
|
|
@@ -470,23 +452,17 @@ async function ensureCodexManagedBundledMarketplace(params) {
|
|
|
470
452
|
ownershipCandidates: params.ownershipCandidates ?? candidates,
|
|
471
453
|
assertCurrent: params.assertCurrent
|
|
472
454
|
});
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
if (activeInstalls$1.get(physicalTargetPath) === activeEntry) activeInstalls$1.delete(physicalTargetPath);
|
|
480
|
-
};
|
|
481
|
-
install.then(clearActive, clearActive);
|
|
482
|
-
return await install;
|
|
455
|
+
activeInstalls$1.set(physicalTargetPath, install);
|
|
456
|
+
try {
|
|
457
|
+
return await install;
|
|
458
|
+
} finally {
|
|
459
|
+
activeInstalls$1.delete(physicalTargetPath);
|
|
460
|
+
}
|
|
483
461
|
}
|
|
484
462
|
async function publishManagedWrapper(params) {
|
|
485
463
|
const { parent, physicalTargetPath, targetPath, source, ownershipCandidates, assertCurrent } = params;
|
|
486
464
|
if (await wrapperMatches(physicalTargetPath, source.bundledMarketplacePath, params.unifiedRuntime)) return targetPath;
|
|
487
465
|
const stagingPath = await fs$1.mkdtemp(path.join(parent.realPath, `.${MARKETPLACE_NAME}.staging-`));
|
|
488
|
-
const backupPath = path.join(parent.realPath, `.${MARKETPLACE_NAME}.backup-${process.pid}-${Date.now()}`);
|
|
489
|
-
let backupCreated = false;
|
|
490
466
|
try {
|
|
491
467
|
const manifestParent = path.join(stagingPath, ".agents", "plugins");
|
|
492
468
|
await fs$1.mkdir(manifestParent, {
|
|
@@ -504,9 +480,6 @@ async function publishManagedWrapper(params) {
|
|
|
504
480
|
}
|
|
505
481
|
await fs$1.writeFile(path.join(stagingPath, UNIFIED_SOURCE_FINGERPRINT), params.unifiedRuntime.sourceFingerprint, { mode: 384 });
|
|
506
482
|
} else await fs$1.symlink(path.join(source.bundledMarketplacePath, "plugins"), path.join(stagingPath, "plugins"));
|
|
507
|
-
await waitForCodexDesktopGeneration();
|
|
508
|
-
assertCurrent?.();
|
|
509
|
-
await assertDirectoryIdentityStable(parent, "managed bundled marketplace parent");
|
|
510
483
|
const existing = await fs$1.lstat(physicalTargetPath).catch((error) => {
|
|
511
484
|
if (extractErrorCode(error) === "ENOENT") return;
|
|
512
485
|
throw error;
|
|
@@ -514,32 +487,14 @@ async function publishManagedWrapper(params) {
|
|
|
514
487
|
if (existing && !existing.isDirectory()) throw new Error(`Managed bundled marketplace must be a real directory: ${targetPath}`);
|
|
515
488
|
if (existing && !await wrapperMatchesAnySource(physicalTargetPath, ownershipCandidates)) throw new Error(`Refusing to replace an unowned bundled marketplace directory: ${targetPath}`);
|
|
516
489
|
if (existing) {
|
|
517
|
-
assertCurrent?.();
|
|
518
|
-
await fs$1.rename(physicalTargetPath, backupPath);
|
|
519
|
-
backupCreated = true;
|
|
520
490
|
await assertDirectoryIdentityStable(parent, "managed bundled marketplace parent");
|
|
491
|
+
assertCurrent?.();
|
|
492
|
+
await fs$1.rm(physicalTargetPath, { recursive: true });
|
|
521
493
|
}
|
|
494
|
+
await assertDirectoryIdentityStable(parent, "managed bundled marketplace parent");
|
|
522
495
|
assertCurrent?.();
|
|
523
496
|
await fs$1.rename(stagingPath, physicalTargetPath);
|
|
524
|
-
await assertDirectoryIdentityStable(parent, "managed bundled marketplace parent");
|
|
525
|
-
if (backupCreated) {
|
|
526
|
-
await fs$1.rm(backupPath, { recursive: true });
|
|
527
|
-
backupCreated = false;
|
|
528
|
-
}
|
|
529
497
|
return targetPath;
|
|
530
|
-
} catch (error) {
|
|
531
|
-
if (backupCreated) try {
|
|
532
|
-
await assertDirectoryIdentityStable(parent, "managed bundled marketplace parent");
|
|
533
|
-
if (await fs$1.lstat(physicalTargetPath).catch(() => void 0)) {
|
|
534
|
-
if (!await wrapperOwnedBySource(physicalTargetPath, source.bundledMarketplacePath)) throw new Error("managed bundled marketplace replacement is no longer owned", { cause: error });
|
|
535
|
-
await fs$1.rm(physicalTargetPath, { recursive: true });
|
|
536
|
-
}
|
|
537
|
-
await fs$1.rename(backupPath, physicalTargetPath);
|
|
538
|
-
backupCreated = false;
|
|
539
|
-
} catch (restoreError) {
|
|
540
|
-
throw new Error(`Failed to restore the prior managed bundled marketplace: ${String(error)}`, { cause: restoreError });
|
|
541
|
-
}
|
|
542
|
-
throw error;
|
|
543
498
|
} finally {
|
|
544
499
|
if (await directoryIdentityIsStable(parent)) await fs$1.rm(stagingPath, {
|
|
545
500
|
recursive: true,
|
|
@@ -646,13 +601,8 @@ async function ensureCodexComputerUseServiceApp(params) {
|
|
|
646
601
|
targetPath
|
|
647
602
|
});
|
|
648
603
|
const candidates = params.sourceAppCandidates ?? resolveMacOSDesktopCodexComputerUseServiceAppCandidates(platform, params.appServerCommand);
|
|
649
|
-
const syncKey = [targetPath, ...candidates].join("\0");
|
|
650
604
|
const active = activeInstalls.get(targetPath);
|
|
651
|
-
if (active)
|
|
652
|
-
if (active.syncKey === syncKey) return await active.promise;
|
|
653
|
-
await active.promise.catch(() => void 0);
|
|
654
|
-
return await ensureCodexComputerUseServiceApp(params);
|
|
655
|
-
}
|
|
605
|
+
if (active) return await active;
|
|
656
606
|
const install = ensureCodexComputerUseServiceAppOnce({
|
|
657
607
|
...params,
|
|
658
608
|
codexHome,
|
|
@@ -661,16 +611,12 @@ async function ensureCodexComputerUseServiceApp(params) {
|
|
|
661
611
|
targetPath,
|
|
662
612
|
sourceAppCandidates: candidates
|
|
663
613
|
});
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
if (activeInstalls.get(targetPath) === activeEntry) activeInstalls.delete(targetPath);
|
|
671
|
-
};
|
|
672
|
-
install.then(clearActive, clearActive);
|
|
673
|
-
return await install;
|
|
614
|
+
activeInstalls.set(targetPath, install);
|
|
615
|
+
try {
|
|
616
|
+
return await install;
|
|
617
|
+
} finally {
|
|
618
|
+
activeInstalls.delete(targetPath);
|
|
619
|
+
}
|
|
674
620
|
}
|
|
675
621
|
async function ensureCodexComputerUseServiceAppOnce(params) {
|
|
676
622
|
const inspectServiceApp = params.inspectServiceApp ?? inspectTrustedServiceApp;
|
|
@@ -695,30 +641,15 @@ async function ensureCodexComputerUseServiceAppOnce(params) {
|
|
|
695
641
|
});
|
|
696
642
|
const operationTargetPath = path.join(ownedParent.realPath, SERVICE_APP_NAME);
|
|
697
643
|
await assertNotSymlink(operationTargetPath, "Computer Use service target");
|
|
698
|
-
const
|
|
699
|
-
|
|
644
|
+
const targetExisted = await pathExists$1(operationTargetPath);
|
|
645
|
+
const initialIdentity = await inspectServiceApp(operationTargetPath);
|
|
646
|
+
if (initialIdentity && identitiesMatch(initialIdentity, sourceIdentity)) return alreadyCurrent;
|
|
700
647
|
await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
|
|
701
648
|
const stagingRoot = await fs$1.mkdtemp(path.join(ownedParent.realPath, ".service-app.staging-"));
|
|
702
649
|
const stagingRootIdentity = await readRealDirectoryIdentity(stagingRoot, "Computer Use service staging directory");
|
|
703
650
|
const stagedPath = path.join(stagingRoot, SERVICE_APP_NAME);
|
|
704
651
|
const backupPath = path.join(ownedParent.realPath, `.service-app.backup-${process.pid}-${Date.now()}`);
|
|
705
652
|
let backupCreated = false;
|
|
706
|
-
const restoreBackup = async () => {
|
|
707
|
-
await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
|
|
708
|
-
await fs$1.rename(backupPath, operationTargetPath);
|
|
709
|
-
await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
|
|
710
|
-
backupCreated = false;
|
|
711
|
-
};
|
|
712
|
-
const removeBackup = async () => {
|
|
713
|
-
await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
|
|
714
|
-
await assertNotSymlink(backupPath, "Computer Use service backup");
|
|
715
|
-
await fs$1.rm(backupPath, {
|
|
716
|
-
recursive: true,
|
|
717
|
-
force: true
|
|
718
|
-
});
|
|
719
|
-
await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
|
|
720
|
-
backupCreated = false;
|
|
721
|
-
};
|
|
722
653
|
try {
|
|
723
654
|
await (params.copyServiceApp ?? copyServiceAppWithDitto)(sourcePath, stagedPath);
|
|
724
655
|
await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
|
|
@@ -726,69 +657,42 @@ async function ensureCodexComputerUseServiceAppOnce(params) {
|
|
|
726
657
|
await assertNotSymlink(stagedPath, "Copied Computer Use service app");
|
|
727
658
|
const stagedIdentity = await inspectServiceApp(stagedPath);
|
|
728
659
|
if (!stagedIdentity || !identitiesMatch(stagedIdentity, sourceIdentity)) throw new Error(`Copied Computer Use service app at ${stagedPath} does not match its selected signed source.`);
|
|
729
|
-
const stagedSnapshot = await readServiceAppSnapshot(stagedPath, inspectServiceApp);
|
|
730
|
-
const currentSourceIdentity = await inspectServiceApp(sourcePath);
|
|
731
|
-
await waitForCodexDesktopGeneration();
|
|
732
660
|
await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
|
|
733
661
|
await assertDirectoryIdentityStable(stagingRootIdentity, "Computer Use service staging directory");
|
|
734
|
-
if (!currentSourceIdentity || !identitiesMatch(currentSourceIdentity, sourceIdentity)) throw new Error("Selected Computer Use service source changed during refresh.");
|
|
735
662
|
await assertNotSymlink(operationTargetPath, "Computer Use service target");
|
|
736
663
|
if (await pathExists$1(operationTargetPath)) {
|
|
737
664
|
await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
|
|
738
665
|
params.assertCurrent?.();
|
|
739
666
|
await fs$1.rename(operationTargetPath, backupPath);
|
|
740
|
-
await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
|
|
741
667
|
backupCreated = true;
|
|
742
|
-
const movedTarget = await readServiceAppSnapshot(backupPath, inspectServiceApp);
|
|
743
|
-
if (movedTarget.identity && identitiesMatch(movedTarget.identity, sourceIdentity)) {
|
|
744
|
-
await restoreBackup();
|
|
745
|
-
return alreadyCurrent;
|
|
746
|
-
}
|
|
747
|
-
if (!snapshotsMatch(initialTarget, movedTarget)) {
|
|
748
|
-
await restoreBackup();
|
|
749
|
-
throw new Error("Computer Use service target changed to an unexpected generation during refresh.");
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
try {
|
|
753
|
-
await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
|
|
754
|
-
params.assertCurrent?.();
|
|
755
|
-
await fs$1.rename(stagedPath, operationTargetPath);
|
|
756
|
-
await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
|
|
757
|
-
} catch (error) {
|
|
758
|
-
await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
|
|
759
|
-
await assertNotSymlink(operationTargetPath, "Computer Use service target");
|
|
760
|
-
const winnerIdentity = await inspectServiceApp(operationTargetPath);
|
|
761
|
-
if (!winnerIdentity || !identitiesMatch(winnerIdentity, sourceIdentity)) {
|
|
762
|
-
if (backupCreated && !await pathExists$1(operationTargetPath)) await restoreBackup();
|
|
763
|
-
throw error;
|
|
764
|
-
}
|
|
765
|
-
if (backupCreated) await removeBackup();
|
|
766
|
-
return alreadyCurrent;
|
|
767
668
|
}
|
|
669
|
+
await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
|
|
670
|
+
params.assertCurrent?.();
|
|
671
|
+
await fs$1.rename(stagedPath, operationTargetPath);
|
|
768
672
|
await assertNotSymlink(operationTargetPath, "Installed Computer Use service app");
|
|
769
|
-
const
|
|
770
|
-
if (!
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
});
|
|
777
|
-
await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
|
|
778
|
-
if (backupCreated) {
|
|
779
|
-
await fs$1.rename(backupPath, operationTargetPath);
|
|
780
|
-
await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
|
|
781
|
-
backupCreated = false;
|
|
782
|
-
}
|
|
783
|
-
}
|
|
673
|
+
const installedIdentity = await inspectServiceApp(operationTargetPath);
|
|
674
|
+
if (!installedIdentity || !identitiesMatch(installedIdentity, sourceIdentity)) {
|
|
675
|
+
await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
|
|
676
|
+
await fs$1.rm(operationTargetPath, {
|
|
677
|
+
recursive: true,
|
|
678
|
+
force: true
|
|
679
|
+
});
|
|
784
680
|
throw new Error("Installed Computer Use service app failed post-install identity verification.");
|
|
785
681
|
}
|
|
786
|
-
if (backupCreated)
|
|
682
|
+
if (backupCreated) {
|
|
683
|
+
await assertDirectoryIdentityStable(ownedParent, SERVICE_PARENT_LABEL);
|
|
684
|
+
await assertNotSymlink(backupPath, "Computer Use service backup");
|
|
685
|
+
await fs$1.rm(backupPath, {
|
|
686
|
+
recursive: true,
|
|
687
|
+
force: true
|
|
688
|
+
});
|
|
689
|
+
backupCreated = false;
|
|
690
|
+
}
|
|
787
691
|
return {
|
|
788
692
|
...alreadyCurrent,
|
|
789
|
-
status:
|
|
693
|
+
status: targetExisted ? "refreshed" : "installed",
|
|
790
694
|
changed: true,
|
|
791
|
-
...
|
|
695
|
+
...initialIdentity ? { previousBuild: initialIdentity.build } : {}
|
|
792
696
|
};
|
|
793
697
|
} catch (error) {
|
|
794
698
|
if (backupCreated && await directoryIdentityIsStable(ownedParent) && !await pathExists$1(operationTargetPath)) {
|
|
@@ -816,32 +720,6 @@ async function findUsableServiceApp(candidates, inspectServiceApp) {
|
|
|
816
720
|
};
|
|
817
721
|
}
|
|
818
722
|
}
|
|
819
|
-
async function readServiceAppSnapshot(appPath, inspectServiceApp) {
|
|
820
|
-
if (!await pathExists$1(appPath)) return { exists: false };
|
|
821
|
-
return {
|
|
822
|
-
exists: true,
|
|
823
|
-
identity: await inspectServiceApp(appPath),
|
|
824
|
-
filesystemKey: await readServiceAppFilesystemKey(appPath)
|
|
825
|
-
};
|
|
826
|
-
}
|
|
827
|
-
async function readServiceAppFilesystemKey(appPath) {
|
|
828
|
-
const paths = [
|
|
829
|
-
appPath,
|
|
830
|
-
path.join(appPath, "Contents", "Info.plist"),
|
|
831
|
-
path.join(appPath, CLIENT_RELATIVE_PATH)
|
|
832
|
-
];
|
|
833
|
-
return (await Promise.all(paths.map((entryPath) => fs$1.stat(entryPath).then((stat) => `${stat.dev}:${stat.ino}:${stat.size}:${stat.mtimeMs}`, () => "missing")))).join("|");
|
|
834
|
-
}
|
|
835
|
-
function snapshotsMatch(left, right) {
|
|
836
|
-
if (left.exists !== right.exists) return false;
|
|
837
|
-
if (!left.exists) return true;
|
|
838
|
-
if (left.filesystemKey && right.filesystemKey && left.filesystemKey !== right.filesystemKey) return false;
|
|
839
|
-
if (left.identity || right.identity) return Boolean(left.identity && right.identity && identitiesMatch(left.identity, right.identity));
|
|
840
|
-
return left.filesystemKey !== void 0 && left.filesystemKey === right.filesystemKey;
|
|
841
|
-
}
|
|
842
|
-
function filesystemSnapshotsMatch(left, right) {
|
|
843
|
-
return Boolean(left.exists && right.exists && left.filesystemKey && left.filesystemKey === right.filesystemKey);
|
|
844
|
-
}
|
|
845
723
|
function identitiesMatch(left, right) {
|
|
846
724
|
return left.bundleId === right.bundleId && left.version === right.version && left.build === right.build && left.cdHash === right.cdHash && left.teamId === right.teamId && left.clientBundleId === right.clientBundleId && left.clientCdHash === right.clientCdHash && left.clientTeamId === right.clientTeamId;
|
|
847
725
|
}
|
|
@@ -957,7 +835,7 @@ async function bridgeCodexAppServerStartOptions(params) {
|
|
|
957
835
|
return withClearedEnvironmentVariables(scopedStartOptions, CODEX_APP_SERVER_PREPARED_AUTH_ENV_VARS);
|
|
958
836
|
}
|
|
959
837
|
if (params.authProfileId === null) return scopeStartOptions();
|
|
960
|
-
const store = resolveCodexAppServerAuthProfileStore({
|
|
838
|
+
const store = await resolveCodexAppServerAuthProfileStore({
|
|
961
839
|
agentDir: params.agentDir,
|
|
962
840
|
authProfileId: params.authProfileId,
|
|
963
841
|
authProfileStore: params.authProfileStore,
|
|
@@ -976,7 +854,10 @@ async function bridgeCodexAppServerStartOptions(params) {
|
|
|
976
854
|
}) ? withClearedEnvironmentVariables(scopedStartOptions, CODEX_APP_SERVER_API_KEY_ENV_VARS) : scopedStartOptions;
|
|
977
855
|
}
|
|
978
856
|
function assertNoUnimportedAgentCodexAuthFile(params) {
|
|
979
|
-
if (params.authRequirement === "api-key"
|
|
857
|
+
if ((params.authRequirement === "api-key" || params.authRequirement === "environment-api-key") && resolveCodexAppServerFallbackApiKeyCacheKey({
|
|
858
|
+
startOptions: params.startOptions,
|
|
859
|
+
allowNativeAuthFile: params.authRequirement === "api-key"
|
|
860
|
+
})) return;
|
|
980
861
|
if (params.startOptions.transport !== "stdio" || params.startOptions.homeScope === "user") return;
|
|
981
862
|
const codexHome = resolveCodexAppServerHomeDir(params.agentDir);
|
|
982
863
|
const authPath = path.join(codexHome, CODEX_AUTH_JSON_FILENAME);
|
|
@@ -984,9 +865,9 @@ function assertNoUnimportedAgentCodexAuthFile(params) {
|
|
|
984
865
|
const targetAgentId = params.agentId?.trim() || "<agent-id>";
|
|
985
866
|
throw new AgentHarnessPreflightError(`A Codex auth file exists at ${authPath}, but agent-scoped Codex runs use OpenClaw's auth store and do not read that file. Preview only that credential import with \`openclaw migrate plan codex --from <codex-home> --agent ${targetAgentId} --include-secrets --item auth:openai\`, then run \`openclaw migrate apply codex --from <codex-home> --agent ${targetAgentId} --include-secrets --item auth:openai --yes\`. If the plan finds no credentials, remove the stale auth file.`);
|
|
986
867
|
}
|
|
987
|
-
function resolveCodexAppServerAuthProfile(params) {
|
|
868
|
+
async function resolveCodexAppServerAuthProfile(params) {
|
|
988
869
|
const agentDir = params.agentDir?.trim() || resolveDefaultAgentDir(params.config ?? {});
|
|
989
|
-
const store = resolveCodexAppServerAuthProfileStore({
|
|
870
|
+
const store = await resolveCodexAppServerAuthProfileStore({
|
|
990
871
|
...params,
|
|
991
872
|
agentDir
|
|
992
873
|
});
|
|
@@ -1006,7 +887,7 @@ function resolveCodexAppServerAuthProfile(params) {
|
|
|
1006
887
|
}
|
|
1007
888
|
/** Resolves prepared profile login material once so cache identity and RPC login cannot drift. */
|
|
1008
889
|
async function resolveCodexAppServerPreparedAuthProfileSnapshot(params) {
|
|
1009
|
-
const profile = resolveCodexAppServerAuthProfile(params);
|
|
890
|
+
const profile = await resolveCodexAppServerAuthProfile(params);
|
|
1010
891
|
if (!profile) return;
|
|
1011
892
|
const { agentDir, store, profileId, credential } = profile;
|
|
1012
893
|
if (isCodexResponsesOAuthCredential(credential)) return {
|
|
@@ -1074,7 +955,7 @@ async function resolveCodexAppServerPreparedAuthHandoff(params) {
|
|
|
1074
955
|
}
|
|
1075
956
|
const authProfileId = params.authProfileId?.trim() || void 0;
|
|
1076
957
|
if (authProfileId && !params.authProfileStore.profiles[authProfileId]) throw new CodexAppServerAuthProfileUnavailableError(formatCodexAuthProfileUnavailableMessage(authProfileId));
|
|
1077
|
-
const nativeAuthProfile = isCodexAppServerNativeAuthProfile({
|
|
958
|
+
const nativeAuthProfile = await isCodexAppServerNativeAuthProfile({
|
|
1078
959
|
authProfileId,
|
|
1079
960
|
authProfileStore: params.authProfileStore,
|
|
1080
961
|
agentDir: params.agentDir,
|
|
@@ -1102,7 +983,7 @@ async function resolveCodexAppServerPreparedAuthHandoff(params) {
|
|
|
1102
983
|
};
|
|
1103
984
|
}
|
|
1104
985
|
async function resolveCodexAppServerAuthAccountCacheKey(params) {
|
|
1105
|
-
const profile = resolveCodexAppServerAuthProfile(params);
|
|
986
|
+
const profile = await resolveCodexAppServerAuthProfile(params);
|
|
1106
987
|
if (!profile) return;
|
|
1107
988
|
const { agentDir, store, profileId, credential } = profile;
|
|
1108
989
|
const accountId = resolveChatgptAccountId(profileId, credential);
|
|
@@ -1148,12 +1029,7 @@ async function reconcileCodexComputerUseStartArtifacts(params) {
|
|
|
1148
1029
|
else activeComputerUseArtifactReconciliations.delete(key);
|
|
1149
1030
|
activeComputerUseArtifactReconciliations.set(key, owner);
|
|
1150
1031
|
owner.active += 1;
|
|
1151
|
-
const
|
|
1152
|
-
if (epoch !== void 0 && (owner.latestEpoch === void 0 || epoch > owner.latestEpoch)) owner.latestEpoch = epoch;
|
|
1153
|
-
const assertCurrent = () => {
|
|
1154
|
-
params.assertCurrent?.();
|
|
1155
|
-
if (epoch !== void 0 && owner.latestEpoch !== epoch) throw new Error("Codex Computer Use artifact reconciliation was superseded.");
|
|
1156
|
-
};
|
|
1032
|
+
const assertCurrent = () => params.assertCurrent?.();
|
|
1157
1033
|
const operation = owner.tail.then(async () => {
|
|
1158
1034
|
assertCurrent();
|
|
1159
1035
|
const appliedCacheBinding = await reconcileCodexComputerUseStartArtifactsOnce({
|
|
@@ -1165,13 +1041,11 @@ async function reconcileCodexComputerUseStartArtifacts(params) {
|
|
|
1165
1041
|
assertCurrent();
|
|
1166
1042
|
owner.appliedCacheBinding = appliedCacheBinding;
|
|
1167
1043
|
});
|
|
1168
|
-
|
|
1169
|
-
owner.tail = settled;
|
|
1044
|
+
owner.tail = operation.catch(() => void 0);
|
|
1170
1045
|
try {
|
|
1171
1046
|
await operation;
|
|
1172
1047
|
} finally {
|
|
1173
|
-
owner.active
|
|
1174
|
-
if (owner.active === 0 && owner.latestEpoch === void 0 && activeComputerUseArtifactReconciliations.get(key) === owner && owner.tail === settled) activeComputerUseArtifactReconciliations.delete(key);
|
|
1048
|
+
owner.active -= 1;
|
|
1175
1049
|
pruneComputerUseArtifactOwners();
|
|
1176
1050
|
}
|
|
1177
1051
|
}
|
|
@@ -1265,9 +1139,14 @@ var CodexComputerUseCandidateArtifactsUnavailableError = class extends Error {
|
|
|
1265
1139
|
}
|
|
1266
1140
|
};
|
|
1267
1141
|
async function applyCodexAppServerAuthProfile(params) {
|
|
1142
|
+
const withCurrent = async (write) => {
|
|
1143
|
+
await params.assertCurrentAsync?.();
|
|
1144
|
+
params.assertCurrent?.();
|
|
1145
|
+
write();
|
|
1146
|
+
};
|
|
1268
1147
|
params.assertCurrent?.();
|
|
1269
1148
|
if (!params.preparedAuth && params.authProfileId === null) {
|
|
1270
|
-
await assertNativeCodexAccountMatchesRoute(params.client, params.authRequirement, params.assertCurrent);
|
|
1149
|
+
await assertNativeCodexAccountMatchesRoute(params.client, params.authRequirement, params.assertCurrent, withCurrent);
|
|
1271
1150
|
return;
|
|
1272
1151
|
}
|
|
1273
1152
|
const agentDir = params.agentDir ?? resolveDefaultAgentDir(params.config ?? {});
|
|
@@ -1277,7 +1156,7 @@ async function applyCodexAppServerAuthProfile(params) {
|
|
|
1277
1156
|
} : await resolveCodexAppServerAuthProfileLoginParamsInternal({
|
|
1278
1157
|
agentDir,
|
|
1279
1158
|
authProfileId: params.authProfileId ?? void 0,
|
|
1280
|
-
authProfileStore: resolveCodexAppServerAuthProfileStore({
|
|
1159
|
+
authProfileStore: await resolveCodexAppServerAuthProfileStore({
|
|
1281
1160
|
...params,
|
|
1282
1161
|
agentDir,
|
|
1283
1162
|
authProfileId: params.authProfileId ?? void 0
|
|
@@ -1285,18 +1164,22 @@ async function applyCodexAppServerAuthProfile(params) {
|
|
|
1285
1164
|
config: params.config
|
|
1286
1165
|
});
|
|
1287
1166
|
if (params.authRequirement === "subscription" && loginParams?.type !== "chatgptAuthTokens") throw createCodexAppServerAuthError("Codex subscription auth profile could not produce login credentials. Sign in with `openclaw models auth login --provider openai`, select that profile, then retry.");
|
|
1288
|
-
if (!loginParams && params.authRequirement === "api-key" && params.startOptions?.transport === "stdio") {
|
|
1167
|
+
if (!loginParams && (params.authRequirement === "api-key" || params.authRequirement === "environment-api-key") && params.startOptions?.transport === "stdio") {
|
|
1289
1168
|
const env = resolveCodexAppServerSpawnEnv(params.startOptions, process.env);
|
|
1290
1169
|
loginParams = await resolveCodexAppServerFallbackApiKeyLoginParams({
|
|
1291
1170
|
client: params.client,
|
|
1292
1171
|
env,
|
|
1293
|
-
codexCliAuthEnv: process.env,
|
|
1294
|
-
assertCurrent: params.assertCurrent
|
|
1172
|
+
...params.authRequirement === "api-key" ? { codexCliAuthEnv: process.env } : {},
|
|
1173
|
+
assertCurrent: params.assertCurrent,
|
|
1174
|
+
withCurrent
|
|
1295
1175
|
});
|
|
1296
1176
|
}
|
|
1297
1177
|
if (loginParams) {
|
|
1298
1178
|
try {
|
|
1299
|
-
await params.client.request("account/login/start", loginParams, {
|
|
1179
|
+
await params.client.request("account/login/start", loginParams, {
|
|
1180
|
+
assertCurrent: params.assertCurrent,
|
|
1181
|
+
withCurrent
|
|
1182
|
+
});
|
|
1300
1183
|
} catch (error) {
|
|
1301
1184
|
throw codexPrewriteRejectionCause(error);
|
|
1302
1185
|
}
|
|
@@ -1316,9 +1199,12 @@ async function applyCodexAppServerAuthProfile(params) {
|
|
|
1316
1199
|
* ChatGPT plan. An absent account is left alone because the native home may serve a
|
|
1317
1200
|
* custom model provider that reports no OpenAI account at all.
|
|
1318
1201
|
*/
|
|
1319
|
-
async function assertNativeCodexAccountMatchesRoute(client, authRequirement, assertCurrent) {
|
|
1202
|
+
async function assertNativeCodexAccountMatchesRoute(client, authRequirement, assertCurrent, withCurrent) {
|
|
1320
1203
|
if (!authRequirement) return;
|
|
1321
|
-
const accountType = (await client.request("account/read", { refreshToken: false }, {
|
|
1204
|
+
const accountType = (await client.request("account/read", { refreshToken: false }, {
|
|
1205
|
+
assertCurrent,
|
|
1206
|
+
withCurrent
|
|
1207
|
+
})).account?.type;
|
|
1322
1208
|
if (authRequirement === "subscription") {
|
|
1323
1209
|
if (accountType !== "chatgpt") throw createCodexAppServerAuthError("Codex subscription route requires ChatGPT auth in the native Codex home. Run `codex login` for that home, or use appServer.homeScope=\"agent\" with an OpenClaw OAuth profile, then retry.");
|
|
1324
1210
|
return;
|
|
@@ -1333,7 +1219,7 @@ async function refreshCodexAppServerAuthTokens(params) {
|
|
|
1333
1219
|
const handoffAccountId = params.authHandoff?.chatgptAccountId.trim();
|
|
1334
1220
|
if (previousAccountId && handoffAccountId && previousAccountId !== handoffAccountId) throw codexWorkspaceChangedError("before");
|
|
1335
1221
|
if (previousAccountId) {
|
|
1336
|
-
const store = resolveCodexAppServerAuthProfileStore(params);
|
|
1222
|
+
const store = await resolveCodexAppServerAuthProfileStore(params);
|
|
1337
1223
|
const profileId = resolveCodexAppServerAuthProfileId({
|
|
1338
1224
|
...params,
|
|
1339
1225
|
store
|
|
@@ -1355,7 +1241,7 @@ async function refreshCodexAppServerAuthTokens(params) {
|
|
|
1355
1241
|
};
|
|
1356
1242
|
}
|
|
1357
1243
|
async function resolveCodexAppServerAuthProfileLoginParamsInternal(params) {
|
|
1358
|
-
const store = resolveCodexAppServerAuthProfileStore(params);
|
|
1244
|
+
const store = await resolveCodexAppServerAuthProfileStore(params);
|
|
1359
1245
|
const profileId = resolveCodexAppServerAuthProfileId({
|
|
1360
1246
|
...params,
|
|
1361
1247
|
store
|
|
@@ -1363,7 +1249,7 @@ async function resolveCodexAppServerAuthProfileLoginParamsInternal(params) {
|
|
|
1363
1249
|
if (!profileId) return;
|
|
1364
1250
|
const credential = store.profiles[profileId];
|
|
1365
1251
|
if (!credential) throw new CodexAppServerAuthProfileUnavailableError(formatCodexAuthProfileUnavailableMessage(profileId));
|
|
1366
|
-
if (!isCodexAppServerAuthProvider(credential.provider)) throw new CodexAppServerAuthProfileUnavailableError(`Codex app-server auth profile "${profileId}" must use the
|
|
1252
|
+
if (!isCodexAppServerAuthProvider(credential.provider)) throw new CodexAppServerAuthProfileUnavailableError(`Codex app-server auth profile "${profileId}" must use the OpenAI auth provider; run "openclaw doctor --fix" to migrate legacy provider IDs.`);
|
|
1367
1253
|
const preferStoreCredential = Boolean(params.authProfileStore?.profiles[profileId]);
|
|
1368
1254
|
let loginCredential = credential;
|
|
1369
1255
|
let value;
|
|
@@ -1371,7 +1257,7 @@ async function resolveCodexAppServerAuthProfileLoginParamsInternal(params) {
|
|
|
1371
1257
|
if (credential.type === "api_key" || credential.type === "token") {
|
|
1372
1258
|
value = (await resolveApiKeyForProfile({
|
|
1373
1259
|
cfg: params.config,
|
|
1374
|
-
store: preferStoreCredential ? store :
|
|
1260
|
+
store: preferStoreCredential ? store : await ensureAuthProfileStoreAsync(params.agentDir, {
|
|
1375
1261
|
allowKeychainPrompt: false,
|
|
1376
1262
|
profileId,
|
|
1377
1263
|
config: params.config
|
|
@@ -1396,27 +1282,30 @@ async function resolveCodexAppServerAuthProfileLoginParamsInternal(params) {
|
|
|
1396
1282
|
} : buildChatgptAuthTokensParams(profileId, loginCredential, value);
|
|
1397
1283
|
}
|
|
1398
1284
|
async function resolveCodexAppServerFallbackApiKeyLoginParams(params) {
|
|
1399
|
-
const apiKey = readFirstNonEmptyEnv(params.env, CODEX_APP_SERVER_API_KEY_ENV_VARS) ?? await readCodexCliAuthFileApiKey(params.codexCliAuthEnv);
|
|
1285
|
+
const apiKey = readFirstNonEmptyEnv(params.env, CODEX_APP_SERVER_API_KEY_ENV_VARS) ?? (params.codexCliAuthEnv ? await readCodexCliAuthFileApiKey(params.codexCliAuthEnv) : void 0);
|
|
1400
1286
|
if (!apiKey) return;
|
|
1401
|
-
if ((await params.client.request("account/read", { refreshToken: false }, {
|
|
1287
|
+
if ((await params.client.request("account/read", { refreshToken: false }, {
|
|
1288
|
+
assertCurrent: params.assertCurrent,
|
|
1289
|
+
withCurrent: params.withCurrent
|
|
1290
|
+
})).account) return;
|
|
1402
1291
|
return {
|
|
1403
1292
|
type: "apiKey",
|
|
1404
1293
|
apiKey
|
|
1405
1294
|
};
|
|
1406
1295
|
}
|
|
1407
1296
|
async function resolveOAuthCredentialForCodexAppServer(profileId, credential, params) {
|
|
1408
|
-
const ownerAgentDir =
|
|
1297
|
+
const ownerAgentDir = await resolvePersistedAuthProfileOwnerAgentDirAsync({
|
|
1409
1298
|
agentDir: params.agentDir,
|
|
1410
1299
|
profileId
|
|
1411
1300
|
});
|
|
1412
|
-
const persistedCredential =
|
|
1301
|
+
const persistedCredential = await findPersistedAuthProfileCredentialAsync({
|
|
1413
1302
|
agentDir: ownerAgentDir,
|
|
1414
1303
|
profileId
|
|
1415
1304
|
});
|
|
1416
1305
|
const persistedProfile = params.store.runtimePersistedProfileIds?.includes(profileId);
|
|
1417
1306
|
const useScopedCredential = params.preferStoreCredential && (!persistedProfile || persistedCredential?.type === "oauth" && isCodexAppServerAuthProvider(persistedCredential.provider) && !isDeepStrictEqual(persistedCredential, credential) && !hasMatchingOAuthIdentity(persistedCredential, credential));
|
|
1418
1307
|
if (params.preferStoreCredential && persistedProfile && (persistedCredential?.type !== "oauth" || !isCodexAppServerAuthProvider(persistedCredential.provider))) throw new CodexAppServerAuthProfileUnavailableError(`Codex app-server auth profile "${profileId}" is no longer an OpenAI OAuth credential in its persisted OpenClaw store. Run "openclaw doctor" to inspect credential ownership, or select an existing OpenAI profile.`);
|
|
1419
|
-
const store = useScopedCredential ? params.store : resolveCodexAppServerAuthProfileStore({
|
|
1308
|
+
const store = useScopedCredential ? params.store : await resolveCodexAppServerAuthProfileStore({
|
|
1420
1309
|
agentDir: ownerAgentDir,
|
|
1421
1310
|
authProfileId: profileId,
|
|
1422
1311
|
config: params.config
|
|
@@ -1504,14 +1393,16 @@ async function resolveScopedOAuthCredential(params) {
|
|
|
1504
1393
|
cfg: params.config
|
|
1505
1394
|
});
|
|
1506
1395
|
if (!refreshed?.access?.trim()) throw new Error(`Codex app-server auth profile "${params.profileId}" could not refresh. Sign in again with OpenClaw, then retry.`);
|
|
1507
|
-
assertCodexOAuthRefreshWorkspace(params.profileId, refreshed,
|
|
1396
|
+
assertCodexOAuthRefreshWorkspace(params.profileId, refreshed, resolveOpenAICodexAuthIdentity(credential).accountId?.trim());
|
|
1508
1397
|
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.`);
|
|
1509
1398
|
params.store.profiles[params.profileId] = refreshed;
|
|
1510
1399
|
return refreshed;
|
|
1511
1400
|
})();
|
|
1512
1401
|
storeRefreshes.set(params.profileId, refresh);
|
|
1513
1402
|
try {
|
|
1514
|
-
|
|
1403
|
+
const refreshed = await refresh;
|
|
1404
|
+
assertCodexOAuthRefreshWorkspace(params.profileId, refreshed, params.expectedAccountId);
|
|
1405
|
+
return refreshed;
|
|
1515
1406
|
} finally {
|
|
1516
1407
|
if (storeRefreshes.get(params.profileId) === refresh) storeRefreshes.delete(params.profileId);
|
|
1517
1408
|
}
|
|
@@ -1560,6 +1451,62 @@ function resolveExplicitChatgptAccountId(credential) {
|
|
|
1560
1451
|
return "accountId" in credential && typeof credential.accountId === "string" ? credential.accountId.trim() || void 0 : void 0;
|
|
1561
1452
|
}
|
|
1562
1453
|
//#endregion
|
|
1454
|
+
//#region extensions/codex/src/app-server/client-fork-settings.ts
|
|
1455
|
+
const clients = defineCodexBuildState("openclaw.codexClientForkSettings", () => /* @__PURE__ */ new WeakMap())();
|
|
1456
|
+
/** The physical client owner initializes and disposes these nonpersistent snapshots. */
|
|
1457
|
+
function initializeCodexClientForkSettings(client) {
|
|
1458
|
+
clients.set(client, /* @__PURE__ */ new Map());
|
|
1459
|
+
}
|
|
1460
|
+
function forgetCodexClientForkSettings(client, threadId) {
|
|
1461
|
+
if (threadId === void 0) clients.delete(client);
|
|
1462
|
+
else clients.get(client)?.delete(threadId);
|
|
1463
|
+
}
|
|
1464
|
+
function recordCodexThreadForkSettings(client, threadId, params) {
|
|
1465
|
+
const settings = clients.get(client);
|
|
1466
|
+
if (!settings || settings.has(threadId)) return;
|
|
1467
|
+
const permissions = typeof params.permissions === "string" ? params.permissions : void 0;
|
|
1468
|
+
const thread = {
|
|
1469
|
+
threadId,
|
|
1470
|
+
...params.model !== void 0 ? { model: params.model } : {},
|
|
1471
|
+
...params.modelProvider !== void 0 ? { modelProvider: params.modelProvider } : {},
|
|
1472
|
+
...params.cwd !== void 0 ? { cwd: params.cwd } : {},
|
|
1473
|
+
...params.runtimeWorkspaceRoots !== void 0 ? { runtimeWorkspaceRoots: params.runtimeWorkspaceRoots } : {},
|
|
1474
|
+
...params.approvalPolicy !== void 0 ? { approvalPolicy: params.approvalPolicy } : {},
|
|
1475
|
+
...params.approvalsReviewer !== void 0 ? { approvalsReviewer: params.approvalsReviewer } : {},
|
|
1476
|
+
...params.sandbox !== void 0 ? { sandbox: params.sandbox } : {},
|
|
1477
|
+
...permissions !== void 0 ? { permissions } : {},
|
|
1478
|
+
...params.serviceTier !== void 0 ? { serviceTier: params.serviceTier } : {},
|
|
1479
|
+
...params.config !== void 0 ? { config: params.config } : {},
|
|
1480
|
+
...params.developerInstructions !== void 0 ? { developerInstructions: params.developerInstructions } : {}
|
|
1481
|
+
};
|
|
1482
|
+
settings.set(threadId, { thread });
|
|
1483
|
+
}
|
|
1484
|
+
function recordCodexTurnForkSettings(client, params) {
|
|
1485
|
+
const settings = clients.get(client)?.get(params.threadId);
|
|
1486
|
+
if (settings) settings.turn = {
|
|
1487
|
+
additionalContext: params.additionalContext,
|
|
1488
|
+
cwd: params.cwd,
|
|
1489
|
+
runtimeWorkspaceRoots: params.runtimeWorkspaceRoots,
|
|
1490
|
+
model: params.model,
|
|
1491
|
+
approvalPolicy: params.approvalPolicy,
|
|
1492
|
+
approvalsReviewer: params.approvalsReviewer,
|
|
1493
|
+
sandboxPolicy: params.sandboxPolicy,
|
|
1494
|
+
serviceTier: params.serviceTier,
|
|
1495
|
+
effort: params.effort,
|
|
1496
|
+
personality: params.personality,
|
|
1497
|
+
environments: params.environments,
|
|
1498
|
+
collaborationMode: params.collaborationMode
|
|
1499
|
+
};
|
|
1500
|
+
}
|
|
1501
|
+
function requireCodexThreadForkSettings(client, threadId) {
|
|
1502
|
+
const settings = clients.get(client)?.get(threadId);
|
|
1503
|
+
if (!settings?.turn) throw new Error("Cache-parity session fork requires a parent turn prepared by this OpenClaw runtime. Send a normal message first.");
|
|
1504
|
+
return {
|
|
1505
|
+
...settings,
|
|
1506
|
+
turn: settings.turn
|
|
1507
|
+
};
|
|
1508
|
+
}
|
|
1509
|
+
//#endregion
|
|
1563
1510
|
//#region extensions/codex/src/app-server/client-thread-owner.ts
|
|
1564
1511
|
function createThreadOwnerToken(threadId, onInvalidated) {
|
|
1565
1512
|
const owner = {
|
|
@@ -1627,8 +1574,12 @@ function revertRetainedThreadInstructions(runtime, threadId) {
|
|
|
1627
1574
|
refreshableInstructions: retained.ephemeralPolicy.nativeRefreshableInstructions
|
|
1628
1575
|
};
|
|
1629
1576
|
}
|
|
1630
|
-
function createCodexEphemeralThreadPolicy({ developerInstructions, refreshableInstructions }) {
|
|
1577
|
+
function createCodexEphemeralThreadPolicy({ developerInstructions, refreshableInstructions, config }, nativeConfig) {
|
|
1578
|
+
const limit = config?.model_auto_compact_token_limit ?? nativeConfig?.model_auto_compact_token_limit;
|
|
1579
|
+
const scope = config?.model_auto_compact_token_limit_scope ?? nativeConfig?.model_auto_compact_token_limit_scope ?? "total";
|
|
1631
1580
|
return {
|
|
1581
|
+
...typeof limit === "number" ? { autoCompactTokenLimit: limit } : {},
|
|
1582
|
+
...typeof scope === "string" ? { autoCompactTokenLimitScope: scope } : {},
|
|
1632
1583
|
developerInstructions,
|
|
1633
1584
|
refreshableInstructions,
|
|
1634
1585
|
nativeRefreshableInstructions: refreshableInstructions
|
|
@@ -1707,12 +1658,11 @@ const rateLimitsByClient = defineCodexBuildState("openclaw.codexAppServerRateLim
|
|
|
1707
1658
|
/** Replaces one physical client's cache with an authoritative rate-limit read response. */
|
|
1708
1659
|
function rememberCodexRateLimitsRead(client, value, nowMs = Date.now()) {
|
|
1709
1660
|
if (value !== void 0) {
|
|
1710
|
-
const
|
|
1711
|
-
for (const limitId of readRateLimitIds(value)) revisionsByLimitId[limitId] = (revisionsByLimitId[limitId] ?? 0) + 1;
|
|
1661
|
+
const currentState = rateLimitsByClient.get(client);
|
|
1712
1662
|
rateLimitsByClient.set(client, {
|
|
1713
1663
|
value,
|
|
1714
1664
|
updatedAtMs: nowMs,
|
|
1715
|
-
|
|
1665
|
+
revision: (currentState?.revision ?? 0) + Number(hasCodexRateLimit(value))
|
|
1716
1666
|
});
|
|
1717
1667
|
}
|
|
1718
1668
|
}
|
|
@@ -1726,15 +1676,12 @@ function mergeCodexRateLimitsUpdate(client, value, nowMs = Date.now()) {
|
|
|
1726
1676
|
rateLimitsByClient.set(client, {
|
|
1727
1677
|
value: mergeRateLimitUpdate(current, update),
|
|
1728
1678
|
updatedAtMs: nowMs,
|
|
1729
|
-
|
|
1730
|
-
...currentState?.revisionsByLimitId,
|
|
1731
|
-
[limitId]: (currentState?.revisionsByLimitId[limitId] ?? 0) + 1
|
|
1732
|
-
}
|
|
1679
|
+
revision: (currentState?.revision ?? 0) + Number(limitId === "codex")
|
|
1733
1680
|
});
|
|
1734
1681
|
}
|
|
1735
|
-
/**
|
|
1736
|
-
function readCodexRateLimitsRevision(client
|
|
1737
|
-
return rateLimitsByClient.get(client)?.
|
|
1682
|
+
/** Marker used to trust only primary Codex updates from one turn startup. */
|
|
1683
|
+
function readCodexRateLimitsRevision(client) {
|
|
1684
|
+
return rateLimitsByClient.get(client)?.revision ?? 0;
|
|
1738
1685
|
}
|
|
1739
1686
|
/** Reads one physical client's cached rate-limit payload within the max-age window. */
|
|
1740
1687
|
function readRecentCodexRateLimits(client, options) {
|
|
@@ -1775,15 +1722,13 @@ function mergeRateLimitUpdate(current, update) {
|
|
|
1775
1722
|
...nextByLimitId ? { rateLimitsByLimitId: nextByLimitId } : {}
|
|
1776
1723
|
};
|
|
1777
1724
|
}
|
|
1778
|
-
function
|
|
1779
|
-
if (!isJsonObject(value)) return
|
|
1780
|
-
|
|
1781
|
-
if (isJsonObject(value.
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
}
|
|
1786
|
-
return [...ids];
|
|
1725
|
+
function hasCodexRateLimit(value) {
|
|
1726
|
+
if (!isJsonObject(value)) return false;
|
|
1727
|
+
if (isJsonObject(value.rateLimits) && readLimitId(value.rateLimits) === "codex") return true;
|
|
1728
|
+
if (!isJsonObject(value.rateLimitsByLimitId)) return false;
|
|
1729
|
+
return Object.entries(value.rateLimitsByLimitId).some(([key, snapshot]) => {
|
|
1730
|
+
return ((isJsonObject(snapshot) && typeof snapshot.limitId === "string" ? snapshot.limitId.trim() : "") || key) === "codex";
|
|
1731
|
+
});
|
|
1787
1732
|
}
|
|
1788
1733
|
function readLimitId(snapshot) {
|
|
1789
1734
|
const value = snapshot.limitId;
|
|
@@ -1832,7 +1777,7 @@ async function readCodexClientSessionMeta(client, sessionsRoot, boundRolloutPath
|
|
|
1832
1777
|
return readCodexWorkspaceSessionMeta(client, configuredClients.get(client), sessionsRoot, boundRolloutPath, threadId, CODEX_APP_SERVER_LIVE_THREAD_MAX_IDLE);
|
|
1833
1778
|
}
|
|
1834
1779
|
/** Installs one auth-refresh handler and one rate-limit observer per physical client. */
|
|
1835
|
-
function ensureCodexAppServerClientRuntime(client, context) {
|
|
1780
|
+
function ensureCodexAppServerClientRuntime(client, context, onThreadOwnershipChange) {
|
|
1836
1781
|
const existing = configuredClients.get(client);
|
|
1837
1782
|
if (existing) {
|
|
1838
1783
|
if (existing.closed) return;
|
|
@@ -1844,6 +1789,7 @@ function ensureCodexAppServerClientRuntime(client, context) {
|
|
|
1844
1789
|
}
|
|
1845
1790
|
const runtime = {
|
|
1846
1791
|
context,
|
|
1792
|
+
onThreadOwnershipChange,
|
|
1847
1793
|
closed: false,
|
|
1848
1794
|
retainedThreads: /* @__PURE__ */ new Map(),
|
|
1849
1795
|
claimedThreads: /* @__PURE__ */ new Map(),
|
|
@@ -1853,6 +1799,7 @@ function ensureCodexAppServerClientRuntime(client, context) {
|
|
|
1853
1799
|
workspaceReferences: /* @__PURE__ */ new Map()
|
|
1854
1800
|
};
|
|
1855
1801
|
configuredClients.set(client, runtime);
|
|
1802
|
+
initializeCodexClientForkSettings(client);
|
|
1856
1803
|
client.addCloseHandler(() => {
|
|
1857
1804
|
runtime.closed = true;
|
|
1858
1805
|
clearTimeout(runtime.evictionTimer);
|
|
@@ -1865,6 +1812,7 @@ function ensureCodexAppServerClientRuntime(client, context) {
|
|
|
1865
1812
|
runtime.protectedThreads.clear();
|
|
1866
1813
|
runtime.sessionMetadata.clear();
|
|
1867
1814
|
runtime.workspaceReferences.clear();
|
|
1815
|
+
forgetCodexClientForkSettings(client);
|
|
1868
1816
|
});
|
|
1869
1817
|
client.addRequestHandler(async (request) => {
|
|
1870
1818
|
if (request.method !== "account/chatgptAuthTokens/refresh") return;
|
|
@@ -1910,16 +1858,18 @@ function ensureCodexAppServerClientRuntime(client, context) {
|
|
|
1910
1858
|
if (typeof threadId === "string") {
|
|
1911
1859
|
invalidateThreadOwnership(runtime, threadId);
|
|
1912
1860
|
runtime.sessionMetadata.delete(threadId);
|
|
1861
|
+
forgetCodexClientForkSettings(client, threadId);
|
|
1913
1862
|
runtime.workspaceReferences.delete(threadId);
|
|
1914
|
-
|
|
1863
|
+
updateThreadOwnership(client, runtime);
|
|
1915
1864
|
}
|
|
1916
1865
|
}
|
|
1917
1866
|
});
|
|
1918
1867
|
}
|
|
1919
|
-
function
|
|
1868
|
+
function updateThreadOwnership(client, runtime) {
|
|
1920
1869
|
clearTimeout(runtime.evictionTimer);
|
|
1921
1870
|
runtime.evictionTimer = void 0;
|
|
1922
1871
|
if (runtime.closed) return;
|
|
1872
|
+
runtime.onThreadOwnershipChange?.();
|
|
1923
1873
|
let expiresAt = Number.POSITIVE_INFINITY;
|
|
1924
1874
|
for (const [threadId, thread] of runtime.retainedThreads) if (!runtime.protectedThreads.has(threadId)) expiresAt = Math.min(expiresAt, thread.expiresAt);
|
|
1925
1875
|
if (!Number.isFinite(expiresAt)) return;
|
|
@@ -1928,7 +1878,7 @@ function scheduleRetainedThreadEviction(client, runtime) {
|
|
|
1928
1878
|
evictExpiredRetainedThreads(client, runtime).catch((error) => {
|
|
1929
1879
|
embeddedAgentLog$1.warn("codex retained thread expiry failed", { reason: formatErrorMessage$1(error) });
|
|
1930
1880
|
});
|
|
1931
|
-
}, Math.max(0, expiresAt -
|
|
1881
|
+
}, Math.max(0, Math.floor(expiresAt - performance.now())));
|
|
1932
1882
|
runtime.evictionTimer.unref?.();
|
|
1933
1883
|
}
|
|
1934
1884
|
async function releaseRetainedThread(client, runtime, threadId, assertCurrent, withCurrent) {
|
|
@@ -1940,13 +1890,7 @@ async function releaseRetainedThread(client, runtime, threadId, assertCurrent, w
|
|
|
1940
1890
|
}
|
|
1941
1891
|
const retained = runtime.retainedThreads.get(threadId);
|
|
1942
1892
|
if (!retained) return false;
|
|
1943
|
-
const olderThreadIds = /* @__PURE__ */ new Set();
|
|
1944
|
-
for (const candidateThreadId of runtime.retainedThreads.keys()) {
|
|
1945
|
-
if (candidateThreadId === threadId) break;
|
|
1946
|
-
olderThreadIds.add(candidateThreadId);
|
|
1947
|
-
}
|
|
1948
1893
|
runtime.retainedThreads.delete(threadId);
|
|
1949
|
-
scheduleRetainedThreadEviction(client, runtime);
|
|
1950
1894
|
const transition = {
|
|
1951
1895
|
retainedOwnerToken: retained.ownerToken,
|
|
1952
1896
|
completion: Promise.resolve().then(() => {
|
|
@@ -1955,29 +1899,28 @@ async function releaseRetainedThread(client, runtime, threadId, assertCurrent, w
|
|
|
1955
1899
|
})
|
|
1956
1900
|
};
|
|
1957
1901
|
runtime.releasingThreads.set(threadId, transition);
|
|
1902
|
+
updateThreadOwnership(client, runtime);
|
|
1958
1903
|
try {
|
|
1959
1904
|
await transition.completion;
|
|
1960
1905
|
runtime.workspaceReferences.delete(threadId);
|
|
1906
|
+
forgetCodexClientForkSettings(client, threadId);
|
|
1961
1907
|
retained.ownerToken?.invalidate();
|
|
1962
1908
|
return true;
|
|
1963
1909
|
} catch (error) {
|
|
1964
1910
|
if (!runtime.closed && !transition.invalidated && runtime.releasingThreads.get(threadId) === transition && !runtime.retainedThreads.has(threadId) && !runtime.claimedThreads.has(threadId)) {
|
|
1965
|
-
if (retained.ephemeralPolicy === void 0) retained.expiresAt =
|
|
1966
|
-
const newerThreads = [...runtime.retainedThreads.entries()].filter(([candidateThreadId]) => !olderThreadIds.has(candidateThreadId));
|
|
1967
|
-
for (const [candidateThreadId] of newerThreads) runtime.retainedThreads.delete(candidateThreadId);
|
|
1911
|
+
if (retained.ephemeralPolicy === void 0) retained.expiresAt = performance.now() + CODEX_APP_SERVER_LIVE_THREAD_IDLE_TIMEOUT_MS;
|
|
1968
1912
|
runtime.retainedThreads.set(threadId, retained);
|
|
1969
|
-
for (const [candidateThreadId, newerThread] of newerThreads) runtime.retainedThreads.set(candidateThreadId, newerThread);
|
|
1970
1913
|
}
|
|
1971
1914
|
throw error;
|
|
1972
1915
|
} finally {
|
|
1973
1916
|
if (runtime.releasingThreads.get(threadId) === transition) runtime.releasingThreads.delete(threadId);
|
|
1974
|
-
|
|
1917
|
+
updateThreadOwnership(client, runtime);
|
|
1975
1918
|
}
|
|
1976
1919
|
}
|
|
1977
1920
|
async function evictExpiredRetainedThreads(client, runtime) {
|
|
1978
|
-
const now =
|
|
1921
|
+
const now = performance.now();
|
|
1979
1922
|
for (const [threadId, thread] of runtime.retainedThreads) if (thread.expiresAt <= now && !runtime.protectedThreads.has(threadId)) await releaseRetainedThread(client, runtime, threadId);
|
|
1980
|
-
|
|
1923
|
+
updateThreadOwnership(client, runtime);
|
|
1981
1924
|
}
|
|
1982
1925
|
async function evictExcessIdleThreads(client, runtime) {
|
|
1983
1926
|
const idleThreads = () => [...runtime.retainedThreads].filter(([threadId, thread]) => thread.ephemeralPolicy === void 0 && !runtime.protectedThreads.has(threadId));
|
|
@@ -2006,7 +1949,7 @@ async function retainCodexAppServerLiveThread(client, threadId, releaseThread, c
|
|
|
2006
1949
|
configFingerprint,
|
|
2007
1950
|
ephemeralPolicy,
|
|
2008
1951
|
serviceTier,
|
|
2009
|
-
expiresAt: ephemeralPolicy === void 0 ?
|
|
1952
|
+
expiresAt: ephemeralPolicy === void 0 ? performance.now() + CODEX_APP_SERVER_LIVE_THREAD_IDLE_TIMEOUT_MS : Number.POSITIVE_INFINITY,
|
|
2010
1953
|
release: (releaseThread ? physicalThreadReleases.get(releaseThread) ?? releaseThread : void 0) ?? defaultThreadRelease(client)
|
|
2011
1954
|
};
|
|
2012
1955
|
runtime.retainedThreads.set(threadId, retained);
|
|
@@ -2015,7 +1958,7 @@ async function retainCodexAppServerLiveThread(client, threadId, releaseThread, c
|
|
|
2015
1958
|
await evictExcessIdleThreads(client, runtime);
|
|
2016
1959
|
} catch (error) {
|
|
2017
1960
|
if (runtime.retainedThreads.get(threadId) === retained) runtime.retainedThreads.delete(threadId);
|
|
2018
|
-
|
|
1961
|
+
updateThreadOwnership(client, runtime);
|
|
2019
1962
|
embeddedAgentLog$1.warn("codex retained thread capacity eviction failed", {
|
|
2020
1963
|
threadId,
|
|
2021
1964
|
reason: formatErrorMessage$1(error)
|
|
@@ -2024,9 +1967,12 @@ async function retainCodexAppServerLiveThread(client, threadId, releaseThread, c
|
|
|
2024
1967
|
}
|
|
2025
1968
|
if (runtime.closed) return false;
|
|
2026
1969
|
if (claimed !== void 0 && runtime.claimedThreads.get(threadId) === claimed) runtime.claimedThreads.delete(threadId);
|
|
2027
|
-
|
|
1970
|
+
updateThreadOwnership(client, runtime);
|
|
2028
1971
|
return true;
|
|
2029
1972
|
}
|
|
1973
|
+
function readCodexLiveThreadEphemeralPolicy(client, threadId) {
|
|
1974
|
+
return configuredClients.get(client)?.retainedThreads.get(threadId)?.ephemeralPolicy;
|
|
1975
|
+
}
|
|
2030
1976
|
/** Transfer one idle subscription to its next turn or compaction without touching sibling threads. */
|
|
2031
1977
|
async function consumeCodexAppServerLiveThread(client, threadId, configFingerprint) {
|
|
2032
1978
|
const runtime = configuredClients.get(client);
|
|
@@ -2050,7 +1996,7 @@ async function claimCodexAppServerLiveThread(client, threadId, onInvalidated) {
|
|
|
2050
1996
|
return;
|
|
2051
1997
|
}
|
|
2052
1998
|
return claimCodexAppServerThreadOwnership(client, runtime, threadId, runtime.retainedThreads.get(threadId) ?? {
|
|
2053
|
-
expiresAt:
|
|
1999
|
+
expiresAt: performance.now() + CODEX_APP_SERVER_LIVE_THREAD_IDLE_TIMEOUT_MS,
|
|
2054
2000
|
release: defaultThreadRelease(client)
|
|
2055
2001
|
}, onInvalidated);
|
|
2056
2002
|
}
|
|
@@ -2061,7 +2007,7 @@ function claimCodexAppServerThreadOwnership(client, runtime, threadId, retained,
|
|
|
2061
2007
|
runtime.claimedThreads.set(threadId, claimed);
|
|
2062
2008
|
previousClaim?.invalidate();
|
|
2063
2009
|
retained.ownerToken?.invalidate();
|
|
2064
|
-
|
|
2010
|
+
updateThreadOwnership(client, runtime);
|
|
2065
2011
|
const assertCurrent = () => {
|
|
2066
2012
|
if (claimed.invalidated || runtime.closed || runtime.claimedThreads.get(threadId) !== claimed) throw new Error(`Codex thread subscription ownership changed: ${threadId}`);
|
|
2067
2013
|
};
|
|
@@ -2102,10 +2048,12 @@ function claimCodexAppServerThreadOwnership(client, runtime, threadId, retained,
|
|
|
2102
2048
|
if (runtime.claimedThreads.get(threadId) === claimed) {
|
|
2103
2049
|
runtime.claimedThreads.delete(threadId);
|
|
2104
2050
|
runtime.workspaceReferences.delete(threadId);
|
|
2051
|
+
forgetCodexClientForkSettings(client, threadId);
|
|
2105
2052
|
claimed.invalidate();
|
|
2106
2053
|
}
|
|
2107
2054
|
} finally {
|
|
2108
2055
|
if (runtime.releasingThreads.get(threadId) === transition) runtime.releasingThreads.delete(threadId);
|
|
2056
|
+
updateThreadOwnership(client, runtime);
|
|
2109
2057
|
}
|
|
2110
2058
|
};
|
|
2111
2059
|
physicalThreadReleases.set(release, retained.release);
|
|
@@ -2119,7 +2067,8 @@ function claimCodexAppServerThreadOwnership(client, runtime, threadId, retained,
|
|
|
2119
2067
|
forget: () => {
|
|
2120
2068
|
if (forgetThreadOwnership(runtime, threadId, claimed)) {
|
|
2121
2069
|
runtime.workspaceReferences.delete(threadId);
|
|
2122
|
-
|
|
2070
|
+
forgetCodexClientForkSettings(client, threadId);
|
|
2071
|
+
updateThreadOwnership(client, runtime);
|
|
2123
2072
|
}
|
|
2124
2073
|
}
|
|
2125
2074
|
};
|
|
@@ -2129,6 +2078,11 @@ function revertCodexAppServerLiveThreadInstructions(client, threadId) {
|
|
|
2129
2078
|
const runtime = configuredClients.get(client);
|
|
2130
2079
|
if (runtime && !runtime.closed) revertRetainedThreadInstructions(runtime, threadId);
|
|
2131
2080
|
}
|
|
2081
|
+
/** Native subscriptions, including ephemeral history and releases, pin their physical client. */
|
|
2082
|
+
function hasCodexAppServerThreadOwnership(client) {
|
|
2083
|
+
const runtime = configuredClients.get(client);
|
|
2084
|
+
return Boolean(runtime && !runtime.closed && (runtime.retainedThreads.size > 0 || runtime.claimedThreads.size > 0 || runtime.releasingThreads.size > 0 || runtime.protectedThreads.size > 0));
|
|
2085
|
+
}
|
|
2132
2086
|
/** Distinguish active claimed ownership from an already-evicted idle subscription. */
|
|
2133
2087
|
function hasCodexAppServerLiveThread(client, threadId) {
|
|
2134
2088
|
return hasThreadOwnership(configuredClients.get(client), threadId);
|
|
@@ -2169,6 +2123,7 @@ async function unsubscribeCodexAppServerLiveThread(client, threadId, timeoutMs,
|
|
|
2169
2123
|
});
|
|
2170
2124
|
assertCurrent?.();
|
|
2171
2125
|
runtime?.workspaceReferences.delete(threadId);
|
|
2126
|
+
forgetCodexClientForkSettings(client, threadId);
|
|
2172
2127
|
});
|
|
2173
2128
|
const ownsTransition = runtime !== void 0 && transition === void 0;
|
|
2174
2129
|
if (transition) transition.physicalRelease = physicalRelease;
|
|
@@ -2178,20 +2133,24 @@ async function unsubscribeCodexAppServerLiveThread(client, threadId, timeoutMs,
|
|
|
2178
2133
|
physicalRelease
|
|
2179
2134
|
};
|
|
2180
2135
|
runtime.releasingThreads.set(threadId, transition);
|
|
2136
|
+
updateThreadOwnership(client, runtime);
|
|
2181
2137
|
}
|
|
2182
2138
|
try {
|
|
2183
2139
|
await physicalRelease;
|
|
2184
2140
|
if (retained !== void 0 && runtime?.retainedThreads.get(threadId) === retained) {
|
|
2185
2141
|
runtime.retainedThreads.delete(threadId);
|
|
2186
2142
|
retained.ownerToken?.invalidate();
|
|
2187
|
-
|
|
2143
|
+
updateThreadOwnership(client, runtime);
|
|
2188
2144
|
}
|
|
2189
2145
|
if (claimed !== void 0 && runtime?.claimedThreads.get(threadId) === claimed) {
|
|
2190
2146
|
runtime.claimedThreads.delete(threadId);
|
|
2191
2147
|
claimed.invalidate();
|
|
2192
2148
|
}
|
|
2193
2149
|
} finally {
|
|
2194
|
-
if (ownsTransition && runtime.releasingThreads.get(threadId) === transition)
|
|
2150
|
+
if (ownsTransition && runtime.releasingThreads.get(threadId) === transition) {
|
|
2151
|
+
runtime.releasingThreads.delete(threadId);
|
|
2152
|
+
updateThreadOwnership(client, runtime);
|
|
2153
|
+
}
|
|
2195
2154
|
}
|
|
2196
2155
|
}
|
|
2197
2156
|
/** Reset/end owns the exact thread; failed generation retirement must never release its successor. */
|
|
@@ -2204,7 +2163,7 @@ function protectCodexAppServerLiveThread(client, threadId) {
|
|
|
2204
2163
|
const runtime = configuredClients.get(client);
|
|
2205
2164
|
if (!runtime || runtime.closed) return () => void 0;
|
|
2206
2165
|
runtime.protectedThreads.set(threadId, (runtime.protectedThreads.get(threadId) ?? 0) + 1);
|
|
2207
|
-
|
|
2166
|
+
updateThreadOwnership(client, runtime);
|
|
2208
2167
|
let protectedThread = true;
|
|
2209
2168
|
return () => {
|
|
2210
2169
|
if (!protectedThread) return;
|
|
@@ -2213,12 +2172,12 @@ function protectCodexAppServerLiveThread(client, threadId) {
|
|
|
2213
2172
|
if (releaseThreadProtection(runtime, threadId)) {
|
|
2214
2173
|
const retained = runtime.retainedThreads.get(threadId);
|
|
2215
2174
|
if (retained) {
|
|
2216
|
-
if (retained.ephemeralPolicy === void 0) retained.expiresAt =
|
|
2175
|
+
if (retained.ephemeralPolicy === void 0) retained.expiresAt = performance.now() + CODEX_APP_SERVER_LIVE_THREAD_IDLE_TIMEOUT_MS;
|
|
2217
2176
|
runtime.retainedThreads.delete(threadId);
|
|
2218
2177
|
runtime.retainedThreads.set(threadId, retained);
|
|
2219
2178
|
}
|
|
2220
2179
|
}
|
|
2221
|
-
|
|
2180
|
+
updateThreadOwnership(client, runtime);
|
|
2222
2181
|
evictExcessIdleThreads(client, runtime).catch((error) => {
|
|
2223
2182
|
embeddedAgentLog$1.warn("codex retained thread unpin eviction failed", {
|
|
2224
2183
|
threadId,
|
|
@@ -2380,7 +2339,7 @@ function ownCodexInferenceClient(client, startOptions = {}, oauth) {
|
|
|
2380
2339
|
};
|
|
2381
2340
|
client.addCloseHandler(close);
|
|
2382
2341
|
client.addNotificationHandler((notification) => {
|
|
2383
|
-
if (notification.method === "thread/closed" && isJsonObject(notification.params) && typeof notification.params.threadId === "string")
|
|
2342
|
+
if ((notification.method === "thread/closed" || notification.method === "thread/archived" || notification.method === "thread/deleted") && isJsonObject(notification.params) && typeof notification.params.threadId === "string") forgetCodexInferenceThread(client, notification.params.threadId);
|
|
2384
2343
|
if (notification.method !== "account/updated" || !owner.authRoute) return;
|
|
2385
2344
|
const mode = isJsonObject(notification.params) ? notification.params.authMode : void 0;
|
|
2386
2345
|
if ((mode === "apiKey" ? "apiKey" : mode === "chatgpt" || mode === "chatgptAuthTokens" ? "chatgpt" : void 0) !== owner.authRoute) close();
|
|
@@ -2485,9 +2444,9 @@ async function prepareCodexInferenceRoute(params) {
|
|
|
2485
2444
|
throw new Error("Codex inference route limit reached; start a fresh managed native connection before retrying.");
|
|
2486
2445
|
}
|
|
2487
2446
|
pending = Promise.all([
|
|
2488
|
-
import("./inference-proxy-
|
|
2489
|
-
import("./native-subagent-monitor-
|
|
2490
|
-
import("./inference-dispatch-
|
|
2447
|
+
import("./inference-proxy-CiLbHMLf.mjs"),
|
|
2448
|
+
import("./native-subagent-monitor-C3CIIaZG.mjs").then((n) => n.n),
|
|
2449
|
+
import("./inference-dispatch-C2zVSnrr.mjs")
|
|
2491
2450
|
]).then(([{ createCodexInferenceProxy }, native, { createCodexInferenceModelBinding }]) => {
|
|
2492
2451
|
assertClient();
|
|
2493
2452
|
return createCodexInferenceProxy({
|
|
@@ -2636,7 +2595,7 @@ function bindCodexInferenceThread(client, threadId, route, providers) {
|
|
|
2636
2595
|
if (!owner && !route) return;
|
|
2637
2596
|
if (!owner || owner.closed) throw new Error("Codex inference client is closed");
|
|
2638
2597
|
if (!route) {
|
|
2639
|
-
|
|
2598
|
+
forgetCodexInferenceThread(client, threadId);
|
|
2640
2599
|
return;
|
|
2641
2600
|
}
|
|
2642
2601
|
route.assertCurrent();
|
|
@@ -2661,12 +2620,19 @@ function bindCodexInferenceThread(client, threadId, route, providers) {
|
|
|
2661
2620
|
return projectedRoute !== void 0 && owner.handles.get(projectedRoute)?.modelPolicyEnforced === true;
|
|
2662
2621
|
}
|
|
2663
2622
|
}) : void 0;
|
|
2623
|
+
const previous = owner.threads.get(threadId)?.route;
|
|
2624
|
+
if (previous && previous !== route) previous.context.forget(threadId);
|
|
2664
2625
|
owner.threads.set(threadId, {
|
|
2665
2626
|
route,
|
|
2666
2627
|
providers: projected,
|
|
2667
2628
|
qualification
|
|
2668
2629
|
});
|
|
2669
2630
|
}
|
|
2631
|
+
function forgetCodexInferenceThread(client, threadId) {
|
|
2632
|
+
const owner = owners.get(client);
|
|
2633
|
+
owner?.threads.get(threadId)?.route.context.forget(threadId);
|
|
2634
|
+
owner?.threads.delete(threadId);
|
|
2635
|
+
}
|
|
2670
2636
|
function getCodexInferenceThread(client, threadId) {
|
|
2671
2637
|
const owner = owners.get(client);
|
|
2672
2638
|
if (owner?.closed) throw new Error("Codex inference client is closed");
|
|
@@ -2679,52 +2645,24 @@ function getCodexInferenceThreadQualification(client, threadId) {
|
|
|
2679
2645
|
return owner?.threads.get(threadId)?.qualification;
|
|
2680
2646
|
}
|
|
2681
2647
|
//#endregion
|
|
2682
|
-
//#region extensions/codex/src/app-server/
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
/** Acquires the per-CODEX_HOME fence and returns an idempotent release. */
|
|
2686
|
-
async function acquireCodexNativeConfigFence(key, options = {}) {
|
|
2687
|
-
const state = resolveGlobalMap(CODEX_NATIVE_CONFIG_FENCE_STATE);
|
|
2688
|
-
const previous = state.get(key) ?? Promise.resolve();
|
|
2689
|
-
const { promise: current, resolve: resolveCurrent } = createDeferred();
|
|
2690
|
-
state.set(key, current);
|
|
2691
|
-
let released = false;
|
|
2692
|
-
const release = () => {
|
|
2693
|
-
if (released) return;
|
|
2694
|
-
released = true;
|
|
2695
|
-
resolveCurrent();
|
|
2696
|
-
if (state.get(key) === current) state.delete(key);
|
|
2697
|
-
};
|
|
2698
|
-
try {
|
|
2699
|
-
await waitForPreviousFence(previous, options);
|
|
2700
|
-
} catch (error) {
|
|
2701
|
-
previous.then(release);
|
|
2702
|
-
throw error;
|
|
2703
|
-
}
|
|
2704
|
-
return release;
|
|
2648
|
+
//#region extensions/codex/src/app-server/managed-fallback.ts
|
|
2649
|
+
function isCodexComputerUseCandidateArtifactsUnavailableError(error) {
|
|
2650
|
+
return error !== null && typeof error === "object" && "code" in error && error.code === "CODEX_COMPUTER_USE_CANDIDATE_ARTIFACTS_UNAVAILABLE";
|
|
2705
2651
|
}
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
const settle = (error) => {
|
|
2715
|
-
clearTimeout(timeout);
|
|
2716
|
-
timeout = void 0;
|
|
2717
|
-
options.signal?.removeEventListener("abort", onAbort);
|
|
2718
|
-
return error ? reject(error) : resolve();
|
|
2652
|
+
function resolveManagedFallbackStartOptions(startOptions) {
|
|
2653
|
+
const commands = [startOptions.command, ...startOptions.managedFallbackCommandPaths ?? []];
|
|
2654
|
+
const candidates = [];
|
|
2655
|
+
for (const [index, command] of commands.entries()) {
|
|
2656
|
+
const managedFallbackCommandPaths = commands.slice(index + 1);
|
|
2657
|
+
const candidate = {
|
|
2658
|
+
...startOptions,
|
|
2659
|
+
command
|
|
2719
2660
|
};
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
timeout.unref?.();
|
|
2726
|
-
}
|
|
2727
|
-
});
|
|
2661
|
+
if (managedFallbackCommandPaths.length === 0) delete candidate.managedFallbackCommandPaths;
|
|
2662
|
+
else candidate.managedFallbackCommandPaths = managedFallbackCommandPaths;
|
|
2663
|
+
candidates.push(candidate);
|
|
2664
|
+
}
|
|
2665
|
+
return candidates;
|
|
2728
2666
|
}
|
|
2729
2667
|
//#endregion
|
|
2730
2668
|
//#region extensions/codex/src/app-server/native-hook-relay-state.ts
|
|
@@ -2763,6 +2701,38 @@ const nativeHookRelayUnregisterQueue = {
|
|
|
2763
2701
|
}
|
|
2764
2702
|
};
|
|
2765
2703
|
//#endregion
|
|
2704
|
+
//#region extensions/codex/src/app-server/shared-client-key.ts
|
|
2705
|
+
/** Cache keys that decide which acquisitions share one physical Codex app-server client. */
|
|
2706
|
+
/**
|
|
2707
|
+
* Returns the shared-client key for start options under one acquisition's
|
|
2708
|
+
* auth identity, desktop generation, and runtime-artifact mode. Callers key
|
|
2709
|
+
* their resolved start options, and rekey after a managed fallback.
|
|
2710
|
+
*/
|
|
2711
|
+
function createSharedCodexAppServerClientKeyResolver(params) {
|
|
2712
|
+
const { preparedAuth, authRequirement, authProfileId, desktopGeneration } = params;
|
|
2713
|
+
const authIdentityCacheKey = preparedAuth?.kind === "api-key" ? resolveCodexAppServerPreparedApiKeyCacheKey(preparedAuth.apiKey) : preparedAuth?.snapshot.secretFreeCacheKey ?? ((authRequirement === "api-key" || authRequirement === "environment-api-key") && !authProfileId ? resolveCodexAppServerFallbackApiKeyCacheKey({
|
|
2714
|
+
startOptions: params.startOptions,
|
|
2715
|
+
allowNativeAuthFile: authRequirement === "api-key"
|
|
2716
|
+
}) : void 0);
|
|
2717
|
+
const expectedRuntimeArtifactKey = params.expectedRuntimeArtifact ? createHash("sha256").update(params.expectedRuntimeArtifact.id).update("\0").update(params.expectedRuntimeArtifact.fingerprint).digest("hex") : "mint";
|
|
2718
|
+
return (startOptions) => {
|
|
2719
|
+
const baseKey = `${codexAppServerStartOptionsKey(startOptions, {
|
|
2720
|
+
authProfileId,
|
|
2721
|
+
authBindingFingerprint: params.authBindingFingerprint,
|
|
2722
|
+
agentDir: params.usesNativeAuth ? void 0 : params.agentDir,
|
|
2723
|
+
fallbackApiKeyCacheKey: authIdentityCacheKey
|
|
2724
|
+
})}\0auth-requirement:${authRequirement ?? "native"}${desktopGeneration ? `\0desktop-generation:${desktopGeneration.epoch}` : ""}`;
|
|
2725
|
+
return params.runtimeArtifactMode ? `${baseKey}\0runtime-artifact:capture-v1:${expectedRuntimeArtifactKey}` : baseKey;
|
|
2726
|
+
};
|
|
2727
|
+
}
|
|
2728
|
+
//#endregion
|
|
2729
|
+
//#region extensions/codex/src/app-server/shared-client-start-policy.ts
|
|
2730
|
+
function shouldTrackDesktopGeneration(startOptions, pluginConfig) {
|
|
2731
|
+
if (startOptions.transport !== "stdio") return false;
|
|
2732
|
+
if (resolveCodexComputerUseConfig({ pluginConfig }).enabled && (startOptions.commandSource === "managed" || startOptions.commandSource === "resolved-managed")) return true;
|
|
2733
|
+
return startOptions.commandSource === "managed" && (startOptions.managedCommandOrder ?? "package-first") === "desktop-first";
|
|
2734
|
+
}
|
|
2735
|
+
//#endregion
|
|
2766
2736
|
//#region extensions/codex/src/app-server/spawn-identity.ts
|
|
2767
2737
|
/** Resolves non-secret spawn identity before startup; argv is represented only by its hash. */
|
|
2768
2738
|
function resolveCodexAppServerSpawnIdentity(startOptions, resolvedNativeCommand) {
|
|
@@ -2777,12 +2747,6 @@ function resolveCodexAppServerSpawnIdentity(startOptions, resolvedNativeCommand)
|
|
|
2777
2747
|
}
|
|
2778
2748
|
//#endregion
|
|
2779
2749
|
//#region extensions/codex/src/app-server/thread-lifecycle-errors.ts
|
|
2780
|
-
const CODEX_APP_SERVER_CONTEXT_RESTART_SELECTION_CHANGED = "CODEX_APP_SERVER_CONTEXT_RESTART_SELECTION_CHANGED";
|
|
2781
|
-
/** True when a pre-write context restart must replay on the newly selected owner. */
|
|
2782
|
-
function isCodexContextRestartSelectionChangedError(error) {
|
|
2783
|
-
const cause = codexPrewriteRejectionCause(error);
|
|
2784
|
-
return cause instanceof Error && "code" in cause && cause.code === "CODEX_APP_SERVER_CONTEXT_RESTART_SELECTION_CHANGED";
|
|
2785
|
-
}
|
|
2786
2750
|
var CodexThreadStartRequestError = class extends Error {
|
|
2787
2751
|
constructor(cause) {
|
|
2788
2752
|
super(`thread/start: ${formatErrorMessage$1(cause)}`, { cause });
|
|
@@ -2810,30 +2774,24 @@ var CodexAdoptedThreadActiveError = class extends AgentHarnessPreflightError$1 {
|
|
|
2810
2774
|
//#endregion
|
|
2811
2775
|
//#region extensions/codex/src/app-server/shared-client.ts
|
|
2812
2776
|
var shared_client_exports = /* @__PURE__ */ __exportAll({
|
|
2813
|
-
assertCodexAppServerClientStartSelectionCurrent: () => assertCodexAppServerClientStartSelectionCurrent,
|
|
2814
2777
|
captureCodexAppServerClientLifetime: () => captureCodexAppServerClientLifetime,
|
|
2815
2778
|
captureSharedCodexAppServerCatalogLifetime: () => captureSharedCodexAppServerCatalogLifetime,
|
|
2816
2779
|
clearSharedCodexAppServerClientAndWait: () => clearSharedCodexAppServerClientAndWait,
|
|
2817
|
-
clearSharedCodexAppServerClientIfCurrent: () => clearSharedCodexAppServerClientIfCurrent,
|
|
2818
2780
|
clearSharedCodexAppServerClientIfCurrentAndUnclaimed: () => clearSharedCodexAppServerClientIfCurrentAndUnclaimed,
|
|
2819
2781
|
clearSharedCodexAppServerClientIfCurrentAndWait: () => clearSharedCodexAppServerClientIfCurrentAndWait,
|
|
2820
2782
|
createIsolatedCodexAppServerClient: () => createIsolatedCodexAppServerClient,
|
|
2821
2783
|
getLeasedSharedCodexAppServerClient: () => getLeasedSharedCodexAppServerClient,
|
|
2822
2784
|
getSharedCodexAppServerClient: () => getSharedCodexAppServerClient,
|
|
2823
|
-
isCodexAppServerStartSelectionChangedError: () => isCodexAppServerStartSelectionChangedError,
|
|
2824
2785
|
readCodexAppServerClientDesktopGeneration: () => readCodexAppServerClientDesktopGeneration,
|
|
2825
2786
|
readCodexAppServerClientDesktopGenerationFingerprint: () => readCodexAppServerClientDesktopGenerationFingerprint,
|
|
2826
2787
|
readCodexAppServerClientProcessIdentity: () => readCodexAppServerClientProcessIdentity,
|
|
2827
2788
|
releaseCodexAppServerClientLease: () => releaseCodexAppServerClientLease,
|
|
2828
2789
|
releaseLeasedSharedCodexAppServerClient: () => releaseLeasedSharedCodexAppServerClient,
|
|
2829
|
-
resolveCodexNativeConfigFenceKey: () => resolveCodexNativeConfigFenceKey,
|
|
2830
2790
|
retainSharedCodexAppServerClientIfCurrent: () => retainSharedCodexAppServerClientIfCurrent,
|
|
2831
2791
|
retireSharedCodexAppServerClientIfCurrent: () => retireSharedCodexAppServerClientIfCurrent,
|
|
2832
|
-
|
|
2833
|
-
withLeasedCodexAppServerClientStartSelectionRetry: () => withLeasedCodexAppServerClientStartSelectionRetry
|
|
2792
|
+
withCodexAppServerClientRequestScope: () => withCodexAppServerClientRequestScope
|
|
2834
2793
|
});
|
|
2835
2794
|
const SHARED_CODEX_APP_SERVER_CLIENT_DISPOSER = codexBuildSymbol("openclaw.codexAppServerClientDisposer");
|
|
2836
|
-
const CODEX_APP_SERVER_INITIALIZE_TIMEOUT_MESSAGE = "codex app-server initialize timed out";
|
|
2837
2795
|
async function prepareCodexAppServerClient(options) {
|
|
2838
2796
|
const lifetime = getSharedCodexAppServerClientState().startup;
|
|
2839
2797
|
const abandonSignal = options?.abandonSignal ? AbortSignal.any([lifetime.controller.signal, options.abandonSignal]) : lifetime.controller.signal;
|
|
@@ -2844,7 +2802,7 @@ async function prepareCodexAppServerClient(options) {
|
|
|
2844
2802
|
const startedAt = performance.now();
|
|
2845
2803
|
observeAcquire(options, { boundary: "context" });
|
|
2846
2804
|
return {
|
|
2847
|
-
context: await withCodexAppServerAcquireDeadline(options?.timeoutMs ?? 0, ownCodexStartup(lifetime, resolveCodexAppServerClientStartContext(options)), abandonSignal),
|
|
2805
|
+
context: await withCodexAppServerAcquireDeadline(options?.timeoutMs ?? 0, ownCodexStartup(lifetime, resolveCodexAppServerClientStartContext(options, startedAt)), abandonSignal),
|
|
2848
2806
|
lifetime,
|
|
2849
2807
|
abandonSignal,
|
|
2850
2808
|
startedAt,
|
|
@@ -2869,59 +2827,7 @@ function readCodexAppServerClientDesktopGenerationFingerprint(client) {
|
|
|
2869
2827
|
function readCodexAppServerClientDesktopGeneration(client) {
|
|
2870
2828
|
return getSharedCodexAppServerClientState().startMetadata.get(client)?.desktopGeneration;
|
|
2871
2829
|
}
|
|
2872
|
-
|
|
2873
|
-
async function waitForCodexAppServerClientDesktopGenerationDrain(params) {
|
|
2874
|
-
const metadata = getSharedCodexAppServerClientState().startMetadata.get(params.client);
|
|
2875
|
-
if (!metadata?.desktopGeneration) return;
|
|
2876
|
-
const drain = createOlderDesktopGenerationDrainWait({
|
|
2877
|
-
generation: metadata.desktopGeneration,
|
|
2878
|
-
startOptions: metadata.startOptions,
|
|
2879
|
-
agentDir: metadata.agentDir
|
|
2880
|
-
});
|
|
2881
|
-
try {
|
|
2882
|
-
await withCodexAppServerAcquireDeadline(params.timeoutMs ?? 0, drain.promise, params.signal, "Codex Computer Use install timed out waiting for older desktop clients");
|
|
2883
|
-
} finally {
|
|
2884
|
-
drain.cancel();
|
|
2885
|
-
}
|
|
2886
|
-
}
|
|
2887
|
-
var CodexAppServerStartSelectionChangedError = class extends Error {
|
|
2888
|
-
constructor() {
|
|
2889
|
-
super("Codex app-server managed executable selection changed during startup");
|
|
2890
|
-
this.code = "CODEX_APP_SERVER_START_SELECTION_CHANGED";
|
|
2891
|
-
this.name = "CodexAppServerStartSelectionChangedError";
|
|
2892
|
-
}
|
|
2893
|
-
};
|
|
2894
|
-
/** Cross-bundle-safe check for a managed executable selection retry. */
|
|
2895
|
-
function isCodexAppServerStartSelectionChangedError(error) {
|
|
2896
|
-
const cause = codexPrewriteRejectionCause(error);
|
|
2897
|
-
return cause instanceof Error && "code" in cause && cause.code === "CODEX_APP_SERVER_START_SELECTION_CHANGED";
|
|
2898
|
-
}
|
|
2899
|
-
/**
|
|
2900
|
-
* Rechecks mutable Codex-owned plugin state immediately before thread start/resume.
|
|
2901
|
-
* The synchronous check prevents another gateway task from installing Computer
|
|
2902
|
-
* Use between the check and the JSON-RPC write on the same event loop turn.
|
|
2903
|
-
*/
|
|
2904
|
-
function assertCodexAppServerClientStartSelectionCurrent(params) {
|
|
2905
|
-
const metadata = getSharedCodexAppServerClientState().startMetadata.get(params.client);
|
|
2906
|
-
if (!metadata) return;
|
|
2907
|
-
if (metadata.desktopGeneration && !isCodexDesktopGenerationCurrent(metadata.desktopGeneration)) throw new CodexAppServerStartSelectionChangedError();
|
|
2908
|
-
const requestedStartOptions = params.startOptions ?? metadata.requestedStartOptions;
|
|
2909
|
-
if (requestedStartOptions.commandSource !== "managed") return;
|
|
2910
|
-
const current = resolveCodexAppServerStartOptionsForAgent({
|
|
2911
|
-
startOptions: requestedStartOptions,
|
|
2912
|
-
agentDir: params.agentDir ?? metadata.agentDir
|
|
2913
|
-
});
|
|
2914
|
-
if ((metadata.startOptions.managedCommandOrder ?? "package-first") !== (current.managedCommandOrder ?? "package-first")) throw new CodexAppServerStartSelectionChangedError();
|
|
2915
|
-
}
|
|
2916
|
-
function resolveCodexNativeConfigFenceKey(params) {
|
|
2917
|
-
const metadata = params.client ? getSharedCodexAppServerClientState().startMetadata.get(params.client) : void 0;
|
|
2918
|
-
const startOptions = metadata?.startOptions ?? params.startOptions;
|
|
2919
|
-
if (!startOptions || startOptions.transport !== "stdio") return;
|
|
2920
|
-
const configuredHome = startOptions.codexHome ?? startOptions.env?.CODEX_HOME?.trim();
|
|
2921
|
-
const codexHome = configuredHome ? configuredHome : startOptions.homeScope === "user" ? resolveCodexAppServerUserHomeDir() : resolveCodexAppServerHomeDir(params.agentDir ?? metadata?.agentDir ?? resolveDefaultAgentDir(params.config ?? {}));
|
|
2922
|
-
return codexHome ? `codex-home:${path.resolve(codexHome)}` : void 0;
|
|
2923
|
-
}
|
|
2924
|
-
async function resolveCodexAppServerClientStartContext(options) {
|
|
2830
|
+
async function resolveCodexAppServerClientStartContext(options, startedAt) {
|
|
2925
2831
|
const requestedStartOptions = options?.startOptions ?? resolveCodexAppServerRuntimeOptions({ pluginConfig: options?.pluginConfig }).start;
|
|
2926
2832
|
const agentDir = options?.agentDir ?? (requestedStartOptions.homeScope === "user" ? void 0 : resolveDefaultAgentDir(options?.config ?? {}));
|
|
2927
2833
|
const desktopGeneration = shouldTrackDesktopGeneration(requestedStartOptions, options?.pluginConfig) ? await waitForCodexDesktopGeneration() : void 0;
|
|
@@ -2936,13 +2842,13 @@ async function resolveCodexAppServerClientStartContext(options) {
|
|
|
2936
2842
|
let authRequirement = options?.authRequirement ?? preparedAuthRequirement;
|
|
2937
2843
|
const usesNativeAuth = !preparedAuth && (options?.authProfileId === null || requestedStartOptions.homeScope === "user");
|
|
2938
2844
|
const requestedAuthProfileId = preparedAuth?.kind === "profile" ? preparedAuth.profileId : options?.authProfileId ?? void 0;
|
|
2939
|
-
const authProfileStore = preparedAuth?.kind === "profile" ? preparedAuth.store : !usesNativeAuth && preparedAuth?.kind !== "api-key" ? resolveCodexAppServerAuthProfileStore({
|
|
2845
|
+
const authProfileStore = preparedAuth?.kind === "profile" ? preparedAuth.store : !usesNativeAuth && preparedAuth?.kind !== "api-key" ? await resolveCodexAppServerAuthProfileStore({
|
|
2940
2846
|
agentDir,
|
|
2941
2847
|
authProfileId: requestedAuthProfileId,
|
|
2942
2848
|
authProfileStore: options?.authProfileStore,
|
|
2943
2849
|
config: options?.config
|
|
2944
2850
|
}) : options?.authProfileStore;
|
|
2945
|
-
const authProfileId = preparedAuth?.kind === "profile" ? preparedAuth.profileId : usesNativeAuth || preparedAuth?.kind === "api-key" ? void 0 : resolveCodexAppServerAuthProfileIdForAgent({
|
|
2851
|
+
const authProfileId = preparedAuth?.kind === "profile" ? preparedAuth.profileId : usesNativeAuth || preparedAuth?.kind === "api-key" ? void 0 : await resolveCodexAppServerAuthProfileIdForAgent({
|
|
2946
2852
|
authProfileId: requestedAuthProfileId,
|
|
2947
2853
|
agentDir,
|
|
2948
2854
|
config: options?.config,
|
|
@@ -2972,8 +2878,9 @@ async function resolveCodexAppServerClientStartContext(options) {
|
|
|
2972
2878
|
startOptions: requestedStartOptions,
|
|
2973
2879
|
agentDir
|
|
2974
2880
|
});
|
|
2881
|
+
const remainingMs = resolveRemainingAcquireTimeout(options?.timeoutMs ?? 0, startedAt);
|
|
2975
2882
|
const startOptions = await bridgeCodexAppServerStartOptions({
|
|
2976
|
-
startOptions: await resolveManagedCodexAppServerStartOptions(agentStartOptions),
|
|
2883
|
+
startOptions: await resolveManagedCodexAppServerStartOptions(agentStartOptions, { selectionTimeoutMs: remainingMs > 0 ? remainingMs / 2 : void 0 }),
|
|
2977
2884
|
agentId: options?.agentId,
|
|
2978
2885
|
agentDir,
|
|
2979
2886
|
authProfileId: usesNativeAuth || preparedAuth?.kind === "api-key" ? null : authProfileId,
|
|
@@ -2996,11 +2903,6 @@ async function resolveCodexAppServerClientStartContext(options) {
|
|
|
2996
2903
|
...desktopGeneration ? { desktopGeneration } : {}
|
|
2997
2904
|
};
|
|
2998
2905
|
}
|
|
2999
|
-
function shouldTrackDesktopGeneration(startOptions, pluginConfig) {
|
|
3000
|
-
if (startOptions.transport !== "stdio") return false;
|
|
3001
|
-
if (resolveCodexComputerUseConfig({ pluginConfig }).enabled && (startOptions.commandSource === "managed" || startOptions.commandSource === "resolved-managed")) return true;
|
|
3002
|
-
return startOptions.commandSource === "managed" && (startOptions.managedCommandOrder ?? "package-first") === "desktop-first";
|
|
3003
|
-
}
|
|
3004
2906
|
/** Gets or starts a shared Codex app-server client without retaining a lease. */
|
|
3005
2907
|
function getSharedCodexAppServerClient(options) {
|
|
3006
2908
|
return acquireSharedCodexAppServerClient(options);
|
|
@@ -3022,58 +2924,43 @@ function releaseCodexAppServerClientLease(lease) {
|
|
|
3022
2924
|
lease.client = void 0;
|
|
3023
2925
|
return client ? releaseLeasedSharedCodexAppServerClient(client) : false;
|
|
3024
2926
|
}
|
|
3025
|
-
/**
|
|
3026
|
-
async function
|
|
3027
|
-
|
|
3028
|
-
if (!client) throw new Error("Codex app-server
|
|
2927
|
+
/** Shares a deadline and live lease check across one operation's requests. */
|
|
2928
|
+
async function withCodexAppServerClientRequestScope(params) {
|
|
2929
|
+
const client = params.lease.client;
|
|
2930
|
+
if (!client) throw new Error("Codex app-server request scope requires an active client lease");
|
|
3029
2931
|
const timeoutMs = params.options?.timeoutMs ?? 6e4;
|
|
3030
2932
|
const deadline = performance.now() + timeoutMs;
|
|
3031
2933
|
const signal = params.signal ?? params.options?.abandonSignal;
|
|
3032
2934
|
const requestOptions = () => {
|
|
3033
|
-
if (signal?.aborted) throw new CodexAppServerStartupError("aborted", "Codex app-server
|
|
2935
|
+
if (signal?.aborted) throw new CodexAppServerStartupError("aborted", "Codex app-server request aborted");
|
|
3034
2936
|
const remainingTimeoutMs = deadline - performance.now();
|
|
3035
|
-
if (remainingTimeoutMs <= 0) throw new CodexAppServerStartupError("timed_out", "Codex app-server
|
|
2937
|
+
if (remainingTimeoutMs <= 0) throw new CodexAppServerStartupError("timed_out", "Codex app-server request timed out");
|
|
3036
2938
|
return {
|
|
3037
2939
|
timeoutMs: remainingTimeoutMs,
|
|
3038
2940
|
...signal ? { signal } : {}
|
|
3039
2941
|
};
|
|
3040
2942
|
};
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
return
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
client.close();
|
|
3062
|
-
throw new Error("Codex app-server selection retry requires a leased shared client", { cause: error });
|
|
3063
|
-
}
|
|
3064
|
-
const replacementOptions = requestOptions();
|
|
3065
|
-
client = await getLeasedSharedCodexAppServerClient({
|
|
3066
|
-
...params.options,
|
|
3067
|
-
timeoutMs: replacementOptions.timeoutMs,
|
|
3068
|
-
...signal ? { abandonSignal: signal } : {}
|
|
3069
|
-
});
|
|
3070
|
-
params.lease.client = client;
|
|
3071
|
-
params.onClientChange?.(client);
|
|
3072
|
-
} finally {
|
|
3073
|
-
scopeActive = false;
|
|
3074
|
-
}
|
|
2943
|
+
let scopeActive = true;
|
|
2944
|
+
const assertCurrent = () => {
|
|
2945
|
+
if (!scopeActive || params.lease.client !== client) throw new CodexAppServerStartupError("aborted", "Codex app-server request scope is closed");
|
|
2946
|
+
};
|
|
2947
|
+
try {
|
|
2948
|
+
requestOptions();
|
|
2949
|
+
return await params.run(client, () => {
|
|
2950
|
+
assertCurrent();
|
|
2951
|
+
return {
|
|
2952
|
+
...requestOptions(),
|
|
2953
|
+
assertCurrent,
|
|
2954
|
+
...params.options?.assertCurrentAsync ? { withCurrent: async (write) => {
|
|
2955
|
+
await params.options?.assertCurrentAsync?.();
|
|
2956
|
+
assertCurrent();
|
|
2957
|
+
write();
|
|
2958
|
+
} } : {}
|
|
2959
|
+
};
|
|
2960
|
+
});
|
|
2961
|
+
} finally {
|
|
2962
|
+
scopeActive = false;
|
|
3075
2963
|
}
|
|
3076
|
-
throw new Error("Codex app-server selection retry loop exited unexpectedly");
|
|
3077
2964
|
}
|
|
3078
2965
|
async function acquireSharedCodexAppServerClient(options, leased = false) {
|
|
3079
2966
|
const timeoutMs = options?.timeoutMs ?? 0;
|
|
@@ -3084,23 +2971,21 @@ async function acquireSharedCodexAppServerClient(options, leased = false) {
|
|
|
3084
2971
|
const { usesNativeAuth, ...startContext } = context;
|
|
3085
2972
|
const { agentDir, authProfileId, authProfileStore, preparedAuth, authRequirement, startOptions, desktopGeneration } = startContext;
|
|
3086
2973
|
const remainingTimeoutMs = resolveRemainingAcquireTimeout(timeoutMs, startedAt);
|
|
3087
|
-
const
|
|
3088
|
-
const
|
|
2974
|
+
const runtimeArtifactMode = options?.runtimeArtifactMode ?? (options?.expectedRuntimeArtifact ? "capture" : void 0);
|
|
2975
|
+
const keyFor = createSharedCodexAppServerClientKeyResolver({
|
|
2976
|
+
startOptions,
|
|
2977
|
+
agentDir,
|
|
3089
2978
|
authProfileId,
|
|
3090
2979
|
authBindingFingerprint: options?.authBindingFingerprint,
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
const
|
|
3099
|
-
const
|
|
3100
|
-
if (existingClient && existingGeneration && !isCodexDesktopGenerationCurrent(existingGeneration)) {
|
|
3101
|
-
retireSharedCodexAppServerClientIfCurrent(existingClient);
|
|
3102
|
-
entry = getOrCreateSharedClientEntry(state, key);
|
|
3103
|
-
}
|
|
2980
|
+
preparedAuth,
|
|
2981
|
+
authRequirement,
|
|
2982
|
+
usesNativeAuth,
|
|
2983
|
+
desktopGeneration,
|
|
2984
|
+
runtimeArtifactMode,
|
|
2985
|
+
expectedRuntimeArtifact: options?.expectedRuntimeArtifact
|
|
2986
|
+
});
|
|
2987
|
+
const key = keyFor(startOptions);
|
|
2988
|
+
const entry = getOrCreateSharedClientEntry(state, key);
|
|
3104
2989
|
entry.startupAbort ??= new AbortController();
|
|
3105
2990
|
entry.closeWhenIdle = false;
|
|
3106
2991
|
const releasePendingAcquire = retainSharedClientEntry(entry, "pendingAcquires");
|
|
@@ -3129,6 +3014,7 @@ async function acquireSharedCodexAppServerClient(options, leased = false) {
|
|
|
3129
3014
|
...startContext,
|
|
3130
3015
|
lifetime,
|
|
3131
3016
|
entry,
|
|
3017
|
+
onManagedFallback: (fallback) => rekeySharedClientEntry(entry, keyFor(fallback)),
|
|
3132
3018
|
authProfileId: usesNativeAuth || preparedAuth?.kind === "api-key" ? null : authProfileId,
|
|
3133
3019
|
runtimeArtifactMode,
|
|
3134
3020
|
expectedRuntimeArtifact: options?.expectedRuntimeArtifact,
|
|
@@ -3156,6 +3042,10 @@ async function acquireSharedCodexAppServerClient(options, leased = false) {
|
|
|
3156
3042
|
retirePendingSharedClientEntryIfUnclaimed(entry);
|
|
3157
3043
|
observeAcquire(options, { boundary: "cleanup" });
|
|
3158
3044
|
await waitForUnclaimedSharedClientStartup(entry);
|
|
3045
|
+
if (isSharedCodexFallbackJoinError(error)) return acquireSharedCodexAppServerClient({
|
|
3046
|
+
...options,
|
|
3047
|
+
timeoutMs: resolveRemainingAcquireTimeout(timeoutMs, startedAt)
|
|
3048
|
+
}, leased);
|
|
3159
3049
|
throw error;
|
|
3160
3050
|
} finally {
|
|
3161
3051
|
cleanupAbandonSignal?.();
|
|
@@ -3163,10 +3053,6 @@ async function acquireSharedCodexAppServerClient(options, leased = false) {
|
|
|
3163
3053
|
releasePendingAcquire();
|
|
3164
3054
|
}
|
|
3165
3055
|
}
|
|
3166
|
-
function buildCodexAppServerInitializeTimeoutError(client) {
|
|
3167
|
-
const stderr = client?.getStderrDiagnostic();
|
|
3168
|
-
return new CodexAppServerStartupError("timed_out", stderr ? `${CODEX_APP_SERVER_INITIALIZE_TIMEOUT_MESSAGE}; stderr=${JSON.stringify(stderr)}` : CODEX_APP_SERVER_INITIALIZE_TIMEOUT_MESSAGE);
|
|
3169
|
-
}
|
|
3170
3056
|
function createSharedCodexAppServerClientStartup(params) {
|
|
3171
3057
|
const initialized = createDeferred();
|
|
3172
3058
|
const ready = ownCodexStartup(params.lifetime, startInitializedCodexAppServerClient({
|
|
@@ -3185,7 +3071,6 @@ function createSharedCodexAppServerClientStartup(params) {
|
|
|
3185
3071
|
state.liveClients.add(startedClient);
|
|
3186
3072
|
startedClient.addTransportExitHandler((exitedClient) => {
|
|
3187
3073
|
state.liveClients.delete(exitedClient);
|
|
3188
|
-
notifyDesktopGenerationDrainChecks(state);
|
|
3189
3074
|
});
|
|
3190
3075
|
for (const callback of params.entry.onStartedClientCallbacks) callback(startedClient);
|
|
3191
3076
|
retirePendingSharedClientEntryIfUnclaimed(params.entry);
|
|
@@ -3194,7 +3079,10 @@ function createSharedCodexAppServerClientStartup(params) {
|
|
|
3194
3079
|
}).then((client) => {
|
|
3195
3080
|
const state = getSharedCodexAppServerClientState();
|
|
3196
3081
|
params.entry.client = client;
|
|
3082
|
+
params.entry.hasOwnedThreads = () => hasCodexAppServerThreadOwnership(client);
|
|
3197
3083
|
client.addCloseHandler((closedClient) => {
|
|
3084
|
+
clearTimeout(params.entry.idleTimer);
|
|
3085
|
+
params.entry.idleTimer = void 0;
|
|
3198
3086
|
const entry = getCurrentSharedClientEntry(closedClient);
|
|
3199
3087
|
if (entry) state.clients.delete(entry.key);
|
|
3200
3088
|
});
|
|
@@ -3212,6 +3100,7 @@ function createSharedCodexAppServerClientStartup(params) {
|
|
|
3212
3100
|
}
|
|
3213
3101
|
/** Starts a caller-owned client; its assertion never binds ordinary shared-client leases. */
|
|
3214
3102
|
async function createIsolatedCodexAppServerClient(options) {
|
|
3103
|
+
await options?.assertCurrentAsync?.();
|
|
3215
3104
|
options?.assertCurrent?.();
|
|
3216
3105
|
const { context, lifetime, abandonSignal, startedAt, assertCurrent } = await prepareCodexAppServerClient(options);
|
|
3217
3106
|
assertCurrent();
|
|
@@ -3231,13 +3120,13 @@ async function createIsolatedCodexAppServerClient(options) {
|
|
|
3231
3120
|
timeoutMs: resolveRemainingAcquireTimeout(timeoutMs, startedAt),
|
|
3232
3121
|
abandonSignal,
|
|
3233
3122
|
assertCurrent: options?.assertCurrent,
|
|
3123
|
+
assertCurrentAsync: options?.assertCurrentAsync,
|
|
3234
3124
|
onAcquireObservation: options?.onAcquireObservation,
|
|
3235
3125
|
onStartedClient: (client) => {
|
|
3236
3126
|
const state = getSharedCodexAppServerClientState();
|
|
3237
3127
|
state.isolatedClients.add(client);
|
|
3238
3128
|
client.addTransportExitHandler((exitedClient) => {
|
|
3239
3129
|
state.isolatedClients.delete(exitedClient);
|
|
3240
|
-
notifyDesktopGenerationDrainChecks(state);
|
|
3241
3130
|
});
|
|
3242
3131
|
options?.onStartedClient?.(client);
|
|
3243
3132
|
}
|
|
@@ -3257,30 +3146,34 @@ async function startInitializedCodexAppServerClientOnce(params) {
|
|
|
3257
3146
|
const acquireStartedAt = performance.now();
|
|
3258
3147
|
const timeoutMs = params.timeoutMs ?? 0;
|
|
3259
3148
|
const abandonSignal = params.abandonSignal ? AbortSignal.any([params.lifetime.controller.signal, params.abandonSignal]) : params.lifetime.controller.signal;
|
|
3260
|
-
const waitForStartup = (operation, timeoutErrorFactory) => {
|
|
3149
|
+
const waitForStartup = (operation, timeoutErrorFactory, candidateLimitMs) => {
|
|
3261
3150
|
if (abandonSignal.aborted) throw new CodexAppServerStartupError("aborted", "codex app-server initialize aborted");
|
|
3262
|
-
|
|
3151
|
+
const remainingMs = resolveRemainingAcquireTimeout(timeoutMs, acquireStartedAt);
|
|
3152
|
+
return withCodexAppServerAcquireDeadline(candidateLimitMs === void 0 ? remainingMs : remainingMs > 0 ? Math.min(remainingMs / 2, candidateLimitMs) : candidateLimitMs, ownCodexStartup(params.lifetime, operation()), abandonSignal, CODEX_APP_SERVER_INITIALIZE_TIMEOUT_MESSAGE, timeoutErrorFactory);
|
|
3263
3153
|
};
|
|
3264
3154
|
const startOptionsCandidates = resolveManagedFallbackStartOptions(params.startOptions);
|
|
3155
|
+
const yieldInstalledCodex = (index, command, error) => {
|
|
3156
|
+
if (params.startOptions.commandSource !== "resolved-managed" || index + 1 >= startOptionsCandidates.length || readInstalledCodexAppServerStatus(command) === void 0 || abandonSignal.aborted) return false;
|
|
3157
|
+
try {
|
|
3158
|
+
params.assertCurrent?.();
|
|
3159
|
+
} catch {
|
|
3160
|
+
return false;
|
|
3161
|
+
}
|
|
3162
|
+
const ownsFallback = params.onManagedFallback?.(startOptionsCandidates[index + 1]) ?? true;
|
|
3163
|
+
rejectInstalledCodexAppServer(command, error);
|
|
3164
|
+
if (!ownsFallback) throw new SharedCodexFallbackJoinError();
|
|
3165
|
+
return true;
|
|
3166
|
+
};
|
|
3265
3167
|
for (const [index, startOptions] of startOptionsCandidates.entries()) {
|
|
3266
3168
|
params.assertCurrent?.();
|
|
3267
|
-
observeAcquire(params, { boundary: "prestart-artifact-drain" });
|
|
3268
3169
|
const desktopCommand = isManagedCodexDesktopCommand(startOptions.command);
|
|
3269
3170
|
const desktopGeneration = params.desktopGeneration ?? (desktopCommand ? await waitForStartup(waitForCodexDesktopGeneration) : void 0);
|
|
3270
3171
|
const assertStartupCurrent = () => {
|
|
3271
3172
|
params.assertCurrent?.();
|
|
3272
3173
|
if (abandonSignal.aborted) throw new CodexAppServerStartupError("aborted", "codex app-server initialize aborted");
|
|
3273
|
-
if (desktopGeneration && !isCodexDesktopGenerationCurrent(desktopGeneration)) throw new CodexAppServerStartSelectionChangedError();
|
|
3274
3174
|
};
|
|
3275
|
-
const computerUseConfig = resolveCodexComputerUseConfig({ pluginConfig: params.pluginConfig });
|
|
3276
3175
|
const ownsIsolatedCodexHome = params.requestedStartOptions.homeScope !== "user" && !params.requestedStartOptions.env?.CODEX_HOME?.trim();
|
|
3277
|
-
const artifactDrain = desktopGeneration && ownsIsolatedCodexHome && computerUseConfig.enabled && (computerUseConfig.autoInstall || computerUseConfig.pluginCacheMode === "shared") ? createOlderDesktopGenerationDrainWait({
|
|
3278
|
-
generation: desktopGeneration,
|
|
3279
|
-
startOptions,
|
|
3280
|
-
agentDir: params.agentDir
|
|
3281
|
-
}) : void 0;
|
|
3282
3176
|
try {
|
|
3283
|
-
if (artifactDrain) await waitForStartup(() => artifactDrain.promise);
|
|
3284
3177
|
await reconcileCodexComputerUseStartArtifacts({
|
|
3285
3178
|
startOptions,
|
|
3286
3179
|
agentDir: params.agentDir,
|
|
@@ -3298,10 +3191,8 @@ async function startInitializedCodexAppServerClientOnce(params) {
|
|
|
3298
3191
|
});
|
|
3299
3192
|
}
|
|
3300
3193
|
throw error;
|
|
3301
|
-
} finally {
|
|
3302
|
-
artifactDrain?.cancel();
|
|
3303
3194
|
}
|
|
3304
|
-
const runtimeArtifactModule = params.runtimeArtifactMode ? await import("./runtime-artifact-
|
|
3195
|
+
const runtimeArtifactModule = params.runtimeArtifactMode ? await import("./runtime-artifact-CmLWeyJB.mjs") : void 0;
|
|
3305
3196
|
const runtimeArtifactBeforeStart = runtimeArtifactModule ? await runtimeArtifactModule.captureCodexAppServerRuntimeArtifactBeforeStart({
|
|
3306
3197
|
startOptions,
|
|
3307
3198
|
spawnIdentity: resolveCodexAppServerSpawnIdentity(startOptions),
|
|
@@ -3317,7 +3208,8 @@ async function startInitializedCodexAppServerClientOnce(params) {
|
|
|
3317
3208
|
try {
|
|
3318
3209
|
observeAcquire(params, { boundary: "transport-registration" });
|
|
3319
3210
|
client = await waitForStartup(() => {
|
|
3320
|
-
starting = CodexAppServerClient.start(startOptions, () => {
|
|
3211
|
+
starting = CodexAppServerClient.start(startOptions, async () => {
|
|
3212
|
+
await params.assertCurrentAsync?.();
|
|
3321
3213
|
assertStartupCurrent();
|
|
3322
3214
|
resolveRemainingAcquireTimeout(timeoutMs, acquireStartedAt);
|
|
3323
3215
|
});
|
|
@@ -3329,6 +3221,7 @@ async function startInitializedCodexAppServerClientOnce(params) {
|
|
|
3329
3221
|
observeAcquire(params, { boundary: "cleanup" });
|
|
3330
3222
|
await ownCodexStartup(params.lifetime, starting.then((lateClient) => lateClient.closeAndWait(), () => {}));
|
|
3331
3223
|
}
|
|
3224
|
+
if (yieldInstalledCodex(index, startOptions.command, error)) continue;
|
|
3332
3225
|
throw error;
|
|
3333
3226
|
}
|
|
3334
3227
|
client.addCloseHandler((closedClient) => {
|
|
@@ -3348,9 +3241,10 @@ async function startInitializedCodexAppServerClientOnce(params) {
|
|
|
3348
3241
|
params.onStartedClient?.(client);
|
|
3349
3242
|
observeAcquire(params, { boundary: "initialize" });
|
|
3350
3243
|
try {
|
|
3351
|
-
await waitForStartup(() => client.initialize(), () => buildCodexAppServerInitializeTimeoutError(client));
|
|
3244
|
+
await waitForStartup(() => client.initialize(), () => buildCodexAppServerInitializeTimeoutError(client), startOptions.commandSource === "resolved-managed" && index + 1 < startOptionsCandidates.length && readInstalledCodexAppServerStatus(startOptions.command) !== void 0 ? INSTALLED_CODEX_START_TIMEOUT_MS : void 0);
|
|
3245
|
+
if (startOptions.commandSource === "resolved-managed") assertInstalledCodexAppServerVersion(startOptions.command, client.getServerVersion());
|
|
3352
3246
|
} catch (error) {
|
|
3353
|
-
if (startOptions.commandSource === "resolved-managed" && index < startOptionsCandidates.length - 1 && isUnsupportedCodexAppServerVersionError(error)) continue;
|
|
3247
|
+
if (yieldInstalledCodex(index, startOptions.command, error) || startOptions.commandSource === "resolved-managed" && index < startOptionsCandidates.length - 1 && isUnsupportedCodexAppServerVersionError(error)) continue;
|
|
3354
3248
|
throw error;
|
|
3355
3249
|
}
|
|
3356
3250
|
assertStartupCurrent();
|
|
@@ -3379,7 +3273,7 @@ async function startInitializedCodexAppServerClientOnce(params) {
|
|
|
3379
3273
|
...params.authProfileStore ? { authProfileStore: params.authProfileStore } : {},
|
|
3380
3274
|
config: params.config,
|
|
3381
3275
|
onAuthRefreshFailure: () => retireSharedCodexAppServerClientIfCurrent(client)
|
|
3382
|
-
});
|
|
3276
|
+
}, () => refreshSharedClientIdleRetirement(client));
|
|
3383
3277
|
assertStartupCurrent();
|
|
3384
3278
|
observeAcquire(params, { boundary: "auth-handoff" });
|
|
3385
3279
|
const authHandoff = await waitForStartup(() => applyCodexAppServerAuthProfile({
|
|
@@ -3391,34 +3285,24 @@ async function startInitializedCodexAppServerClientOnce(params) {
|
|
|
3391
3285
|
startOptions,
|
|
3392
3286
|
config: params.config,
|
|
3393
3287
|
assertCurrent: assertStartupCurrent,
|
|
3288
|
+
assertCurrentAsync: params.assertCurrentAsync,
|
|
3394
3289
|
...params.authProfileStore ? { authProfileStore: params.authProfileStore } : {}
|
|
3395
3290
|
}));
|
|
3396
3291
|
const ownsInference = startOptions.transport === "stdio" && nativeCommandAtStart && !isCodexAppServerProxyLaunch(startOptions.args);
|
|
3397
3292
|
if (isCodexResponsesOAuth(params.preparedAuth) && (!ownsInference || desktopGeneration || desktopCommand)) throw new Error("ChatGPT subscription sharing requires a managed local Codex process.");
|
|
3398
3293
|
if (ownsInference) {
|
|
3399
3294
|
const prepared = params.preparedAuth;
|
|
3400
|
-
ownCodexInferenceClient(client, startOptions, isCodexResponsesOAuth(prepared) && prepared?.kind === "profile" ? createCodexResponsesOAuth({
|
|
3295
|
+
ownCodexInferenceClient(client, startOptions, isCodexResponsesOAuth(prepared) && prepared?.kind === "profile" ? await waitForStartup(() => createCodexResponsesOAuth({
|
|
3401
3296
|
profileId: prepared.profileId,
|
|
3402
3297
|
store: prepared.store,
|
|
3403
3298
|
fingerprint: prepared.snapshot.secretFreeCacheKey,
|
|
3404
3299
|
agentDir: params.agentDir,
|
|
3405
3300
|
config: params.config
|
|
3406
|
-
}) : void 0);
|
|
3301
|
+
})) : void 0);
|
|
3407
3302
|
}
|
|
3408
3303
|
recordCodexAppServerAuthHandoff(client, authHandoff);
|
|
3409
3304
|
if (runtimeArtifactModule && runtimeArtifact) runtimeArtifactModule.bindCodexAppServerRuntimeArtifact(client, runtimeArtifact);
|
|
3410
3305
|
assertStartupCurrent();
|
|
3411
|
-
const fenceKey = resolveCodexNativeConfigFenceKey({ client });
|
|
3412
|
-
if (fenceKey) client.setThreadSessionRequestGuard(async (options) => {
|
|
3413
|
-
const release = await acquireCodexNativeConfigFence(fenceKey, options);
|
|
3414
|
-
try {
|
|
3415
|
-
assertCodexAppServerClientStartSelectionCurrent({ client });
|
|
3416
|
-
return release;
|
|
3417
|
-
} catch (error) {
|
|
3418
|
-
release();
|
|
3419
|
-
throw error;
|
|
3420
|
-
}
|
|
3421
|
-
}, () => Boolean(retireSharedCodexAppServerClientIfCurrent(client)));
|
|
3422
3306
|
ready = true;
|
|
3423
3307
|
observeAcquire(params, { boundary: "ready" });
|
|
3424
3308
|
return client;
|
|
@@ -3431,34 +3315,11 @@ async function startInitializedCodexAppServerClientOnce(params) {
|
|
|
3431
3315
|
}
|
|
3432
3316
|
throw new Error("Managed Codex app-server fallback candidates were exhausted.");
|
|
3433
3317
|
}
|
|
3434
|
-
function isCodexComputerUseCandidateArtifactsUnavailableError(error) {
|
|
3435
|
-
return error !== null && typeof error === "object" && "code" in error && error.code === "CODEX_COMPUTER_USE_CANDIDATE_ARTIFACTS_UNAVAILABLE";
|
|
3436
|
-
}
|
|
3437
|
-
function resolveManagedFallbackStartOptions(startOptions) {
|
|
3438
|
-
const commands = [startOptions.command, ...startOptions.managedFallbackCommandPaths ?? []];
|
|
3439
|
-
const candidates = [];
|
|
3440
|
-
for (const [index, command] of commands.entries()) {
|
|
3441
|
-
const managedFallbackCommandPaths = commands.slice(index + 1);
|
|
3442
|
-
const candidate = {
|
|
3443
|
-
...startOptions,
|
|
3444
|
-
command
|
|
3445
|
-
};
|
|
3446
|
-
if (managedFallbackCommandPaths.length === 0) delete candidate.managedFallbackCommandPaths;
|
|
3447
|
-
else candidate.managedFallbackCommandPaths = managedFallbackCommandPaths;
|
|
3448
|
-
candidates.push(candidate);
|
|
3449
|
-
}
|
|
3450
|
-
return candidates;
|
|
3451
|
-
}
|
|
3452
3318
|
function detachCurrentSharedClient(client) {
|
|
3453
3319
|
const entry = client && getCurrentSharedClientEntry(client);
|
|
3454
3320
|
return Boolean(entry && getSharedCodexAppServerClientState().clients.delete(entry.key));
|
|
3455
3321
|
}
|
|
3456
|
-
|
|
3457
|
-
if (!detachCurrentSharedClient(client)) return false;
|
|
3458
|
-
client.close();
|
|
3459
|
-
return true;
|
|
3460
|
-
}
|
|
3461
|
-
/** Captures a revocable observation of the exact shared client and native account/config. */
|
|
3322
|
+
/** Captures the physical client lifetime for passive catalog reads. */
|
|
3462
3323
|
function captureSharedCodexAppServerCatalogLifetime(client) {
|
|
3463
3324
|
const isCurrent = captureSharedClientRegistration(client);
|
|
3464
3325
|
const revision = client.getModelCatalogRevision();
|
|
@@ -3468,8 +3329,7 @@ function captureSharedCodexAppServerCatalogLifetime(client) {
|
|
|
3468
3329
|
function captureSharedClientRegistration(client) {
|
|
3469
3330
|
const state = getSharedCodexAppServerClientState();
|
|
3470
3331
|
const entry = getCurrentSharedClientEntry(client);
|
|
3471
|
-
|
|
3472
|
-
return () => entry !== void 0 && state.clients.get(entry.key) === entry && entry.client === client && !entry.closeWhenIdle && !entry.closeError && !client.getCloseError() && (!generation || isCodexDesktopGenerationCurrent(generation));
|
|
3332
|
+
return () => entry !== void 0 && state.clients.get(entry.key) === entry && entry.client === client && !entry.closeWhenIdle && !entry.closeError && !client.getCloseError();
|
|
3473
3333
|
}
|
|
3474
3334
|
function retainSharedCodexAppServerClientIfCurrent(client) {
|
|
3475
3335
|
const entry = getCurrentSharedClientEntry(client);
|
|
@@ -3483,47 +3343,10 @@ function captureCodexAppServerClientLifetime(client, requiredOwnership) {
|
|
|
3483
3343
|
const isCurrent = requiredOwnership !== "connection" && state.isolatedClients.has(client) ? () => state.isolatedClients.has(client) && !client.getCloseError() : captureSharedClientRegistration(client);
|
|
3484
3344
|
const assertCurrent = () => {
|
|
3485
3345
|
if (!isCurrent()) throw new CodexAdoptedThreadActiveError("Codex app-server connection changed during thread preparation; reconnect before continuing");
|
|
3486
|
-
assertCodexAppServerClientStartSelectionCurrent({ client });
|
|
3487
3346
|
};
|
|
3488
3347
|
assertCurrent();
|
|
3489
3348
|
return assertCurrent;
|
|
3490
3349
|
}
|
|
3491
|
-
function createOlderDesktopGenerationDrainWait(params) {
|
|
3492
|
-
const targetHome = resolveCodexNativeConfigFenceKey({
|
|
3493
|
-
startOptions: params.startOptions,
|
|
3494
|
-
agentDir: params.agentDir
|
|
3495
|
-
});
|
|
3496
|
-
if (!targetHome) return {
|
|
3497
|
-
promise: Promise.resolve(),
|
|
3498
|
-
cancel: () => void 0
|
|
3499
|
-
};
|
|
3500
|
-
const state = getSharedCodexAppServerClientState();
|
|
3501
|
-
const { promise, resolve: resolveWait } = createDeferred();
|
|
3502
|
-
const cancel = () => {
|
|
3503
|
-
state.desktopGenerationDrainChecks.delete(check);
|
|
3504
|
-
resolveWait();
|
|
3505
|
-
};
|
|
3506
|
-
const check = () => {
|
|
3507
|
-
if (!hasLiveOlderDesktopGenerationClient({
|
|
3508
|
-
state,
|
|
3509
|
-
generation: params.generation,
|
|
3510
|
-
targetHome
|
|
3511
|
-
})) cancel();
|
|
3512
|
-
};
|
|
3513
|
-
state.desktopGenerationDrainChecks.add(check);
|
|
3514
|
-
check();
|
|
3515
|
-
return {
|
|
3516
|
-
promise,
|
|
3517
|
-
cancel
|
|
3518
|
-
};
|
|
3519
|
-
}
|
|
3520
|
-
function hasLiveOlderDesktopGenerationClient(params) {
|
|
3521
|
-
for (const clients of [params.state.liveClients, params.state.isolatedClients]) for (const client of clients) {
|
|
3522
|
-
const metadata = params.state.startMetadata.get(client);
|
|
3523
|
-
if (metadata?.desktopGeneration && metadata.desktopGeneration.epoch < params.generation.epoch && resolveCodexNativeConfigFenceKey({ client }) === params.targetHome) return true;
|
|
3524
|
-
}
|
|
3525
|
-
return false;
|
|
3526
|
-
}
|
|
3527
3350
|
async function clearSharedCodexAppServerClientIfCurrentAndWait(client, options) {
|
|
3528
3351
|
if (!detachCurrentSharedClient(client)) return false;
|
|
3529
3352
|
await client.closeAndWait(options);
|
|
@@ -3555,4 +3378,4 @@ function clearSharedCodexAppServerClientIfCurrentAndUnclaimed(client) {
|
|
|
3555
3378
|
};
|
|
3556
3379
|
}
|
|
3557
3380
|
//#endregion
|
|
3558
|
-
export {
|
|
3381
|
+
export { resolveBundledComputerUseMarketplacePath as $, hasCodexAppServerLiveThread as A, retainCodexAppServerLiveThread as B, getCodexInferenceThread as C, consumeCodexAppServerLiveThread as D, claimCodexAppServerLiveThread as E, prepareCodexWorkspaceReferences as F, rememberCodexRateLimitsRead as G, unsubscribeCodexAppServerLiveThread as H, protectCodexAppServerLiveThread as I, recordCodexTurnForkSettings as J, createCodexEphemeralThreadPolicy as K, readCodexClientSessionMeta as L, isCodexAppServerClientRuntimeLive as M, isCodexAppServerLiveThreadClaimed as N, ensureCodexAppServerClientRuntime as O, isCodexAppServerLiveThreadProtected as P, resolveCodexAppServerPreparedAuthHandoff as Q, readCodexLiveThreadEphemeralPolicy as R, bindCodexInferenceThread as S, prepareCodexInferenceThreadConfig as T, readCodexRateLimitsRevision as U, revertCodexAppServerLiveThreadInstructions as V, readRecentCodexRateLimits as W, reconcileCodexComputerUseStartArtifacts as X, requireCodexThreadForkSettings as Y, resolveCodexAppServerAuthAccountCacheKey as Z, CodexThreadBindingConflictError as _, createIsolatedCodexAppServerClient as a, assertNotSymlink as at, nativeHookRelayUnregisterQueue as b, readCodexAppServerClientDesktopGeneration as c, TURN_TERMINAL_SETTLEMENT_TIMEOUT_MS as ct, releaseCodexAppServerClientLease as d, resolveCodexStartupTimeoutMs as dt, resolveClientManagedBundledMarketplacePath as et, releaseLeasedSharedCodexAppServerClient as f, withCodexStartupTimeout as ft, CodexAdoptedThreadActiveError as g, withCodexAppServerClientRequestScope as h, clearSharedCodexAppServerClientIfCurrentAndWait as i, ensureCodexComputerUseSharedPluginCache as it, hasCodexAppServerSiblingThreadWork as j, forgetCodexWorkspaceReferences as k, readCodexAppServerClientDesktopGenerationFingerprint as l, isCodexAppServerStartupError as lt, shared_client_exports as m, captureSharedCodexAppServerCatalogLifetime as n, isLegacyCodexComputerUsePluginDisabled as nt, getLeasedSharedCodexAppServerClient as o, CodexAppServerStartupError as ot, retainSharedCodexAppServerClientIfCurrent as p, recordCodexThreadForkSettings as q, clearSharedCodexAppServerClientIfCurrentAndUnclaimed as r, resolveManagedCodexComputerUseConfig as rt, getSharedCodexAppServerClient as s, TURN_FINALIZE_DRAIN_ABORT_GRACE_MS as st, captureCodexAppServerClientLifetime as t, hasLegacyCodexComputerUseMcpPolicy as tt, readCodexAppServerClientProcessIdentity as u, resolveCodexGatewayTimeoutWithGraceMs as ut, CodexThreadClientReplacementError as v, getCodexInferenceThreadQualification as w, assertCodexInferenceRouteConfig as x, CodexThreadStartRequestError as y, releaseCodexAppServerLiveThread as z };
|