@openclaw/codex 2026.6.1 → 2026.6.5-beta.1

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 (31) hide show
  1. package/dist/client-factory-Bt49r45B.js +17 -0
  2. package/dist/{client-BnOmn0y-.js → client-kMCtlApt.js} +43 -1
  3. package/dist/{command-handlers-VhJdcXcI.js → command-handlers-DMn2M7W7.js} +10 -10
  4. package/dist/{compact-D1dSrNrT.js → compact-CwnPeYnM.js} +16 -5
  5. package/dist/{computer-use-DYLSxIfq.js → computer-use-ClweWaMz.js} +12 -2
  6. package/dist/{config-AlzuNKCY.js → config-BT6SLiE6.js} +4 -12
  7. package/dist/{conversation-binding-CqVPKJPp.js → conversation-binding-CzpvaBs1.js} +8 -8
  8. package/dist/doctor-contract-api.js +5 -0
  9. package/dist/harness.js +9 -5
  10. package/dist/index.js +12 -13
  11. package/dist/media-understanding-provider.js +14 -6
  12. package/dist/{models-DAJvlyJu.js → models-DXorTaja.js} +9 -2
  13. package/dist/{native-hook-relay-CIJt8cLN.js → native-hook-relay-DZ3Oon0b.js} +61 -3
  14. package/dist/{notification-correlation-BykOI_jh.js → notification-correlation-o8quHmTK.js} +30 -1
  15. package/dist/prompt-overlay.js +7 -0
  16. package/dist/{protocol-validators-DIt7cXIp.js → protocol-validators-CIpP8IJ2.js} +13 -0
  17. package/dist/provider-catalog.js +8 -0
  18. package/dist/provider-discovery.js +1 -0
  19. package/dist/provider.js +17 -2
  20. package/dist/{rate-limit-cache-N66I-Rd7.js → rate-limit-cache-C7qmZ0Jh.js} +2 -0
  21. package/dist/{request-CPtFWp-f.js → request-D64BfplD.js} +16 -4
  22. package/dist/{run-attempt-DM53zFlW.js → run-attempt-B_6VkFQN.js} +432 -35
  23. package/dist/{sandbox-guard-DMCJlzmz.js → sandbox-guard-C-Yv9uwY.js} +5 -0
  24. package/dist/{session-binding-DWiEGATW.js → session-binding-BgTv_YGm.js} +13 -2
  25. package/dist/{shared-client-DUWLidr5.js → shared-client-xytpSKD0.js} +92 -5
  26. package/dist/{side-question-dIZf9RBV.js → side-question-BEpALo9c.js} +10 -10
  27. package/dist/{thread-lifecycle-6nrEQZMV.js → thread-lifecycle-BJsazZ8j.js} +79 -46
  28. package/npm-shrinkwrap.json +2 -2
  29. package/openclaw.plugin.json +1 -1
  30. package/package.json +4 -4
  31. package/dist/client-factory-3ykiiX2z.js +0 -20
@@ -6,6 +6,7 @@ const VALID_AGENT_ID_PATTERN = /^[a-z0-9][a-z0-9_-]{0,63}$/i;
6
6
  const INVALID_AGENT_ID_CHARS_PATTERN = /[^a-z0-9_-]+/g;
7
7
  const LEADING_DASH_PATTERN = /^-+/;
8
8
  const TRAILING_DASH_PATTERN = /-+$/;
9
+ /** Resolves node/gateway/sandbox execution ownership from overrides, session, agent, and config. */
9
10
  function resolveCodexNativeExecutionPolicy(params) {
10
11
  const config = params.config ?? {};
11
12
  const sessionKey = params.sessionKey?.trim() || params.sessionId?.trim() || void 0;
@@ -43,6 +44,7 @@ function resolveCodexNativeExecutionPolicy(params) {
43
44
  blockReason: "OpenClaw exec host=node is active for this session. Codex app-server native execution cannot route shell, filesystem, MCP, or app-backed work through the selected OpenClaw node."
44
45
  };
45
46
  }
47
+ /** Formats the user-facing explanation shown when native tools are blocked by exec host=node. */
46
48
  function formatCodexNativeNodeExecBlock(params) {
47
49
  return [
48
50
  `Codex-native ${params.surface} is unavailable because OpenClaw exec host=node is active for this session.`,
@@ -155,6 +157,7 @@ const BLOCKED_DIRECT_METHOD_PREFIXES = [
155
157
  "windowsSandbox/"
156
158
  ];
157
159
  const NODE_EXEC_BLOCKED_CONTROL_PLANE_METHODS = new Set(["config/mcpServer/reload"]);
160
+ /** Returns a block message when a direct app-server method would bypass OpenClaw execution policy. */
158
161
  function resolveCodexAppServerDirectSandboxBypassBlock(params) {
159
162
  const policy = resolveDirectMethodPolicy(params.method);
160
163
  if (NODE_EXEC_BLOCKED_CONTROL_PLANE_METHODS.has(params.method)) {
@@ -185,9 +188,11 @@ function resolveCodexAppServerDirectSandboxBypassBlock(params) {
185
188
  if (policy === "requires-openclaw-environment" && hasOpenClawSandboxEnvironmentSelection(params.requestParams)) return;
186
189
  return sandboxBlock;
187
190
  }
191
+ /** Resolves the generic native-execution block for sandboxed or node-hosted sessions. */
188
192
  function resolveCodexNativeExecutionBlock(params) {
189
193
  return resolveCodexNativeSandboxBlock(params) ?? resolveCodexNativeNodeExecBlock(params);
190
194
  }
195
+ /** Returns a block message when native Codex execution cannot honor active sandboxing. */
191
196
  function resolveCodexNativeSandboxBlock(params) {
192
197
  const sessionKey = params.sessionKey?.trim() || params.sessionId?.trim();
193
198
  if (!sessionKey) return;
@@ -1,9 +1,13 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
- import { l as normalizeCodexServiceTier, s as isCodexPluginsMarketplaceName } from "./config-AlzuNKCY.js";
2
+ import { s as normalizeCodexServiceTier } from "./config-BT6SLiE6.js";
3
3
  import { embeddedAgentLog } from "openclaw/plugin-sdk/agent-harness-runtime";
4
4
  import fs from "node:fs/promises";
5
5
  import { ensureAuthProfileStore, resolveDefaultAgentDir, resolveProviderIdForAuth } from "openclaw/plugin-sdk/agent-runtime";
6
6
  //#region extensions/codex/src/app-server/session-binding.ts
7
+ /**
8
+ * Persists and normalizes the Codex app-server thread binding associated with
9
+ * an OpenClaw session file.
10
+ */
7
11
  var session_binding_exports = /* @__PURE__ */ __exportAll({
8
12
  clearCodexAppServerBinding: () => clearCodexAppServerBinding,
9
13
  clearCodexAppServerBindingForThread: () => clearCodexAppServerBindingForThread,
@@ -15,9 +19,11 @@ var session_binding_exports = /* @__PURE__ */ __exportAll({
15
19
  });
16
20
  const CODEX_APP_SERVER_NATIVE_AUTH_PROVIDER = "openai";
17
21
  const PUBLIC_OPENAI_MODEL_PROVIDER = "openai";
22
+ /** Returns the JSON sidecar path for the Codex app-server binding beside a session file. */
18
23
  function resolveCodexAppServerBindingPath(sessionFile) {
19
24
  return `${sessionFile}.codex-app-server.json`;
20
25
  }
26
+ /** Reads and normalizes a Codex app-server binding sidecar, returning undefined on stale data. */
21
27
  async function readCodexAppServerBinding(sessionFile, lookup = {}) {
22
28
  const path = resolveCodexAppServerBindingPath(sessionFile);
23
29
  let raw;
@@ -71,6 +77,7 @@ async function readCodexAppServerBinding(sessionFile, lookup = {}) {
71
77
  return;
72
78
  }
73
79
  }
80
+ /** Writes the Codex app-server binding sidecar with normalized provider/auth metadata. */
74
81
  async function writeCodexAppServerBinding(sessionFile, binding, lookup = {}) {
75
82
  const now = (/* @__PURE__ */ new Date()).toISOString();
76
83
  const payload = {
@@ -135,7 +142,7 @@ function readPluginAppPolicyContext(value) {
135
142
  for (const [appId, rawEntry] of Object.entries(apps)) {
136
143
  if (!rawEntry || typeof rawEntry !== "object" || Array.isArray(rawEntry)) return;
137
144
  const entry = rawEntry;
138
- if ("appId" in entry || typeof entry.configKey !== "string" || typeof entry.marketplaceName !== "string" || !isCodexPluginsMarketplaceName(entry.marketplaceName) || typeof entry.pluginName !== "string" || typeof entry.allowDestructiveActions !== "boolean" || !Array.isArray(entry.mcpServerNames) || entry.mcpServerNames.some((serverName) => typeof serverName !== "string")) return;
145
+ if ("appId" in entry || typeof entry.configKey !== "string" || entry.marketplaceName !== "openai-curated" || typeof entry.pluginName !== "string" || typeof entry.allowDestructiveActions !== "boolean" || !Array.isArray(entry.mcpServerNames) || entry.mcpServerNames.some((serverName) => typeof serverName !== "string")) return;
139
146
  parsedApps[appId] = {
140
147
  configKey: entry.configKey,
141
148
  marketplaceName: entry.marketplaceName,
@@ -157,6 +164,7 @@ function readPluginAppPolicyContext(value) {
157
164
  pluginAppIds: parsedPluginAppIds
158
165
  };
159
166
  }
167
+ /** Removes the Codex app-server binding sidecar if present. */
160
168
  async function clearCodexAppServerBinding(sessionFile, _lookup = {}) {
161
169
  try {
162
170
  await fs.unlink(resolveCodexAppServerBindingPath(sessionFile));
@@ -167,6 +175,7 @@ async function clearCodexAppServerBinding(sessionFile, _lookup = {}) {
167
175
  });
168
176
  }
169
177
  }
178
+ /** Clears a binding only when it still points at the expected Codex thread id. */
170
179
  async function clearCodexAppServerBindingForThread(sessionFile, threadId, lookup = {}) {
171
180
  const binding = await readCodexAppServerBinding(sessionFile, lookup);
172
181
  if (!binding) return false;
@@ -184,6 +193,7 @@ async function clearCodexAppServerBindingForThread(sessionFile, threadId, lookup
184
193
  function isNotFound(error) {
185
194
  return Boolean(error && typeof error === "object" && "code" in error && error.code === "ENOENT");
186
195
  }
196
+ /** Returns true when an auth profile uses native Codex/OpenAI app-server auth. */
187
197
  function isCodexAppServerNativeAuthProfile(lookup) {
188
198
  const authProfileId = lookup.authProfileId?.trim();
189
199
  if (!authProfileId) return false;
@@ -205,6 +215,7 @@ function isCodexAppServerNativeAuthProfile(lookup) {
205
215
  return false;
206
216
  }
207
217
  }
218
+ /** Hides redundant OpenAI provider attribution for native Codex auth bindings. */
208
219
  function normalizeCodexAppServerBindingModelProvider(params) {
209
220
  const modelProvider = params.modelProvider?.trim();
210
221
  if (!modelProvider) return;
@@ -1,6 +1,6 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
- import { d as resolveCodexAppServerRuntimeOptions, r as codexAppServerStartOptionsKey } from "./config-AlzuNKCY.js";
3
- import { c as resolveCodexAppServerSpawnEnv, o as MANAGED_CODEX_APP_SERVER_PACKAGE, t as CodexAppServerClient } from "./client-BnOmn0y-.js";
2
+ import { l as resolveCodexAppServerRuntimeOptions, n as codexAppServerStartOptionsKey } from "./config-BT6SLiE6.js";
3
+ import { c as resolveCodexAppServerSpawnEnv, o as MANAGED_CODEX_APP_SERVER_PACKAGE, t as CodexAppServerClient } from "./client-kMCtlApt.js";
4
4
  import { createRequire } from "node:module";
5
5
  import { createHash } from "node:crypto";
6
6
  import fsSync, { constants, readFileSync } from "node:fs";
@@ -12,6 +12,7 @@ import { fileURLToPath } from "node:url";
12
12
  import { withTimeout } from "openclaw/plugin-sdk/security-runtime";
13
13
  //#region extensions/codex/src/app-server/auth-bridge.ts
14
14
  const CODEX_APP_SERVER_AUTH_PROVIDER = "openai";
15
+ const OPENAI_CODEX_APP_SERVER_AUTH_PROVIDER = "openai-codex";
15
16
  const LEGACY_CODEX_APP_SERVER_AUTH_PROVIDER = "codex-cli";
16
17
  const CODEX_APP_SERVER_EXTERNAL_CLI_PROVIDER_IDS = [CODEX_APP_SERVER_AUTH_PROVIDER, LEGACY_CODEX_APP_SERVER_AUTH_PROVIDER];
17
18
  const OPENAI_PROVIDER = "openai";
@@ -368,7 +369,7 @@ async function resolveOAuthCredentialForCodexAppServer(profileId, credential, pa
368
369
  }
369
370
  function isCodexAppServerAuthProvider(provider, config) {
370
371
  const resolvedProvider = resolveProviderIdForAuth(provider, { config });
371
- return resolvedProvider === CODEX_APP_SERVER_AUTH_PROVIDER || resolvedProvider === LEGACY_CODEX_APP_SERVER_AUTH_PROVIDER;
372
+ return resolvedProvider === CODEX_APP_SERVER_AUTH_PROVIDER || resolvedProvider === OPENAI_CODEX_APP_SERVER_AUTH_PROVIDER || resolvedProvider === LEGACY_CODEX_APP_SERVER_AUTH_PROVIDER;
372
373
  }
373
374
  function isOpenAIApiKeyBackupCredential(credential, config) {
374
375
  return credential.type === "api_key" && resolveProviderIdForAuth(credential.provider, { config }) === OPENAI_PROVIDER;
@@ -427,7 +428,12 @@ function resolveChatgptAccountId(profileId, credential) {
427
428
  }
428
429
  //#endregion
429
430
  //#region extensions/codex/src/app-server/managed-binary.ts
431
+ /**
432
+ * Resolves the managed Codex app-server binary shipped with or installed beside
433
+ * the Codex plugin before stdio startup.
434
+ */
430
435
  const CODEX_PLUGIN_ROOT = resolveDefaultCodexPluginRoot(path.dirname(fileURLToPath(import.meta.url)));
436
+ /** Rewrites managed stdio start options to point at an executable Codex binary path. */
431
437
  async function resolveManagedCodexAppServerStartOptions(startOptions, options = {}) {
432
438
  if (startOptions.transport !== "stdio" || startOptions.commandSource !== "managed") return startOptions;
433
439
  const platform = options.platform ?? process.platform;
@@ -447,6 +453,7 @@ async function resolveManagedCodexAppServerStartOptions(startOptions, options =
447
453
  commandSource: "resolved-managed"
448
454
  };
449
455
  }
456
+ /** Returns the preferred and fallback managed Codex binary paths for a plugin root. */
450
457
  function resolveManagedCodexAppServerPaths(params) {
451
458
  const platform = params.platform ?? process.platform;
452
459
  const candidateCommandPaths = resolveManagedCodexAppServerCommandCandidates(params.pluginRoot ?? CODEX_PLUGIN_ROOT, platform);
@@ -543,15 +550,25 @@ async function commandPathExists(filePath, platform) {
543
550
  }
544
551
  //#endregion
545
552
  //#region extensions/codex/src/app-server/timeout.ts
553
+ /**
554
+ * Thin Codex app-server timeout adapter around OpenClaw's shared security
555
+ * runtime timeout helper.
556
+ */
557
+ /** Awaits a promise with a Codex-specific timeout error message. */
546
558
  async function withTimeout$1(promise, timeoutMs, timeoutMessage) {
547
559
  return await withTimeout(promise, timeoutMs, { message: timeoutMessage });
548
560
  }
549
561
  //#endregion
550
562
  //#region extensions/codex/src/app-server/shared-client.ts
563
+ /**
564
+ * Owns shared and isolated Codex app-server client startup, auth application,
565
+ * lease tracking, and teardown.
566
+ */
551
567
  var shared_client_exports = /* @__PURE__ */ __exportAll({
552
568
  clearSharedCodexAppServerClient: () => clearSharedCodexAppServerClient,
553
569
  clearSharedCodexAppServerClientAndWait: () => clearSharedCodexAppServerClientAndWait,
554
570
  clearSharedCodexAppServerClientIfCurrent: () => clearSharedCodexAppServerClientIfCurrent,
571
+ clearSharedCodexAppServerClientIfCurrentAndUnclaimed: () => clearSharedCodexAppServerClientIfCurrentAndUnclaimed,
555
572
  clearSharedCodexAppServerClientIfCurrentAndWait: () => clearSharedCodexAppServerClientIfCurrentAndWait,
556
573
  createIsolatedCodexAppServerClient: () => createIsolatedCodexAppServerClient,
557
574
  detachSharedCodexAppServerClientIfCurrent: () => detachSharedCodexAppServerClientIfCurrent,
@@ -571,6 +588,7 @@ function getSharedCodexAppServerClientState() {
571
588
  const clients = keyedState.clients;
572
589
  for (const entry of clients.values()) {
573
590
  entry.activeLeases ??= 0;
591
+ entry.pendingAcquires ??= 0;
574
592
  entry.closeWhenIdle ??= false;
575
593
  }
576
594
  const nextState = {
@@ -588,6 +606,7 @@ function getSharedCodexAppServerClientState() {
588
606
  client: legacyState.client,
589
607
  promise: legacyState.promise,
590
608
  activeLeases: 0,
609
+ pendingAcquires: 0,
591
610
  closeWhenIdle: false
592
611
  });
593
612
  legacyState.client?.addCloseHandler((closedClient) => clearSharedClientEntryIfCurrent(legacyKey, closedClient));
@@ -627,9 +646,11 @@ async function resolveCodexAppServerClientStartContext(options) {
627
646
  })
628
647
  };
629
648
  }
649
+ /** Gets or starts a shared Codex app-server client without retaining a lease. */
630
650
  async function getSharedCodexAppServerClient(options) {
631
651
  return (await acquireSharedCodexAppServerClient(options)).client;
632
652
  }
653
+ /** Gets or starts a shared Codex app-server client and records a release lease. */
633
654
  async function getLeasedSharedCodexAppServerClient(options) {
634
655
  const acquired = await acquireSharedCodexAppServerClient(options, { leased: true });
635
656
  const state = getSharedCodexAppServerClientState();
@@ -638,6 +659,7 @@ async function getLeasedSharedCodexAppServerClient(options) {
638
659
  state.leasedReleases.set(acquired.client, releases);
639
660
  return acquired.client;
640
661
  }
662
+ /** Releases one outstanding lease for a shared Codex app-server client. */
641
663
  function releaseLeasedSharedCodexAppServerClient(client) {
642
664
  const state = getSharedCodexAppServerClientState();
643
665
  const releases = state.leasedReleases.get(client);
@@ -658,9 +680,21 @@ async function acquireSharedCodexAppServerClient(options, leaseOptions) {
658
680
  });
659
681
  const state = getSharedCodexAppServerClientState();
660
682
  const entry = getOrCreateSharedClientEntry(state, key);
683
+ const releasePendingAcquire = retainPendingSharedClientAcquire(entry);
684
+ let cleanupAbandonSignal;
685
+ if (options?.abandonSignal) {
686
+ const abandon = () => {
687
+ releasePendingAcquire();
688
+ closeSharedClientEntryIfUnclaimed(key, entry);
689
+ };
690
+ options.abandonSignal.addEventListener("abort", abandon, { once: true });
691
+ cleanupAbandonSignal = () => options.abandonSignal?.removeEventListener("abort", abandon);
692
+ if (options.abandonSignal.aborted) abandon();
693
+ }
661
694
  const sharedPromise = entry.promise ?? (entry.promise = (async () => {
662
695
  const client = CodexAppServerClient.start(startOptions);
663
696
  entry.client = client;
697
+ options?.onStartedClient?.(client);
664
698
  client.setActiveSharedLeaseCountProviderForUnscopedNotifications(() => entry.activeLeases);
665
699
  client.addCloseHandler((closedClient) => clearSharedClientEntryIfCurrent(key, closedClient));
666
700
  try {
@@ -690,8 +724,12 @@ async function acquireSharedCodexAppServerClient(options, leaseOptions) {
690
724
  const currentEntry = state.clients.get(key);
691
725
  if (currentEntry?.promise === sharedPromise) clearSharedClientEntry(key, currentEntry);
692
726
  throw error;
727
+ } finally {
728
+ cleanupAbandonSignal?.();
729
+ releasePendingAcquire();
693
730
  }
694
731
  }
732
+ /** Starts a non-shared Codex app-server client owned entirely by the caller. */
695
733
  async function createIsolatedCodexAppServerClient(options) {
696
734
  const { agentDir, usesNativeAuth, authProfileId, startOptions } = await resolveCodexAppServerClientStartContext(options);
697
735
  const client = CodexAppServerClient.start(startOptions);
@@ -712,6 +750,7 @@ async function createIsolatedCodexAppServerClient(options) {
712
750
  throw error;
713
751
  }
714
752
  }
753
+ /** Clears and closes all shared clients for deterministic tests. */
715
754
  function resetSharedCodexAppServerClientForTests() {
716
755
  const state = getSharedCodexAppServerClientState();
717
756
  const clients = collectSharedClients(state);
@@ -719,12 +758,14 @@ function resetSharedCodexAppServerClientForTests() {
719
758
  state.leasedReleases = /* @__PURE__ */ new WeakMap();
720
759
  for (const client of clients) client.close();
721
760
  }
761
+ /** Clears and closes all shared clients. */
722
762
  function clearSharedCodexAppServerClient() {
723
763
  const state = getSharedCodexAppServerClientState();
724
764
  const clients = collectSharedClients(state);
725
765
  state.clients.clear();
726
766
  for (const client of clients) client.close();
727
767
  }
768
+ /** Clears and closes the shared entry only if it still owns the supplied client. */
728
769
  function clearSharedCodexAppServerClientIfCurrent(client) {
729
770
  if (!client) return false;
730
771
  const state = getSharedCodexAppServerClientState();
@@ -735,6 +776,7 @@ function clearSharedCodexAppServerClientIfCurrent(client) {
735
776
  }
736
777
  return false;
737
778
  }
779
+ /** Detaches the shared entry without closing the client when it still matches. */
738
780
  function detachSharedCodexAppServerClientIfCurrent(client) {
739
781
  if (!client) return false;
740
782
  const state = getSharedCodexAppServerClientState();
@@ -744,11 +786,13 @@ function detachSharedCodexAppServerClientIfCurrent(client) {
744
786
  }
745
787
  return false;
746
788
  }
789
+ /** Retains the matching shared client and returns a release callback. */
747
790
  function retainSharedCodexAppServerClientIfCurrent(client) {
748
791
  if (!client) return;
749
792
  const state = getSharedCodexAppServerClientState();
750
793
  for (const entry of state.clients.values()) if (entry.client === client) return retainSharedClientEntry(entry);
751
794
  }
795
+ /** Marks a matching shared client to close after active leases/acquires drain. */
752
796
  function retireSharedCodexAppServerClientIfCurrent(client) {
753
797
  if (!client) return;
754
798
  const state = getSharedCodexAppServerClientState();
@@ -767,6 +811,7 @@ function retireSharedCodexAppServerClientIfCurrent(client) {
767
811
  closed: false
768
812
  };
769
813
  }
814
+ /** Clears a matching shared client and waits for its process to exit. */
770
815
  async function clearSharedCodexAppServerClientIfCurrentAndWait(client, options) {
771
816
  if (!client) return false;
772
817
  const state = getSharedCodexAppServerClientState();
@@ -777,6 +822,7 @@ async function clearSharedCodexAppServerClientIfCurrentAndWait(client, options)
777
822
  }
778
823
  return false;
779
824
  }
825
+ /** Clears all shared clients and waits for their processes to exit. */
780
826
  async function clearSharedCodexAppServerClientAndWait(options) {
781
827
  const state = getSharedCodexAppServerClientState();
782
828
  const clients = collectSharedClients(state);
@@ -788,6 +834,7 @@ function getOrCreateSharedClientEntry(state, key) {
788
834
  if (!entry) {
789
835
  entry = {
790
836
  activeLeases: 0,
837
+ pendingAcquires: 0,
791
838
  closeWhenIdle: false
792
839
  };
793
840
  state.clients.set(key, entry);
@@ -804,6 +851,38 @@ function clearSharedClientEntryIfCurrent(key, client) {
804
851
  const state = getSharedCodexAppServerClientState();
805
852
  if (state.clients.get(key)?.client === client) state.clients.delete(key);
806
853
  }
854
+ /** Clears a matching shared client only when no lease or acquire currently claims it. */
855
+ function clearSharedCodexAppServerClientIfCurrentAndUnclaimed(client) {
856
+ if (!client) return {
857
+ found: false,
858
+ closed: false,
859
+ activeLeases: 0,
860
+ pendingAcquires: 0
861
+ };
862
+ const state = getSharedCodexAppServerClientState();
863
+ for (const [key, entry] of state.clients) if (entry.client === client) return {
864
+ found: true,
865
+ closed: closeSharedClientEntryIfUnclaimed(key, entry),
866
+ activeLeases: entry.activeLeases,
867
+ pendingAcquires: entry.pendingAcquires
868
+ };
869
+ return {
870
+ found: false,
871
+ closed: false,
872
+ activeLeases: 0,
873
+ pendingAcquires: 0
874
+ };
875
+ }
876
+ function retainPendingSharedClientAcquire(entry) {
877
+ let released = false;
878
+ entry.pendingAcquires += 1;
879
+ return () => {
880
+ if (released) return;
881
+ released = true;
882
+ entry.pendingAcquires = Math.max(0, entry.pendingAcquires - 1);
883
+ closeRetiredSharedClientEntryIfIdle(entry);
884
+ };
885
+ }
807
886
  function retainSharedClientEntry(entry) {
808
887
  let released = false;
809
888
  entry.activeLeases += 1;
@@ -815,15 +894,23 @@ function retainSharedClientEntry(entry) {
815
894
  };
816
895
  }
817
896
  function closeRetiredSharedClientEntryIfIdle(entry) {
818
- if (!entry.closeWhenIdle || entry.activeLeases > 0 || !entry.client) return false;
897
+ if (!entry.closeWhenIdle || entry.activeLeases > 0 || entry.pendingAcquires > 0 || !entry.client) return false;
819
898
  const client = entry.client;
820
899
  entry.closeWhenIdle = false;
821
900
  entry.client = void 0;
822
901
  client.close();
823
902
  return true;
824
903
  }
904
+ function closeSharedClientEntryIfUnclaimed(key, entry) {
905
+ if (entry.activeLeases > 0 || entry.pendingAcquires > 0) return false;
906
+ const state = getSharedCodexAppServerClientState();
907
+ if (state.clients.get(key) !== entry) return false;
908
+ state.clients.delete(key);
909
+ entry.client?.close();
910
+ return Boolean(entry.client);
911
+ }
825
912
  function collectSharedClients(state) {
826
913
  return [...new Set([...state.clients.values()].map((entry) => entry.client).filter((client) => Boolean(client)))];
827
914
  }
828
915
  //#endregion
829
- export { releaseLeasedSharedCodexAppServerClient as a, withTimeout$1 as c, resolveCodexAppServerAuthProfileId as d, resolveCodexAppServerAuthProfileIdForAgent as f, getLeasedSharedCodexAppServerClient as i, refreshCodexAppServerAuthTokens as l, resolveCodexAppServerHomeDir as m, clearSharedCodexAppServerClientIfCurrentAndWait as n, retireSharedCodexAppServerClientIfCurrent as o, resolveCodexAppServerFallbackApiKeyCacheKey as p, createIsolatedCodexAppServerClient as r, shared_client_exports as s, clearSharedCodexAppServerClientIfCurrent as t, resolveCodexAppServerAuthAccountCacheKey as u };
916
+ export { getLeasedSharedCodexAppServerClient as a, shared_client_exports as c, resolveCodexAppServerAuthAccountCacheKey as d, resolveCodexAppServerAuthProfileId as f, resolveCodexAppServerHomeDir as h, createIsolatedCodexAppServerClient as i, withTimeout$1 as l, resolveCodexAppServerFallbackApiKeyCacheKey as m, clearSharedCodexAppServerClientIfCurrentAndUnclaimed as n, releaseLeasedSharedCodexAppServerClient as o, resolveCodexAppServerAuthProfileIdForAgent as p, clearSharedCodexAppServerClientIfCurrentAndWait as r, retireSharedCodexAppServerClientIfCurrent as s, clearSharedCodexAppServerClientIfCurrent as t, refreshCodexAppServerAuthTokens as u };
@@ -1,13 +1,13 @@
1
- import { d as resolveCodexAppServerRuntimeOptions, h as shouldAutoApproveCodexAppServerApprovals, u as readCodexPluginConfig } from "./config-AlzuNKCY.js";
2
- import { a as readCodexDynamicToolCallParams, c as readCodexTurn, i as assertCodexTurnStartResponse, t as assertCodexThreadForkResponse } from "./protocol-validators-DIt7cXIp.js";
3
- import { i as isCodexAppServerApprovalRequest, l as isJsonObject } from "./client-BnOmn0y-.js";
4
- import { O as resolveCodexDynamicToolsLoading, T as filterCodexDynamicTools, d as resolveReasoningEffort, g as mergeCodexThreadConfigs, r as buildCodexRuntimeThreadConfig, t as CODEX_NATIVE_PERSONALITY_NONE, u as resolveCodexAppServerModelProvider } from "./thread-lifecycle-6nrEQZMV.js";
5
- import { a as readCodexAppServerBinding } from "./session-binding-DWiEGATW.js";
6
- import { h as formatCodexUsageLimitErrorMessage, i as readCodexNotificationTurnId, r as readCodexNotificationThreadId } from "./notification-correlation-BykOI_jh.js";
7
- import { a as releaseLeasedSharedCodexAppServerClient, i as getLeasedSharedCodexAppServerClient, l as refreshCodexAppServerAuthTokens } from "./shared-client-DUWLidr5.js";
8
- import { n as resolveCodexNativeExecutionBlock } from "./sandbox-guard-DMCJlzmz.js";
9
- import { d as emitDynamicToolErrorDiagnostic, f as emitDynamicToolStartedDiagnostic, h as handleCodexAppServerApprovalRequest, i as buildCodexNativeHookRelayDisabledConfig, l as handleCodexAppServerElicitationRequest, m as filterToolsForVisionInputs, p as emitDynamicToolTerminalDiagnostic, r as buildCodexNativeHookRelayConfig, t as CODEX_NATIVE_HOOK_RELAY_EVENTS, u as createCodexDynamicToolBridge } from "./native-hook-relay-CIJt8cLN.js";
10
- import { n as rememberCodexRateLimits, t as readRecentCodexRateLimits } from "./rate-limit-cache-N66I-Rd7.js";
1
+ import { c as readCodexPluginConfig, l as resolveCodexAppServerRuntimeOptions, p as shouldAutoApproveCodexAppServerApprovals } from "./config-BT6SLiE6.js";
2
+ import { a as readCodexDynamicToolCallParams, c as readCodexTurn, i as assertCodexTurnStartResponse, t as assertCodexThreadForkResponse } from "./protocol-validators-CIpP8IJ2.js";
3
+ import { i as isCodexAppServerApprovalRequest, l as isJsonObject } from "./client-kMCtlApt.js";
4
+ import { O as resolveCodexDynamicToolsLoading, T as filterCodexDynamicTools, d as resolveReasoningEffort, g as mergeCodexThreadConfigs, r as buildCodexRuntimeThreadConfig, t as CODEX_NATIVE_PERSONALITY_NONE, u as resolveCodexAppServerModelProvider } from "./thread-lifecycle-BJsazZ8j.js";
5
+ import { a as readCodexAppServerBinding } from "./session-binding-BgTv_YGm.js";
6
+ import { h as formatCodexUsageLimitErrorMessage, i as readCodexNotificationTurnId, r as readCodexNotificationThreadId } from "./notification-correlation-o8quHmTK.js";
7
+ import { a as getLeasedSharedCodexAppServerClient, o as releaseLeasedSharedCodexAppServerClient, u as refreshCodexAppServerAuthTokens } from "./shared-client-xytpSKD0.js";
8
+ import { n as resolveCodexNativeExecutionBlock } from "./sandbox-guard-C-Yv9uwY.js";
9
+ import { d as emitDynamicToolErrorDiagnostic, f as emitDynamicToolStartedDiagnostic, h as handleCodexAppServerApprovalRequest, i as buildCodexNativeHookRelayDisabledConfig, l as handleCodexAppServerElicitationRequest, m as filterToolsForVisionInputs, p as emitDynamicToolTerminalDiagnostic, r as buildCodexNativeHookRelayConfig, t as CODEX_NATIVE_HOOK_RELAY_EVENTS, u as createCodexDynamicToolBridge } from "./native-hook-relay-DZ3Oon0b.js";
10
+ import { n as rememberCodexRateLimits, t as readRecentCodexRateLimits } from "./rate-limit-cache-C7qmZ0Jh.js";
11
11
  import { buildAgentHookContextChannelFields, embeddedAgentLog, formatErrorMessage, registerNativeHookRelay, resolveAgentDir, resolveAttemptSpawnWorkspaceDir, resolveModelAuthMode, resolveSandboxContext, resolveSessionAgentIds, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
12
12
  //#region extensions/codex/src/app-server/side-question.ts
13
13
  const CODEX_SIDE_DYNAMIC_TOOL_TIMEOUT_MS = 9e4;