@openclaw/codex 2026.9.1-beta.1 → 2026.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.js +5 -6
- package/dist/{attempt-client-cleanup-bfsmcQ6m.js → attempt-client-cleanup-DYHcRQAa.js} +31 -45
- package/dist/attempt-context-DmQUNWwT.js +634 -0
- package/dist/{auth-binding-B4FfbcCg.js → auth-binding-Ds_QVm-X.js} +18 -3
- package/dist/{binding-connection-BMvPX73o.js → binding-connection-E6uDsPlx.js} +2 -2
- package/dist/{bounded-turn-B7iBUcuP.js → bounded-turn-wzJrwKKe.js} +15 -20
- package/dist/{capabilities-BRMh0aIq.js → capabilities-dIjNVCYH.js} +1 -1
- package/dist/cli-metadata.js +1 -1
- package/dist/{command-formatters-DEsIufkt.js → command-formatters-CLHhEB1Q.js} +5 -4
- package/dist/{command-handlers-D_-1_qRp.js → command-handlers-CTGb2csu.js} +124 -101
- package/dist/{compact-BglNFZrQ.js → compact-_t0HQrUS.js} +38 -29
- package/dist/{config-giW8X0QA.js → config-BhmfC1s6.js} +294 -282
- package/dist/{context-compaction-activity-BOeJf7yo.js → context-compaction-activity-CMla5FPJ.js} +4 -1
- package/dist/{conversation-binding-data-CW2GuupV.js → conversation-binding-data-BiodpIzq.js} +2 -1
- package/dist/doctor-contract-api.js +143 -12
- package/dist/{dynamic-tools-Dnlfa--w.js → dynamic-tools-BU9tmlYm.js} +599 -655
- package/dist/{effective-mcp-catalog-CTeGrnfO.js → effective-mcp-catalog-DzYBW4h1.js} +2 -2
- package/dist/{event-projector-assistant-message-C5-Ds8mA.js → event-projector-assistant-message-DHRFXKbS.js} +4 -4
- package/dist/{event-projector-usage-Bk1I90Bg.js → event-projector-usage-C5mcrGjp.js} +15 -148
- package/dist/{harness-Csz0F-DK.js → harness-DXVZ5II5.js} +42 -52
- package/dist/harness.js +1 -1
- package/dist/index.js +458 -404
- package/dist/{isolated-completion-Cv6FqygM.js → isolated-completion-kg9kv4iH.js} +4 -4
- package/dist/launch-args-RXQwn8zV.js +90 -0
- package/dist/{managed-binary-DFYK4DWq.js → managed-binary-4-Vjz5GH.js} +14 -9
- package/dist/media-understanding-provider.js +1 -1
- package/dist/model-catalog-CUM68Hkl.js +101 -0
- package/dist/{models-TS3HBU-q.js → models-sYnEc0gd.js} +25 -28
- package/dist/{native-subagent-monitor-4Mfq2HDs.js → native-subagent-monitor-CnH147jH.js} +55 -115
- package/dist/{node-exec-server.runtime-BpWqJO1V.js → node-exec-server.runtime-CstNHCmC.js} +9 -6
- package/dist/{plugin-approval-roundtrip-bUm777tR.js → plugin-approval-roundtrip-CNe-Xrjx.js} +30 -3
- package/dist/{plugin-marketplace-discovery-B9DvaAG-.js → plugin-marketplace-discovery-CfFlKqDl.js} +15 -14
- package/dist/{plugin-metadata-cache-CTCT3w5L.js → plugin-metadata-cache-BFrPhb2c.js} +6 -6
- package/dist/provider-capabilities-DW5p4k9w.js +101 -0
- package/dist/{rate-limits-C5_D8Gmb.js → rate-limits-CawQJfUS.js} +3 -2
- package/dist/{sandbox-guard-kuWTn9C5.js → request-DYAI5FQE.js} +195 -2
- package/dist/{run-attempt-DYc0QCBF.js → run-attempt-D1hJO4fX.js} +828 -2100
- package/dist/{runtime-artifact-BvyT1uyd.js → runtime-artifact-C3jVimFn.js} +21 -14
- package/dist/{session-binding-Bcynfd-_.js → session-binding-BHuTCRZQ.js} +198 -127
- package/dist/{session-catalog-DaLKVtpH.js → session-catalog-yyvTWFOw.js} +564 -408
- package/dist/{session-cli-DMc4oS2w.js → session-cli-CmFEXMAM.js} +1 -1
- package/dist/session-history-C5J1AKzG.js +87 -0
- package/dist/session-initialization-BeWzjGiR.js +74 -0
- package/dist/{session-permission-policy-BrNH1bjy.js → session-permission-policy-DeWVTCMj.js} +2 -2
- package/dist/session-retirement-BujDjXVF.js +97 -0
- package/dist/{session-upstream-marker-BIkusb95.js → session-upstream-marker-C351-5Qw.js} +19 -4
- package/dist/settled-turn-context-D3SNWtUn.js +268 -0
- package/dist/settled-turn-finalizer-BVJx4yoc.js +104 -0
- package/dist/{shared-client-DKz23hHY.js → shared-client-DxcfF9KX.js} +3480 -679
- package/dist/{side-question-DjA_jsNe.js → side-question-BTZAII4l.js} +108 -70
- package/dist/{thread-lifecycle-L7oEkTlq.js → thread-lifecycle-DAcEJ_Om.js} +2188 -1915
- package/dist/{thread-ownership-DZeuKH1j.js → thread-ownership-zGokd8i1.js} +25 -14
- package/dist/thread-policy-g4KbJPzp.js +54 -0
- package/dist/{plugin-app-cache-key-C1CAdfcP.js → thread-resume-C7pyVKeW.js} +59 -7
- package/dist/{transcript-mirror-DsCMWBca.js → transcript-mirror-DTUxFWa_.js} +79 -17
- package/dist/transport-stdio-CyPldczm.js +726 -0
- package/dist/{upstream-prompt-provenance-CFmsKwr9.js → upstream-prompt-provenance-LphB8slG.js} +8 -4
- package/dist/upstream-session-fork-CYlBIGVt.js +966 -0
- package/dist/{usage-ROIaW3wo.js → usage-Bj-rrzkR.js} +3 -3
- package/dist/{web-search-provider.runtime-ClaNPV7N.js → web-search-provider.runtime-D2FWSK4w.js} +3 -3
- package/openclaw.plugin.json +1 -30
- package/package.json +6 -6
- package/dist/command-rpc-CCeCkf_v.js +0 -90
- package/dist/incognito-session-ET_ufDH-.js +0 -2
- package/dist/model-catalog-i9rNBthX.js +0 -48
- package/dist/protocol-validators-VeJxxJ0U.js +0 -2421
- package/dist/request-DXXGHko0.js +0 -157
- package/dist/session-catalog-home-id-BNwAJ9D7.js +0 -18
- package/dist/session-retirement-CcNC3YSY.js +0 -36
- package/dist/settled-turn-finalizer-Dc3ApjU4.js +0 -328
- package/dist/thread-resume-BE9qNEW0.js +0 -30
- package/dist/transport-stdio-DhoGy33Z.js +0 -99
- package/dist/upstream-session-fork-DlaHxSLC.js +0 -326
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as normalizeCodexAppServerArgs, r as readCodexAppServerConfigOptions } from "./launch-args-RXQwn8zV.js";
|
|
2
|
+
import { asNullableRecord, asOptionalRecord as readRecord, normalizeOptionalString, normalizeOptionalString as readNonEmptyString, normalizeTrimmedStringList, parseBooleanValue } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import { resolvePositiveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
|
|
4
5
|
import { AgentHarnessPreflightError } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
@@ -6,13 +7,46 @@ import { createHash, createHmac, randomBytes } from "node:crypto";
|
|
|
6
7
|
import { readFileSync } from "node:fs";
|
|
7
8
|
import { homedir, hostname } from "node:os";
|
|
8
9
|
import { resolveProviderIdForAuth } from "openclaw/plugin-sdk/agent-runtime";
|
|
9
|
-
import { parse } from "smol-toml";
|
|
10
10
|
import { resolveAgentConfig as resolveAgentConfig$1 } from "openclaw/plugin-sdk/agent-scope-runtime";
|
|
11
11
|
import { resolveExecApprovalsFromFile } from "openclaw/plugin-sdk/exec-approvals-runtime";
|
|
12
12
|
import { buildSecretInputSchema, normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-input";
|
|
13
13
|
import { detectWindowsSpawnCommandInlineArgs } from "openclaw/plugin-sdk/windows-spawn";
|
|
14
14
|
import { z } from "zod";
|
|
15
|
+
import { parse } from "smol-toml";
|
|
15
16
|
import { isLoopbackHost } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
17
|
+
//#region extensions/codex/src/app-server/auth-start-options.ts
|
|
18
|
+
const CODEX_APP_SERVER_HOME_DIRNAME = "codex-home";
|
|
19
|
+
const CODEX_EPHEMERAL_AUTH_STORE_OVERRIDE = "cli_auth_credentials_store=\"ephemeral\"";
|
|
20
|
+
function resolveCodexAppServerHomeDir(agentDir) {
|
|
21
|
+
return path.join(path.resolve(agentDir), CODEX_APP_SERVER_HOME_DIRNAME);
|
|
22
|
+
}
|
|
23
|
+
/** Resolves the native user Codex home used by Desktop and the CLI. */
|
|
24
|
+
function resolveCodexAppServerUserHomeDir(env = process.env, homedir$1 = homedir) {
|
|
25
|
+
const configured = normalizeOptionalString(env.CODEX_HOME);
|
|
26
|
+
return path.resolve(configured ?? path.join(homedir$1(), ".codex"));
|
|
27
|
+
}
|
|
28
|
+
/** Resolves the local CODEX_HOME used when starting one app-server connection. */
|
|
29
|
+
function resolveCodexAppServerLocalHomeDir(startOptions, agentDir, env = process.env) {
|
|
30
|
+
const configured = startOptions.env?.CODEX_HOME;
|
|
31
|
+
if (configured?.trim()) return configured;
|
|
32
|
+
return startOptions.homeScope === "user" ? resolveCodexAppServerUserHomeDir(env) : resolveCodexAppServerHomeDir(agentDir);
|
|
33
|
+
}
|
|
34
|
+
/** Forces OpenClaw-owned Codex auth to remain process-local. */
|
|
35
|
+
function withEphemeralCodexAuthStore(params) {
|
|
36
|
+
const { startOptions } = params;
|
|
37
|
+
if (!params.preparedAuth && params.authProfileId === null) return startOptions;
|
|
38
|
+
const args = normalizeCodexAppServerArgs(startOptions.args, CODEX_EPHEMERAL_AUTH_STORE_OVERRIDE);
|
|
39
|
+
return args === startOptions.args ? startOptions : {
|
|
40
|
+
...startOptions,
|
|
41
|
+
args
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region extensions/codex/src/app-server/config-contracts.ts
|
|
46
|
+
const CODEX_PLUGINS_MARKETPLACE_NAME = "openai-curated";
|
|
47
|
+
const CODEX_PLUGINS_WORKSPACE_MARKETPLACE_NAME = "workspace-directory";
|
|
48
|
+
const CODEX_PLUGIN_MARKETPLACE_NAME_PATTERN = /^[A-Za-z0-9_-]+$/;
|
|
49
|
+
//#endregion
|
|
16
50
|
//#region extensions/codex/src/app-server/config-utils.ts
|
|
17
51
|
const START_OPTIONS_KEY_SECRET_SYMBOL = Symbol.for("openclaw.codexAppServerStartOptionsKeySecret");
|
|
18
52
|
const START_OPTIONS_KEY_SECRET = getStartOptionsKeySecret();
|
|
@@ -266,6 +300,226 @@ function readExecMode(value) {
|
|
|
266
300
|
return value === "deny" || value === "allowlist" || value === "ask" || value === "auto" || value === "full" ? value : void 0;
|
|
267
301
|
}
|
|
268
302
|
//#endregion
|
|
303
|
+
//#region extensions/codex/src/app-server/session-discovery-config.ts
|
|
304
|
+
const codexSessionCatalogHomeSchema = z.union([z.string().trim().min(1), z.object({
|
|
305
|
+
path: z.string().trim().min(1),
|
|
306
|
+
label: z.string().trim().min(1).optional()
|
|
307
|
+
}).strict()]);
|
|
308
|
+
const codexSessionCatalogConfigSchema = z.object({
|
|
309
|
+
enabled: z.boolean().optional(),
|
|
310
|
+
homes: z.array(codexSessionCatalogHomeSchema).optional()
|
|
311
|
+
}).strict();
|
|
312
|
+
const codexDiscoveryConfigSchema = z.object({
|
|
313
|
+
enabled: z.boolean().optional(),
|
|
314
|
+
timeoutMs: z.number().positive().optional()
|
|
315
|
+
}).strict();
|
|
316
|
+
//#endregion
|
|
317
|
+
//#region extensions/codex/src/app-server/config-parsing.ts
|
|
318
|
+
const DEFAULT_CODEX_COMPUTER_USE_PLUGIN_NAME = "computer-use";
|
|
319
|
+
const DEFAULT_CODEX_COMPUTER_USE_MARKETPLACE_DISCOVERY_TIMEOUT_MS = 6e4;
|
|
320
|
+
const DEFAULT_CODEX_COMPUTER_USE_LIVE_TEST_TIMEOUT_MS = 6e4;
|
|
321
|
+
const DEFAULT_CODEX_COMPUTER_USE_TOOL_CALL_TIMEOUT_MS = 6e4;
|
|
322
|
+
const DEFAULT_CODEX_APP_SERVER_NETWORK_PROXY_PROFILE_PREFIX = "openclaw-network";
|
|
323
|
+
const codexAppServerTransportSchema = z.enum([
|
|
324
|
+
"stdio",
|
|
325
|
+
"websocket",
|
|
326
|
+
"unix"
|
|
327
|
+
]);
|
|
328
|
+
const codexAppServerHomeScopeSchema = z.enum(["agent", "user"]);
|
|
329
|
+
const SecretInputSchema = buildSecretInputSchema();
|
|
330
|
+
const codexAppServerPolicyModeSchema = z.enum(["yolo", "guardian"]);
|
|
331
|
+
const codexAppServerApprovalPolicySchema = z.preprocess((value) => value === "on-failure" ? "on-request" : value, z.enum(["never", "on-request"]));
|
|
332
|
+
const codexAppServerSandboxSchema = z.enum([
|
|
333
|
+
"read-only",
|
|
334
|
+
"workspace-write",
|
|
335
|
+
"danger-full-access"
|
|
336
|
+
]);
|
|
337
|
+
const codexAppServerApprovalsReviewerSchema = z.enum([
|
|
338
|
+
"user",
|
|
339
|
+
"auto_review",
|
|
340
|
+
"guardian_subagent"
|
|
341
|
+
]);
|
|
342
|
+
const codexDynamicToolsLoadingSchema = z.enum(["searchable", "direct"]);
|
|
343
|
+
const codexComputerUseHealthIntervalSchema = z.union([
|
|
344
|
+
z.literal(30),
|
|
345
|
+
z.literal(60),
|
|
346
|
+
z.literal(120),
|
|
347
|
+
z.literal(240)
|
|
348
|
+
]);
|
|
349
|
+
const codexComputerUsePluginCacheModeSchema = z.enum(["shared", "independent"]);
|
|
350
|
+
const codexPluginDestructivePolicySchema = z.union([
|
|
351
|
+
z.boolean(),
|
|
352
|
+
z.literal("auto"),
|
|
353
|
+
z.literal("ask")
|
|
354
|
+
]);
|
|
355
|
+
const codexAppServerServiceTierSchema = z.preprocess((value) => value === null ? null : normalizeCodexServiceTier(value), z.string().trim().min(1).nullable().optional()).optional();
|
|
356
|
+
const codexAppServerExperimentalSchema = z.object({ sandboxExecServer: z.boolean().optional() }).strict();
|
|
357
|
+
const codexAppServerRemoteWorkspaceRootSchema = z.string().trim().min(1);
|
|
358
|
+
const codexAppServerNetworkProxyDomainPermissionSchema = z.enum(["allow", "deny"]);
|
|
359
|
+
const codexAppServerNetworkProxyUnixSocketPermissionSchema = z.enum(["allow", "none"]);
|
|
360
|
+
const codexAppServerNetworkProxySchema = z.object({
|
|
361
|
+
enabled: z.boolean().optional(),
|
|
362
|
+
profileName: z.string().trim().min(1).optional(),
|
|
363
|
+
baseProfile: z.enum(["read-only", "workspace"]).optional(),
|
|
364
|
+
mode: z.enum(["limited", "full"]).optional(),
|
|
365
|
+
domains: z.record(z.string(), codexAppServerNetworkProxyDomainPermissionSchema).optional(),
|
|
366
|
+
unixSockets: z.record(z.string(), codexAppServerNetworkProxyUnixSocketPermissionSchema).optional(),
|
|
367
|
+
proxyUrl: z.string().trim().min(1).optional(),
|
|
368
|
+
socksUrl: z.string().trim().min(1).optional(),
|
|
369
|
+
enableSocks5: z.boolean().optional(),
|
|
370
|
+
enableSocks5Udp: z.boolean().optional(),
|
|
371
|
+
allowUpstreamProxy: z.boolean().optional(),
|
|
372
|
+
allowLocalBinding: z.boolean().optional(),
|
|
373
|
+
dangerouslyAllowNonLoopbackProxy: z.boolean().optional(),
|
|
374
|
+
dangerouslyAllowAllUnixSockets: z.boolean().optional()
|
|
375
|
+
}).strict();
|
|
376
|
+
const codexPluginEntryConfigSchema = z.object({
|
|
377
|
+
enabled: z.boolean().optional(),
|
|
378
|
+
marketplaceName: z.string().regex(CODEX_PLUGIN_MARKETPLACE_NAME_PATTERN).optional(),
|
|
379
|
+
pluginName: z.string().trim().min(1).optional(),
|
|
380
|
+
allow_destructive_actions: codexPluginDestructivePolicySchema.optional()
|
|
381
|
+
}).strict();
|
|
382
|
+
const codexPluginsConfigSchema = z.object({
|
|
383
|
+
enabled: z.boolean().optional(),
|
|
384
|
+
allow_all_plugins: z.boolean().optional(),
|
|
385
|
+
allow_destructive_actions: codexPluginDestructivePolicySchema.optional(),
|
|
386
|
+
plugins: z.record(z.string(), codexPluginEntryConfigSchema).optional()
|
|
387
|
+
}).strict();
|
|
388
|
+
const codexSupervisionEndpointSchema = z.union([z.object({
|
|
389
|
+
id: z.string().optional(),
|
|
390
|
+
label: z.string().optional(),
|
|
391
|
+
transport: z.literal("stdio-proxy").optional(),
|
|
392
|
+
command: z.string().optional(),
|
|
393
|
+
args: z.array(z.string()).optional(),
|
|
394
|
+
cwd: z.string().optional()
|
|
395
|
+
}).strict(), z.object({
|
|
396
|
+
id: z.string().optional(),
|
|
397
|
+
label: z.string().optional(),
|
|
398
|
+
transport: z.literal("websocket"),
|
|
399
|
+
url: z.string(),
|
|
400
|
+
authTokenEnv: z.string().optional()
|
|
401
|
+
}).strict()]);
|
|
402
|
+
const codexSupervisionConfigSchema = z.object({
|
|
403
|
+
enabled: z.boolean().optional(),
|
|
404
|
+
endpoints: z.array(codexSupervisionEndpointSchema).optional(),
|
|
405
|
+
allowRawTranscripts: z.boolean().optional(),
|
|
406
|
+
allowWriteControls: z.boolean().optional()
|
|
407
|
+
}).strict();
|
|
408
|
+
const codexPluginConfigSchema = z.object({
|
|
409
|
+
codexDynamicToolsLoading: codexDynamicToolsLoadingSchema.optional(),
|
|
410
|
+
codexDynamicToolsExclude: z.array(z.string()).optional(),
|
|
411
|
+
sessionCatalog: codexSessionCatalogConfigSchema.optional(),
|
|
412
|
+
discovery: codexDiscoveryConfigSchema.optional(),
|
|
413
|
+
computerUse: z.object({
|
|
414
|
+
enabled: z.boolean().optional(),
|
|
415
|
+
autoInstall: z.boolean().optional(),
|
|
416
|
+
marketplaceDiscoveryTimeoutMs: z.number().positive().optional(),
|
|
417
|
+
liveTestTimeoutMs: z.number().positive().optional(),
|
|
418
|
+
toolCallTimeoutMs: z.number().positive().optional(),
|
|
419
|
+
healthCheckEnabled: z.boolean().optional(),
|
|
420
|
+
healthCheckIntervalMinutes: codexComputerUseHealthIntervalSchema.optional(),
|
|
421
|
+
pluginCacheMode: codexComputerUsePluginCacheModeSchema.optional(),
|
|
422
|
+
strictReadiness: z.boolean().optional(),
|
|
423
|
+
autoRepair: z.boolean().optional(),
|
|
424
|
+
marketplaceSource: z.string().optional(),
|
|
425
|
+
marketplacePath: z.string().optional(),
|
|
426
|
+
marketplaceName: z.string().optional(),
|
|
427
|
+
pluginName: z.string().optional(),
|
|
428
|
+
mcpServerName: z.string().optional()
|
|
429
|
+
}).strict().optional(),
|
|
430
|
+
codexPlugins: z.unknown().optional(),
|
|
431
|
+
supervision: codexSupervisionConfigSchema.optional(),
|
|
432
|
+
appServer: z.object({
|
|
433
|
+
mode: codexAppServerPolicyModeSchema.optional(),
|
|
434
|
+
transport: codexAppServerTransportSchema.optional(),
|
|
435
|
+
homeScope: codexAppServerHomeScopeSchema.optional(),
|
|
436
|
+
command: z.string().optional(),
|
|
437
|
+
args: z.union([z.array(z.string()), z.string()]).optional(),
|
|
438
|
+
url: z.string().optional(),
|
|
439
|
+
authToken: SecretInputSchema.optional(),
|
|
440
|
+
headers: z.record(z.string(), SecretInputSchema).optional(),
|
|
441
|
+
clearEnv: z.array(z.string()).optional(),
|
|
442
|
+
remoteWorkspaceRoot: codexAppServerRemoteWorkspaceRootSchema.optional(),
|
|
443
|
+
codeModeOnly: z.boolean().optional(),
|
|
444
|
+
loopDetectionPreToolUseRelay: z.boolean().optional(),
|
|
445
|
+
requestTimeoutMs: 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
|
+
if (asNullableRecord(asNullableRecord(value)?.appServer)?.approvalPolicy === "untrusted") throw new Error("plugins.entries.codex.config.appServer.approvalPolicy=\"untrusted\" is retired; run \"openclaw doctor --fix\" to migrate it to \"on-request\".");
|
|
457
|
+
const parsed = codexPluginConfigSchema.safeParse(value);
|
|
458
|
+
if (!parsed.success) return {};
|
|
459
|
+
const { codexPlugins: rawCodexPlugins, ...config } = parsed.data;
|
|
460
|
+
const plugins = codexPluginsConfigSchema.safeParse(rawCodexPlugins);
|
|
461
|
+
if (!plugins.success) return config;
|
|
462
|
+
return {
|
|
463
|
+
...config,
|
|
464
|
+
...plugins.data ? { codexPlugins: plugins.data } : {}
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
function isCodexSandboxExecServerEnabled(pluginConfig, sandbox) {
|
|
468
|
+
return isCodexRemoteExecPlacementSandbox(sandbox) || readCodexPluginConfig(pluginConfig).appServer?.experimental?.sandboxExecServer === true;
|
|
469
|
+
}
|
|
470
|
+
function isCodexRemoteExecPlacementSandbox(sandbox) {
|
|
471
|
+
return typeof sandbox === "object" && sandbox !== null && "placementExecutionMode" in sandbox && sandbox.placementExecutionMode === "remote-exec";
|
|
472
|
+
}
|
|
473
|
+
function isCodexPairedNodeRemoteExecPlacementSandbox(sandbox) {
|
|
474
|
+
return isCodexRemoteExecPlacementSandbox(sandbox) && typeof sandbox === "object" && sandbox !== null && "placementNodeId" in sandbox && typeof sandbox.placementNodeId === "string" && sandbox.placementNodeId.length > 0;
|
|
475
|
+
}
|
|
476
|
+
function assertCodexAppServerCommandHasNoInlineArgs(params) {
|
|
477
|
+
const inlineArgs = detectWindowsSpawnCommandInlineArgs(params.command);
|
|
478
|
+
if (!inlineArgs) return;
|
|
479
|
+
const sourceLabel = params.source === "env" ? "OPENCLAW_CODEX_APP_SERVER_BIN" : "plugins.entries.codex.config.appServer.command";
|
|
480
|
+
const argsLabel = params.source === "env" ? "OPENCLAW_CODEX_APP_SERVER_ARGS" : "plugins.entries.codex.config.appServer.args";
|
|
481
|
+
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.`);
|
|
482
|
+
}
|
|
483
|
+
function resolveCodexPluginsPolicy(pluginConfig) {
|
|
484
|
+
const config = readCodexPluginConfig(pluginConfig).codexPlugins;
|
|
485
|
+
const configured = config !== void 0;
|
|
486
|
+
const enabled = config?.enabled === true;
|
|
487
|
+
const destructivePolicy = resolveCodexPluginDestructivePolicy(config?.allow_destructive_actions ?? true);
|
|
488
|
+
const pluginPolicies = Object.entries(config?.plugins ?? {}).flatMap(([configKey, entry]) => {
|
|
489
|
+
if (!isCodexPluginMarketplaceName(entry.marketplaceName) || !entry.pluginName) return [];
|
|
490
|
+
const entryDestructivePolicy = resolveCodexPluginDestructivePolicy(entry.allow_destructive_actions ?? config?.allow_destructive_actions ?? true);
|
|
491
|
+
return [{
|
|
492
|
+
configKey,
|
|
493
|
+
marketplaceName: entry.marketplaceName,
|
|
494
|
+
pluginName: entry.pluginName,
|
|
495
|
+
enabled: enabled && entry.enabled !== false,
|
|
496
|
+
allowDestructiveActions: entryDestructivePolicy.allowDestructiveActions,
|
|
497
|
+
destructiveApprovalMode: entryDestructivePolicy.destructiveApprovalMode
|
|
498
|
+
}];
|
|
499
|
+
}).toSorted((left, right) => left.configKey.localeCompare(right.configKey));
|
|
500
|
+
return {
|
|
501
|
+
configured,
|
|
502
|
+
enabled,
|
|
503
|
+
allowAllPlugins: enabled && config?.allow_all_plugins === true,
|
|
504
|
+
allowDestructiveActions: destructivePolicy.allowDestructiveActions,
|
|
505
|
+
destructiveApprovalMode: destructivePolicy.destructiveApprovalMode,
|
|
506
|
+
pluginPolicies
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
function isCodexPluginMarketplaceName(value) {
|
|
510
|
+
return typeof value === "string" && CODEX_PLUGIN_MARKETPLACE_NAME_PATTERN.test(value);
|
|
511
|
+
}
|
|
512
|
+
function resolveCodexPluginDestructivePolicy(policy) {
|
|
513
|
+
if (policy === "auto" || policy === "ask") return {
|
|
514
|
+
allowDestructiveActions: true,
|
|
515
|
+
destructiveApprovalMode: policy
|
|
516
|
+
};
|
|
517
|
+
return {
|
|
518
|
+
allowDestructiveActions: policy,
|
|
519
|
+
destructiveApprovalMode: policy ? "allow" : "deny"
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
//#endregion
|
|
269
523
|
//#region extensions/codex/src/app-server/config-requirements.ts
|
|
270
524
|
const UNIX_CODEX_REQUIREMENTS_PATH = "/etc/codex/requirements.toml";
|
|
271
525
|
const WINDOWS_CODEX_REQUIREMENTS_SUFFIX = "\\OpenAI\\Codex\\requirements.toml";
|
|
@@ -461,15 +715,15 @@ function selectUserApprovalsReviewer(allowedApprovalsReviewers, execModeRequirin
|
|
|
461
715
|
}
|
|
462
716
|
//#endregion
|
|
463
717
|
//#region extensions/codex/src/app-server/config-reviewer.ts
|
|
464
|
-
const CODEX_APP_SERVER_HOME_DIRNAME = "codex-home";
|
|
465
718
|
const CODEX_CONFIG_TOML_FILENAME = "config.toml";
|
|
466
719
|
/** Cloud/system config can redirect reviews after local home/profile checks have passed. */
|
|
467
720
|
async function assertCodexModelBackedReviewerEffectiveConfig(params) {
|
|
468
721
|
if (params.approvalsReviewer !== "auto_review" && params.approvalsReviewer !== "guardian_subagent") return;
|
|
469
|
-
const
|
|
722
|
+
const response = await params.client.request("config/read", {
|
|
470
723
|
cwd: path.resolve(params.cwd),
|
|
471
724
|
includeLayers: false
|
|
472
|
-
}, { signal: params.signal })
|
|
725
|
+
}, { signal: params.signal });
|
|
726
|
+
const effectiveConfig = readRecord(readRecord(response)?.config);
|
|
473
727
|
if (!effectiveConfig) throw new Error("Codex config/read returned an invalid model-backed reviewer config");
|
|
474
728
|
const modelProvider = effectiveConfig.model_provider;
|
|
475
729
|
const providers = effectiveConfig.model_providers;
|
|
@@ -484,9 +738,8 @@ function isTrustedOptionalReviewerEndpoint(value, isTrusted) {
|
|
|
484
738
|
function canUseCodexModelBackedApprovalsReviewerForModel(params) {
|
|
485
739
|
const explicitProvider = params.modelProvider?.trim().toLowerCase();
|
|
486
740
|
const inferredProvider = inferProviderFromModelRef(params.model);
|
|
487
|
-
if (explicitProvider && explicitProvider !== "codex"
|
|
488
|
-
|
|
489
|
-
return isTrustedCodexModelBackedApprovalsReviewerProvider(explicitProvider, params);
|
|
741
|
+
if (explicitProvider && explicitProvider !== "codex" && explicitProvider !== "openai") return false;
|
|
742
|
+
return (inferredProvider ?? explicitProvider) === "openai" && isTrustedCodexModelBackedOpenAIProvider(params);
|
|
490
743
|
}
|
|
491
744
|
function isTrustedCodexModelBackedOpenAIProvider(params) {
|
|
492
745
|
if (!openAIBaseUrlEnvOverridesAreTrustedForModelBackedReview(params.env)) return false;
|
|
@@ -523,20 +776,6 @@ function resolveCodexModelBackedReviewerPolicyContext(params) {
|
|
|
523
776
|
model: params.model ?? params.bindingModel
|
|
524
777
|
};
|
|
525
778
|
}
|
|
526
|
-
function isCodexModelBackedApprovalsReviewerProvider(provider) {
|
|
527
|
-
return provider?.trim().toLowerCase() === "openai";
|
|
528
|
-
}
|
|
529
|
-
function isTrustedCodexModelBackedApprovalsReviewerProvider(provider, params) {
|
|
530
|
-
return isCodexModelBackedApprovalsReviewerProvider(provider) && isTrustedCodexModelBackedOpenAIProvider({
|
|
531
|
-
config: params.config,
|
|
532
|
-
env: params.env,
|
|
533
|
-
model: params.model,
|
|
534
|
-
agentDir: params.agentDir,
|
|
535
|
-
codexConfigToml: params.codexConfigToml,
|
|
536
|
-
homeScope: params.homeScope,
|
|
537
|
-
codexArgs: params.codexArgs
|
|
538
|
-
});
|
|
539
|
-
}
|
|
540
779
|
function readCodexBaseUrlOverridesForModelBackedReview(params) {
|
|
541
780
|
const configToml = readCodexAppServerConfigToml(params);
|
|
542
781
|
if (configToml === false) return false;
|
|
@@ -561,19 +800,13 @@ function readCodexBaseUrlOverridesForModelBackedReview(params) {
|
|
|
561
800
|
};
|
|
562
801
|
}
|
|
563
802
|
function readNativeCodexReviewerConfigOverrides(params) {
|
|
803
|
+
if (params.codexArgs?.some((arg) => !arg)) return false;
|
|
564
804
|
const overrides = [];
|
|
565
805
|
let profile;
|
|
566
|
-
const
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
if (arg === "--profile" || arg === "-p") profile = args[++index];
|
|
571
|
-
else if (arg.startsWith("--profile=")) profile = arg.slice(10);
|
|
572
|
-
else if (arg === "-c" || arg === "--config") {
|
|
573
|
-
const override = args[++index];
|
|
574
|
-
if (!override) return false;
|
|
575
|
-
overrides.push(`${override}\n`);
|
|
576
|
-
} else if (arg.startsWith("--config=")) overrides.push(`${arg.slice(9)}\n`);
|
|
806
|
+
for (const { name, value } of readCodexAppServerConfigOptions(params.codexArgs ?? [])) {
|
|
807
|
+
if (!value) return false;
|
|
808
|
+
if (name === "--profile" || name === "-p") profile = value;
|
|
809
|
+
else overrides.push(`${value}\n`);
|
|
577
810
|
}
|
|
578
811
|
if (profile) {
|
|
579
812
|
if (path.basename(profile) !== profile || profile === "." || profile === "..") return false;
|
|
@@ -623,13 +856,7 @@ function codexConfigEnablesNativeComputerUse(params) {
|
|
|
623
856
|
function resolveCodexAppServerConfigPath(params) {
|
|
624
857
|
if (params.homeScope === "user") return path.join(resolveCodexAppServerUserHomeDir(params.env), CODEX_CONFIG_TOML_FILENAME);
|
|
625
858
|
const agentDir = readNonEmptyString(params.agentDir);
|
|
626
|
-
|
|
627
|
-
return codexHome ? path.join(codexHome, CODEX_CONFIG_TOML_FILENAME) : void 0;
|
|
628
|
-
}
|
|
629
|
-
/** Resolves the native user Codex home used by Desktop and the CLI. */
|
|
630
|
-
function resolveCodexAppServerUserHomeDir(env = process.env, homedir$1 = homedir) {
|
|
631
|
-
const configured = readNonEmptyString(env.CODEX_HOME);
|
|
632
|
-
return path.resolve(configured ?? path.join(homedir$1(), ".codex"));
|
|
859
|
+
return agentDir ? path.join(resolveCodexAppServerHomeDir(agentDir), CODEX_CONFIG_TOML_FILENAME) : void 0;
|
|
633
860
|
}
|
|
634
861
|
function readErrorCode(error) {
|
|
635
862
|
return error && typeof error === "object" && "code" in error ? String(error.code) : void 0;
|
|
@@ -703,234 +930,6 @@ function inferProviderFromModelRef(model) {
|
|
|
703
930
|
return slashIndex > 0 ? normalized?.slice(0, slashIndex) : void 0;
|
|
704
931
|
}
|
|
705
932
|
//#endregion
|
|
706
|
-
//#region extensions/codex/src/app-server/config-contracts.ts
|
|
707
|
-
const CODEX_PLUGINS_MARKETPLACE_NAME = "openai-curated";
|
|
708
|
-
const CODEX_PLUGINS_WORKSPACE_MARKETPLACE_NAME = "workspace-directory";
|
|
709
|
-
const CODEX_PLUGIN_MARKETPLACE_NAME_PATTERN = /^[A-Za-z0-9_-]+$/;
|
|
710
|
-
//#endregion
|
|
711
|
-
//#region extensions/codex/src/app-server/session-discovery-config.ts
|
|
712
|
-
const codexSessionCatalogHomeSchema = z.union([z.string().trim().min(1), z.object({
|
|
713
|
-
path: z.string().trim().min(1),
|
|
714
|
-
label: z.string().trim().min(1).optional()
|
|
715
|
-
}).strict()]);
|
|
716
|
-
const codexSessionCatalogConfigSchema = z.object({
|
|
717
|
-
enabled: z.boolean().optional(),
|
|
718
|
-
homes: z.array(codexSessionCatalogHomeSchema).optional()
|
|
719
|
-
}).strict();
|
|
720
|
-
const codexDiscoveryConfigSchema = z.object({
|
|
721
|
-
enabled: z.boolean().optional(),
|
|
722
|
-
timeoutMs: z.number().positive().optional()
|
|
723
|
-
}).strict();
|
|
724
|
-
//#endregion
|
|
725
|
-
//#region extensions/codex/src/app-server/config-parsing.ts
|
|
726
|
-
const DEFAULT_CODEX_COMPUTER_USE_PLUGIN_NAME = "computer-use";
|
|
727
|
-
const DEFAULT_CODEX_COMPUTER_USE_MARKETPLACE_DISCOVERY_TIMEOUT_MS = 6e4;
|
|
728
|
-
const DEFAULT_CODEX_COMPUTER_USE_LIVE_TEST_TIMEOUT_MS = 6e4;
|
|
729
|
-
const DEFAULT_CODEX_COMPUTER_USE_TOOL_CALL_TIMEOUT_MS = 6e4;
|
|
730
|
-
const DEFAULT_CODEX_APP_SERVER_NETWORK_PROXY_PROFILE_PREFIX = "openclaw-network";
|
|
731
|
-
const codexAppServerTransportSchema = z.enum([
|
|
732
|
-
"stdio",
|
|
733
|
-
"websocket",
|
|
734
|
-
"unix"
|
|
735
|
-
]);
|
|
736
|
-
const codexAppServerHomeScopeSchema = z.enum(["agent", "user"]);
|
|
737
|
-
const SecretInputSchema = buildSecretInputSchema();
|
|
738
|
-
const codexAppServerPolicyModeSchema = z.enum(["yolo", "guardian"]);
|
|
739
|
-
const codexAppServerApprovalPolicySchema = z.preprocess((value) => value === "on-failure" ? "on-request" : value, z.enum(["never", "on-request"]));
|
|
740
|
-
const codexAppServerSandboxSchema = z.enum([
|
|
741
|
-
"read-only",
|
|
742
|
-
"workspace-write",
|
|
743
|
-
"danger-full-access"
|
|
744
|
-
]);
|
|
745
|
-
const codexAppServerApprovalsReviewerSchema = z.enum([
|
|
746
|
-
"user",
|
|
747
|
-
"auto_review",
|
|
748
|
-
"guardian_subagent"
|
|
749
|
-
]);
|
|
750
|
-
const codexDynamicToolsLoadingSchema = z.enum(["searchable", "direct"]);
|
|
751
|
-
const codexComputerUseHealthIntervalSchema = z.union([
|
|
752
|
-
z.literal(30),
|
|
753
|
-
z.literal(60),
|
|
754
|
-
z.literal(120),
|
|
755
|
-
z.literal(240)
|
|
756
|
-
]);
|
|
757
|
-
const codexComputerUsePluginCacheModeSchema = z.enum(["shared", "independent"]);
|
|
758
|
-
const codexPluginDestructivePolicySchema = z.union([
|
|
759
|
-
z.boolean(),
|
|
760
|
-
z.literal("auto"),
|
|
761
|
-
z.literal("ask")
|
|
762
|
-
]);
|
|
763
|
-
const codexAppServerServiceTierSchema = z.preprocess((value) => value === null ? null : normalizeCodexServiceTier(value), z.string().trim().min(1).nullable().optional()).optional();
|
|
764
|
-
const codexAppServerExperimentalSchema = z.object({ sandboxExecServer: z.boolean().optional() }).strict();
|
|
765
|
-
const codexAppServerRemoteWorkspaceRootSchema = z.string().trim().min(1);
|
|
766
|
-
const codexAppServerNetworkProxyDomainPermissionSchema = z.enum(["allow", "deny"]);
|
|
767
|
-
const codexAppServerNetworkProxyUnixSocketPermissionSchema = z.enum(["allow", "none"]);
|
|
768
|
-
const codexAppServerNetworkProxySchema = z.object({
|
|
769
|
-
enabled: z.boolean().optional(),
|
|
770
|
-
profileName: z.string().trim().min(1).optional(),
|
|
771
|
-
baseProfile: z.enum(["read-only", "workspace"]).optional(),
|
|
772
|
-
mode: z.enum(["limited", "full"]).optional(),
|
|
773
|
-
domains: z.record(z.string(), codexAppServerNetworkProxyDomainPermissionSchema).optional(),
|
|
774
|
-
unixSockets: z.record(z.string(), codexAppServerNetworkProxyUnixSocketPermissionSchema).optional(),
|
|
775
|
-
proxyUrl: z.string().trim().min(1).optional(),
|
|
776
|
-
socksUrl: z.string().trim().min(1).optional(),
|
|
777
|
-
enableSocks5: z.boolean().optional(),
|
|
778
|
-
enableSocks5Udp: z.boolean().optional(),
|
|
779
|
-
allowUpstreamProxy: z.boolean().optional(),
|
|
780
|
-
allowLocalBinding: z.boolean().optional(),
|
|
781
|
-
dangerouslyAllowNonLoopbackProxy: z.boolean().optional(),
|
|
782
|
-
dangerouslyAllowAllUnixSockets: z.boolean().optional()
|
|
783
|
-
}).strict();
|
|
784
|
-
const codexPluginEntryConfigSchema = z.object({
|
|
785
|
-
enabled: z.boolean().optional(),
|
|
786
|
-
marketplaceName: z.string().regex(CODEX_PLUGIN_MARKETPLACE_NAME_PATTERN).optional(),
|
|
787
|
-
pluginName: z.string().trim().min(1).optional(),
|
|
788
|
-
allow_destructive_actions: codexPluginDestructivePolicySchema.optional()
|
|
789
|
-
}).strict();
|
|
790
|
-
const codexPluginsConfigSchema = z.object({
|
|
791
|
-
enabled: z.boolean().optional(),
|
|
792
|
-
allow_all_plugins: z.boolean().optional(),
|
|
793
|
-
allow_destructive_actions: codexPluginDestructivePolicySchema.optional(),
|
|
794
|
-
plugins: z.record(z.string(), codexPluginEntryConfigSchema).optional()
|
|
795
|
-
}).strict();
|
|
796
|
-
const codexSupervisionEndpointSchema = z.union([z.object({
|
|
797
|
-
id: z.string().optional(),
|
|
798
|
-
label: z.string().optional(),
|
|
799
|
-
transport: z.literal("stdio-proxy").optional(),
|
|
800
|
-
command: z.string().optional(),
|
|
801
|
-
args: z.array(z.string()).optional(),
|
|
802
|
-
cwd: z.string().optional()
|
|
803
|
-
}).strict(), z.object({
|
|
804
|
-
id: z.string().optional(),
|
|
805
|
-
label: z.string().optional(),
|
|
806
|
-
transport: z.literal("websocket"),
|
|
807
|
-
url: z.string(),
|
|
808
|
-
authTokenEnv: z.string().optional()
|
|
809
|
-
}).strict()]);
|
|
810
|
-
const codexSupervisionConfigSchema = z.object({
|
|
811
|
-
enabled: z.boolean().optional(),
|
|
812
|
-
endpoints: z.array(codexSupervisionEndpointSchema).optional(),
|
|
813
|
-
allowRawTranscripts: z.boolean().optional(),
|
|
814
|
-
allowWriteControls: z.boolean().optional()
|
|
815
|
-
}).strict();
|
|
816
|
-
const codexPluginConfigSchema = z.object({
|
|
817
|
-
codexDynamicToolsLoading: codexDynamicToolsLoadingSchema.optional(),
|
|
818
|
-
codexDynamicToolsExclude: z.array(z.string()).optional(),
|
|
819
|
-
sessionCatalog: codexSessionCatalogConfigSchema.optional(),
|
|
820
|
-
discovery: codexDiscoveryConfigSchema.optional(),
|
|
821
|
-
computerUse: z.object({
|
|
822
|
-
enabled: z.boolean().optional(),
|
|
823
|
-
autoInstall: z.boolean().optional(),
|
|
824
|
-
marketplaceDiscoveryTimeoutMs: z.number().positive().optional(),
|
|
825
|
-
liveTestTimeoutMs: z.number().positive().optional(),
|
|
826
|
-
toolCallTimeoutMs: z.number().positive().optional(),
|
|
827
|
-
healthCheckEnabled: z.boolean().optional(),
|
|
828
|
-
healthCheckIntervalMinutes: codexComputerUseHealthIntervalSchema.optional(),
|
|
829
|
-
pluginCacheMode: codexComputerUsePluginCacheModeSchema.optional(),
|
|
830
|
-
strictReadiness: z.boolean().optional(),
|
|
831
|
-
autoRepair: z.boolean().optional(),
|
|
832
|
-
marketplaceSource: z.string().optional(),
|
|
833
|
-
marketplacePath: z.string().optional(),
|
|
834
|
-
marketplaceName: z.string().optional(),
|
|
835
|
-
pluginName: z.string().optional(),
|
|
836
|
-
mcpServerName: z.string().optional()
|
|
837
|
-
}).strict().optional(),
|
|
838
|
-
codexPlugins: z.unknown().optional(),
|
|
839
|
-
supervision: codexSupervisionConfigSchema.optional(),
|
|
840
|
-
appServer: z.object({
|
|
841
|
-
mode: codexAppServerPolicyModeSchema.optional(),
|
|
842
|
-
transport: codexAppServerTransportSchema.optional(),
|
|
843
|
-
homeScope: codexAppServerHomeScopeSchema.optional(),
|
|
844
|
-
command: z.string().optional(),
|
|
845
|
-
args: z.union([z.array(z.string()), z.string()]).optional(),
|
|
846
|
-
url: z.string().optional(),
|
|
847
|
-
authToken: SecretInputSchema.optional(),
|
|
848
|
-
headers: z.record(z.string(), SecretInputSchema).optional(),
|
|
849
|
-
clearEnv: z.array(z.string()).optional(),
|
|
850
|
-
remoteWorkspaceRoot: codexAppServerRemoteWorkspaceRootSchema.optional(),
|
|
851
|
-
codeModeOnly: z.boolean().optional(),
|
|
852
|
-
loopDetectionPreToolUseRelay: z.boolean().optional(),
|
|
853
|
-
requestTimeoutMs: z.number().positive().optional(),
|
|
854
|
-
turnCompletionIdleTimeoutMs: z.number().positive().optional(),
|
|
855
|
-
turnAssistantCompletionIdleTimeoutMs: z.number().positive().optional(),
|
|
856
|
-
postToolRawAssistantCompletionIdleTimeoutMs: z.number().positive().optional(),
|
|
857
|
-
approvalPolicy: codexAppServerApprovalPolicySchema.optional(),
|
|
858
|
-
sandbox: codexAppServerSandboxSchema.optional(),
|
|
859
|
-
approvalsReviewer: codexAppServerApprovalsReviewerSchema.optional(),
|
|
860
|
-
serviceTier: codexAppServerServiceTierSchema,
|
|
861
|
-
networkProxy: codexAppServerNetworkProxySchema.optional(),
|
|
862
|
-
defaultWorkspaceDir: z.string().optional(),
|
|
863
|
-
experimental: codexAppServerExperimentalSchema.optional()
|
|
864
|
-
}).strict().optional()
|
|
865
|
-
}).strict();
|
|
866
|
-
function readCodexPluginConfig(value) {
|
|
867
|
-
if (asNullableRecord(asNullableRecord(value)?.appServer)?.approvalPolicy === "untrusted") throw new Error("plugins.entries.codex.config.appServer.approvalPolicy=\"untrusted\" is retired; run \"openclaw doctor --fix\" to migrate it to \"on-request\".");
|
|
868
|
-
const parsed = codexPluginConfigSchema.safeParse(value);
|
|
869
|
-
if (!parsed.success) return {};
|
|
870
|
-
const { codexPlugins: rawCodexPlugins, ...config } = parsed.data;
|
|
871
|
-
const plugins = codexPluginsConfigSchema.safeParse(rawCodexPlugins);
|
|
872
|
-
if (!plugins.success) return config;
|
|
873
|
-
return {
|
|
874
|
-
...config,
|
|
875
|
-
...plugins.data ? { codexPlugins: plugins.data } : {}
|
|
876
|
-
};
|
|
877
|
-
}
|
|
878
|
-
function isCodexSandboxExecServerEnabled(pluginConfig, sandbox) {
|
|
879
|
-
return isCodexRemoteExecPlacementSandbox(sandbox) || readCodexPluginConfig(pluginConfig).appServer?.experimental?.sandboxExecServer === true;
|
|
880
|
-
}
|
|
881
|
-
function isCodexRemoteExecPlacementSandbox(sandbox) {
|
|
882
|
-
return typeof sandbox === "object" && sandbox !== null && "placementExecutionMode" in sandbox && sandbox.placementExecutionMode === "remote-exec";
|
|
883
|
-
}
|
|
884
|
-
function isCodexPairedNodeRemoteExecPlacementSandbox(sandbox) {
|
|
885
|
-
return isCodexRemoteExecPlacementSandbox(sandbox) && typeof sandbox === "object" && sandbox !== null && "placementNodeId" in sandbox && typeof sandbox.placementNodeId === "string" && sandbox.placementNodeId.length > 0;
|
|
886
|
-
}
|
|
887
|
-
function assertCodexAppServerCommandHasNoInlineArgs(params) {
|
|
888
|
-
const inlineArgs = detectWindowsSpawnCommandInlineArgs(params.command);
|
|
889
|
-
if (!inlineArgs) return;
|
|
890
|
-
const sourceLabel = params.source === "env" ? "OPENCLAW_CODEX_APP_SERVER_BIN" : "plugins.entries.codex.config.appServer.command";
|
|
891
|
-
const argsLabel = params.source === "env" ? "OPENCLAW_CODEX_APP_SERVER_ARGS" : "plugins.entries.codex.config.appServer.args";
|
|
892
|
-
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.`);
|
|
893
|
-
}
|
|
894
|
-
function resolveCodexPluginsPolicy(pluginConfig) {
|
|
895
|
-
const config = readCodexPluginConfig(pluginConfig).codexPlugins;
|
|
896
|
-
const configured = config !== void 0;
|
|
897
|
-
const enabled = config?.enabled === true;
|
|
898
|
-
const destructivePolicy = resolveCodexPluginDestructivePolicy(config?.allow_destructive_actions ?? true);
|
|
899
|
-
const pluginPolicies = Object.entries(config?.plugins ?? {}).flatMap(([configKey, entry]) => {
|
|
900
|
-
if (!isCodexPluginMarketplaceName(entry.marketplaceName) || !entry.pluginName) return [];
|
|
901
|
-
const entryDestructivePolicy = resolveCodexPluginDestructivePolicy(entry.allow_destructive_actions ?? config?.allow_destructive_actions ?? true);
|
|
902
|
-
return [{
|
|
903
|
-
configKey,
|
|
904
|
-
marketplaceName: entry.marketplaceName,
|
|
905
|
-
pluginName: entry.pluginName,
|
|
906
|
-
enabled: enabled && entry.enabled !== false,
|
|
907
|
-
allowDestructiveActions: entryDestructivePolicy.allowDestructiveActions,
|
|
908
|
-
destructiveApprovalMode: entryDestructivePolicy.destructiveApprovalMode
|
|
909
|
-
}];
|
|
910
|
-
}).toSorted((left, right) => left.configKey.localeCompare(right.configKey));
|
|
911
|
-
return {
|
|
912
|
-
configured,
|
|
913
|
-
enabled,
|
|
914
|
-
allowAllPlugins: enabled && config?.allow_all_plugins === true,
|
|
915
|
-
allowDestructiveActions: destructivePolicy.allowDestructiveActions,
|
|
916
|
-
destructiveApprovalMode: destructivePolicy.destructiveApprovalMode,
|
|
917
|
-
pluginPolicies
|
|
918
|
-
};
|
|
919
|
-
}
|
|
920
|
-
function isCodexPluginMarketplaceName(value) {
|
|
921
|
-
return typeof value === "string" && CODEX_PLUGIN_MARKETPLACE_NAME_PATTERN.test(value);
|
|
922
|
-
}
|
|
923
|
-
function resolveCodexPluginDestructivePolicy(policy) {
|
|
924
|
-
if (policy === "auto" || policy === "ask") return {
|
|
925
|
-
allowDestructiveActions: true,
|
|
926
|
-
destructiveApprovalMode: policy
|
|
927
|
-
};
|
|
928
|
-
return {
|
|
929
|
-
allowDestructiveActions: policy,
|
|
930
|
-
destructiveApprovalMode: policy ? "allow" : "deny"
|
|
931
|
-
};
|
|
932
|
-
}
|
|
933
|
-
//#endregion
|
|
934
933
|
//#region extensions/codex/src/app-server/config-security.ts
|
|
935
934
|
function shouldAutoApproveCodexAppServerApprovals(appServer) {
|
|
936
935
|
return appServer.networkProxy === void 0 && appServer.approvalPolicy === "never" && appServer.sandbox === "danger-full-access";
|
|
@@ -974,10 +973,11 @@ function resolveCodexAppServerNetworkProxy(config, sandbox) {
|
|
|
974
973
|
function resolveNetworkProxyPermissionProfileName(config, profile) {
|
|
975
974
|
const explicitProfileName = readNonEmptyString(config.profileName);
|
|
976
975
|
if (explicitProfileName) return explicitProfileName;
|
|
977
|
-
|
|
976
|
+
const suffix = createHash("sha256").update(stableStringifyJson({
|
|
978
977
|
version: 1,
|
|
979
978
|
profile
|
|
980
|
-
})).digest("hex").slice(0, 16)
|
|
979
|
+
})).digest("hex").slice(0, 16);
|
|
980
|
+
return `${DEFAULT_CODEX_APP_SERVER_NETWORK_PROXY_PROFILE_PREFIX}-${suffix}`;
|
|
981
981
|
}
|
|
982
982
|
function fingerprintCodexAppServerNetworkProxyConfigPatch(configPatch) {
|
|
983
983
|
return createHash("sha256").update(stableStringifyJson(configPatch)).digest("hex");
|
|
@@ -994,6 +994,16 @@ function stableStringifyJson(value) {
|
|
|
994
994
|
if (value && typeof value === "object") return `{${Object.entries(value).toSorted(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${stableStringifyJson(item)}`).join(",")}}`;
|
|
995
995
|
return JSON.stringify(value);
|
|
996
996
|
}
|
|
997
|
+
/** Explicit MCP prompting must bypass Codex's unconditional Never-policy approval. */
|
|
998
|
+
function hasCodexMcpToolApprovalOverrides(servers, serverNames, projectedMcpServers) {
|
|
999
|
+
const modes = new Map(Object.entries(projectedMcpServers ?? {}).map(([name, server]) => [name, server.default_tools_approval_mode]));
|
|
1000
|
+
for (const name of serverNames ?? Object.keys(servers ?? {})) {
|
|
1001
|
+
const server = servers?.[name];
|
|
1002
|
+
const mode = server?.codex?.defaultToolsApprovalMode;
|
|
1003
|
+
if (mode !== void 0 && (serverNames !== void 0 || server?.enabled !== false)) modes.set(name, mode);
|
|
1004
|
+
}
|
|
1005
|
+
return [...modes.values()].some((mode) => mode === "auto" || mode === "prompt");
|
|
1006
|
+
}
|
|
997
1007
|
function withMcpElicitationsApprovalPolicy(policy) {
|
|
998
1008
|
if (policy === "untrusted") return policy;
|
|
999
1009
|
if (typeof policy !== "string") return { granular: {
|
|
@@ -1243,9 +1253,6 @@ function resolveCodexAppServerRuntimeOptions(params = {}) {
|
|
|
1243
1253
|
codeModeOnly: config.codeModeOnly === true,
|
|
1244
1254
|
loopDetectionPreToolUseRelay: config.loopDetectionPreToolUseRelay !== false,
|
|
1245
1255
|
requestTimeoutMs: normalizePositiveNumber(config.requestTimeoutMs, 6e4),
|
|
1246
|
-
turnCompletionIdleTimeoutMs: normalizePositiveNumber(config.turnCompletionIdleTimeoutMs, 6e4),
|
|
1247
|
-
turnAssistantCompletionIdleTimeoutMs: normalizePositiveNumber(config.turnAssistantCompletionIdleTimeoutMs, 1e4),
|
|
1248
|
-
...config.postToolRawAssistantCompletionIdleTimeoutMs !== void 0 ? { postToolRawAssistantCompletionIdleTimeoutMs: normalizePositiveNumber(config.postToolRawAssistantCompletionIdleTimeoutMs, 6e4) } : {},
|
|
1249
1256
|
approvalPolicy: forcedPolicy?.approvalPolicy ?? approvalPolicy,
|
|
1250
1257
|
approvalPolicySource,
|
|
1251
1258
|
sandbox: resolvedSandbox,
|
|
@@ -1346,17 +1353,22 @@ function codexSandboxPolicyForTurn(mode, cwd, nativeArgs = []) {
|
|
|
1346
1353
|
};
|
|
1347
1354
|
let excludeTmpdirEnvVar = false;
|
|
1348
1355
|
let excludeSlashTmp = false;
|
|
1349
|
-
for (
|
|
1350
|
-
|
|
1351
|
-
const override = arg === "-c" || arg === "--config" ? nativeArgs[++index] : arg?.startsWith("--config=") ? arg.slice(9) : void 0;
|
|
1352
|
-
if (!override) continue;
|
|
1356
|
+
for (const { name, value: override } of readCodexAppServerConfigOptions(nativeArgs)) {
|
|
1357
|
+
if (name !== "-c" && name !== "--config" || !override) continue;
|
|
1353
1358
|
const separator = override.indexOf("=");
|
|
1354
1359
|
if (separator < 0) continue;
|
|
1355
1360
|
const key = override.slice(0, separator).trim();
|
|
1356
|
-
const
|
|
1357
|
-
if (
|
|
1358
|
-
|
|
1359
|
-
|
|
1361
|
+
const isTmpdirExclusion = key === "sandbox_workspace_write.exclude_tmpdir_env_var";
|
|
1362
|
+
if (!isTmpdirExclusion && key !== "sandbox_workspace_write.exclude_slash_tmp") continue;
|
|
1363
|
+
let value;
|
|
1364
|
+
try {
|
|
1365
|
+
value = parse(`_x_ = ${override.slice(separator + 1).trim()}`)["_x_"];
|
|
1366
|
+
} catch {
|
|
1367
|
+
continue;
|
|
1368
|
+
}
|
|
1369
|
+
if (typeof value !== "boolean") continue;
|
|
1370
|
+
if (isTmpdirExclusion) excludeTmpdirEnvVar = value;
|
|
1371
|
+
else excludeSlashTmp = value;
|
|
1360
1372
|
}
|
|
1361
1373
|
return {
|
|
1362
1374
|
type: "workspaceWrite",
|
|
@@ -1386,4 +1398,4 @@ function resolveCodexSupervisionAppServerRuntimeOptions(params = {}) {
|
|
|
1386
1398
|
});
|
|
1387
1399
|
}
|
|
1388
1400
|
//#endregion
|
|
1389
|
-
export {
|
|
1401
|
+
export { isCodexFastServiceTier as A, isCodexPairedNodeRemoteExecPlacementSandbox as C, resolveCodexPluginsPolicy as D, readCodexPluginConfig as E, resolveCodexAppServerHomeDir as F, resolveCodexAppServerLocalHomeDir as I, resolveCodexAppServerUserHomeDir as L, CODEX_PLUGINS_MARKETPLACE_NAME as M, CODEX_PLUGINS_WORKSPACE_MARKETPLACE_NAME as N, resolveOpenClawExecPolicyForCodexAppServer as O, CODEX_PLUGIN_MARKETPLACE_NAME_PATTERN as P, withEphemeralCodexAuthStore as R, selectUserApprovalsReviewer as S, isCodexSandboxExecServerEnabled as T, parseAllowedApprovalsReviewersFromCodexRequirements as _, resolveCodexAppServerStartOptionsForAgent as a, selectGuardianApprovalPolicy as b, assertCodexAppServerConnectionSecurity as c, shouldAutoApproveCodexAppServerApprovals as d, withMcpElicitationsApprovalPolicy as f, parseAllowedApprovalPoliciesFromCodexRequirements as g, resolveCodexModelBackedReviewerPolicyContext as h, resolveCodexAppServerRuntimeOptions as i, normalizeCodexServiceTier as j, selectGuardianSandbox as k, hasCodexMcpToolApprovalOverrides as l, canUseCodexModelBackedApprovalsReviewerForModel as m, codexSandboxPolicyForTurn as n, resolveCodexComputerUseConfig as o, assertCodexModelBackedReviewerEffectiveConfig as p, resolveCodexAppServerHomeScope as r, resolveCodexSupervisionAppServerRuntimeOptions as s, codexAppServerStartOptionsKey as t, resolveCodexAppServerNetworkProxy as u, parseAllowedSandboxModesFromCodexRequirements as v, isCodexRemoteExecPlacementSandbox as w, selectGuardianApprovalsReviewer as x, readCodexRequirementsToml as y };
|