@openclaw/codex 2026.9.1-beta.1 → 2026.9.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 +8 -9
- package/dist/{attempt-client-cleanup-bfsmcQ6m.js → attempt-client-cleanup-Bp1ZOnk2.js} +105 -75
- package/dist/attempt-context-CSazkWns.js +634 -0
- package/dist/{auth-binding-B4FfbcCg.js → auth-binding-Ds_QVm-X.js} +18 -3
- package/dist/{bounded-turn-B7iBUcuP.js → bounded-turn-DxGJRYbY.js} +53 -57
- package/dist/{capabilities-BRMh0aIq.js → capabilities-B1mgvpP8.js} +2 -1
- package/dist/cli-metadata.js +1 -1
- package/dist/{command-formatters-DEsIufkt.js → command-formatters-DSbGMXA0.js} +5 -4
- package/dist/{command-handlers-D_-1_qRp.js → command-handlers-DOJvGv6-.js} +243 -148
- package/dist/{compact-BglNFZrQ.js → compact-Y_xBqrHN.js} +109 -65
- package/dist/{config-giW8X0QA.js → config-CyapYSji.js} +328 -374
- package/dist/config-utils-C57JiJrU.js +69 -0
- 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 +144 -14
- package/dist/{dynamic-tools-Dnlfa--w.js → dynamic-tools-BwpvTxaX.js} +1119 -1135
- package/dist/{effective-mcp-catalog-CTeGrnfO.js → effective-mcp-catalog-CY9Jn4bA.js} +4 -3
- package/dist/{event-projector-assistant-message-C5-Ds8mA.js → event-projector-assistant-message-B9kp6iGC.js} +15 -6
- package/dist/event-projector-usage-ZqEVbAEY.js +212 -0
- package/dist/{harness-Csz0F-DK.js → harness-Czh2Sdoc.js} +65 -52
- package/dist/harness.js +1 -1
- package/dist/{image-payload-sanitizer-CnfoUPCE.js → image-payload-sanitizer-tupAr-2o.js} +29 -15
- package/dist/index.js +495 -457
- package/dist/{isolated-completion-Cv6FqygM.js → isolated-completion-CRh-51AK.js} +9 -21
- package/dist/{managed-binary-DFYK4DWq.js → managed-binary-DcpnJF9x.js} +117 -80
- package/dist/media-understanding-provider.js +1 -1
- package/dist/model-catalog-DT5vo6qo.js +101 -0
- package/dist/{models-TS3HBU-q.js → models-CcrgSMQR.js} +26 -29
- package/dist/{native-subagent-monitor-4Mfq2HDs.js → native-subagent-monitor-B3bvQGcg.js} +63 -122
- package/dist/{node-exec-server.runtime-BpWqJO1V.js → node-exec-server.runtime-nfbUOtUB.js} +10 -7
- package/dist/{plugin-approval-roundtrip-bUm777tR.js → plugin-approval-roundtrip-aQVdyL5g.js} +30 -3
- package/dist/{plugin-marketplace-discovery-B9DvaAG-.js → plugin-marketplace-discovery-B7gHXJ3d.js} +44 -30
- package/dist/{plugin-metadata-cache-CTCT3w5L.js → plugin-metadata-cache-BwCLTY_U.js} +6 -6
- package/dist/provider-capabilities-BpG9Ltc5.js +101 -0
- package/dist/{rate-limits-C5_D8Gmb.js → rate-limits-Fx_l4eNa.js} +3 -2
- package/dist/{sandbox-guard-kuWTn9C5.js → request-C8H22rPi.js} +195 -2
- package/dist/{run-attempt-DYc0QCBF.js → run-attempt-BzthFQSM.js} +1616 -2634
- package/dist/{runtime-artifact-BvyT1uyd.js → runtime-artifact-Bh_gf6-t.js} +22 -15
- package/dist/{session-binding-Bcynfd-_.js → session-binding-4Ki04sW-.js} +282 -399
- package/dist/session-binding-record-CyaXZvTe.js +270 -0
- package/dist/{session-catalog-DaLKVtpH.js → session-catalog-B47uwekb.js} +812 -504
- package/dist/{session-cli-DMc4oS2w.js → session-cli-BjLhpmS1.js} +1 -1
- package/dist/session-history-DWmMqiqW.js +93 -0
- package/dist/session-history-read-LHldwvyh.js +36 -0
- package/dist/session-history-worker-runtime.js +48 -0
- package/dist/session-history.worker-zZVcx0ME.js +267 -0
- package/dist/session-history.worker.js +2 -0
- package/dist/session-initialization-BCFVnLL4.js +75 -0
- package/dist/{session-permission-policy-BrNH1bjy.js → session-permission-policy-BaueHmSj.js} +2 -2
- package/dist/session-retirement-DNdmYdFc.js +97 -0
- package/dist/{session-upstream-marker-BIkusb95.js → session-upstream-marker-DReTpGz6.js} +20 -4
- package/dist/settled-turn-context-BOM3Y1pl.js +45 -0
- package/dist/settled-turn-finalizer-BI-b1sry.js +115 -0
- package/dist/{shared-client-DKz23hHY.js → shared-client-CKhX2kFt.js} +3659 -847
- package/dist/{side-question-DjA_jsNe.js → side-question-B6DWAw1A.js} +168 -81
- package/dist/{thread-lifecycle-L7oEkTlq.js → thread-lifecycle-DPK30jad.js} +2412 -2145
- package/dist/{thread-ownership-DZeuKH1j.js → thread-ownership-CbucAmmp.js} +27 -16
- package/dist/thread-policy-CTalhWFy.js +105 -0
- package/dist/{plugin-app-cache-key-C1CAdfcP.js → thread-resume-BLgqkUc1.js} +61 -9
- package/dist/{transcript-mirror-DsCMWBca.js → transcript-mirror-_njEB84z.js} +114 -110
- package/dist/transcript-mirror-attestation-Byl34PC-.js +76 -0
- package/dist/transport-stdio-CzTngV0j.js +728 -0
- package/dist/{upstream-prompt-provenance-CFmsKwr9.js → upstream-prompt-provenance-LphB8slG.js} +8 -4
- package/dist/upstream-session-fork-1fwbNKzQ.js +886 -0
- package/dist/{usage-ROIaW3wo.js → usage-i9fv5-4m.js} +3 -3
- package/dist/{web-search-provider.runtime-ClaNPV7N.js → web-search-provider.runtime-DKQn67A7.js} +3 -3
- package/openclaw.plugin.json +1 -30
- package/package.json +6 -6
- package/dist/binding-connection-BMvPX73o.js +0 -45
- package/dist/command-rpc-CCeCkf_v.js +0 -90
- package/dist/event-projector-usage-Bk1I90Bg.js +0 -328
- 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,101 +1,60 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as normalizeHeaders, c as readExecAsk, d as readNumberEnv, f as readRecord, g as CODEX_PLUGIN_MARKETPLACE_NAME_PATTERN, i as normalizeCodexServiceTier, l as readExecSecurity, o as normalizePositiveNumber, p as resolveArgs, r as normalizeCodexAppServerSecretInput, s as readBooleanEnv, t as hashSecretForKey, u as readNonEmptyString } from "./config-utils-C57JiJrU.js";
|
|
2
|
+
import { m as readCodexAppServerConfigOptions, p as normalizeCodexAppServerArgs } from "./managed-binary-DcpnJF9x.js";
|
|
3
|
+
import { asNullableRecord, isRecord, normalizeOptionalString, normalizeTrimmedStringList } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
4
|
+
import { createHash } from "node:crypto";
|
|
5
|
+
import { resolveAgentConfig } from "openclaw/plugin-sdk/agent-scope-runtime";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { buildSecretInputSchema } from "openclaw/plugin-sdk/secret-input";
|
|
2
8
|
import path from "node:path";
|
|
3
|
-
import { resolvePositiveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
|
|
4
9
|
import { AgentHarnessPreflightError } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
5
|
-
import { createHash, createHmac, randomBytes } from "node:crypto";
|
|
6
10
|
import { readFileSync } from "node:fs";
|
|
7
11
|
import { homedir, hostname } from "node:os";
|
|
8
12
|
import { resolveProviderIdForAuth } from "openclaw/plugin-sdk/agent-runtime";
|
|
9
|
-
import { parse } from "smol-toml";
|
|
10
|
-
import { resolveAgentConfig as resolveAgentConfig$1 } from "openclaw/plugin-sdk/agent-scope-runtime";
|
|
11
13
|
import { resolveExecApprovalsFromFile } from "openclaw/plugin-sdk/exec-approvals-runtime";
|
|
12
|
-
import { buildSecretInputSchema, normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-input";
|
|
13
14
|
import { detectWindowsSpawnCommandInlineArgs } from "openclaw/plugin-sdk/windows-spawn";
|
|
14
|
-
import {
|
|
15
|
+
import { parse } from "smol-toml";
|
|
15
16
|
import { isLoopbackHost } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
16
|
-
//#region extensions/codex/src/app-server/
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const parsed = Number(trimmed);
|
|
58
|
-
return Number.isFinite(parsed) ? parsed : void 0;
|
|
59
|
-
}
|
|
60
|
-
function resolveArgs(configArgs, envArgs) {
|
|
61
|
-
if (Array.isArray(configArgs)) return configArgs.map((entry) => readNonEmptyString(entry)).filter((entry) => entry !== void 0);
|
|
62
|
-
if (typeof configArgs === "string") return splitShellWords(configArgs);
|
|
63
|
-
return splitShellWords(envArgs ?? "");
|
|
64
|
-
}
|
|
65
|
-
function hashSecretForKey(value, label) {
|
|
66
|
-
if (!value) return null;
|
|
67
|
-
return createHmac("sha256", START_OPTIONS_KEY_SECRET).update(label).update("\0").update(value).digest("hex");
|
|
68
|
-
}
|
|
69
|
-
function getStartOptionsKeySecret() {
|
|
70
|
-
const globalState = globalThis;
|
|
71
|
-
globalState[START_OPTIONS_KEY_SECRET_SYMBOL] ??= randomBytes(32);
|
|
72
|
-
return globalState[START_OPTIONS_KEY_SECRET_SYMBOL];
|
|
73
|
-
}
|
|
74
|
-
function splitShellWords(value) {
|
|
75
|
-
const words = [];
|
|
76
|
-
let current = "";
|
|
77
|
-
let quote = null;
|
|
78
|
-
for (const char of value) {
|
|
79
|
-
if (quote) {
|
|
80
|
-
if (char === quote) quote = null;
|
|
81
|
-
else current += char;
|
|
82
|
-
continue;
|
|
83
|
-
}
|
|
84
|
-
if (char === "\"" || char === "'") {
|
|
85
|
-
quote = char;
|
|
86
|
-
continue;
|
|
87
|
-
}
|
|
88
|
-
if (/\s/.test(char)) {
|
|
89
|
-
if (current) {
|
|
90
|
-
words.push(current);
|
|
91
|
-
current = "";
|
|
92
|
-
}
|
|
93
|
-
continue;
|
|
94
|
-
}
|
|
95
|
-
current += char;
|
|
96
|
-
}
|
|
97
|
-
if (current) words.push(current);
|
|
98
|
-
return words;
|
|
17
|
+
//#region extensions/codex/src/app-server/protocol.ts
|
|
18
|
+
/** Namespace Codex keeps directly model-visible without exposing it to Code Mode guests. */
|
|
19
|
+
const CODEX_OPENCLAW_DIRECT_DYNAMIC_TOOL_NAMESPACE = "openclaw_direct";
|
|
20
|
+
function flattenCodexDynamicToolFunctions(tools) {
|
|
21
|
+
return (tools ?? []).flatMap((tool) => tool.type === "namespace" ? tool.tools : [tool]);
|
|
22
|
+
}
|
|
23
|
+
const CODEX_INTERACTIVE_THREAD_SOURCE_KINDS = ["cli", "vscode"];
|
|
24
|
+
const CODEX_INTERACTIVE_CUSTOM_THREAD_SOURCES = ["atlas", "chatgpt"];
|
|
25
|
+
function isJsonObject(value) {
|
|
26
|
+
return isRecord(value);
|
|
27
|
+
}
|
|
28
|
+
function isRpcResponse(message) {
|
|
29
|
+
return "id" in message && !("method" in message);
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
//#region extensions/codex/src/app-server/auth-start-options.ts
|
|
33
|
+
const CODEX_APP_SERVER_HOME_DIRNAME = "codex-home";
|
|
34
|
+
const CODEX_EPHEMERAL_AUTH_STORE_OVERRIDE = "cli_auth_credentials_store=\"ephemeral\"";
|
|
35
|
+
function resolveCodexAppServerHomeDir(agentDir) {
|
|
36
|
+
return path.join(path.resolve(agentDir), CODEX_APP_SERVER_HOME_DIRNAME);
|
|
37
|
+
}
|
|
38
|
+
/** Resolves the native user Codex home used by Desktop and the CLI. */
|
|
39
|
+
function resolveCodexAppServerUserHomeDir(env = process.env, homedir$1 = homedir) {
|
|
40
|
+
const configured = normalizeOptionalString(env.CODEX_HOME);
|
|
41
|
+
return path.resolve(configured ?? path.join(homedir$1(), ".codex"));
|
|
42
|
+
}
|
|
43
|
+
/** Resolves the local CODEX_HOME used when starting one app-server connection. */
|
|
44
|
+
function resolveCodexAppServerLocalHomeDir(startOptions, agentDir, env = process.env) {
|
|
45
|
+
const configured = startOptions.env?.CODEX_HOME;
|
|
46
|
+
if (configured?.trim()) return configured;
|
|
47
|
+
return startOptions.homeScope === "user" ? resolveCodexAppServerUserHomeDir(env) : resolveCodexAppServerHomeDir(agentDir);
|
|
48
|
+
}
|
|
49
|
+
/** Forces OpenClaw-owned Codex auth to remain process-local. */
|
|
50
|
+
function withEphemeralCodexAuthStore(params) {
|
|
51
|
+
const { startOptions } = params;
|
|
52
|
+
if (!params.preparedAuth && params.authProfileId === null) return startOptions;
|
|
53
|
+
const args = normalizeCodexAppServerArgs(startOptions.args, CODEX_EPHEMERAL_AUTH_STORE_OVERRIDE);
|
|
54
|
+
return args === startOptions.args ? startOptions : {
|
|
55
|
+
...startOptions,
|
|
56
|
+
args
|
|
57
|
+
};
|
|
99
58
|
}
|
|
100
59
|
//#endregion
|
|
101
60
|
//#region extensions/codex/src/app-server/config-exec-policy.ts
|
|
@@ -132,7 +91,7 @@ function resolveOpenClawExecPolicyFromConfig(params) {
|
|
|
132
91
|
const globalExec = readRecord(params.config?.tools?.exec);
|
|
133
92
|
const globalPolicy = applyOpenClawExecPolicyLayer(createDefaultOpenClawExecPolicy(), globalExec);
|
|
134
93
|
const agentId = params.agentId?.trim();
|
|
135
|
-
return applyOpenClawExecPolicyLayer(globalPolicy, agentId ? readRecord(resolveAgentConfig
|
|
94
|
+
return applyOpenClawExecPolicyLayer(globalPolicy, agentId ? readRecord(resolveAgentConfig(params.config ?? {}, agentId)?.tools?.exec) : void 0);
|
|
136
95
|
}
|
|
137
96
|
function resolveOpenClawExecPolicyForCodexAppServer(params) {
|
|
138
97
|
if (params.permissionMode === "full") return {
|
|
@@ -266,6 +225,246 @@ function readExecMode(value) {
|
|
|
266
225
|
return value === "deny" || value === "allowlist" || value === "ask" || value === "auto" || value === "full" ? value : void 0;
|
|
267
226
|
}
|
|
268
227
|
//#endregion
|
|
228
|
+
//#region extensions/codex/src/app-server/session-discovery-config.ts
|
|
229
|
+
const codexSessionCatalogHomeSchema = z.union([z.string().trim().min(1), z.object({
|
|
230
|
+
path: z.string().trim().min(1),
|
|
231
|
+
label: z.string().trim().min(1).optional()
|
|
232
|
+
}).strict()]);
|
|
233
|
+
const codexSessionCatalogConfigSchema = z.object({
|
|
234
|
+
enabled: z.boolean().optional(),
|
|
235
|
+
homes: z.array(codexSessionCatalogHomeSchema).optional()
|
|
236
|
+
}).strict();
|
|
237
|
+
const codexDiscoveryConfigSchema = z.object({
|
|
238
|
+
enabled: z.boolean().optional(),
|
|
239
|
+
timeoutMs: z.number().positive().optional()
|
|
240
|
+
}).strict();
|
|
241
|
+
//#endregion
|
|
242
|
+
//#region extensions/codex/src/app-server/config-parsing.ts
|
|
243
|
+
const DEFAULT_CODEX_COMPUTER_USE_PLUGIN_NAME = "computer-use";
|
|
244
|
+
const DEFAULT_CODEX_COMPUTER_USE_MARKETPLACE_DISCOVERY_TIMEOUT_MS = 6e4;
|
|
245
|
+
const DEFAULT_CODEX_COMPUTER_USE_LIVE_TEST_TIMEOUT_MS = 6e4;
|
|
246
|
+
const DEFAULT_CODEX_COMPUTER_USE_TOOL_CALL_TIMEOUT_MS = 6e4;
|
|
247
|
+
const DEFAULT_CODEX_APP_SERVER_NETWORK_PROXY_PROFILE_PREFIX = "openclaw-network";
|
|
248
|
+
const codexAppServerTransportSchema = z.enum([
|
|
249
|
+
"stdio",
|
|
250
|
+
"websocket",
|
|
251
|
+
"unix"
|
|
252
|
+
]);
|
|
253
|
+
const codexAppServerHomeScopeSchema = z.enum(["agent", "user"]);
|
|
254
|
+
const SecretInputSchema = buildSecretInputSchema();
|
|
255
|
+
const codexAppServerPolicyModeSchema = z.enum(["yolo", "guardian"]);
|
|
256
|
+
const codexAppServerApprovalPolicySchema = z.preprocess((value) => value === "on-failure" ? "on-request" : value, z.enum(["never", "on-request"]));
|
|
257
|
+
const codexAppServerSandboxSchema = z.enum([
|
|
258
|
+
"read-only",
|
|
259
|
+
"workspace-write",
|
|
260
|
+
"danger-full-access"
|
|
261
|
+
]);
|
|
262
|
+
const codexAppServerApprovalsReviewerSchema = z.enum([
|
|
263
|
+
"user",
|
|
264
|
+
"auto_review",
|
|
265
|
+
"guardian_subagent"
|
|
266
|
+
]);
|
|
267
|
+
const codexDynamicToolsLoadingSchema = z.enum(["searchable", "direct"]);
|
|
268
|
+
const codexComputerUseHealthIntervalSchema = z.union([
|
|
269
|
+
z.literal(30),
|
|
270
|
+
z.literal(60),
|
|
271
|
+
z.literal(120),
|
|
272
|
+
z.literal(240)
|
|
273
|
+
]);
|
|
274
|
+
const codexComputerUsePluginCacheModeSchema = z.enum(["shared", "independent"]);
|
|
275
|
+
const codexPluginDestructivePolicySchema = z.union([
|
|
276
|
+
z.boolean(),
|
|
277
|
+
z.literal("auto"),
|
|
278
|
+
z.literal("ask")
|
|
279
|
+
]);
|
|
280
|
+
const codexAppServerServiceTierSchema = z.preprocess((value) => value === null ? null : normalizeCodexServiceTier(value), z.string().trim().min(1).nullable().optional()).optional();
|
|
281
|
+
const codexAppServerExperimentalSchema = z.object({ sandboxExecServer: z.boolean().optional() }).strict();
|
|
282
|
+
const codexAppServerRemoteWorkspaceRootSchema = z.string().trim().min(1);
|
|
283
|
+
const codexAppServerNetworkProxyDomainPermissionSchema = z.enum(["allow", "deny"]);
|
|
284
|
+
const codexAppServerNetworkProxyUnixSocketPermissionSchema = z.enum(["allow", "none"]);
|
|
285
|
+
const codexAppServerNetworkProxySchema = z.object({
|
|
286
|
+
enabled: z.boolean().optional(),
|
|
287
|
+
profileName: z.string().trim().min(1).optional(),
|
|
288
|
+
baseProfile: z.enum(["read-only", "workspace"]).optional(),
|
|
289
|
+
mode: z.enum(["limited", "full"]).optional(),
|
|
290
|
+
domains: z.record(z.string(), codexAppServerNetworkProxyDomainPermissionSchema).optional(),
|
|
291
|
+
unixSockets: z.record(z.string(), codexAppServerNetworkProxyUnixSocketPermissionSchema).optional(),
|
|
292
|
+
proxyUrl: z.string().trim().min(1).optional(),
|
|
293
|
+
socksUrl: z.string().trim().min(1).optional(),
|
|
294
|
+
enableSocks5: z.boolean().optional(),
|
|
295
|
+
enableSocks5Udp: z.boolean().optional(),
|
|
296
|
+
allowUpstreamProxy: z.boolean().optional(),
|
|
297
|
+
allowLocalBinding: z.boolean().optional(),
|
|
298
|
+
dangerouslyAllowNonLoopbackProxy: z.boolean().optional(),
|
|
299
|
+
dangerouslyAllowAllUnixSockets: z.boolean().optional()
|
|
300
|
+
}).strict();
|
|
301
|
+
const codexPluginEntryConfigSchema = z.object({
|
|
302
|
+
enabled: z.boolean().optional(),
|
|
303
|
+
marketplaceName: z.string().regex(CODEX_PLUGIN_MARKETPLACE_NAME_PATTERN).optional(),
|
|
304
|
+
pluginName: z.string().trim().min(1).optional(),
|
|
305
|
+
allow_destructive_actions: codexPluginDestructivePolicySchema.optional()
|
|
306
|
+
}).strict();
|
|
307
|
+
const codexPluginsConfigSchema = z.object({
|
|
308
|
+
enabled: z.boolean().optional(),
|
|
309
|
+
allow_all_plugins: z.boolean().optional(),
|
|
310
|
+
allow_destructive_actions: codexPluginDestructivePolicySchema.optional(),
|
|
311
|
+
plugins: z.record(z.string(), codexPluginEntryConfigSchema).optional()
|
|
312
|
+
}).strict();
|
|
313
|
+
const codexSupervisionEndpointSchema = z.union([z.object({
|
|
314
|
+
id: z.string().optional(),
|
|
315
|
+
label: z.string().optional(),
|
|
316
|
+
transport: z.literal("stdio-proxy").optional(),
|
|
317
|
+
command: z.string().optional(),
|
|
318
|
+
args: z.array(z.string()).optional(),
|
|
319
|
+
cwd: z.string().optional()
|
|
320
|
+
}).strict(), z.object({
|
|
321
|
+
id: z.string().optional(),
|
|
322
|
+
label: z.string().optional(),
|
|
323
|
+
transport: z.literal("websocket"),
|
|
324
|
+
url: z.string(),
|
|
325
|
+
authTokenEnv: z.string().optional()
|
|
326
|
+
}).strict()]);
|
|
327
|
+
const codexSupervisionConfigSchema = z.object({
|
|
328
|
+
enabled: z.boolean().optional(),
|
|
329
|
+
endpoints: z.array(codexSupervisionEndpointSchema).optional(),
|
|
330
|
+
allowRawTranscripts: z.boolean().optional(),
|
|
331
|
+
allowWriteControls: z.boolean().optional()
|
|
332
|
+
}).strict();
|
|
333
|
+
const codexPluginConfigSchema = z.object({
|
|
334
|
+
codexDynamicToolsLoading: codexDynamicToolsLoadingSchema.optional(),
|
|
335
|
+
codexDynamicToolsExclude: z.array(z.string()).optional(),
|
|
336
|
+
sessionCatalog: codexSessionCatalogConfigSchema.optional(),
|
|
337
|
+
discovery: codexDiscoveryConfigSchema.optional(),
|
|
338
|
+
computerUse: z.object({
|
|
339
|
+
enabled: z.boolean().optional(),
|
|
340
|
+
autoInstall: z.boolean().optional(),
|
|
341
|
+
marketplaceDiscoveryTimeoutMs: z.number().positive().optional(),
|
|
342
|
+
liveTestTimeoutMs: z.number().positive().optional(),
|
|
343
|
+
toolCallTimeoutMs: z.number().positive().optional(),
|
|
344
|
+
healthCheckEnabled: z.boolean().optional(),
|
|
345
|
+
healthCheckIntervalMinutes: codexComputerUseHealthIntervalSchema.optional(),
|
|
346
|
+
pluginCacheMode: codexComputerUsePluginCacheModeSchema.optional(),
|
|
347
|
+
strictReadiness: z.boolean().optional(),
|
|
348
|
+
autoRepair: z.boolean().optional(),
|
|
349
|
+
marketplaceSource: z.string().optional(),
|
|
350
|
+
marketplacePath: z.string().optional(),
|
|
351
|
+
marketplaceName: z.string().optional(),
|
|
352
|
+
pluginName: z.string().optional(),
|
|
353
|
+
mcpServerName: z.string().optional()
|
|
354
|
+
}).strict().optional(),
|
|
355
|
+
codexPlugins: z.unknown().optional(),
|
|
356
|
+
supervision: codexSupervisionConfigSchema.optional(),
|
|
357
|
+
appServer: z.object({
|
|
358
|
+
mode: codexAppServerPolicyModeSchema.optional(),
|
|
359
|
+
transport: codexAppServerTransportSchema.optional(),
|
|
360
|
+
homeScope: codexAppServerHomeScopeSchema.optional(),
|
|
361
|
+
command: z.string().optional(),
|
|
362
|
+
args: z.union([z.array(z.string()), z.string()]).optional(),
|
|
363
|
+
url: z.string().optional(),
|
|
364
|
+
authToken: SecretInputSchema.optional(),
|
|
365
|
+
headers: z.record(z.string(), SecretInputSchema).optional(),
|
|
366
|
+
clearEnv: z.array(z.string()).optional(),
|
|
367
|
+
remoteWorkspaceRoot: codexAppServerRemoteWorkspaceRootSchema.optional(),
|
|
368
|
+
codeModeOnly: z.boolean().optional(),
|
|
369
|
+
loopDetectionPreToolUseRelay: z.boolean().optional(),
|
|
370
|
+
requestTimeoutMs: z.number().positive().optional(),
|
|
371
|
+
approvalPolicy: codexAppServerApprovalPolicySchema.optional(),
|
|
372
|
+
sandbox: codexAppServerSandboxSchema.optional(),
|
|
373
|
+
approvalsReviewer: codexAppServerApprovalsReviewerSchema.optional(),
|
|
374
|
+
serviceTier: codexAppServerServiceTierSchema,
|
|
375
|
+
networkProxy: codexAppServerNetworkProxySchema.optional(),
|
|
376
|
+
defaultWorkspaceDir: z.string().optional(),
|
|
377
|
+
experimental: codexAppServerExperimentalSchema.optional()
|
|
378
|
+
}).strict().optional()
|
|
379
|
+
}).strict();
|
|
380
|
+
function readCodexPluginConfig(value) {
|
|
381
|
+
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\".");
|
|
382
|
+
const parsed = codexPluginConfigSchema.safeParse(value);
|
|
383
|
+
if (!parsed.success) return {};
|
|
384
|
+
const { codexPlugins: rawCodexPlugins, ...config } = parsed.data;
|
|
385
|
+
const plugins = codexPluginsConfigSchema.safeParse(rawCodexPlugins);
|
|
386
|
+
if (!plugins.success) return config;
|
|
387
|
+
return {
|
|
388
|
+
...config,
|
|
389
|
+
...plugins.data ? { codexPlugins: plugins.data } : {}
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
function isCodexSandboxExecServerEnabled(pluginConfig, sandbox) {
|
|
393
|
+
return isCodexRemoteExecPlacementSandbox(sandbox) || readCodexPluginConfig(pluginConfig).appServer?.experimental?.sandboxExecServer === true;
|
|
394
|
+
}
|
|
395
|
+
function isCodexRemoteExecPlacementSandbox(sandbox) {
|
|
396
|
+
return typeof sandbox === "object" && sandbox !== null && "placementExecutionMode" in sandbox && sandbox.placementExecutionMode === "remote-exec";
|
|
397
|
+
}
|
|
398
|
+
function isCodexPairedNodeRemoteExecPlacementSandbox(sandbox) {
|
|
399
|
+
return isCodexRemoteExecPlacementSandbox(sandbox) && typeof sandbox === "object" && sandbox !== null && "placementNodeId" in sandbox && typeof sandbox.placementNodeId === "string" && sandbox.placementNodeId.length > 0;
|
|
400
|
+
}
|
|
401
|
+
function assertCodexAppServerCommandHasNoInlineArgs(params) {
|
|
402
|
+
const inlineArgs = detectWindowsSpawnCommandInlineArgs(params.command);
|
|
403
|
+
if (!inlineArgs) return;
|
|
404
|
+
const sourceLabel = params.source === "env" ? "OPENCLAW_CODEX_APP_SERVER_BIN" : "plugins.entries.codex.config.appServer.command";
|
|
405
|
+
const argsLabel = params.source === "env" ? "OPENCLAW_CODEX_APP_SERVER_ARGS" : "plugins.entries.codex.config.appServer.args";
|
|
406
|
+
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.`);
|
|
407
|
+
}
|
|
408
|
+
function resolveCodexPluginsPolicy(pluginConfig) {
|
|
409
|
+
const config = readCodexPluginConfig(pluginConfig).codexPlugins;
|
|
410
|
+
const configured = config !== void 0;
|
|
411
|
+
const enabled = config?.enabled === true;
|
|
412
|
+
const destructivePolicy = resolveCodexPluginDestructivePolicy(config?.allow_destructive_actions ?? true);
|
|
413
|
+
const pluginPolicies = Object.entries(config?.plugins ?? {}).flatMap(([configKey, entry]) => {
|
|
414
|
+
if (!isCodexPluginMarketplaceName(entry.marketplaceName) || !entry.pluginName) return [];
|
|
415
|
+
const entryDestructivePolicy = resolveCodexPluginDestructivePolicy(entry.allow_destructive_actions ?? config?.allow_destructive_actions ?? true);
|
|
416
|
+
return [{
|
|
417
|
+
configKey,
|
|
418
|
+
marketplaceName: entry.marketplaceName,
|
|
419
|
+
pluginName: entry.pluginName,
|
|
420
|
+
enabled: enabled && entry.enabled !== false,
|
|
421
|
+
allowDestructiveActions: entryDestructivePolicy.allowDestructiveActions,
|
|
422
|
+
destructiveApprovalMode: entryDestructivePolicy.destructiveApprovalMode
|
|
423
|
+
}];
|
|
424
|
+
}).toSorted((left, right) => left.configKey.localeCompare(right.configKey));
|
|
425
|
+
return {
|
|
426
|
+
configured,
|
|
427
|
+
enabled,
|
|
428
|
+
allowAllPlugins: enabled && config?.allow_all_plugins === true,
|
|
429
|
+
allowDestructiveActions: destructivePolicy.allowDestructiveActions,
|
|
430
|
+
destructiveApprovalMode: destructivePolicy.destructiveApprovalMode,
|
|
431
|
+
pluginPolicies
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
function isCodexPluginMarketplaceName(value) {
|
|
435
|
+
return typeof value === "string" && CODEX_PLUGIN_MARKETPLACE_NAME_PATTERN.test(value);
|
|
436
|
+
}
|
|
437
|
+
function resolveCodexPluginDestructivePolicy(policy) {
|
|
438
|
+
if (policy === "auto" || policy === "ask") return {
|
|
439
|
+
allowDestructiveActions: true,
|
|
440
|
+
destructiveApprovalMode: policy
|
|
441
|
+
};
|
|
442
|
+
return {
|
|
443
|
+
allowDestructiveActions: policy,
|
|
444
|
+
destructiveApprovalMode: policy ? "allow" : "deny"
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
//#endregion
|
|
448
|
+
//#region extensions/codex/src/app-server/config-layer-policy.ts
|
|
449
|
+
const CODEX_SESSION_OVERRIDABLE_LAYER_TYPES = /* @__PURE__ */ new Set([
|
|
450
|
+
"packagedDefaults",
|
|
451
|
+
"mdm",
|
|
452
|
+
"system",
|
|
453
|
+
"enterpriseManaged",
|
|
454
|
+
"user",
|
|
455
|
+
"project",
|
|
456
|
+
"sessionFlags"
|
|
457
|
+
]);
|
|
458
|
+
/** Read one effective snapshot for the current boundary's reviewer and tool-policy checks. */
|
|
459
|
+
async function readCodexEffectiveConfig(client, cwd, signal) {
|
|
460
|
+
const response = await client.request("config/read", {
|
|
461
|
+
cwd: path.resolve(cwd),
|
|
462
|
+
includeLayers: true
|
|
463
|
+
}, { signal });
|
|
464
|
+
if (!isJsonObject(response) || !isJsonObject(response.config)) throw new Error("Codex config/read returned an invalid effective config");
|
|
465
|
+
return response;
|
|
466
|
+
}
|
|
467
|
+
//#endregion
|
|
269
468
|
//#region extensions/codex/src/app-server/config-requirements.ts
|
|
270
469
|
const UNIX_CODEX_REQUIREMENTS_PATH = "/etc/codex/requirements.toml";
|
|
271
470
|
const WINDOWS_CODEX_REQUIREMENTS_SUFFIX = "\\OpenAI\\Codex\\requirements.toml";
|
|
@@ -461,22 +660,19 @@ function selectUserApprovalsReviewer(allowedApprovalsReviewers, execModeRequirin
|
|
|
461
660
|
}
|
|
462
661
|
//#endregion
|
|
463
662
|
//#region extensions/codex/src/app-server/config-reviewer.ts
|
|
464
|
-
const CODEX_APP_SERVER_HOME_DIRNAME = "codex-home";
|
|
465
663
|
const CODEX_CONFIG_TOML_FILENAME = "config.toml";
|
|
466
664
|
/** Cloud/system config can redirect reviews after local home/profile checks have passed. */
|
|
467
665
|
async function assertCodexModelBackedReviewerEffectiveConfig(params) {
|
|
468
666
|
if (params.approvalsReviewer !== "auto_review" && params.approvalsReviewer !== "guardian_subagent") return;
|
|
469
|
-
const
|
|
470
|
-
|
|
471
|
-
includeLayers: false
|
|
472
|
-
}, { signal: params.signal }))?.config);
|
|
473
|
-
if (!effectiveConfig) throw new Error("Codex config/read returned an invalid model-backed reviewer config");
|
|
667
|
+
const response = await readCodexEffectiveConfig(params.client, params.cwd, params.signal);
|
|
668
|
+
const effectiveConfig = response.config;
|
|
474
669
|
const modelProvider = effectiveConfig.model_provider;
|
|
475
670
|
const providers = effectiveConfig.model_providers;
|
|
476
671
|
const providerRecords = providers == null ? void 0 : readRecord(providers);
|
|
477
672
|
const provider = providerRecords?.openai;
|
|
478
673
|
const openAIProvider = provider == null ? void 0 : readRecord(provider);
|
|
479
674
|
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");
|
|
675
|
+
return response;
|
|
480
676
|
}
|
|
481
677
|
function isTrustedOptionalReviewerEndpoint(value, isTrusted) {
|
|
482
678
|
return value == null || typeof value === "string" && isTrusted(value);
|
|
@@ -484,9 +680,8 @@ function isTrustedOptionalReviewerEndpoint(value, isTrusted) {
|
|
|
484
680
|
function canUseCodexModelBackedApprovalsReviewerForModel(params) {
|
|
485
681
|
const explicitProvider = params.modelProvider?.trim().toLowerCase();
|
|
486
682
|
const inferredProvider = inferProviderFromModelRef(params.model);
|
|
487
|
-
if (explicitProvider && explicitProvider !== "codex"
|
|
488
|
-
|
|
489
|
-
return isTrustedCodexModelBackedApprovalsReviewerProvider(explicitProvider, params);
|
|
683
|
+
if (explicitProvider && explicitProvider !== "codex" && explicitProvider !== "openai") return false;
|
|
684
|
+
return (inferredProvider ?? explicitProvider) === "openai" && isTrustedCodexModelBackedOpenAIProvider(params);
|
|
490
685
|
}
|
|
491
686
|
function isTrustedCodexModelBackedOpenAIProvider(params) {
|
|
492
687
|
if (!openAIBaseUrlEnvOverridesAreTrustedForModelBackedReview(params.env)) return false;
|
|
@@ -523,20 +718,6 @@ function resolveCodexModelBackedReviewerPolicyContext(params) {
|
|
|
523
718
|
model: params.model ?? params.bindingModel
|
|
524
719
|
};
|
|
525
720
|
}
|
|
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
721
|
function readCodexBaseUrlOverridesForModelBackedReview(params) {
|
|
541
722
|
const configToml = readCodexAppServerConfigToml(params);
|
|
542
723
|
if (configToml === false) return false;
|
|
@@ -561,19 +742,13 @@ function readCodexBaseUrlOverridesForModelBackedReview(params) {
|
|
|
561
742
|
};
|
|
562
743
|
}
|
|
563
744
|
function readNativeCodexReviewerConfigOverrides(params) {
|
|
745
|
+
if (params.codexArgs?.some((arg) => !arg)) return false;
|
|
564
746
|
const overrides = [];
|
|
565
747
|
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`);
|
|
748
|
+
for (const { name, value } of readCodexAppServerConfigOptions(params.codexArgs ?? [])) {
|
|
749
|
+
if (!value) return false;
|
|
750
|
+
if (name === "--profile" || name === "-p") profile = value;
|
|
751
|
+
else overrides.push(`${value}\n`);
|
|
577
752
|
}
|
|
578
753
|
if (profile) {
|
|
579
754
|
if (path.basename(profile) !== profile || profile === "." || profile === "..") return false;
|
|
@@ -623,13 +798,7 @@ function codexConfigEnablesNativeComputerUse(params) {
|
|
|
623
798
|
function resolveCodexAppServerConfigPath(params) {
|
|
624
799
|
if (params.homeScope === "user") return path.join(resolveCodexAppServerUserHomeDir(params.env), CODEX_CONFIG_TOML_FILENAME);
|
|
625
800
|
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"));
|
|
801
|
+
return agentDir ? path.join(resolveCodexAppServerHomeDir(agentDir), CODEX_CONFIG_TOML_FILENAME) : void 0;
|
|
633
802
|
}
|
|
634
803
|
function readErrorCode(error) {
|
|
635
804
|
return error && typeof error === "object" && "code" in error ? String(error.code) : void 0;
|
|
@@ -703,234 +872,6 @@ function inferProviderFromModelRef(model) {
|
|
|
703
872
|
return slashIndex > 0 ? normalized?.slice(0, slashIndex) : void 0;
|
|
704
873
|
}
|
|
705
874
|
//#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
875
|
//#region extensions/codex/src/app-server/config-security.ts
|
|
935
876
|
function shouldAutoApproveCodexAppServerApprovals(appServer) {
|
|
936
877
|
return appServer.networkProxy === void 0 && appServer.approvalPolicy === "never" && appServer.sandbox === "danger-full-access";
|
|
@@ -974,10 +915,11 @@ function resolveCodexAppServerNetworkProxy(config, sandbox) {
|
|
|
974
915
|
function resolveNetworkProxyPermissionProfileName(config, profile) {
|
|
975
916
|
const explicitProfileName = readNonEmptyString(config.profileName);
|
|
976
917
|
if (explicitProfileName) return explicitProfileName;
|
|
977
|
-
|
|
918
|
+
const suffix = createHash("sha256").update(stableStringifyJson({
|
|
978
919
|
version: 1,
|
|
979
920
|
profile
|
|
980
|
-
})).digest("hex").slice(0, 16)
|
|
921
|
+
})).digest("hex").slice(0, 16);
|
|
922
|
+
return `${DEFAULT_CODEX_APP_SERVER_NETWORK_PROXY_PROFILE_PREFIX}-${suffix}`;
|
|
981
923
|
}
|
|
982
924
|
function fingerprintCodexAppServerNetworkProxyConfigPatch(configPatch) {
|
|
983
925
|
return createHash("sha256").update(stableStringifyJson(configPatch)).digest("hex");
|
|
@@ -994,6 +936,16 @@ function stableStringifyJson(value) {
|
|
|
994
936
|
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
937
|
return JSON.stringify(value);
|
|
996
938
|
}
|
|
939
|
+
/** Explicit MCP prompting must bypass Codex's unconditional Never-policy approval. */
|
|
940
|
+
function hasCodexMcpToolApprovalOverrides(servers, serverNames, projectedMcpServers) {
|
|
941
|
+
const modes = new Map(Object.entries(projectedMcpServers ?? {}).map(([name, server]) => [name, server.default_tools_approval_mode]));
|
|
942
|
+
for (const name of serverNames ?? Object.keys(servers ?? {})) {
|
|
943
|
+
const server = servers?.[name];
|
|
944
|
+
const mode = server?.codex?.defaultToolsApprovalMode;
|
|
945
|
+
if (mode !== void 0 && (serverNames !== void 0 || server?.enabled !== false)) modes.set(name, mode);
|
|
946
|
+
}
|
|
947
|
+
return [...modes.values()].some((mode) => mode === "auto" || mode === "prompt");
|
|
948
|
+
}
|
|
997
949
|
function withMcpElicitationsApprovalPolicy(policy) {
|
|
998
950
|
if (policy === "untrusted") return policy;
|
|
999
951
|
if (typeof policy !== "string") return { granular: {
|
|
@@ -1243,9 +1195,6 @@ function resolveCodexAppServerRuntimeOptions(params = {}) {
|
|
|
1243
1195
|
codeModeOnly: config.codeModeOnly === true,
|
|
1244
1196
|
loopDetectionPreToolUseRelay: config.loopDetectionPreToolUseRelay !== false,
|
|
1245
1197
|
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
1198
|
approvalPolicy: forcedPolicy?.approvalPolicy ?? approvalPolicy,
|
|
1250
1199
|
approvalPolicySource,
|
|
1251
1200
|
sandbox: resolvedSandbox,
|
|
@@ -1346,17 +1295,22 @@ function codexSandboxPolicyForTurn(mode, cwd, nativeArgs = []) {
|
|
|
1346
1295
|
};
|
|
1347
1296
|
let excludeTmpdirEnvVar = false;
|
|
1348
1297
|
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;
|
|
1298
|
+
for (const { name, value: override } of readCodexAppServerConfigOptions(nativeArgs)) {
|
|
1299
|
+
if (name !== "-c" && name !== "--config" || !override) continue;
|
|
1353
1300
|
const separator = override.indexOf("=");
|
|
1354
1301
|
if (separator < 0) continue;
|
|
1355
1302
|
const key = override.slice(0, separator).trim();
|
|
1356
|
-
const
|
|
1357
|
-
if (
|
|
1358
|
-
|
|
1359
|
-
|
|
1303
|
+
const isTmpdirExclusion = key === "sandbox_workspace_write.exclude_tmpdir_env_var";
|
|
1304
|
+
if (!isTmpdirExclusion && key !== "sandbox_workspace_write.exclude_slash_tmp") continue;
|
|
1305
|
+
let value;
|
|
1306
|
+
try {
|
|
1307
|
+
value = parse(`_x_ = ${override.slice(separator + 1).trim()}`)["_x_"];
|
|
1308
|
+
} catch {
|
|
1309
|
+
continue;
|
|
1310
|
+
}
|
|
1311
|
+
if (typeof value !== "boolean") continue;
|
|
1312
|
+
if (isTmpdirExclusion) excludeTmpdirEnvVar = value;
|
|
1313
|
+
else excludeSlashTmp = value;
|
|
1360
1314
|
}
|
|
1361
1315
|
return {
|
|
1362
1316
|
type: "workspaceWrite",
|
|
@@ -1386,4 +1340,4 @@ function resolveCodexSupervisionAppServerRuntimeOptions(params = {}) {
|
|
|
1386
1340
|
});
|
|
1387
1341
|
}
|
|
1388
1342
|
//#endregion
|
|
1389
|
-
export {
|
|
1343
|
+
export { resolveOpenClawExecPolicyForCodexAppServer as A, isJsonObject as B, CODEX_SESSION_OVERRIDABLE_LAYER_TYPES as C, isCodexSandboxExecServerEnabled as D, isCodexRemoteExecPlacementSandbox as E, withEphemeralCodexAuthStore as F, CODEX_INTERACTIVE_CUSTOM_THREAD_SOURCES as I, CODEX_INTERACTIVE_THREAD_SOURCE_KINDS as L, resolveCodexAppServerHomeDir as M, resolveCodexAppServerLocalHomeDir as N, readCodexPluginConfig as O, resolveCodexAppServerUserHomeDir as P, CODEX_OPENCLAW_DIRECT_DYNAMIC_TOOL_NAMESPACE as R, selectUserApprovalsReviewer as S, isCodexPairedNodeRemoteExecPlacementSandbox as T, isRpcResponse as V, 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, selectGuardianSandbox as j, resolveCodexPluginsPolicy 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, readCodexEffectiveConfig as w, selectGuardianApprovalsReviewer as x, readCodexRequirementsToml as y, flattenCodexDynamicToolFunctions as z };
|