@openclaw/codex 2026.6.6-beta.2 → 2026.6.8-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.
@@ -1,7 +1,7 @@
1
1
  //#region extensions/codex/src/app-server/client-factory.ts
2
2
  let sharedClientModulePromise = null;
3
3
  const loadSharedClientModule = async () => {
4
- sharedClientModulePromise ??= import("./shared-client-CflavQ_i.js").then((n) => n.c);
4
+ sharedClientModulePromise ??= import("./shared-client-jFMumCOe.js").then((n) => n.c);
5
5
  return await sharedClientModulePromise;
6
6
  };
7
7
  /** Returns a leased shared client so startup can release ownership explicitly. */
@@ -1,14 +1,14 @@
1
1
  import { d as resolveCodexAppServerRuntimeOptions, o as isCodexFastServiceTier } from "./config-DJXpBkGf.js";
2
- import { n as listCodexAppServerModels, t as listAllCodexAppServerModels } from "./models-CQGfP7nG.js";
2
+ import { n as listCodexAppServerModels, t as listAllCodexAppServerModels } from "./models-DRKnOpzF.js";
3
3
  import { t as isJsonObject } from "./protocol-oeJQu4rs.js";
4
- import { l as summarizeCodexAccountUsage } from "./provider-Cs6kWhDQ.js";
4
+ import { l as summarizeCodexAccountUsage } from "./provider-C5P6352f.js";
5
5
  import { l as writeCodexAppServerBinding, n as clearCodexAppServerBinding, o as readCodexAppServerBinding } from "./session-binding-ElbcSq2o.js";
6
- import { n as CODEX_CONTROL_METHODS, r as describeControlFailure } from "./plugin-app-cache-key-NpzxEcSR.js";
7
- import { c as formatAccount, d as formatComputerUseStatus, f as formatList, g as readString$1, h as formatThreads, l as formatCodexDisplayText, m as formatSkills, p as formatModels, s as buildHelp, u as formatCodexStatus } from "./notification-correlation-D-MYfJwV.js";
6
+ import { n as CODEX_CONTROL_METHODS, r as describeControlFailure } from "./plugin-app-cache-key-kIqpGTQj.js";
7
+ import { c as formatAccount, d as formatComputerUseStatus, f as formatList, g as readString$1, h as formatThreads, l as formatCodexDisplayText, m as formatSkills, p as formatModels, s as buildHelp, u as formatCodexStatus } from "./notification-correlation-BGoG0N90.js";
8
8
  import { n as resolveCodexNativeExecutionBlock, r as resolveCodexNativeSandboxBlock } from "./sandbox-guard-C-Yv9uwY.js";
9
- import { _ as steerCodexConversationTurn, b as readCodexConversationBindingData, d as parseCodexFastModeArg, f as parseCodexPermissionsModeArg, g as setCodexConversationPermissions, h as setCodexConversationModel, m as setCodexConversationFastMode, o as formatCodexCliSessions, p as readCodexConversationActiveTurn, r as startCodexConversationThread, u as formatPermissionsMode, v as stopCodexConversationTurn, x as resolveCodexDefaultWorkspaceDir, y as createCodexCliNodeConversationBindingData } from "./conversation-binding-CMwrZrt7.js";
10
- import { t as requestCodexAppServerJson } from "./request-Dq0LUOqZ.js";
11
- import { n as installCodexComputerUse, r as readCodexComputerUseStatus } from "./computer-use-D3pi5csE.js";
9
+ import { _ as steerCodexConversationTurn, b as readCodexConversationBindingData, d as parseCodexFastModeArg, f as parseCodexPermissionsModeArg, g as setCodexConversationPermissions, h as setCodexConversationModel, m as setCodexConversationFastMode, o as formatCodexCliSessions, p as readCodexConversationActiveTurn, r as startCodexConversationThread, u as formatPermissionsMode, v as stopCodexConversationTurn, x as resolveCodexDefaultWorkspaceDir, y as createCodexCliNodeConversationBindingData } from "./conversation-binding-CbnMilVW.js";
10
+ import { t as requestCodexAppServerJson } from "./request-BxZ40QKY.js";
11
+ import { n as installCodexComputerUse, r as readCodexComputerUseStatus } from "./computer-use-D1qxvTE_.js";
12
12
  import { n as rememberCodexRateLimits } from "./rate-limit-cache-C7qmZ0Jh.js";
13
13
  import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
14
14
  import crypto from "node:crypto";
@@ -1,8 +1,8 @@
1
1
  import { d as resolveCodexAppServerRuntimeOptions } from "./config-DJXpBkGf.js";
2
2
  import { c as withCodexAppServerBindingLock, l as writeCodexAppServerBinding, o as readCodexAppServerBinding, t as CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS } from "./session-binding-ElbcSq2o.js";
3
- import { o as releaseLeasedSharedCodexAppServerClient } from "./shared-client-CflavQ_i.js";
3
+ import { o as releaseLeasedSharedCodexAppServerClient } from "./shared-client-jFMumCOe.js";
4
4
  import { n as resolveCodexNativeExecutionBlock } from "./sandbox-guard-C-Yv9uwY.js";
5
- import { t as defaultLeasedCodexAppServerClientFactory } from "./client-factory-XajDuvQ1.js";
5
+ import { t as defaultLeasedCodexAppServerClientFactory } from "./client-factory-C71Xdb6z.js";
6
6
  import { embeddedAgentLog } from "openclaw/plugin-sdk/agent-harness-runtime";
7
7
  //#region extensions/codex/src/app-server/compact.ts
8
8
  /**
@@ -1,6 +1,6 @@
1
1
  import { d as resolveCodexAppServerRuntimeOptions, f as resolveCodexComputerUseConfig } from "./config-DJXpBkGf.js";
2
- import { r as describeControlFailure } from "./plugin-app-cache-key-NpzxEcSR.js";
3
- import { t as requestCodexAppServerJson } from "./request-Dq0LUOqZ.js";
2
+ import { r as describeControlFailure } from "./plugin-app-cache-key-kIqpGTQj.js";
3
+ import { t as requestCodexAppServerJson } from "./request-BxZ40QKY.js";
4
4
  import { existsSync } from "node:fs";
5
5
  //#region extensions/codex/src/app-server/computer-use.ts
6
6
  /**
@@ -1,10 +1,10 @@
1
1
  import { d as resolveCodexAppServerRuntimeOptions, h as resolveOpenClawExecPolicyForCodexAppServer, i as codexSandboxPolicyForTurn, n as canUseCodexModelBackedApprovalsReviewerForModel, o as isCodexFastServiceTier, p as resolveCodexModelBackedReviewerPolicyContext } from "./config-DJXpBkGf.js";
2
2
  import { t as isJsonObject } from "./protocol-oeJQu4rs.js";
3
- import { d as resolveCodexAppServerRequestModelSelection, f as resolveCodexBindingModelProviderFallback, t as CODEX_NATIVE_PERSONALITY_NONE } from "./thread-lifecycle-Cq1-IfZB.js";
3
+ import { d as resolveCodexAppServerRequestModelSelection, f as resolveCodexBindingModelProviderFallback, t as CODEX_NATIVE_PERSONALITY_NONE } from "./thread-lifecycle-cban34w3.js";
4
4
  import { a as normalizeCodexAppServerBindingModelProvider, i as isCodexAppServerNativeAuthProfile, l as writeCodexAppServerBinding, n as clearCodexAppServerBinding, o as readCodexAppServerBinding } from "./session-binding-ElbcSq2o.js";
5
- import { n as CODEX_CONTROL_METHODS } from "./plugin-app-cache-key-NpzxEcSR.js";
6
- import { a as resolveCodexAppServerForModelProvider, i as readCodexNotificationTurnId, l as formatCodexDisplayText, r as readCodexNotificationThreadId } from "./notification-correlation-D-MYfJwV.js";
7
- import { a as getLeasedSharedCodexAppServerClient, o as releaseLeasedSharedCodexAppServerClient, p as resolveCodexAppServerAuthProfileIdForAgent } from "./shared-client-CflavQ_i.js";
5
+ import { n as CODEX_CONTROL_METHODS } from "./plugin-app-cache-key-kIqpGTQj.js";
6
+ import { a as resolveCodexAppServerForModelProvider, i as readCodexNotificationTurnId, l as formatCodexDisplayText, r as readCodexNotificationThreadId } from "./notification-correlation-BGoG0N90.js";
7
+ import { a as getLeasedSharedCodexAppServerClient, o as releaseLeasedSharedCodexAppServerClient, p as resolveCodexAppServerAuthProfileIdForAgent } from "./shared-client-jFMumCOe.js";
8
8
  import { n as resolveCodexNativeExecutionBlock, r as resolveCodexNativeSandboxBlock } from "./sandbox-guard-C-Yv9uwY.js";
9
9
  import { resolveTimerTimeoutMs, timestampMsToIsoString } from "openclaw/plugin-sdk/number-runtime";
10
10
  import os from "node:os";
package/dist/harness.js CHANGED
@@ -32,25 +32,25 @@ function createCodexAppServerAgentHarness(options) {
32
32
  };
33
33
  },
34
34
  runAttempt: async (params) => {
35
- const { runCodexAppServerAttempt } = await import("./run-attempt-DG9p9ReO.js");
35
+ const { runCodexAppServerAttempt } = await import("./run-attempt-D_q-VrpR.js");
36
36
  return runCodexAppServerAttempt(params, {
37
37
  pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig,
38
38
  nativeHookRelay: { enabled: true }
39
39
  });
40
40
  },
41
41
  runSideQuestion: async (params) => {
42
- const { runCodexAppServerSideQuestion } = await import("./side-question-Ctu2VXAG.js");
42
+ const { runCodexAppServerSideQuestion } = await import("./side-question-DqKLfWMB.js");
43
43
  return runCodexAppServerSideQuestion(params, {
44
44
  pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig,
45
45
  nativeHookRelay: { enabled: true }
46
46
  });
47
47
  },
48
48
  compact: async (params) => {
49
- const { maybeCompactCodexAppServerSession } = await import("./compact-BWiNkDSs.js");
49
+ const { maybeCompactCodexAppServerSession } = await import("./compact-GEKusemL.js");
50
50
  return maybeCompactCodexAppServerSession(params, { pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig });
51
51
  },
52
52
  compactAfterContextEngine: async (params) => {
53
- const { maybeCompactCodexAppServerSession } = await import("./compact-BWiNkDSs.js");
53
+ const { maybeCompactCodexAppServerSession } = await import("./compact-GEKusemL.js");
54
54
  return maybeCompactCodexAppServerSession(params, {
55
55
  pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig,
56
56
  allowNonManualNativeRequest: true
@@ -63,7 +63,7 @@ function createCodexAppServerAgentHarness(options) {
63
63
  }
64
64
  },
65
65
  dispose: async () => {
66
- const { clearSharedCodexAppServerClientAndWait } = await import("./shared-client-CflavQ_i.js").then((n) => n.c);
66
+ const { clearSharedCodexAppServerClientAndWait } = await import("./shared-client-jFMumCOe.js").then((n) => n.c);
67
67
  await clearSharedCodexAppServerClientAndWait();
68
68
  }
69
69
  };
package/dist/index.js CHANGED
@@ -1,13 +1,13 @@
1
1
  import { createCodexAppServerAgentHarness } from "./harness.js";
2
2
  import { d as resolveCodexAppServerRuntimeOptions, t as CODEX_PLUGINS_MARKETPLACE_NAME, u as readCodexPluginConfig } from "./config-DJXpBkGf.js";
3
- import { t as buildCodexProvider } from "./provider-Cs6kWhDQ.js";
4
- import { C as defaultCodexAppInventoryCache, b as ensureCodexPluginActivation, x as pluginReadParams } from "./thread-lifecycle-Cq1-IfZB.js";
3
+ import { t as buildCodexProvider } from "./provider-C5P6352f.js";
4
+ import { C as defaultCodexAppInventoryCache, b as ensureCodexPluginActivation, x as pluginReadParams } from "./thread-lifecycle-cban34w3.js";
5
5
  import { buildCodexMediaUnderstandingProvider } from "./media-understanding-provider.js";
6
- import { r as describeControlFailure, t as buildCodexPluginAppCacheKey } from "./plugin-app-cache-key-NpzxEcSR.js";
7
- import { l as formatCodexDisplayText } from "./notification-correlation-D-MYfJwV.js";
8
- import { a as getLeasedSharedCodexAppServerClient, d as resolveCodexAppServerAuthAccountCacheKey, m as resolveCodexAppServerFallbackApiKeyCacheKey, o as releaseLeasedSharedCodexAppServerClient, p as resolveCodexAppServerAuthProfileIdForAgent, r as clearSharedCodexAppServerClientIfCurrentAndWait } from "./shared-client-CflavQ_i.js";
9
- import { a as createCodexCliSessionNodeInvokePolicies, c as resolveCodexCliSessionForBindingOnNode, i as createCodexCliSessionNodeHostCommands, l as resumeCodexCliSessionOnNode, n as handleCodexConversationInboundClaim, s as listCodexCliSessionsOnNode, t as handleCodexConversationBindingResolved } from "./conversation-binding-CMwrZrt7.js";
10
- import { t as requestCodexAppServerJson } from "./request-Dq0LUOqZ.js";
6
+ import { r as describeControlFailure, t as buildCodexPluginAppCacheKey } from "./plugin-app-cache-key-kIqpGTQj.js";
7
+ import { l as formatCodexDisplayText } from "./notification-correlation-BGoG0N90.js";
8
+ import { a as getLeasedSharedCodexAppServerClient, d as resolveCodexAppServerAuthAccountCacheKey, m as resolveCodexAppServerFallbackApiKeyCacheKey, o as releaseLeasedSharedCodexAppServerClient, p as resolveCodexAppServerAuthProfileIdForAgent, r as clearSharedCodexAppServerClientIfCurrentAndWait } from "./shared-client-jFMumCOe.js";
9
+ import { a as createCodexCliSessionNodeInvokePolicies, c as resolveCodexCliSessionForBindingOnNode, i as createCodexCliSessionNodeHostCommands, l as resumeCodexCliSessionOnNode, n as handleCodexConversationInboundClaim, s as listCodexCliSessionsOnNode, t as handleCodexConversationBindingResolved } from "./conversation-binding-CbnMilVW.js";
10
+ import { t as requestCodexAppServerJson } from "./request-BxZ40QKY.js";
11
11
  import { mutateConfigFile } from "openclaw/plugin-sdk/config-mutation";
12
12
  import { resolveLivePluginConfigObject } from "openclaw/plugin-sdk/plugin-config-runtime";
13
13
  import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
@@ -17,10 +17,10 @@ import path from "node:path";
17
17
  import { loadAuthProfileStoreWithoutExternalProfiles, resolveAgentConfig, resolveAgentWorkspaceDir, resolveDefaultAgentId } from "openclaw/plugin-sdk/agent-runtime";
18
18
  import { asBoolean, isRecord, normalizeOptionalString, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
19
19
  import fs from "node:fs/promises";
20
+ import { applyAuthProfileConfig, buildApiKeyCredential, buildOauthProviderAuthResult, buildOpenAICodexCredentialExtra, readCodexCliCredentialsCached, resolveOpenAICodexAuthIdentity, resolveOpenAICodexImportProfileName, updateAuthProfileStoreWithLock } from "openclaw/plugin-sdk/provider-auth";
20
21
  import { pathExists } from "openclaw/plugin-sdk/security-runtime";
21
22
  import { MIGRATION_REASON_TARGET_EXISTS, applyMigrationManualItem, createMigrationItem, createMigrationManualItem, hasMigrationConfigPatchConflict, markMigrationItemConflict, markMigrationItemError, markMigrationItemSkipped, readMigrationConfigPath, summarizeMigrationItems, writeMigrationConfigPath } from "openclaw/plugin-sdk/migration";
22
23
  import { archiveMigrationItem, copyMigrationFileItem, withCachedMigrationConfigRuntime, writeMigrationReport } from "openclaw/plugin-sdk/migration-runtime";
23
- import { applyAuthProfileConfig, buildApiKeyCredential, buildOauthProviderAuthResult, buildOpenAICodexCredentialExtra, readCodexCliCredentialsCached, resolveOpenAICodexAuthIdentity, resolveOpenAICodexImportProfileName, updateAuthProfileStoreWithLock } from "openclaw/plugin-sdk/provider-auth";
24
24
  import { readJsonFileWithFallback } from "openclaw/plugin-sdk/json-store";
25
25
  //#region extensions/codex/src/commands.ts
26
26
  /** Creates the reserved `/codex` command definition exposed by the plugin. */
@@ -51,7 +51,7 @@ async function handleCodexCommand(ctx, options = {}) {
51
51
  }
52
52
  }
53
53
  async function loadDefaultCodexSubcommandHandler() {
54
- const { handleCodexSubcommand } = await import("./command-handlers-DIUFKqaF.js");
54
+ const { handleCodexSubcommand } = await import("./command-handlers-DHecBkuc.js");
55
55
  return handleCodexSubcommand;
56
56
  }
57
57
  //#endregion
@@ -1,9 +1,9 @@
1
1
  import { CODEX_PROVIDER_ID, FALLBACK_CODEX_MODELS } from "./provider-catalog.js";
2
2
  import { d as resolveCodexAppServerRuntimeOptions } from "./config-DJXpBkGf.js";
3
3
  import { i as assertCodexTurnStartResponse, l as readCodexTurnCompletedNotification, o as readCodexErrorNotification, r as assertCodexThreadStartResponse } from "./protocol-validators-B48C6S9O.js";
4
- import { i as readModelListResult } from "./models-CQGfP7nG.js";
4
+ import { i as readModelListResult } from "./models-DRKnOpzF.js";
5
5
  import { t as isJsonObject } from "./protocol-oeJQu4rs.js";
6
- import { r as buildCodexRuntimeThreadConfig } from "./thread-lifecycle-Cq1-IfZB.js";
6
+ import { r as buildCodexRuntimeThreadConfig } from "./thread-lifecycle-cban34w3.js";
7
7
  import { validateJsonSchemaValue } from "openclaw/plugin-sdk/json-schema-runtime";
8
8
  import { resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
9
9
  //#region extensions/codex/media-understanding-provider.ts
@@ -52,6 +52,8 @@ async function describeCodexImages(req, options) {
52
52
  profile: req.profile,
53
53
  timeoutMs: req.timeoutMs,
54
54
  agentDir: req.agentDir,
55
+ authStore: req.authStore,
56
+ cfg: req.cfg,
55
57
  options,
56
58
  taskLabel: "image understanding",
57
59
  developerInstructions: "You are OpenClaw's bounded image-understanding worker. Describe only the provided image content. Do not call tools, edit files, or ask follow-up questions.",
@@ -71,11 +73,16 @@ async function describeCodexImages(req, options) {
71
73
  async function runBoundedCodexVisionTurn(params) {
72
74
  const appServer = resolveCodexAppServerRuntimeOptions({ pluginConfig: params.options.pluginConfig });
73
75
  const timeoutMs = resolveTimerTimeoutMs(params.timeoutMs, 100, 100);
76
+ const agentDir = params.agentDir?.trim() || void 0;
77
+ const cwd = agentDir ?? process.cwd();
74
78
  const ownsClient = !params.options.clientFactory;
75
- const client = params.options.clientFactory ? await params.options.clientFactory(appServer.start, params.profile) : await import("./shared-client-CflavQ_i.js").then((n) => n.c).then(({ createIsolatedCodexAppServerClient }) => createIsolatedCodexAppServerClient({
79
+ const client = params.options.clientFactory ? await params.options.clientFactory(appServer.start, params.profile, agentDir, params.cfg) : await import("./shared-client-jFMumCOe.js").then((n) => n.c).then(({ createIsolatedCodexAppServerClient }) => createIsolatedCodexAppServerClient({
76
80
  startOptions: appServer.start,
77
81
  timeoutMs,
78
- authProfileId: params.profile
82
+ authProfileId: params.profile,
83
+ agentDir,
84
+ authProfileStore: params.authStore,
85
+ config: params.cfg
79
86
  }));
80
87
  const abortController = new AbortController();
81
88
  const timeout = setTimeout(() => abortController.abort("timeout"), timeoutMs);
@@ -91,7 +98,7 @@ async function runBoundedCodexVisionTurn(params) {
91
98
  const thread = assertCodexThreadStartResponse(await client.request("thread/start", {
92
99
  model: params.model,
93
100
  modelProvider: "openai",
94
- cwd: params.agentDir || process.cwd(),
101
+ cwd,
95
102
  approvalPolicy: "on-request",
96
103
  sandbox: "read-only",
97
104
  serviceName: "OpenClaw",
@@ -113,7 +120,7 @@ async function runBoundedCodexVisionTurn(params) {
113
120
  const turn = assertCodexTurnStartResponse(await client.request("turn/start", {
114
121
  threadId: thread.thread.id,
115
122
  input: params.input,
116
- cwd: params.agentDir || process.cwd(),
123
+ cwd,
117
124
  approvalPolicy: "on-request",
118
125
  model: params.model,
119
126
  effort: "low"
@@ -146,6 +153,8 @@ async function extractCodexStructured(req, options) {
146
153
  profile: req.profile,
147
154
  timeoutMs: req.timeoutMs,
148
155
  agentDir: req.agentDir,
156
+ authStore: req.authStore,
157
+ cfg: req.cfg,
149
158
  options,
150
159
  taskLabel: "structured extraction",
151
160
  developerInstructions: "You are OpenClaw's bounded structured-extraction worker. Return only the requested extraction. Do not call tools, edit files, ask follow-up questions, or include secrets.",
@@ -46,7 +46,7 @@ async function listAllCodexAppServerModels(options = {}) {
46
46
  async function withCodexAppServerModelClient(options, run) {
47
47
  const timeoutMs = options.timeoutMs ?? 2500;
48
48
  const useSharedClient = options.sharedClient !== false;
49
- const { createIsolatedCodexAppServerClient, getLeasedSharedCodexAppServerClient, releaseLeasedSharedCodexAppServerClient } = await import("./shared-client-CflavQ_i.js").then((n) => n.c);
49
+ const { createIsolatedCodexAppServerClient, getLeasedSharedCodexAppServerClient, releaseLeasedSharedCodexAppServerClient } = await import("./shared-client-jFMumCOe.js").then((n) => n.c);
50
50
  const client = useSharedClient ? await getLeasedSharedCodexAppServerClient({
51
51
  startOptions: options.startOptions,
52
52
  timeoutMs,
@@ -1,12 +1,12 @@
1
1
  import { c as isTrustedCodexModelBackedOpenAIProvider } from "./config-DJXpBkGf.js";
2
2
  import { t as isJsonObject } from "./protocol-oeJQu4rs.js";
3
- import { E as sanitizeInlineImageDataUrl, w as invalidInlineImageText } from "./thread-lifecycle-Cq1-IfZB.js";
4
- import { l as formatCodexDisplayText } from "./notification-correlation-D-MYfJwV.js";
3
+ import { E as sanitizeInlineImageDataUrl, w as invalidInlineImageText } from "./thread-lifecycle-cban34w3.js";
4
+ import { l as formatCodexDisplayText } from "./notification-correlation-BGoG0N90.js";
5
5
  import { addTimerTimeoutGraceMs, finiteSecondsToTimerSafeMilliseconds, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
6
6
  import { createHash } from "node:crypto";
7
7
  import { normalizeAgentId } from "openclaw/plugin-sdk/routing";
8
8
  import { asOptionalRecord, isRecord, normalizeTrimmedStringList } from "openclaw/plugin-sdk/string-coerce-runtime";
9
- import { HEARTBEAT_RESPONSE_TOOL_NAME, buildAgentHookContextChannelFields, callGatewayTool, createAgentToolResultMiddlewareRunner, createCodexAppServerToolResultExtensionRunner, embeddedAgentLog, extractToolResultMediaArtifact, filterToolResultMediaUrls, formatApprovalDisplayPath, hasNativeHookRelayInvocation, invokeNativeHookRelay, isMessagingTool, isMessagingToolSendAction, isToolWrappedWithBeforeToolCallHook, normalizeHeartbeatToolResponse, projectRuntimeToolInputSchema, registerNativeHookRelay, resolveNativeHookRelayDeferredToolApproval, runAgentHarnessAfterToolCallHook, runBeforeToolCallHook, setBeforeToolCallDiagnosticsEnabled, wrapToolWithBeforeToolCallHook } from "openclaw/plugin-sdk/agent-harness-runtime";
9
+ import { HEARTBEAT_RESPONSE_TOOL_NAME, buildAgentHookContextChannelFields, callGatewayTool, createAgentToolResultMiddlewareRunner, createCodexAppServerToolResultExtensionRunner, embeddedAgentLog, extractToolResultMediaArtifact, filterToolResultMediaUrls, formatApprovalDisplayPath, hasNativeHookRelayInvocation, invokeNativeHookRelay, isMessagingTool, isMessagingToolSendAction, isToolResultError, isToolWrappedWithBeforeToolCallHook, normalizeHeartbeatToolResponse, projectRuntimeToolInputSchema, registerNativeHookRelay, resolveNativeHookRelayDeferredToolApproval, runAgentHarnessAfterToolCallHook, runBeforeToolCallHook, sanitizeToolResult, setBeforeToolCallDiagnosticsEnabled, wrapToolWithBeforeToolCallHook } from "openclaw/plugin-sdk/agent-harness-runtime";
10
10
  import { emitTrustedDiagnosticEvent } from "openclaw/plugin-sdk/diagnostic-runtime";
11
11
  import { buildExecAutoReviewInputForShellCommand, reviewExecRequestWithConfiguredModel } from "openclaw/plugin-sdk/agent-harness-exec-review-runtime";
12
12
  /** Default idle timeout while waiting for app-server turn completion. */
@@ -1185,17 +1185,19 @@ function createCodexDynamicToolBridge(params) {
1185
1185
  handleToolCall: async (call, options) => {
1186
1186
  const toolEntry = toolMap.get(call.tool);
1187
1187
  if (!toolEntry) {
1188
+ const message = registeredToolNames.has(call.tool) ? `OpenClaw tool is not available for this turn: ${call.tool}` : `Unknown OpenClaw tool: ${call.tool}`;
1189
+ notifyAgentToolResult(options?.onAgentToolResult, call.tool, failedToolResult(message), true);
1188
1190
  if (registeredToolNames.has(call.tool)) return {
1189
1191
  contentItems: [{
1190
1192
  type: "inputText",
1191
- text: `OpenClaw tool is not available for this turn: ${call.tool}`
1193
+ text: message
1192
1194
  }],
1193
1195
  success: false
1194
1196
  };
1195
1197
  return {
1196
1198
  contentItems: [{
1197
1199
  type: "inputText",
1198
- text: `Unknown OpenClaw tool: ${call.tool}`
1200
+ text: message
1199
1201
  }],
1200
1202
  success: false
1201
1203
  };
@@ -1209,7 +1211,7 @@ function createCodexDynamicToolBridge(params) {
1209
1211
  const preparedArgs = tool.prepareArguments ? tool.prepareArguments(args) : args;
1210
1212
  didStartExecution = true;
1211
1213
  const rawResult = await tool.execute(call.callId, preparedArgs, signal);
1212
- const rawIsError = isToolResultError(rawResult);
1214
+ const rawIsError = isCodexToolResultError(rawResult);
1213
1215
  const middlewareResult = await middlewareRunner.applyToolResultMiddleware({
1214
1216
  threadId: call.threadId,
1215
1217
  turnId: call.turnId,
@@ -1227,7 +1229,8 @@ function createCodexDynamicToolBridge(params) {
1227
1229
  args,
1228
1230
  result: middlewareResult
1229
1231
  });
1230
- const resultIsError = rawIsError || isToolResultError(result);
1232
+ const resultIsError = rawIsError || isCodexToolResultError(result);
1233
+ notifyAgentToolResult(options?.onAgentToolResult, toolName, result, resultIsError);
1231
1234
  collectToolTelemetry({
1232
1235
  toolName,
1233
1236
  args,
@@ -1257,6 +1260,8 @@ function createCodexDynamicToolBridge(params) {
1257
1260
  withDynamicToolAsyncStarted(response, isAsyncStartedToolResult(rawResult) || isAsyncStartedToolResult(result));
1258
1261
  return withSideEffectEvidence(response, terminalType !== "blocked");
1259
1262
  } catch (error) {
1263
+ const errorMessage = error instanceof Error ? error.message : String(error);
1264
+ notifyAgentToolResult(options?.onAgentToolResult, toolName, failedToolResult(errorMessage), true);
1260
1265
  collectToolTelemetry({
1261
1266
  toolName,
1262
1267
  args,
@@ -1273,13 +1278,13 @@ function createCodexDynamicToolBridge(params) {
1273
1278
  sessionKey: toolResultHookContext.sessionKey,
1274
1279
  channelId: toolResultHookContext.channelId,
1275
1280
  startArgs: args,
1276
- error: error instanceof Error ? error.message : String(error),
1281
+ error: errorMessage,
1277
1282
  startedAt
1278
1283
  });
1279
1284
  return withSideEffectEvidence(withDiagnosticTerminalType({
1280
1285
  contentItems: [{
1281
1286
  type: "inputText",
1282
- text: error instanceof Error ? error.message : String(error)
1287
+ text: errorMessage
1283
1288
  }],
1284
1289
  success: false
1285
1290
  }, "error"), didStartExecution);
@@ -1287,6 +1292,29 @@ function createCodexDynamicToolBridge(params) {
1287
1292
  }
1288
1293
  };
1289
1294
  }
1295
+ function notifyAgentToolResult(observer, toolName, result, isError) {
1296
+ try {
1297
+ observer?.({
1298
+ toolName,
1299
+ result: sanitizeToolResult(result),
1300
+ isError
1301
+ });
1302
+ } catch (error) {
1303
+ embeddedAgentLog.warn(`onAgentToolResult handler failed: tool=${toolName} error=${String(error)}`);
1304
+ }
1305
+ }
1306
+ function failedToolResult(message) {
1307
+ return {
1308
+ content: [{
1309
+ type: "text",
1310
+ text: message
1311
+ }],
1312
+ details: {
1313
+ status: "failed",
1314
+ error: message
1315
+ }
1316
+ };
1317
+ }
1290
1318
  function wrapProjectedCodexDynamicTools(tools, hookContext) {
1291
1319
  const wrappedTools = [];
1292
1320
  const quarantinedTools = [];
@@ -1565,9 +1593,11 @@ function readPositiveInteger(value) {
1565
1593
  if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) return;
1566
1594
  return Math.floor(value);
1567
1595
  }
1568
- function isToolResultError(result) {
1596
+ function isCodexToolResultError(result) {
1597
+ if (isToolResultError(result)) return true;
1569
1598
  const details = result.details;
1570
1599
  if (!isRecord(details)) return false;
1600
+ if (details.ok === true || details.success === true) return false;
1571
1601
  if (details.timedOut === true) return true;
1572
1602
  if (typeof details.exitCode === "number" && details.exitCode !== 0) return true;
1573
1603
  if (typeof details.status !== "string") return false;
@@ -1,6 +1,6 @@
1
1
  import { n as canUseCodexModelBackedApprovalsReviewerForModel } from "./config-DJXpBkGf.js";
2
2
  import { t as isJsonObject } from "./protocol-oeJQu4rs.js";
3
- import { a as hasCodexRateLimitSnapshots, c as summarizeCodexAccountRateLimits, u as summarizeCodexRateLimits } from "./provider-Cs6kWhDQ.js";
3
+ import { a as hasCodexRateLimitSnapshots, c as summarizeCodexAccountRateLimits, u as summarizeCodexRateLimits } from "./provider-C5P6352f.js";
4
4
  //#region extensions/codex/src/command-formatters.ts
5
5
  /** Formats the combined `/codex status` probe result. */
6
6
  function formatCodexStatus(probes) {
@@ -1,6 +1,6 @@
1
1
  import { n as CodexAppServerRpcError } from "./client-DovmVtbr.js";
2
- import { S as buildCodexAppInventoryCacheKey } from "./thread-lifecycle-Cq1-IfZB.js";
3
- import { h as resolveCodexAppServerHomeDir } from "./shared-client-CflavQ_i.js";
2
+ import { S as buildCodexAppInventoryCacheKey } from "./thread-lifecycle-cban34w3.js";
3
+ import { h as resolveCodexAppServerHomeDir } from "./shared-client-jFMumCOe.js";
4
4
  import { createHash } from "node:crypto";
5
5
  //#region extensions/codex/src/app-server/capabilities.ts
6
6
  /**
@@ -541,11 +541,11 @@ async function listModelsBestEffort(params) {
541
541
  }
542
542
  }
543
543
  async function listCodexAppServerModelsLazy(options) {
544
- const { listCodexAppServerModels } = await import("./models-CQGfP7nG.js").then((n) => n.r);
544
+ const { listCodexAppServerModels } = await import("./models-DRKnOpzF.js").then((n) => n.r);
545
545
  return listCodexAppServerModels(options);
546
546
  }
547
547
  async function requestCodexAppServerRateLimitsLazy(options) {
548
- const { requestCodexAppServerJson } = await import("./request-Dq0LUOqZ.js").then((n) => n.n);
548
+ const { requestCodexAppServerJson } = await import("./request-BxZ40QKY.js").then((n) => n.n);
549
549
  return await requestCodexAppServerJson({
550
550
  method: "account/rateLimits/read",
551
551
  timeoutMs: options.timeoutMs,
package/dist/provider.js CHANGED
@@ -1,2 +1,2 @@
1
- import { n as buildCodexProviderCatalog, r as isModernCodexModel, t as buildCodexProvider } from "./provider-Cs6kWhDQ.js";
1
+ import { n as buildCodexProviderCatalog, r as isModernCodexModel, t as buildCodexProvider } from "./provider-C5P6352f.js";
2
2
  export { buildCodexProvider, buildCodexProviderCatalog, isModernCodexModel };
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
- import { a as getLeasedSharedCodexAppServerClient, i as createIsolatedCodexAppServerClient, l as withTimeout, o as releaseLeasedSharedCodexAppServerClient } from "./shared-client-CflavQ_i.js";
2
+ import { a as getLeasedSharedCodexAppServerClient, i as createIsolatedCodexAppServerClient, l as withTimeout, o as releaseLeasedSharedCodexAppServerClient } from "./shared-client-jFMumCOe.js";
3
3
  import { t as resolveCodexAppServerDirectSandboxBypassBlock } from "./sandbox-guard-C-Yv9uwY.js";
4
4
  //#region extensions/codex/src/app-server/request.ts
5
5
  var request_exports = /* @__PURE__ */ __exportAll({ requestCodexAppServerJson: () => requestCodexAppServerJson });
@@ -1,17 +1,17 @@
1
1
  import { _ as withMcpElicitationsApprovalPolicy, a as isCodexAppServerApprovalPolicyAllowedByRequirements, d as resolveCodexAppServerRuntimeOptions, f as resolveCodexComputerUseConfig, g as shouldAutoApproveCodexAppServerApprovals, h as resolveOpenClawExecPolicyForCodexAppServer, m as resolveCodexPluginsPolicy, p as resolveCodexModelBackedReviewerPolicyContext, s as isCodexSandboxExecServerEnabled, u as readCodexPluginConfig } from "./config-DJXpBkGf.js";
2
2
  import { a as readCodexDynamicToolCallParams, c as readCodexTurn, i as assertCodexTurnStartResponse } from "./protocol-validators-B48C6S9O.js";
3
3
  import { t as isJsonObject } from "./protocol-oeJQu4rs.js";
4
- import { i as formatCodexUsageLimitErrorMessage, o as resolveCodexUsageLimitResetAtMs, s as shouldRefreshCodexRateLimitsForUsageLimitMessage } from "./provider-Cs6kWhDQ.js";
4
+ import { i as formatCodexUsageLimitErrorMessage, o as resolveCodexUsageLimitResetAtMs, s as shouldRefreshCodexRateLimitsForUsageLimitMessage } from "./provider-C5P6352f.js";
5
5
  import { a as isCodexAppServerConnectionClosedError, i as isCodexAppServerApprovalRequest, n as CodexAppServerRpcError, r as compareCodexAppServerVersions, s as MIN_CODEX_SANDBOX_EXEC_SERVER_APP_SERVER_VERSION } from "./client-DovmVtbr.js";
6
- import { C as defaultCodexAppInventoryCache, D as filterCodexDynamicTools, M as projectContextEngineAssemblyForCodex, N as resolveCodexContextEngineProjectionMaxChars, O as isForcedPrivateQaCodexRuntime, P as resolveCodexContextEngineProjectionReserveTokens, T as sanitizeCodexHistoryImagePayloads, _ as buildCodexPluginThreadConfigInputFingerprint, a as buildDeveloperInstructions, c as codexDynamicToolsFingerprint, g as buildCodexPluginThreadConfig, h as isCodexAppServerProfilerEnabled, i as buildContextEngineBinding, j as resolveCodexDynamicToolsLoadingForModel, k as normalizeCodexDynamicToolName$1, l as isContextEngineBindingCompatible, m as startOrResumeThread, n as areCodexDynamicToolFingerprintsCompatible, o as buildTurnCollaborationMode, s as buildTurnStartParams, v as mergeCodexThreadConfigs, y as shouldBuildCodexPluginThreadConfig } from "./thread-lifecycle-Cq1-IfZB.js";
6
+ import { C as defaultCodexAppInventoryCache, D as filterCodexDynamicTools, M as projectContextEngineAssemblyForCodex, N as resolveCodexContextEngineProjectionMaxChars, O as isForcedPrivateQaCodexRuntime, P as resolveCodexContextEngineProjectionReserveTokens, T as sanitizeCodexHistoryImagePayloads, _ as buildCodexPluginThreadConfigInputFingerprint, a as buildDeveloperInstructions, c as codexDynamicToolsFingerprint, g as buildCodexPluginThreadConfig, h as isCodexAppServerProfilerEnabled, i as buildContextEngineBinding, j as resolveCodexDynamicToolsLoadingForModel, k as normalizeCodexDynamicToolName$1, l as isContextEngineBindingCompatible, m as startOrResumeThread, n as areCodexDynamicToolFingerprintsCompatible, o as buildTurnCollaborationMode, s as buildTurnStartParams, v as mergeCodexThreadConfigs, y as shouldBuildCodexPluginThreadConfig } from "./thread-lifecycle-cban34w3.js";
7
7
  import { i as isCodexAppServerNativeAuthProfile, l as writeCodexAppServerBinding, n as clearCodexAppServerBinding, o as readCodexAppServerBinding, r as clearCodexAppServerBindingForThread } from "./session-binding-ElbcSq2o.js";
8
- import { n as CODEX_CONTROL_METHODS, t as buildCodexPluginAppCacheKey } from "./plugin-app-cache-key-NpzxEcSR.js";
9
- import { a as resolveCodexAppServerForModelProvider, i as readCodexNotificationTurnId, l as formatCodexDisplayText, n as isCodexNotificationForTurn, o as resolveCodexAppServerForOpenClawToolPolicy, r as readCodexNotificationThreadId, t as describeCodexNotificationCorrelation } from "./notification-correlation-D-MYfJwV.js";
10
- import { d as resolveCodexAppServerAuthAccountCacheKey, f as resolveCodexAppServerAuthProfileId, h as resolveCodexAppServerHomeDir, m as resolveCodexAppServerFallbackApiKeyCacheKey, n as clearSharedCodexAppServerClientIfCurrentAndUnclaimed, o as releaseLeasedSharedCodexAppServerClient, p as resolveCodexAppServerAuthProfileIdForAgent, s as retireSharedCodexAppServerClientIfCurrent, t as clearSharedCodexAppServerClientIfCurrent, u as refreshCodexAppServerAuthTokens } from "./shared-client-CflavQ_i.js";
8
+ import { n as CODEX_CONTROL_METHODS, t as buildCodexPluginAppCacheKey } from "./plugin-app-cache-key-kIqpGTQj.js";
9
+ import { a as resolveCodexAppServerForModelProvider, i as readCodexNotificationTurnId, l as formatCodexDisplayText, n as isCodexNotificationForTurn, o as resolveCodexAppServerForOpenClawToolPolicy, r as readCodexNotificationThreadId, t as describeCodexNotificationCorrelation } from "./notification-correlation-BGoG0N90.js";
10
+ import { d as resolveCodexAppServerAuthAccountCacheKey, f as resolveCodexAppServerAuthProfileId, h as resolveCodexAppServerHomeDir, m as resolveCodexAppServerFallbackApiKeyCacheKey, n as clearSharedCodexAppServerClientIfCurrentAndUnclaimed, o as releaseLeasedSharedCodexAppServerClient, p as resolveCodexAppServerAuthProfileIdForAgent, s as retireSharedCodexAppServerClientIfCurrent, t as clearSharedCodexAppServerClientIfCurrent, u as refreshCodexAppServerAuthTokens } from "./shared-client-jFMumCOe.js";
11
11
  import { i as resolveCodexNativeExecutionPolicy } from "./sandbox-guard-C-Yv9uwY.js";
12
- import { t as defaultLeasedCodexAppServerClientFactory } from "./client-factory-XajDuvQ1.js";
13
- import { S as withCodexStartupTimeout, _ as resolveCodexPostToolRawAssistantCompletionIdleTimeoutMs, a as createCodexNativeHookRelay, b as resolveCodexTurnCompletionIdleTimeoutMs, c as scheduleCodexNativeHookRelayUnregister, d as emitDynamicToolErrorDiagnostic, f as emitDynamicToolStartedDiagnostic, g as CODEX_POST_REASONING_REPLY_IDLE_TIMEOUT_MS, h as handleCodexAppServerApprovalRequest, i as buildCodexNativeHookRelayDisabledConfig, l as handleCodexAppServerElicitationRequest, m as filterToolsForVisionInputs, n as CODEX_NATIVE_HOOK_RELAY_TTL_GRACE_MS, o as resolveCodexNativeHookRelayEvents, p as emitDynamicToolTerminalDiagnostic, r as buildCodexNativeHookRelayConfig, s as resolveCodexNativeHookRelayTtlMs, u as createCodexDynamicToolBridge, v as resolveCodexStartupTimeoutMs, x as resolveCodexTurnTerminalIdleTimeoutMs, y as resolveCodexTurnAssistantCompletionIdleTimeoutMs } from "./native-hook-relay-CmUUO3Eu.js";
14
- import { t as ensureCodexComputerUse } from "./computer-use-D3pi5csE.js";
12
+ import { t as defaultLeasedCodexAppServerClientFactory } from "./client-factory-C71Xdb6z.js";
13
+ import { S as withCodexStartupTimeout, _ as resolveCodexPostToolRawAssistantCompletionIdleTimeoutMs, a as createCodexNativeHookRelay, b as resolveCodexTurnCompletionIdleTimeoutMs, c as scheduleCodexNativeHookRelayUnregister, d as emitDynamicToolErrorDiagnostic, f as emitDynamicToolStartedDiagnostic, g as CODEX_POST_REASONING_REPLY_IDLE_TIMEOUT_MS, h as handleCodexAppServerApprovalRequest, i as buildCodexNativeHookRelayDisabledConfig, l as handleCodexAppServerElicitationRequest, m as filterToolsForVisionInputs, n as CODEX_NATIVE_HOOK_RELAY_TTL_GRACE_MS, o as resolveCodexNativeHookRelayEvents, p as emitDynamicToolTerminalDiagnostic, r as buildCodexNativeHookRelayConfig, s as resolveCodexNativeHookRelayTtlMs, u as createCodexDynamicToolBridge, v as resolveCodexStartupTimeoutMs, x as resolveCodexTurnTerminalIdleTimeoutMs, y as resolveCodexTurnAssistantCompletionIdleTimeoutMs } from "./native-hook-relay-C3i3FYtc.js";
14
+ import { t as ensureCodexComputerUse } from "./computer-use-D1qxvTE_.js";
15
15
  import { n as rememberCodexRateLimits, t as readRecentCodexRateLimits } from "./rate-limit-cache-C7qmZ0Jh.js";
16
16
  import { asDateTimestampMs, parseStrictNonNegativeInteger, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
17
17
  import { createHash, randomUUID } from "node:crypto";
@@ -21,6 +21,7 @@ import { markAuthProfileBlockedUntil, resolveAgentDir, resolveAgentWorkspaceDir
21
21
  import { loadExecApprovals } from "openclaw/plugin-sdk/exec-approvals-runtime";
22
22
  import { asBoolean, asFiniteNumber, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
23
23
  import { CODEX_APP_SERVER_CONTEXT_ENGINE_HOST, TOOL_PROGRESS_OUTPUT_MAX_CHARS, acquireSessionWriteLock, appendSessionTranscriptMessage, assembleHarnessContextEngine, assertContextEngineHostSupport, awaitAgentHarnessAgentEndHook, bootstrapHarnessContextEngine, buildAgentHookContextChannelFields, buildBootstrapContextForFiles, buildEmbeddedAttemptToolRunContext, buildHarnessContextEngineRuntimeContext, buildHarnessContextEngineRuntimeContextFromUsage, classifyAgentHarnessTerminalOutcome, clearActiveEmbeddedRun, embeddedAgentLog, emitAgentEvent, emitSessionTranscriptUpdate, filterProviderNormalizableTools, finalizeHarnessContextEngineTurn, formatErrorMessage, formatToolAggregate, formatToolProgressOutput, getAgentHarnessHookRunner, getBeforeToolCallPolicyDiagnosticState, inferToolMetaFromArgs, isActiveHarnessContextEngine, isSubagentSessionKey, loadCodexBundleMcpThreadConfig, normalizeAgentRuntimeTools, normalizeUsage, resolveAgentHarnessBeforePromptBuildResult, resolveAttemptSpawnWorkspaceDir, resolveBootstrapFilesForRun, resolveContextEngineOwnerPluginId, resolveModelAuthMode, resolveSandboxContext, resolveSessionAgentIds as resolveSessionAgentIds$1, resolveSessionWriteLockOptions, resolveUserPath, runAgentCleanupStep, runAgentHarnessAfterCompactionHook, runAgentHarnessAfterToolCallHook, runAgentHarnessAgentEndHook, runAgentHarnessBeforeCompactionHook, runAgentHarnessBeforeMessageWriteHook, runAgentHarnessLlmInputHook, runAgentHarnessLlmOutputHook, runHarnessContextEngineMaintenance, setActiveEmbeddedRun, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
24
+ import { buildMemorySystemPromptAddition } from "openclaw/plugin-sdk/core";
24
25
  import { spawn } from "node:child_process";
25
26
  import { once } from "node:events";
26
27
  import { WebSocketServer } from "ws";
@@ -29,6 +30,7 @@ import fs from "node:fs/promises";
29
30
  import { createDiagnosticTraceContextFromActiveScope, emitTrustedDiagnosticEvent, emitTrustedDiagnosticEventWithPrivateData, freezeDiagnosticTraceContext, hasPendingInternalDiagnosticEvent, onInternalDiagnosticEvent, resolveDiagnosticModelContentCapturePolicy } from "openclaw/plugin-sdk/diagnostic-runtime";
30
31
  import { isToolAllowed } from "openclaw/plugin-sdk/sandbox";
31
32
  import { appendRegularFile, pathExists } from "openclaw/plugin-sdk/security-runtime";
33
+ import { MESSAGE_TOOL_DELIVERY_HINTS } from "openclaw/plugin-sdk/message-tool-delivery-hints";
32
34
  import { buildSessionContext, migrateSessionEntries, parseSessionEntries } from "openclaw/plugin-sdk/agent-sessions";
33
35
  import { isIP } from "node:net";
34
36
  import { SsrFBlockedError, isBlockedHostnameOrIp } from "openclaw/plugin-sdk/ssrf-runtime";
@@ -270,9 +272,11 @@ async function buildCodexWorkspaceBootstrapContext(params) {
270
272
  promptContext: renderCodexWorkspaceBootstrapPromptContext(promptContextFiles),
271
273
  developerInstructions: renderCodexWorkspaceThreadDeveloperInstructions(developerInstructionFiles),
272
274
  turnScopedDeveloperInstructions: renderCodexWorkspaceCollaborationDeveloperInstructions(turnScopedDeveloperInstructionFiles),
273
- memoryCollaborationInstructions: shouldInjectCodexOpenClawPromptContext(params.params) ? renderCodexWorkspaceMemoryReference({
275
+ memoryCollaborationInstructions: shouldInjectCodexOpenClawPromptContext(params.params) ? renderCodexWorkspaceMemoryCollaborationInstructions({
274
276
  files: memoryReferenceFiles,
275
- toolNames: params.memoryToolNames
277
+ toolNames: params.memoryToolNames,
278
+ memoryToolRouted: memoryToolsAvailable,
279
+ citationsMode: params.params.config?.memory?.citations
276
280
  }) : void 0,
277
281
  heartbeatCollaborationInstructions: renderCodexWorkspaceHeartbeatReference(heartbeatReferenceFiles)
278
282
  };
@@ -495,10 +499,9 @@ function prependCodexOpenClawPromptContext(prompt, context, options = {}) {
495
499
  promptSection
496
500
  ].filter(Boolean).join("\n\n");
497
501
  }
498
- const CODEX_DELIVERY_HINT_LINES = ["Delivery: to send a message, use the `message` tool.", "Delivery: Final assistant text is not automatically delivered in this run. Use the `message` tool to send user-visible output."];
499
502
  function splitLeadingCodexDeliveryHint(prompt) {
500
503
  const trimmedStart = prompt.trimStart();
501
- const matchedHint = CODEX_DELIVERY_HINT_LINES.find((hint) => trimmedStart.startsWith(hint));
504
+ const matchedHint = MESSAGE_TOOL_DELIVERY_HINTS.find((hint) => trimmedStart.startsWith(hint));
502
505
  if (!matchedHint) return { prompt };
503
506
  return {
504
507
  deliveryHint: matchedHint,
@@ -609,6 +612,29 @@ function renderCodexWorkspaceMemoryReference(params) {
609
612
  for (const file of params.files) lines.push(`- ${file.path}`);
610
613
  return lines.join("\n").trim();
611
614
  }
615
+ function renderCodexWorkspaceMemoryCollaborationInstructions(params) {
616
+ const sections = [params.memoryToolRouted ? renderCodexMemoryRecallInstructions({
617
+ toolNames: params.toolNames,
618
+ citationsMode: params.citationsMode
619
+ }) : void 0, renderCodexWorkspaceMemoryReference({
620
+ files: params.files,
621
+ toolNames: params.toolNames
622
+ })].filter(isNonEmptyString$2);
623
+ return sections.length > 0 ? sections.join("\n\n") : void 0;
624
+ }
625
+ function renderCodexMemoryRecallInstructions(params) {
626
+ const memoryPrompt = buildMemorySystemPromptAddition({
627
+ availableTools: new Set(params.toolNames),
628
+ citationsMode: params.citationsMode
629
+ });
630
+ if (!memoryPrompt) return;
631
+ return [memoryPrompt, renderCodexMemoryToolSearchBridge(params.toolNames)].filter(isNonEmptyString$2).join("\n").trim();
632
+ }
633
+ function renderCodexMemoryToolSearchBridge(toolNames) {
634
+ const memoryToolNames = toolNames.map((name) => normalizeCodexDynamicToolName(name)).filter((name) => CODEX_MEMORY_TOOL_NAMES.has(name)).toSorted();
635
+ if (memoryToolNames.length === 0) return;
636
+ return `Codex may expose ${memoryToolNames.join(" and ")} as deferred tools. When the memory guidance above calls for memory recall, use an already-loaded memory tool directly. If the needed memory tool is deferred and not currently callable, use \`tool_search\` to load it, then call that memory tool.`;
637
+ }
612
638
  /** Lists available memory tool names understood by Codex workspace memory routing. */
613
639
  function getCodexWorkspaceMemoryToolNames(tools) {
614
640
  const availableToolNames = new Set(tools.map((tool) => normalizeCodexDynamicToolName(tool.name)));
@@ -2788,6 +2814,7 @@ function readStringList(value) {
2788
2814
  * execution can register as an external environment.
2789
2815
  */
2790
2816
  const SANDBOX_EXEC_SERVERS = /* @__PURE__ */ new Map();
2817
+ const CODEX_SANDBOX_EXEC_SERVER_MAX_INBOUND_MESSAGE_BYTES = 100 * 1024 * 1024;
2791
2818
  /** Starts or reuses a sandbox exec-server and registers it with Codex app-server. */
2792
2819
  async function ensureCodexSandboxExecServerEnvironment(params) {
2793
2820
  if (!params.sandbox?.enabled || !params.sandbox.backend) return;
@@ -2864,7 +2891,8 @@ function startAndRememberOpenClawExecServer(sandbox) {
2864
2891
  async function startOpenClawExecServer(sandbox) {
2865
2892
  const server = new WebSocketServer({
2866
2893
  host: "127.0.0.1",
2867
- port: 0
2894
+ port: 0,
2895
+ maxPayload: CODEX_SANDBOX_EXEC_SERVER_MAX_INBOUND_MESSAGE_BYTES
2868
2896
  });
2869
2897
  await once(server, "listening");
2870
2898
  const address = server.address();
@@ -2881,6 +2909,7 @@ async function startOpenClawExecServer(sandbox) {
2881
2909
  server
2882
2910
  };
2883
2911
  server.on("connection", (socket, request) => {
2912
+ socket.on("error", handleExecServerSocketError);
2884
2913
  if (!isAuthorizedExecServerRequest(execServer, request)) {
2885
2914
  socket.close(1008, "unauthorized");
2886
2915
  return;
@@ -2928,6 +2957,9 @@ function handleConnection(execServer, socket) {
2928
2957
  for (const process of processes.values()) process.abortController.abort();
2929
2958
  });
2930
2959
  }
2960
+ function handleExecServerSocketError(error) {
2961
+ embeddedAgentLog.debug("codex sandbox exec-server websocket failed", { error });
2962
+ }
2931
2963
  async function handleMessage(execServer, processes, socket, data) {
2932
2964
  const request = parseRequest(data);
2933
2965
  if (!request.method) {
@@ -3797,7 +3829,37 @@ function formatDynamicToolTimeoutDetails(params) {
3797
3829
  * returning a Codex protocol response instead of throwing.
3798
3830
  */
3799
3831
  async function handleDynamicToolCallWithTimeout(params) {
3800
- if (params.signal.aborted) return failedDynamicToolResponse("OpenClaw dynamic tool call aborted before execution.");
3832
+ let didNotifyAgentToolResult = false;
3833
+ const notifyAgentToolResult = (event) => {
3834
+ if (didNotifyAgentToolResult) return;
3835
+ didNotifyAgentToolResult = true;
3836
+ try {
3837
+ params.onAgentToolResult?.(event);
3838
+ } catch (error) {
3839
+ embeddedAgentLog.warn(`onAgentToolResult handler failed: tool=${params.call.tool} error=${String(error)}`);
3840
+ }
3841
+ };
3842
+ const notifyFailedToolResult = (message) => {
3843
+ notifyAgentToolResult({
3844
+ toolName: params.call.tool,
3845
+ result: {
3846
+ content: [{
3847
+ type: "text",
3848
+ text: message
3849
+ }],
3850
+ details: {
3851
+ status: "failed",
3852
+ error: message
3853
+ }
3854
+ },
3855
+ isError: true
3856
+ });
3857
+ };
3858
+ if (params.signal.aborted) {
3859
+ const message = "OpenClaw dynamic tool call aborted before execution.";
3860
+ notifyFailedToolResult(message);
3861
+ return failedDynamicToolResponse(message);
3862
+ }
3801
3863
  const controller = new AbortController();
3802
3864
  let timeout;
3803
3865
  let timedOut = false;
@@ -3805,6 +3867,7 @@ async function handleDynamicToolCallWithTimeout(params) {
3805
3867
  const abortFromRun = () => {
3806
3868
  const message = "OpenClaw dynamic tool call aborted.";
3807
3869
  controller.abort(params.signal.reason ?? /* @__PURE__ */ new Error(message));
3870
+ notifyFailedToolResult(message);
3808
3871
  resolveAbort?.(failedDynamicToolResponse(message, { sideEffectEvidence: true }));
3809
3872
  };
3810
3873
  const abortPromise = new Promise((resolve) => {
@@ -3824,6 +3887,7 @@ async function handleDynamicToolCallWithTimeout(params) {
3824
3887
  ...timeoutDetails.meta,
3825
3888
  consoleMessage: timeoutDetails.consoleMessage
3826
3889
  });
3890
+ notifyFailedToolResult(timeoutDetails.responseMessage);
3827
3891
  resolve(failedDynamicToolResponse(timeoutDetails.responseMessage, { sideEffectEvidence: true }));
3828
3892
  }, timeoutMs);
3829
3893
  timeout.unref?.();
@@ -3831,13 +3895,20 @@ async function handleDynamicToolCallWithTimeout(params) {
3831
3895
  try {
3832
3896
  params.signal.addEventListener("abort", abortFromRun, { once: true });
3833
3897
  if (params.signal.aborted) abortFromRun();
3834
- return await Promise.race([
3835
- params.toolBridge.handleToolCall(params.call, { signal: controller.signal }),
3898
+ const response = await Promise.race([
3899
+ params.toolBridge.handleToolCall(params.call, {
3900
+ signal: controller.signal,
3901
+ onAgentToolResult: notifyAgentToolResult
3902
+ }),
3836
3903
  abortPromise,
3837
3904
  timeoutPromise
3838
3905
  ]);
3906
+ if (!response.success && !didNotifyAgentToolResult) notifyFailedToolResult(readDynamicToolResponseText(response));
3907
+ return response;
3839
3908
  } catch (error) {
3840
- return failedDynamicToolResponse(error instanceof Error ? error.message : String(error), { sideEffectEvidence: true });
3909
+ const message = error instanceof Error ? error.message : String(error);
3910
+ notifyFailedToolResult(message);
3911
+ return failedDynamicToolResponse(message, { sideEffectEvidence: true });
3841
3912
  } finally {
3842
3913
  if (timeout) clearTimeout(timeout);
3843
3914
  params.signal.removeEventListener("abort", abortFromRun);
@@ -3845,6 +3916,9 @@ async function handleDynamicToolCallWithTimeout(params) {
3845
3916
  if (!timedOut && !controller.signal.aborted) controller.abort(/* @__PURE__ */ new Error("OpenClaw dynamic tool call finished."));
3846
3917
  }
3847
3918
  }
3919
+ function readDynamicToolResponseText(response) {
3920
+ return response.contentItems.flatMap((item) => item.type === "inputText" && typeof item.text === "string" ? [item.text] : []).join("\n").trim() || "OpenClaw dynamic tool call failed.";
3921
+ }
3848
3922
  function failedDynamicToolResponse(message, options) {
3849
3923
  const response = {
3850
3924
  contentItems: [{
@@ -9130,6 +9204,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
9130
9204
  toolBridge,
9131
9205
  signal: runAbortController.signal,
9132
9206
  timeoutMs: dynamicToolTimeoutMs,
9207
+ onAgentToolResult: params.onAgentToolResult,
9133
9208
  onTimeout: () => {
9134
9209
  trajectoryRecorder?.recordEvent("tool.timeout", {
9135
9210
  threadId: call.threadId,
@@ -6,8 +6,10 @@ import { createHash } from "node:crypto";
6
6
  import fsSync, { constants, readFileSync } from "node:fs";
7
7
  import os from "node:os";
8
8
  import path from "node:path";
9
- import { ensureAuthProfileStore, ensureAuthProfileStoreWithoutExternalProfiles, loadAuthProfileStoreForSecretsRuntime, refreshOAuthCredentialForRuntime, resolveApiKeyForProfile, resolveAuthProfileOrder, resolveDefaultAgentDir, resolvePersistedAuthProfileOwnerAgentDir, resolveProviderIdForAuth } from "openclaw/plugin-sdk/agent-runtime";
9
+ import { ensureAuthProfileStore, findPersistedAuthProfileCredential, loadAuthProfileStoreForSecretsRuntime, refreshOAuthCredentialForRuntime, resolveApiKeyForProfile, resolveAuthProfileOrder, resolveDefaultAgentDir, resolvePersistedAuthProfileOwnerAgentDir, resolveProviderIdForAuth } from "openclaw/plugin-sdk/agent-runtime";
10
10
  import fs, { access } from "node:fs/promises";
11
+ import { isDeepStrictEqual } from "node:util";
12
+ import { hasUsableOAuthCredential } from "openclaw/plugin-sdk/provider-auth";
11
13
  import { fileURLToPath } from "node:url";
12
14
  import { withTimeout } from "openclaw/plugin-sdk/security-runtime";
13
15
  //#region extensions/codex/src/app-server/auth-bridge.ts
@@ -24,13 +26,15 @@ const CODEX_APP_SERVER_API_KEY_ENV_VARS = ["CODEX_API_KEY", "OPENAI_API_KEY"];
24
26
  const CODEX_APP_SERVER_HOME_ENV_VARS = [CODEX_HOME_ENV_VAR, HOME_ENV_VAR];
25
27
  const CODEX_AUTH_JSON_FILENAME = "auth.json";
26
28
  const CODEX_HOME_DIRNAME = ".codex";
29
+ const scopedOAuthRefreshQueues = /* @__PURE__ */ new WeakMap();
27
30
  async function bridgeCodexAppServerStartOptions(params) {
28
31
  if (params.startOptions.transport !== "stdio") return params.startOptions;
29
32
  const isolatedStartOptions = await withAgentCodexHomeEnvironment(params.startOptions, params.agentDir);
30
33
  if (params.authProfileId === null) return isolatedStartOptions;
31
- const store = ensureCodexAppServerAuthProfileStore({
34
+ const store = resolveCodexAppServerAuthProfileStore({
32
35
  agentDir: params.agentDir,
33
36
  authProfileId: params.authProfileId,
37
+ authProfileStore: params.authProfileStore,
34
38
  config: params.config
35
39
  });
36
40
  return shouldClearOpenAiApiKeyForCodexAuthProfile({
@@ -53,9 +57,10 @@ function resolveCodexAppServerAuthProfileId(params) {
53
57
  })[0]?.trim();
54
58
  }
55
59
  function resolveCodexAppServerAuthProfileIdForAgent(params) {
56
- const store = ensureCodexAppServerAuthProfileStore({
60
+ const store = resolveCodexAppServerAuthProfileStore({
57
61
  agentDir: params.agentDir?.trim() || resolveDefaultAgentDir(params.config ?? {}),
58
62
  authProfileId: params.authProfileId,
63
+ authProfileStore: params.authProfileStore,
59
64
  config: params.config
60
65
  });
61
66
  return resolveCodexAppServerAuthProfileId({
@@ -91,13 +96,24 @@ function resolveCodexAppServerAuthProfileStore(params) {
91
96
  ...overlaidStore.order,
92
97
  ...params.authProfileStore.order
93
98
  } : void 0;
99
+ const profiles = {
100
+ ...overlaidStore.profiles,
101
+ ...params.authProfileStore.profiles
102
+ };
103
+ const suppliedProfileIds = new Set(Object.keys(params.authProfileStore.profiles));
104
+ const mergeRuntimeProfileIds = (overlaidIds, suppliedIds) => [...(overlaidIds ?? []).filter((profileId) => !suppliedProfileIds.has(profileId)), ...suppliedIds ?? []];
105
+ const runtimePersistedProfileIds = mergeRuntimeProfileIds(overlaidStore.runtimePersistedProfileIds, params.authProfileStore.runtimePersistedProfileIds).filter((profileId) => profiles[profileId]);
106
+ const runtimeExternalProfileIds = mergeRuntimeProfileIds(overlaidStore.runtimeExternalProfileIds, params.authProfileStore.runtimeExternalProfileIds).filter((profileId) => profiles[profileId]);
107
+ const runtimeExternalProfileIdsAuthoritative = overlaidStore.runtimeExternalProfileIdsAuthoritative === true || params.authProfileStore.runtimeExternalProfileIdsAuthoritative === true;
94
108
  return {
95
109
  ...params.authProfileStore,
96
110
  ...order ? { order } : {},
97
- profiles: {
98
- ...overlaidStore.profiles,
99
- ...params.authProfileStore.profiles
100
- }
111
+ profiles,
112
+ ...runtimePersistedProfileIds.length > 0 ? { runtimePersistedProfileIds: [...new Set(runtimePersistedProfileIds)] } : {},
113
+ ...runtimeExternalProfileIds.length > 0 || runtimeExternalProfileIdsAuthoritative ? {
114
+ runtimeExternalProfileIds: [...new Set(runtimeExternalProfileIds)],
115
+ ...runtimeExternalProfileIdsAuthoritative ? { runtimeExternalProfileIdsAuthoritative: true } : {}
116
+ } : {}
101
117
  };
102
118
  }
103
119
  async function resolveCodexAppServerAuthAccountCacheKey(params) {
@@ -203,6 +219,7 @@ async function applyCodexAppServerAuthProfile(params) {
203
219
  const loginParams = await resolveCodexAppServerAuthProfileLoginParams({
204
220
  agentDir: params.agentDir,
205
221
  authProfileId: params.authProfileId,
222
+ authProfileStore: params.authProfileStore,
206
223
  config: params.config
207
224
  });
208
225
  if (!loginParams) {
@@ -234,9 +251,10 @@ async function refreshCodexAppServerAuthTokens(params) {
234
251
  };
235
252
  }
236
253
  async function resolveCodexAppServerAuthProfileLoginParamsInternal(params) {
237
- const store = ensureCodexAppServerAuthProfileStore({
254
+ const store = resolveCodexAppServerAuthProfileStore({
238
255
  agentDir: params.agentDir,
239
256
  authProfileId: params.authProfileId,
257
+ authProfileStore: params.authProfileStore,
240
258
  config: params.config
241
259
  });
242
260
  const profileId = resolveCodexAppServerAuthProfileId({
@@ -250,6 +268,8 @@ async function resolveCodexAppServerAuthProfileLoginParamsInternal(params) {
250
268
  if (!isCodexAppServerAuthProfileCredential(credential, params.config)) throw new Error(`Codex app-server auth profile "${profileId}" must be OpenAI Codex auth or an OpenAI API-key backup.`);
251
269
  const loginParams = await resolveLoginParamsForCredential(profileId, credential, {
252
270
  agentDir: params.agentDir,
271
+ store,
272
+ preferStoreCredential: Boolean(params.authProfileStore?.profiles[profileId]),
253
273
  forceOAuthRefresh: params.forceOAuthRefresh === true,
254
274
  config: params.config
255
275
  });
@@ -307,7 +327,7 @@ function resolveCodexCliAuthFileApiKeyCacheKey(env) {
307
327
  async function resolveLoginParamsForCredential(profileId, credential, params) {
308
328
  if (credential.type === "api_key") {
309
329
  const apiKey = (await resolveApiKeyForProfile({
310
- store: ensureAuthProfileStore(params.agentDir, { allowKeychainPrompt: false }),
330
+ store: params.preferStoreCredential ? params.store : ensureAuthProfileStore(params.agentDir, { allowKeychainPrompt: false }),
311
331
  profileId,
312
332
  agentDir: params.agentDir
313
333
  }))?.apiKey?.trim();
@@ -318,7 +338,7 @@ async function resolveLoginParamsForCredential(profileId, credential, params) {
318
338
  }
319
339
  if (credential.type === "token") {
320
340
  const accessToken = (await resolveApiKeyForProfile({
321
- store: ensureAuthProfileStore(params.agentDir, { allowKeychainPrompt: false }),
341
+ store: params.preferStoreCredential ? params.store : ensureAuthProfileStore(params.agentDir, { allowKeychainPrompt: false }),
322
342
  profileId,
323
343
  agentDir: params.agentDir
324
344
  }))?.apiKey?.trim();
@@ -327,6 +347,8 @@ async function resolveLoginParamsForCredential(profileId, credential, params) {
327
347
  if (credential.type !== "oauth") return;
328
348
  const resolvedCredential = await resolveOAuthCredentialForCodexAppServer(profileId, credential, {
329
349
  agentDir: params.agentDir,
350
+ store: params.store,
351
+ preferStoreCredential: params.preferStoreCredential,
330
352
  forceRefresh: params.forceOAuthRefresh,
331
353
  config: params.config
332
354
  });
@@ -338,15 +360,31 @@ async function resolveOAuthCredentialForCodexAppServer(profileId, credential, pa
338
360
  agentDir: params.agentDir,
339
361
  profileId
340
362
  });
341
- const store = ensureCodexAppServerAuthProfileStore({
363
+ const persistedCredential = findPersistedAuthProfileCredential({
364
+ agentDir: ownerAgentDir,
365
+ profileId
366
+ });
367
+ const useScopedCredential = params.preferStoreCredential && shouldUseScopedOAuthCredential({
368
+ store: params.store,
369
+ profileId,
370
+ persistedCredential,
371
+ suppliedCredential: credential,
372
+ config: params.config
373
+ });
374
+ const store = useScopedCredential ? params.store : ensureCodexAppServerAuthProfileStore({
342
375
  agentDir: ownerAgentDir,
343
376
  authProfileId: profileId,
344
377
  config: params.config
345
378
  });
346
- const persistedCredential = ensureAuthProfileStoreWithoutExternalProfiles(ownerAgentDir, { allowKeychainPrompt: false }).profiles[profileId];
347
- const persistedOAuthCredential = persistedCredential?.type === "oauth" && isCodexAppServerAuthProvider(persistedCredential.provider, params.config) ? persistedCredential : void 0;
379
+ const persistedOAuthCredential = !useScopedCredential && persistedCredential?.type === "oauth" && isCodexAppServerAuthProvider(persistedCredential.provider, params.config) ? persistedCredential : void 0;
348
380
  const ownerCredential = store.profiles[profileId];
349
381
  const overlaidOAuthCredential = ownerCredential?.type === "oauth" && isCodexAppServerAuthProvider(ownerCredential.provider, params.config) ? ownerCredential : void 0;
382
+ if (useScopedCredential && overlaidOAuthCredential) return await resolveScopedOAuthCredential({
383
+ store,
384
+ profileId,
385
+ credential: overlaidOAuthCredential,
386
+ forceRefresh: params.forceRefresh
387
+ });
350
388
  if (params.forceRefresh && !persistedOAuthCredential && overlaidOAuthCredential) {
351
389
  const refreshedRuntimeCredential = await refreshOAuthCredentialForRuntime({ credential: overlaidOAuthCredential });
352
390
  if (!refreshedRuntimeCredential?.access?.trim()) throw new Error(`Codex app-server auth profile "${profileId}" could not refresh.`);
@@ -359,14 +397,54 @@ async function resolveOAuthCredentialForCodexAppServer(profileId, credential, pa
359
397
  agentDir: ownerAgentDir,
360
398
  forceRefresh: params.forceRefresh && Boolean(persistedOAuthCredential)
361
399
  });
362
- const refreshed = loadAuthProfileStoreForSecretsRuntime(ownerAgentDir).profiles[profileId];
400
+ const refreshed = useScopedCredential ? void 0 : loadAuthProfileStoreForSecretsRuntime(ownerAgentDir).profiles[profileId];
401
+ const refreshedOAuthCredential = refreshed?.type === "oauth" && isCodexAppServerAuthProvider(refreshed.provider, params.config) ? refreshed : void 0;
402
+ if (refreshedOAuthCredential && isDeepStrictEqual(params.store.profiles[profileId], credential)) params.store.profiles[profileId] = refreshedOAuthCredential;
363
403
  const storedCredential = store.profiles[profileId];
364
- const candidate = refreshed?.type === "oauth" && isCodexAppServerAuthProvider(refreshed.provider, params.config) ? refreshed : storedCredential?.type === "oauth" && isCodexAppServerAuthProvider(storedCredential.provider, params.config) ? storedCredential : credential;
404
+ const candidate = refreshedOAuthCredential ? refreshedOAuthCredential : storedCredential?.type === "oauth" && isCodexAppServerAuthProvider(storedCredential.provider, params.config) ? storedCredential : credential;
365
405
  return resolved?.apiKey ? {
366
406
  ...candidate,
367
407
  access: resolved.apiKey
368
408
  } : candidate;
369
409
  }
410
+ function shouldUseScopedOAuthCredential(params) {
411
+ if (!params.store.runtimePersistedProfileIds?.includes(params.profileId)) return true;
412
+ const persisted = params.persistedCredential;
413
+ if (persisted?.type !== "oauth") return true;
414
+ if (resolveProviderIdForAuth(persisted.provider, { config: params.config }) !== resolveProviderIdForAuth(params.suppliedCredential.provider, { config: params.config })) return true;
415
+ return !isDeepStrictEqual(persisted, params.suppliedCredential) && !hasMatchingOAuthIdentity(persisted, params.suppliedCredential);
416
+ }
417
+ function hasMatchingOAuthIdentity(persisted, supplied) {
418
+ const persistedAccountId = persisted.accountId?.trim();
419
+ const suppliedAccountId = supplied.accountId?.trim();
420
+ if (persistedAccountId && suppliedAccountId) return persistedAccountId === suppliedAccountId;
421
+ const persistedEmail = persisted.email?.trim().toLowerCase();
422
+ const suppliedEmail = supplied.email?.trim().toLowerCase();
423
+ return Boolean(persistedEmail && suppliedEmail && persistedEmail === suppliedEmail);
424
+ }
425
+ async function resolveScopedOAuthCredential(params) {
426
+ const existingRefresh = scopedOAuthRefreshQueues.get(params.store)?.get(params.profileId);
427
+ if (existingRefresh) return await existingRefresh;
428
+ if (!params.forceRefresh && hasUsableOAuthCredential(params.credential)) return params.credential;
429
+ const storeRefreshes = scopedOAuthRefreshQueues.get(params.store) ?? /* @__PURE__ */ new Map();
430
+ scopedOAuthRefreshQueues.set(params.store, storeRefreshes);
431
+ const refresh = (async () => {
432
+ const current = params.store.profiles[params.profileId];
433
+ const credential = current?.type === "oauth" ? current : params.credential;
434
+ if (!params.forceRefresh && hasUsableOAuthCredential(credential)) return credential;
435
+ const refreshed = await refreshOAuthCredentialForRuntime({ credential });
436
+ if (!refreshed?.access?.trim()) throw new Error(`Codex app-server auth profile "${params.profileId}" could not refresh.`);
437
+ if (!isDeepStrictEqual(params.store.profiles[params.profileId], credential)) throw new Error(`Codex app-server auth profile "${params.profileId}" changed while refreshing.`);
438
+ params.store.profiles[params.profileId] = refreshed;
439
+ return refreshed;
440
+ })();
441
+ storeRefreshes.set(params.profileId, refresh);
442
+ try {
443
+ return await refresh;
444
+ } finally {
445
+ if (storeRefreshes.get(params.profileId) === refresh) storeRefreshes.delete(params.profileId);
446
+ }
447
+ }
370
448
  function isCodexAppServerAuthProvider(provider, config) {
371
449
  const resolvedProvider = resolveProviderIdForAuth(provider, { config });
372
450
  return resolvedProvider === CODEX_APP_SERVER_AUTH_PROVIDER || resolvedProvider === OPENAI_CODEX_APP_SERVER_AUTH_PROVIDER || resolvedProvider === LEGACY_CODEX_APP_SERVER_AUTH_PROVIDER;
@@ -629,20 +707,29 @@ async function resolveCodexAppServerClientStartContext(options) {
629
707
  const agentDir = options?.agentDir ?? resolveDefaultAgentDir(options?.config ?? {});
630
708
  const usesNativeAuth = options?.authProfileId === null;
631
709
  const requestedAuthProfileId = options?.authProfileId === null ? void 0 : options?.authProfileId;
710
+ const authProfileStore = !usesNativeAuth && options?.authProfileStore ? resolveCodexAppServerAuthProfileStore({
711
+ agentDir,
712
+ authProfileId: requestedAuthProfileId,
713
+ authProfileStore: options.authProfileStore,
714
+ config: options.config
715
+ }) : options?.authProfileStore;
632
716
  const authProfileId = usesNativeAuth ? void 0 : resolveCodexAppServerAuthProfileIdForAgent({
633
717
  authProfileId: requestedAuthProfileId,
634
718
  agentDir,
635
- config: options?.config
719
+ config: options?.config,
720
+ ...authProfileStore ? { authProfileStore } : {}
636
721
  });
637
722
  return {
638
723
  agentDir,
639
724
  usesNativeAuth,
640
725
  authProfileId,
726
+ authProfileStore,
641
727
  startOptions: await bridgeCodexAppServerStartOptions({
642
728
  startOptions: await resolveManagedCodexAppServerStartOptions(options?.startOptions ?? resolveCodexAppServerRuntimeOptions().start),
643
729
  agentDir,
644
730
  authProfileId: usesNativeAuth ? null : authProfileId,
645
- config: options?.config
731
+ config: options?.config,
732
+ ...authProfileStore ? { authProfileStore } : {}
646
733
  })
647
734
  };
648
735
  }
@@ -731,8 +818,17 @@ async function acquireSharedCodexAppServerClient(options, leaseOptions) {
731
818
  }
732
819
  /** Starts a non-shared Codex app-server client owned entirely by the caller. */
733
820
  async function createIsolatedCodexAppServerClient(options) {
734
- const { agentDir, usesNativeAuth, authProfileId, startOptions } = await resolveCodexAppServerClientStartContext(options);
821
+ const { agentDir, usesNativeAuth, authProfileId, authProfileStore, startOptions } = await resolveCodexAppServerClientStartContext(options);
735
822
  const client = CodexAppServerClient.start(startOptions);
823
+ if (authProfileId) client.addRequestHandler(async (request) => {
824
+ if (request.method !== "account/chatgptAuthTokens/refresh") return;
825
+ return await refreshCodexAppServerAuthTokens({
826
+ agentDir,
827
+ authProfileId,
828
+ ...authProfileStore ? { authProfileStore } : {},
829
+ config: options?.config
830
+ });
831
+ });
736
832
  const initialize = client.initialize();
737
833
  try {
738
834
  await withTimeout$1(initialize, options?.timeoutMs ?? 0, "codex app-server initialize timed out");
@@ -741,7 +837,8 @@ async function createIsolatedCodexAppServerClient(options) {
741
837
  agentDir,
742
838
  authProfileId: usesNativeAuth ? null : authProfileId,
743
839
  startOptions,
744
- config: options?.config
840
+ config: options?.config,
841
+ ...authProfileStore ? { authProfileStore } : {}
745
842
  });
746
843
  return client;
747
844
  } catch (error) {
@@ -1,14 +1,14 @@
1
1
  import { d as resolveCodexAppServerRuntimeOptions, g as shouldAutoApproveCodexAppServerApprovals, h as resolveOpenClawExecPolicyForCodexAppServer, n as canUseCodexModelBackedApprovalsReviewerForModel, p as resolveCodexModelBackedReviewerPolicyContext, u as readCodexPluginConfig } from "./config-DJXpBkGf.js";
2
2
  import { a as readCodexDynamicToolCallParams, c as readCodexTurn, i as assertCodexTurnStartResponse, t as assertCodexThreadForkResponse } from "./protocol-validators-B48C6S9O.js";
3
3
  import { t as isJsonObject } from "./protocol-oeJQu4rs.js";
4
- import { i as formatCodexUsageLimitErrorMessage } from "./provider-Cs6kWhDQ.js";
4
+ import { i as formatCodexUsageLimitErrorMessage } from "./provider-C5P6352f.js";
5
5
  import { i as isCodexAppServerApprovalRequest } from "./client-DovmVtbr.js";
6
- import { A as resolveCodexDynamicToolsLoading, D as filterCodexDynamicTools, d as resolveCodexAppServerRequestModelSelection, f as resolveCodexBindingModelProviderFallback, p as resolveReasoningEffort, r as buildCodexRuntimeThreadConfig, t as CODEX_NATIVE_PERSONALITY_NONE, u as resolveCodexAppServerModelProvider, v as mergeCodexThreadConfigs } from "./thread-lifecycle-Cq1-IfZB.js";
6
+ import { A as resolveCodexDynamicToolsLoading, D as filterCodexDynamicTools, d as resolveCodexAppServerRequestModelSelection, f as resolveCodexBindingModelProviderFallback, p as resolveReasoningEffort, r as buildCodexRuntimeThreadConfig, t as CODEX_NATIVE_PERSONALITY_NONE, u as resolveCodexAppServerModelProvider, v as mergeCodexThreadConfigs } from "./thread-lifecycle-cban34w3.js";
7
7
  import { i as isCodexAppServerNativeAuthProfile, o as readCodexAppServerBinding } from "./session-binding-ElbcSq2o.js";
8
- import { a as resolveCodexAppServerForModelProvider, i as readCodexNotificationTurnId, r as readCodexNotificationThreadId } from "./notification-correlation-D-MYfJwV.js";
9
- import { a as getLeasedSharedCodexAppServerClient, o as releaseLeasedSharedCodexAppServerClient, u as refreshCodexAppServerAuthTokens } from "./shared-client-CflavQ_i.js";
8
+ import { a as resolveCodexAppServerForModelProvider, i as readCodexNotificationTurnId, r as readCodexNotificationThreadId } from "./notification-correlation-BGoG0N90.js";
9
+ import { a as getLeasedSharedCodexAppServerClient, o as releaseLeasedSharedCodexAppServerClient, u as refreshCodexAppServerAuthTokens } from "./shared-client-jFMumCOe.js";
10
10
  import { n as resolveCodexNativeExecutionBlock } from "./sandbox-guard-C-Yv9uwY.js";
11
- 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-CmUUO3Eu.js";
11
+ 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-C3i3FYtc.js";
12
12
  import { n as rememberCodexRateLimits, t as readRecentCodexRateLimits } from "./rate-limit-cache-C7qmZ0Jh.js";
13
13
  import { loadExecApprovals } from "openclaw/plugin-sdk/exec-approvals-runtime";
14
14
  import { buildAgentHookContextChannelFields, embeddedAgentLog, formatErrorMessage, registerNativeHookRelay, resolveAgentDir, resolveAttemptSpawnWorkspaceDir, resolveModelAuthMode, resolveSandboxContext, resolveSessionAgentIds, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
@@ -2,7 +2,7 @@ import { i as codexSandboxPolicyForTurn, m as resolveCodexPluginsPolicy, t as CO
2
2
  import { n as assertCodexThreadResumeResponse, r as assertCodexThreadStartResponse } from "./protocol-validators-B48C6S9O.js";
3
3
  import { t as isJsonObject } from "./protocol-oeJQu4rs.js";
4
4
  import { CODEX_GPT5_HEARTBEAT_PROMPT_OVERLAY } from "./prompt-overlay.js";
5
- import { r as isModernCodexModel } from "./provider-Cs6kWhDQ.js";
5
+ import { r as isModernCodexModel } from "./provider-C5P6352f.js";
6
6
  import { a as isCodexAppServerConnectionClosedError, n as CodexAppServerRpcError } from "./client-DovmVtbr.js";
7
7
  import { i as isCodexAppServerNativeAuthProfile, l as writeCodexAppServerBinding, n as clearCodexAppServerBinding, o as readCodexAppServerBinding } from "./session-binding-ElbcSq2o.js";
8
8
  import { isFutureDateTimestampMs, resolveDateTimestampMs, resolveExpiresAtMsFromDurationMs } from "openclaw/plugin-sdk/number-runtime";
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@openclaw/codex",
3
- "version": "2026.6.6-beta.2",
3
+ "version": "2026.6.8-beta.1",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@openclaw/codex",
9
- "version": "2026.6.6-beta.2",
9
+ "version": "2026.6.8-beta.1",
10
10
  "dependencies": {
11
11
  "@openai/codex": "0.139.0",
12
12
  "typebox": "1.1.39",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/codex",
3
- "version": "2026.6.6-beta.2",
3
+ "version": "2026.6.8-beta.1",
4
4
  "description": "OpenClaw Codex app-server harness and model provider plugin with a Codex-managed GPT catalog.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -26,10 +26,10 @@
26
26
  "minHostVersion": ">=2026.5.1-beta.1"
27
27
  },
28
28
  "compat": {
29
- "pluginApi": ">=2026.6.6-beta.2"
29
+ "pluginApi": ">=2026.6.8-beta.1"
30
30
  },
31
31
  "build": {
32
- "openclawVersion": "2026.6.6-beta.2"
32
+ "openclawVersion": "2026.6.8-beta.1"
33
33
  },
34
34
  "release": {
35
35
  "publishToClawHub": true,
@@ -47,7 +47,7 @@
47
47
  "README.md"
48
48
  ],
49
49
  "peerDependencies": {
50
- "openclaw": ">=2026.6.6-beta.2"
50
+ "openclaw": ">=2026.6.8-beta.1"
51
51
  },
52
52
  "peerDependenciesMeta": {
53
53
  "openclaw": {