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