@openclaw/codex 2026.7.2-beta.4 → 2026.7.2-beta.5

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 (41) hide show
  1. package/dist/{app-server-policy-BO3jYBkv.js → app-server-policy-BmDgseo_.js} +1 -1
  2. package/dist/attempt-client-cleanup-Ia52yRWc.js +127 -0
  3. package/dist/{attempt-notifications-DdmnBMUp.js → attempt-notifications-CMR2_fmR.js} +1 -1
  4. package/dist/{bounded-turn-CaQL96kg.js → bounded-turn-FEbUXoYT.js} +36 -13
  5. package/dist/{capabilities-CLICvTxf.js → capabilities-BHRSI6Cn.js} +1 -1
  6. package/dist/cli-metadata.js +1 -1
  7. package/dist/{command-formatters-DgADqnHa.js → command-formatters-ico4ZFnk.js} +2 -2
  8. package/dist/{command-handlers-l_lVPNlB.js → command-handlers-CRmnwI2N.js} +1232 -1221
  9. package/dist/{compact-CC5KhBzX.js → compact-dEN49UH6.js} +7 -7
  10. package/dist/{computer-use-Ip1-QGa-.js → computer-use-BjGylO-E.js} +16 -6
  11. package/dist/{conversation-control-sNPsbTCP.js → conversation-control-DE7d9DOj.js} +6 -6
  12. package/dist/doctor-contract-api.js +24 -86
  13. package/dist/{dynamic-tools-CQI3UwqY.js → dynamic-tools-LIt9ojep.js} +50 -46
  14. package/dist/{event-projector-usage-D6tE7_qD.js → event-projector-usage-tvgb1NCX.js} +2 -2
  15. package/dist/harness.js +14 -13
  16. package/dist/index.js +208 -267
  17. package/dist/media-understanding-provider.js +6 -1
  18. package/dist/{models-BNeMlHgg.js → models-BA01NEez.js} +2 -2
  19. package/dist/{notification-correlation-BGLixv5_.js → notification-correlation-Bj_Ak_jI.js} +3 -3
  20. package/dist/{plugin-app-cache-key-CvzvmBRz.js → plugin-app-cache-key-DSXX-rXO.js} +5 -5
  21. package/dist/{transcript-mirror-2p7kl6e4.js → protocol-validators-Dm4eXZmt.js} +2 -550
  22. package/dist/{rate-limits-D0IJT-a6.js → rate-limits-S_PXs0ul.js} +1 -1
  23. package/dist/realtime-voice-api-BPcA1uN9.js +494 -0
  24. package/dist/realtime-voice-api.js +2 -0
  25. package/dist/{request-BTccUTD3.js → request-CXpPennK.js} +1 -1
  26. package/dist/{run-attempt--858NXDl.js → run-attempt-C5GTPJOE.js} +417 -237
  27. package/dist/{session-binding-ZSMX1omP.js → session-binding-DlVQ-Pxs.js} +952 -890
  28. package/dist/{session-catalog-DsKaezgR.js → session-catalog-CP2oCcEb.js} +32 -23
  29. package/dist/{session-cli-CYJTfRLG.js → session-cli-CqZ0Fp2a.js} +2 -2
  30. package/dist/{session-upstream-marker-D7XlI9us.js → session-upstream-marker-QE-m5QFG.js} +1 -1
  31. package/dist/{settled-turn-finalizer-DHltNgtF.js → settled-turn-finalizer-CA_2QXIE.js} +2 -2
  32. package/dist/{shared-client-wmgNFNYp.js → shared-client-BVKE40c-.js} +1863 -1707
  33. package/dist/{side-question-BfFZCsJ-.js → side-question-CO12sHxo.js} +11 -9
  34. package/dist/{thread-lifecycle-cqrOlJkq.js → thread-lifecycle-DRg_FdzC.js} +12 -132
  35. package/dist/transcript-mirror-uKA-A4tB.js +550 -0
  36. package/dist/{upstream-session-fork-vPjwkT1i.js → upstream-session-fork-_Vrz4WJr.js} +3 -3
  37. package/dist/{usage-DM_I3mPT.js → usage-UpVbdX5G.js} +3 -3
  38. package/dist/{web-search-provider.runtime-Bx6HAc_k.js → web-search-provider.runtime-CaQMYDbp.js} +3 -3
  39. package/package.json +4 -5
  40. package/npm-shrinkwrap.json +0 -202
  41. package/dist/{auth-binding-C1czuHPA.js → auth-binding-B4FfbcCg.js} +1 -1
@@ -2,704 +2,526 @@ import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
2
  import { n as CODEX_APP_SERVER_BINDING_NAMESPACE, t as CODEX_APP_SERVER_BINDING_MAX_ENTRIES } from "./session-binding-meta-B7aEMU7g.js";
3
3
  import path from "node:path";
4
4
  import { resolvePositiveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
5
+ import { AgentHarnessSessionSupersededError, embeddedAgentLog } from "openclaw/plugin-sdk/agent-harness-runtime";
5
6
  import { createHash, createHmac, randomBytes, randomUUID } from "node:crypto";
7
+ import { ensureAuthProfileStore, resolveDefaultAgentDir, resolveProviderIdForAuth, resolveSessionAgentIds as resolveSessionAgentIds$1 } from "openclaw/plugin-sdk/agent-runtime";
6
8
  import { readFileSync } from "node:fs";
7
9
  import { homedir, hostname } from "node:os";
8
- import { ensureAuthProfileStore, resolveDefaultAgentDir, resolveProviderIdForAuth, resolveSessionAgentIds } from "openclaw/plugin-sdk/agent-runtime";
9
10
  import { resolveExecApprovalsFromFile } from "openclaw/plugin-sdk/exec-approvals-runtime";
10
11
  import { normalizeAgentId } from "openclaw/plugin-sdk/routing";
11
12
  import { buildSecretInputSchema, normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-input";
12
13
  import { normalizeTrimmedStringList } from "openclaw/plugin-sdk/string-coerce-runtime";
13
14
  import { detectWindowsSpawnCommandInlineArgs } from "openclaw/plugin-sdk/windows-spawn";
14
- import { parse } from "smol-toml";
15
15
  import { z } from "zod";
16
- import { AgentHarnessSessionSupersededError, embeddedAgentLog } from "openclaw/plugin-sdk/agent-harness-runtime";
16
+ import { parse } from "smol-toml";
17
17
  import { AsyncLocalStorage } from "node:async_hooks";
18
18
  import { getSessionEntry, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
19
- //#region extensions/codex/src/app-server/session-discovery-config.ts
20
- const codexSessionCatalogConfigSchema = z.object({ enabled: z.boolean().optional() }).strict();
21
- const codexDiscoveryConfigSchema = z.object({
22
- enabled: z.boolean().optional(),
23
- timeoutMs: z.number().positive().optional()
24
- }).strict();
19
+ //#region extensions/codex/src/app-server/config-contracts.ts
20
+ const CODEX_PLUGINS_MARKETPLACE_NAME = "openai-curated";
21
+ const CODEX_PLUGINS_WORKSPACE_MARKETPLACE_NAME = "workspace-directory";
25
22
  //#endregion
26
- //#region extensions/codex/src/app-server/config.ts
23
+ //#region extensions/codex/src/app-server/config-utils.ts
27
24
  const START_OPTIONS_KEY_SECRET_SYMBOL = Symbol.for("openclaw.codexAppServerStartOptionsKeySecret");
28
25
  const START_OPTIONS_KEY_SECRET = getStartOptionsKeySecret();
29
- const UNIX_CODEX_REQUIREMENTS_PATH = "/etc/codex/requirements.toml";
30
- const WINDOWS_CODEX_REQUIREMENTS_SUFFIX = "\\OpenAI\\Codex\\requirements.toml";
31
- const CODEX_APP_SERVER_HOME_DIRNAME = "codex-home";
32
- const CODEX_CONFIG_TOML_FILENAME = "config.toml";
33
26
  const PLAIN_DECIMAL_NUMBER_RE = /^[+-]?(?:(?:\d+\.?\d*)|(?:\.\d+))$/;
34
- const CODEX_PLUGINS_MARKETPLACE_NAME = "openai-curated";
35
- const CODEX_PLUGINS_WORKSPACE_MARKETPLACE_NAME = "workspace-directory";
36
- function shouldAutoApproveCodexAppServerApprovals(appServer) {
37
- return appServer.networkProxy === void 0 && appServer.approvalPolicy === "never" && appServer.sandbox === "danger-full-access";
27
+ function readRecord(value) {
28
+ return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
38
29
  }
39
- const DEFAULT_CODEX_COMPUTER_USE_PLUGIN_NAME = "computer-use";
40
- const DEFAULT_CODEX_COMPUTER_USE_MCP_SERVER_NAME = "computer-use";
41
- const DEFAULT_CODEX_COMPUTER_USE_MARKETPLACE_DISCOVERY_TIMEOUT_MS = 6e4;
42
- const DEFAULT_CODEX_COMPUTER_USE_LIVE_TEST_TIMEOUT_MS = 6e4;
43
- const DEFAULT_CODEX_COMPUTER_USE_TOOL_CALL_TIMEOUT_MS = 6e4;
44
- const DEFAULT_CODEX_COMPUTER_USE_HEALTH_CHECK_INTERVAL_MINUTES = 60;
45
- const DEFAULT_CODEX_APP_SERVER_NETWORK_PROXY_PROFILE_PREFIX = "openclaw-network";
46
- const codexAppServerTransportSchema = z.enum([
47
- "stdio",
48
- "websocket",
49
- "unix"
50
- ]);
51
- const codexAppServerHomeScopeSchema = z.enum(["agent", "user"]);
52
- const SecretInputSchema = buildSecretInputSchema();
53
- const codexAppServerPolicyModeSchema = z.enum(["yolo", "guardian"]);
54
- const codexAppServerApprovalPolicySchema = z.preprocess((value) => value === "on-failure" ? "on-request" : value, z.enum([
55
- "never",
56
- "on-request",
57
- "untrusted"
58
- ]));
59
- const codexAppServerSandboxSchema = z.enum([
60
- "read-only",
61
- "workspace-write",
62
- "danger-full-access"
63
- ]);
64
- const codexAppServerApprovalsReviewerSchema = z.enum([
65
- "user",
66
- "auto_review",
67
- "guardian_subagent"
68
- ]);
69
- const codexDynamicToolsLoadingSchema = z.enum(["searchable", "direct"]);
70
- const codexComputerUseHealthIntervalSchema = z.union([
71
- z.literal(30),
72
- z.literal(60),
73
- z.literal(120),
74
- z.literal(240)
75
- ]);
76
- const codexComputerUsePluginCacheModeSchema = z.enum(["shared", "independent"]);
77
- const codexPluginDestructivePolicySchema = z.union([
78
- z.boolean(),
79
- z.literal("auto"),
80
- z.literal("ask")
81
- ]);
82
- const codexAppServerServiceTierSchema = z.preprocess((value) => value === null ? null : normalizeCodexServiceTier(value), z.string().trim().min(1).nullable().optional()).optional();
83
- const codexAppServerExperimentalSchema = z.object({ sandboxExecServer: z.boolean().optional() }).strict();
84
- const codexAppServerRemoteWorkspaceRootSchema = z.string().trim().min(1);
85
- const codexAppServerNetworkProxyDomainPermissionSchema = z.enum(["allow", "deny"]);
86
- const codexAppServerNetworkProxyUnixSocketPermissionSchema = z.enum(["allow", "none"]);
87
- const codexAppServerNetworkProxySchema = z.object({
88
- enabled: z.boolean().optional(),
89
- profileName: z.string().trim().min(1).optional(),
90
- baseProfile: z.enum(["read-only", "workspace"]).optional(),
91
- mode: z.enum(["limited", "full"]).optional(),
92
- domains: z.record(z.string(), codexAppServerNetworkProxyDomainPermissionSchema).optional(),
93
- unixSockets: z.record(z.string(), codexAppServerNetworkProxyUnixSocketPermissionSchema).optional(),
94
- proxyUrl: z.string().trim().min(1).optional(),
95
- socksUrl: z.string().trim().min(1).optional(),
96
- enableSocks5: z.boolean().optional(),
97
- enableSocks5Udp: z.boolean().optional(),
98
- allowUpstreamProxy: z.boolean().optional(),
99
- allowLocalBinding: z.boolean().optional(),
100
- dangerouslyAllowNonLoopbackProxy: z.boolean().optional(),
101
- dangerouslyAllowAllUnixSockets: z.boolean().optional()
102
- }).strict();
103
- const codexPluginEntryConfigSchema = z.object({
104
- enabled: z.boolean().optional(),
105
- marketplaceName: z.enum([CODEX_PLUGINS_MARKETPLACE_NAME, CODEX_PLUGINS_WORKSPACE_MARKETPLACE_NAME]).optional(),
106
- pluginName: z.string().trim().min(1).optional(),
107
- allow_destructive_actions: codexPluginDestructivePolicySchema.optional()
108
- }).strict();
109
- const codexPluginsConfigSchema = z.object({
110
- enabled: z.boolean().optional(),
111
- allow_all_plugins: z.boolean().optional(),
112
- allow_destructive_actions: codexPluginDestructivePolicySchema.optional(),
113
- plugins: z.record(z.string(), codexPluginEntryConfigSchema).optional()
114
- }).strict();
115
- const codexSupervisionEndpointSchema = z.union([z.object({
116
- id: z.string().optional(),
117
- label: z.string().optional(),
118
- transport: z.literal("stdio-proxy").optional(),
119
- command: z.string().optional(),
120
- args: z.array(z.string()).optional(),
121
- cwd: z.string().optional()
122
- }).strict(), z.object({
123
- id: z.string().optional(),
124
- label: z.string().optional(),
125
- transport: z.literal("websocket"),
126
- url: z.string(),
127
- authTokenEnv: z.string().optional()
128
- }).strict()]);
129
- const codexSupervisionConfigSchema = z.object({
130
- enabled: z.boolean().optional(),
131
- endpoints: z.array(codexSupervisionEndpointSchema).optional(),
132
- allowRawTranscripts: z.boolean().optional(),
133
- allowWriteControls: z.boolean().optional()
134
- }).strict();
135
- const codexPluginConfigSchema = z.object({
136
- codexDynamicToolsLoading: codexDynamicToolsLoadingSchema.optional(),
137
- codexDynamicToolsExclude: z.array(z.string()).optional(),
138
- sessionCatalog: codexSessionCatalogConfigSchema.optional(),
139
- discovery: codexDiscoveryConfigSchema.optional(),
140
- computerUse: z.object({
141
- enabled: z.boolean().optional(),
142
- autoInstall: z.boolean().optional(),
143
- marketplaceDiscoveryTimeoutMs: z.number().positive().optional(),
144
- liveTestTimeoutMs: z.number().positive().optional(),
145
- toolCallTimeoutMs: z.number().positive().optional(),
146
- healthCheckEnabled: z.boolean().optional(),
147
- healthCheckIntervalMinutes: codexComputerUseHealthIntervalSchema.optional(),
148
- pluginCacheMode: codexComputerUsePluginCacheModeSchema.optional(),
149
- strictReadiness: z.boolean().optional(),
150
- autoRepair: z.boolean().optional(),
151
- marketplaceSource: z.string().optional(),
152
- marketplacePath: z.string().optional(),
153
- marketplaceName: z.string().optional(),
154
- pluginName: z.string().optional(),
155
- mcpServerName: z.string().optional()
156
- }).strict().optional(),
157
- codexPlugins: z.unknown().optional(),
158
- supervision: codexSupervisionConfigSchema.optional(),
159
- appServer: z.object({
160
- mode: codexAppServerPolicyModeSchema.optional(),
161
- transport: codexAppServerTransportSchema.optional(),
162
- homeScope: codexAppServerHomeScopeSchema.optional(),
163
- command: z.string().optional(),
164
- args: z.union([z.array(z.string()), z.string()]).optional(),
165
- url: z.string().optional(),
166
- authToken: SecretInputSchema.optional(),
167
- headers: z.record(z.string(), SecretInputSchema).optional(),
168
- clearEnv: z.array(z.string()).optional(),
169
- remoteWorkspaceRoot: codexAppServerRemoteWorkspaceRootSchema.optional(),
170
- codeModeOnly: z.boolean().optional(),
171
- loopDetectionPreToolUseRelay: z.boolean().optional(),
172
- requestTimeoutMs: z.number().positive().optional(),
173
- turnCompletionIdleTimeoutMs: z.number().positive().optional(),
174
- turnAssistantCompletionIdleTimeoutMs: z.number().positive().optional(),
175
- postToolRawAssistantCompletionIdleTimeoutMs: z.number().positive().optional(),
176
- approvalPolicy: codexAppServerApprovalPolicySchema.optional(),
177
- sandbox: codexAppServerSandboxSchema.optional(),
178
- approvalsReviewer: codexAppServerApprovalsReviewerSchema.optional(),
179
- serviceTier: codexAppServerServiceTierSchema,
180
- networkProxy: codexAppServerNetworkProxySchema.optional(),
181
- defaultWorkspaceDir: z.string().optional(),
182
- experimental: codexAppServerExperimentalSchema.optional()
183
- }).strict().optional()
184
- }).strict();
185
- function readCodexPluginConfig(value) {
186
- const parsed = codexPluginConfigSchema.safeParse(value);
187
- if (!parsed.success) return {};
188
- const { codexPlugins: rawCodexPlugins, ...config } = parsed.data;
189
- const plugins = codexPluginsConfigSchema.safeParse(rawCodexPlugins);
190
- if (!plugins.success) return config;
191
- return {
192
- ...config,
193
- ...plugins.data ? { codexPlugins: plugins.data } : {}
194
- };
30
+ function normalizeCodexServiceTier(value) {
31
+ if (typeof value !== "string") return;
32
+ const trimmed = value.trim();
33
+ if (!trimmed) return;
34
+ const normalized = trimmed.toLowerCase();
35
+ if (normalized === "fast" || normalized === "priority") return "priority";
36
+ if (normalized === "flex") return "flex";
37
+ return trimmed;
195
38
  }
196
- function isCodexSandboxExecServerEnabled(pluginConfig) {
197
- return readCodexPluginConfig(pluginConfig).appServer?.experimental?.sandboxExecServer === true;
39
+ function isCodexFastServiceTier(value) {
40
+ return normalizeCodexServiceTier(value) === "priority";
198
41
  }
199
- function assertCodexAppServerCommandHasNoInlineArgs(params) {
200
- const inlineArgs = detectWindowsSpawnCommandInlineArgs(params.command);
201
- if (!inlineArgs) return;
202
- const sourceLabel = params.source === "env" ? "OPENCLAW_CODEX_APP_SERVER_BIN" : "plugins.entries.codex.config.appServer.command";
203
- const argsLabel = params.source === "env" ? "OPENCLAW_CODEX_APP_SERVER_ARGS" : "plugins.entries.codex.config.appServer.args";
204
- throw new Error(`${sourceLabel} must be only the Codex app-server executable path; "${inlineArgs.executable}" was configured with inline arguments "${inlineArgs.arguments}". Move those arguments to ${argsLabel}, or remove the override to use the managed Codex startup path.`);
42
+ function normalizePositiveNumber(value, fallback) {
43
+ return resolvePositiveTimerTimeoutMs(value, fallback);
205
44
  }
206
- function resolveCodexPluginsPolicy(pluginConfig) {
207
- const config = readCodexPluginConfig(pluginConfig).codexPlugins;
208
- const configured = config !== void 0;
209
- const enabled = config?.enabled === true;
210
- const destructivePolicy = resolveCodexPluginDestructivePolicy(config?.allow_destructive_actions ?? true);
211
- const pluginPolicies = Object.entries(config?.plugins ?? {}).flatMap(([configKey, entry]) => {
212
- if (!isCodexPluginMarketplaceName(entry.marketplaceName) || !entry.pluginName) return [];
213
- const entryDestructivePolicy = resolveCodexPluginDestructivePolicy(entry.allow_destructive_actions ?? config?.allow_destructive_actions ?? true);
214
- return [{
215
- configKey,
216
- marketplaceName: entry.marketplaceName,
217
- pluginName: entry.pluginName,
218
- enabled: enabled && entry.enabled !== false,
219
- allowDestructiveActions: entryDestructivePolicy.allowDestructiveActions,
220
- destructiveApprovalMode: entryDestructivePolicy.destructiveApprovalMode
221
- }];
222
- }).toSorted((left, right) => left.configKey.localeCompare(right.configKey));
223
- return {
224
- configured,
225
- enabled,
226
- allowAllPlugins: enabled && config?.allow_all_plugins === true,
227
- allowDestructiveActions: destructivePolicy.allowDestructiveActions,
228
- destructiveApprovalMode: destructivePolicy.destructiveApprovalMode,
229
- pluginPolicies
230
- };
45
+ function normalizeHeaders(value) {
46
+ if (!value || typeof value !== "object" || Array.isArray(value)) return {};
47
+ return Object.fromEntries(Object.entries(value).map(([key, child]) => [key.trim(), normalizeCodexAppServerSecretInput({
48
+ value: child,
49
+ path: `plugins.entries.codex.config.appServer.headers.${key}`
50
+ })]).filter((entry) => Boolean(entry[0] && entry[1])));
231
51
  }
232
- function isCodexPluginMarketplaceName(value) {
233
- return value === "openai-curated" || value === "workspace-directory";
52
+ function normalizeCodexAppServerSecretInput(params) {
53
+ return normalizeResolvedSecretInputString(params);
234
54
  }
235
- function resolveCodexPluginDestructivePolicy(policy) {
236
- if (policy === "auto" || policy === "ask") return {
237
- allowDestructiveActions: true,
238
- destructiveApprovalMode: policy
239
- };
240
- return {
241
- allowDestructiveActions: policy,
242
- destructiveApprovalMode: policy ? "allow" : "deny"
243
- };
55
+ function normalizeStringList(value) {
56
+ return normalizeTrimmedStringList(value);
244
57
  }
245
- function resolveCodexAppServerRuntimeOptions(params = {}) {
246
- const env = params.env ?? process.env;
247
- const config = readCodexPluginConfig(params.pluginConfig).appServer ?? {};
248
- const transport = resolveTransport(config.transport);
249
- const homeScope = config.homeScope ?? "agent";
250
- const configCommand = readNonEmptyString(config.command);
251
- const envCommand = readNonEmptyString(env.OPENCLAW_CODEX_APP_SERVER_BIN);
252
- const command = configCommand ?? envCommand ?? "codex";
253
- const commandSource = configCommand ? "config" : envCommand ? "env" : "managed";
254
- if (commandSource === "config" || commandSource === "env") assertCodexAppServerCommandHasNoInlineArgs({
255
- command,
256
- source: commandSource
257
- });
258
- const args = resolveArgs(config.args, env.OPENCLAW_CODEX_APP_SERVER_ARGS);
259
- const headers = normalizeHeaders(config.headers);
260
- const clearEnv = normalizeStringList(config.clearEnv);
261
- const authToken = normalizeCodexAppServerSecretInput({
262
- value: config.authToken,
263
- path: "plugins.entries.codex.config.appServer.authToken"
264
- });
265
- const url = readNonEmptyString(config.url) ?? (transport === "unix" ? "unix://" : void 0);
266
- const connectionClass = inferCodexAppServerConnectionClass({
267
- transport,
268
- url
269
- });
270
- const remoteAppsSubstrate = "preconfigured";
271
- const remoteWorkspaceRoot = normalizeRemoteWorkspaceRoot(config.remoteWorkspaceRoot);
272
- const execMode = resolveEffectiveOpenClawExecModeForCodexAppServer({
273
- execMode: params.execMode,
274
- execPolicy: params.execPolicy
275
- });
276
- assertCodexAppServerAllowedForOpenClawExecMode(execMode);
277
- const explicitPolicyMode = resolvePolicyMode(config.mode) ?? resolvePolicyMode(env.OPENCLAW_CODEX_APP_SERVER_MODE);
278
- const configuredSandbox = resolveSandbox(config.sandbox) ?? resolveSandbox(env.OPENCLAW_CODEX_APP_SERVER_SANDBOX);
279
- const explicitApprovalsReviewer = resolveApprovalsReviewer(config.approvalsReviewer);
280
- const normalizedPolicyMode = resolveCodexPolicyModeForOpenClawExecMode(execMode);
281
- const ignoreLegacyYoloPolicyMode = normalizedPolicyMode === "guardian" && explicitPolicyMode === "yolo";
282
- const canUseModelBackedReviewer = canUseCodexModelBackedApprovalsReviewerForModel({
283
- modelProvider: params.modelProvider,
284
- model: params.model,
285
- config: params.config,
286
- env,
287
- agentDir: params.agentDir,
288
- codexConfigToml: params.codexConfigToml,
289
- homeScope
290
- });
291
- const forceUserReviewer = !canUseModelBackedReviewer && (explicitApprovalsReviewer === "auto_review" || explicitApprovalsReviewer === "guardian_subagent" || explicitPolicyMode === "guardian" && explicitApprovalsReviewer !== "user") || execMode !== void 0 && execMode !== "full" && (execMode !== "auto" || !canUseModelBackedReviewer);
292
- const forceGuardianReviewer = execMode === "auto" && canUseModelBackedReviewer;
293
- const execModeRequiringPromptingApprovals = execMode === "auto" || execMode === "ask" ? execMode : forceUserReviewer ? "ask" : void 0;
294
- const forceDangerFullAccessSandbox = params.execPolicy?.touched === true && params.execPolicy.security === "full" && params.execPolicy.ask === "always";
295
- const forceRuntimePolicy = forceUserReviewer || forceGuardianReviewer || forceDangerFullAccessSandbox;
296
- const defaultPolicy = explicitPolicyMode && !forceRuntimePolicy && !ignoreLegacyYoloPolicyMode ? void 0 : resolveDefaultCodexAppServerPolicy({
297
- transport,
298
- env,
299
- forceGuardian: normalizedPolicyMode === "guardian",
300
- forceUserReviewer: forceUserReviewer || !canUseModelBackedReviewer,
301
- execModeRequiringPromptingApprovals,
302
- requirementsToml: params.requirementsToml,
303
- requirementsPath: params.requirementsPath,
304
- readRequirementsFile: params.readRequirementsFile,
305
- platform: params.platform,
306
- hostName: params.hostName,
307
- execModeRequiringUserReviewer: forceUserReviewer ? execMode : void 0
308
- });
309
- const preserveExplicitAutoSandbox = forceGuardianReviewer && configuredSandbox === "read-only";
310
- const forcedPolicy = forceRuntimePolicy ? {
311
- approvalPolicy: defaultPolicy?.approvalPolicy ?? "on-request",
312
- sandbox: preserveExplicitAutoSandbox ? void 0 : forceDangerFullAccessSandbox ? selectForcedDangerFullAccessSandbox({
313
- configuredSandbox,
314
- defaultPolicy,
315
- openClawSandboxActive: Boolean(params.openClawSandboxActive)
316
- }) : selectForcedPromptingSandbox({
317
- configuredSandbox,
318
- defaultSandbox: defaultPolicy?.sandbox
319
- }),
320
- approvalsReviewer: defaultPolicy?.approvalsReviewer ?? (forceUserReviewer ? "user" : "auto_review")
321
- } : void 0;
322
- const policyMode = ignoreLegacyYoloPolicyMode ? normalizedPolicyMode : explicitPolicyMode ?? normalizedPolicyMode ?? defaultPolicy?.mode ?? "yolo";
323
- const serviceTier = normalizeCodexServiceTier(config.serviceTier);
324
- const resolvedSandbox = forcedPolicy?.sandbox ?? configuredSandbox ?? defaultPolicy?.sandbox ?? (policyMode === "guardian" ? "workspace-write" : "danger-full-access");
325
- if (transport === "websocket" && !url) throw new Error("plugins.entries.codex.config.appServer.url is required when appServer.transport is websocket");
326
- if (transport === "websocket" && homeScope === "user") throw new Error("plugins.entries.codex.config.appServer.homeScope=user requires appServer.transport=stdio or unix");
327
- if (transport === "unix" && homeScope !== "user") throw new Error("plugins.entries.codex.config.appServer.transport=unix requires appServer.homeScope=user");
328
- if (transport === "unix" && !url?.startsWith("unix://")) throw new Error("plugins.entries.codex.config.appServer.url must use unix:// when appServer.transport is unix");
329
- assertCodexAppServerConnectionSecurity({
330
- transport,
331
- url,
332
- authToken,
333
- headers
334
- });
335
- const configApprovalPolicy = resolveApprovalPolicy(config.approvalPolicy);
336
- const envApprovalPolicy = resolveApprovalPolicy(env.OPENCLAW_CODEX_APP_SERVER_APPROVAL_POLICY);
337
- const approvalPolicy = configApprovalPolicy ?? envApprovalPolicy ?? defaultPolicy?.approvalPolicy ?? (policyMode === "guardian" ? "on-request" : "never");
338
- const approvalPolicySource = configApprovalPolicy ? "config" : envApprovalPolicy ? "env" : defaultPolicy?.approvalPolicy ? "requirements" : "implicit";
339
- const computerUseConfig = resolveCodexComputerUseConfig({
340
- pluginConfig: params.pluginConfig,
341
- env
342
- });
343
- const managedCommandOrder = params.managedCommandOrder ?? (homeScope === "user" || computerUseConfig.enabled ? "desktop-first" : "package-first");
344
- const includeManagedCommandOrder = commandSource === "managed" && (managedCommandOrder === "desktop-first" || params.managedCommandOrder === "package-first");
345
- const managedComputerUsePluginNames = [.../* @__PURE__ */ new Set([DEFAULT_CODEX_COMPUTER_USE_PLUGIN_NAME, computerUseConfig.pluginName])];
346
- return {
347
- start: {
348
- transport,
349
- homeScope,
350
- command,
351
- commandSource,
352
- ...includeManagedCommandOrder ? { managedCommandOrder } : {},
353
- ...commandSource === "managed" ? { managedComputerUsePluginNames } : {},
354
- args: args.length > 0 ? args : [
355
- "app-server",
356
- "--listen",
357
- "stdio://"
358
- ],
359
- ...url ? { url } : {},
360
- ...authToken ? { authToken } : {},
361
- headers,
362
- ...transport === "stdio" && clearEnv.length > 0 ? { clearEnv } : {}
363
- },
364
- connectionClass,
365
- remoteAppsSubstrate,
366
- ...remoteWorkspaceRoot ? { remoteWorkspaceRoot } : {},
367
- codeModeOnly: config.codeModeOnly === true,
368
- loopDetectionPreToolUseRelay: config.loopDetectionPreToolUseRelay !== false,
369
- requestTimeoutMs: normalizePositiveNumber(config.requestTimeoutMs, 6e4),
370
- turnCompletionIdleTimeoutMs: normalizePositiveNumber(config.turnCompletionIdleTimeoutMs, 6e4),
371
- turnAssistantCompletionIdleTimeoutMs: normalizePositiveNumber(config.turnAssistantCompletionIdleTimeoutMs, 1e4),
372
- ...config.postToolRawAssistantCompletionIdleTimeoutMs !== void 0 ? { postToolRawAssistantCompletionIdleTimeoutMs: normalizePositiveNumber(config.postToolRawAssistantCompletionIdleTimeoutMs, 6e4) } : {},
373
- approvalPolicy: forcedPolicy?.approvalPolicy ?? approvalPolicy,
374
- approvalPolicySource,
375
- sandbox: resolvedSandbox,
376
- approvalsReviewer: forcedPolicy?.approvalsReviewer ?? explicitApprovalsReviewer ?? defaultPolicy?.approvalsReviewer ?? (policyMode === "guardian" ? "auto_review" : "user"),
377
- ...serviceTier ? { serviceTier } : {},
378
- ...resolveCodexAppServerNetworkProxy(config.networkProxy, resolvedSandbox)
379
- };
58
+ function readBooleanEnv(value) {
59
+ if (value === void 0) return;
60
+ const normalized = value.trim().toLowerCase();
61
+ if ([
62
+ "1",
63
+ "true",
64
+ "yes",
65
+ "on"
66
+ ].includes(normalized)) return true;
67
+ if ([
68
+ "0",
69
+ "false",
70
+ "no",
71
+ "off"
72
+ ].includes(normalized)) return false;
380
73
  }
381
- /**
382
- * Rechecks Codex-owned plugin state at the final spawn boundary, where the
383
- * effective agent home is known, so Computer Use keeps the desktop app's TCC ownership.
384
- */
385
- function resolveCodexAppServerStartOptionsForAgent(params) {
386
- const startOptions = params.startOptions;
387
- if (startOptions.transport !== "stdio" || startOptions.commandSource !== "managed" || startOptions.managedCommandOrder !== void 0) return startOptions;
388
- if (startOptions.homeScope === "user") return {
389
- ...startOptions,
390
- managedCommandOrder: "desktop-first"
391
- };
392
- return codexConfigEnablesNativeComputerUse({
393
- agentDir: params.agentDir,
394
- codexConfigToml: params.codexConfigToml,
395
- env: params.env,
396
- homeScope: "agent",
397
- pluginNames: startOptions.managedComputerUsePluginNames ?? [DEFAULT_CODEX_COMPUTER_USE_PLUGIN_NAME]
398
- }) ? {
399
- ...startOptions,
400
- managedCommandOrder: "desktop-first"
401
- } : startOptions;
74
+ function readExecSecurity(value) {
75
+ return value === "deny" || value === "allowlist" || value === "full" ? value : void 0;
402
76
  }
403
- function isCodexAppServerApprovalPolicyAllowedByRequirements(policy, params = {}) {
404
- const content = readCodexRequirementsToml(params);
405
- if (content === void 0) return true;
406
- const allowedApprovalPolicies = parseAllowedApprovalPoliciesFromCodexRequirements(content);
407
- return allowedApprovalPolicies === void 0 || allowedApprovalPolicies.has(policy);
77
+ function readExecAsk(value) {
78
+ return value === "off" || value === "on-miss" || value === "always" ? value : void 0;
408
79
  }
409
- function canUseCodexModelBackedApprovalsReviewerForModel(params) {
410
- const explicitProvider = params.modelProvider?.trim().toLowerCase();
411
- const inferredProvider = inferProviderFromModelRef(params.model);
412
- if (explicitProvider && explicitProvider !== "codex") return isTrustedCodexModelBackedApprovalsReviewerProvider(explicitProvider, params) && (inferredProvider === void 0 || isTrustedCodexModelBackedApprovalsReviewerProvider(inferredProvider, params));
413
- if (inferredProvider !== void 0) return isTrustedCodexModelBackedApprovalsReviewerProvider(inferredProvider, params);
414
- return isTrustedCodexModelBackedApprovalsReviewerProvider(explicitProvider, params);
80
+ function readNumberEnv(value) {
81
+ const trimmed = value?.trim();
82
+ if (!trimmed || !PLAIN_DECIMAL_NUMBER_RE.test(trimmed)) return;
83
+ const parsed = Number(trimmed);
84
+ return Number.isFinite(parsed) ? parsed : void 0;
415
85
  }
416
- function isTrustedCodexModelBackedOpenAIProvider(params) {
417
- if (!openAIBaseUrlEnvOverridesAreTrustedForModelBackedReview(params.env)) return false;
418
- const codexBaseUrlOverrides = readCodexBaseUrlOverridesForModelBackedReview(params);
419
- if (codexBaseUrlOverrides === false || !codexBaseUrlOverrides.openAI.every(isNativeOpenAIBaseUrl) || !codexBaseUrlOverrides.chatGPT.every(isNativeChatGPTBaseUrl)) return false;
420
- const openAIProviders = readConfiguredOpenAIProvidersForModelBackedReview(params.config);
421
- if (openAIProviders.length === 0) return true;
422
- return openAIProviders.every((openAIProvider) => configuredOpenAIProviderIsTrustedForModelBackedReview(openAIProvider, params.model));
86
+ function resolveArgs(configArgs, envArgs) {
87
+ if (Array.isArray(configArgs)) return configArgs.map((entry) => readNonEmptyString(entry)).filter((entry) => entry !== void 0);
88
+ if (typeof configArgs === "string") return splitShellWords(configArgs);
89
+ return splitShellWords(envArgs ?? "");
423
90
  }
424
- function resolveCodexModelBackedReviewerPolicyContext(params) {
425
- const provider = params.provider?.trim();
426
- if (provider && provider.toLowerCase() !== "codex") return {
427
- modelProvider: normalizeCodexModelBackedReviewerPolicyProvider(provider),
428
- model: params.model
429
- };
430
- const bindingModelProvider = params.bindingModelProvider?.trim();
431
- const currentModel = params.model?.trim();
432
- const bindingModel = params.bindingModel?.trim();
433
- if (bindingModelProvider && currentModel && bindingModel && currentModel === bindingModel) return {
434
- modelProvider: normalizeCodexModelBackedReviewerPolicyProvider(bindingModelProvider),
435
- model: params.model ?? params.bindingModel
436
- };
437
- const currentModelProvider = inferProviderFromModelRef(params.model);
438
- if (currentModelProvider) return {
439
- modelProvider: normalizeCodexModelBackedReviewerPolicyProvider(currentModelProvider),
440
- model: params.model
441
- };
442
- if (bindingModelProvider) return {
443
- modelProvider: normalizeCodexModelBackedReviewerPolicyProvider(bindingModelProvider),
444
- model: params.model ?? params.bindingModel
445
- };
446
- return {
447
- modelProvider: params.nativeAuthProfile === true ? "openai" : void 0,
448
- model: params.model ?? params.bindingModel
449
- };
91
+ function readNonEmptyString(value) {
92
+ if (typeof value !== "string") return;
93
+ return value.trim() || void 0;
450
94
  }
451
- function resolveCodexComputerUseConfig(params = {}) {
452
- const env = params.env ?? process.env;
453
- const config = readCodexPluginConfig(params.pluginConfig).computerUse ?? {};
454
- const marketplaceSource = readNonEmptyString(params.overrides?.marketplaceSource) ?? readNonEmptyString(config.marketplaceSource) ?? readNonEmptyString(env.OPENCLAW_CODEX_COMPUTER_USE_MARKETPLACE_SOURCE);
455
- const marketplacePath = readNonEmptyString(params.overrides?.marketplacePath) ?? readNonEmptyString(config.marketplacePath) ?? readNonEmptyString(env.OPENCLAW_CODEX_COMPUTER_USE_MARKETPLACE_PATH);
456
- const marketplaceName = readNonEmptyString(params.overrides?.marketplaceName) ?? readNonEmptyString(config.marketplaceName) ?? readNonEmptyString(env.OPENCLAW_CODEX_COMPUTER_USE_MARKETPLACE_NAME);
457
- const configuredPluginName = readNonEmptyString(params.overrides?.pluginName) ?? readNonEmptyString(config.pluginName) ?? readNonEmptyString(env.OPENCLAW_CODEX_COMPUTER_USE_PLUGIN_NAME);
458
- const configuredMcpServerName = readNonEmptyString(params.overrides?.mcpServerName) ?? readNonEmptyString(config.mcpServerName) ?? readNonEmptyString(env.OPENCLAW_CODEX_COMPUTER_USE_MCP_SERVER_NAME);
459
- const autoInstall = params.overrides?.autoInstall ?? config.autoInstall ?? readBooleanEnv(env.OPENCLAW_CODEX_COMPUTER_USE_AUTO_INSTALL) ?? false;
460
- const marketplaceDiscoveryTimeoutMs = normalizePositiveNumber(params.overrides?.marketplaceDiscoveryTimeoutMs ?? config.marketplaceDiscoveryTimeoutMs ?? readNumberEnv(env.OPENCLAW_CODEX_COMPUTER_USE_MARKETPLACE_DISCOVERY_TIMEOUT_MS), DEFAULT_CODEX_COMPUTER_USE_MARKETPLACE_DISCOVERY_TIMEOUT_MS);
461
- const liveTestTimeoutMs = normalizePositiveNumber(params.overrides?.liveTestTimeoutMs ?? config.liveTestTimeoutMs ?? readNumberEnv(env.OPENCLAW_CODEX_COMPUTER_USE_LIVE_TEST_TIMEOUT_MS), DEFAULT_CODEX_COMPUTER_USE_LIVE_TEST_TIMEOUT_MS);
462
- const toolCallTimeoutMs = normalizePositiveNumber(params.overrides?.toolCallTimeoutMs ?? config.toolCallTimeoutMs ?? readNumberEnv(env.OPENCLAW_CODEX_COMPUTER_USE_TOOL_CALL_TIMEOUT_MS), DEFAULT_CODEX_COMPUTER_USE_TOOL_CALL_TIMEOUT_MS);
463
- const healthCheckIntervalMinutes = normalizeComputerUseHealthCheckIntervalMinutes(params.overrides?.healthCheckIntervalMinutes ?? config.healthCheckIntervalMinutes ?? readNumberEnv(env.OPENCLAW_CODEX_COMPUTER_USE_HEALTH_CHECK_INTERVAL_MINUTES));
464
- const healthCheckEnabled = params.overrides?.healthCheckEnabled ?? config.healthCheckEnabled ?? readBooleanEnv(env.OPENCLAW_CODEX_COMPUTER_USE_HEALTH_CHECK_ENABLED) ?? false;
465
- const pluginCacheMode = normalizeComputerUsePluginCacheMode(params.overrides?.pluginCacheMode) ?? normalizeComputerUsePluginCacheMode(config.pluginCacheMode) ?? normalizeComputerUsePluginCacheMode(env.OPENCLAW_CODEX_COMPUTER_USE_PLUGIN_CACHE_MODE) ?? "independent";
466
- const strictReadiness = params.overrides?.strictReadiness ?? config.strictReadiness ?? readBooleanEnv(env.OPENCLAW_CODEX_COMPUTER_USE_STRICT_READINESS) ?? false;
467
- const autoRepair = params.overrides?.autoRepair ?? config.autoRepair ?? readBooleanEnv(env.OPENCLAW_CODEX_COMPUTER_USE_AUTO_REPAIR) ?? false;
468
- return {
469
- enabled: params.overrides?.enabled ?? config.enabled ?? readBooleanEnv(env.OPENCLAW_CODEX_COMPUTER_USE) ?? Boolean(autoInstall || marketplaceSource || marketplacePath || marketplaceName || configuredPluginName || configuredMcpServerName),
470
- autoInstall,
471
- marketplaceDiscoveryTimeoutMs,
472
- liveTestTimeoutMs,
473
- toolCallTimeoutMs,
474
- healthCheckEnabled,
475
- healthCheckIntervalMinutes,
476
- pluginCacheMode,
477
- strictReadiness,
478
- autoRepair,
479
- pluginName: configuredPluginName ?? DEFAULT_CODEX_COMPUTER_USE_PLUGIN_NAME,
480
- mcpServerName: configuredMcpServerName ?? DEFAULT_CODEX_COMPUTER_USE_MCP_SERVER_NAME,
481
- ...marketplaceSource ? { marketplaceSource } : {},
482
- ...marketplacePath ? { marketplacePath } : {},
483
- ...marketplaceName ? { marketplaceName } : {}
484
- };
95
+ function hashSecretForKey(value, label) {
96
+ if (!value) return null;
97
+ return createHmac("sha256", START_OPTIONS_KEY_SECRET).update(label).update("\0").update(value).digest("hex");
485
98
  }
486
- function normalizeComputerUseHealthCheckIntervalMinutes(value) {
487
- return value === 30 || value === 60 || value === 120 || value === 240 ? value : DEFAULT_CODEX_COMPUTER_USE_HEALTH_CHECK_INTERVAL_MINUTES;
99
+ function getStartOptionsKeySecret() {
100
+ const globalState = globalThis;
101
+ globalState[START_OPTIONS_KEY_SECRET_SYMBOL] ??= randomBytes(32);
102
+ return globalState[START_OPTIONS_KEY_SECRET_SYMBOL];
488
103
  }
489
- function normalizeComputerUsePluginCacheMode(value) {
490
- return value === "shared" || value === "independent" ? value : null;
104
+ function splitShellWords(value) {
105
+ const words = [];
106
+ let current = "";
107
+ let quote = null;
108
+ for (const char of value) {
109
+ if (quote) {
110
+ if (char === quote) quote = null;
111
+ else current += char;
112
+ continue;
113
+ }
114
+ if (char === "\"" || char === "'") {
115
+ quote = char;
116
+ continue;
117
+ }
118
+ if (/\s/.test(char)) {
119
+ if (current) {
120
+ words.push(current);
121
+ current = "";
122
+ }
123
+ continue;
124
+ }
125
+ current += char;
126
+ }
127
+ if (current) words.push(current);
128
+ return words;
491
129
  }
492
- function codexAppServerStartOptionsKey(options, params = {}) {
493
- return JSON.stringify({
494
- transport: options.transport,
495
- command: options.command,
496
- commandSource: options.commandSource ?? null,
497
- managedCommandOrder: options.managedCommandOrder ?? "package-first",
498
- managedComputerUsePluginNames: [...options.managedComputerUsePluginNames ?? []].toSorted(),
499
- managedFallbackCommandPaths: [...options.managedFallbackCommandPaths ?? []],
500
- args: options.args,
501
- cwd: options.cwd ?? null,
502
- url: options.url ?? null,
503
- authToken: hashSecretForKey(options.authToken, "authToken"),
504
- headers: Object.entries(options.headers).toSorted(([left], [right]) => left.localeCompare(right)).map(([key, value]) => [key, hashSecretForKey(value, `header:${key}`)]),
505
- env: Object.entries(options.env ?? {}).toSorted(([left], [right]) => left.localeCompare(right)).map(([key, value]) => [key, hashSecretForKey(value, `env:${key}`)]),
506
- clearEnv: [...options.clearEnv ?? []].toSorted(),
507
- authProfileId: params.authProfileId ?? null,
508
- authBindingFingerprint: params.authBindingFingerprint ?? null,
509
- agentDir: params.agentDir ?? null,
510
- fallbackApiKeyCacheKey: params.fallbackApiKeyCacheKey ?? null
511
- });
130
+ //#endregion
131
+ //#region extensions/codex/src/app-server/config-exec-policy.ts
132
+ function selectForcedPromptingSandbox(params) {
133
+ if (params.configuredSandbox === "read-only" || params.defaultSandbox === "read-only") return "read-only";
134
+ return params.defaultSandbox ?? "workspace-write";
512
135
  }
513
- function codexSandboxPolicyForTurn(mode, cwd) {
514
- if (mode === "danger-full-access") return { type: "dangerFullAccess" };
515
- if (mode === "read-only") return {
516
- type: "readOnly",
517
- networkAccess: false
518
- };
519
- return {
520
- type: "workspaceWrite",
521
- writableRoots: [cwd],
522
- networkAccess: false,
523
- excludeTmpdirEnvVar: false,
524
- excludeSlashTmp: false
525
- };
136
+ function selectForcedDangerFullAccessSandbox(params) {
137
+ if (params.configuredSandbox === "read-only") return "read-only";
138
+ if (params.defaultPolicy?.dangerFullAccessAllowed === false) {
139
+ if (params.openClawSandboxActive) return params.defaultPolicy.sandbox ?? "workspace-write";
140
+ throw new Error("legacy full exec security with ask requires Codex app-server danger-full-access");
141
+ }
142
+ return "danger-full-access";
526
143
  }
527
- /** Resolves the passive supervision control connection without changing harness defaults. */
528
- function resolveCodexSupervisionAppServerRuntimeOptions(params = {}) {
529
- const pluginConfig = readCodexPluginConfig(params.pluginConfig);
530
- const appServer = pluginConfig.appServer ?? {};
531
- const transport = resolveTransport(appServer.transport);
532
- const homeScope = appServer.homeScope ?? (transport === "websocket" ? "agent" : "user");
533
- return resolveCodexAppServerRuntimeOptions({
534
- ...params,
535
- pluginConfig: {
536
- ...pluginConfig,
537
- appServer: {
538
- ...appServer,
539
- homeScope
540
- }
541
- }
542
- });
144
+ function selectGuardianSandbox(allowedSandboxModes) {
145
+ if (allowedSandboxModes === void 0 || allowedSandboxModes.has("workspace-write")) return "workspace-write";
146
+ if (allowedSandboxModes.has("read-only")) return "read-only";
147
+ if (allowedSandboxModes.has("danger-full-access")) return "danger-full-access";
148
+ return "workspace-write";
543
149
  }
544
- function resolveCodexAppServerNetworkProxy(config, sandbox) {
545
- if (config?.enabled !== true) return {};
546
- const fileSystemMode = config.baseProfile === "read-only" || !config.baseProfile && sandbox === "read-only" ? "read" : "write";
547
- const networkConfig = removeUndefinedJsonFields({
548
- enabled: true,
549
- mode: config.mode,
550
- domains: normalizeNetworkProxyPermissionMap(config.domains),
551
- unix_sockets: normalizeNetworkProxyPermissionMap(config.unixSockets),
552
- proxy_url: readNonEmptyString(config.proxyUrl),
553
- socks_url: readNonEmptyString(config.socksUrl),
554
- enable_socks5: config.enableSocks5,
555
- enable_socks5_udp: config.enableSocks5Udp,
556
- allow_upstream_proxy: config.allowUpstreamProxy,
557
- allow_local_binding: config.allowLocalBinding,
558
- dangerously_allow_non_loopback_proxy: config.dangerouslyAllowNonLoopbackProxy,
559
- dangerously_allow_all_unix_sockets: config.dangerouslyAllowAllUnixSockets
560
- });
561
- const profile = {
562
- filesystem: {
563
- ":minimal": "read",
564
- ":project_roots": { ".": fileSystemMode }
565
- },
566
- network: networkConfig
567
- };
568
- const profileName = resolveNetworkProxyPermissionProfileName(config, profile);
569
- const configPatch = {
570
- "features.network_proxy.enabled": true,
571
- default_permissions: profileName,
572
- permissions: { [profileName]: profile }
573
- };
574
- return { networkProxy: {
575
- profileName,
576
- configFingerprint: fingerprintCodexAppServerNetworkProxyConfigPatch(configPatch),
577
- configPatch
578
- } };
150
+ function resolveApprovalPolicy(value) {
151
+ if (value === "on-failure") return "on-request";
152
+ return value === "on-request" || value === "untrusted" || value === "never" ? value : void 0;
579
153
  }
580
- function resolveNetworkProxyPermissionProfileName(config, profile) {
581
- const explicitProfileName = readNonEmptyString(config.profileName);
582
- if (explicitProfileName) return explicitProfileName;
583
- const suffix = createHash("sha256").update(stableStringifyJson({
584
- version: 1,
585
- profile
586
- })).digest("hex").slice(0, 16);
587
- return `${DEFAULT_CODEX_APP_SERVER_NETWORK_PROXY_PROFILE_PREFIX}-${suffix}`;
154
+ function resolveSandbox(value) {
155
+ return value === "read-only" || value === "workspace-write" || value === "danger-full-access" ? value : void 0;
588
156
  }
589
- function fingerprintCodexAppServerNetworkProxyConfigPatch(configPatch) {
590
- return createHash("sha256").update(stableStringifyJson(configPatch)).digest("hex");
157
+ function resolveApprovalsReviewer(value) {
158
+ return value === "auto_review" || value === "guardian_subagent" || value === "user" ? value : void 0;
591
159
  }
592
- function normalizeNetworkProxyPermissionMap(value) {
593
- const entries = Object.entries(value ?? {}).map(([key, permission]) => [key.trim(), permission]).filter(([key]) => key.length > 0);
594
- return entries.length > 0 ? Object.fromEntries(entries) : void 0;
160
+ function resolveOpenClawExecPolicyFromConfig(params) {
161
+ const root = readRecord(params.config);
162
+ const globalExec = readRecord(readRecord(root?.tools)?.exec);
163
+ const globalPolicy = applyOpenClawExecPolicyLayer(createDefaultOpenClawExecPolicy(), globalExec);
164
+ const agentId = params.agentId?.trim();
165
+ if (!agentId) return globalPolicy;
166
+ const agents = readRecord(root?.agents);
167
+ const agentList = Array.isArray(agents?.list) ? agents.list : [];
168
+ const normalizedAgentId = normalizeAgentId(agentId);
169
+ return applyOpenClawExecPolicyLayer(globalPolicy, readRecord(readRecord(readRecord(agentList.find((entry) => {
170
+ const id = readRecord(entry)?.id;
171
+ return typeof id === "string" && normalizeAgentId(id) === normalizedAgentId;
172
+ }))?.tools)?.exec));
595
173
  }
596
- function removeUndefinedJsonFields(value) {
597
- return Object.fromEntries(Object.entries(value).filter((entry) => entry[1] !== void 0));
174
+ function resolveOpenClawExecPolicyForCodexAppServer(params) {
175
+ const overridePolicy = applyOpenClawExecPolicyLayer(resolveOpenClawExecPolicyFromConfig({
176
+ config: params.config,
177
+ agentId: params.agentId
178
+ }), params.execOverrides);
179
+ return applyOpenClawExecApprovalFloors(overridePolicy, resolveOpenClawExecApprovalFloorsForCodexAppServer({
180
+ approvals: params.approvals,
181
+ agentId: params.agentId,
182
+ policy: overridePolicy
183
+ }));
598
184
  }
599
- function stableStringifyJson(value) {
600
- if (Array.isArray(value)) return `[${value.map((item) => stableStringifyJson(item)).join(",")}]`;
601
- if (value && typeof value === "object") return `{${Object.entries(value).toSorted(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${stableStringifyJson(item)}`).join(",")}}`;
602
- return JSON.stringify(value);
185
+ function resolveEffectiveOpenClawExecModeForCodexAppServer(params) {
186
+ if (params.execPolicy?.touched === true) return params.execPolicy.mode;
187
+ return params.execMode;
603
188
  }
604
- function withMcpElicitationsApprovalPolicy(policy) {
605
- if (typeof policy !== "string") return { granular: {
606
- ...policy.granular,
607
- mcp_elicitations: true
608
- } };
609
- if (policy === "never") return { granular: {
610
- mcp_elicitations: true,
611
- rules: false,
612
- sandbox_approval: false,
613
- request_permissions: false,
614
- skill_approval: false
615
- } };
616
- return { granular: {
617
- mcp_elicitations: true,
618
- rules: true,
619
- sandbox_approval: true,
620
- request_permissions: true,
621
- skill_approval: true
622
- } };
189
+ function resolveCodexPolicyModeForOpenClawExecMode(mode) {
190
+ if (!mode || mode === "full") return;
191
+ return "guardian";
623
192
  }
624
- function resolveTransport(value) {
625
- return value === "websocket" || value === "unix" ? value : "stdio";
193
+ function assertCodexAppServerAllowedForOpenClawExecMode(mode) {
194
+ if (mode === "deny" || mode === "allowlist") throw new Error(`Codex app-server local execution is not available when tools.exec.mode=${mode}`);
626
195
  }
627
- function normalizeRemoteWorkspaceRoot(value) {
628
- return readNonEmptyString(value);
196
+ function createDefaultOpenClawExecPolicy() {
197
+ return {
198
+ security: "full",
199
+ ask: "off",
200
+ touched: false
201
+ };
629
202
  }
630
- function inferCodexAppServerConnectionClass(params) {
631
- if (params.transport !== "websocket") return "local-loopback";
632
- return params.url && isLoopbackWebSocketUrl(params.url) ? "local-loopback" : "remote";
203
+ function applyOpenClawExecPolicyLayer(base, exec) {
204
+ if (!exec) return base;
205
+ const mode = readExecMode(exec.mode);
206
+ if (mode !== void 0) return {
207
+ ...resolveOpenClawExecPolicyForMode(mode),
208
+ touched: true
209
+ };
210
+ const security = readExecSecurity(exec.security);
211
+ const ask = readExecAsk(exec.ask);
212
+ if (security === void 0 && ask === void 0) return base;
213
+ const nextSecurity = security ?? base.security;
214
+ const nextAsk = ask ?? base.ask;
215
+ return {
216
+ mode: resolveOpenClawExecModeFromPolicy({
217
+ security: nextSecurity,
218
+ ask: nextAsk
219
+ }),
220
+ security: nextSecurity,
221
+ ask: nextAsk,
222
+ touched: true
223
+ };
633
224
  }
634
- function assertCodexAppServerConnectionClassConfig(params) {
635
- if (params.connectionClass === "remote" && !hasIdentityBearingWebSocketAuth({
636
- authToken: params.authToken,
637
- headers: params.headers
638
- })) throw new Error("remote Codex app-server WebSocket URLs require appServer.authToken or an Authorization header");
225
+ function resolveOpenClawExecApprovalFloorsForCodexAppServer(params) {
226
+ if (!params.approvals) return;
227
+ return resolveExecApprovalsFromFile({
228
+ file: params.approvals,
229
+ agentId: params.agentId,
230
+ overrides: {
231
+ security: params.policy.security,
232
+ ask: params.policy.ask
233
+ }
234
+ }).agent;
639
235
  }
640
- /** Applies the canonical remote-auth boundary to any Codex AppServer transport. */
641
- function assertCodexAppServerConnectionSecurity(params) {
642
- assertCodexAppServerConnectionClassConfig({
643
- connectionClass: inferCodexAppServerConnectionClass(params),
644
- authToken: params.authToken,
645
- headers: params.headers
646
- });
236
+ function applyOpenClawExecApprovalFloors(base, approvalFloors) {
237
+ if (!approvalFloors) return base;
238
+ const nextSecurity = approvalFloors.security ? minOpenClawExecSecurity(base.security, approvalFloors.security) : base.security;
239
+ const nextAsk = approvalFloors.ask ? maxOpenClawExecAsk(base.ask, approvalFloors.ask) : base.ask;
240
+ if (nextSecurity === base.security && nextAsk === base.ask) return base;
241
+ return {
242
+ mode: resolveOpenClawExecModeFromPolicy({
243
+ security: nextSecurity,
244
+ ask: nextAsk
245
+ }),
246
+ security: nextSecurity,
247
+ ask: nextAsk,
248
+ touched: true
249
+ };
647
250
  }
648
- function isLoopbackWebSocketUrl(value) {
649
- let parsed;
650
- try {
651
- parsed = new URL(value);
652
- } catch {
653
- return false;
251
+ function resolveOpenClawExecPolicyForMode(mode) {
252
+ switch (mode) {
253
+ case "deny": return {
254
+ mode,
255
+ security: "deny",
256
+ ask: "off"
257
+ };
258
+ case "allowlist": return {
259
+ mode,
260
+ security: "allowlist",
261
+ ask: "off"
262
+ };
263
+ case "ask":
264
+ case "auto": return {
265
+ mode,
266
+ security: "allowlist",
267
+ ask: "on-miss"
268
+ };
269
+ case "full": return {
270
+ mode,
271
+ security: "full",
272
+ ask: "off"
273
+ };
654
274
  }
655
- if (parsed.protocol !== "ws:" && parsed.protocol !== "wss:") return false;
656
- const host = parsed.hostname.toLowerCase();
657
- return host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "[::1]" || host.startsWith("127.");
275
+ return mode;
658
276
  }
659
- function hasIdentityBearingWebSocketAuth(params) {
660
- if (readNonEmptyString(params.authToken)) return true;
661
- return Object.entries(params.headers).some(([key, value]) => key.trim().toLowerCase() === "authorization" && Boolean(readNonEmptyString(value)));
277
+ function resolveOpenClawExecModeFromPolicy(params) {
278
+ if (params.security === "deny") return "deny";
279
+ if (params.security === "allowlist" && params.ask === "off") return "allowlist";
280
+ if (params.security === "full" && params.ask !== "always") return "full";
281
+ return "ask";
282
+ }
283
+ function minOpenClawExecSecurity(left, right) {
284
+ const order = {
285
+ deny: 0,
286
+ allowlist: 1,
287
+ full: 2
288
+ };
289
+ return order[left] <= order[right] ? left : right;
290
+ }
291
+ function maxOpenClawExecAsk(left, right) {
292
+ const order = {
293
+ off: 0,
294
+ "on-miss": 1,
295
+ always: 2
296
+ };
297
+ return order[left] >= order[right] ? left : right;
298
+ }
299
+ function readExecMode(value) {
300
+ return value === "deny" || value === "allowlist" || value === "ask" || value === "auto" || value === "full" ? value : void 0;
301
+ }
302
+ //#endregion
303
+ //#region extensions/codex/src/app-server/session-discovery-config.ts
304
+ const codexSessionCatalogConfigSchema = z.object({ enabled: z.boolean().optional() }).strict();
305
+ const codexDiscoveryConfigSchema = z.object({
306
+ enabled: z.boolean().optional(),
307
+ timeoutMs: z.number().positive().optional()
308
+ }).strict();
309
+ //#endregion
310
+ //#region extensions/codex/src/app-server/config-parsing.ts
311
+ const DEFAULT_CODEX_COMPUTER_USE_PLUGIN_NAME = "computer-use";
312
+ const DEFAULT_CODEX_COMPUTER_USE_MARKETPLACE_DISCOVERY_TIMEOUT_MS = 6e4;
313
+ const DEFAULT_CODEX_COMPUTER_USE_LIVE_TEST_TIMEOUT_MS = 6e4;
314
+ const DEFAULT_CODEX_COMPUTER_USE_TOOL_CALL_TIMEOUT_MS = 6e4;
315
+ const DEFAULT_CODEX_APP_SERVER_NETWORK_PROXY_PROFILE_PREFIX = "openclaw-network";
316
+ const codexAppServerTransportSchema = z.enum([
317
+ "stdio",
318
+ "websocket",
319
+ "unix"
320
+ ]);
321
+ const codexAppServerHomeScopeSchema = z.enum(["agent", "user"]);
322
+ const SecretInputSchema = buildSecretInputSchema();
323
+ const codexAppServerPolicyModeSchema = z.enum(["yolo", "guardian"]);
324
+ const codexAppServerApprovalPolicySchema = z.preprocess((value) => value === "on-failure" ? "on-request" : value, z.enum([
325
+ "never",
326
+ "on-request",
327
+ "untrusted"
328
+ ]));
329
+ const codexAppServerSandboxSchema = z.enum([
330
+ "read-only",
331
+ "workspace-write",
332
+ "danger-full-access"
333
+ ]);
334
+ const codexAppServerApprovalsReviewerSchema = z.enum([
335
+ "user",
336
+ "auto_review",
337
+ "guardian_subagent"
338
+ ]);
339
+ const codexDynamicToolsLoadingSchema = z.enum(["searchable", "direct"]);
340
+ const codexComputerUseHealthIntervalSchema = z.union([
341
+ z.literal(30),
342
+ z.literal(60),
343
+ z.literal(120),
344
+ z.literal(240)
345
+ ]);
346
+ const codexComputerUsePluginCacheModeSchema = z.enum(["shared", "independent"]);
347
+ const codexPluginDestructivePolicySchema = z.union([
348
+ z.boolean(),
349
+ z.literal("auto"),
350
+ z.literal("ask")
351
+ ]);
352
+ const codexAppServerServiceTierSchema = z.preprocess((value) => value === null ? null : normalizeCodexServiceTier(value), z.string().trim().min(1).nullable().optional()).optional();
353
+ const codexAppServerExperimentalSchema = z.object({ sandboxExecServer: z.boolean().optional() }).strict();
354
+ const codexAppServerRemoteWorkspaceRootSchema = z.string().trim().min(1);
355
+ const codexAppServerNetworkProxyDomainPermissionSchema = z.enum(["allow", "deny"]);
356
+ const codexAppServerNetworkProxyUnixSocketPermissionSchema = z.enum(["allow", "none"]);
357
+ const codexAppServerNetworkProxySchema = z.object({
358
+ enabled: z.boolean().optional(),
359
+ profileName: z.string().trim().min(1).optional(),
360
+ baseProfile: z.enum(["read-only", "workspace"]).optional(),
361
+ mode: z.enum(["limited", "full"]).optional(),
362
+ domains: z.record(z.string(), codexAppServerNetworkProxyDomainPermissionSchema).optional(),
363
+ unixSockets: z.record(z.string(), codexAppServerNetworkProxyUnixSocketPermissionSchema).optional(),
364
+ proxyUrl: z.string().trim().min(1).optional(),
365
+ socksUrl: z.string().trim().min(1).optional(),
366
+ enableSocks5: z.boolean().optional(),
367
+ enableSocks5Udp: z.boolean().optional(),
368
+ allowUpstreamProxy: z.boolean().optional(),
369
+ allowLocalBinding: z.boolean().optional(),
370
+ dangerouslyAllowNonLoopbackProxy: z.boolean().optional(),
371
+ dangerouslyAllowAllUnixSockets: z.boolean().optional()
372
+ }).strict();
373
+ const codexPluginEntryConfigSchema = z.object({
374
+ enabled: z.boolean().optional(),
375
+ marketplaceName: z.enum([CODEX_PLUGINS_MARKETPLACE_NAME, CODEX_PLUGINS_WORKSPACE_MARKETPLACE_NAME]).optional(),
376
+ pluginName: z.string().trim().min(1).optional(),
377
+ allow_destructive_actions: codexPluginDestructivePolicySchema.optional()
378
+ }).strict();
379
+ const codexPluginsConfigSchema = z.object({
380
+ enabled: z.boolean().optional(),
381
+ allow_all_plugins: z.boolean().optional(),
382
+ allow_destructive_actions: codexPluginDestructivePolicySchema.optional(),
383
+ plugins: z.record(z.string(), codexPluginEntryConfigSchema).optional()
384
+ }).strict();
385
+ const codexSupervisionEndpointSchema = z.union([z.object({
386
+ id: z.string().optional(),
387
+ label: z.string().optional(),
388
+ transport: z.literal("stdio-proxy").optional(),
389
+ command: z.string().optional(),
390
+ args: z.array(z.string()).optional(),
391
+ cwd: z.string().optional()
392
+ }).strict(), z.object({
393
+ id: z.string().optional(),
394
+ label: z.string().optional(),
395
+ transport: z.literal("websocket"),
396
+ url: z.string(),
397
+ authTokenEnv: z.string().optional()
398
+ }).strict()]);
399
+ const codexSupervisionConfigSchema = z.object({
400
+ enabled: z.boolean().optional(),
401
+ endpoints: z.array(codexSupervisionEndpointSchema).optional(),
402
+ allowRawTranscripts: z.boolean().optional(),
403
+ allowWriteControls: z.boolean().optional()
404
+ }).strict();
405
+ const codexPluginConfigSchema = z.object({
406
+ codexDynamicToolsLoading: codexDynamicToolsLoadingSchema.optional(),
407
+ codexDynamicToolsExclude: z.array(z.string()).optional(),
408
+ sessionCatalog: codexSessionCatalogConfigSchema.optional(),
409
+ discovery: codexDiscoveryConfigSchema.optional(),
410
+ computerUse: z.object({
411
+ enabled: z.boolean().optional(),
412
+ autoInstall: z.boolean().optional(),
413
+ marketplaceDiscoveryTimeoutMs: z.number().positive().optional(),
414
+ liveTestTimeoutMs: z.number().positive().optional(),
415
+ toolCallTimeoutMs: z.number().positive().optional(),
416
+ healthCheckEnabled: z.boolean().optional(),
417
+ healthCheckIntervalMinutes: codexComputerUseHealthIntervalSchema.optional(),
418
+ pluginCacheMode: codexComputerUsePluginCacheModeSchema.optional(),
419
+ strictReadiness: z.boolean().optional(),
420
+ autoRepair: z.boolean().optional(),
421
+ marketplaceSource: z.string().optional(),
422
+ marketplacePath: z.string().optional(),
423
+ marketplaceName: z.string().optional(),
424
+ pluginName: z.string().optional(),
425
+ mcpServerName: z.string().optional()
426
+ }).strict().optional(),
427
+ codexPlugins: z.unknown().optional(),
428
+ supervision: codexSupervisionConfigSchema.optional(),
429
+ appServer: z.object({
430
+ mode: codexAppServerPolicyModeSchema.optional(),
431
+ transport: codexAppServerTransportSchema.optional(),
432
+ homeScope: codexAppServerHomeScopeSchema.optional(),
433
+ command: z.string().optional(),
434
+ args: z.union([z.array(z.string()), z.string()]).optional(),
435
+ url: z.string().optional(),
436
+ authToken: SecretInputSchema.optional(),
437
+ headers: z.record(z.string(), SecretInputSchema).optional(),
438
+ clearEnv: z.array(z.string()).optional(),
439
+ remoteWorkspaceRoot: codexAppServerRemoteWorkspaceRootSchema.optional(),
440
+ codeModeOnly: z.boolean().optional(),
441
+ loopDetectionPreToolUseRelay: z.boolean().optional(),
442
+ requestTimeoutMs: z.number().positive().optional(),
443
+ turnCompletionIdleTimeoutMs: z.number().positive().optional(),
444
+ turnAssistantCompletionIdleTimeoutMs: z.number().positive().optional(),
445
+ postToolRawAssistantCompletionIdleTimeoutMs: z.number().positive().optional(),
446
+ approvalPolicy: codexAppServerApprovalPolicySchema.optional(),
447
+ sandbox: codexAppServerSandboxSchema.optional(),
448
+ approvalsReviewer: codexAppServerApprovalsReviewerSchema.optional(),
449
+ serviceTier: codexAppServerServiceTierSchema,
450
+ networkProxy: codexAppServerNetworkProxySchema.optional(),
451
+ defaultWorkspaceDir: z.string().optional(),
452
+ experimental: codexAppServerExperimentalSchema.optional()
453
+ }).strict().optional()
454
+ }).strict();
455
+ function readCodexPluginConfig(value) {
456
+ const parsed = codexPluginConfigSchema.safeParse(value);
457
+ if (!parsed.success) return {};
458
+ const { codexPlugins: rawCodexPlugins, ...config } = parsed.data;
459
+ const plugins = codexPluginsConfigSchema.safeParse(rawCodexPlugins);
460
+ if (!plugins.success) return config;
461
+ return {
462
+ ...config,
463
+ ...plugins.data ? { codexPlugins: plugins.data } : {}
464
+ };
465
+ }
466
+ function isCodexSandboxExecServerEnabled(pluginConfig) {
467
+ return readCodexPluginConfig(pluginConfig).appServer?.experimental?.sandboxExecServer === true;
662
468
  }
663
- function resolvePolicyMode(value) {
664
- return value === "guardian" || value === "yolo" ? value : void 0;
469
+ function assertCodexAppServerCommandHasNoInlineArgs(params) {
470
+ const inlineArgs = detectWindowsSpawnCommandInlineArgs(params.command);
471
+ if (!inlineArgs) return;
472
+ const sourceLabel = params.source === "env" ? "OPENCLAW_CODEX_APP_SERVER_BIN" : "plugins.entries.codex.config.appServer.command";
473
+ const argsLabel = params.source === "env" ? "OPENCLAW_CODEX_APP_SERVER_ARGS" : "plugins.entries.codex.config.appServer.args";
474
+ throw new Error(`${sourceLabel} must be only the Codex app-server executable path; "${inlineArgs.executable}" was configured with inline arguments "${inlineArgs.arguments}". Move those arguments to ${argsLabel}, or remove the override to use the managed Codex startup path.`);
665
475
  }
666
- function resolveDefaultCodexAppServerPolicy(params) {
667
- if (params.transport !== "stdio") return {
668
- mode: "yolo",
669
- dangerFullAccessAllowed: true
476
+ function resolveCodexPluginsPolicy(pluginConfig) {
477
+ const config = readCodexPluginConfig(pluginConfig).codexPlugins;
478
+ const configured = config !== void 0;
479
+ const enabled = config?.enabled === true;
480
+ const destructivePolicy = resolveCodexPluginDestructivePolicy(config?.allow_destructive_actions ?? true);
481
+ const pluginPolicies = Object.entries(config?.plugins ?? {}).flatMap(([configKey, entry]) => {
482
+ if (!isCodexPluginMarketplaceName(entry.marketplaceName) || !entry.pluginName) return [];
483
+ const entryDestructivePolicy = resolveCodexPluginDestructivePolicy(entry.allow_destructive_actions ?? config?.allow_destructive_actions ?? true);
484
+ return [{
485
+ configKey,
486
+ marketplaceName: entry.marketplaceName,
487
+ pluginName: entry.pluginName,
488
+ enabled: enabled && entry.enabled !== false,
489
+ allowDestructiveActions: entryDestructivePolicy.allowDestructiveActions,
490
+ destructiveApprovalMode: entryDestructivePolicy.destructiveApprovalMode
491
+ }];
492
+ }).toSorted((left, right) => left.configKey.localeCompare(right.configKey));
493
+ return {
494
+ configured,
495
+ enabled,
496
+ allowAllPlugins: enabled && config?.allow_all_plugins === true,
497
+ allowDestructiveActions: destructivePolicy.allowDestructiveActions,
498
+ destructiveApprovalMode: destructivePolicy.destructiveApprovalMode,
499
+ pluginPolicies
670
500
  };
671
- const content = readCodexRequirementsToml(params);
672
- if (content === void 0) {
673
- if (!params.forceGuardian) return {
674
- mode: "yolo",
675
- dangerFullAccessAllowed: true
676
- };
677
- return {
678
- mode: "guardian",
679
- dangerFullAccessAllowed: true,
680
- approvalPolicy: selectGuardianApprovalPolicy(void 0, params.execModeRequiringPromptingApprovals),
681
- approvalsReviewer: params.forceUserReviewer ? selectUserApprovalsReviewer(void 0, params.execModeRequiringUserReviewer) : selectGuardianApprovalsReviewer(void 0, params.execModeRequiringPromptingApprovals === "auto" ? "auto" : void 0),
682
- sandbox: selectGuardianSandbox(void 0)
683
- };
684
- }
685
- const allowedSandboxModes = parseAllowedSandboxModesFromCodexRequirements(content, readNonEmptyString(params.hostName) ?? hostname());
686
- const allowedApprovalPolicies = parseAllowedApprovalPoliciesFromCodexRequirements(content);
687
- const allowedApprovalsReviewers = parseAllowedApprovalsReviewersFromCodexRequirements(content);
688
- const yoloSandboxAllowed = allowedSandboxModes === void 0 || allowedSandboxModes.has("danger-full-access");
689
- const yoloApprovalAllowed = allowedApprovalPolicies === void 0 || allowedApprovalPolicies.has("never");
690
- const yoloReviewerAllowed = allowedApprovalsReviewers === void 0 || allowedApprovalsReviewers.has("user");
691
- if (!params.forceGuardian && yoloSandboxAllowed && yoloApprovalAllowed && yoloReviewerAllowed) return {
692
- mode: "yolo",
693
- dangerFullAccessAllowed: true
501
+ }
502
+ function isCodexPluginMarketplaceName(value) {
503
+ return value === "openai-curated" || value === "workspace-directory";
504
+ }
505
+ function resolveCodexPluginDestructivePolicy(policy) {
506
+ if (policy === "auto" || policy === "ask") return {
507
+ allowDestructiveActions: true,
508
+ destructiveApprovalMode: policy
694
509
  };
695
510
  return {
696
- mode: "guardian",
697
- dangerFullAccessAllowed: yoloSandboxAllowed,
698
- approvalPolicy: selectGuardianApprovalPolicy(allowedApprovalPolicies, params.execModeRequiringPromptingApprovals),
699
- approvalsReviewer: params.forceUserReviewer ? selectUserApprovalsReviewer(allowedApprovalsReviewers, params.execModeRequiringUserReviewer) : selectGuardianApprovalsReviewer(allowedApprovalsReviewers, params.execModeRequiringPromptingApprovals === "auto" ? "auto" : void 0),
700
- sandbox: selectGuardianSandbox(allowedSandboxModes)
511
+ allowDestructiveActions: policy,
512
+ destructiveApprovalMode: policy ? "allow" : "deny"
701
513
  };
702
514
  }
515
+ //#endregion
516
+ //#region extensions/codex/src/app-server/config-requirements.ts
517
+ const UNIX_CODEX_REQUIREMENTS_PATH = "/etc/codex/requirements.toml";
518
+ const WINDOWS_CODEX_REQUIREMENTS_SUFFIX = "\\OpenAI\\Codex\\requirements.toml";
519
+ function isCodexAppServerApprovalPolicyAllowedByRequirements(policy, params = {}) {
520
+ const content = readCodexRequirementsToml(params);
521
+ if (content === void 0) return true;
522
+ const allowedApprovalPolicies = parseAllowedApprovalPoliciesFromCodexRequirements(content);
523
+ return allowedApprovalPolicies === void 0 || allowedApprovalPolicies.has(policy);
524
+ }
703
525
  function readCodexRequirementsToml(params) {
704
526
  if (params.requirementsToml !== void 0) return params.requirementsToml ?? void 0;
705
527
  const requirementsPath = readNonEmptyString(params.requirementsPath) ?? resolveCodexRequirementsPath(params.env ?? process.env, params.platform ?? process.platform);
@@ -889,6 +711,52 @@ function selectUserApprovalsReviewer(allowedApprovalsReviewers, execModeRequirin
889
711
  if (allowedApprovalsReviewers === void 0 || allowedApprovalsReviewers.has("user")) return "user";
890
712
  throw new Error(`tools.exec.mode=${execModeRequiringUserReviewer ?? "ask"} requires Codex app-server user approvals`);
891
713
  }
714
+ //#endregion
715
+ //#region extensions/codex/src/app-server/config-reviewer.ts
716
+ const CODEX_APP_SERVER_HOME_DIRNAME = "codex-home";
717
+ const CODEX_CONFIG_TOML_FILENAME = "config.toml";
718
+ function canUseCodexModelBackedApprovalsReviewerForModel(params) {
719
+ const explicitProvider = params.modelProvider?.trim().toLowerCase();
720
+ const inferredProvider = inferProviderFromModelRef(params.model);
721
+ if (explicitProvider && explicitProvider !== "codex") return isTrustedCodexModelBackedApprovalsReviewerProvider(explicitProvider, params) && (inferredProvider === void 0 || isTrustedCodexModelBackedApprovalsReviewerProvider(inferredProvider, params));
722
+ if (inferredProvider !== void 0) return isTrustedCodexModelBackedApprovalsReviewerProvider(inferredProvider, params);
723
+ return isTrustedCodexModelBackedApprovalsReviewerProvider(explicitProvider, params);
724
+ }
725
+ function isTrustedCodexModelBackedOpenAIProvider(params) {
726
+ if (!openAIBaseUrlEnvOverridesAreTrustedForModelBackedReview(params.env)) return false;
727
+ const codexBaseUrlOverrides = readCodexBaseUrlOverridesForModelBackedReview(params);
728
+ if (codexBaseUrlOverrides === false || !codexBaseUrlOverrides.openAI.every(isNativeOpenAIBaseUrl) || !codexBaseUrlOverrides.chatGPT.every(isNativeChatGPTBaseUrl)) return false;
729
+ const openAIProviders = readConfiguredOpenAIProvidersForModelBackedReview(params.config);
730
+ if (openAIProviders.length === 0) return true;
731
+ return openAIProviders.every((openAIProvider) => configuredOpenAIProviderIsTrustedForModelBackedReview(openAIProvider, params.model));
732
+ }
733
+ function resolveCodexModelBackedReviewerPolicyContext(params) {
734
+ const provider = params.provider?.trim();
735
+ if (provider && provider.toLowerCase() !== "codex") return {
736
+ modelProvider: normalizeCodexModelBackedReviewerPolicyProvider(provider),
737
+ model: params.model
738
+ };
739
+ const bindingModelProvider = params.bindingModelProvider?.trim();
740
+ const currentModel = params.model?.trim();
741
+ const bindingModel = params.bindingModel?.trim();
742
+ if (bindingModelProvider && currentModel && bindingModel && currentModel === bindingModel) return {
743
+ modelProvider: normalizeCodexModelBackedReviewerPolicyProvider(bindingModelProvider),
744
+ model: params.model ?? params.bindingModel
745
+ };
746
+ const currentModelProvider = inferProviderFromModelRef(params.model);
747
+ if (currentModelProvider) return {
748
+ modelProvider: normalizeCodexModelBackedReviewerPolicyProvider(currentModelProvider),
749
+ model: params.model
750
+ };
751
+ if (bindingModelProvider) return {
752
+ modelProvider: normalizeCodexModelBackedReviewerPolicyProvider(bindingModelProvider),
753
+ model: params.model ?? params.bindingModel
754
+ };
755
+ return {
756
+ modelProvider: params.nativeAuthProfile === true ? "openai" : void 0,
757
+ model: params.model ?? params.bindingModel
758
+ };
759
+ }
892
760
  function isCodexModelBackedApprovalsReviewerProvider(provider) {
893
761
  return provider?.trim().toLowerCase() === "openai";
894
762
  }
@@ -1041,278 +909,435 @@ function inferProviderFromModelRef(model) {
1041
909
  const slashIndex = normalized?.indexOf("/") ?? -1;
1042
910
  return slashIndex > 0 ? normalized?.slice(0, slashIndex) : void 0;
1043
911
  }
1044
- function selectForcedPromptingSandbox(params) {
1045
- if (params.configuredSandbox === "read-only" || params.defaultSandbox === "read-only") return "read-only";
1046
- return params.defaultSandbox ?? "workspace-write";
912
+ //#endregion
913
+ //#region extensions/codex/src/app-server/config-security.ts
914
+ function shouldAutoApproveCodexAppServerApprovals(appServer) {
915
+ return appServer.networkProxy === void 0 && appServer.approvalPolicy === "never" && appServer.sandbox === "danger-full-access";
1047
916
  }
1048
- function selectForcedDangerFullAccessSandbox(params) {
1049
- if (params.configuredSandbox === "read-only") return "read-only";
1050
- if (params.defaultPolicy?.dangerFullAccessAllowed === false) {
1051
- if (params.openClawSandboxActive) return params.defaultPolicy.sandbox ?? "workspace-write";
1052
- throw new Error("legacy full exec security with ask requires Codex app-server danger-full-access");
1053
- }
1054
- return "danger-full-access";
917
+ function resolveCodexAppServerNetworkProxy(config, sandbox) {
918
+ if (config?.enabled !== true) return {};
919
+ const fileSystemMode = config.baseProfile === "read-only" || !config.baseProfile && sandbox === "read-only" ? "read" : "write";
920
+ const networkConfig = removeUndefinedJsonFields({
921
+ enabled: true,
922
+ mode: config.mode,
923
+ domains: normalizeNetworkProxyPermissionMap(config.domains),
924
+ unix_sockets: normalizeNetworkProxyPermissionMap(config.unixSockets),
925
+ proxy_url: readNonEmptyString(config.proxyUrl),
926
+ socks_url: readNonEmptyString(config.socksUrl),
927
+ enable_socks5: config.enableSocks5,
928
+ enable_socks5_udp: config.enableSocks5Udp,
929
+ allow_upstream_proxy: config.allowUpstreamProxy,
930
+ allow_local_binding: config.allowLocalBinding,
931
+ dangerously_allow_non_loopback_proxy: config.dangerouslyAllowNonLoopbackProxy,
932
+ dangerously_allow_all_unix_sockets: config.dangerouslyAllowAllUnixSockets
933
+ });
934
+ const profile = {
935
+ filesystem: {
936
+ ":minimal": "read",
937
+ ":project_roots": { ".": fileSystemMode }
938
+ },
939
+ network: networkConfig
940
+ };
941
+ const profileName = resolveNetworkProxyPermissionProfileName(config, profile);
942
+ const configPatch = {
943
+ "features.network_proxy.enabled": true,
944
+ default_permissions: profileName,
945
+ permissions: { [profileName]: profile }
946
+ };
947
+ return { networkProxy: {
948
+ profileName,
949
+ configFingerprint: fingerprintCodexAppServerNetworkProxyConfigPatch(configPatch),
950
+ configPatch
951
+ } };
1055
952
  }
1056
- function selectGuardianSandbox(allowedSandboxModes) {
1057
- if (allowedSandboxModes === void 0 || allowedSandboxModes.has("workspace-write")) return "workspace-write";
1058
- if (allowedSandboxModes.has("read-only")) return "read-only";
1059
- if (allowedSandboxModes.has("danger-full-access")) return "danger-full-access";
1060
- return "workspace-write";
953
+ function resolveNetworkProxyPermissionProfileName(config, profile) {
954
+ const explicitProfileName = readNonEmptyString(config.profileName);
955
+ if (explicitProfileName) return explicitProfileName;
956
+ return `${DEFAULT_CODEX_APP_SERVER_NETWORK_PROXY_PROFILE_PREFIX}-${createHash("sha256").update(stableStringifyJson({
957
+ version: 1,
958
+ profile
959
+ })).digest("hex").slice(0, 16)}`;
1061
960
  }
1062
- function resolveApprovalPolicy(value) {
1063
- if (value === "on-failure") return "on-request";
1064
- return value === "on-request" || value === "untrusted" || value === "never" ? value : void 0;
961
+ function fingerprintCodexAppServerNetworkProxyConfigPatch(configPatch) {
962
+ return createHash("sha256").update(stableStringifyJson(configPatch)).digest("hex");
1065
963
  }
1066
- function resolveSandbox(value) {
1067
- return value === "read-only" || value === "workspace-write" || value === "danger-full-access" ? value : void 0;
964
+ function normalizeNetworkProxyPermissionMap(value) {
965
+ const entries = Object.entries(value ?? {}).map(([key, permission]) => [key.trim(), permission]).filter(([key]) => key.length > 0);
966
+ return entries.length > 0 ? Object.fromEntries(entries) : void 0;
1068
967
  }
1069
- function resolveApprovalsReviewer(value) {
1070
- return value === "auto_review" || value === "guardian_subagent" || value === "user" ? value : void 0;
968
+ function removeUndefinedJsonFields(value) {
969
+ return Object.fromEntries(Object.entries(value).filter((entry) => entry[1] !== void 0));
1071
970
  }
1072
- function resolveOpenClawExecPolicyFromConfig(params) {
1073
- const root = readRecord(params.config);
1074
- const globalExec = readRecord(readRecord(root?.tools)?.exec);
1075
- const globalPolicy = applyOpenClawExecPolicyLayer(createDefaultOpenClawExecPolicy(), globalExec);
1076
- const agentId = params.agentId?.trim();
1077
- if (!agentId) return globalPolicy;
1078
- const agents = readRecord(root?.agents);
1079
- const agentList = Array.isArray(agents?.list) ? agents.list : [];
1080
- const normalizedAgentId = normalizeAgentId(agentId);
1081
- return applyOpenClawExecPolicyLayer(globalPolicy, readRecord(readRecord(readRecord(agentList.find((entry) => {
1082
- const id = readRecord(entry)?.id;
1083
- return typeof id === "string" && normalizeAgentId(id) === normalizedAgentId;
1084
- }))?.tools)?.exec));
971
+ function stableStringifyJson(value) {
972
+ if (Array.isArray(value)) return `[${value.map((item) => stableStringifyJson(item)).join(",")}]`;
973
+ if (value && typeof value === "object") return `{${Object.entries(value).toSorted(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${stableStringifyJson(item)}`).join(",")}}`;
974
+ return JSON.stringify(value);
1085
975
  }
1086
- function resolveOpenClawExecPolicyForCodexAppServer(params) {
1087
- const overridePolicy = applyOpenClawExecPolicyLayer(resolveOpenClawExecPolicyFromConfig({
1088
- config: params.config,
1089
- agentId: params.agentId
1090
- }), params.execOverrides);
1091
- return applyOpenClawExecApprovalFloors(overridePolicy, resolveOpenClawExecApprovalFloorsForCodexAppServer({
1092
- approvals: params.approvals,
1093
- agentId: params.agentId,
1094
- policy: overridePolicy
1095
- }));
976
+ function withMcpElicitationsApprovalPolicy(policy) {
977
+ if (typeof policy !== "string") return { granular: {
978
+ ...policy.granular,
979
+ mcp_elicitations: true
980
+ } };
981
+ if (policy === "never") return { granular: {
982
+ mcp_elicitations: true,
983
+ rules: false,
984
+ sandbox_approval: false,
985
+ request_permissions: false,
986
+ skill_approval: false
987
+ } };
988
+ return { granular: {
989
+ mcp_elicitations: true,
990
+ rules: true,
991
+ sandbox_approval: true,
992
+ request_permissions: true,
993
+ skill_approval: true
994
+ } };
1096
995
  }
1097
- function resolveEffectiveOpenClawExecModeForCodexAppServer(params) {
1098
- if (params.execPolicy?.touched === true) return params.execPolicy.mode;
1099
- return params.execMode;
996
+ function resolveTransport(value) {
997
+ return value === "websocket" || value === "unix" ? value : "stdio";
998
+ }
999
+ function normalizeRemoteWorkspaceRoot(value) {
1000
+ return readNonEmptyString(value);
1001
+ }
1002
+ function inferCodexAppServerConnectionClass(params) {
1003
+ if (params.transport !== "websocket") return "local-loopback";
1004
+ return params.url && isLoopbackWebSocketUrl(params.url) ? "local-loopback" : "remote";
1100
1005
  }
1101
- function resolveCodexPolicyModeForOpenClawExecMode(mode) {
1102
- if (!mode || mode === "full") return;
1103
- return "guardian";
1006
+ function assertCodexAppServerConnectionClassConfig(params) {
1007
+ if (params.connectionClass === "remote" && !hasIdentityBearingWebSocketAuth({
1008
+ authToken: params.authToken,
1009
+ headers: params.headers
1010
+ })) throw new Error("remote Codex app-server WebSocket URLs require appServer.authToken or an Authorization header");
1104
1011
  }
1105
- function assertCodexAppServerAllowedForOpenClawExecMode(mode) {
1106
- if (mode === "deny" || mode === "allowlist") throw new Error(`Codex app-server local execution is not available when tools.exec.mode=${mode}`);
1012
+ /** Applies the canonical remote-auth boundary to any Codex AppServer transport. */
1013
+ function assertCodexAppServerConnectionSecurity(params) {
1014
+ assertCodexAppServerConnectionClassConfig({
1015
+ connectionClass: inferCodexAppServerConnectionClass(params),
1016
+ authToken: params.authToken,
1017
+ headers: params.headers
1018
+ });
1107
1019
  }
1108
- function createDefaultOpenClawExecPolicy() {
1109
- return {
1110
- security: "full",
1111
- ask: "off",
1112
- touched: false
1113
- };
1020
+ function isLoopbackWebSocketUrl(value) {
1021
+ let parsed;
1022
+ try {
1023
+ parsed = new URL(value);
1024
+ } catch {
1025
+ return false;
1026
+ }
1027
+ if (parsed.protocol !== "ws:" && parsed.protocol !== "wss:") return false;
1028
+ const host = parsed.hostname.toLowerCase();
1029
+ return host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "[::1]" || host.startsWith("127.");
1114
1030
  }
1115
- function applyOpenClawExecPolicyLayer(base, exec) {
1116
- if (!exec) return base;
1117
- const mode = readExecMode(exec.mode);
1118
- if (mode !== void 0) return {
1119
- ...resolveOpenClawExecPolicyForMode(mode),
1120
- touched: true
1121
- };
1122
- const security = readExecSecurity(exec.security);
1123
- const ask = readExecAsk(exec.ask);
1124
- if (security === void 0 && ask === void 0) return base;
1125
- const nextSecurity = security ?? base.security;
1126
- const nextAsk = ask ?? base.ask;
1127
- return {
1128
- mode: resolveOpenClawExecModeFromPolicy({
1129
- security: nextSecurity,
1130
- ask: nextAsk
1131
- }),
1132
- security: nextSecurity,
1133
- ask: nextAsk,
1134
- touched: true
1135
- };
1031
+ function hasIdentityBearingWebSocketAuth(params) {
1032
+ if (readNonEmptyString(params.authToken)) return true;
1033
+ return Object.entries(params.headers).some(([key, value]) => key.trim().toLowerCase() === "authorization" && Boolean(readNonEmptyString(value)));
1136
1034
  }
1137
- function resolveOpenClawExecApprovalFloorsForCodexAppServer(params) {
1138
- if (!params.approvals) return;
1139
- return resolveExecApprovalsFromFile({
1140
- file: params.approvals,
1141
- agentId: params.agentId,
1142
- overrides: {
1143
- security: params.policy.security,
1144
- ask: params.policy.ask
1145
- }
1146
- }).agent;
1035
+ function resolvePolicyMode(value) {
1036
+ return value === "guardian" || value === "yolo" ? value : void 0;
1147
1037
  }
1148
- function applyOpenClawExecApprovalFloors(base, approvalFloors) {
1149
- if (!approvalFloors) return base;
1150
- const nextSecurity = approvalFloors.security ? minOpenClawExecSecurity(base.security, approvalFloors.security) : base.security;
1151
- const nextAsk = approvalFloors.ask ? maxOpenClawExecAsk(base.ask, approvalFloors.ask) : base.ask;
1152
- if (nextSecurity === base.security && nextAsk === base.ask) return base;
1153
- return {
1154
- mode: resolveOpenClawExecModeFromPolicy({
1155
- security: nextSecurity,
1156
- ask: nextAsk
1157
- }),
1158
- security: nextSecurity,
1159
- ask: nextAsk,
1160
- touched: true
1038
+ function resolveDefaultCodexAppServerPolicy(params) {
1039
+ if (params.transport !== "stdio") return {
1040
+ mode: "yolo",
1041
+ dangerFullAccessAllowed: true
1161
1042
  };
1162
- }
1163
- function resolveOpenClawExecPolicyForMode(mode) {
1164
- switch (mode) {
1165
- case "deny": return {
1166
- mode,
1167
- security: "deny",
1168
- ask: "off"
1169
- };
1170
- case "allowlist": return {
1171
- mode,
1172
- security: "allowlist",
1173
- ask: "off"
1174
- };
1175
- case "ask":
1176
- case "auto": return {
1177
- mode,
1178
- security: "allowlist",
1179
- ask: "on-miss"
1043
+ const content = readCodexRequirementsToml(params);
1044
+ if (content === void 0) {
1045
+ if (!params.forceGuardian) return {
1046
+ mode: "yolo",
1047
+ dangerFullAccessAllowed: true
1180
1048
  };
1181
- case "full": return {
1182
- mode,
1183
- security: "full",
1184
- ask: "off"
1049
+ return {
1050
+ mode: "guardian",
1051
+ dangerFullAccessAllowed: true,
1052
+ approvalPolicy: selectGuardianApprovalPolicy(void 0, params.execModeRequiringPromptingApprovals),
1053
+ approvalsReviewer: params.forceUserReviewer ? selectUserApprovalsReviewer(void 0, params.execModeRequiringUserReviewer) : selectGuardianApprovalsReviewer(void 0, params.execModeRequiringPromptingApprovals === "auto" ? "auto" : void 0),
1054
+ sandbox: selectGuardianSandbox(void 0)
1185
1055
  };
1186
1056
  }
1187
- return mode;
1188
- }
1189
- function resolveOpenClawExecModeFromPolicy(params) {
1190
- if (params.security === "deny") return "deny";
1191
- if (params.security === "allowlist" && params.ask === "off") return "allowlist";
1192
- if (params.security === "full" && params.ask !== "always") return "full";
1193
- return "ask";
1057
+ const allowedSandboxModes = parseAllowedSandboxModesFromCodexRequirements(content, readNonEmptyString(params.hostName) ?? hostname());
1058
+ const allowedApprovalPolicies = parseAllowedApprovalPoliciesFromCodexRequirements(content);
1059
+ const allowedApprovalsReviewers = parseAllowedApprovalsReviewersFromCodexRequirements(content);
1060
+ const yoloSandboxAllowed = allowedSandboxModes === void 0 || allowedSandboxModes.has("danger-full-access");
1061
+ const yoloApprovalAllowed = allowedApprovalPolicies === void 0 || allowedApprovalPolicies.has("never");
1062
+ const yoloReviewerAllowed = allowedApprovalsReviewers === void 0 || allowedApprovalsReviewers.has("user");
1063
+ if (!params.forceGuardian && yoloSandboxAllowed && yoloApprovalAllowed && yoloReviewerAllowed) return {
1064
+ mode: "yolo",
1065
+ dangerFullAccessAllowed: true
1066
+ };
1067
+ return {
1068
+ mode: "guardian",
1069
+ dangerFullAccessAllowed: yoloSandboxAllowed,
1070
+ approvalPolicy: selectGuardianApprovalPolicy(allowedApprovalPolicies, params.execModeRequiringPromptingApprovals),
1071
+ approvalsReviewer: params.forceUserReviewer ? selectUserApprovalsReviewer(allowedApprovalsReviewers, params.execModeRequiringUserReviewer) : selectGuardianApprovalsReviewer(allowedApprovalsReviewers, params.execModeRequiringPromptingApprovals === "auto" ? "auto" : void 0),
1072
+ sandbox: selectGuardianSandbox(allowedSandboxModes)
1073
+ };
1194
1074
  }
1195
- function minOpenClawExecSecurity(left, right) {
1196
- const order = {
1197
- deny: 0,
1198
- allowlist: 1,
1199
- full: 2
1075
+ //#endregion
1076
+ //#region extensions/codex/src/app-server/config-runtime.ts
1077
+ function resolveCodexAppServerRuntimeOptions(params = {}) {
1078
+ const env = params.env ?? process.env;
1079
+ const config = readCodexPluginConfig(params.pluginConfig).appServer ?? {};
1080
+ const transport = resolveTransport(config.transport);
1081
+ const homeScope = config.homeScope ?? "agent";
1082
+ const configCommand = readNonEmptyString(config.command);
1083
+ const envCommand = readNonEmptyString(env.OPENCLAW_CODEX_APP_SERVER_BIN);
1084
+ const command = configCommand ?? envCommand ?? "codex";
1085
+ const commandSource = configCommand ? "config" : envCommand ? "env" : "managed";
1086
+ if (commandSource === "config" || commandSource === "env") assertCodexAppServerCommandHasNoInlineArgs({
1087
+ command,
1088
+ source: commandSource
1089
+ });
1090
+ const args = resolveArgs(config.args, env.OPENCLAW_CODEX_APP_SERVER_ARGS);
1091
+ const headers = normalizeHeaders(config.headers);
1092
+ const clearEnv = normalizeStringList(config.clearEnv);
1093
+ const authToken = normalizeCodexAppServerSecretInput({
1094
+ value: config.authToken,
1095
+ path: "plugins.entries.codex.config.appServer.authToken"
1096
+ });
1097
+ const url = readNonEmptyString(config.url) ?? (transport === "unix" ? "unix://" : void 0);
1098
+ const connectionClass = inferCodexAppServerConnectionClass({
1099
+ transport,
1100
+ url
1101
+ });
1102
+ const remoteAppsSubstrate = "preconfigured";
1103
+ const remoteWorkspaceRoot = normalizeRemoteWorkspaceRoot(config.remoteWorkspaceRoot);
1104
+ const execMode = resolveEffectiveOpenClawExecModeForCodexAppServer({
1105
+ execMode: params.execMode,
1106
+ execPolicy: params.execPolicy
1107
+ });
1108
+ assertCodexAppServerAllowedForOpenClawExecMode(execMode);
1109
+ const explicitPolicyMode = resolvePolicyMode(config.mode) ?? resolvePolicyMode(env.OPENCLAW_CODEX_APP_SERVER_MODE);
1110
+ const configuredSandbox = resolveSandbox(config.sandbox) ?? resolveSandbox(env.OPENCLAW_CODEX_APP_SERVER_SANDBOX);
1111
+ const explicitApprovalsReviewer = resolveApprovalsReviewer(config.approvalsReviewer);
1112
+ const normalizedPolicyMode = resolveCodexPolicyModeForOpenClawExecMode(execMode);
1113
+ const ignoreLegacyYoloPolicyMode = normalizedPolicyMode === "guardian" && explicitPolicyMode === "yolo";
1114
+ const canUseModelBackedReviewer = canUseCodexModelBackedApprovalsReviewerForModel({
1115
+ modelProvider: params.modelProvider,
1116
+ model: params.model,
1117
+ config: params.config,
1118
+ env,
1119
+ agentDir: params.agentDir,
1120
+ codexConfigToml: params.codexConfigToml,
1121
+ homeScope
1122
+ });
1123
+ const forceUserReviewer = !canUseModelBackedReviewer && (explicitApprovalsReviewer === "auto_review" || explicitApprovalsReviewer === "guardian_subagent" || explicitPolicyMode === "guardian" && explicitApprovalsReviewer !== "user") || execMode !== void 0 && execMode !== "full" && (execMode !== "auto" || !canUseModelBackedReviewer);
1124
+ const forceGuardianReviewer = execMode === "auto" && canUseModelBackedReviewer;
1125
+ const execModeRequiringPromptingApprovals = execMode === "auto" || execMode === "ask" ? execMode : forceUserReviewer ? "ask" : void 0;
1126
+ const forceDangerFullAccessSandbox = params.execPolicy?.touched === true && params.execPolicy.security === "full" && params.execPolicy.ask === "always";
1127
+ const forceRuntimePolicy = forceUserReviewer || forceGuardianReviewer || forceDangerFullAccessSandbox;
1128
+ const defaultPolicy = explicitPolicyMode && !forceRuntimePolicy && !ignoreLegacyYoloPolicyMode ? void 0 : resolveDefaultCodexAppServerPolicy({
1129
+ transport,
1130
+ env,
1131
+ forceGuardian: normalizedPolicyMode === "guardian",
1132
+ forceUserReviewer: forceUserReviewer || !canUseModelBackedReviewer,
1133
+ execModeRequiringPromptingApprovals,
1134
+ requirementsToml: params.requirementsToml,
1135
+ requirementsPath: params.requirementsPath,
1136
+ readRequirementsFile: params.readRequirementsFile,
1137
+ platform: params.platform,
1138
+ hostName: params.hostName,
1139
+ execModeRequiringUserReviewer: forceUserReviewer ? execMode : void 0
1140
+ });
1141
+ const preserveExplicitAutoSandbox = forceGuardianReviewer && configuredSandbox === "read-only";
1142
+ const forcedPolicy = forceRuntimePolicy ? {
1143
+ approvalPolicy: defaultPolicy?.approvalPolicy ?? "on-request",
1144
+ sandbox: preserveExplicitAutoSandbox ? void 0 : forceDangerFullAccessSandbox ? selectForcedDangerFullAccessSandbox({
1145
+ configuredSandbox,
1146
+ defaultPolicy,
1147
+ openClawSandboxActive: Boolean(params.openClawSandboxActive)
1148
+ }) : selectForcedPromptingSandbox({
1149
+ configuredSandbox,
1150
+ defaultSandbox: defaultPolicy?.sandbox
1151
+ }),
1152
+ approvalsReviewer: defaultPolicy?.approvalsReviewer ?? (forceUserReviewer ? "user" : "auto_review")
1153
+ } : void 0;
1154
+ const policyMode = ignoreLegacyYoloPolicyMode ? normalizedPolicyMode : explicitPolicyMode ?? normalizedPolicyMode ?? defaultPolicy?.mode ?? "yolo";
1155
+ const serviceTier = normalizeCodexServiceTier(config.serviceTier);
1156
+ const resolvedSandbox = forcedPolicy?.sandbox ?? configuredSandbox ?? defaultPolicy?.sandbox ?? (policyMode === "guardian" ? "workspace-write" : "danger-full-access");
1157
+ if (transport === "websocket" && !url) throw new Error("plugins.entries.codex.config.appServer.url is required when appServer.transport is websocket");
1158
+ if (transport === "websocket" && homeScope === "user") throw new Error("plugins.entries.codex.config.appServer.homeScope=user requires appServer.transport=stdio or unix");
1159
+ if (transport === "unix" && homeScope !== "user") throw new Error("plugins.entries.codex.config.appServer.transport=unix requires appServer.homeScope=user");
1160
+ if (transport === "unix" && !url?.startsWith("unix://")) throw new Error("plugins.entries.codex.config.appServer.url must use unix:// when appServer.transport is unix");
1161
+ assertCodexAppServerConnectionSecurity({
1162
+ transport,
1163
+ url,
1164
+ authToken,
1165
+ headers
1166
+ });
1167
+ const configApprovalPolicy = resolveApprovalPolicy(config.approvalPolicy);
1168
+ const envApprovalPolicy = resolveApprovalPolicy(env.OPENCLAW_CODEX_APP_SERVER_APPROVAL_POLICY);
1169
+ const approvalPolicy = configApprovalPolicy ?? envApprovalPolicy ?? defaultPolicy?.approvalPolicy ?? (policyMode === "guardian" ? "on-request" : "never");
1170
+ const approvalPolicySource = configApprovalPolicy ? "config" : envApprovalPolicy ? "env" : defaultPolicy?.approvalPolicy ? "requirements" : "implicit";
1171
+ const computerUseConfig = resolveCodexComputerUseConfig({
1172
+ pluginConfig: params.pluginConfig,
1173
+ env
1174
+ });
1175
+ const managedCommandOrder = params.managedCommandOrder ?? (homeScope === "user" || computerUseConfig.enabled ? "desktop-first" : "package-first");
1176
+ const includeManagedCommandOrder = commandSource === "managed" && (managedCommandOrder === "desktop-first" || params.managedCommandOrder === "package-first");
1177
+ const managedComputerUsePluginNames = [.../* @__PURE__ */ new Set([DEFAULT_CODEX_COMPUTER_USE_PLUGIN_NAME, computerUseConfig.pluginName])];
1178
+ return {
1179
+ start: {
1180
+ transport,
1181
+ homeScope,
1182
+ command,
1183
+ commandSource,
1184
+ ...includeManagedCommandOrder ? { managedCommandOrder } : {},
1185
+ ...commandSource === "managed" ? { managedComputerUsePluginNames } : {},
1186
+ args: args.length > 0 ? args : [
1187
+ "app-server",
1188
+ "--listen",
1189
+ "stdio://"
1190
+ ],
1191
+ ...url ? { url } : {},
1192
+ ...authToken ? { authToken } : {},
1193
+ headers,
1194
+ ...transport === "stdio" && clearEnv.length > 0 ? { clearEnv } : {}
1195
+ },
1196
+ connectionClass,
1197
+ remoteAppsSubstrate,
1198
+ ...remoteWorkspaceRoot ? { remoteWorkspaceRoot } : {},
1199
+ codeModeOnly: config.codeModeOnly === true,
1200
+ loopDetectionPreToolUseRelay: config.loopDetectionPreToolUseRelay !== false,
1201
+ requestTimeoutMs: normalizePositiveNumber(config.requestTimeoutMs, 6e4),
1202
+ turnCompletionIdleTimeoutMs: normalizePositiveNumber(config.turnCompletionIdleTimeoutMs, 6e4),
1203
+ turnAssistantCompletionIdleTimeoutMs: normalizePositiveNumber(config.turnAssistantCompletionIdleTimeoutMs, 1e4),
1204
+ ...config.postToolRawAssistantCompletionIdleTimeoutMs !== void 0 ? { postToolRawAssistantCompletionIdleTimeoutMs: normalizePositiveNumber(config.postToolRawAssistantCompletionIdleTimeoutMs, 6e4) } : {},
1205
+ approvalPolicy: forcedPolicy?.approvalPolicy ?? approvalPolicy,
1206
+ approvalPolicySource,
1207
+ sandbox: resolvedSandbox,
1208
+ approvalsReviewer: forcedPolicy?.approvalsReviewer ?? explicitApprovalsReviewer ?? defaultPolicy?.approvalsReviewer ?? (policyMode === "guardian" ? "auto_review" : "user"),
1209
+ ...serviceTier ? { serviceTier } : {},
1210
+ ...resolveCodexAppServerNetworkProxy(config.networkProxy, resolvedSandbox)
1200
1211
  };
1201
- return order[left] <= order[right] ? left : right;
1202
1212
  }
1203
- function maxOpenClawExecAsk(left, right) {
1204
- const order = {
1205
- off: 0,
1206
- "on-miss": 1,
1207
- always: 2
1213
+ /**
1214
+ * Rechecks Codex-owned plugin state at the final spawn boundary, where the
1215
+ * effective agent home is known, so Computer Use keeps the desktop app's TCC ownership.
1216
+ */
1217
+ function resolveCodexAppServerStartOptionsForAgent(params) {
1218
+ const startOptions = params.startOptions;
1219
+ if (startOptions.transport !== "stdio" || startOptions.commandSource !== "managed" || startOptions.managedCommandOrder !== void 0) return startOptions;
1220
+ if (startOptions.homeScope === "user") return {
1221
+ ...startOptions,
1222
+ managedCommandOrder: "desktop-first"
1208
1223
  };
1209
- return order[left] >= order[right] ? left : right;
1210
- }
1211
- function readExecMode(value) {
1212
- return value === "deny" || value === "allowlist" || value === "ask" || value === "auto" || value === "full" ? value : void 0;
1213
- }
1214
- function readRecord(value) {
1215
- return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
1216
- }
1217
- function normalizeCodexServiceTier(value) {
1218
- if (typeof value !== "string") return;
1219
- const trimmed = value.trim();
1220
- if (!trimmed) return;
1221
- const normalized = trimmed.toLowerCase();
1222
- if (normalized === "fast" || normalized === "priority") return "priority";
1223
- if (normalized === "flex") return "flex";
1224
- return trimmed;
1225
- }
1226
- function isCodexFastServiceTier(value) {
1227
- return normalizeCodexServiceTier(value) === "priority";
1228
- }
1229
- function normalizePositiveNumber(value, fallback) {
1230
- return resolvePositiveTimerTimeoutMs(value, fallback);
1231
- }
1232
- function normalizeHeaders(value) {
1233
- if (!value || typeof value !== "object" || Array.isArray(value)) return {};
1234
- return Object.fromEntries(Object.entries(value).map(([key, child]) => [key.trim(), normalizeCodexAppServerSecretInput({
1235
- value: child,
1236
- path: `plugins.entries.codex.config.appServer.headers.${key}`
1237
- })]).filter((entry) => Boolean(entry[0] && entry[1])));
1238
- }
1239
- function normalizeCodexAppServerSecretInput(params) {
1240
- return normalizeResolvedSecretInputString(params);
1241
- }
1242
- function normalizeStringList(value) {
1243
- return normalizeTrimmedStringList(value);
1244
- }
1245
- function readBooleanEnv(value) {
1246
- if (value === void 0) return;
1247
- const normalized = value.trim().toLowerCase();
1248
- if ([
1249
- "1",
1250
- "true",
1251
- "yes",
1252
- "on"
1253
- ].includes(normalized)) return true;
1254
- if ([
1255
- "0",
1256
- "false",
1257
- "no",
1258
- "off"
1259
- ].includes(normalized)) return false;
1260
- }
1261
- function readExecSecurity(value) {
1262
- return value === "deny" || value === "allowlist" || value === "full" ? value : void 0;
1263
- }
1264
- function readExecAsk(value) {
1265
- return value === "off" || value === "on-miss" || value === "always" ? value : void 0;
1224
+ return codexConfigEnablesNativeComputerUse({
1225
+ agentDir: params.agentDir,
1226
+ codexConfigToml: params.codexConfigToml,
1227
+ env: params.env,
1228
+ homeScope: "agent",
1229
+ pluginNames: startOptions.managedComputerUsePluginNames ?? ["computer-use"]
1230
+ }) ? {
1231
+ ...startOptions,
1232
+ managedCommandOrder: "desktop-first"
1233
+ } : startOptions;
1266
1234
  }
1267
- function readNumberEnv(value) {
1268
- const trimmed = value?.trim();
1269
- if (!trimmed || !PLAIN_DECIMAL_NUMBER_RE.test(trimmed)) return;
1270
- const parsed = Number(trimmed);
1271
- return Number.isFinite(parsed) ? parsed : void 0;
1235
+ function resolveCodexComputerUseConfig(params = {}) {
1236
+ const env = params.env ?? process.env;
1237
+ const config = readCodexPluginConfig(params.pluginConfig).computerUse ?? {};
1238
+ const marketplaceSource = readNonEmptyString(params.overrides?.marketplaceSource) ?? readNonEmptyString(config.marketplaceSource) ?? readNonEmptyString(env.OPENCLAW_CODEX_COMPUTER_USE_MARKETPLACE_SOURCE);
1239
+ const marketplacePath = readNonEmptyString(params.overrides?.marketplacePath) ?? readNonEmptyString(config.marketplacePath) ?? readNonEmptyString(env.OPENCLAW_CODEX_COMPUTER_USE_MARKETPLACE_PATH);
1240
+ const marketplaceName = readNonEmptyString(params.overrides?.marketplaceName) ?? readNonEmptyString(config.marketplaceName) ?? readNonEmptyString(env.OPENCLAW_CODEX_COMPUTER_USE_MARKETPLACE_NAME);
1241
+ const configuredPluginName = readNonEmptyString(params.overrides?.pluginName) ?? readNonEmptyString(config.pluginName) ?? readNonEmptyString(env.OPENCLAW_CODEX_COMPUTER_USE_PLUGIN_NAME);
1242
+ const configuredMcpServerName = readNonEmptyString(params.overrides?.mcpServerName) ?? readNonEmptyString(config.mcpServerName) ?? readNonEmptyString(env.OPENCLAW_CODEX_COMPUTER_USE_MCP_SERVER_NAME);
1243
+ const autoInstall = params.overrides?.autoInstall ?? config.autoInstall ?? readBooleanEnv(env.OPENCLAW_CODEX_COMPUTER_USE_AUTO_INSTALL) ?? false;
1244
+ const marketplaceDiscoveryTimeoutMs = normalizePositiveNumber(params.overrides?.marketplaceDiscoveryTimeoutMs ?? config.marketplaceDiscoveryTimeoutMs ?? readNumberEnv(env.OPENCLAW_CODEX_COMPUTER_USE_MARKETPLACE_DISCOVERY_TIMEOUT_MS), DEFAULT_CODEX_COMPUTER_USE_MARKETPLACE_DISCOVERY_TIMEOUT_MS);
1245
+ const liveTestTimeoutMs = normalizePositiveNumber(params.overrides?.liveTestTimeoutMs ?? config.liveTestTimeoutMs ?? readNumberEnv(env.OPENCLAW_CODEX_COMPUTER_USE_LIVE_TEST_TIMEOUT_MS), DEFAULT_CODEX_COMPUTER_USE_LIVE_TEST_TIMEOUT_MS);
1246
+ const toolCallTimeoutMs = normalizePositiveNumber(params.overrides?.toolCallTimeoutMs ?? config.toolCallTimeoutMs ?? readNumberEnv(env.OPENCLAW_CODEX_COMPUTER_USE_TOOL_CALL_TIMEOUT_MS), DEFAULT_CODEX_COMPUTER_USE_TOOL_CALL_TIMEOUT_MS);
1247
+ const healthCheckIntervalMinutes = normalizeComputerUseHealthCheckIntervalMinutes(params.overrides?.healthCheckIntervalMinutes ?? config.healthCheckIntervalMinutes ?? readNumberEnv(env.OPENCLAW_CODEX_COMPUTER_USE_HEALTH_CHECK_INTERVAL_MINUTES));
1248
+ const healthCheckEnabled = params.overrides?.healthCheckEnabled ?? config.healthCheckEnabled ?? readBooleanEnv(env.OPENCLAW_CODEX_COMPUTER_USE_HEALTH_CHECK_ENABLED) ?? false;
1249
+ const pluginCacheMode = normalizeComputerUsePluginCacheMode(params.overrides?.pluginCacheMode) ?? normalizeComputerUsePluginCacheMode(config.pluginCacheMode) ?? normalizeComputerUsePluginCacheMode(env.OPENCLAW_CODEX_COMPUTER_USE_PLUGIN_CACHE_MODE) ?? "independent";
1250
+ const strictReadiness = params.overrides?.strictReadiness ?? config.strictReadiness ?? readBooleanEnv(env.OPENCLAW_CODEX_COMPUTER_USE_STRICT_READINESS) ?? false;
1251
+ const autoRepair = params.overrides?.autoRepair ?? config.autoRepair ?? readBooleanEnv(env.OPENCLAW_CODEX_COMPUTER_USE_AUTO_REPAIR) ?? false;
1252
+ return {
1253
+ enabled: params.overrides?.enabled ?? config.enabled ?? readBooleanEnv(env.OPENCLAW_CODEX_COMPUTER_USE) ?? Boolean(autoInstall || marketplaceSource || marketplacePath || marketplaceName || configuredPluginName || configuredMcpServerName),
1254
+ autoInstall,
1255
+ marketplaceDiscoveryTimeoutMs,
1256
+ liveTestTimeoutMs,
1257
+ toolCallTimeoutMs,
1258
+ healthCheckEnabled,
1259
+ healthCheckIntervalMinutes,
1260
+ pluginCacheMode,
1261
+ strictReadiness,
1262
+ autoRepair,
1263
+ pluginName: configuredPluginName ?? "computer-use",
1264
+ mcpServerName: configuredMcpServerName ?? "computer-use",
1265
+ ...marketplaceSource ? { marketplaceSource } : {},
1266
+ ...marketplacePath ? { marketplacePath } : {},
1267
+ ...marketplaceName ? { marketplaceName } : {}
1268
+ };
1272
1269
  }
1273
- function resolveArgs(configArgs, envArgs) {
1274
- if (Array.isArray(configArgs)) return configArgs.map((entry) => readNonEmptyString(entry)).filter((entry) => entry !== void 0);
1275
- if (typeof configArgs === "string") return splitShellWords(configArgs);
1276
- return splitShellWords(envArgs ?? "");
1270
+ function normalizeComputerUseHealthCheckIntervalMinutes(value) {
1271
+ return value === 30 || value === 60 || value === 120 || value === 240 ? value : 60;
1277
1272
  }
1278
- function readNonEmptyString(value) {
1279
- if (typeof value !== "string") return;
1280
- return value.trim() || void 0;
1273
+ function normalizeComputerUsePluginCacheMode(value) {
1274
+ return value === "shared" || value === "independent" ? value : null;
1281
1275
  }
1282
- function hashSecretForKey(value, label) {
1283
- if (!value) return null;
1284
- return createHmac("sha256", START_OPTIONS_KEY_SECRET).update(label).update("\0").update(value).digest("hex");
1276
+ function codexAppServerStartOptionsKey(options, params = {}) {
1277
+ return JSON.stringify({
1278
+ transport: options.transport,
1279
+ command: options.command,
1280
+ commandSource: options.commandSource ?? null,
1281
+ managedCommandOrder: options.managedCommandOrder ?? "package-first",
1282
+ managedComputerUsePluginNames: [...options.managedComputerUsePluginNames ?? []].toSorted(),
1283
+ managedFallbackCommandPaths: [...options.managedFallbackCommandPaths ?? []],
1284
+ args: options.args,
1285
+ cwd: options.cwd ?? null,
1286
+ url: options.url ?? null,
1287
+ authToken: hashSecretForKey(options.authToken, "authToken"),
1288
+ headers: Object.entries(options.headers).toSorted(([left], [right]) => left.localeCompare(right)).map(([key, value]) => [key, hashSecretForKey(value, `header:${key}`)]),
1289
+ env: Object.entries(options.env ?? {}).toSorted(([left], [right]) => left.localeCompare(right)).map(([key, value]) => [key, hashSecretForKey(value, `env:${key}`)]),
1290
+ clearEnv: [...options.clearEnv ?? []].toSorted(),
1291
+ authProfileId: params.authProfileId ?? null,
1292
+ authBindingFingerprint: params.authBindingFingerprint ?? null,
1293
+ agentDir: params.agentDir ?? null,
1294
+ fallbackApiKeyCacheKey: params.fallbackApiKeyCacheKey ?? null
1295
+ });
1285
1296
  }
1286
- function getStartOptionsKeySecret() {
1287
- const globalState = globalThis;
1288
- globalState[START_OPTIONS_KEY_SECRET_SYMBOL] ??= randomBytes(32);
1289
- return globalState[START_OPTIONS_KEY_SECRET_SYMBOL];
1297
+ function codexSandboxPolicyForTurn(mode, cwd, nativeArgs = []) {
1298
+ if (mode === "danger-full-access") return { type: "dangerFullAccess" };
1299
+ if (mode === "read-only") return {
1300
+ type: "readOnly",
1301
+ networkAccess: false
1302
+ };
1303
+ let excludeTmpdirEnvVar = false;
1304
+ let excludeSlashTmp = false;
1305
+ for (let index = 0; index < nativeArgs.length; index += 1) {
1306
+ const arg = nativeArgs[index];
1307
+ const override = arg === "-c" || arg === "--config" ? nativeArgs[++index] : arg?.startsWith("--config=") ? arg.slice(9) : void 0;
1308
+ if (!override) continue;
1309
+ const separator = override.indexOf("=");
1310
+ if (separator < 0) continue;
1311
+ const key = override.slice(0, separator).trim();
1312
+ const value = override.slice(separator + 1).trim();
1313
+ if (value !== "true" && value !== "false") continue;
1314
+ if (key === "sandbox_workspace_write.exclude_tmpdir_env_var") excludeTmpdirEnvVar = value === "true";
1315
+ else if (key === "sandbox_workspace_write.exclude_slash_tmp") excludeSlashTmp = value === "true";
1316
+ }
1317
+ return {
1318
+ type: "workspaceWrite",
1319
+ writableRoots: [cwd],
1320
+ networkAccess: false,
1321
+ excludeTmpdirEnvVar,
1322
+ excludeSlashTmp
1323
+ };
1290
1324
  }
1291
- function splitShellWords(value) {
1292
- const words = [];
1293
- let current = "";
1294
- let quote = null;
1295
- for (const char of value) {
1296
- if (quote) {
1297
- if (char === quote) quote = null;
1298
- else current += char;
1299
- continue;
1300
- }
1301
- if (char === "\"" || char === "'") {
1302
- quote = char;
1303
- continue;
1304
- }
1305
- if (/\s/.test(char)) {
1306
- if (current) {
1307
- words.push(current);
1308
- current = "";
1325
+ /** Resolves the passive supervision control connection without changing harness defaults. */
1326
+ function resolveCodexSupervisionAppServerRuntimeOptions(params = {}) {
1327
+ const pluginConfig = readCodexPluginConfig(params.pluginConfig);
1328
+ const appServer = pluginConfig.appServer ?? {};
1329
+ const transport = resolveTransport(appServer.transport);
1330
+ const homeScope = appServer.homeScope ?? (transport === "websocket" ? "agent" : "user");
1331
+ return resolveCodexAppServerRuntimeOptions({
1332
+ ...params,
1333
+ pluginConfig: {
1334
+ ...pluginConfig,
1335
+ appServer: {
1336
+ ...appServer,
1337
+ homeScope
1309
1338
  }
1310
- continue;
1311
1339
  }
1312
- current += char;
1313
- }
1314
- if (current) words.push(current);
1315
- return words;
1340
+ });
1316
1341
  }
1317
1342
  //#endregion
1318
1343
  //#region extensions/codex/src/app-server/session-binding.ts
@@ -1348,7 +1373,7 @@ const BINDING_LEASE_RENEW_INTERVAL_MS = Math.floor(BINDING_LEASE_STALE_MS / 3);
1348
1373
  const PHYSICAL_SESSION_RETIRE_TTL_MS = BINDING_LEASE_WAIT_MS;
1349
1374
  /** Resolves the same agent scope OpenClaw uses for transcript/session ownership. */
1350
1375
  function sessionBindingIdentity(params) {
1351
- const { sessionAgentId } = resolveSessionAgentIds(params);
1376
+ const { sessionAgentId } = resolveSessionAgentIds$1(params);
1352
1377
  const sessionKey = params.sessionKey?.trim();
1353
1378
  return {
1354
1379
  kind: "session",
@@ -1727,10 +1752,17 @@ function createCodexAppServerBindingStore(state) {
1727
1752
  result: true
1728
1753
  };
1729
1754
  const currentSessionId = current.sessionId;
1730
- if (!currentSessionId || currentSessionId === identity.sessionId) return {
1755
+ if (!currentSessionId) return {
1731
1756
  kind: "resolved",
1732
1757
  result: current.state !== "cleared" || current.retired !== true
1733
1758
  };
1759
+ if (currentSessionId === identity.sessionId) return current.state === "cleared" && current.retired === true ? {
1760
+ kind: "verify",
1761
+ expectedPreviousSessionId: currentSessionId
1762
+ } : {
1763
+ kind: "resolved",
1764
+ result: true
1765
+ };
1734
1766
  return {
1735
1767
  kind: "verify",
1736
1768
  expectedPreviousSessionId: currentSessionId
@@ -1746,7 +1778,18 @@ function createCodexAppServerBindingStore(state) {
1746
1778
  if (mutation.kind === "reclaim-generation") {
1747
1779
  if (identity.kind !== "session" || !identity.sessionKey?.trim()) return { result: false };
1748
1780
  if (!current) return { result: true };
1749
- if (ownsGeneration) return { result: current.state !== "cleared" || current.retired !== true };
1781
+ if (ownsGeneration) {
1782
+ if (current.state === "cleared" && current.retired === true && current.sessionId === mutation.expectedPreviousSessionId) return {
1783
+ result: true,
1784
+ next: {
1785
+ version: 1,
1786
+ state: "cleared",
1787
+ sessionId: identity.sessionId,
1788
+ ...ownedLease
1789
+ }
1790
+ };
1791
+ return { result: current.state !== "cleared" || current.retired !== true };
1792
+ }
1750
1793
  if (current.sessionId !== mutation.expectedPreviousSessionId) return { result: false };
1751
1794
  if (current.state === "active" && current.binding.connectionScope === "supervision") return { result: false };
1752
1795
  return {
@@ -1825,6 +1868,25 @@ function createCodexAppServerBindingStore(state) {
1825
1868
  });
1826
1869
  });
1827
1870
  },
1871
+ async resetSessionGeneration(identity) {
1872
+ return await runBindingMutation(async () => {
1873
+ const key = bindingStoreKey(identity);
1874
+ return await transactKey(key, (current, leaseToken) => {
1875
+ if (!current) return { result: "absent" };
1876
+ if (!ownsStoredSessionGeneration(identity, current)) return { result: "conflict" };
1877
+ if (current.state === "cleared" && current.retired === true) return { result: "conflict" };
1878
+ return {
1879
+ result: "applied",
1880
+ next: {
1881
+ version: 1,
1882
+ state: "cleared",
1883
+ ...storedSessionGeneration(identity, current),
1884
+ ...current.lease && current.lease.token === leaseToken ? { lease: current.lease } : {}
1885
+ }
1886
+ };
1887
+ }, leaseContext.getStore()?.has(key) ? void 0 : 1);
1888
+ });
1889
+ },
1828
1890
  async retireSessionGeneration(identity) {
1829
1891
  return await runBindingMutation(async () => {
1830
1892
  const key = bindingStoreKey(identity);
@@ -1956,7 +2018,7 @@ function bindingStoreKey(identity) {
1956
2018
  const sessionId = identity.sessionId.trim();
1957
2019
  if (!rawAgentId) throw new Error("Codex app-server binding requires an agent id");
1958
2020
  if (!sessionId) throw new Error("Codex app-server binding requires a session id");
1959
- const agentId = resolveSessionAgentIds({ agentId: rawAgentId }).sessionAgentId;
2021
+ const agentId = resolveSessionAgentIds$1({ agentId: rawAgentId }).sessionAgentId;
1960
2022
  const sessionKey = identity.sessionKey?.trim();
1961
2023
  if (sessionKey) return `session-key:${agentId}:${createHash("sha256").update(sessionKey).digest("base64url")}`;
1962
2024
  return `session:${agentId}:${sessionId}`;
@@ -2096,4 +2158,4 @@ function resolveCodexAppServerBindingModelProvider(params) {
2096
2158
  return params.modelProvider?.trim() || (isCodexAppServerNativeAuthProfile(params) ? PUBLIC_OPENAI_MODEL_PROVIDER : void 0);
2097
2159
  }
2098
2160
  //#endregion
2099
- export { withMcpElicitationsApprovalPolicy as A, resolveCodexAppServerUserHomeDir as C, resolveCodexSupervisionAppServerRuntimeOptions as D, resolveCodexPluginsPolicy as E, resolveOpenClawExecPolicyForCodexAppServer as O, resolveCodexAppServerStartOptionsForAgent as S, resolveCodexModelBackedReviewerPolicyContext as T, isCodexAppServerApprovalPolicyAllowedByRequirements as _, hashCodexAppServerBindingFingerprint as a, readCodexPluginConfig as b, reclaimCurrentCodexSessionGeneration as c, CODEX_PLUGINS_MARKETPLACE_NAME as d, CODEX_PLUGINS_WORKSPACE_MARKETPLACE_NAME as f, codexSandboxPolicyForTurn as g, codexAppServerStartOptionsKey as h, createCodexSessionGenerationSupersededError as i, shouldAutoApproveCodexAppServerApprovals as k, sessionBindingIdentity as l, canUseCodexModelBackedApprovalsReviewerForModel as m, assertCodexBindingMayBeReplaced as n, isCodexAppServerNativeAuthProfile as o, assertCodexAppServerConnectionSecurity as p, bindingStoreKey as r, normalizeCodexAppServerBindingModelProvider as s, CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS as t, session_binding_exports as u, isCodexFastServiceTier as v, resolveCodexComputerUseConfig as w, resolveCodexAppServerRuntimeOptions as x, isCodexSandboxExecServerEnabled as y };
2161
+ export { CODEX_PLUGINS_WORKSPACE_MARKETPLACE_NAME as A, isCodexAppServerApprovalPolicyAllowedByRequirements as C, resolveOpenClawExecPolicyForCodexAppServer as D, resolveCodexPluginsPolicy as E, isCodexFastServiceTier as O, resolveCodexModelBackedReviewerPolicyContext as S, readCodexPluginConfig as T, assertCodexAppServerConnectionSecurity as _, hashCodexAppServerBindingFingerprint as a, canUseCodexModelBackedApprovalsReviewerForModel as b, reclaimCurrentCodexSessionGeneration as c, codexAppServerStartOptionsKey as d, codexSandboxPolicyForTurn as f, resolveCodexSupervisionAppServerRuntimeOptions as g, resolveCodexComputerUseConfig as h, createCodexSessionGenerationSupersededError as i, CODEX_PLUGINS_MARKETPLACE_NAME as k, sessionBindingIdentity as l, resolveCodexAppServerStartOptionsForAgent as m, assertCodexBindingMayBeReplaced as n, isCodexAppServerNativeAuthProfile as o, resolveCodexAppServerRuntimeOptions as p, bindingStoreKey as r, normalizeCodexAppServerBindingModelProvider as s, CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS as t, session_binding_exports as u, shouldAutoApproveCodexAppServerApprovals as v, isCodexSandboxExecServerEnabled as w, resolveCodexAppServerUserHomeDir as x, withMcpElicitationsApprovalPolicy as y };