@openclaw/codex 2026.6.5 → 2026.6.6-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/dist/{client-kMCtlApt.js → client-DovmVtbr.js} +3 -10
  2. package/dist/{client-factory-Bt49r45B.js → client-factory-XajDuvQ1.js} +1 -1
  3. package/dist/{command-handlers-DMn2M7W7.js → command-handlers-DIUFKqaF.js} +11 -9
  4. package/dist/{compact-CwnPeYnM.js → compact-BWiNkDSs.js} +96 -9
  5. package/dist/{computer-use-ClweWaMz.js → computer-use-D3pi5csE.js} +3 -2
  6. package/dist/{config-BT6SLiE6.js → config-DJXpBkGf.js} +214 -13
  7. package/dist/{conversation-binding-CzpvaBs1.js → conversation-binding-CMwrZrt7.js} +190 -65
  8. package/dist/harness.js +12 -5
  9. package/dist/index.js +11 -10
  10. package/dist/media-understanding-provider.js +6 -6
  11. package/dist/{models-DXorTaja.js → models-CQGfP7nG.js} +2 -2
  12. package/dist/{native-hook-relay-DHwz_ICg.js → native-hook-relay-CmUUO3Eu.js} +160 -4
  13. package/dist/notification-correlation-D-MYfJwV.js +382 -0
  14. package/dist/{request-D64BfplD.js → plugin-app-cache-key-NpzxEcSR.js} +4 -36
  15. package/dist/protocol-oeJQu4rs.js +9 -0
  16. package/dist/{protocol-validators-CIpP8IJ2.js → protocol-validators-B48C6S9O.js} +2296 -2273
  17. package/dist/provider-Cs6kWhDQ.js +584 -0
  18. package/dist/provider.js +1 -164
  19. package/dist/request-Dq0LUOqZ.js +36 -0
  20. package/dist/{run-attempt-BWdNnok4.js → run-attempt-DG9p9ReO.js} +374 -65
  21. package/dist/{session-binding-BgTv_YGm.js → session-binding-ElbcSq2o.js} +107 -44
  22. package/dist/{shared-client-xytpSKD0.js → shared-client-CflavQ_i.js} +3 -3
  23. package/dist/{side-question-BnvBQPqW.js → side-question-Ctu2VXAG.js} +82 -26
  24. package/dist/{thread-lifecycle-BJsazZ8j.js → thread-lifecycle-Cq1-IfZB.js} +115 -34
  25. package/npm-shrinkwrap.json +30 -30
  26. package/package.json +5 -5
  27. package/dist/notification-correlation-o8quHmTK.js +0 -656
@@ -1,28 +1,67 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
- import { s as normalizeCodexServiceTier } from "./config-BT6SLiE6.js";
2
+ import { l as normalizeCodexServiceTier } from "./config-DJXpBkGf.js";
3
+ import { ensureAuthProfileStore, resolveDefaultAgentDir, resolveProviderIdForAuth } from "openclaw/plugin-sdk/agent-runtime";
3
4
  import { embeddedAgentLog } from "openclaw/plugin-sdk/agent-harness-runtime";
4
5
  import fs from "node:fs/promises";
5
- import { ensureAuthProfileStore, resolveDefaultAgentDir, resolveProviderIdForAuth } from "openclaw/plugin-sdk/agent-runtime";
6
+ import { AsyncLocalStorage } from "node:async_hooks";
7
+ import { withFileLock } from "openclaw/plugin-sdk/file-lock";
6
8
  //#region extensions/codex/src/app-server/session-binding.ts
7
9
  /**
8
10
  * Persists and normalizes the Codex app-server thread binding associated with
9
11
  * an OpenClaw session file.
10
12
  */
11
13
  var session_binding_exports = /* @__PURE__ */ __exportAll({
14
+ CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS: () => CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS,
12
15
  clearCodexAppServerBinding: () => clearCodexAppServerBinding,
13
16
  clearCodexAppServerBindingForThread: () => clearCodexAppServerBindingForThread,
14
17
  isCodexAppServerNativeAuthProfile: () => isCodexAppServerNativeAuthProfile,
15
18
  normalizeCodexAppServerBindingModelProvider: () => normalizeCodexAppServerBindingModelProvider,
16
19
  readCodexAppServerBinding: () => readCodexAppServerBinding,
17
20
  resolveCodexAppServerBindingPath: () => resolveCodexAppServerBindingPath,
21
+ withCodexAppServerBindingLock: () => withCodexAppServerBindingLock,
18
22
  writeCodexAppServerBinding: () => writeCodexAppServerBinding
19
23
  });
20
24
  const CODEX_APP_SERVER_NATIVE_AUTH_PROVIDER = "openai";
21
25
  const PUBLIC_OPENAI_MODEL_PROVIDER = "openai";
26
+ const CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS = 6e4;
27
+ const CODEX_APP_SERVER_BINDING_LOCK_RETRY_INTERVAL_MS = 1e3;
28
+ const CODEX_APP_SERVER_BINDING_LOCK_OPTIONS = {
29
+ retries: {
30
+ retries: Math.ceil(75e3 / CODEX_APP_SERVER_BINDING_LOCK_RETRY_INTERVAL_MS),
31
+ factor: 1,
32
+ minTimeout: CODEX_APP_SERVER_BINDING_LOCK_RETRY_INTERVAL_MS,
33
+ maxTimeout: CODEX_APP_SERVER_BINDING_LOCK_RETRY_INTERVAL_MS
34
+ },
35
+ stale: CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS * 2
36
+ };
37
+ const bindingMutationQueues = /* @__PURE__ */ new Map();
38
+ const bindingMutationContext = new AsyncLocalStorage();
22
39
  /** Returns the JSON sidecar path for the Codex app-server binding beside a session file. */
23
40
  function resolveCodexAppServerBindingPath(sessionFile) {
24
41
  return `${sessionFile}.codex-app-server.json`;
25
42
  }
43
+ /** Serializes mutation of the Codex app-server binding sidecar for a session file. */
44
+ async function withCodexAppServerBindingLock(sessionFile, run) {
45
+ const bindingPath = resolveCodexAppServerBindingPath(sessionFile);
46
+ const ownedBindings = bindingMutationContext.getStore();
47
+ if (ownedBindings?.has(bindingPath)) return await withFileLock(bindingPath, CODEX_APP_SERVER_BINDING_LOCK_OPTIONS, run);
48
+ const previous = bindingMutationQueues.get(bindingPath) ?? Promise.resolve();
49
+ let releaseCurrent;
50
+ const current = new Promise((resolve) => {
51
+ releaseCurrent = resolve;
52
+ });
53
+ const queued = previous.then(() => current, () => current);
54
+ bindingMutationQueues.set(bindingPath, queued);
55
+ await previous.catch(() => void 0);
56
+ const nestedOwnedBindings = new Set(ownedBindings);
57
+ nestedOwnedBindings.add(bindingPath);
58
+ try {
59
+ return await bindingMutationContext.run(nestedOwnedBindings, () => withFileLock(bindingPath, CODEX_APP_SERVER_BINDING_LOCK_OPTIONS, run));
60
+ } finally {
61
+ releaseCurrent();
62
+ if (bindingMutationQueues.get(bindingPath) === queued) bindingMutationQueues.delete(bindingPath);
63
+ }
64
+ }
26
65
  /** Reads and normalizes a Codex app-server binding sidecar, returning undefined on stale data. */
27
66
  async function readCodexAppServerBinding(sessionFile, lookup = {}) {
28
67
  const path = resolveCodexAppServerBindingPath(sessionFile);
@@ -79,36 +118,38 @@ async function readCodexAppServerBinding(sessionFile, lookup = {}) {
79
118
  }
80
119
  /** Writes the Codex app-server binding sidecar with normalized provider/auth metadata. */
81
120
  async function writeCodexAppServerBinding(sessionFile, binding, lookup = {}) {
82
- const now = (/* @__PURE__ */ new Date()).toISOString();
83
- const payload = {
84
- schemaVersion: 1,
85
- sessionFile,
86
- threadId: binding.threadId,
87
- cwd: binding.cwd,
88
- authProfileId: binding.authProfileId,
89
- model: binding.model,
90
- modelProvider: normalizeCodexAppServerBindingModelProvider({
91
- ...lookup,
121
+ await withCodexAppServerBindingLock(sessionFile, async () => {
122
+ const now = (/* @__PURE__ */ new Date()).toISOString();
123
+ const payload = {
124
+ schemaVersion: 1,
125
+ sessionFile,
126
+ threadId: binding.threadId,
127
+ cwd: binding.cwd,
92
128
  authProfileId: binding.authProfileId,
93
- modelProvider: binding.modelProvider
94
- }),
95
- approvalPolicy: binding.approvalPolicy,
96
- sandbox: binding.sandbox,
97
- serviceTier: binding.serviceTier,
98
- dynamicToolsFingerprint: binding.dynamicToolsFingerprint,
99
- dynamicToolsContainDeferred: binding.dynamicToolsContainDeferred,
100
- userMcpServersFingerprint: binding.userMcpServersFingerprint,
101
- mcpServersFingerprint: binding.mcpServersFingerprint,
102
- nativeHookRelayGeneration: binding.nativeHookRelayGeneration,
103
- pluginAppsFingerprint: binding.pluginAppsFingerprint,
104
- pluginAppsInputFingerprint: binding.pluginAppsInputFingerprint,
105
- pluginAppPolicyContext: binding.pluginAppPolicyContext,
106
- contextEngine: binding.contextEngine,
107
- environmentSelectionFingerprint: binding.environmentSelectionFingerprint,
108
- createdAt: binding.createdAt ?? now,
109
- updatedAt: now
110
- };
111
- await fs.writeFile(resolveCodexAppServerBindingPath(sessionFile), `${JSON.stringify(payload, null, 2)}\n`);
129
+ model: binding.model,
130
+ modelProvider: normalizeCodexAppServerBindingModelProvider({
131
+ ...lookup,
132
+ authProfileId: binding.authProfileId,
133
+ modelProvider: binding.modelProvider
134
+ }),
135
+ approvalPolicy: binding.approvalPolicy,
136
+ sandbox: binding.sandbox,
137
+ serviceTier: binding.serviceTier,
138
+ dynamicToolsFingerprint: binding.dynamicToolsFingerprint,
139
+ dynamicToolsContainDeferred: binding.dynamicToolsContainDeferred,
140
+ userMcpServersFingerprint: binding.userMcpServersFingerprint,
141
+ mcpServersFingerprint: binding.mcpServersFingerprint,
142
+ nativeHookRelayGeneration: binding.nativeHookRelayGeneration,
143
+ pluginAppsFingerprint: binding.pluginAppsFingerprint,
144
+ pluginAppsInputFingerprint: binding.pluginAppsInputFingerprint,
145
+ pluginAppPolicyContext: binding.pluginAppPolicyContext,
146
+ contextEngine: binding.contextEngine,
147
+ environmentSelectionFingerprint: binding.environmentSelectionFingerprint,
148
+ createdAt: binding.createdAt ?? now,
149
+ updatedAt: now
150
+ };
151
+ await fs.writeFile(resolveCodexAppServerBindingPath(sessionFile), `${JSON.stringify(payload, null, 2)}\n`);
152
+ });
112
153
  }
113
154
  function readContextEngineBinding(value) {
114
155
  if (!value || typeof value !== "object" || Array.isArray(value)) return;
@@ -166,29 +207,51 @@ function readPluginAppPolicyContext(value) {
166
207
  }
167
208
  /** Removes the Codex app-server binding sidecar if present. */
168
209
  async function clearCodexAppServerBinding(sessionFile, _lookup = {}) {
210
+ if (!await codexAppServerBindingSidecarExists(sessionFile)) return;
211
+ await withCodexAppServerBindingLock(sessionFile, async () => {
212
+ await unlinkCodexAppServerBinding(sessionFile);
213
+ });
214
+ }
215
+ async function codexAppServerBindingSidecarExists(sessionFile) {
169
216
  try {
170
- await fs.unlink(resolveCodexAppServerBindingPath(sessionFile));
217
+ await fs.access(resolveCodexAppServerBindingPath(sessionFile));
218
+ return true;
171
219
  } catch (error) {
172
- if (!isNotFound(error)) embeddedAgentLog.warn("failed to clear codex app-server binding", {
220
+ if (!isNotFound(error)) embeddedAgentLog.warn("failed to inspect codex app-server binding", {
173
221
  sessionFile,
174
222
  error
175
223
  });
224
+ return false;
176
225
  }
177
226
  }
178
- /** Clears a binding only when it still points at the expected Codex thread id. */
179
- async function clearCodexAppServerBindingForThread(sessionFile, threadId, lookup = {}) {
180
- const binding = await readCodexAppServerBinding(sessionFile, lookup);
181
- if (!binding) return false;
182
- if (binding.threadId !== threadId) {
183
- embeddedAgentLog.debug("codex app-server binding points at a different thread; preserving", {
227
+ async function unlinkCodexAppServerBinding(sessionFile) {
228
+ try {
229
+ await fs.unlink(resolveCodexAppServerBindingPath(sessionFile));
230
+ return true;
231
+ } catch (error) {
232
+ if (!isNotFound(error)) embeddedAgentLog.warn("failed to clear codex app-server binding", {
184
233
  sessionFile,
185
- threadId,
186
- boundThreadId: binding.threadId
234
+ error
187
235
  });
188
236
  return false;
189
237
  }
190
- await clearCodexAppServerBinding(sessionFile);
191
- return true;
238
+ }
239
+ /** Clears a binding only when it still points at the expected Codex thread id. */
240
+ async function clearCodexAppServerBindingForThread(sessionFile, threadId, lookup = {}) {
241
+ if (!await readCodexAppServerBinding(sessionFile, lookup)) return false;
242
+ return await withCodexAppServerBindingLock(sessionFile, async () => {
243
+ const binding = await readCodexAppServerBinding(sessionFile, lookup);
244
+ if (!binding) return false;
245
+ if (binding.threadId !== threadId) {
246
+ embeddedAgentLog.debug("codex app-server binding points at a different thread; preserving", {
247
+ sessionFile,
248
+ threadId,
249
+ boundThreadId: binding.threadId
250
+ });
251
+ return false;
252
+ }
253
+ return await unlinkCodexAppServerBinding(sessionFile);
254
+ });
192
255
  }
193
256
  function isNotFound(error) {
194
257
  return Boolean(error && typeof error === "object" && "code" in error && error.code === "ENOENT");
@@ -253,4 +316,4 @@ function readServiceTier(value) {
253
316
  return normalizeCodexServiceTier(value);
254
317
  }
255
318
  //#endregion
256
- export { readCodexAppServerBinding as a, normalizeCodexAppServerBindingModelProvider as i, clearCodexAppServerBindingForThread as n, session_binding_exports as o, isCodexAppServerNativeAuthProfile as r, writeCodexAppServerBinding as s, clearCodexAppServerBinding as t };
319
+ export { normalizeCodexAppServerBindingModelProvider as a, withCodexAppServerBindingLock as c, isCodexAppServerNativeAuthProfile as i, writeCodexAppServerBinding as l, clearCodexAppServerBinding as n, readCodexAppServerBinding as o, clearCodexAppServerBindingForThread as r, session_binding_exports as s, CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS as t };
@@ -1,13 +1,13 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
- import { l as resolveCodexAppServerRuntimeOptions, n as codexAppServerStartOptionsKey } from "./config-BT6SLiE6.js";
3
- import { c as resolveCodexAppServerSpawnEnv, o as MANAGED_CODEX_APP_SERVER_PACKAGE, t as CodexAppServerClient } from "./client-kMCtlApt.js";
2
+ import { d as resolveCodexAppServerRuntimeOptions, r as codexAppServerStartOptionsKey } from "./config-DJXpBkGf.js";
3
+ import { c as resolveCodexAppServerSpawnEnv, o as MANAGED_CODEX_APP_SERVER_PACKAGE, t as CodexAppServerClient } from "./client-DovmVtbr.js";
4
4
  import { createRequire } from "node:module";
5
5
  import { createHash } from "node:crypto";
6
6
  import fsSync, { constants, readFileSync } from "node:fs";
7
7
  import os from "node:os";
8
- import fs, { access } from "node:fs/promises";
9
8
  import path from "node:path";
10
9
  import { ensureAuthProfileStore, ensureAuthProfileStoreWithoutExternalProfiles, loadAuthProfileStoreForSecretsRuntime, refreshOAuthCredentialForRuntime, resolveApiKeyForProfile, resolveAuthProfileOrder, resolveDefaultAgentDir, resolvePersistedAuthProfileOwnerAgentDir, resolveProviderIdForAuth } from "openclaw/plugin-sdk/agent-runtime";
10
+ import fs, { access } from "node:fs/promises";
11
11
  import { fileURLToPath } from "node:url";
12
12
  import { withTimeout } from "openclaw/plugin-sdk/security-runtime";
13
13
  //#region extensions/codex/src/app-server/auth-bridge.ts
@@ -1,13 +1,16 @@
1
- import { c as readCodexPluginConfig, l as resolveCodexAppServerRuntimeOptions, p as shouldAutoApproveCodexAppServerApprovals } from "./config-BT6SLiE6.js";
2
- import { a as readCodexDynamicToolCallParams, c as readCodexTurn, i as assertCodexTurnStartResponse, t as assertCodexThreadForkResponse } from "./protocol-validators-CIpP8IJ2.js";
3
- import { i as isCodexAppServerApprovalRequest, l as isJsonObject } from "./client-kMCtlApt.js";
4
- import { O as resolveCodexDynamicToolsLoading, T as filterCodexDynamicTools, d as resolveReasoningEffort, g as mergeCodexThreadConfigs, r as buildCodexRuntimeThreadConfig, t as CODEX_NATIVE_PERSONALITY_NONE, u as resolveCodexAppServerModelProvider } from "./thread-lifecycle-BJsazZ8j.js";
5
- import { a as readCodexAppServerBinding } from "./session-binding-BgTv_YGm.js";
6
- import { h as formatCodexUsageLimitErrorMessage, i as readCodexNotificationTurnId, r as readCodexNotificationThreadId } from "./notification-correlation-o8quHmTK.js";
7
- import { a as getLeasedSharedCodexAppServerClient, o as releaseLeasedSharedCodexAppServerClient, u as refreshCodexAppServerAuthTokens } from "./shared-client-xytpSKD0.js";
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
+ import { a as readCodexDynamicToolCallParams, c as readCodexTurn, i as assertCodexTurnStartResponse, t as assertCodexThreadForkResponse } from "./protocol-validators-B48C6S9O.js";
3
+ import { t as isJsonObject } from "./protocol-oeJQu4rs.js";
4
+ import { i as formatCodexUsageLimitErrorMessage } from "./provider-Cs6kWhDQ.js";
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";
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
10
  import { n as resolveCodexNativeExecutionBlock } from "./sandbox-guard-C-Yv9uwY.js";
9
- import { d as emitDynamicToolErrorDiagnostic, f as emitDynamicToolStartedDiagnostic, h as handleCodexAppServerApprovalRequest, i as buildCodexNativeHookRelayDisabledConfig, l as handleCodexAppServerElicitationRequest, m as filterToolsForVisionInputs, p as emitDynamicToolTerminalDiagnostic, r as buildCodexNativeHookRelayConfig, t as CODEX_NATIVE_HOOK_RELAY_EVENTS, u as createCodexDynamicToolBridge } from "./native-hook-relay-DHwz_ICg.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";
10
12
  import { n as rememberCodexRateLimits, t as readRecentCodexRateLimits } from "./rate-limit-cache-C7qmZ0Jh.js";
13
+ import { loadExecApprovals } from "openclaw/plugin-sdk/exec-approvals-runtime";
11
14
  import { buildAgentHookContextChannelFields, embeddedAgentLog, formatErrorMessage, registerNativeHookRelay, resolveAgentDir, resolveAttemptSpawnWorkspaceDir, resolveModelAuthMode, resolveSandboxContext, resolveSessionAgentIds, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
12
15
  //#region extensions/codex/src/app-server/side-question.ts
13
16
  const CODEX_SIDE_DYNAMIC_TOOL_TIMEOUT_MS = 9e4;
@@ -57,8 +60,54 @@ async function runCodexAppServerSideQuestion(params, options = {}) {
57
60
  });
58
61
  if (nativeExecutionBlock) throw new Error(nativeExecutionBlock);
59
62
  const pluginConfig = readCodexPluginConfig(options.pluginConfig);
60
- const appServer = resolveCodexAppServerRuntimeOptions({ pluginConfig });
63
+ const { sessionAgentId } = resolveSessionAgentIds({
64
+ sessionKey: params.sessionKey,
65
+ config: params.cfg,
66
+ agentId: params.agentId
67
+ });
68
+ const execPolicy = resolveOpenClawExecPolicyForCodexAppServer({
69
+ approvals: loadExecApprovals(),
70
+ config: params.cfg,
71
+ agentId: sessionAgentId
72
+ });
61
73
  const authProfileId = params.authProfileId ?? binding.authProfileId;
74
+ const modelProvider = resolveCodexAppServerModelProvider({
75
+ provider: params.provider,
76
+ authProfileId,
77
+ agentDir: params.agentDir,
78
+ config: params.cfg
79
+ }) ?? resolveCodexBindingModelProviderFallback({
80
+ provider: params.provider,
81
+ currentModel: params.model,
82
+ bindingModel: binding.model,
83
+ bindingModelProvider: binding.modelProvider
84
+ });
85
+ const modelSelection = resolveCodexAppServerRequestModelSelection({
86
+ model: params.model,
87
+ modelProvider,
88
+ authProfileId,
89
+ agentDir: params.agentDir,
90
+ config: params.cfg
91
+ });
92
+ const reviewerPolicyContext = resolveCodexModelBackedReviewerPolicyContext({
93
+ provider: params.provider,
94
+ model: params.model,
95
+ bindingModelProvider: binding.modelProvider,
96
+ bindingModel: binding.model,
97
+ nativeAuthProfile: isCodexAppServerNativeAuthProfile({
98
+ authProfileId,
99
+ agentDir: params.agentDir,
100
+ config: params.cfg
101
+ })
102
+ });
103
+ const appServer = resolveCodexAppServerRuntimeOptions({
104
+ pluginConfig,
105
+ execPolicy,
106
+ modelProvider: reviewerPolicyContext.modelProvider,
107
+ model: reviewerPolicyContext.model,
108
+ config: params.cfg,
109
+ agentDir: params.agentDir
110
+ });
62
111
  const client = await getLeasedSharedCodexAppServerClient({
63
112
  startOptions: appServer.start,
64
113
  timeoutMs: appServer.requestTimeoutMs,
@@ -82,13 +131,23 @@ async function runCodexAppServerSideQuestion(params, options = {}) {
82
131
  cwd,
83
132
  authProfileId
84
133
  });
85
- const approvalPolicy = binding.approvalPolicy ?? appServer.approvalPolicy;
86
- const sandbox = binding.sandbox ?? appServer.sandbox;
87
- const { sessionAgentId } = resolveSessionAgentIds({
88
- sessionKey: params.sessionKey,
134
+ const modelScopedAppServer = resolveCodexAppServerForModelProvider({
135
+ appServer,
136
+ provider: reviewerPolicyContext.modelProvider,
137
+ model: reviewerPolicyContext.model,
138
+ config: params.cfg,
139
+ env: process.env,
140
+ agentDir: params.agentDir
141
+ });
142
+ const useModelScopedPolicy = !canUseCodexModelBackedApprovalsReviewerForModel({
143
+ modelProvider: reviewerPolicyContext.modelProvider,
144
+ model: reviewerPolicyContext.model,
89
145
  config: params.cfg,
90
- agentId: params.agentId
146
+ env: process.env,
147
+ agentDir: params.agentDir
91
148
  });
149
+ const approvalPolicy = useModelScopedPolicy ? modelScopedAppServer.approvalPolicy : binding.approvalPolicy ?? modelScopedAppServer.approvalPolicy;
150
+ const sandbox = useModelScopedPolicy ? modelScopedAppServer.sandbox : binding.sandbox ?? modelScopedAppServer.sandbox;
92
151
  const toolBridge = await createCodexSideToolBridge({
93
152
  params,
94
153
  cwd,
@@ -119,6 +178,9 @@ async function runCodexAppServerSideQuestion(params, options = {}) {
119
178
  threadId: childThreadId,
120
179
  turnId,
121
180
  nativeHookRelay,
181
+ execPolicy,
182
+ execReviewerAgentId: sessionAgentId,
183
+ internalExecAutoReview: modelScopedAppServer.approvalsReviewer === "user",
122
184
  autoApprove: shouldAutoApproveCodexAppServerApprovals({
123
185
  approvalPolicy,
124
186
  sandbox
@@ -195,20 +257,14 @@ async function runCodexAppServerSideQuestion(params, options = {}) {
195
257
  }) : options.nativeHookRelay?.enabled === false ? buildCodexNativeHookRelayDisabledConfig() : void 0;
196
258
  const runtimeThreadConfig = buildCodexRuntimeThreadConfig(void 0, { nativeCodeModeOnlyEnabled: appServer.codeModeOnly });
197
259
  const threadConfig = mergeCodexThreadConfigs(nativeHookRelayConfig, runtimeThreadConfig) ?? runtimeThreadConfig;
198
- const modelProvider = resolveCodexAppServerModelProvider({
199
- provider: params.provider,
200
- authProfileId,
201
- agentDir: params.agentDir,
202
- config: params.cfg
203
- });
204
260
  childThreadId = assertCodexThreadForkResponse(await forkCodexSideThread(client, {
205
261
  threadId: binding.threadId,
206
- model: params.model,
207
- ...modelProvider ? { modelProvider } : {},
262
+ model: modelSelection.model,
263
+ ...modelSelection.modelProvider ? { modelProvider: modelSelection.modelProvider } : {},
208
264
  personality: CODEX_NATIVE_PERSONALITY_NONE,
209
265
  cwd,
210
266
  approvalPolicy,
211
- approvalsReviewer: appServer.approvalsReviewer,
267
+ approvalsReviewer: modelScopedAppServer.approvalsReviewer,
212
268
  sandbox,
213
269
  ...serviceTier ? { serviceTier } : {},
214
270
  config: threadConfig,
@@ -226,7 +282,7 @@ async function runCodexAppServerSideQuestion(params, options = {}) {
226
282
  timeoutMs: appServer.requestTimeoutMs,
227
283
  signal: params.opts?.abortSignal
228
284
  });
229
- const effort = resolveReasoningEffort(params.resolvedThinkLevel ?? "off", params.model);
285
+ const effort = resolveReasoningEffort(params.resolvedThinkLevel ?? "off", modelSelection.model);
230
286
  turnId = assertCodexTurnStartResponse(await client.request("turn/start", {
231
287
  threadId: childThreadId,
232
288
  input: [{
@@ -235,14 +291,14 @@ async function runCodexAppServerSideQuestion(params, options = {}) {
235
291
  text_elements: []
236
292
  }],
237
293
  cwd,
238
- model: params.model,
294
+ model: modelSelection.model,
239
295
  personality: CODEX_NATIVE_PERSONALITY_NONE,
240
296
  ...serviceTier ? { serviceTier } : {},
241
297
  effort,
242
298
  collaborationMode: {
243
299
  mode: "default",
244
300
  settings: {
245
- model: params.model,
301
+ model: modelSelection.model,
246
302
  reasoning_effort: effort,
247
303
  developer_instructions: null
248
304
  }