@openclaw/codex 2026.8.1-beta.3 → 2026.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.js +5 -6
- package/dist/{attempt-client-cleanup-URjUlCHg.js → attempt-client-cleanup-CpVfwctT.js} +47 -5
- package/dist/{auth-binding-B4FfbcCg.js → auth-binding-Ds_QVm-X.js} +18 -3
- package/dist/{binding-connection-DAvZwp96.js → binding-connection-CF7BmrDk.js} +2 -2
- package/dist/{bounded-turn-4BjrZEwW.js → bounded-turn-DRC3hcjm.js} +16 -20
- package/dist/{capabilities-CH3K57v4.js → capabilities-D6m_TdVy.js} +1 -1
- package/dist/cli-metadata.js +1 -1
- package/dist/{command-formatters-D0nZ3qtd.js → command-formatters--UToCokS.js} +4 -3
- package/dist/{command-handlers-DC86lgT4.js → command-handlers-CLFx2Ypa.js} +114 -79
- package/dist/{compact-COqgBRny.js → compact-5xqW1oCh.js} +13 -12
- package/dist/{config-CpNeo5AE.js → config-CcYL77O6.js} +350 -288
- package/dist/{conversation-binding-data-CW2GuupV.js → conversation-binding-data-BiodpIzq.js} +2 -1
- package/dist/doctor-contract-api.js +121 -16
- package/dist/{dynamic-tools-fJZhl4CE.js → dynamic-tools-BmeXjwNZ.js} +243 -1002
- package/dist/{effective-mcp-catalog-4YKn51aG.js → effective-mcp-catalog-XXQKgK1U.js} +2 -2
- package/dist/{event-projector-assistant-message-BwxV4d6N.js → event-projector-assistant-message-C5-Ds8mA.js} +18 -1
- package/dist/{event-projector-usage-CLwNEJqW.js → event-projector-usage-B2r5vhWH.js} +9 -14
- package/dist/{harness-DoKQcF8n.js → harness-BgeB7LnD.js} +42 -52
- package/dist/harness.js +1 -1
- package/dist/index.js +308 -306
- package/dist/{isolated-completion-DPMtlH9r.js → isolated-completion-CxTus3vZ.js} +4 -4
- package/dist/launch-args-sXOAg0SX.js +84 -0
- package/dist/{managed-binary-By4FZC6i.js → managed-binary-ZkGodW19.js} +43 -7
- package/dist/media-understanding-provider.js +1 -1
- package/dist/model-catalog-DULBcniB.js +101 -0
- package/dist/{models-CZw1wClT.js → models-DaWfETQk.js} +27 -29
- package/dist/{native-subagent-monitor-GGq3RnOo.js → native-subagent-monitor-vXYUZH37.js} +226 -129
- package/dist/{node-exec-server.runtime-Bsu1LdFZ.js → node-exec-server.runtime-DirKVZ5h.js} +9 -6
- package/dist/{plugin-approval-roundtrip-C75Yiiwc.js → plugin-approval-roundtrip-CCWQGlAI.js} +2 -1
- package/dist/{plugin-marketplace-discovery-CSWDkMrP.js → plugin-marketplace-discovery-BXjIFEiw.js} +38 -46
- package/dist/{plugin-metadata-cache-BXH5NF-4.js → plugin-metadata-cache-DQQm4gWT.js} +163 -136
- package/dist/{protocol-validators-VAVyEnDp.js → protocol-validators-Bg5rpNxk.js} +148 -5
- package/dist/{rate-limits-BI1dMHDG.js → rate-limits-BqHEHXQJ.js} +3 -2
- package/dist/{sandbox-guard-C1qEeZ5C.js → request-BWxweEdK.js} +183 -2
- package/dist/{run-attempt-BV3HzuCf.js → run-attempt-BVLE4Gbi.js} +706 -517
- package/dist/{runtime-artifact-BvyT1uyd.js → runtime-artifact-D9pYp4zL.js} +3 -3
- package/dist/{session-binding-BTrLf9Qm.js → session-binding-D0zinCP1.js} +195 -122
- package/dist/{session-catalog-ezP_UcRM.js → session-catalog-eMhVm0Ql.js} +448 -313
- package/dist/session-catalog-home-id-Dt2GiG5o.js +112 -0
- package/dist/{session-cli-B1hKvfkI.js → session-cli-B2lyjJA0.js} +1 -1
- package/dist/session-history-C5J1AKzG.js +87 -0
- package/dist/session-permission-policy-ScnAyG90.js +160 -0
- package/dist/session-retirement-CtUtUTr9.js +90 -0
- package/dist/{session-upstream-marker-D_2npHlA.js → session-upstream-marker-gqrYIRHk.js} +2 -3
- package/dist/settled-turn-context-Bk3IUwod.js +290 -0
- package/dist/settled-turn-finalizer-BXLN9PfJ.js +104 -0
- package/dist/{shared-client-Dw-rzii0.js → shared-client-B1tT5U6r.js} +1738 -806
- package/dist/{side-question-DbXkJZzg.js → side-question-CZ-mCw-t.js} +76 -43
- package/dist/{thread-lifecycle-DKdrnTMX.js → thread-lifecycle-CGGKP720.js} +991 -455
- package/dist/{thread-ownership-i2NBwDUL.js → thread-ownership-RkaoZCmQ.js} +18 -8
- package/dist/{plugin-app-cache-key-DMNQ8Zi8.js → thread-resume-BFt1-ZDa.js} +55 -8
- package/dist/{transcript-mirror-BU0_LKAL.js → transcript-mirror-1ep4XjzF.js} +124 -18
- package/dist/transport-stdio-NT_Dpd9V.js +724 -0
- package/dist/{upstream-prompt-provenance-CFmsKwr9.js → upstream-prompt-provenance-LphB8slG.js} +8 -4
- package/dist/{upstream-session-fork-BDVJCLAD.js → upstream-session-fork-Dc8BFExw.js} +76 -90
- package/dist/{usage-9dKJCgcy.js → usage-DUhd58gI.js} +3 -3
- package/dist/{web-search-provider.runtime-DCdx4DGu.js → web-search-provider.runtime-BEmlE7ov.js} +3 -3
- package/openclaw.plugin.json +19 -1
- package/package.json +8 -8
- package/dist/app-server-policy-bg5QPSVP.js +0 -25
- package/dist/command-rpc-xUIIonsO.js +0 -90
- package/dist/incognito-session-ET_ufDH-.js +0 -2
- package/dist/model-catalog-CmGoqVKB.js +0 -48
- package/dist/request-DSK0W6YI.js +0 -157
- package/dist/session-catalog-home-id-BNwAJ9D7.js +0 -18
- package/dist/session-retirement-CE4iMiLh.js +0 -36
- package/dist/settled-turn-finalizer-Dx1onIqg.js +0 -328
- package/dist/thread-resume-CdJk2Ehf.js +0 -30
- package/dist/transport-stdio-DhoGy33Z.js +0 -99
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as readCodexAppServerConfigOptions, t as normalizeCodexAppServerArgs } from "./launch-args-sXOAg0SX.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();
|
|
@@ -118,8 +152,9 @@ function selectGuardianSandbox(allowedSandboxModes) {
|
|
|
118
152
|
return "workspace-write";
|
|
119
153
|
}
|
|
120
154
|
function resolveApprovalPolicy(value) {
|
|
155
|
+
if (value === "untrusted") throw new Error("Codex app-server approval policy \"untrusted\" is retired; run \"openclaw doctor --fix\" and use \"on-request\".");
|
|
121
156
|
if (value === "on-failure") return "on-request";
|
|
122
|
-
return value === "on-request" || value === "
|
|
157
|
+
return value === "on-request" || value === "never" ? value : void 0;
|
|
123
158
|
}
|
|
124
159
|
function resolveSandbox(value) {
|
|
125
160
|
return value === "read-only" || value === "workspace-write" || value === "danger-full-access" ? value : void 0;
|
|
@@ -265,6 +300,229 @@ function readExecMode(value) {
|
|
|
265
300
|
return value === "deny" || value === "allowlist" || value === "ask" || value === "auto" || value === "full" ? value : void 0;
|
|
266
301
|
}
|
|
267
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
|
+
turnCompletionIdleTimeoutMs: z.number().positive().optional(),
|
|
447
|
+
turnAssistantCompletionIdleTimeoutMs: z.number().positive().optional(),
|
|
448
|
+
postToolRawAssistantCompletionIdleTimeoutMs: z.number().positive().optional(),
|
|
449
|
+
approvalPolicy: codexAppServerApprovalPolicySchema.optional(),
|
|
450
|
+
sandbox: codexAppServerSandboxSchema.optional(),
|
|
451
|
+
approvalsReviewer: codexAppServerApprovalsReviewerSchema.optional(),
|
|
452
|
+
serviceTier: codexAppServerServiceTierSchema,
|
|
453
|
+
networkProxy: codexAppServerNetworkProxySchema.optional(),
|
|
454
|
+
defaultWorkspaceDir: z.string().optional(),
|
|
455
|
+
experimental: codexAppServerExperimentalSchema.optional()
|
|
456
|
+
}).strict().optional()
|
|
457
|
+
}).strict();
|
|
458
|
+
function readCodexPluginConfig(value) {
|
|
459
|
+
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\".");
|
|
460
|
+
const parsed = codexPluginConfigSchema.safeParse(value);
|
|
461
|
+
if (!parsed.success) return {};
|
|
462
|
+
const { codexPlugins: rawCodexPlugins, ...config } = parsed.data;
|
|
463
|
+
const plugins = codexPluginsConfigSchema.safeParse(rawCodexPlugins);
|
|
464
|
+
if (!plugins.success) return config;
|
|
465
|
+
return {
|
|
466
|
+
...config,
|
|
467
|
+
...plugins.data ? { codexPlugins: plugins.data } : {}
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
function isCodexSandboxExecServerEnabled(pluginConfig, sandbox) {
|
|
471
|
+
return isCodexRemoteExecPlacementSandbox(sandbox) || readCodexPluginConfig(pluginConfig).appServer?.experimental?.sandboxExecServer === true;
|
|
472
|
+
}
|
|
473
|
+
function isCodexRemoteExecPlacementSandbox(sandbox) {
|
|
474
|
+
return typeof sandbox === "object" && sandbox !== null && "placementExecutionMode" in sandbox && sandbox.placementExecutionMode === "remote-exec";
|
|
475
|
+
}
|
|
476
|
+
function isCodexPairedNodeRemoteExecPlacementSandbox(sandbox) {
|
|
477
|
+
return isCodexRemoteExecPlacementSandbox(sandbox) && typeof sandbox === "object" && sandbox !== null && "placementNodeId" in sandbox && typeof sandbox.placementNodeId === "string" && sandbox.placementNodeId.length > 0;
|
|
478
|
+
}
|
|
479
|
+
function assertCodexAppServerCommandHasNoInlineArgs(params) {
|
|
480
|
+
const inlineArgs = detectWindowsSpawnCommandInlineArgs(params.command);
|
|
481
|
+
if (!inlineArgs) return;
|
|
482
|
+
const sourceLabel = params.source === "env" ? "OPENCLAW_CODEX_APP_SERVER_BIN" : "plugins.entries.codex.config.appServer.command";
|
|
483
|
+
const argsLabel = params.source === "env" ? "OPENCLAW_CODEX_APP_SERVER_ARGS" : "plugins.entries.codex.config.appServer.args";
|
|
484
|
+
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.`);
|
|
485
|
+
}
|
|
486
|
+
function resolveCodexPluginsPolicy(pluginConfig) {
|
|
487
|
+
const config = readCodexPluginConfig(pluginConfig).codexPlugins;
|
|
488
|
+
const configured = config !== void 0;
|
|
489
|
+
const enabled = config?.enabled === true;
|
|
490
|
+
const destructivePolicy = resolveCodexPluginDestructivePolicy(config?.allow_destructive_actions ?? true);
|
|
491
|
+
const pluginPolicies = Object.entries(config?.plugins ?? {}).flatMap(([configKey, entry]) => {
|
|
492
|
+
if (!isCodexPluginMarketplaceName(entry.marketplaceName) || !entry.pluginName) return [];
|
|
493
|
+
const entryDestructivePolicy = resolveCodexPluginDestructivePolicy(entry.allow_destructive_actions ?? config?.allow_destructive_actions ?? true);
|
|
494
|
+
return [{
|
|
495
|
+
configKey,
|
|
496
|
+
marketplaceName: entry.marketplaceName,
|
|
497
|
+
pluginName: entry.pluginName,
|
|
498
|
+
enabled: enabled && entry.enabled !== false,
|
|
499
|
+
allowDestructiveActions: entryDestructivePolicy.allowDestructiveActions,
|
|
500
|
+
destructiveApprovalMode: entryDestructivePolicy.destructiveApprovalMode
|
|
501
|
+
}];
|
|
502
|
+
}).toSorted((left, right) => left.configKey.localeCompare(right.configKey));
|
|
503
|
+
return {
|
|
504
|
+
configured,
|
|
505
|
+
enabled,
|
|
506
|
+
allowAllPlugins: enabled && config?.allow_all_plugins === true,
|
|
507
|
+
allowDestructiveActions: destructivePolicy.allowDestructiveActions,
|
|
508
|
+
destructiveApprovalMode: destructivePolicy.destructiveApprovalMode,
|
|
509
|
+
pluginPolicies
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
function isCodexPluginMarketplaceName(value) {
|
|
513
|
+
return typeof value === "string" && CODEX_PLUGIN_MARKETPLACE_NAME_PATTERN.test(value);
|
|
514
|
+
}
|
|
515
|
+
function resolveCodexPluginDestructivePolicy(policy) {
|
|
516
|
+
if (policy === "auto" || policy === "ask") return {
|
|
517
|
+
allowDestructiveActions: true,
|
|
518
|
+
destructiveApprovalMode: policy
|
|
519
|
+
};
|
|
520
|
+
return {
|
|
521
|
+
allowDestructiveActions: policy,
|
|
522
|
+
destructiveApprovalMode: policy ? "allow" : "deny"
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
//#endregion
|
|
268
526
|
//#region extensions/codex/src/app-server/config-requirements.ts
|
|
269
527
|
const UNIX_CODEX_REQUIREMENTS_PATH = "/etc/codex/requirements.toml";
|
|
270
528
|
const WINDOWS_CODEX_REQUIREMENTS_SUFFIX = "\\OpenAI\\Codex\\requirements.toml";
|
|
@@ -434,6 +692,7 @@ function globPatternMatches(value, pattern) {
|
|
|
434
692
|
function normalizeRequirementsApprovalPolicy(value) {
|
|
435
693
|
const normalized = value.trim().toLowerCase();
|
|
436
694
|
if (normalized === "on-failure") return "on-request";
|
|
695
|
+
if (normalized === "untrusted") return normalized;
|
|
437
696
|
return resolveApprovalPolicy(normalized);
|
|
438
697
|
}
|
|
439
698
|
function normalizeRequirementsApprovalsReviewer(value) {
|
|
@@ -441,8 +700,8 @@ function normalizeRequirementsApprovalsReviewer(value) {
|
|
|
441
700
|
}
|
|
442
701
|
function selectGuardianApprovalPolicy(allowedApprovalPolicies, execModeRequiringPromptingApprovals) {
|
|
443
702
|
if (allowedApprovalPolicies === void 0 || allowedApprovalPolicies.has("on-request")) return "on-request";
|
|
444
|
-
if (execModeRequiringPromptingApprovals) throw new Error(`tools.exec.mode=${execModeRequiringPromptingApprovals} requires Codex app-server prompting approvals`);
|
|
445
703
|
if (allowedApprovalPolicies.has("untrusted")) return "untrusted";
|
|
704
|
+
if (execModeRequiringPromptingApprovals) throw new Error(`tools.exec.mode=${execModeRequiringPromptingApprovals} requires Codex app-server prompting approvals`);
|
|
446
705
|
if (allowedApprovalPolicies.has("never")) return "never";
|
|
447
706
|
return "on-request";
|
|
448
707
|
}
|
|
@@ -459,14 +718,31 @@ function selectUserApprovalsReviewer(allowedApprovalsReviewers, execModeRequirin
|
|
|
459
718
|
}
|
|
460
719
|
//#endregion
|
|
461
720
|
//#region extensions/codex/src/app-server/config-reviewer.ts
|
|
462
|
-
const CODEX_APP_SERVER_HOME_DIRNAME = "codex-home";
|
|
463
721
|
const CODEX_CONFIG_TOML_FILENAME = "config.toml";
|
|
722
|
+
/** Cloud/system config can redirect reviews after local home/profile checks have passed. */
|
|
723
|
+
async function assertCodexModelBackedReviewerEffectiveConfig(params) {
|
|
724
|
+
if (params.approvalsReviewer !== "auto_review" && params.approvalsReviewer !== "guardian_subagent") return;
|
|
725
|
+
const response = await params.client.request("config/read", {
|
|
726
|
+
cwd: path.resolve(params.cwd),
|
|
727
|
+
includeLayers: false
|
|
728
|
+
}, { signal: params.signal });
|
|
729
|
+
const effectiveConfig = readRecord(readRecord(response)?.config);
|
|
730
|
+
if (!effectiveConfig) throw new Error("Codex config/read returned an invalid model-backed reviewer config");
|
|
731
|
+
const modelProvider = effectiveConfig.model_provider;
|
|
732
|
+
const providers = effectiveConfig.model_providers;
|
|
733
|
+
const providerRecords = providers == null ? void 0 : readRecord(providers);
|
|
734
|
+
const provider = providerRecords?.openai;
|
|
735
|
+
const openAIProvider = provider == null ? void 0 : readRecord(provider);
|
|
736
|
+
if (modelProvider != null && modelProvider !== "openai" || providers != null && !providerRecords || provider != null && !openAIProvider || !isTrustedOptionalReviewerEndpoint(effectiveConfig.openai_base_url, isNativeOpenAIBaseUrl) || !isTrustedOptionalReviewerEndpoint(effectiveConfig.chatgpt_base_url, isNativeChatGPTBaseUrl) || !isTrustedOptionalReviewerEndpoint(openAIProvider?.base_url, isNativeOpenAIBaseUrl)) throw new Error("Codex model-backed approval reviewer requires the running server to use a trusted OpenAI endpoint");
|
|
737
|
+
}
|
|
738
|
+
function isTrustedOptionalReviewerEndpoint(value, isTrusted) {
|
|
739
|
+
return value == null || typeof value === "string" && isTrusted(value);
|
|
740
|
+
}
|
|
464
741
|
function canUseCodexModelBackedApprovalsReviewerForModel(params) {
|
|
465
742
|
const explicitProvider = params.modelProvider?.trim().toLowerCase();
|
|
466
743
|
const inferredProvider = inferProviderFromModelRef(params.model);
|
|
467
|
-
if (explicitProvider && explicitProvider !== "codex"
|
|
468
|
-
|
|
469
|
-
return isTrustedCodexModelBackedApprovalsReviewerProvider(explicitProvider, params);
|
|
744
|
+
if (explicitProvider && explicitProvider !== "codex" && explicitProvider !== "openai") return false;
|
|
745
|
+
return (inferredProvider ?? explicitProvider) === "openai" && isTrustedCodexModelBackedOpenAIProvider(params);
|
|
470
746
|
}
|
|
471
747
|
function isTrustedCodexModelBackedOpenAIProvider(params) {
|
|
472
748
|
if (!openAIBaseUrlEnvOverridesAreTrustedForModelBackedReview(params.env)) return false;
|
|
@@ -503,43 +779,50 @@ function resolveCodexModelBackedReviewerPolicyContext(params) {
|
|
|
503
779
|
model: params.model ?? params.bindingModel
|
|
504
780
|
};
|
|
505
781
|
}
|
|
506
|
-
function isCodexModelBackedApprovalsReviewerProvider(provider) {
|
|
507
|
-
return provider?.trim().toLowerCase() === "openai";
|
|
508
|
-
}
|
|
509
|
-
function isTrustedCodexModelBackedApprovalsReviewerProvider(provider, params) {
|
|
510
|
-
return isCodexModelBackedApprovalsReviewerProvider(provider) && isTrustedCodexModelBackedOpenAIProvider({
|
|
511
|
-
config: params.config,
|
|
512
|
-
env: params.env,
|
|
513
|
-
model: params.model,
|
|
514
|
-
agentDir: params.agentDir,
|
|
515
|
-
codexConfigToml: params.codexConfigToml,
|
|
516
|
-
homeScope: params.homeScope
|
|
517
|
-
});
|
|
518
|
-
}
|
|
519
782
|
function readCodexBaseUrlOverridesForModelBackedReview(params) {
|
|
520
783
|
const configToml = readCodexAppServerConfigToml(params);
|
|
521
784
|
if (configToml === false) return false;
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
const
|
|
527
|
-
const
|
|
528
|
-
const
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
parseInlineOpenAIModelProviderBaseUrl(topLevelContent),
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
const chatGPT = [chatGPTBaseUrl];
|
|
785
|
+
const configTomls = configToml === void 0 ? [] : [configToml];
|
|
786
|
+
const nativeOverrides = readNativeCodexReviewerConfigOverrides(params);
|
|
787
|
+
if (nativeOverrides === false) return false;
|
|
788
|
+
configTomls.push(...nativeOverrides);
|
|
789
|
+
const openAI = [];
|
|
790
|
+
const chatGPT = [];
|
|
791
|
+
for (const content of configTomls) {
|
|
792
|
+
const topLevelContent = stripTomlLineComments(content).slice(0, firstTomlTableOffset(content));
|
|
793
|
+
const modelProviderOpenAISection = parseTomlTableSection(content, "model_providers.openai");
|
|
794
|
+
const modelProvider = parseTomlStringValue(topLevelContent, "model_provider");
|
|
795
|
+
if (modelProvider === false || modelProvider && modelProvider !== "openai") return false;
|
|
796
|
+
openAI.push(parseTomlStringValue(topLevelContent, "openai_base_url"), parseTomlStringValue(topLevelContent, "model_providers.openai.base_url"), parseInlineOpenAIModelProviderBaseUrl(topLevelContent), modelProviderOpenAISection ? parseTomlStringValue(modelProviderOpenAISection, "base_url") : void 0);
|
|
797
|
+
chatGPT.push(parseTomlStringValue(topLevelContent, "chatgpt_base_url"));
|
|
798
|
+
}
|
|
537
799
|
if ([...openAI, ...chatGPT].includes(false)) return false;
|
|
538
800
|
return {
|
|
539
801
|
openAI: openAI.filter((entry) => typeof entry === "string"),
|
|
540
802
|
chatGPT: chatGPT.filter((entry) => typeof entry === "string")
|
|
541
803
|
};
|
|
542
804
|
}
|
|
805
|
+
function readNativeCodexReviewerConfigOverrides(params) {
|
|
806
|
+
if (params.codexArgs?.some((arg) => !arg)) return false;
|
|
807
|
+
const overrides = [];
|
|
808
|
+
let profile;
|
|
809
|
+
for (const { name, value } of readCodexAppServerConfigOptions(params.codexArgs ?? [])) {
|
|
810
|
+
if (!value) return false;
|
|
811
|
+
if (name === "--profile" || name === "-p") profile = value;
|
|
812
|
+
else overrides.push(`${value}\n`);
|
|
813
|
+
}
|
|
814
|
+
if (profile) {
|
|
815
|
+
if (path.basename(profile) !== profile || profile === "." || profile === "..") return false;
|
|
816
|
+
const configPath = resolveCodexAppServerConfigPath(params);
|
|
817
|
+
if (!configPath) return false;
|
|
818
|
+
try {
|
|
819
|
+
overrides.unshift(readFileSync(path.join(path.dirname(configPath), `${profile}.config.toml`), "utf8"));
|
|
820
|
+
} catch (error) {
|
|
821
|
+
if (readErrorCode(error) !== "ENOENT") return false;
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
return overrides;
|
|
825
|
+
}
|
|
543
826
|
function readCodexAppServerConfigToml(params) {
|
|
544
827
|
if (params.codexConfigToml !== void 0) return params.codexConfigToml ?? void 0;
|
|
545
828
|
const configPath = resolveCodexAppServerConfigPath(params);
|
|
@@ -576,13 +859,7 @@ function codexConfigEnablesNativeComputerUse(params) {
|
|
|
576
859
|
function resolveCodexAppServerConfigPath(params) {
|
|
577
860
|
if (params.homeScope === "user") return path.join(resolveCodexAppServerUserHomeDir(params.env), CODEX_CONFIG_TOML_FILENAME);
|
|
578
861
|
const agentDir = readNonEmptyString(params.agentDir);
|
|
579
|
-
|
|
580
|
-
return codexHome ? path.join(codexHome, CODEX_CONFIG_TOML_FILENAME) : void 0;
|
|
581
|
-
}
|
|
582
|
-
/** Resolves the native user Codex home used by Desktop and the CLI. */
|
|
583
|
-
function resolveCodexAppServerUserHomeDir(env = process.env, homedir$1 = homedir) {
|
|
584
|
-
const configured = readNonEmptyString(env.CODEX_HOME);
|
|
585
|
-
return path.resolve(configured ?? path.join(homedir$1(), ".codex"));
|
|
862
|
+
return agentDir ? path.join(resolveCodexAppServerHomeDir(agentDir), CODEX_CONFIG_TOML_FILENAME) : void 0;
|
|
586
863
|
}
|
|
587
864
|
function readErrorCode(error) {
|
|
588
865
|
return error && typeof error === "object" && "code" in error ? String(error.code) : void 0;
|
|
@@ -656,237 +933,6 @@ function inferProviderFromModelRef(model) {
|
|
|
656
933
|
return slashIndex > 0 ? normalized?.slice(0, slashIndex) : void 0;
|
|
657
934
|
}
|
|
658
935
|
//#endregion
|
|
659
|
-
//#region extensions/codex/src/app-server/config-contracts.ts
|
|
660
|
-
const CODEX_PLUGINS_MARKETPLACE_NAME = "openai-curated";
|
|
661
|
-
const CODEX_PLUGINS_WORKSPACE_MARKETPLACE_NAME = "workspace-directory";
|
|
662
|
-
const CODEX_PLUGIN_MARKETPLACE_NAME_PATTERN = /^[A-Za-z0-9_-]+$/;
|
|
663
|
-
//#endregion
|
|
664
|
-
//#region extensions/codex/src/app-server/session-discovery-config.ts
|
|
665
|
-
const codexSessionCatalogHomeSchema = z.union([z.string().trim().min(1), z.object({
|
|
666
|
-
path: z.string().trim().min(1),
|
|
667
|
-
label: z.string().trim().min(1).optional()
|
|
668
|
-
}).strict()]);
|
|
669
|
-
const codexSessionCatalogConfigSchema = z.object({
|
|
670
|
-
enabled: z.boolean().optional(),
|
|
671
|
-
homes: z.array(codexSessionCatalogHomeSchema).optional()
|
|
672
|
-
}).strict();
|
|
673
|
-
const codexDiscoveryConfigSchema = z.object({
|
|
674
|
-
enabled: z.boolean().optional(),
|
|
675
|
-
timeoutMs: z.number().positive().optional()
|
|
676
|
-
}).strict();
|
|
677
|
-
//#endregion
|
|
678
|
-
//#region extensions/codex/src/app-server/config-parsing.ts
|
|
679
|
-
const DEFAULT_CODEX_COMPUTER_USE_PLUGIN_NAME = "computer-use";
|
|
680
|
-
const DEFAULT_CODEX_COMPUTER_USE_MARKETPLACE_DISCOVERY_TIMEOUT_MS = 6e4;
|
|
681
|
-
const DEFAULT_CODEX_COMPUTER_USE_LIVE_TEST_TIMEOUT_MS = 6e4;
|
|
682
|
-
const DEFAULT_CODEX_COMPUTER_USE_TOOL_CALL_TIMEOUT_MS = 6e4;
|
|
683
|
-
const DEFAULT_CODEX_APP_SERVER_NETWORK_PROXY_PROFILE_PREFIX = "openclaw-network";
|
|
684
|
-
const codexAppServerTransportSchema = z.enum([
|
|
685
|
-
"stdio",
|
|
686
|
-
"websocket",
|
|
687
|
-
"unix"
|
|
688
|
-
]);
|
|
689
|
-
const codexAppServerHomeScopeSchema = z.enum(["agent", "user"]);
|
|
690
|
-
const SecretInputSchema = buildSecretInputSchema();
|
|
691
|
-
const codexAppServerPolicyModeSchema = z.enum(["yolo", "guardian"]);
|
|
692
|
-
const codexAppServerApprovalPolicySchema = z.preprocess((value) => value === "on-failure" ? "on-request" : value, z.enum([
|
|
693
|
-
"never",
|
|
694
|
-
"on-request",
|
|
695
|
-
"untrusted"
|
|
696
|
-
]));
|
|
697
|
-
const codexAppServerSandboxSchema = z.enum([
|
|
698
|
-
"read-only",
|
|
699
|
-
"workspace-write",
|
|
700
|
-
"danger-full-access"
|
|
701
|
-
]);
|
|
702
|
-
const codexAppServerApprovalsReviewerSchema = z.enum([
|
|
703
|
-
"user",
|
|
704
|
-
"auto_review",
|
|
705
|
-
"guardian_subagent"
|
|
706
|
-
]);
|
|
707
|
-
const codexDynamicToolsLoadingSchema = z.enum(["searchable", "direct"]);
|
|
708
|
-
const codexComputerUseHealthIntervalSchema = z.union([
|
|
709
|
-
z.literal(30),
|
|
710
|
-
z.literal(60),
|
|
711
|
-
z.literal(120),
|
|
712
|
-
z.literal(240)
|
|
713
|
-
]);
|
|
714
|
-
const codexComputerUsePluginCacheModeSchema = z.enum(["shared", "independent"]);
|
|
715
|
-
const codexPluginDestructivePolicySchema = z.union([
|
|
716
|
-
z.boolean(),
|
|
717
|
-
z.literal("auto"),
|
|
718
|
-
z.literal("ask")
|
|
719
|
-
]);
|
|
720
|
-
const codexAppServerServiceTierSchema = z.preprocess((value) => value === null ? null : normalizeCodexServiceTier(value), z.string().trim().min(1).nullable().optional()).optional();
|
|
721
|
-
const codexAppServerExperimentalSchema = z.object({ sandboxExecServer: z.boolean().optional() }).strict();
|
|
722
|
-
const codexAppServerRemoteWorkspaceRootSchema = z.string().trim().min(1);
|
|
723
|
-
const codexAppServerNetworkProxyDomainPermissionSchema = z.enum(["allow", "deny"]);
|
|
724
|
-
const codexAppServerNetworkProxyUnixSocketPermissionSchema = z.enum(["allow", "none"]);
|
|
725
|
-
const codexAppServerNetworkProxySchema = z.object({
|
|
726
|
-
enabled: z.boolean().optional(),
|
|
727
|
-
profileName: z.string().trim().min(1).optional(),
|
|
728
|
-
baseProfile: z.enum(["read-only", "workspace"]).optional(),
|
|
729
|
-
mode: z.enum(["limited", "full"]).optional(),
|
|
730
|
-
domains: z.record(z.string(), codexAppServerNetworkProxyDomainPermissionSchema).optional(),
|
|
731
|
-
unixSockets: z.record(z.string(), codexAppServerNetworkProxyUnixSocketPermissionSchema).optional(),
|
|
732
|
-
proxyUrl: z.string().trim().min(1).optional(),
|
|
733
|
-
socksUrl: z.string().trim().min(1).optional(),
|
|
734
|
-
enableSocks5: z.boolean().optional(),
|
|
735
|
-
enableSocks5Udp: z.boolean().optional(),
|
|
736
|
-
allowUpstreamProxy: z.boolean().optional(),
|
|
737
|
-
allowLocalBinding: z.boolean().optional(),
|
|
738
|
-
dangerouslyAllowNonLoopbackProxy: z.boolean().optional(),
|
|
739
|
-
dangerouslyAllowAllUnixSockets: z.boolean().optional()
|
|
740
|
-
}).strict();
|
|
741
|
-
const codexPluginEntryConfigSchema = z.object({
|
|
742
|
-
enabled: z.boolean().optional(),
|
|
743
|
-
marketplaceName: z.string().regex(CODEX_PLUGIN_MARKETPLACE_NAME_PATTERN).optional(),
|
|
744
|
-
pluginName: z.string().trim().min(1).optional(),
|
|
745
|
-
allow_destructive_actions: codexPluginDestructivePolicySchema.optional()
|
|
746
|
-
}).strict();
|
|
747
|
-
const codexPluginsConfigSchema = z.object({
|
|
748
|
-
enabled: z.boolean().optional(),
|
|
749
|
-
allow_all_plugins: z.boolean().optional(),
|
|
750
|
-
allow_destructive_actions: codexPluginDestructivePolicySchema.optional(),
|
|
751
|
-
plugins: z.record(z.string(), codexPluginEntryConfigSchema).optional()
|
|
752
|
-
}).strict();
|
|
753
|
-
const codexSupervisionEndpointSchema = z.union([z.object({
|
|
754
|
-
id: z.string().optional(),
|
|
755
|
-
label: z.string().optional(),
|
|
756
|
-
transport: z.literal("stdio-proxy").optional(),
|
|
757
|
-
command: z.string().optional(),
|
|
758
|
-
args: z.array(z.string()).optional(),
|
|
759
|
-
cwd: z.string().optional()
|
|
760
|
-
}).strict(), z.object({
|
|
761
|
-
id: z.string().optional(),
|
|
762
|
-
label: z.string().optional(),
|
|
763
|
-
transport: z.literal("websocket"),
|
|
764
|
-
url: z.string(),
|
|
765
|
-
authTokenEnv: z.string().optional()
|
|
766
|
-
}).strict()]);
|
|
767
|
-
const codexSupervisionConfigSchema = z.object({
|
|
768
|
-
enabled: z.boolean().optional(),
|
|
769
|
-
endpoints: z.array(codexSupervisionEndpointSchema).optional(),
|
|
770
|
-
allowRawTranscripts: z.boolean().optional(),
|
|
771
|
-
allowWriteControls: z.boolean().optional()
|
|
772
|
-
}).strict();
|
|
773
|
-
const codexPluginConfigSchema = z.object({
|
|
774
|
-
codexDynamicToolsLoading: codexDynamicToolsLoadingSchema.optional(),
|
|
775
|
-
codexDynamicToolsExclude: z.array(z.string()).optional(),
|
|
776
|
-
sessionCatalog: codexSessionCatalogConfigSchema.optional(),
|
|
777
|
-
discovery: codexDiscoveryConfigSchema.optional(),
|
|
778
|
-
computerUse: z.object({
|
|
779
|
-
enabled: z.boolean().optional(),
|
|
780
|
-
autoInstall: z.boolean().optional(),
|
|
781
|
-
marketplaceDiscoveryTimeoutMs: z.number().positive().optional(),
|
|
782
|
-
liveTestTimeoutMs: z.number().positive().optional(),
|
|
783
|
-
toolCallTimeoutMs: z.number().positive().optional(),
|
|
784
|
-
healthCheckEnabled: z.boolean().optional(),
|
|
785
|
-
healthCheckIntervalMinutes: codexComputerUseHealthIntervalSchema.optional(),
|
|
786
|
-
pluginCacheMode: codexComputerUsePluginCacheModeSchema.optional(),
|
|
787
|
-
strictReadiness: z.boolean().optional(),
|
|
788
|
-
autoRepair: z.boolean().optional(),
|
|
789
|
-
marketplaceSource: z.string().optional(),
|
|
790
|
-
marketplacePath: z.string().optional(),
|
|
791
|
-
marketplaceName: z.string().optional(),
|
|
792
|
-
pluginName: z.string().optional(),
|
|
793
|
-
mcpServerName: z.string().optional()
|
|
794
|
-
}).strict().optional(),
|
|
795
|
-
codexPlugins: z.unknown().optional(),
|
|
796
|
-
supervision: codexSupervisionConfigSchema.optional(),
|
|
797
|
-
appServer: z.object({
|
|
798
|
-
mode: codexAppServerPolicyModeSchema.optional(),
|
|
799
|
-
transport: codexAppServerTransportSchema.optional(),
|
|
800
|
-
homeScope: codexAppServerHomeScopeSchema.optional(),
|
|
801
|
-
command: z.string().optional(),
|
|
802
|
-
args: z.union([z.array(z.string()), z.string()]).optional(),
|
|
803
|
-
url: z.string().optional(),
|
|
804
|
-
authToken: SecretInputSchema.optional(),
|
|
805
|
-
headers: z.record(z.string(), SecretInputSchema).optional(),
|
|
806
|
-
clearEnv: z.array(z.string()).optional(),
|
|
807
|
-
remoteWorkspaceRoot: codexAppServerRemoteWorkspaceRootSchema.optional(),
|
|
808
|
-
codeModeOnly: z.boolean().optional(),
|
|
809
|
-
loopDetectionPreToolUseRelay: z.boolean().optional(),
|
|
810
|
-
requestTimeoutMs: z.number().positive().optional(),
|
|
811
|
-
turnCompletionIdleTimeoutMs: z.number().positive().optional(),
|
|
812
|
-
turnAssistantCompletionIdleTimeoutMs: z.number().positive().optional(),
|
|
813
|
-
postToolRawAssistantCompletionIdleTimeoutMs: z.number().positive().optional(),
|
|
814
|
-
approvalPolicy: codexAppServerApprovalPolicySchema.optional(),
|
|
815
|
-
sandbox: codexAppServerSandboxSchema.optional(),
|
|
816
|
-
approvalsReviewer: codexAppServerApprovalsReviewerSchema.optional(),
|
|
817
|
-
serviceTier: codexAppServerServiceTierSchema,
|
|
818
|
-
networkProxy: codexAppServerNetworkProxySchema.optional(),
|
|
819
|
-
defaultWorkspaceDir: z.string().optional(),
|
|
820
|
-
experimental: codexAppServerExperimentalSchema.optional()
|
|
821
|
-
}).strict().optional()
|
|
822
|
-
}).strict();
|
|
823
|
-
function readCodexPluginConfig(value) {
|
|
824
|
-
const parsed = codexPluginConfigSchema.safeParse(value);
|
|
825
|
-
if (!parsed.success) return {};
|
|
826
|
-
const { codexPlugins: rawCodexPlugins, ...config } = parsed.data;
|
|
827
|
-
const plugins = codexPluginsConfigSchema.safeParse(rawCodexPlugins);
|
|
828
|
-
if (!plugins.success) return config;
|
|
829
|
-
return {
|
|
830
|
-
...config,
|
|
831
|
-
...plugins.data ? { codexPlugins: plugins.data } : {}
|
|
832
|
-
};
|
|
833
|
-
}
|
|
834
|
-
function isCodexSandboxExecServerEnabled(pluginConfig, sandbox) {
|
|
835
|
-
return isCodexRemoteExecPlacementSandbox(sandbox) || readCodexPluginConfig(pluginConfig).appServer?.experimental?.sandboxExecServer === true;
|
|
836
|
-
}
|
|
837
|
-
function isCodexRemoteExecPlacementSandbox(sandbox) {
|
|
838
|
-
return typeof sandbox === "object" && sandbox !== null && "placementExecutionMode" in sandbox && sandbox.placementExecutionMode === "remote-exec";
|
|
839
|
-
}
|
|
840
|
-
function isCodexPairedNodeRemoteExecPlacementSandbox(sandbox) {
|
|
841
|
-
return isCodexRemoteExecPlacementSandbox(sandbox) && typeof sandbox === "object" && sandbox !== null && "placementNodeId" in sandbox && typeof sandbox.placementNodeId === "string" && sandbox.placementNodeId.length > 0;
|
|
842
|
-
}
|
|
843
|
-
function assertCodexAppServerCommandHasNoInlineArgs(params) {
|
|
844
|
-
const inlineArgs = detectWindowsSpawnCommandInlineArgs(params.command);
|
|
845
|
-
if (!inlineArgs) return;
|
|
846
|
-
const sourceLabel = params.source === "env" ? "OPENCLAW_CODEX_APP_SERVER_BIN" : "plugins.entries.codex.config.appServer.command";
|
|
847
|
-
const argsLabel = params.source === "env" ? "OPENCLAW_CODEX_APP_SERVER_ARGS" : "plugins.entries.codex.config.appServer.args";
|
|
848
|
-
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.`);
|
|
849
|
-
}
|
|
850
|
-
function resolveCodexPluginsPolicy(pluginConfig) {
|
|
851
|
-
const config = readCodexPluginConfig(pluginConfig).codexPlugins;
|
|
852
|
-
const configured = config !== void 0;
|
|
853
|
-
const enabled = config?.enabled === true;
|
|
854
|
-
const destructivePolicy = resolveCodexPluginDestructivePolicy(config?.allow_destructive_actions ?? true);
|
|
855
|
-
const pluginPolicies = Object.entries(config?.plugins ?? {}).flatMap(([configKey, entry]) => {
|
|
856
|
-
if (!isCodexPluginMarketplaceName(entry.marketplaceName) || !entry.pluginName) return [];
|
|
857
|
-
const entryDestructivePolicy = resolveCodexPluginDestructivePolicy(entry.allow_destructive_actions ?? config?.allow_destructive_actions ?? true);
|
|
858
|
-
return [{
|
|
859
|
-
configKey,
|
|
860
|
-
marketplaceName: entry.marketplaceName,
|
|
861
|
-
pluginName: entry.pluginName,
|
|
862
|
-
enabled: enabled && entry.enabled !== false,
|
|
863
|
-
allowDestructiveActions: entryDestructivePolicy.allowDestructiveActions,
|
|
864
|
-
destructiveApprovalMode: entryDestructivePolicy.destructiveApprovalMode
|
|
865
|
-
}];
|
|
866
|
-
}).toSorted((left, right) => left.configKey.localeCompare(right.configKey));
|
|
867
|
-
return {
|
|
868
|
-
configured,
|
|
869
|
-
enabled,
|
|
870
|
-
allowAllPlugins: enabled && config?.allow_all_plugins === true,
|
|
871
|
-
allowDestructiveActions: destructivePolicy.allowDestructiveActions,
|
|
872
|
-
destructiveApprovalMode: destructivePolicy.destructiveApprovalMode,
|
|
873
|
-
pluginPolicies
|
|
874
|
-
};
|
|
875
|
-
}
|
|
876
|
-
function isCodexPluginMarketplaceName(value) {
|
|
877
|
-
return typeof value === "string" && CODEX_PLUGIN_MARKETPLACE_NAME_PATTERN.test(value);
|
|
878
|
-
}
|
|
879
|
-
function resolveCodexPluginDestructivePolicy(policy) {
|
|
880
|
-
if (policy === "auto" || policy === "ask") return {
|
|
881
|
-
allowDestructiveActions: true,
|
|
882
|
-
destructiveApprovalMode: policy
|
|
883
|
-
};
|
|
884
|
-
return {
|
|
885
|
-
allowDestructiveActions: policy,
|
|
886
|
-
destructiveApprovalMode: policy ? "allow" : "deny"
|
|
887
|
-
};
|
|
888
|
-
}
|
|
889
|
-
//#endregion
|
|
890
936
|
//#region extensions/codex/src/app-server/config-security.ts
|
|
891
937
|
function shouldAutoApproveCodexAppServerApprovals(appServer) {
|
|
892
938
|
return appServer.networkProxy === void 0 && appServer.approvalPolicy === "never" && appServer.sandbox === "danger-full-access";
|
|
@@ -930,10 +976,11 @@ function resolveCodexAppServerNetworkProxy(config, sandbox) {
|
|
|
930
976
|
function resolveNetworkProxyPermissionProfileName(config, profile) {
|
|
931
977
|
const explicitProfileName = readNonEmptyString(config.profileName);
|
|
932
978
|
if (explicitProfileName) return explicitProfileName;
|
|
933
|
-
|
|
979
|
+
const suffix = createHash("sha256").update(stableStringifyJson({
|
|
934
980
|
version: 1,
|
|
935
981
|
profile
|
|
936
|
-
})).digest("hex").slice(0, 16)
|
|
982
|
+
})).digest("hex").slice(0, 16);
|
|
983
|
+
return `${DEFAULT_CODEX_APP_SERVER_NETWORK_PROXY_PROFILE_PREFIX}-${suffix}`;
|
|
937
984
|
}
|
|
938
985
|
function fingerprintCodexAppServerNetworkProxyConfigPatch(configPatch) {
|
|
939
986
|
return createHash("sha256").update(stableStringifyJson(configPatch)).digest("hex");
|
|
@@ -951,6 +998,7 @@ function stableStringifyJson(value) {
|
|
|
951
998
|
return JSON.stringify(value);
|
|
952
999
|
}
|
|
953
1000
|
function withMcpElicitationsApprovalPolicy(policy) {
|
|
1001
|
+
if (policy === "untrusted") return policy;
|
|
954
1002
|
if (typeof policy !== "string") return { granular: {
|
|
955
1003
|
...policy.granular,
|
|
956
1004
|
mcp_elicitations: true
|
|
@@ -1034,7 +1082,7 @@ function resolveDefaultCodexAppServerPolicy(params) {
|
|
|
1034
1082
|
const allowedApprovalPolicies = parseAllowedApprovalPoliciesFromCodexRequirements(content);
|
|
1035
1083
|
const allowedApprovalsReviewers = parseAllowedApprovalsReviewersFromCodexRequirements(content);
|
|
1036
1084
|
const yoloSandboxAllowed = allowedSandboxModes === void 0 || allowedSandboxModes.has("danger-full-access");
|
|
1037
|
-
const yoloApprovalAllowed = allowedApprovalPolicies === void 0 || allowedApprovalPolicies.has("never");
|
|
1085
|
+
const yoloApprovalAllowed = allowedApprovalPolicies === void 0 || allowedApprovalPolicies.has("never") && !allowedApprovalPolicies.has("untrusted");
|
|
1038
1086
|
const yoloReviewerAllowed = allowedApprovalsReviewers === void 0 || allowedApprovalsReviewers.has("user");
|
|
1039
1087
|
if (!params.forceGuardian && yoloSandboxAllowed && yoloApprovalAllowed && yoloReviewerAllowed) return {
|
|
1040
1088
|
mode: "yolo",
|
|
@@ -1114,6 +1162,15 @@ function resolveCodexAppServerRuntimeOptions(params = {}) {
|
|
|
1114
1162
|
const forceGuardianReviewer = execMode === "auto" && canUseModelBackedReviewer;
|
|
1115
1163
|
const execModeRequiringPromptingApprovals = execMode === "auto" || execMode === "ask" ? execMode : forceUserReviewer ? "ask" : void 0;
|
|
1116
1164
|
const forceDangerFullAccessSandbox = params.execPolicy?.touched === true && params.execPolicy.security === "full" && params.execPolicy.ask === "always";
|
|
1165
|
+
const forcePerCommandApprovals = params.execPolicy?.ask === "always";
|
|
1166
|
+
const requirementsToml = forcePerCommandApprovals ? readCodexRequirementsToml({
|
|
1167
|
+
env,
|
|
1168
|
+
requirementsToml: params.requirementsToml,
|
|
1169
|
+
requirementsPath: params.requirementsPath,
|
|
1170
|
+
readRequirementsFile: params.readRequirementsFile,
|
|
1171
|
+
platform: params.platform
|
|
1172
|
+
}) ?? null : params.requirementsToml;
|
|
1173
|
+
if (forcePerCommandApprovals && requirementsToml && parseAllowedApprovalPoliciesFromCodexRequirements(requirementsToml)?.has("untrusted") === false) throw new Error("tools.exec.ask=always requires Codex app-server per-command approvals");
|
|
1117
1174
|
const forceRuntimePolicy = forceUserReviewer || forceGuardianReviewer || forceDangerFullAccessSandbox;
|
|
1118
1175
|
const defaultPolicy = explicitPolicyMode && !forceRuntimePolicy && !ignoreLegacyYoloPolicyMode ? void 0 : resolveDefaultCodexAppServerPolicy({
|
|
1119
1176
|
transport,
|
|
@@ -1121,7 +1178,7 @@ function resolveCodexAppServerRuntimeOptions(params = {}) {
|
|
|
1121
1178
|
forceGuardian: normalizedPolicyMode === "guardian",
|
|
1122
1179
|
forceUserReviewer: forceUserReviewer || !canUseModelBackedReviewer,
|
|
1123
1180
|
execModeRequiringPromptingApprovals,
|
|
1124
|
-
requirementsToml
|
|
1181
|
+
requirementsToml,
|
|
1125
1182
|
requirementsPath: params.requirementsPath,
|
|
1126
1183
|
readRequirementsFile: params.readRequirementsFile,
|
|
1127
1184
|
platform: params.platform,
|
|
@@ -1130,7 +1187,7 @@ function resolveCodexAppServerRuntimeOptions(params = {}) {
|
|
|
1130
1187
|
});
|
|
1131
1188
|
const preserveExplicitAutoSandbox = forceGuardianReviewer && configuredSandbox === "read-only";
|
|
1132
1189
|
const forcedPolicy = forceRuntimePolicy ? {
|
|
1133
|
-
approvalPolicy: defaultPolicy?.approvalPolicy ?? "on-request",
|
|
1190
|
+
approvalPolicy: forcePerCommandApprovals ? "untrusted" : defaultPolicy?.approvalPolicy ?? "on-request",
|
|
1134
1191
|
sandbox: preserveExplicitAutoSandbox ? void 0 : forceDangerFullAccessSandbox ? selectForcedDangerFullAccessSandbox({
|
|
1135
1192
|
configuredSandbox,
|
|
1136
1193
|
defaultPolicy,
|
|
@@ -1292,17 +1349,22 @@ function codexSandboxPolicyForTurn(mode, cwd, nativeArgs = []) {
|
|
|
1292
1349
|
};
|
|
1293
1350
|
let excludeTmpdirEnvVar = false;
|
|
1294
1351
|
let excludeSlashTmp = false;
|
|
1295
|
-
for (
|
|
1296
|
-
|
|
1297
|
-
const override = arg === "-c" || arg === "--config" ? nativeArgs[++index] : arg?.startsWith("--config=") ? arg.slice(9) : void 0;
|
|
1298
|
-
if (!override) continue;
|
|
1352
|
+
for (const { name, value: override } of readCodexAppServerConfigOptions(nativeArgs)) {
|
|
1353
|
+
if (name !== "-c" && name !== "--config" || !override) continue;
|
|
1299
1354
|
const separator = override.indexOf("=");
|
|
1300
1355
|
if (separator < 0) continue;
|
|
1301
1356
|
const key = override.slice(0, separator).trim();
|
|
1302
|
-
const
|
|
1303
|
-
if (
|
|
1304
|
-
|
|
1305
|
-
|
|
1357
|
+
const isTmpdirExclusion = key === "sandbox_workspace_write.exclude_tmpdir_env_var";
|
|
1358
|
+
if (!isTmpdirExclusion && key !== "sandbox_workspace_write.exclude_slash_tmp") continue;
|
|
1359
|
+
let value;
|
|
1360
|
+
try {
|
|
1361
|
+
value = parse(`_x_ = ${override.slice(separator + 1).trim()}`)["_x_"];
|
|
1362
|
+
} catch {
|
|
1363
|
+
continue;
|
|
1364
|
+
}
|
|
1365
|
+
if (typeof value !== "boolean") continue;
|
|
1366
|
+
if (isTmpdirExclusion) excludeTmpdirEnvVar = value;
|
|
1367
|
+
else excludeSlashTmp = value;
|
|
1306
1368
|
}
|
|
1307
1369
|
return {
|
|
1308
1370
|
type: "workspaceWrite",
|
|
@@ -1332,4 +1394,4 @@ function resolveCodexSupervisionAppServerRuntimeOptions(params = {}) {
|
|
|
1332
1394
|
});
|
|
1333
1395
|
}
|
|
1334
1396
|
//#endregion
|
|
1335
|
-
export {
|
|
1397
|
+
export { normalizeCodexServiceTier as A, isCodexRemoteExecPlacementSandbox as C, resolveOpenClawExecPolicyForCodexAppServer as D, resolveCodexPluginsPolicy as E, resolveCodexAppServerLocalHomeDir as F, resolveCodexAppServerUserHomeDir as I, withEphemeralCodexAuthStore as L, CODEX_PLUGINS_WORKSPACE_MARKETPLACE_NAME as M, CODEX_PLUGIN_MARKETPLACE_NAME_PATTERN as N, selectGuardianSandbox as O, resolveCodexAppServerHomeDir as P, isCodexPairedNodeRemoteExecPlacementSandbox as S, readCodexPluginConfig as T, parseAllowedSandboxModesFromCodexRequirements as _, resolveCodexAppServerStartOptionsForAgent as a, selectGuardianApprovalsReviewer as b, assertCodexAppServerConnectionSecurity as c, withMcpElicitationsApprovalPolicy as d, assertCodexModelBackedReviewerEffectiveConfig as f, parseAllowedApprovalsReviewersFromCodexRequirements as g, parseAllowedApprovalPoliciesFromCodexRequirements as h, resolveCodexAppServerRuntimeOptions as i, CODEX_PLUGINS_MARKETPLACE_NAME as j, isCodexFastServiceTier as k, resolveCodexAppServerNetworkProxy as l, resolveCodexModelBackedReviewerPolicyContext as m, codexSandboxPolicyForTurn as n, resolveCodexComputerUseConfig as o, canUseCodexModelBackedApprovalsReviewerForModel as p, resolveCodexAppServerHomeScope as r, resolveCodexSupervisionAppServerRuntimeOptions as s, codexAppServerStartOptionsKey as t, shouldAutoApproveCodexAppServerApprovals as u, readCodexRequirementsToml as v, isCodexSandboxExecServerEnabled as w, selectUserApprovalsReviewer as x, selectGuardianApprovalPolicy as y };
|