@openclaw/codex 2026.5.18 → 2026.5.19-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. package/dist/{client-6FkrXfaz.js → client-BCJaLwdZ.js} +1 -1
  2. package/dist/{client-factory-9L6Ie1dC.js → client-factory-By1f68U_.js} +1 -1
  3. package/dist/{command-formatters-BRW7_Nu7.js → command-formatters-BpPOTePl.js} +2 -1
  4. package/dist/{command-handlers-DcoFMn4e.js → command-handlers-CFFYwpt4.js} +78 -7
  5. package/dist/{compact-UKyG6Pw2.js → compact-BPnB6ZWJ.js} +6 -6
  6. package/dist/{computer-use-UJ3dxrXF.js → computer-use-BD8UmXB-.js} +2 -2
  7. package/dist/{config-B5pq6hEz.js → config-B5rU0vP3.js} +2 -0
  8. package/dist/harness.js +8 -8
  9. package/dist/index.js +54 -10
  10. package/dist/media-understanding-provider.js +3 -3
  11. package/dist/{models-C1zn2RN0.js → models-6ViLQ-HQ.js} +1 -1
  12. package/dist/{node-cli-sessions-C9rlYMPw.js → node-cli-sessions-douLgfcf.js} +5 -5
  13. package/dist/{plugin-activation-B49xb7pI.js → plugin-activation-Dtcfb3sk.js} +65 -6
  14. package/dist/provider.js +2 -2
  15. package/dist/{request-XPjLayGw.js → request-BLCZjckr.js} +3 -3
  16. package/dist/{run-attempt-DyLQRA61.js → run-attempt-BqRPAaHk.js} +469 -118
  17. package/dist/{session-binding-DqApZIgD.js → session-binding-D9ejASYj.js} +1 -1
  18. package/dist/{shared-client-DlvmoLBJ.js → shared-client-DWgKldR5.js} +2 -2
  19. package/dist/{side-question-CfRPUq5X.js → side-question-DjyRnjPQ.js} +50 -17
  20. package/dist/test-api.js +8 -4
  21. package/dist/{thread-lifecycle-5SBrtWFl.js → thread-lifecycle-C07GnPSH.js} +141 -57
  22. package/dist/{vision-tools-BX9YuTEK.js → vision-tools-CDoJ4rDN.js} +61 -7
  23. package/openclaw.plugin.json +9 -0
  24. package/package.json +4 -4
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-DUslC3ob.js";
2
- import { o as normalizeCodexServiceTier } from "./config-B5pq6hEz.js";
2
+ import { o as normalizeCodexServiceTier } from "./config-B5rU0vP3.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";
@@ -1,6 +1,6 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-DUslC3ob.js";
2
- import { c as resolveCodexAppServerRuntimeOptions, n as codexAppServerStartOptionsKey } from "./config-B5pq6hEz.js";
3
- import { a as MANAGED_CODEX_APP_SERVER_PACKAGE, o as resolveCodexAppServerSpawnEnv, t as CodexAppServerClient } from "./client-6FkrXfaz.js";
2
+ import { c as resolveCodexAppServerRuntimeOptions, n as codexAppServerStartOptionsKey } from "./config-B5rU0vP3.js";
3
+ import { a as MANAGED_CODEX_APP_SERVER_PACKAGE, o as resolveCodexAppServerSpawnEnv, t as CodexAppServerClient } from "./client-BCJaLwdZ.js";
4
4
  import { createRequire } from "node:module";
5
5
  import { createHash } from "node:crypto";
6
6
  import { constants, readFileSync } from "node:fs";
@@ -1,17 +1,18 @@
1
- import { c as resolveCodexAppServerRuntimeOptions, s as readCodexPluginConfig } from "./config-B5pq6hEz.js";
1
+ import { c as resolveCodexAppServerRuntimeOptions, s as readCodexPluginConfig } from "./config-B5rU0vP3.js";
2
2
  import { a as readCodexDynamicToolCallParams, i as assertCodexTurnStartResponse, l as readCodexTurnCompletedNotification, t as assertCodexThreadForkResponse } from "./protocol-validators-BGBspNmF.js";
3
3
  import { t as isJsonObject } from "./protocol-C9UWI98H.js";
4
- import { r as isCodexAppServerApprovalRequest } from "./client-6FkrXfaz.js";
5
- import { u as formatCodexUsageLimitErrorMessage } from "./command-formatters-BRW7_Nu7.js";
6
- import { i as getSharedCodexAppServerClient, s as refreshCodexAppServerAuthTokens } from "./shared-client-DlvmoLBJ.js";
7
- import { i as readCodexAppServerBinding } from "./session-binding-DqApZIgD.js";
8
- import { S as filterCodexDynamicTools, T as resolveCodexDynamicToolsLoading, b as createCodexDynamicToolBridge, d as resolveReasoningEffort, h as mergeCodexThreadConfigs, n as buildCodexRuntimeThreadConfig, u as resolveCodexAppServerModelProvider } from "./thread-lifecycle-5SBrtWFl.js";
9
- import { a as handleCodexAppServerElicitationRequest, i as buildCodexNativeHookRelayDisabledConfig, n as CODEX_NATIVE_HOOK_RELAY_EVENTS, o as handleCodexAppServerApprovalRequest, r as buildCodexNativeHookRelayConfig, t as filterToolsForVisionInputs } from "./vision-tools-BX9YuTEK.js";
4
+ import { r as isCodexAppServerApprovalRequest } from "./client-BCJaLwdZ.js";
5
+ import { u as formatCodexUsageLimitErrorMessage } from "./command-formatters-BpPOTePl.js";
6
+ import { i as getSharedCodexAppServerClient, s as refreshCodexAppServerAuthTokens } from "./shared-client-DWgKldR5.js";
7
+ import { i as readCodexAppServerBinding } from "./session-binding-D9ejASYj.js";
8
+ import { S as filterCodexDynamicTools, T as resolveCodexDynamicToolsLoading, b as createCodexDynamicToolBridge, d as resolveReasoningEffort, h as mergeCodexThreadConfigs, n as buildCodexRuntimeThreadConfig, u as resolveCodexAppServerModelProvider } from "./thread-lifecycle-C07GnPSH.js";
9
+ import { a as handleCodexAppServerElicitationRequest, c as emitDynamicToolTerminalDiagnostic, i as buildCodexNativeHookRelayDisabledConfig, l as handleCodexAppServerApprovalRequest, n as CODEX_NATIVE_HOOK_RELAY_EVENTS, o as emitDynamicToolErrorDiagnostic, r as buildCodexNativeHookRelayConfig, s as emitDynamicToolStartedDiagnostic, t as filterToolsForVisionInputs } from "./vision-tools-CDoJ4rDN.js";
10
10
  import { n as rememberCodexRateLimits, t as readRecentCodexRateLimits } from "./rate-limit-cache-dvhq-4pi.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 = 3e4;
14
14
  const CODEX_SIDE_DYNAMIC_TOOL_MAX_TIMEOUT_MS = 6e5;
15
+ const CODEX_SIDE_DYNAMIC_IMAGE_GENERATION_TOOL_TIMEOUT_MS = 12e4;
15
16
  const CODEX_SIDE_DYNAMIC_IMAGE_TOOL_TIMEOUT_MS = 6e4;
16
17
  const SIDE_QUESTION_COMPLETION_TIMEOUT_MS = 6e5;
17
18
  const CODEX_SIDE_NATIVE_HOOK_RELAY_MIN_TTL_MS = 30 * 6e4;
@@ -118,12 +119,37 @@ async function runCodexAppServerSideQuestion(params, options = {}) {
118
119
  call,
119
120
  config: params.cfg
120
121
  });
121
- return await handleSideDynamicToolCallWithTimeout({
122
+ const toolStartedAt = Date.now();
123
+ const diagnosticContext = {
122
124
  call,
123
- toolBridge,
124
- signal: runAbortController.signal,
125
- timeoutMs
126
- });
125
+ runId: sideRunParams.runId,
126
+ sessionId: params.sessionId,
127
+ sessionKey: params.sessionKey
128
+ };
129
+ emitDynamicToolStartedDiagnostic(diagnosticContext);
130
+ try {
131
+ const response = await handleSideDynamicToolCallWithTimeout({
132
+ call,
133
+ toolBridge,
134
+ signal: runAbortController.signal,
135
+ timeoutMs
136
+ });
137
+ emitDynamicToolTerminalDiagnostic({
138
+ ...diagnosticContext,
139
+ response,
140
+ durationMs: Math.max(0, Date.now() - toolStartedAt)
141
+ });
142
+ return {
143
+ contentItems: response.contentItems,
144
+ success: response.success
145
+ };
146
+ } catch (error) {
147
+ emitDynamicToolErrorDiagnostic({
148
+ ...diagnosticContext,
149
+ durationMs: Math.max(0, Date.now() - toolStartedAt)
150
+ });
151
+ throw error;
152
+ }
127
153
  });
128
154
  const approvalPolicy = binding.approvalPolicy ?? appServer.approvalPolicy;
129
155
  const sandbox = binding.sandbox ?? appServer.sandbox;
@@ -156,7 +182,7 @@ async function runCodexAppServerSideQuestion(params, options = {}) {
156
182
  hookTimeoutSec: options.nativeHookRelay?.hookTimeoutSec,
157
183
  clearOmittedEvents: true
158
184
  }) : options.nativeHookRelay?.enabled === false ? buildCodexNativeHookRelayDisabledConfig() : void 0;
159
- const runtimeThreadConfig = buildCodexRuntimeThreadConfig(void 0);
185
+ const runtimeThreadConfig = buildCodexRuntimeThreadConfig(void 0, { nativeCodeModeOnlyEnabled: appServer.codeModeOnly });
160
186
  const threadConfig = mergeCodexThreadConfigs(nativeHookRelayConfig, runtimeThreadConfig) ?? runtimeThreadConfig;
161
187
  const modelProvider = resolveCodexAppServerModelProvider({
162
188
  provider: params.provider,
@@ -343,6 +369,7 @@ async function createCodexSideToolBridge(input) {
343
369
  currentChannelId: input.params.currentChannelId
344
370
  }).channelId,
345
371
  sandbox,
372
+ emitBeforeToolCallDiagnostics: false,
346
373
  modelHasVision: runtimeModel.input?.includes("image") ?? false,
347
374
  requireExplicitMessageTarget: true
348
375
  }), input.pluginConfig), {
@@ -409,13 +436,19 @@ async function handleSideDynamicToolCallWithTimeout(params) {
409
436
  }
410
437
  }
411
438
  function failedSideDynamicToolResponse(message) {
412
- return {
413
- success: false,
439
+ const response = {
414
440
  contentItems: [{
415
441
  type: "inputText",
416
442
  text: message
417
- }]
443
+ }],
444
+ success: false
418
445
  };
446
+ Object.defineProperty(response, "diagnosticTerminalType", {
447
+ configurable: true,
448
+ enumerable: false,
449
+ value: "error"
450
+ });
451
+ return response;
419
452
  }
420
453
  function emptySideUserInputResponse() {
421
454
  return { answers: {} };
@@ -424,7 +457,7 @@ function isSideUserInputRequest(value, threadId, turnId) {
424
457
  return isJsonObject(value) && value.threadId === threadId && value.turnId === turnId;
425
458
  }
426
459
  function resolveSideDynamicToolCallTimeoutMs(params) {
427
- return clampSideDynamicToolTimeoutMs(readSideDynamicToolCallTimeoutMs(params.call.arguments) ?? (params.call.tool === "image_generate" ? readSideImageGenerationModelTimeoutMs(params.config) : void 0) ?? (params.call.tool === "image" ? readSideTimeoutSecondsAsMs(params.config?.tools?.media?.image?.timeoutSeconds) ?? CODEX_SIDE_DYNAMIC_IMAGE_TOOL_TIMEOUT_MS : void 0) ?? CODEX_SIDE_DYNAMIC_TOOL_TIMEOUT_MS);
460
+ return clampSideDynamicToolTimeoutMs(readSideDynamicToolCallTimeoutMs(params.call.arguments) ?? (params.call.tool === "image_generate" ? readSideImageGenerationModelTimeoutMs(params.config) ?? CODEX_SIDE_DYNAMIC_IMAGE_GENERATION_TOOL_TIMEOUT_MS : void 0) ?? (params.call.tool === "image" ? readSideTimeoutSecondsAsMs(params.config?.tools?.media?.image?.timeoutSeconds) ?? CODEX_SIDE_DYNAMIC_IMAGE_TOOL_TIMEOUT_MS : void 0) ?? CODEX_SIDE_DYNAMIC_TOOL_TIMEOUT_MS);
428
461
  }
429
462
  function readSideDynamicToolCallTimeoutMs(value) {
430
463
  if (!isJsonObject(value)) return;
package/dist/test-api.js CHANGED
@@ -1,5 +1,5 @@
1
- import { c as resolveCodexAppServerRuntimeOptions } from "./config-B5pq6hEz.js";
2
- import { S as filterCodexDynamicTools, a as buildThreadResumeParams, b as createCodexDynamicToolBridge, i as buildDeveloperInstructions, o as buildThreadStartParams, s as buildTurnStartParams } from "./thread-lifecycle-5SBrtWFl.js";
1
+ import { c as resolveCodexAppServerRuntimeOptions } from "./config-B5rU0vP3.js";
2
+ import { S as filterCodexDynamicTools, a as buildThreadResumeParams, b as createCodexDynamicToolBridge, i as buildDeveloperInstructions, o as buildThreadStartParams, s as buildTurnStartParams } from "./thread-lifecycle-C07GnPSH.js";
3
3
  //#region extensions/codex/test-api.ts
4
4
  function resolveCodexPromptSnapshotAppServerOptions(pluginConfig) {
5
5
  return resolveCodexAppServerRuntimeOptions({
@@ -9,7 +9,7 @@ function resolveCodexPromptSnapshotAppServerOptions(pluginConfig) {
9
9
  });
10
10
  }
11
11
  function buildCodexHarnessPromptSnapshot(params) {
12
- const developerInstructions = buildDeveloperInstructions(params.attempt);
12
+ const developerInstructions = joinPresentSections(buildDeveloperInstructions(params.attempt, { dynamicTools: params.dynamicTools }), params.developerInstructionAdditions);
13
13
  return {
14
14
  developerInstructions,
15
15
  threadStartParams: buildThreadStartParams(params.attempt, {
@@ -29,10 +29,14 @@ function buildCodexHarnessPromptSnapshot(params) {
29
29
  threadId: params.threadId,
30
30
  cwd: params.cwd,
31
31
  appServer: params.appServer,
32
- promptText: params.promptText
32
+ promptText: params.promptText,
33
+ heartbeatCollaborationInstructions: params.heartbeatCollaborationInstructions
33
34
  })
34
35
  };
35
36
  }
37
+ function joinPresentSections(...sections) {
38
+ return sections.filter((section) => Boolean(section?.trim())).join("\n\n");
39
+ }
36
40
  function createCodexDynamicToolSpecsForPromptSnapshot(params) {
37
41
  return createCodexDynamicToolBridge({
38
42
  tools: filterCodexDynamicTools(params.tools, params.pluginConfig ?? {}),
@@ -1,15 +1,16 @@
1
- import { r as codexSandboxPolicyForTurn, u as resolveCodexPluginsPolicy } from "./config-B5pq6hEz.js";
1
+ import { r as codexSandboxPolicyForTurn, u as resolveCodexPluginsPolicy } from "./config-B5rU0vP3.js";
2
2
  import { n as assertCodexThreadResumeResponse, r as assertCodexThreadStartResponse } from "./protocol-validators-BGBspNmF.js";
3
3
  import { t as isJsonObject } from "./protocol-C9UWI98H.js";
4
- import { CODEX_GPT5_HEARTBEAT_PROMPT_OVERLAY, renderCodexPromptOverlay } from "./prompt-overlay.js";
4
+ import { CODEX_GPT5_HEARTBEAT_PROMPT_OVERLAY } from "./prompt-overlay.js";
5
5
  import { isModernCodexModel } from "./provider.js";
6
- import { i as isCodexAppServerConnectionClosedError } from "./client-6FkrXfaz.js";
7
- import { i as readCodexAppServerBinding, n as isCodexAppServerNativeAuthProfile, o as writeCodexAppServerBinding, t as clearCodexAppServerBinding } from "./session-binding-DqApZIgD.js";
8
- import { a as defaultCodexAppInventoryCache, r as readCodexPluginInventory, t as ensureCodexPluginActivation } from "./plugin-activation-B49xb7pI.js";
6
+ import { i as isCodexAppServerConnectionClosedError } from "./client-BCJaLwdZ.js";
7
+ import { i as readCodexAppServerBinding, n as isCodexAppServerNativeAuthProfile, o as writeCodexAppServerBinding, t as clearCodexAppServerBinding } from "./session-binding-D9ejASYj.js";
8
+ import { a as defaultCodexAppInventoryCache, o as serializeCodexAppInventoryError, r as readCodexPluginInventory, t as ensureCodexPluginActivation } from "./plugin-activation-Dtcfb3sk.js";
9
9
  import crypto from "node:crypto";
10
- import { HEARTBEAT_RESPONSE_TOOL_NAME, createAgentToolResultMiddlewareRunner, createCodexAppServerToolResultExtensionRunner, embeddedAgentLog, extractToolResultMediaArtifact, filterToolResultMediaUrls, isActiveHarnessContextEngine, isMessagingTool, isMessagingToolSendAction, isToolWrappedWithBeforeToolCallHook, normalizeHeartbeatToolResponse, runAgentHarnessAfterToolCallHook, wrapToolWithBeforeToolCallHook } from "openclaw/plugin-sdk/agent-harness-runtime";
10
+ import { HEARTBEAT_RESPONSE_TOOL_NAME, createAgentToolResultMiddlewareRunner, createCodexAppServerToolResultExtensionRunner, embeddedAgentLog, extractToolResultMediaArtifact, filterToolResultMediaUrls, isActiveHarnessContextEngine, isMessagingTool, isMessagingToolSendAction, isToolWrappedWithBeforeToolCallHook, normalizeHeartbeatToolResponse, runAgentHarnessAfterToolCallHook, setBeforeToolCallDiagnosticsEnabled, wrapToolWithBeforeToolCallHook } from "openclaw/plugin-sdk/agent-harness-runtime";
11
11
  import { normalizeAgentId } from "openclaw/plugin-sdk/routing";
12
12
  import { buildCodexUserMcpServersThreadConfigPatch } from "openclaw/plugin-sdk/codex-mcp-projection";
13
+ import { listRegisteredPluginAgentPromptGuidance } from "openclaw/plugin-sdk/plugin-runtime";
13
14
  import { redactSensitiveFieldValue, redactToolPayloadText } from "openclaw/plugin-sdk/logging-core";
14
15
  //#region extensions/codex/src/app-server/dynamic-tool-profile.ts
15
16
  const CODEX_APP_SERVER_OWNED_DYNAMIC_TOOL_EXCLUDES = [
@@ -156,7 +157,13 @@ const DEFAULT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS = 16e3;
156
157
  function createCodexDynamicToolBridge(params) {
157
158
  const toolResultHookContext = toToolResultHookContext(params.hookContext);
158
159
  const toolResultMaxChars = resolveCodexDynamicToolResultMaxChars(params.hookContext);
159
- const tools = params.tools.map((tool) => isToolWrappedWithBeforeToolCallHook(tool) ? tool : wrapToolWithBeforeToolCallHook(tool, params.hookContext));
160
+ const tools = params.tools.map((tool) => {
161
+ if (isToolWrappedWithBeforeToolCallHook(tool)) {
162
+ setBeforeToolCallDiagnosticsEnabled(tool, false);
163
+ return tool;
164
+ }
165
+ return wrapToolWithBeforeToolCallHook(tool, params.hookContext, { emitDiagnostics: false });
166
+ });
160
167
  const toolMap = new Map(tools.map((tool) => [tool.name, tool]));
161
168
  const telemetry = {
162
169
  didSendViaMessagingTool: false,
@@ -234,10 +241,10 @@ function createCodexDynamicToolBridge(params) {
234
241
  result,
235
242
  startedAt
236
243
  });
237
- return {
244
+ return withDiagnosticTerminalType({
238
245
  contentItems: convertToolContents(result.content, toolResultMaxChars),
239
246
  success: !resultIsError
240
- };
247
+ }, inferToolResultDiagnosticTerminalType(result, resultIsError));
241
248
  } catch (error) {
242
249
  collectToolTelemetry({
243
250
  toolName: tool.name,
@@ -258,13 +265,13 @@ function createCodexDynamicToolBridge(params) {
258
265
  error: error instanceof Error ? error.message : String(error),
259
266
  startedAt
260
267
  });
261
- return {
268
+ return withDiagnosticTerminalType({
262
269
  contentItems: [{
263
270
  type: "inputText",
264
271
  text: error instanceof Error ? error.message : String(error)
265
272
  }],
266
273
  success: false
267
- };
274
+ }, "error");
268
275
  }
269
276
  }
270
277
  };
@@ -408,6 +415,21 @@ function isToolResultError(result) {
408
415
  const status = details.status.trim().toLowerCase();
409
416
  return status !== "" && status !== "0" && status !== "ok" && status !== "success" && status !== "completed" && status !== "recorded" && status !== "running";
410
417
  }
418
+ function inferToolResultDiagnosticTerminalType(result, isError) {
419
+ const details = result.details;
420
+ if (isRecord(details) && typeof details.status === "string") {
421
+ if (details.status.trim().toLowerCase() === "blocked") return "blocked";
422
+ }
423
+ return isError ? "error" : "completed";
424
+ }
425
+ function withDiagnosticTerminalType(response, terminalType) {
426
+ Object.defineProperty(response, "diagnosticTerminalType", {
427
+ configurable: true,
428
+ enumerable: false,
429
+ value: terminalType
430
+ });
431
+ return response;
432
+ }
411
433
  function normalizeToolResultMaxChars(maxChars) {
412
434
  return typeof maxChars === "number" && Number.isFinite(maxChars) && maxChars > 0 ? Math.floor(maxChars) : DEFAULT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS;
413
435
  }
@@ -782,10 +804,14 @@ async function buildCodexPluginThreadConfig(params) {
782
804
  request: params.request,
783
805
  appCache,
784
806
  appCacheKey: params.appCacheKey,
785
- nowMs: params.nowMs
807
+ nowMs: params.nowMs,
808
+ suppressAppInventoryRefresh: true
786
809
  });
787
810
  if (shouldWaitForInitialAppInventory(params, policy, inventory)) {
788
- await refreshAppInventoryNow(params, appCache);
811
+ await refreshAppInventoryNow(params, appCache, {
812
+ forceRefetch: true,
813
+ reason: "initial_missing"
814
+ });
789
815
  inventory = await readCodexPluginInventory({
790
816
  pluginConfig: params.pluginConfig,
791
817
  policy,
@@ -817,7 +843,28 @@ async function buildCodexPluginThreadConfig(params) {
817
843
  });
818
844
  }
819
845
  if (activationResults.some((activation) => activation.ok && activation.installAttempted)) {
820
- await refreshAppInventoryNow(params, appCache, { forceRefetch: true });
846
+ await refreshAppInventoryNow(params, appCache, {
847
+ forceRefetch: true,
848
+ reason: "post_install"
849
+ });
850
+ inventory = await readCodexPluginInventory({
851
+ pluginConfig: params.pluginConfig,
852
+ policy,
853
+ request: params.request,
854
+ appCache,
855
+ appCacheKey: params.appCacheKey,
856
+ nowMs: params.nowMs
857
+ });
858
+ inputFingerprint = buildCodexPluginThreadConfigInputFingerprint({
859
+ pluginConfig: params.pluginConfig,
860
+ appCacheKey: params.appCacheKey
861
+ });
862
+ }
863
+ if (shouldForceRefreshForNotReadyPluginApps(params, policy, inventory)) {
864
+ await refreshAppInventoryNow(params, appCache, {
865
+ forceRefetch: true,
866
+ reason: "not_ready_plugin_apps"
867
+ });
821
868
  inventory = await readCodexPluginInventory({
822
869
  pluginConfig: params.pluginConfig,
823
870
  policy,
@@ -845,7 +892,10 @@ async function buildCodexPluginThreadConfig(params) {
845
892
  }
846
893
  if (record.appOwnership !== "proven") continue;
847
894
  pluginAppIds[record.policy.configKey] = [...record.ownedAppIds].toSorted();
848
- for (const app of record.apps) {
895
+ for (const app of resolveThreadConfigAppsForRecord({
896
+ record,
897
+ inventory
898
+ })) {
849
899
  if (!app.accessible || !app.enabled) {
850
900
  diagnostics.push({
851
901
  code: "app_not_ready",
@@ -942,13 +992,29 @@ async function refreshAppInventoryNow(params, appCache, options = {}) {
942
992
  if (!appCacheKey) return;
943
993
  const request = async (method, requestParams) => await params.request(method, requestParams);
944
994
  try {
945
- await appCache.refreshNow({
995
+ return await appCache.refreshNow({
946
996
  key: appCacheKey,
947
997
  request,
948
998
  nowMs: params.nowMs,
949
999
  forceRefetch: options.forceRefetch
950
1000
  });
951
- } catch {}
1001
+ } catch (error) {
1002
+ embeddedAgentLog.warn("codex plugin thread config app inventory refresh failed", {
1003
+ reason: options.reason,
1004
+ forceRefetch: options.forceRefetch === true,
1005
+ error: serializeCodexAppInventoryError(error)
1006
+ });
1007
+ return;
1008
+ }
1009
+ }
1010
+ function resolveThreadConfigAppsForRecord(params) {
1011
+ if (params.inventory.appInventory?.state === "missing") return [];
1012
+ return params.record.apps;
1013
+ }
1014
+ function shouldForceRefreshForNotReadyPluginApps(params, policy, inventory) {
1015
+ if (!params.appCacheKey || !policy.pluginPolicies.some((plugin) => plugin.enabled)) return false;
1016
+ if (inventory.appInventory?.state === "missing") return false;
1017
+ return inventory.records.some((record) => record.appOwnership === "proven" && record.ownedAppIds.length > 0 && (record.apps.length === 0 || record.apps.some((app) => !app.accessible || !app.enabled)));
952
1018
  }
953
1019
  function policyFingerprint(policy) {
954
1020
  return {
@@ -1087,9 +1153,11 @@ async function startOrResumeThread(params) {
1087
1153
  threadId: binding.threadId,
1088
1154
  authProfileId,
1089
1155
  appServer: params.appServer,
1156
+ dynamicTools: params.dynamicTools,
1090
1157
  developerInstructions: params.developerInstructions,
1091
1158
  config: resumeConfig,
1092
- nativeCodeModeEnabled: params.nativeCodeModeEnabled
1159
+ nativeCodeModeEnabled: params.nativeCodeModeEnabled,
1160
+ nativeCodeModeOnlyEnabled: params.nativeCodeModeOnlyEnabled
1093
1161
  })));
1094
1162
  const boundAuthProfileId = authProfileId;
1095
1163
  const fallbackModelProvider = resolveCodexAppServerModelProvider({
@@ -1157,7 +1225,8 @@ async function startOrResumeThread(params) {
1157
1225
  appServer: params.appServer,
1158
1226
  developerInstructions: params.developerInstructions,
1159
1227
  config,
1160
- nativeCodeModeEnabled: params.nativeCodeModeEnabled
1228
+ nativeCodeModeEnabled: params.nativeCodeModeEnabled,
1229
+ nativeCodeModeOnlyEnabled: params.nativeCodeModeOnlyEnabled
1161
1230
  })));
1162
1231
  const modelProvider = resolveCodexAppServerModelProvider({
1163
1232
  provider: params.params.provider,
@@ -1298,9 +1367,12 @@ function buildThreadStartParams(params, options) {
1298
1367
  sandbox: options.appServer.sandbox,
1299
1368
  ...options.appServer.serviceTier ? { serviceTier: options.appServer.serviceTier } : {},
1300
1369
  serviceName: "OpenClaw",
1301
- config: buildCodexRuntimeThreadConfigForRun(params, options.config, { nativeCodeModeEnabled: options.nativeCodeModeEnabled }),
1370
+ config: buildCodexRuntimeThreadConfigForRun(params, options.config, {
1371
+ nativeCodeModeEnabled: options.nativeCodeModeEnabled,
1372
+ nativeCodeModeOnlyEnabled: options.nativeCodeModeOnlyEnabled
1373
+ }),
1302
1374
  ...options.nativeCodeModeEnabled === false ? { environments: [] } : {},
1303
- developerInstructions: options.developerInstructions ?? buildDeveloperInstructions(params),
1375
+ developerInstructions: options.developerInstructions ?? buildDeveloperInstructions(params, { dynamicTools: options.dynamicTools }),
1304
1376
  dynamicTools: options.dynamicTools,
1305
1377
  experimentalRawEvents: true,
1306
1378
  persistExtendedHistory: true
@@ -1322,14 +1394,25 @@ function buildThreadResumeParams(params, options) {
1322
1394
  approvalsReviewer: options.appServer.approvalsReviewer,
1323
1395
  sandbox: options.appServer.sandbox,
1324
1396
  ...options.appServer.serviceTier ? { serviceTier: options.appServer.serviceTier } : {},
1325
- config: buildCodexRuntimeThreadConfigForRun(params, options.config, { nativeCodeModeEnabled: options.nativeCodeModeEnabled }),
1326
- developerInstructions: options.developerInstructions ?? buildDeveloperInstructions(params),
1397
+ config: buildCodexRuntimeThreadConfigForRun(params, options.config, {
1398
+ nativeCodeModeEnabled: options.nativeCodeModeEnabled,
1399
+ nativeCodeModeOnlyEnabled: options.nativeCodeModeOnlyEnabled
1400
+ }),
1401
+ developerInstructions: options.developerInstructions ?? buildDeveloperInstructions(params, { dynamicTools: options.dynamicTools }),
1327
1402
  persistExtendedHistory: true
1328
1403
  };
1329
1404
  }
1330
1405
  function buildCodexRuntimeThreadConfig(config, options = {}) {
1331
- if (options.nativeCodeModeEnabled === false) return mergeCodexThreadConfigs(CODEX_CODE_MODE_THREAD_CONFIG, config, CODEX_CODE_MODE_DISABLED_THREAD_CONFIG) ?? { ...CODEX_CODE_MODE_DISABLED_THREAD_CONFIG };
1332
- return mergeCodexThreadConfigs(CODEX_CODE_MODE_THREAD_CONFIG, config) ?? { ...CODEX_CODE_MODE_THREAD_CONFIG };
1406
+ const codeModeConfig = {
1407
+ ...CODEX_CODE_MODE_THREAD_CONFIG,
1408
+ "features.code_mode_only": options.nativeCodeModeOnlyEnabled === true
1409
+ };
1410
+ if (options.nativeCodeModeEnabled === false) return mergeCodexThreadConfigs(codeModeConfig, config, CODEX_CODE_MODE_DISABLED_THREAD_CONFIG) ?? { ...CODEX_CODE_MODE_DISABLED_THREAD_CONFIG };
1411
+ if (options.nativeCodeModeOnlyEnabled === true) return mergeCodexThreadConfigs(codeModeConfig, config, { "features.code_mode_only": true }) ?? {
1412
+ ...codeModeConfig,
1413
+ "features.code_mode_only": true
1414
+ };
1415
+ return mergeCodexThreadConfigs(codeModeConfig, config) ?? { ...codeModeConfig };
1333
1416
  }
1334
1417
  function buildCodexRuntimeThreadConfigForRun(params, config, options = {}) {
1335
1418
  const runtimeConfig = buildCodexRuntimeThreadConfig(config, options);
@@ -1350,22 +1433,22 @@ function buildTurnStartParams(params, options) {
1350
1433
  model: params.modelId,
1351
1434
  ...options.appServer.serviceTier ? { serviceTier: options.appServer.serviceTier } : {},
1352
1435
  effort: resolveReasoningEffort(params.thinkLevel, params.modelId),
1353
- collaborationMode: buildTurnCollaborationMode(params)
1436
+ collaborationMode: buildTurnCollaborationMode(params, { heartbeatCollaborationInstructions: options.heartbeatCollaborationInstructions })
1354
1437
  };
1355
1438
  }
1356
- function buildTurnCollaborationMode(params) {
1439
+ function buildTurnCollaborationMode(params, options = {}) {
1357
1440
  return {
1358
1441
  mode: "default",
1359
1442
  settings: {
1360
1443
  model: params.modelId,
1361
1444
  reasoning_effort: resolveReasoningEffort(params.thinkLevel, params.modelId),
1362
- developer_instructions: buildTurnScopedCollaborationInstructions(params)
1445
+ developer_instructions: buildTurnScopedCollaborationInstructions(params, options)
1363
1446
  }
1364
1447
  };
1365
1448
  }
1366
- function buildTurnScopedCollaborationInstructions(params) {
1449
+ function buildTurnScopedCollaborationInstructions(params, options = {}) {
1367
1450
  if (params.trigger === "cron") return buildCronCollaborationInstructions();
1368
- if (params.trigger === "heartbeat") return buildHeartbeatCollaborationInstructions();
1451
+ if (params.trigger === "heartbeat") return joinPresentSections(buildHeartbeatCollaborationInstructions(), options.heartbeatCollaborationInstructions);
1369
1452
  return null;
1370
1453
  }
1371
1454
  function buildCronCollaborationInstructions() {
@@ -1383,6 +1466,9 @@ function buildHeartbeatCollaborationInstructions() {
1383
1466
  CODEX_GPT5_HEARTBEAT_PROMPT_OVERLAY
1384
1467
  ].join("\n\n");
1385
1468
  }
1469
+ function joinPresentSections(...sections) {
1470
+ return sections.filter((section) => Boolean(section?.trim())).join("\n\n");
1471
+ }
1386
1472
  function codexDynamicToolsFingerprint(dynamicTools) {
1387
1473
  return fingerprintDynamicTools(dynamicTools);
1388
1474
  }
@@ -1421,36 +1507,34 @@ function shouldStartTransientNoToolThread(params) {
1421
1507
  function compareJsonFingerprint(left, right) {
1422
1508
  return JSON.stringify(left).localeCompare(JSON.stringify(right));
1423
1509
  }
1424
- function buildDeveloperInstructions(params) {
1510
+ function buildDeveloperInstructions(params, options = {}) {
1511
+ const nativeCommandGuidance = listRegisteredPluginAgentPromptGuidance({
1512
+ surface: "codex_app_server",
1513
+ includeLegacyGlobalGuidance: false
1514
+ }).join("\n");
1425
1515
  return [
1426
- "Running inside OpenClaw. Use dynamic tools for messaging, cron, sessions, media, gateway, and nodes when available.",
1427
- "Use Codex native `spawn_agent` for Codex subagents. Use OpenClaw `sessions_spawn` only for OpenClaw or ACP delegation; if it is not already loaded, search for `sessions_spawn` in the `openclaw` dynamic tool namespace before calling it.",
1428
- "Preserve channel/session context. Visible channel replies: use `message`, do not describe would-reply.",
1429
- renderCodexRuntimePromptOverlay(params),
1430
- params.extraSystemPrompt,
1431
- params.skillsSnapshot?.prompt
1516
+ "You are a personal agent running inside OpenClaw. OpenClaw has dynamic tools for OpenClaw-owned messaging, cron, sessions, media, gateway, and nodes.",
1517
+ buildDeferredDynamicToolManifest(options.dynamicTools),
1518
+ "Use Codex native `spawn_agent` for Codex subagents. Use OpenClaw `sessions_spawn` only for OpenClaw or ACP delegation.",
1519
+ buildVisibleReplyInstruction(params, options.dynamicTools),
1520
+ nativeCommandGuidance,
1521
+ params.extraSystemPrompt
1432
1522
  ].filter((section) => typeof section === "string" && section.trim()).join("\n\n");
1433
1523
  }
1434
- function renderCodexRuntimePromptOverlay(params) {
1435
- const contribution = params.runtimePlan?.prompt.resolveSystemPromptContribution({
1436
- config: params.config,
1437
- agentDir: params.agentDir,
1438
- workspaceDir: params.workspaceDir,
1439
- provider: params.provider,
1440
- modelId: params.modelId,
1441
- promptMode: "full",
1442
- agentId: params.agentId
1443
- });
1444
- if (!contribution) return renderCodexPromptOverlay({
1445
- config: params.config,
1446
- providerId: params.provider,
1447
- modelId: params.modelId
1448
- });
1449
- return [
1450
- contribution.stablePrefix,
1451
- ...Object.values(contribution.sectionOverrides ?? {}),
1452
- contribution.dynamicSuffix
1453
- ].filter((section) => typeof section === "string" && section.trim().length > 0).join("\n\n");
1524
+ function buildDeferredDynamicToolManifest(dynamicTools) {
1525
+ const deferredToolNames = [...new Set((dynamicTools ?? []).filter((tool) => tool.deferLoading === true).map((tool) => tool.name.trim()).filter(Boolean))].toSorted((left, right) => left.localeCompare(right));
1526
+ if (deferredToolNames.length === 0) return;
1527
+ return `Deferred searchable OpenClaw dynamic tools available: ${deferredToolNames.join(", ")}. Use \`tool_search\` to load exact callable specs before use.`;
1528
+ }
1529
+ function buildVisibleReplyInstruction(params, dynamicTools) {
1530
+ const messageToolAvailable = dynamicTools ? dynamicTools.some((tool) => tool.name.trim() === "message") : params.disableMessageTool !== true;
1531
+ if (params.sourceReplyDeliveryMode === "message_tool_only" && messageToolAvailable) return [
1532
+ "Preserve channel/session context.",
1533
+ "If this turn needs visible output in the current channel, call `message` with `action=\"send\"` before ending the turn.",
1534
+ "Do not rely on normal final assistant text for visible delivery; final text is private to OpenClaw/Codex in this mode.",
1535
+ "If no visible channel response is needed, do not call `message(action=\"send\")`."
1536
+ ].join(" ");
1537
+ return "To send a visible reply, use the active Codex delivery path.";
1454
1538
  }
1455
1539
  function buildUserInput(params, promptText = params.prompt) {
1456
1540
  const imageInputs = (params.images ?? []).map((image) => {
@@ -1,7 +1,8 @@
1
1
  import { t as isJsonObject } from "./protocol-C9UWI98H.js";
2
- import { r as formatCodexDisplayText } from "./command-formatters-BRW7_Nu7.js";
2
+ import { r as formatCodexDisplayText } from "./command-formatters-BpPOTePl.js";
3
3
  import { createHash } from "node:crypto";
4
4
  import { buildAgentHookContextChannelFields, callGatewayTool, embeddedAgentLog, formatApprovalDisplayPath, hasNativeHookRelayInvocation, invokeNativeHookRelay, runBeforeToolCallHook } from "openclaw/plugin-sdk/agent-harness-runtime";
5
+ import { emitTrustedDiagnosticEvent } from "openclaw/plugin-sdk/diagnostic-runtime";
5
6
  //#region extensions/codex/src/app-server/plugin-approval-roundtrip.ts
6
7
  const DEFAULT_CODEX_APPROVAL_TIMEOUT_MS = 12e4;
7
8
  const MAX_PLUGIN_APPROVAL_TITLE_LENGTH = 80;
@@ -743,6 +744,59 @@ function formatErrorMessage$1(error) {
743
744
  return error instanceof Error ? error.message : String(error);
744
745
  }
745
746
  //#endregion
747
+ //#region extensions/codex/src/app-server/dynamic-tool-diagnostics.ts
748
+ function emitDynamicToolStartedDiagnostic(params) {
749
+ emitTrustedDiagnosticEvent({
750
+ type: "tool.execution.started",
751
+ runId: params.runId,
752
+ sessionId: params.sessionId,
753
+ sessionKey: params.sessionKey,
754
+ toolName: params.call.tool,
755
+ toolCallId: params.call.callId
756
+ });
757
+ }
758
+ function emitDynamicToolErrorDiagnostic(params) {
759
+ emitTrustedDiagnosticEvent({
760
+ type: "tool.execution.error",
761
+ runId: params.runId,
762
+ sessionId: params.sessionId,
763
+ sessionKey: params.sessionKey,
764
+ toolName: params.call.tool,
765
+ toolCallId: params.call.callId,
766
+ durationMs: params.durationMs,
767
+ errorCategory: "codex_dynamic_tool_error"
768
+ });
769
+ }
770
+ function emitDynamicToolTerminalDiagnostic(params) {
771
+ const terminalType = params.response.diagnosticTerminalType ?? (params.response.success ? "completed" : "error");
772
+ if (terminalType === "completed") {
773
+ emitTrustedDiagnosticEvent({
774
+ type: "tool.execution.completed",
775
+ runId: params.runId,
776
+ sessionId: params.sessionId,
777
+ sessionKey: params.sessionKey,
778
+ toolName: params.call.tool,
779
+ toolCallId: params.call.callId,
780
+ durationMs: params.durationMs
781
+ });
782
+ return;
783
+ }
784
+ if (terminalType === "blocked") {
785
+ emitTrustedDiagnosticEvent({
786
+ type: "tool.execution.blocked",
787
+ runId: params.runId,
788
+ sessionId: params.sessionId,
789
+ sessionKey: params.sessionKey,
790
+ toolName: params.call.tool,
791
+ toolCallId: params.call.callId,
792
+ deniedReason: "plugin-before-tool-call",
793
+ reason: "Tool call blocked"
794
+ });
795
+ return;
796
+ }
797
+ emitDynamicToolErrorDiagnostic(params);
798
+ }
799
+ //#endregion
746
800
  //#region extensions/codex/src/app-server/elicitation-bridge.ts
747
801
  const MCP_TOOL_APPROVAL_KIND = "mcp_tool_call";
748
802
  const MCP_TOOL_APPROVAL_KIND_KEY = "codex_approval_kind";
@@ -832,7 +886,7 @@ function hasExactTurnId(requestParams, turnId) {
832
886
  function resolvePluginElicitation(params) {
833
887
  const requestParams = params.requestParams;
834
888
  if (!requestParams) return { kind: "not_plugin" };
835
- const meta = isJsonObject(requestParams._meta) ? requestParams._meta : {};
889
+ const meta = isJsonObject(requestParams["_meta"]) ? requestParams["_meta"] : {};
836
890
  const context = params.pluginAppPolicyContext;
837
891
  const entries = context ? Object.values(context.apps) : [];
838
892
  const appId = readFirstString(meta, PLUGIN_APP_ID_META_KEYS) ?? readFirstString(requestParams, PLUGIN_APP_ID_META_KEYS);
@@ -923,7 +977,7 @@ function buildPluginPolicyElicitationResponse(entry, requestParams) {
923
977
  logPluginElicitationDecline("unsupported_schema", requestParams);
924
978
  return declineElicitationResponse();
925
979
  }
926
- const meta = isJsonObject(requestParams._meta) ? requestParams._meta : {};
980
+ const meta = isJsonObject(requestParams["_meta"]) ? requestParams["_meta"] : {};
927
981
  const response = buildElicitationResponse(requestParams.requestedSchema, meta, "approved-once");
928
982
  if (isJsonObject(response) && response.action === "accept") return response;
929
983
  logPluginElicitationDecline("unmappable_schema", requestParams);
@@ -944,7 +998,7 @@ function logPluginElicitationDecline(reason, requestParams) {
944
998
  });
945
999
  }
946
1000
  function readBridgeableApprovalElicitation(requestParams) {
947
- if (!requestParams || readString(requestParams, "mode") !== "form" || !isJsonObject(requestParams._meta) || requestParams._meta[MCP_TOOL_APPROVAL_KIND_KEY] !== MCP_TOOL_APPROVAL_KIND || !isJsonObject(requestParams.requestedSchema)) return;
1001
+ if (!requestParams || readString(requestParams, "mode") !== "form" || !isJsonObject(requestParams["_meta"]) || requestParams["_meta"][MCP_TOOL_APPROVAL_KIND_KEY] !== MCP_TOOL_APPROVAL_KIND || !isJsonObject(requestParams.requestedSchema)) return;
948
1002
  const requestedSchema = requestParams.requestedSchema;
949
1003
  if (readString(requestedSchema, "type") !== "object" || !isJsonObject(requestedSchema.properties)) return;
950
1004
  const title = sanitizeDisplayText(readString(requestParams, "message") ?? "") || "Codex MCP tool approval";
@@ -952,12 +1006,12 @@ function readBridgeableApprovalElicitation(requestParams) {
952
1006
  title,
953
1007
  description: buildApprovalDescription({
954
1008
  title,
955
- meta: requestParams._meta,
1009
+ meta: requestParams["_meta"],
956
1010
  requestedSchema,
957
1011
  serverName: sanitizeOptionalDisplayText(readString(requestParams, "serverName"))
958
1012
  }),
959
1013
  requestedSchema,
960
- meta: requestParams._meta
1014
+ meta: requestParams["_meta"]
961
1015
  };
962
1016
  }
963
1017
  function buildApprovalDescription(params) {
@@ -1322,4 +1376,4 @@ function filterToolsForVisionInputs(tools, params) {
1322
1376
  return tools.filter((tool) => tool.name !== "image");
1323
1377
  }
1324
1378
  //#endregion
1325
- export { handleCodexAppServerElicitationRequest as a, buildCodexNativeHookRelayDisabledConfig as i, CODEX_NATIVE_HOOK_RELAY_EVENTS as n, handleCodexAppServerApprovalRequest as o, buildCodexNativeHookRelayConfig as r, filterToolsForVisionInputs as t };
1379
+ export { handleCodexAppServerElicitationRequest as a, emitDynamicToolTerminalDiagnostic as c, buildCodexNativeHookRelayDisabledConfig as i, handleCodexAppServerApprovalRequest as l, CODEX_NATIVE_HOOK_RELAY_EVENTS as n, emitDynamicToolErrorDiagnostic as o, buildCodexNativeHookRelayConfig as r, emitDynamicToolStartedDiagnostic as s, filterToolsForVisionInputs as t };
@@ -161,6 +161,10 @@
161
161
  "type": "array",
162
162
  "items": { "type": "string" }
163
163
  },
164
+ "codeModeOnly": {
165
+ "type": "boolean",
166
+ "default": false
167
+ },
164
168
  "requestTimeoutMs": {
165
169
  "type": "number",
166
170
  "minimum": 1,
@@ -326,6 +330,11 @@
326
330
  "help": "Environment variable names removed from the spawned stdio app-server process after overrides are applied.",
327
331
  "advanced": true
328
332
  },
333
+ "appServer.codeModeOnly": {
334
+ "label": "Code Mode Only",
335
+ "help": "Expose Codex's code-mode-only tool surface. OpenClaw dynamic tools remain available through Codex nested tool calls.",
336
+ "advanced": true
337
+ },
329
338
  "appServer.requestTimeoutMs": {
330
339
  "label": "Request Timeout",
331
340
  "help": "Maximum time to wait for Codex app-server control-plane requests.",