@openclaw/codex 2026.9.1 → 2026.9.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.
Files changed (67) hide show
  1. package/dist/api.js +6 -6
  2. package/dist/{attempt-client-cleanup-DYHcRQAa.js → attempt-client-cleanup-Bp1ZOnk2.js} +76 -32
  3. package/dist/{attempt-context-DmQUNWwT.js → attempt-context-CSazkWns.js} +6 -6
  4. package/dist/{bounded-turn-wzJrwKKe.js → bounded-turn-DxGJRYbY.js} +46 -45
  5. package/dist/{capabilities-dIjNVCYH.js → capabilities-B1mgvpP8.js} +2 -1
  6. package/dist/cli-metadata.js +1 -1
  7. package/dist/{command-formatters-CLHhEB1Q.js → command-formatters-DSbGMXA0.js} +2 -2
  8. package/dist/{command-handlers-CTGb2csu.js → command-handlers-DOJvGv6-.js} +146 -74
  9. package/dist/{compact-_t0HQrUS.js → compact-Y_xBqrHN.js} +83 -48
  10. package/dist/{config-BhmfC1s6.js → config-CyapYSji.js} +47 -105
  11. package/dist/config-utils-C57JiJrU.js +69 -0
  12. package/dist/doctor-contract-api.js +4 -5
  13. package/dist/{dynamic-tools-BU9tmlYm.js → dynamic-tools-BwpvTxaX.js} +678 -638
  14. package/dist/{effective-mcp-catalog-DzYBW4h1.js → effective-mcp-catalog-CY9Jn4bA.js} +4 -3
  15. package/dist/{event-projector-assistant-message-DHRFXKbS.js → event-projector-assistant-message-B9kp6iGC.js} +11 -2
  16. package/dist/{event-projector-usage-C5mcrGjp.js → event-projector-usage-ZqEVbAEY.js} +30 -13
  17. package/dist/{harness-DXVZ5II5.js → harness-Czh2Sdoc.js} +36 -13
  18. package/dist/harness.js +1 -1
  19. package/dist/{image-payload-sanitizer-CnfoUPCE.js → image-payload-sanitizer-tupAr-2o.js} +29 -15
  20. package/dist/index.js +68 -84
  21. package/dist/{isolated-completion-kg9kv4iH.js → isolated-completion-CRh-51AK.js} +9 -21
  22. package/dist/{managed-binary-4-Vjz5GH.js → managed-binary-DcpnJF9x.js} +105 -73
  23. package/dist/media-understanding-provider.js +1 -1
  24. package/dist/{model-catalog-CUM68Hkl.js → model-catalog-DT5vo6qo.js} +5 -5
  25. package/dist/{models-sYnEc0gd.js → models-CcrgSMQR.js} +4 -4
  26. package/dist/{native-subagent-monitor-CnH147jH.js → native-subagent-monitor-B3bvQGcg.js} +12 -11
  27. package/dist/{node-exec-server.runtime-CstNHCmC.js → node-exec-server.runtime-nfbUOtUB.js} +3 -3
  28. package/dist/{plugin-approval-roundtrip-CNe-Xrjx.js → plugin-approval-roundtrip-aQVdyL5g.js} +1 -1
  29. package/dist/{plugin-marketplace-discovery-CfFlKqDl.js → plugin-marketplace-discovery-B7gHXJ3d.js} +35 -22
  30. package/dist/{plugin-metadata-cache-BFrPhb2c.js → plugin-metadata-cache-BwCLTY_U.js} +5 -5
  31. package/dist/{provider-capabilities-DW5p4k9w.js → provider-capabilities-BpG9Ltc5.js} +2 -2
  32. package/dist/{rate-limits-CawQJfUS.js → rate-limits-Fx_l4eNa.js} +1 -1
  33. package/dist/{request-DYAI5FQE.js → request-C8H22rPi.js} +2 -2
  34. package/dist/{run-attempt-D1hJO4fX.js → run-attempt-BzthFQSM.js} +977 -723
  35. package/dist/{runtime-artifact-C3jVimFn.js → runtime-artifact-Bh_gf6-t.js} +3 -3
  36. package/dist/{session-binding-BHuTCRZQ.js → session-binding-4Ki04sW-.js} +94 -282
  37. package/dist/session-binding-record-CyaXZvTe.js +270 -0
  38. package/dist/{session-catalog-yyvTWFOw.js → session-catalog-B47uwekb.js} +266 -114
  39. package/dist/{session-cli-CmFEXMAM.js → session-cli-BjLhpmS1.js} +1 -1
  40. package/dist/session-history-DWmMqiqW.js +93 -0
  41. package/dist/session-history-read-LHldwvyh.js +36 -0
  42. package/dist/session-history-worker-runtime.js +48 -0
  43. package/dist/{settled-turn-context-D3SNWtUn.js → session-history.worker-zZVcx0ME.js} +30 -31
  44. package/dist/session-history.worker.js +2 -0
  45. package/dist/{session-initialization-BeWzjGiR.js → session-initialization-BCFVnLL4.js} +2 -1
  46. package/dist/{session-permission-policy-DeWVTCMj.js → session-permission-policy-BaueHmSj.js} +1 -1
  47. package/dist/{session-retirement-BujDjXVF.js → session-retirement-DNdmYdFc.js} +7 -7
  48. package/dist/{session-upstream-marker-C351-5Qw.js → session-upstream-marker-DReTpGz6.js} +4 -3
  49. package/dist/settled-turn-context-BOM3Y1pl.js +45 -0
  50. package/dist/{settled-turn-finalizer-BVJx4yoc.js → settled-turn-finalizer-BI-b1sry.js} +53 -42
  51. package/dist/{shared-client-DxcfF9KX.js → shared-client-CKhX2kFt.js} +279 -268
  52. package/dist/{side-question-BTZAII4l.js → side-question-B6DWAw1A.js} +85 -36
  53. package/dist/{thread-lifecycle-DAcEJ_Om.js → thread-lifecycle-DPK30jad.js} +382 -388
  54. package/dist/{thread-ownership-zGokd8i1.js → thread-ownership-CbucAmmp.js} +5 -5
  55. package/dist/thread-policy-CTalhWFy.js +105 -0
  56. package/dist/{thread-resume-C7pyVKeW.js → thread-resume-BLgqkUc1.js} +7 -7
  57. package/dist/{transcript-mirror-DTUxFWa_.js → transcript-mirror-_njEB84z.js} +67 -125
  58. package/dist/transcript-mirror-attestation-Byl34PC-.js +76 -0
  59. package/dist/{transport-stdio-CyPldczm.js → transport-stdio-CzTngV0j.js} +10 -8
  60. package/dist/{upstream-session-fork-CYlBIGVt.js → upstream-session-fork-1fwbNKzQ.js} +85 -165
  61. package/dist/{usage-Bj-rrzkR.js → usage-i9fv5-4m.js} +3 -3
  62. package/dist/{web-search-provider.runtime-D2FWSK4w.js → web-search-provider.runtime-DKQn67A7.js} +3 -3
  63. package/package.json +6 -6
  64. package/dist/binding-connection-E6uDsPlx.js +0 -45
  65. package/dist/launch-args-RXQwn8zV.js +0 -90
  66. package/dist/session-history-C5J1AKzG.js +0 -87
  67. package/dist/thread-policy-g4KbJPzp.js +0 -54
@@ -1,19 +1,19 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
- import { t as isCodexAppServerProxyLaunch } from "./launch-args-RXQwn8zV.js";
3
- import { F as resolveCodexAppServerHomeDir, I as resolveCodexAppServerLocalHomeDir, L as resolveCodexAppServerUserHomeDir, R as withEphemeralCodexAuthStore, a as resolveCodexAppServerStartOptionsForAgent, i as resolveCodexAppServerRuntimeOptions, o as resolveCodexComputerUseConfig, t as codexAppServerStartOptionsKey } from "./config-BhmfC1s6.js";
4
- import { c as resolveFirstExistingMacOSDesktopCodexBundledMarketplacePath, d as resolveMacOSDesktopCodexComputerUseServiceAppCandidates, l as resolveMacOSDesktopCodexAppPathCandidates, n as resolveManagedCodexAppServerStartOptions, o as CODEX_APP_SERVER_VERSION, r as resolveManagedCodexNativeCommand, s as MIN_SUPPORTED_CODEX_APP_SERVER_VERSION, t as isManagedCodexDesktopCommand, u as resolveMacOSDesktopCodexBundledMarketplaceCandidates } from "./managed-binary-4-Vjz5GH.js";
5
- import { o as isCodexAppServerNativeAuthProfile } from "./session-binding-BHuTCRZQ.js";
6
- import { a as hasCodexAppServerNaturalExit, i as closeCodexAppServerTransportAndWait, n as resolveCodexAppServerSpawnEnv, r as closeCodexAppServerTransport, t as createStdioTransport } from "./transport-stdio-CyPldczm.js";
2
+ import { B as isJsonObject, F as withEphemeralCodexAuthStore, M as resolveCodexAppServerHomeDir, N as resolveCodexAppServerLocalHomeDir, P as resolveCodexAppServerUserHomeDir, V as isRpcResponse, a as resolveCodexAppServerStartOptionsForAgent, i as resolveCodexAppServerRuntimeOptions, o as resolveCodexComputerUseConfig, t as codexAppServerStartOptionsKey } from "./config-CyapYSji.js";
3
+ import { c as resolveFirstExistingMacOSDesktopCodexBundledMarketplacePath, d as resolveMacOSDesktopCodexComputerUseServiceAppCandidates, f as isCodexAppServerProxyLaunch, l as resolveMacOSDesktopCodexAppPathCandidates, n as resolveManagedCodexAppServerStartOptions, o as CODEX_APP_SERVER_VERSION, r as resolveManagedCodexNativeCommand, s as MIN_SUPPORTED_CODEX_APP_SERVER_VERSION, t as isManagedCodexDesktopCommand, u as resolveMacOSDesktopCodexBundledMarketplaceCandidates } from "./managed-binary-DcpnJF9x.js";
4
+ import { a as isCodexAppServerNativeAuthProfile } from "./session-binding-4Ki04sW-.js";
5
+ import { a as hasCodexAppServerNaturalExit, i as closeCodexAppServerTransportAndWait, n as resolveCodexAppServerSpawnEnv, r as closeCodexAppServerTransport, t as createStdioTransport } from "./transport-stdio-CzTngV0j.js";
7
6
  import { isRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
7
+ import { createHash, randomUUID } from "node:crypto";
8
+ import { addTimerTimeoutGraceMs, parseStrictNonNegativeInteger, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
9
+ import { runExec } from "openclaw/plugin-sdk/process-runtime";
8
10
  import fs from "node:fs/promises";
9
11
  import path from "node:path";
10
12
  import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
11
- import { addTimerTimeoutGraceMs, parseStrictNonNegativeInteger, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
12
13
  import { AgentHarnessPreflightError, OPENCLAW_VERSION, embeddedAgentLog, formatErrorMessage, formatToolExecutionErrorMessage, normalizeQuestionTimeoutSeconds, resolveToolExecutionErrorKind } from "openclaw/plugin-sdk/agent-harness-runtime";
13
14
  import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
14
15
  import { createZstdDecompress } from "node:zlib";
15
16
  import { root } from "openclaw/plugin-sdk/file-access-runtime";
16
- import { createHash, randomUUID } from "node:crypto";
17
17
  import fsSync, { constants as constants$1, existsSync, watch } from "node:fs";
18
18
  import os from "node:os";
19
19
  import { isDeepStrictEqual } from "node:util";
@@ -21,7 +21,6 @@ import { ensureAuthProfileStore, findPersistedAuthProfileCredential, loadAuthPro
21
21
  import { hasUsableOAuthCredential, resolveAuthProfileOrder, resolveOpenAICodexAuthIdentity } from "openclaw/plugin-sdk/provider-auth";
22
22
  import { readSecretFile } from "openclaw/plugin-sdk/secret-file";
23
23
  import { assertNoSymlinkParents, withTimeout } from "openclaw/plugin-sdk/security-runtime";
24
- import { runExec } from "openclaw/plugin-sdk/process-runtime";
25
24
  import { EventEmitter } from "node:events";
26
25
  import { createInterface } from "node:readline";
27
26
  import { coerceErrorMessage, toStringifiedError } from "openclaw/plugin-sdk/error-runtime";
@@ -33,21 +32,6 @@ import net from "node:net";
33
32
  import { PassThrough, Writable } from "node:stream";
34
33
  import { StringDecoder } from "node:string_decoder";
35
34
  import WebSocket from "ws";
36
- //#region extensions/codex/src/app-server/protocol.ts
37
- /** Namespace Codex keeps directly model-visible without exposing it to Code Mode guests. */
38
- const CODEX_OPENCLAW_DIRECT_DYNAMIC_TOOL_NAMESPACE = "openclaw_direct";
39
- function flattenCodexDynamicToolFunctions(tools) {
40
- return (tools ?? []).flatMap((tool) => tool.type === "namespace" ? tool.tools : [tool]);
41
- }
42
- const CODEX_INTERACTIVE_THREAD_SOURCE_KINDS = ["cli", "vscode"];
43
- const CODEX_INTERACTIVE_CUSTOM_THREAD_SOURCES = ["atlas", "chatgpt"];
44
- function isJsonObject(value) {
45
- return isRecord(value);
46
- }
47
- function isRpcResponse(message) {
48
- return "id" in message && !("method" in message);
49
- }
50
- //#endregion
51
35
  //#region extensions/codex/src/session-catalog-provenance.ts
52
36
  const MAX_SESSION_META_BYTES = 1048576;
53
37
  const SESSION_META_READ_CHUNK_BYTES = 65536;
@@ -979,6 +963,7 @@ function resolveCodexAppServerAuthProfileIdForAgent(params) {
979
963
  }
980
964
  function ensureCodexAppServerAuthProfileStore(params) {
981
965
  return ensureAuthProfileStore(params.agentDir, {
966
+ profileId: params.authProfileId,
982
967
  allowKeychainPrompt: false,
983
968
  config: params.config,
984
969
  externalCliProviderIds: CODEX_APP_SERVER_EXTERNAL_CLI_PROVIDER_IDS,
@@ -1306,11 +1291,12 @@ function withoutClearedCodexHomeEnv(clearEnv) {
1306
1291
  return filtered.length === clearEnv.length ? clearEnv : filtered;
1307
1292
  }
1308
1293
  async function applyCodexAppServerAuthProfile(params) {
1294
+ params.assertCurrent?.();
1309
1295
  if (!params.preparedAuth && params.authProfileId === null) {
1310
- await assertNativeCodexAccountMatchesRoute(params.client, params.authRequirement);
1296
+ await assertNativeCodexAccountMatchesRoute(params.client, params.authRequirement, params.assertCurrent);
1311
1297
  return;
1312
1298
  }
1313
- const loginParams = params.preparedAuth?.kind === "profile" ? params.preparedAuth.snapshot.loginParams : params.preparedAuth?.kind === "api-key" ? {
1299
+ let loginParams = params.preparedAuth?.kind === "profile" ? params.preparedAuth.snapshot.loginParams : params.preparedAuth?.kind === "api-key" ? {
1314
1300
  type: "apiKey",
1315
1301
  apiKey: params.preparedAuth.apiKey
1316
1302
  } : await resolveCodexAppServerAuthProfileLoginParams({
@@ -1320,18 +1306,16 @@ async function applyCodexAppServerAuthProfile(params) {
1320
1306
  config: params.config
1321
1307
  });
1322
1308
  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.");
1323
- if (!loginParams) {
1324
- if (params.authRequirement !== "api-key" || params.startOptions?.transport !== "stdio") return;
1309
+ if (!loginParams && params.authRequirement === "api-key" && params.startOptions?.transport === "stdio") {
1325
1310
  const env = resolveCodexAppServerSpawnEnv(params.startOptions, process.env);
1326
- const fallbackLoginParams = await resolveCodexAppServerFallbackApiKeyLoginParams({
1311
+ loginParams = await resolveCodexAppServerFallbackApiKeyLoginParams({
1327
1312
  client: params.client,
1328
1313
  env,
1329
- codexCliAuthEnv: process.env
1314
+ codexCliAuthEnv: process.env,
1315
+ assertCurrent: params.assertCurrent
1330
1316
  });
1331
- if (fallbackLoginParams) await params.client.request("account/login/start", fallbackLoginParams);
1332
- return;
1333
1317
  }
1334
- await params.client.request("account/login/start", loginParams);
1318
+ if (loginParams) await params.client.request("account/login/start", loginParams, { assertCurrent: params.assertCurrent });
1335
1319
  }
1336
1320
  /**
1337
1321
  * Native-home connections are verified, never logged into. Both directions of the
@@ -1340,9 +1324,9 @@ async function applyCodexAppServerAuthProfile(params) {
1340
1324
  * ChatGPT plan. An absent account is left alone because the native home may serve a
1341
1325
  * custom model provider that reports no OpenAI account at all.
1342
1326
  */
1343
- async function assertNativeCodexAccountMatchesRoute(client, authRequirement) {
1327
+ async function assertNativeCodexAccountMatchesRoute(client, authRequirement, assertCurrent) {
1344
1328
  if (!authRequirement) return;
1345
- const response = await client.request("account/read", { refreshToken: false });
1329
+ const response = await client.request("account/read", { refreshToken: false }, { assertCurrent });
1346
1330
  const accountType = isJsonObject(response.account) ? response.account.type : void 0;
1347
1331
  if (authRequirement === "subscription") {
1348
1332
  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.");
@@ -1430,7 +1414,7 @@ async function resolveCodexAppServerAuthProfileLoginParamsInternal(params) {
1430
1414
  async function resolveCodexAppServerFallbackApiKeyLoginParams(params) {
1431
1415
  const apiKey = readFirstNonEmptyEnv(params.env, CODEX_APP_SERVER_API_KEY_ENV_VARS) ?? await readCodexCliAuthFileApiKey(params.codexCliAuthEnv);
1432
1416
  if (!apiKey) return;
1433
- if ((await params.client.request("account/read", { refreshToken: false })).account) return;
1417
+ if ((await params.client.request("account/read", { refreshToken: false }, { assertCurrent: params.assertCurrent })).account) return;
1434
1418
  return {
1435
1419
  type: "apiKey",
1436
1420
  apiKey
@@ -1478,7 +1462,10 @@ function resolveCodexCliAuthFileApiKeyCacheKey(env) {
1478
1462
  async function resolveLoginParamsForCredential(profileId, credential, params) {
1479
1463
  if (credential.type === "api_key") {
1480
1464
  const apiKey = (await resolveApiKeyForProfile({
1481
- store: params.preferStoreCredential ? params.store : ensureAuthProfileStore(params.agentDir, { allowKeychainPrompt: false }),
1465
+ store: params.preferStoreCredential ? params.store : ensureAuthProfileStore(params.agentDir, {
1466
+ allowKeychainPrompt: false,
1467
+ profileId
1468
+ }),
1482
1469
  profileId,
1483
1470
  agentDir: params.agentDir
1484
1471
  }))?.apiKey?.trim();
@@ -1489,7 +1476,10 @@ async function resolveLoginParamsForCredential(profileId, credential, params) {
1489
1476
  }
1490
1477
  if (credential.type === "token") {
1491
1478
  const accessToken = (await resolveApiKeyForProfile({
1492
- store: params.preferStoreCredential ? params.store : ensureAuthProfileStore(params.agentDir, { allowKeychainPrompt: false }),
1479
+ store: params.preferStoreCredential ? params.store : ensureAuthProfileStore(params.agentDir, {
1480
+ allowKeychainPrompt: false,
1481
+ profileId
1482
+ }),
1493
1483
  profileId,
1494
1484
  agentDir: params.agentDir
1495
1485
  }))?.apiKey?.trim();
@@ -1548,7 +1538,7 @@ async function resolveOAuthCredentialForCodexAppServer(profileId, credential, pa
1548
1538
  agentDir: ownerAgentDir,
1549
1539
  forceRefresh: params.forceRefresh && Boolean(persistedOAuthCredential)
1550
1540
  });
1551
- const refreshed = useScopedCredential ? void 0 : loadAuthProfileStoreForSecretsRuntime(ownerAgentDir).profiles[profileId];
1541
+ const refreshed = useScopedCredential ? void 0 : loadAuthProfileStoreForSecretsRuntime(ownerAgentDir, { profileId }).profiles[profileId];
1552
1542
  const refreshedOAuthCredential = refreshed?.type === "oauth" && isCodexAppServerAuthProvider(refreshed.provider) ? refreshed : void 0;
1553
1543
  if (refreshedOAuthCredential && isDeepStrictEqual(params.store.profiles[profileId], credential)) params.store.profiles[profileId] = refreshedOAuthCredential;
1554
1544
  const storedCredential = store.profiles[profileId];
@@ -2555,8 +2545,9 @@ function hasPendingDynamicToolTerminalDiagnostic(params) {
2555
2545
  /** Resolves per-tool timeout, applying media/message defaults and hard caps. */
2556
2546
  function resolveDynamicToolCallTimeoutMs(params) {
2557
2547
  const args = isJsonObject(params.call.arguments) ? params.call.arguments : void 0;
2558
- if (params.call.tool === "ask_user" || params.call.tool === "secrets" && args?.action === "request") try {
2559
- return normalizeQuestionTimeoutSeconds(args?.timeoutSeconds) * 1e3 + CODEX_DYNAMIC_TOOL_TIMEOUT_SECONDS_GRACE_MS;
2548
+ if (params.call.tool === "openclaw" || params.call.tool === "ask_user" || params.call.tool === "secrets" && args?.action === "request") try {
2549
+ const timeoutSeconds = params.call.tool === "openclaw" ? void 0 : args?.timeoutSeconds;
2550
+ return normalizeQuestionTimeoutSeconds(timeoutSeconds) * 1e3 + CODEX_DYNAMIC_TOOL_TIMEOUT_SECONDS_GRACE_MS;
2560
2551
  } catch {
2561
2552
  return CODEX_DYNAMIC_TOOL_TIMEOUT_MS;
2562
2553
  }
@@ -2763,6 +2754,18 @@ var definitions = {
2763
2754
  ],
2764
2755
  "type": "string"
2765
2756
  }] },
2757
+ "AsyncUserInputQuestion": {
2758
+ "additionalProperties": false,
2759
+ "properties": {
2760
+ "options": {
2761
+ "items": { "type": "string" },
2762
+ "type": ["array", "null"]
2763
+ },
2764
+ "title": { "type": "string" }
2765
+ },
2766
+ "required": ["title"],
2767
+ "type": "object"
2768
+ },
2766
2769
  "ByteRange": {
2767
2770
  "properties": {
2768
2771
  "end": {
@@ -3716,6 +3719,10 @@ var definitions = {
3716
3719
  "description": "Identifier for this thread. Codex-generated thread IDs are UUIDv7.",
3717
3720
  "type": "string"
3718
3721
  },
3722
+ "model": {
3723
+ "description": "Current configured model when loaded, otherwise the latest persisted model. Null when unavailable. This is not per-turn execution telemetry.",
3724
+ "type": ["string", "null"]
3725
+ },
3719
3726
  "modelProvider": {
3720
3727
  "description": "Model provider used for this thread (for example, 'openai').",
3721
3728
  "type": "string"
@@ -3740,6 +3747,10 @@ var definitions = {
3740
3747
  "description": "Canonical project assignment owned by app-server, if any.",
3741
3748
  "type": ["string", "null"]
3742
3749
  },
3750
+ "reasoningEffort": {
3751
+ "anyOf": [{ "$ref": "#/definitions/ReasoningEffort" }, { "type": "null" }],
3752
+ "description": "Current configured reasoning effort when loaded, otherwise the latest persisted effort. Null when unset or unavailable. This is not per-turn execution telemetry."
3753
+ },
3743
3754
  "recencyAt": {
3744
3755
  "description": "Unix timestamp (in seconds) used for thread recency ordering.",
3745
3756
  "format": "int64",
@@ -3872,6 +3883,11 @@ var definitions = {
3872
3883
  "anyOf": [{ "$ref": "#/definitions/MessagePhase" }, { "type": "null" }],
3873
3884
  "default": null
3874
3885
  },
3886
+ "questions": {
3887
+ "default": null,
3888
+ "items": { "$ref": "#/definitions/AsyncUserInputQuestion" },
3889
+ "type": ["array", "null"]
3890
+ },
3875
3891
  "text": { "type": "string" },
3876
3892
  "type": {
3877
3893
  "enum": ["agentMessage"],
@@ -5074,6 +5090,22 @@ function assertCodexTurnStartResponse(value) {
5074
5090
  const normalized = normalizeWithDefaults(turnStartResponseSchema, normalizeTurnStartResponse(value));
5075
5091
  return assertCodexShape(validateTurnStartResponse, normalized, "turn/start response");
5076
5092
  }
5093
+ /** Only the current text prompt may be echoed; capabilities and historical items are not passive. */
5094
+ function assertCodexPassiveTurnItems(items, prompt, taskLabel) {
5095
+ let promptEchoSeen = false;
5096
+ for (const item of items) {
5097
+ if (item.type === "agentMessage" || item.type === "reasoning") continue;
5098
+ if (item.type === "userMessage" && !promptEchoSeen) {
5099
+ const content = Array.isArray(item.content) ? item.content : [];
5100
+ const input = content[0];
5101
+ if (content.length === 1 && isJsonObject(input) && input.type === "text" && input.text === prompt) {
5102
+ promptEchoSeen = true;
5103
+ continue;
5104
+ }
5105
+ }
5106
+ throw new Error(`Codex ${taskLabel} returned unexpected native item: ${item.type}`);
5107
+ }
5108
+ }
5077
5109
  /** Reads Codex dynamic-tool call params, returning undefined for invalid payloads. */
5078
5110
  function readCodexDynamicToolCallParams(value) {
5079
5111
  return readCodexShape(validateDynamicToolCallParams, normalizeWithDefaults(dynamicToolCallParamsSchema, value));
@@ -5176,6 +5208,9 @@ var CodexAppServerRpcError = class extends Error {
5176
5208
  this.method = method;
5177
5209
  }
5178
5210
  };
5211
+ function isCodexThreadReadMissingError(error, threadId) {
5212
+ return error instanceof CodexAppServerRpcError && error.method === "thread/read" && error.code === -32600 && error.message === `thread not loaded: ${threadId}`;
5213
+ }
5179
5214
  function formatCodexAppServerRpcErrorMessage(error, method) {
5180
5215
  const message = error.message || `${method} failed`;
5181
5216
  const detail = readCodexAppServerRpcReloginDetail(error.data);
@@ -5972,7 +6007,11 @@ var CodexAppServerClient = class CodexAppServerClient {
5972
6007
  pending.reject(error);
5973
6008
  }
5974
6009
  this.pending.clear();
5975
- for (const handler of this.closeHandlers) handler(this);
6010
+ for (const handler of this.closeHandlers) try {
6011
+ handler(this);
6012
+ } catch (closeError) {
6013
+ embeddedAgentLog.warn("codex app-server close handler failed", { error: closeError });
6014
+ }
5976
6015
  }
5977
6016
  };
5978
6017
  function defaultServerRequestResponse(request) {
@@ -6018,7 +6057,7 @@ function assertSupportedCodexAppServerVersion(response) {
6018
6057
  if (!detectedVersion) throw new CodexAppServerVersionError(detectedVersion);
6019
6058
  const detected = parse(detectedVersion);
6020
6059
  if (!detected || detected.compare("0.149.0") < 0) throw new CodexAppServerVersionError(detectedVersion);
6021
- if (detected.compare("0.152.1") > 0) embeddedAgentLog.warn("codex app-server is newer than OpenClaw's managed runtime; continuing with normal startup validation", {
6060
+ if (detected.compare("0.153.4") > 0) embeddedAgentLog.warn("codex app-server is newer than OpenClaw's managed runtime; continuing with normal startup validation", {
6022
6061
  detectedVersion,
6023
6062
  validatedVersion: CODEX_APP_SERVER_VERSION
6024
6063
  });
@@ -6597,7 +6636,10 @@ var shared_client_exports = /* @__PURE__ */ __exportAll({
6597
6636
  const CODEX_APP_SERVER_INITIALIZE_TIMEOUT_MESSAGE = "codex app-server initialize timed out";
6598
6637
  const SHARED_CODEX_APP_SERVER_CLIENT_STATE = Symbol.for("openclaw.codexAppServerClientState");
6599
6638
  const SHARED_CODEX_APP_SERVER_CLIENT_DISPOSER = Symbol.for("openclaw.codexAppServerClientDisposer");
6600
- const CODEX_APP_SERVER_CLIENT_START_METADATA = Symbol.for("openclaw.codexAppServerClientStartMetadata");
6639
+ const createStartupLifetime = () => ({
6640
+ controller: new AbortController(),
6641
+ pending: /* @__PURE__ */ new Set()
6642
+ });
6601
6643
  function getSharedCodexAppServerClientState() {
6602
6644
  const globalState = globalThis;
6603
6645
  globalState[SHARED_CODEX_APP_SERVER_CLIENT_STATE] ??= {
@@ -6605,19 +6647,37 @@ function getSharedCodexAppServerClientState() {
6605
6647
  liveClients: /* @__PURE__ */ new Set(),
6606
6648
  isolatedClients: /* @__PURE__ */ new Set(),
6607
6649
  entriesByClient: /* @__PURE__ */ new WeakMap(),
6608
- leasedReleases: /* @__PURE__ */ new WeakMap(),
6609
- desktopGenerationDrainChecks: /* @__PURE__ */ new Set()
6650
+ desktopGenerationDrainChecks: /* @__PURE__ */ new Set(),
6651
+ startup: createStartupLifetime(),
6652
+ startMetadata: /* @__PURE__ */ new WeakMap()
6610
6653
  };
6611
6654
  return globalState[SHARED_CODEX_APP_SERVER_CLIENT_STATE];
6612
6655
  }
6613
- function getCodexAppServerClientStartMetadata() {
6614
- const globalState = globalThis;
6615
- globalState[CODEX_APP_SERVER_CLIENT_START_METADATA] ??= /* @__PURE__ */ new WeakMap();
6616
- return globalState[CODEX_APP_SERVER_CLIENT_START_METADATA];
6656
+ function ownCodexStartup(lifetime, operation) {
6657
+ lifetime.pending.add(operation);
6658
+ const release = () => lifetime.pending.delete(operation);
6659
+ operation.then(release, release);
6660
+ return operation;
6661
+ }
6662
+ async function prepareCodexAppServerClient(options) {
6663
+ const lifetime = getSharedCodexAppServerClientState().startup;
6664
+ const abandonSignal = options?.abandonSignal ? AbortSignal.any([lifetime.controller.signal, options.abandonSignal]) : lifetime.controller.signal;
6665
+ const assertCurrent = () => {
6666
+ if (abandonSignal.aborted) throw new CodexAppServerStartupError("aborted", "codex app-server initialize aborted");
6667
+ };
6668
+ assertCurrent();
6669
+ const startedAt = Date.now();
6670
+ return {
6671
+ context: await withCodexAppServerAcquireDeadline(options?.timeoutMs ?? 0, ownCodexStartup(lifetime, resolveCodexAppServerClientStartContext(options)), abandonSignal),
6672
+ lifetime,
6673
+ abandonSignal,
6674
+ startedAt,
6675
+ assertCurrent
6676
+ };
6617
6677
  }
6618
6678
  /** Reads the exact successful spawn selection plus its initialized runtime identity. */
6619
6679
  function readCodexAppServerClientProcessIdentity(client) {
6620
- const metadata = getCodexAppServerClientStartMetadata().get(client);
6680
+ const metadata = getSharedCodexAppServerClientState().startMetadata.get(client);
6621
6681
  if (!metadata) return;
6622
6682
  const runtimeIdentity = client.getRuntimeIdentity();
6623
6683
  return {
@@ -6633,11 +6693,11 @@ function readCodexAppServerClientDesktopGenerationFingerprint(client) {
6633
6693
  }
6634
6694
  /** Returns the lifecycle generation that owns a managed desktop client. */
6635
6695
  function readCodexAppServerClientDesktopGeneration(client) {
6636
- return getCodexAppServerClientStartMetadata().get(client)?.desktopGeneration;
6696
+ return getSharedCodexAppServerClientState().startMetadata.get(client)?.desktopGeneration;
6637
6697
  }
6638
6698
  /** Waits until older physical desktop clients for this client's Codex home exit. */
6639
6699
  async function waitForCodexAppServerClientDesktopGenerationDrain(params) {
6640
- const metadata = getCodexAppServerClientStartMetadata().get(params.client);
6700
+ const metadata = getSharedCodexAppServerClientState().startMetadata.get(params.client);
6641
6701
  if (!metadata?.desktopGeneration) return;
6642
6702
  const drain = createOlderDesktopGenerationDrainWait({
6643
6703
  generation: metadata.desktopGeneration,
@@ -6678,7 +6738,7 @@ function isCodexAppServerStartSelectionChangedError(error) {
6678
6738
  * Use between the check and the JSON-RPC write on the same event loop turn.
6679
6739
  */
6680
6740
  function assertCodexAppServerClientStartSelectionCurrent(params) {
6681
- const metadata = getCodexAppServerClientStartMetadata().get(params.client);
6741
+ const metadata = getSharedCodexAppServerClientState().startMetadata.get(params.client);
6682
6742
  if (!metadata) return;
6683
6743
  if (metadata.desktopGeneration && !isCodexDesktopGenerationCurrent(metadata.desktopGeneration)) throw new CodexAppServerStartSelectionChangedError();
6684
6744
  const requestedStartOptions = params.startOptions ?? metadata.requestedStartOptions;
@@ -6691,7 +6751,7 @@ function assertCodexAppServerClientStartSelectionCurrent(params) {
6691
6751
  }
6692
6752
  /** Resolves the per-CODEX_HOME key used to serialize native config loading. */
6693
6753
  function resolveCodexNativeConfigFenceKey(params) {
6694
- const metadata = params.client ? getCodexAppServerClientStartMetadata().get(params.client) : void 0;
6754
+ const metadata = params.client ? getSharedCodexAppServerClientState().startMetadata.get(params.client) : void 0;
6695
6755
  const startOptions = metadata?.startOptions ?? params.startOptions;
6696
6756
  if (!startOptions || startOptions.transport !== "stdio") return;
6697
6757
  const configuredHome = startOptions.env?.CODEX_HOME?.trim();
@@ -6779,27 +6839,19 @@ function shouldTrackDesktopGeneration(startOptions, pluginConfig) {
6779
6839
  return startOptions.commandSource === "managed" && (startOptions.managedCommandOrder ?? "package-first") === "desktop-first";
6780
6840
  }
6781
6841
  /** Gets or starts a shared Codex app-server client without retaining a lease. */
6782
- async function getSharedCodexAppServerClient(options) {
6783
- return (await acquireSharedCodexAppServerClient(options)).client;
6842
+ function getSharedCodexAppServerClient(options) {
6843
+ return acquireSharedCodexAppServerClient(options);
6784
6844
  }
6785
6845
  /** Gets or starts a shared Codex app-server client and records a release lease. */
6786
- async function getLeasedSharedCodexAppServerClient(options) {
6787
- const acquired = await acquireSharedCodexAppServerClient(options, { leased: true });
6788
- const state = getSharedCodexAppServerClientState();
6789
- const releases = state.leasedReleases.get(acquired.client) ?? [];
6790
- releases.push(acquired.release);
6791
- state.leasedReleases.set(acquired.client, releases);
6792
- return acquired.client;
6846
+ function getLeasedSharedCodexAppServerClient(options) {
6847
+ return acquireSharedCodexAppServerClient(options, true);
6793
6848
  }
6794
6849
  /** Releases one outstanding lease for a shared Codex app-server client. */
6795
6850
  function releaseLeasedSharedCodexAppServerClient(client) {
6796
- const state = getSharedCodexAppServerClientState();
6797
- const releases = state.leasedReleases.get(client);
6798
- if (!releases) return false;
6799
- const release = releases.pop();
6800
- if (!release) return false;
6801
- if (releases.length === 0) state.leasedReleases.delete(client);
6802
- release();
6851
+ const entry = getSharedCodexAppServerClientState().entriesByClient.get(client);
6852
+ if (!entry || entry.anonymousLeases === 0) return false;
6853
+ entry.anonymousLeases -= 1;
6854
+ releaseSharedClientEntry(entry, "activeLeases");
6803
6855
  return true;
6804
6856
  }
6805
6857
  /** Releases the currently owned client exactly once. */
@@ -6861,13 +6913,13 @@ async function withLeasedCodexAppServerClientStartSelectionRetry(params) {
6861
6913
  }
6862
6914
  throw new Error("Codex app-server selection retry loop exited unexpectedly");
6863
6915
  }
6864
- async function acquireSharedCodexAppServerClient(options, leaseOptions) {
6865
- if (options?.abandonSignal?.aborted) throw new CodexAppServerStartupError("aborted", "codex app-server initialize aborted");
6866
- const acquireStartedAt = Date.now();
6916
+ async function acquireSharedCodexAppServerClient(options, leased = false) {
6867
6917
  const timeoutMs = options?.timeoutMs ?? 0;
6868
6918
  const state = getSharedCodexAppServerClientState();
6869
- const { agentDir, usesNativeAuth, authProfileId, authProfileStore, preparedAuth, authRequirement, requestedStartOptions, startOptions, desktopGeneration, pluginConfig } = await withCodexAppServerAcquireDeadline(timeoutMs, resolveCodexAppServerClientStartContext(options), options?.abandonSignal);
6870
- const remainingTimeoutMs = resolveRemainingAcquireTimeout(timeoutMs, acquireStartedAt);
6919
+ const { context, lifetime, abandonSignal, startedAt, assertCurrent } = await prepareCodexAppServerClient(options);
6920
+ assertCurrent();
6921
+ const { agentDir, usesNativeAuth, authProfileId, authProfileStore, preparedAuth, authRequirement, requestedStartOptions, startOptions, desktopGeneration, pluginConfig } = context;
6922
+ const remainingTimeoutMs = resolveRemainingAcquireTimeout(timeoutMs, startedAt);
6871
6923
  const authIdentityCacheKey = preparedAuth?.kind === "api-key" ? resolveCodexAppServerPreparedApiKeyCacheKey(preparedAuth.apiKey) : preparedAuth?.snapshot.secretFreeCacheKey ?? (authRequirement === "api-key" && !authProfileId ? resolveCodexAppServerFallbackApiKeyCacheKey({ startOptions }) : void 0);
6872
6924
  const baseKey = `${codexAppServerStartOptionsKey(startOptions, {
6873
6925
  authProfileId,
@@ -6880,14 +6932,14 @@ async function acquireSharedCodexAppServerClient(options, leaseOptions) {
6880
6932
  const key = runtimeArtifactMode ? `${baseKey}\0runtime-artifact:capture-v1:${expectedRuntimeArtifactKey}` : baseKey;
6881
6933
  let entry = getOrCreateSharedClientEntry(state, key);
6882
6934
  const existingClient = entry.client;
6883
- const existingGeneration = existingClient ? getCodexAppServerClientStartMetadata().get(existingClient)?.desktopGeneration : void 0;
6935
+ const existingGeneration = existingClient ? state.startMetadata.get(existingClient)?.desktopGeneration : void 0;
6884
6936
  if (existingClient && existingGeneration && !isCodexDesktopGenerationCurrent(existingGeneration)) {
6885
6937
  retireSharedCodexAppServerClientIfCurrent(existingClient);
6886
6938
  entry = getOrCreateSharedClientEntry(state, key);
6887
6939
  }
6888
6940
  entry.startupAbort ??= new AbortController();
6889
6941
  entry.closeWhenIdle = false;
6890
- const releasePendingAcquire = retainPendingSharedClientAcquire(entry);
6942
+ const releasePendingAcquire = retainSharedClientEntry(entry, "pendingAcquires");
6891
6943
  const startedCallback = options?.onStartedClient;
6892
6944
  if (startedCallback) {
6893
6945
  entry.onStartedClientCallbacks.add(startedCallback);
@@ -6901,15 +6953,15 @@ async function acquireSharedCodexAppServerClient(options, leaseOptions) {
6901
6953
  const abandon = () => {
6902
6954
  stopStartedClientNotifications();
6903
6955
  releasePendingAcquire();
6904
- retirePendingSharedClientEntryIfUnclaimed(key, entry);
6956
+ retirePendingSharedClientEntryIfUnclaimed(entry);
6905
6957
  };
6906
6958
  options.abandonSignal.addEventListener("abort", abandon, { once: true });
6907
6959
  cleanupAbandonSignal = () => options.abandonSignal?.removeEventListener("abort", abandon);
6908
6960
  if (options.abandonSignal.aborted) abandon();
6909
6961
  }
6910
6962
  const startup = entry.startup ?? (entry.startup = createSharedCodexAppServerClientStartup({
6963
+ lifetime,
6911
6964
  entry,
6912
- key,
6913
6965
  requestedStartOptions,
6914
6966
  startOptions,
6915
6967
  desktopGeneration,
@@ -6921,13 +6973,12 @@ async function acquireSharedCodexAppServerClient(options, leaseOptions) {
6921
6973
  authRequirement,
6922
6974
  runtimeArtifactMode,
6923
6975
  ...options?.expectedRuntimeArtifact ? { expectedRuntimeArtifact: options.expectedRuntimeArtifact } : {},
6924
- runtimeArtifactSignal: entry.startupAbort.signal,
6925
6976
  abandonSignal: entry.startupAbort.signal,
6926
6977
  config: options?.config
6927
6978
  }));
6928
6979
  try {
6929
- await withCodexAppServerAcquireDeadline(remainingTimeoutMs, startup.initialized, options?.abandonSignal, CODEX_APP_SERVER_INITIALIZE_TIMEOUT_MESSAGE, () => buildCodexAppServerInitializeTimeoutError(entry.client));
6930
- const client = await withCodexAppServerAcquireDeadline(timeoutMs, startup.ready, options?.abandonSignal, "codex app-server authentication timed out");
6980
+ await withCodexAppServerAcquireDeadline(remainingTimeoutMs, startup.initialized, abandonSignal, CODEX_APP_SERVER_INITIALIZE_TIMEOUT_MESSAGE, () => buildCodexAppServerInitializeTimeoutError(entry.client));
6981
+ const client = await withCodexAppServerAcquireDeadline(timeoutMs, startup.ready, abandonSignal, "codex app-server authentication timed out");
6931
6982
  if (entry.closeError) throw entry.closeError;
6932
6983
  ensureCodexAppServerClientRuntime(client, {
6933
6984
  agentDir,
@@ -6936,14 +6987,14 @@ async function acquireSharedCodexAppServerClient(options, leaseOptions) {
6936
6987
  authMode: preparedAuth?.kind === "api-key" ? "prepared-api-key" : "profile",
6937
6988
  config: options?.config
6938
6989
  });
6939
- const release = leaseOptions?.leased ? retainSharedClientEntry(entry) : void 0;
6940
- return release ? {
6941
- client,
6942
- release
6943
- } : { client };
6990
+ if (leased) {
6991
+ entry.anonymousLeases += 1;
6992
+ entry.activeLeases += 1;
6993
+ }
6994
+ return client;
6944
6995
  } catch (error) {
6945
6996
  releasePendingAcquire();
6946
- retirePendingSharedClientEntryIfUnclaimed(key, entry);
6997
+ retirePendingSharedClientEntryIfUnclaimed(entry);
6947
6998
  throw error;
6948
6999
  } finally {
6949
7000
  cleanupAbandonSignal?.();
@@ -6973,45 +7024,34 @@ function resolveRemainingAcquireTimeout(timeoutMs, startedAt) {
6973
7024
  }
6974
7025
  function createSharedCodexAppServerClientStartup(params) {
6975
7026
  const initialized = createDeferred();
6976
- const ready = startInitializedCodexAppServerClient({
6977
- requestedStartOptions: params.requestedStartOptions,
6978
- startOptions: params.startOptions,
6979
- ...params.desktopGeneration ? { desktopGeneration: params.desktopGeneration } : {},
6980
- ...params.pluginConfig !== void 0 ? { pluginConfig: params.pluginConfig } : {},
6981
- agentDir: params.agentDir,
6982
- authProfileId: params.authProfileId,
6983
- authProfileStore: params.authProfileStore,
6984
- preparedAuth: params.preparedAuth,
6985
- authRequirement: params.authRequirement,
6986
- runtimeArtifactMode: params.runtimeArtifactMode,
6987
- ...params.expectedRuntimeArtifact ? { expectedRuntimeArtifact: params.expectedRuntimeArtifact } : {},
6988
- runtimeArtifactSignal: params.runtimeArtifactSignal,
6989
- abandonSignal: params.abandonSignal,
6990
- config: params.config,
7027
+ const ready = ownCodexStartup(params.lifetime, startInitializedCodexAppServerClient({
7028
+ ...params,
6991
7029
  onStartedClient: (startedClient) => {
6992
7030
  const state = getSharedCodexAppServerClientState();
7031
+ if (params.entry.client) state.entriesByClient.delete(params.entry.client);
6993
7032
  params.entry.client = startedClient;
7033
+ state.entriesByClient.set(startedClient, params.entry);
6994
7034
  state.liveClients.add(startedClient);
6995
7035
  startedClient.addTransportExitHandler((exitedClient) => {
6996
7036
  state.liveClients.delete(exitedClient);
6997
7037
  notifyDesktopGenerationDrainChecks(state);
6998
7038
  });
6999
- startedClient.addCloseHandler((closedClient) => {
7000
- if (state.entriesByClient.get(closedClient) === params.entry) clearSharedClientEntryIfCurrent(params.key, closedClient);
7001
- });
7002
7039
  for (const callback of params.entry.onStartedClientCallbacks) callback(startedClient);
7003
- retirePendingSharedClientEntryIfUnclaimed(params.key, params.entry);
7040
+ retirePendingSharedClientEntryIfUnclaimed(params.entry);
7004
7041
  },
7005
7042
  onInitializedClient: () => initialized.resolve()
7006
7043
  }).then((client) => {
7007
7044
  const state = getSharedCodexAppServerClientState();
7008
7045
  params.entry.client = client;
7009
- state.entriesByClient.set(client, params.entry);
7046
+ client.addCloseHandler((closedClient) => {
7047
+ const entry = getCurrentSharedClientEntry(closedClient);
7048
+ if (entry) state.clients.delete(entry.key);
7049
+ });
7010
7050
  return client;
7011
7051
  }, (error) => {
7012
7052
  initialized.reject(error);
7013
7053
  throw error;
7014
- });
7054
+ }));
7015
7055
  initialized.promise.catch(() => void 0);
7016
7056
  ready.catch(() => void 0);
7017
7057
  return {
@@ -7019,13 +7059,15 @@ function createSharedCodexAppServerClientStartup(params) {
7019
7059
  ready
7020
7060
  };
7021
7061
  }
7022
- /** Starts a non-shared Codex app-server client owned entirely by the caller. */
7062
+ /** Starts a caller-owned client; its assertion never binds ordinary shared-client leases. */
7023
7063
  async function createIsolatedCodexAppServerClient(options) {
7024
- if (options?.abandonSignal?.aborted) throw new CodexAppServerStartupError("aborted", "codex app-server initialize aborted");
7025
- const acquireStartedAt = Date.now();
7064
+ options?.assertCurrent?.();
7065
+ const { context, lifetime, abandonSignal, startedAt, assertCurrent } = await prepareCodexAppServerClient(options);
7066
+ assertCurrent();
7026
7067
  const timeoutMs = options?.timeoutMs ?? 0;
7027
- const { agentDir, usesNativeAuth, authProfileId, authProfileStore, preparedAuth, authRequirement, requestedStartOptions, startOptions, desktopGeneration, pluginConfig } = await withCodexAppServerAcquireDeadline(timeoutMs, resolveCodexAppServerClientStartContext(options), options?.abandonSignal);
7028
- return await startInitializedCodexAppServerClient({
7068
+ const { agentDir, usesNativeAuth, authProfileId, authProfileStore, preparedAuth, authRequirement, requestedStartOptions, startOptions, desktopGeneration, pluginConfig } = context;
7069
+ return await ownCodexStartup(lifetime, startInitializedCodexAppServerClient({
7070
+ lifetime,
7029
7071
  requestedStartOptions,
7030
7072
  startOptions,
7031
7073
  ...desktopGeneration ? { desktopGeneration } : {},
@@ -7037,15 +7079,15 @@ async function createIsolatedCodexAppServerClient(options) {
7037
7079
  authRequirement,
7038
7080
  runtimeArtifactMode: options?.runtimeArtifactMode ?? (options?.expectedRuntimeArtifact ? "capture" : void 0),
7039
7081
  ...options?.expectedRuntimeArtifact ? { expectedRuntimeArtifact: options.expectedRuntimeArtifact } : {},
7040
- runtimeArtifactSignal: options?.abandonSignal,
7041
7082
  config: options?.config,
7042
- timeoutMs: resolveRemainingAcquireTimeout(timeoutMs, acquireStartedAt),
7043
- abandonSignal: options?.abandonSignal,
7083
+ timeoutMs: resolveRemainingAcquireTimeout(timeoutMs, startedAt),
7084
+ abandonSignal,
7085
+ assertCurrent: options?.assertCurrent,
7044
7086
  onStartedClient: (client) => {
7045
7087
  trackIsolatedCodexAppServerClient(client);
7046
7088
  options?.onStartedClient?.(client);
7047
7089
  }
7048
- });
7090
+ }));
7049
7091
  }
7050
7092
  function trackIsolatedCodexAppServerClient(client) {
7051
7093
  const state = getSharedCodexAppServerClientState();
@@ -7058,11 +7100,18 @@ function trackIsolatedCodexAppServerClient(client) {
7058
7100
  async function startInitializedCodexAppServerClient(params) {
7059
7101
  const acquireStartedAt = Date.now();
7060
7102
  const timeoutMs = params.timeoutMs ?? 0;
7103
+ const abandonSignal = params.abandonSignal ? AbortSignal.any([params.lifetime.controller.signal, params.abandonSignal]) : params.lifetime.controller.signal;
7104
+ const waitForStartup = (operation, timeoutMessage = CODEX_APP_SERVER_INITIALIZE_TIMEOUT_MESSAGE, timeoutErrorFactory) => {
7105
+ if (abandonSignal.aborted) throw new CodexAppServerStartupError("aborted", "codex app-server initialize aborted");
7106
+ return withCodexAppServerAcquireDeadline(resolveRemainingAcquireTimeout(timeoutMs, acquireStartedAt), ownCodexStartup(params.lifetime, operation()), abandonSignal, timeoutMessage, timeoutErrorFactory);
7107
+ };
7061
7108
  const startOptionsCandidates = resolveManagedFallbackStartOptions(params.startOptions);
7062
7109
  for (const [index, startOptions] of startOptionsCandidates.entries()) {
7063
- const desktopGeneration = params.desktopGeneration ?? (isManagedCodexDesktopCommand(startOptions.command) ? await withCodexAppServerAcquireDeadline(resolveRemainingAcquireTimeout(timeoutMs, acquireStartedAt), waitForCodexDesktopGeneration(), params.abandonSignal) : void 0);
7064
- const assertDesktopGenerationCurrent = () => {
7065
- if (params.abandonSignal?.aborted) throw new CodexAppServerStartupError("aborted", "codex app-server initialize aborted");
7110
+ params.assertCurrent?.();
7111
+ const desktopGeneration = params.desktopGeneration ?? (isManagedCodexDesktopCommand(startOptions.command) ? await waitForStartup(waitForCodexDesktopGeneration) : void 0);
7112
+ const assertStartupCurrent = () => {
7113
+ params.assertCurrent?.();
7114
+ if (abandonSignal.aborted) throw new CodexAppServerStartupError("aborted", "codex app-server initialize aborted");
7066
7115
  if (desktopGeneration && !isCodexDesktopGenerationCurrent(desktopGeneration)) throw new CodexAppServerStartSelectionChangedError();
7067
7116
  };
7068
7117
  const computerUseConfig = resolveCodexComputerUseConfig({ pluginConfig: params.pluginConfig });
@@ -7073,13 +7122,13 @@ async function startInitializedCodexAppServerClient(params) {
7073
7122
  agentDir: params.agentDir
7074
7123
  }) : void 0;
7075
7124
  try {
7076
- if (artifactDrain) await withCodexAppServerAcquireDeadline(resolveRemainingAcquireTimeout(timeoutMs, acquireStartedAt), artifactDrain.promise, params.abandonSignal);
7125
+ if (artifactDrain) await waitForStartup(() => artifactDrain.promise);
7077
7126
  await reconcileCodexComputerUseStartArtifacts({
7078
7127
  startOptions,
7079
7128
  agentDir: params.agentDir,
7080
7129
  pluginConfig: params.pluginConfig,
7081
7130
  ...desktopGeneration ? { desktopGeneration } : {},
7082
- assertCurrent: assertDesktopGenerationCurrent,
7131
+ assertCurrent: assertStartupCurrent,
7083
7132
  ownsIsolatedCodexHome
7084
7133
  });
7085
7134
  } catch (error) {
@@ -7094,80 +7143,69 @@ async function startInitializedCodexAppServerClient(params) {
7094
7143
  } finally {
7095
7144
  artifactDrain?.cancel();
7096
7145
  }
7097
- const runtimeArtifactModule = params.runtimeArtifactMode ? await import("./runtime-artifact-C3jVimFn.js") : void 0;
7146
+ const runtimeArtifactModule = params.runtimeArtifactMode ? await import("./runtime-artifact-Bh_gf6-t.js") : void 0;
7098
7147
  const runtimeArtifactBeforeStart = runtimeArtifactModule ? await runtimeArtifactModule.captureCodexAppServerRuntimeArtifactBeforeStart({
7099
7148
  startOptions,
7100
7149
  spawnIdentity: resolveCodexAppServerSpawnIdentity(startOptions),
7101
- signal: params.runtimeArtifactSignal
7150
+ signal: abandonSignal
7102
7151
  }) : void 0;
7103
7152
  if (runtimeArtifactModule && runtimeArtifactBeforeStart && params.expectedRuntimeArtifact && !runtimeArtifactModule.validateCodexAppServerRuntimeArtifactCapture(params.expectedRuntimeArtifact, runtimeArtifactBeforeStart)) {
7104
7153
  if (index + 1 < startOptionsCandidates.length) continue;
7105
7154
  throw new Error("Codex app-server runtime artifact does not match verified inference");
7106
7155
  }
7107
- assertDesktopGenerationCurrent();
7156
+ assertStartupCurrent();
7108
7157
  let starting;
7109
7158
  let client;
7110
7159
  try {
7111
- client = await withCodexAppServerAcquireDeadline(resolveRemainingAcquireTimeout(timeoutMs, acquireStartedAt), starting = CodexAppServerClient.start(startOptions, () => {
7112
- assertDesktopGenerationCurrent();
7160
+ client = await waitForStartup(() => starting = CodexAppServerClient.start(startOptions, () => {
7161
+ assertStartupCurrent();
7113
7162
  resolveRemainingAcquireTimeout(timeoutMs, acquireStartedAt);
7114
- }), params.abandonSignal);
7115
- } catch (error) {
7116
- starting?.then((lateClient) => lateClient.close(), () => {});
7117
- throw error;
7118
- }
7119
- const nativeCommandAtStart = startOptions.commandSource === "resolved-managed" ? resolveManagedCodexNativeCommand(startOptions.command) : void 0;
7120
- getCodexAppServerClientStartMetadata().set(client, {
7121
- requestedStartOptions: params.requestedStartOptions,
7122
- startOptions,
7123
- agentDir: params.agentDir,
7124
- ...nativeCommandAtStart ? { nativeCommand: nativeCommandAtStart } : {},
7125
- ...desktopGeneration ? { desktopGeneration } : {}
7126
- });
7127
- params.onStartedClient?.(client);
7128
- let initialize;
7129
- try {
7130
- await withCodexAppServerAcquireDeadline(resolveRemainingAcquireTimeout(timeoutMs, acquireStartedAt), initialize = client.initialize(), params.abandonSignal, CODEX_APP_SERVER_INITIALIZE_TIMEOUT_MESSAGE, () => buildCodexAppServerInitializeTimeoutError(client));
7131
- } catch (error) {
7132
- client.close();
7133
- initialize?.catch(() => void 0);
7134
- if (shouldTryManagedFallbackStartOption(error, startOptions, index, startOptionsCandidates)) continue;
7135
- throw error;
7136
- }
7137
- try {
7138
- assertDesktopGenerationCurrent();
7163
+ }));
7139
7164
  } catch (error) {
7140
- client.close();
7165
+ if (starting) ownCodexStartup(params.lifetime, starting.then((lateClient) => lateClient.closeAndWait(), () => {}));
7141
7166
  throw error;
7142
7167
  }
7143
- params.onInitializedClient?.();
7144
- let runtimeArtifact;
7168
+ let ready = false;
7145
7169
  try {
7170
+ const nativeCommandAtStart = startOptions.commandSource === "resolved-managed" ? resolveManagedCodexNativeCommand(startOptions.command) : void 0;
7171
+ getSharedCodexAppServerClientState().startMetadata.set(client, {
7172
+ requestedStartOptions: params.requestedStartOptions,
7173
+ startOptions,
7174
+ agentDir: params.agentDir,
7175
+ ...nativeCommandAtStart ? { nativeCommand: nativeCommandAtStart } : {},
7176
+ ...desktopGeneration ? { desktopGeneration } : {}
7177
+ });
7178
+ assertStartupCurrent();
7179
+ params.onStartedClient?.(client);
7180
+ try {
7181
+ await waitForStartup(() => client.initialize(), CODEX_APP_SERVER_INITIALIZE_TIMEOUT_MESSAGE, () => buildCodexAppServerInitializeTimeoutError(client));
7182
+ } catch (error) {
7183
+ if (shouldTryManagedFallbackStartOption(error, startOptions, index, startOptionsCandidates)) continue;
7184
+ throw error;
7185
+ }
7186
+ assertStartupCurrent();
7187
+ params.onInitializedClient?.();
7188
+ let runtimeArtifact;
7146
7189
  if (runtimeArtifactModule && runtimeArtifactBeforeStart) {
7147
7190
  runtimeArtifact = await runtimeArtifactModule.finalizeCodexAppServerRuntimeArtifact({
7148
7191
  before: runtimeArtifactBeforeStart,
7149
7192
  startOptions,
7150
7193
  spawnIdentity: resolveCodexAppServerSpawnIdentity(startOptions),
7151
7194
  runtimeIdentity: client.getRuntimeIdentity(),
7152
- signal: params.runtimeArtifactSignal
7195
+ signal: abandonSignal
7153
7196
  });
7154
7197
  if (params.expectedRuntimeArtifact && (runtimeArtifact.id !== params.expectedRuntimeArtifact.id || runtimeArtifact.fingerprint !== params.expectedRuntimeArtifact.fingerprint)) throw new Error("Codex app-server runtime artifact does not match verified inference");
7155
7198
  }
7156
- } catch (error) {
7157
- client.close();
7158
- throw error;
7159
- }
7160
- ensureCodexAppServerClientRuntime(client, {
7161
- agentDir: params.agentDir,
7162
- authProfileId: params.authProfileId ?? void 0,
7163
- authMode: params.preparedAuth?.kind === "api-key" ? "prepared-api-key" : "profile",
7164
- ...params.authProfileStore ? { authProfileStore: params.authProfileStore } : {},
7165
- config: params.config,
7166
- onAuthRefreshFailure: () => retireSharedCodexAppServerClientIfCurrent(client)
7167
- });
7168
- try {
7169
- assertDesktopGenerationCurrent();
7170
- await withCodexAppServerAcquireDeadline(resolveRemainingAcquireTimeout(timeoutMs, acquireStartedAt), applyCodexAppServerAuthProfile({
7199
+ ensureCodexAppServerClientRuntime(client, {
7200
+ agentDir: params.agentDir,
7201
+ authProfileId: params.authProfileId ?? void 0,
7202
+ authMode: params.preparedAuth?.kind === "api-key" ? "prepared-api-key" : "profile",
7203
+ ...params.authProfileStore ? { authProfileStore: params.authProfileStore } : {},
7204
+ config: params.config,
7205
+ onAuthRefreshFailure: () => retireSharedCodexAppServerClientIfCurrent(client)
7206
+ });
7207
+ assertStartupCurrent();
7208
+ await waitForStartup(() => applyCodexAppServerAuthProfile({
7171
7209
  client,
7172
7210
  agentDir: params.agentDir,
7173
7211
  authProfileId: params.authProfileId,
@@ -7175,10 +7213,11 @@ async function startInitializedCodexAppServerClient(params) {
7175
7213
  authRequirement: params.authRequirement,
7176
7214
  startOptions,
7177
7215
  config: params.config,
7216
+ assertCurrent: assertStartupCurrent,
7178
7217
  ...params.authProfileStore ? { authProfileStore: params.authProfileStore } : {}
7179
- }), params.abandonSignal);
7218
+ }));
7180
7219
  if (runtimeArtifactModule && runtimeArtifact) runtimeArtifactModule.bindCodexAppServerRuntimeArtifact(client, runtimeArtifact);
7181
- assertDesktopGenerationCurrent();
7220
+ assertStartupCurrent();
7182
7221
  const fenceKey = resolveCodexNativeConfigFenceKey({ client });
7183
7222
  if (fenceKey) client.setThreadSessionRequestGuard(async (options) => {
7184
7223
  const release = await acquireCodexNativeConfigFence(fenceKey, options);
@@ -7190,10 +7229,10 @@ async function startInitializedCodexAppServerClient(params) {
7190
7229
  throw error;
7191
7230
  }
7192
7231
  });
7232
+ ready = true;
7193
7233
  return client;
7194
- } catch (error) {
7195
- client.close();
7196
- throw error;
7234
+ } finally {
7235
+ if (!ready) ownCodexStartup(params.lifetime, client.closeAndWait());
7197
7236
  }
7198
7237
  }
7199
7238
  throw new Error("Managed Codex app-server fallback candidates were exhausted.");
@@ -7223,12 +7262,11 @@ function shouldTryManagedFallbackStartOption(error, startOptions, index, startOp
7223
7262
  function clearSharedCodexAppServerClientIfCurrent(client) {
7224
7263
  if (!client) return false;
7225
7264
  const state = getSharedCodexAppServerClientState();
7226
- for (const [key, entry] of state.clients) if (entry.client === client) {
7227
- state.clients.delete(key);
7228
- client.close();
7229
- return true;
7230
- }
7231
- return false;
7265
+ const entry = getCurrentSharedClientEntry(client);
7266
+ if (!entry) return false;
7267
+ state.clients.delete(entry.key);
7268
+ client.close();
7269
+ return true;
7232
7270
  }
7233
7271
  /** Captures a revocable observation of the exact shared client and native account/config. */
7234
7272
  function captureSharedCodexAppServerCatalogLifetime(client) {
@@ -7239,16 +7277,14 @@ function captureSharedCodexAppServerCatalogLifetime(client) {
7239
7277
  /** Registration ends on retirement even when sibling leases keep the process alive. */
7240
7278
  function captureSharedClientRegistration(client) {
7241
7279
  const state = getSharedCodexAppServerClientState();
7242
- const entry = state.entriesByClient.get(client);
7243
- const key = [...state.clients].find(([, candidate]) => candidate === entry)?.[0];
7280
+ const entry = getCurrentSharedClientEntry(client);
7244
7281
  const generation = readCodexAppServerClientDesktopGeneration(client);
7245
- return () => key !== void 0 && state.clients.get(key) === entry && entry?.client === client && !entry.closeWhenIdle && !entry.closeError && !client.getCloseError() && (!generation || isCodexDesktopGenerationCurrent(generation));
7282
+ return () => entry !== void 0 && state.clients.get(entry.key) === entry && entry.client === client && !entry.closeWhenIdle && !entry.closeError && !client.getCloseError() && (!generation || isCodexDesktopGenerationCurrent(generation));
7246
7283
  }
7247
7284
  /** Retains the matching shared client and returns a release callback. */
7248
7285
  function retainSharedCodexAppServerClientIfCurrent(client) {
7249
- if (!client) return;
7250
- const state = getSharedCodexAppServerClientState();
7251
- for (const entry of state.clients.values()) if (entry.client === client) return retainSharedClientEntry(entry);
7286
+ const entry = getCurrentSharedClientEntry(client);
7287
+ return entry ? retainSharedClientEntry(entry) : void 0;
7252
7288
  }
7253
7289
  /** Retains the live shared client whose initialized instance id matches a thread binding. */
7254
7290
  function retainSharedCodexAppServerClientByInstanceId(clientId) {
@@ -7266,7 +7302,7 @@ function retainSharedCodexAppServerClientByInstanceId(clientId) {
7266
7302
  /** Captures physical ownership, independently of unrelated thread and reader leases. */
7267
7303
  function captureCodexAppServerClientLifetime(client, requiredOwnership) {
7268
7304
  const state = getSharedCodexAppServerClientState();
7269
- const start = getCodexAppServerClientStartMetadata().get(client)?.startOptions;
7305
+ const start = state.startMetadata.get(client)?.startOptions;
7270
7306
  if (requiredOwnership === "native-process" && (start?.transport !== "stdio" || isCodexAppServerProxyLaunch(start.args))) throw new AgentHarnessPreflightError("Codex ordinary configuration refresh requires an OpenClaw-managed local stdio process, not an external socket or app-server proxy. No turn was sent; reconnect through managed local stdio before continuing.");
7271
7307
  const isCurrent = requiredOwnership === "native-process" && state.isolatedClients.has(client) ? () => state.isolatedClients.has(client) && !client.getCloseError() : captureSharedClientRegistration(client);
7272
7308
  const assertCurrent = () => {
@@ -7288,43 +7324,31 @@ function captureCodexAppServerClientLifetime(client, requiredOwnership) {
7288
7324
  function retireSharedCodexAppServerClientIfCurrent(client, opts) {
7289
7325
  if (!client) return;
7290
7326
  const state = getSharedCodexAppServerClientState();
7291
- for (const [key, entry] of state.clients) if (entry.client === client) {
7292
- state.clients.delete(key);
7327
+ const currentEntry = getCurrentSharedClientEntry(client);
7328
+ const entry = currentEntry ?? state.entriesByClient.get(client);
7329
+ if (!entry || entry.client !== client && !entry.closeError) return;
7330
+ if (currentEntry) {
7331
+ state.clients.delete(entry.key);
7293
7332
  entry.closeWhenIdle = true;
7294
- if (opts?.failActiveLeases) {
7295
- entry.closeError = /* @__PURE__ */ new Error("codex app-server client is closed");
7296
- return {
7297
- activeLeases: entry.activeLeases,
7298
- closed: closeRetiredSharedClientEntry(entry)
7299
- };
7300
- }
7301
- const closed = closeRetiredSharedClientEntryIfIdle(entry);
7302
- return {
7303
- activeLeases: entry.activeLeases,
7304
- closed
7305
- };
7306
7333
  }
7307
- const detachedEntry = state.entriesByClient.get(client);
7308
- if (detachedEntry && (detachedEntry.client === client || detachedEntry.closeError)) {
7309
- if (opts?.failActiveLeases && !detachedEntry.closeError) {
7310
- detachedEntry.closeError = /* @__PURE__ */ new Error("codex app-server client is closed");
7311
- return {
7312
- activeLeases: detachedEntry.activeLeases,
7313
- closed: closeRetiredSharedClientEntry(detachedEntry)
7314
- };
7315
- }
7334
+ if (opts?.failActiveLeases && (currentEntry || !entry.closeError)) {
7335
+ entry.closeError = /* @__PURE__ */ new Error("codex app-server client is closed");
7316
7336
  return {
7317
- activeLeases: detachedEntry.activeLeases,
7318
- closed: false
7337
+ activeLeases: entry.activeLeases,
7338
+ closed: closeRetiredSharedClientEntry(entry)
7319
7339
  };
7320
7340
  }
7341
+ return {
7342
+ activeLeases: entry.activeLeases,
7343
+ closed: currentEntry ? closeRetiredSharedClientEntryIfIdle(entry) : false
7344
+ };
7321
7345
  }
7322
7346
  /** Gracefully retires exact clients attached to an older desktop generation. */
7323
7347
  function retireSharedCodexAppServerClientsBeforeDesktopGeneration(generation) {
7324
7348
  const state = getSharedCodexAppServerClientState();
7325
7349
  for (const entry of state.clients.values()) {
7326
7350
  const client = entry.client;
7327
- const attached = client ? getCodexAppServerClientStartMetadata().get(client) : void 0;
7351
+ const attached = client ? state.startMetadata.get(client) : void 0;
7328
7352
  if (client && attached?.desktopGeneration && attached.desktopGeneration.epoch < generation.epoch) retireSharedCodexAppServerClientIfCurrent(client);
7329
7353
  }
7330
7354
  }
@@ -7369,7 +7393,7 @@ function hasLiveOlderDesktopGenerationClient(params) {
7369
7393
  return false;
7370
7394
  }
7371
7395
  function isOlderDesktopGenerationClientForHome(client, generation, targetHome) {
7372
- const metadata = getCodexAppServerClientStartMetadata().get(client);
7396
+ const metadata = getSharedCodexAppServerClientState().startMetadata.get(client);
7373
7397
  return Boolean(metadata?.desktopGeneration && metadata.desktopGeneration.epoch < generation.epoch && resolveCodexNativeConfigFenceKey({ client }) === targetHome);
7374
7398
  }
7375
7399
  function notifyDesktopGenerationDrainChecks(state) {
@@ -7379,26 +7403,35 @@ function notifyDesktopGenerationDrainChecks(state) {
7379
7403
  async function clearSharedCodexAppServerClientIfCurrentAndWait(client, options) {
7380
7404
  if (!client) return false;
7381
7405
  const state = getSharedCodexAppServerClientState();
7382
- for (const [key, entry] of state.clients) if (entry.client === client) {
7383
- state.clients.delete(key);
7384
- await client.closeAndWait(options);
7385
- return true;
7386
- }
7387
- return false;
7406
+ const entry = getCurrentSharedClientEntry(client);
7407
+ if (!entry) return false;
7408
+ state.clients.delete(entry.key);
7409
+ await client.closeAndWait(options);
7410
+ return true;
7388
7411
  }
7389
7412
  /** Clears all shared clients and waits for their processes to exit. */
7390
7413
  async function clearSharedCodexAppServerClientAndWait(options) {
7391
7414
  const state = getSharedCodexAppServerClientState();
7392
- const clients = collectSharedClients(state);
7415
+ const lifetime = state.startup;
7416
+ lifetime.controller.abort();
7393
7417
  state.clients.clear();
7394
- await Promise.all(clients.map((client) => client.closeAndWait(options)));
7418
+ const closing = Promise.all([...state.liveClients].map((client) => ownCodexStartup(lifetime, client.closeAndWait(options))));
7419
+ closing.catch(() => void 0);
7420
+ try {
7421
+ while (lifetime.pending.size > 0) await Promise.allSettled(lifetime.pending);
7422
+ await closing;
7423
+ } finally {
7424
+ if (state.startup === lifetime) state.startup = createStartupLifetime();
7425
+ }
7395
7426
  }
7396
7427
  globalThis[SHARED_CODEX_APP_SERVER_CLIENT_DISPOSER] = clearSharedCodexAppServerClientAndWait;
7397
7428
  function getOrCreateSharedClientEntry(state, key) {
7398
7429
  let entry = state.clients.get(key);
7399
7430
  if (!entry) {
7400
7431
  entry = {
7432
+ key,
7401
7433
  activeLeases: 0,
7434
+ anonymousLeases: 0,
7402
7435
  pendingAcquires: 0,
7403
7436
  closeWhenIdle: false,
7404
7437
  onStartedClientCallbacks: /* @__PURE__ */ new Set()
@@ -7407,53 +7440,34 @@ function getOrCreateSharedClientEntry(state, key) {
7407
7440
  }
7408
7441
  return entry;
7409
7442
  }
7410
- function clearSharedClientEntryIfCurrent(key, client) {
7443
+ function getCurrentSharedClientEntry(client) {
7411
7444
  const state = getSharedCodexAppServerClientState();
7412
- if (state.clients.get(key)?.client === client) state.clients.delete(key);
7445
+ const entry = client ? state.entriesByClient.get(client) : void 0;
7446
+ return entry && entry.client === client && state.clients.get(entry.key) === entry ? entry : void 0;
7413
7447
  }
7414
7448
  /** Clears a matching shared client only when no lease or acquire currently claims it. */
7415
7449
  function clearSharedCodexAppServerClientIfCurrentAndUnclaimed(client) {
7416
- if (!client) return {
7417
- found: false,
7418
- closed: false,
7419
- activeLeases: 0,
7420
- pendingAcquires: 0
7421
- };
7422
- const state = getSharedCodexAppServerClientState();
7423
- for (const [key, entry] of state.clients) if (entry.client === client) return {
7424
- found: true,
7425
- closed: closeSharedClientEntryIfUnclaimed(key, entry),
7426
- activeLeases: entry.activeLeases,
7427
- pendingAcquires: entry.pendingAcquires
7428
- };
7450
+ const entry = getCurrentSharedClientEntry(client);
7429
7451
  return {
7430
- found: false,
7431
- closed: false,
7432
- activeLeases: 0,
7433
- pendingAcquires: 0
7452
+ found: entry !== void 0,
7453
+ closed: entry ? closeSharedClientEntryIfUnclaimed(entry) : false,
7454
+ activeLeases: entry?.activeLeases ?? 0,
7455
+ pendingAcquires: entry?.pendingAcquires ?? 0
7434
7456
  };
7435
7457
  }
7436
- function retainPendingSharedClientAcquire(entry) {
7458
+ function retainSharedClientEntry(entry, counter = "activeLeases") {
7437
7459
  let released = false;
7438
- entry.pendingAcquires += 1;
7460
+ entry[counter] += 1;
7439
7461
  return () => {
7440
7462
  if (released) return;
7441
7463
  released = true;
7442
- entry.pendingAcquires = Math.max(0, entry.pendingAcquires - 1);
7443
- closeRetiredSharedClientEntryIfIdle(entry);
7444
- notifyDesktopGenerationDrainChecks(getSharedCodexAppServerClientState());
7464
+ releaseSharedClientEntry(entry, counter);
7445
7465
  };
7446
7466
  }
7447
- function retainSharedClientEntry(entry) {
7448
- let released = false;
7449
- entry.activeLeases += 1;
7450
- return () => {
7451
- if (released) return;
7452
- released = true;
7453
- entry.activeLeases = Math.max(0, entry.activeLeases - 1);
7454
- closeRetiredSharedClientEntryIfIdle(entry);
7455
- notifyDesktopGenerationDrainChecks(getSharedCodexAppServerClientState());
7456
- };
7467
+ function releaseSharedClientEntry(entry, counter) {
7468
+ entry[counter] -= 1;
7469
+ closeRetiredSharedClientEntryIfIdle(entry);
7470
+ notifyDesktopGenerationDrainChecks(getSharedCodexAppServerClientState());
7457
7471
  }
7458
7472
  function closeRetiredSharedClientEntryIfIdle(entry) {
7459
7473
  if (!entry.closeWhenIdle || entry.activeLeases > 0 || entry.pendingAcquires > 0 || !entry.client) return false;
@@ -7470,25 +7484,22 @@ function closeRetiredSharedClientEntry(entry) {
7470
7484
  client.close();
7471
7485
  return true;
7472
7486
  }
7473
- function closeSharedClientEntryIfUnclaimed(key, entry) {
7487
+ function closeSharedClientEntryIfUnclaimed(entry) {
7474
7488
  if (entry.activeLeases > 0 || entry.pendingAcquires > 0) return false;
7475
7489
  const state = getSharedCodexAppServerClientState();
7476
- if (state.clients.get(key) !== entry) return false;
7477
- state.clients.delete(key);
7490
+ if (state.clients.get(entry.key) !== entry) return false;
7491
+ state.clients.delete(entry.key);
7478
7492
  entry.client?.close();
7479
7493
  return Boolean(entry.client);
7480
7494
  }
7481
- function retirePendingSharedClientEntryIfUnclaimed(key, entry) {
7495
+ function retirePendingSharedClientEntryIfUnclaimed(entry) {
7482
7496
  if (entry.activeLeases > 0 || entry.pendingAcquires > 0) return;
7483
7497
  entry.startupAbort?.abort(/* @__PURE__ */ new Error("Codex app-server startup was abandoned"));
7484
7498
  entry.closeWhenIdle = true;
7485
7499
  const state = getSharedCodexAppServerClientState();
7486
- if (state.clients.get(key) === entry) state.clients.delete(key);
7500
+ if (state.clients.get(entry.key) === entry) state.clients.delete(entry.key);
7487
7501
  if (!entry.client) return;
7488
7502
  closeRetiredSharedClientEntry(entry);
7489
7503
  }
7490
- function collectSharedClients(state) {
7491
- return [...state.liveClients];
7492
- }
7493
7504
  //#endregion
7494
- export { assertCodexThreadResumeResponse as $, isJsonObject as $t, TURN_FINALIZE_DRAIN_ABORT_GRACE_MS as A, retainCodexAppServerLiveThread as At, isCodexAppServerIndeterminateRequestCancellationError as B, resolveCodexAppServerAuthProfileIdForAgent as Bt, withLeasedCodexAppServerClientStartSelectionRetry as C, ensureCodexAppServerClientRuntime as Ct, acquireCodexNativeConfigFence as D, protectCodexAppServerLiveThread as Dt, CodexThreadStartRequestError as E, isCodexAppServerLiveThreadClaimed as Et, withCodexStartupTimeout as F, readRecentCodexRateLimits as Ft, isUnsupportedCodexAppServerVersionError as G, resolveCodexManagedBundledMarketplacePath as Gt, isCodexAppServerOverloadError as H, resolveCodexAppServerFallbackApiKeyCacheKey as Ht, getCodexAppServerClientInstanceId as I, rememberCodexRateLimitsRead as It, CodexThreadDirectInputError as J, readCodexSessionMeta as Jt, resolveCodexAppServerClientInstanceId as K, assertNotSymlink as Kt, isCodexAppServerApprovalRequest as L, reconcileCodexComputerUseStartArtifacts as Lt, isCodexAppServerStartupError as M, withAbortableTimeout as Mt, resolveCodexGatewayTimeoutWithGraceMs as N, withTimeout$1 as Nt, createCodexDesktopGenerationService as O, readCodexClientSessionMeta as Ot, resolveCodexStartupTimeoutMs as P, readCodexRateLimitsRevision as Pt, assertCodexThreadForkResponse as Q, flattenCodexDynamicToolFunctions as Qt, isCodexAppServerBrokenPipeError as R, resolveCodexAppServerAuthAccountCacheKey as Rt, waitForCodexAppServerClientDesktopGenerationDrain as S, consumeCodexAppServerLiveThread as St, CodexThreadBindingConflictError as T, isCodexAppServerClientRuntimeLive as Tt, isCodexAppServerPrewriteRequestCancellationError as U, resolveCodexAppServerPreparedApiKeyCacheKey as Ut, isCodexAppServerIndeterminateTransportError as V, resolveCodexAppServerAuthProfileStore as Vt, isCodexAppServerRequestTimeoutError as W, resolveCodexAppServerPreparedAuthHandoff as Wt, assertCodexThreadAcceptsDirectInput as X, CODEX_INTERACTIVE_THREAD_SOURCE_KINDS as Xt, assertCodexModelListResponse as Y, CODEX_INTERACTIVE_CUSTOM_THREAD_SOURCES as Yt, assertCodexThreadForkParams as Z, CODEX_OPENCLAW_DIRECT_DYNAMIC_TOOL_NAMESPACE as Zt, retainSharedCodexAppServerClientByInstanceId as _, resolveCodexToolAbortTerminalReason as _t, clearSharedCodexAppServerClientIfCurrentAndUnclaimed as a, readCodexTurnCompletedNotification as at, retireSharedCodexAppServerClientsBeforeDesktopGeneration as b, withDynamicToolTranscriptDetails as bt, getLeasedSharedCodexAppServerClient as c, hasPendingDynamicToolTerminalDiagnostic as ct, readCodexAppServerClientDesktopGeneration as d, resolveDynamicToolCallTimeoutMs as dt, assertCodexThreadStartResponse as et, readCodexAppServerClientDesktopGenerationFingerprint as f, resolveTerminalDynamicToolBatchAction as ft, resolveCodexNativeConfigFenceKey as g, toCodexDynamicToolProtocolResponse as gt, releaseLeasedSharedCodexAppServerClient as h, toCodexDynamicToolProgressResponse as ht, clearSharedCodexAppServerClientIfCurrent as i, readCodexTurn as it, TURN_TERMINAL_SETTLEMENT_TIMEOUT_MS as j, unsubscribeCodexAppServerLiveThread as jt, CodexAppServerStartupError as k, releaseCodexAppServerLiveThread as kt, getSharedCodexAppServerClient as l, isDynamicToolTerminalDiagnosticEvent as lt, releaseCodexAppServerClientLease as m, shouldReleaseTurnAfterTerminalDynamicTool as mt, captureCodexAppServerClientLifetime as n, readCodexDynamicToolCallParams as nt, clearSharedCodexAppServerClientIfCurrentAndWait as o, createCodexElicitationResponse as ot, readCodexAppServerClientProcessIdentity as p, shouldBlockTerminalReleaseForNonTerminalDynamicToolResult as pt, CodexAppServerRpcError as q, isOpenClawManagedCodexThread as qt, captureSharedCodexAppServerCatalogLifetime as r, readCodexErrorNotification as rt, createIsolatedCodexAppServerClient as s, handleDynamicToolCallWithTimeout as st, assertCodexAppServerClientStartSelectionCurrent as t, assertCodexTurnStartResponse as tt, isCodexAppServerStartSelectionChangedError as u, isMatchingDynamicToolTerminalDiagnostic as ut, retainSharedCodexAppServerClientIfCurrent as v, createFailedDynamicToolResponse as vt, CodexAdoptedThreadActiveError as w, hasCodexAppServerLiveThread as wt, shared_client_exports as x, claimCodexAppServerLiveThread as xt, retireSharedCodexAppServerClientIfCurrent as y, withDynamicToolExecutionState as yt, isCodexAppServerConnectionClosedError as z, resolveCodexAppServerAuthProfileId as zt };
7505
+ export { assertCodexThreadForkParams as $, TURN_FINALIZE_DRAIN_ABORT_GRACE_MS as A, readCodexClientSessionMeta as At, isCodexAppServerIndeterminateRequestCancellationError as B, resolveCodexAppServerAuthAccountCacheKey as Bt, withLeasedCodexAppServerClientStartSelectionRetry as C, claimCodexAppServerLiveThread as Ct, acquireCodexNativeConfigFence as D, isCodexAppServerClientRuntimeLive as Dt, CodexThreadStartRequestError as E, hasCodexAppServerLiveThread as Et, withCodexStartupTimeout as F, withTimeout$1 as Ft, isUnsupportedCodexAppServerVersionError as G, resolveCodexAppServerPreparedApiKeyCacheKey as Gt, isCodexAppServerOverloadError as H, resolveCodexAppServerAuthProfileIdForAgent as Ht, getCodexAppServerClientInstanceId as I, readCodexRateLimitsRevision as It, isCodexThreadReadMissingError as J, assertNotSymlink as Jt, resolveCodexAppServerClientInstanceId as K, resolveCodexAppServerPreparedAuthHandoff as Kt, isCodexAppServerApprovalRequest as L, readRecentCodexRateLimits as Lt, isCodexAppServerStartupError as M, retainCodexAppServerLiveThread as Mt, resolveCodexGatewayTimeoutWithGraceMs as N, unsubscribeCodexAppServerLiveThread as Nt, createCodexDesktopGenerationService as O, isCodexAppServerLiveThreadClaimed as Ot, resolveCodexStartupTimeoutMs as P, withAbortableTimeout as Pt, assertCodexThreadAcceptsDirectInput as Q, isCodexAppServerBrokenPipeError as R, rememberCodexRateLimitsRead as Rt, waitForCodexAppServerClientDesktopGenerationDrain as S, withDynamicToolTranscriptDetails as St, CodexThreadBindingConflictError as T, ensureCodexAppServerClientRuntime as Tt, isCodexAppServerPrewriteRequestCancellationError as U, resolveCodexAppServerAuthProfileStore as Ut, isCodexAppServerIndeterminateTransportError as V, resolveCodexAppServerAuthProfileId as Vt, isCodexAppServerRequestTimeoutError as W, resolveCodexAppServerFallbackApiKeyCacheKey as Wt, assertCodexModelListResponse as X, readCodexSessionMeta as Xt, CodexThreadDirectInputError as Y, isOpenClawManagedCodexThread as Yt, assertCodexPassiveTurnItems as Z, retainSharedCodexAppServerClientByInstanceId as _, toCodexDynamicToolProgressResponse as _t, clearSharedCodexAppServerClientIfCurrentAndUnclaimed as a, readCodexErrorNotification as at, retireSharedCodexAppServerClientsBeforeDesktopGeneration as b, createFailedDynamicToolResponse as bt, getLeasedSharedCodexAppServerClient as c, createCodexElicitationResponse as ct, readCodexAppServerClientDesktopGeneration as d, isDynamicToolTerminalDiagnosticEvent as dt, assertCodexThreadForkResponse as et, readCodexAppServerClientDesktopGenerationFingerprint as f, isMatchingDynamicToolTerminalDiagnostic as ft, resolveCodexNativeConfigFenceKey as g, shouldReleaseTurnAfterTerminalDynamicTool as gt, releaseLeasedSharedCodexAppServerClient as h, shouldBlockTerminalReleaseForNonTerminalDynamicToolResult as ht, clearSharedCodexAppServerClientIfCurrent as i, readCodexDynamicToolCallParams as it, TURN_TERMINAL_SETTLEMENT_TIMEOUT_MS as j, releaseCodexAppServerLiveThread as jt, CodexAppServerStartupError as k, protectCodexAppServerLiveThread as kt, getSharedCodexAppServerClient as l, handleDynamicToolCallWithTimeout as lt, releaseCodexAppServerClientLease as m, resolveTerminalDynamicToolBatchAction as mt, captureCodexAppServerClientLifetime as n, assertCodexThreadStartResponse as nt, clearSharedCodexAppServerClientIfCurrentAndWait as o, readCodexTurn as ot, readCodexAppServerClientProcessIdentity as p, resolveDynamicToolCallTimeoutMs as pt, CodexAppServerRpcError as q, resolveCodexManagedBundledMarketplacePath as qt, captureSharedCodexAppServerCatalogLifetime as r, assertCodexTurnStartResponse as rt, createIsolatedCodexAppServerClient as s, readCodexTurnCompletedNotification as st, assertCodexAppServerClientStartSelectionCurrent as t, assertCodexThreadResumeResponse as tt, isCodexAppServerStartSelectionChangedError as u, hasPendingDynamicToolTerminalDiagnostic as ut, retainSharedCodexAppServerClientIfCurrent as v, toCodexDynamicToolProtocolResponse as vt, CodexAdoptedThreadActiveError as w, consumeCodexAppServerLiveThread as wt, shared_client_exports as x, withDynamicToolExecutionState as xt, retireSharedCodexAppServerClientIfCurrent as y, resolveCodexToolAbortTerminalReason as yt, isCodexAppServerConnectionClosedError as z, reconcileCodexComputerUseStartArtifacts as zt };