@openclaw/codex 2026.6.8 → 2026.6.9-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/{notification-correlation-BGoG0N90.js → app-server-policy-KpyUye2D.js} +15 -74
  2. package/dist/attempt-notifications-Meja3TX6.js +249 -0
  3. package/dist/{client-factory-C71Xdb6z.js → client-factory-CPuoOOx6.js} +3 -2
  4. package/dist/{client-DovmVtbr.js → client-m7XiCQpO.js} +24 -2
  5. package/dist/{command-handlers-DHecBkuc.js → command-handlers-CqS0Kv3Z.js} +17 -13
  6. package/dist/{compact-GEKusemL.js → compact-CMVlldii.js} +5 -5
  7. package/dist/{computer-use-D1qxvTE_.js → computer-use-qLm7Gf35.js} +3 -3
  8. package/dist/{config-DJXpBkGf.js → config-BksX0T33.js} +160 -20
  9. package/dist/{conversation-binding-CbnMilVW.js → conversation-binding-DBof5w9J.js} +166 -58
  10. package/dist/doctor-contract-api.js +37 -3
  11. package/dist/harness.js +6 -6
  12. package/dist/index.js +108 -27
  13. package/dist/media-understanding-provider-CiwPkR58.js +463 -0
  14. package/dist/media-understanding-provider.js +1 -355
  15. package/dist/{models-DRKnOpzF.js → models-BsyV1Psm.js} +2 -2
  16. package/dist/{plugin-app-cache-key-kIqpGTQj.js → plugin-app-cache-key-CN9zBiCG.js} +17 -6
  17. package/dist/{protocol-oeJQu4rs.js → protocol-dh-ETiNd.js} +4 -1
  18. package/dist/{protocol-validators-B48C6S9O.js → protocol-validators-B19q5BIX.js} +210 -16
  19. package/dist/{native-hook-relay-C3i3FYtc.js → provider-capabilities-BOvTfMhF.js} +803 -78
  20. package/dist/{provider-C5P6352f.js → provider-qJygHQx4.js} +4 -4
  21. package/dist/provider.js +1 -1
  22. package/dist/{request-BxZ40QKY.js → request-DTIEyUrA.js} +2 -2
  23. package/dist/{run-attempt-D_q-VrpR.js → run-attempt-DRhB6bTc.js} +421 -774
  24. package/dist/{sandbox-guard-C-Yv9uwY.js → sandbox-guard-3tnjhjFb.js} +37 -10
  25. package/dist/{session-binding-ElbcSq2o.js → session-binding-BRUi8y6E.js} +27 -8
  26. package/dist/{shared-client-jFMumCOe.js → shared-client-Bg5d7VV9.js} +4 -4
  27. package/dist/{side-question-DqKLfWMB.js → side-question-BdYL4kj1.js} +106 -42
  28. package/dist/{thread-lifecycle-cban34w3.js → thread-lifecycle-CbJqqnEw.js} +912 -616
  29. package/dist/web-search-contract-api.js +10 -0
  30. package/dist/web-search-provider.runtime-DrpQ8Cyd.js +74 -0
  31. package/dist/web-search-provider.shared-BrZmlqyR.js +32 -0
  32. package/npm-shrinkwrap.json +2 -2
  33. package/openclaw.plugin.json +129 -4
  34. package/package.json +4 -4
@@ -1,12 +1,12 @@
1
+ import path from "node:path";
1
2
  import { resolvePositiveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
2
- import { createHmac, randomBytes } from "node:crypto";
3
+ import { normalizeTrimmedStringList } from "openclaw/plugin-sdk/string-coerce-runtime";
4
+ import { createHash, createHmac, randomBytes } from "node:crypto";
3
5
  import { readFileSync } from "node:fs";
4
6
  import { hostname } from "node:os";
5
- import path from "node:path";
6
7
  import { resolveProviderIdForAuth } from "openclaw/plugin-sdk/agent-runtime";
7
8
  import { resolveExecApprovalsFromFile } from "openclaw/plugin-sdk/exec-approvals-runtime";
8
9
  import { normalizeAgentId } from "openclaw/plugin-sdk/routing";
9
- import { normalizeTrimmedStringList } from "openclaw/plugin-sdk/string-coerce-runtime";
10
10
  import { detectWindowsSpawnCommandInlineArgs } from "openclaw/plugin-sdk/windows-spawn";
11
11
  import { z } from "zod";
12
12
  //#region extensions/codex/src/app-server/config.ts
@@ -19,11 +19,12 @@ const CODEX_CONFIG_TOML_FILENAME = "config.toml";
19
19
  const PLAIN_DECIMAL_NUMBER_RE = /^[+-]?(?:(?:\d+\.?\d*)|(?:\.\d+))$/;
20
20
  const CODEX_PLUGINS_MARKETPLACE_NAME = "openai-curated";
21
21
  function shouldAutoApproveCodexAppServerApprovals(appServer) {
22
- return appServer.approvalPolicy === "never" && appServer.sandbox === "danger-full-access";
22
+ return appServer.networkProxy === void 0 && appServer.approvalPolicy === "never" && appServer.sandbox === "danger-full-access";
23
23
  }
24
24
  const DEFAULT_CODEX_COMPUTER_USE_PLUGIN_NAME = "computer-use";
25
25
  const DEFAULT_CODEX_COMPUTER_USE_MCP_SERVER_NAME = "computer-use";
26
26
  const DEFAULT_CODEX_COMPUTER_USE_MARKETPLACE_DISCOVERY_TIMEOUT_MS = 6e4;
27
+ const DEFAULT_CODEX_APP_SERVER_NETWORK_PROXY_PROFILE_PREFIX = "openclaw-network";
27
28
  const codexAppServerTransportSchema = z.enum(["stdio", "websocket"]);
28
29
  const codexAppServerPolicyModeSchema = z.enum(["yolo", "guardian"]);
29
30
  const codexAppServerApprovalPolicySchema = z.enum([
@@ -43,17 +44,37 @@ const codexAppServerApprovalsReviewerSchema = z.enum([
43
44
  "guardian_subagent"
44
45
  ]);
45
46
  const codexDynamicToolsLoadingSchema = z.enum(["searchable", "direct"]);
47
+ const codexPluginDestructivePolicySchema = z.union([z.boolean(), z.literal("auto")]);
46
48
  const codexAppServerServiceTierSchema = z.preprocess((value) => value === null ? null : normalizeCodexServiceTier(value), z.string().trim().min(1).nullable().optional()).optional();
47
49
  const codexAppServerExperimentalSchema = z.object({ sandboxExecServer: z.boolean().optional() }).strict();
50
+ const codexAppServerRemoteWorkspaceRootSchema = z.string().trim().min(1);
51
+ const codexAppServerNetworkProxyDomainPermissionSchema = z.enum(["allow", "deny"]);
52
+ const codexAppServerNetworkProxyUnixSocketPermissionSchema = z.enum(["allow", "none"]);
53
+ const codexAppServerNetworkProxySchema = z.object({
54
+ enabled: z.boolean().optional(),
55
+ profileName: z.string().trim().min(1).optional(),
56
+ baseProfile: z.enum(["read-only", "workspace"]).optional(),
57
+ mode: z.enum(["limited", "full"]).optional(),
58
+ domains: z.record(z.string(), codexAppServerNetworkProxyDomainPermissionSchema).optional(),
59
+ unixSockets: z.record(z.string(), codexAppServerNetworkProxyUnixSocketPermissionSchema).optional(),
60
+ proxyUrl: z.string().trim().min(1).optional(),
61
+ socksUrl: z.string().trim().min(1).optional(),
62
+ enableSocks5: z.boolean().optional(),
63
+ enableSocks5Udp: z.boolean().optional(),
64
+ allowUpstreamProxy: z.boolean().optional(),
65
+ allowLocalBinding: z.boolean().optional(),
66
+ dangerouslyAllowNonLoopbackProxy: z.boolean().optional(),
67
+ dangerouslyAllowAllUnixSockets: z.boolean().optional()
68
+ }).strict();
48
69
  const codexPluginEntryConfigSchema = z.object({
49
70
  enabled: z.boolean().optional(),
50
71
  marketplaceName: z.literal(CODEX_PLUGINS_MARKETPLACE_NAME).optional(),
51
72
  pluginName: z.string().trim().min(1).optional(),
52
- allow_destructive_actions: z.boolean().optional()
73
+ allow_destructive_actions: codexPluginDestructivePolicySchema.optional()
53
74
  }).strict();
54
75
  const codexPluginsConfigSchema = z.object({
55
76
  enabled: z.boolean().optional(),
56
- allow_destructive_actions: z.boolean().optional(),
77
+ allow_destructive_actions: codexPluginDestructivePolicySchema.optional(),
57
78
  plugins: z.record(z.string(), codexPluginEntryConfigSchema).optional()
58
79
  }).strict();
59
80
  const codexPluginConfigSchema = z.object({
@@ -83,6 +104,7 @@ const codexPluginConfigSchema = z.object({
83
104
  authToken: z.string().optional(),
84
105
  headers: z.record(z.string(), z.string()).optional(),
85
106
  clearEnv: z.array(z.string()).optional(),
107
+ remoteWorkspaceRoot: codexAppServerRemoteWorkspaceRootSchema.optional(),
86
108
  codeModeOnly: z.boolean().optional(),
87
109
  requestTimeoutMs: z.number().positive().optional(),
88
110
  turnCompletionIdleTimeoutMs: z.number().positive().optional(),
@@ -91,6 +113,7 @@ const codexPluginConfigSchema = z.object({
91
113
  sandbox: codexAppServerSandboxSchema.optional(),
92
114
  approvalsReviewer: codexAppServerApprovalsReviewerSchema.optional(),
93
115
  serviceTier: codexAppServerServiceTierSchema,
116
+ networkProxy: codexAppServerNetworkProxySchema.optional(),
94
117
  defaultWorkspaceDir: z.string().optional(),
95
118
  experimental: codexAppServerExperimentalSchema.optional()
96
119
  }).strict().optional()
@@ -120,21 +143,35 @@ function resolveCodexPluginsPolicy(pluginConfig) {
120
143
  const config = readCodexPluginConfig(pluginConfig).codexPlugins;
121
144
  const configured = config !== void 0;
122
145
  const enabled = config?.enabled === true;
123
- const allowDestructiveActions = config?.allow_destructive_actions ?? true;
146
+ const destructivePolicy = resolveCodexPluginDestructivePolicy(config?.allow_destructive_actions ?? true);
147
+ const pluginPolicies = Object.entries(config?.plugins ?? {}).flatMap(([configKey, entry]) => {
148
+ if (entry.marketplaceName !== "openai-curated" || !entry.pluginName) return [];
149
+ const entryDestructivePolicy = resolveCodexPluginDestructivePolicy(entry.allow_destructive_actions ?? config?.allow_destructive_actions ?? true);
150
+ return [{
151
+ configKey,
152
+ marketplaceName: CODEX_PLUGINS_MARKETPLACE_NAME,
153
+ pluginName: entry.pluginName,
154
+ enabled: enabled && entry.enabled !== false,
155
+ allowDestructiveActions: entryDestructivePolicy.allowDestructiveActions,
156
+ destructiveApprovalMode: entryDestructivePolicy.destructiveApprovalMode
157
+ }];
158
+ }).toSorted((left, right) => left.configKey.localeCompare(right.configKey));
124
159
  return {
125
160
  configured,
126
161
  enabled,
127
- allowDestructiveActions,
128
- pluginPolicies: Object.entries(config?.plugins ?? {}).flatMap(([configKey, entry]) => {
129
- if (entry.marketplaceName !== "openai-curated" || !entry.pluginName) return [];
130
- return [{
131
- configKey,
132
- marketplaceName: CODEX_PLUGINS_MARKETPLACE_NAME,
133
- pluginName: entry.pluginName,
134
- enabled: enabled && entry.enabled !== false,
135
- allowDestructiveActions: entry.allow_destructive_actions ?? allowDestructiveActions
136
- }];
137
- }).toSorted((left, right) => left.configKey.localeCompare(right.configKey))
162
+ allowDestructiveActions: destructivePolicy.allowDestructiveActions,
163
+ destructiveApprovalMode: destructivePolicy.destructiveApprovalMode,
164
+ pluginPolicies
165
+ };
166
+ }
167
+ function resolveCodexPluginDestructivePolicy(policy) {
168
+ if (policy === "auto") return {
169
+ allowDestructiveActions: true,
170
+ destructiveApprovalMode: "auto"
171
+ };
172
+ return {
173
+ allowDestructiveActions: policy,
174
+ destructiveApprovalMode: policy ? "allow" : "deny"
138
175
  };
139
176
  }
140
177
  function resolveCodexAppServerRuntimeOptions(params = {}) {
@@ -154,6 +191,12 @@ function resolveCodexAppServerRuntimeOptions(params = {}) {
154
191
  const clearEnv = normalizeStringList(config.clearEnv);
155
192
  const authToken = readNonEmptyString(config.authToken);
156
193
  const url = readNonEmptyString(config.url);
194
+ const connectionClass = inferCodexAppServerConnectionClass({
195
+ transport,
196
+ url
197
+ });
198
+ const remoteAppsSubstrate = "preconfigured";
199
+ const remoteWorkspaceRoot = normalizeRemoteWorkspaceRoot(config.remoteWorkspaceRoot);
157
200
  const execMode = resolveEffectiveOpenClawExecModeForCodexAppServer({
158
201
  execMode: params.execMode,
159
202
  execPolicy: params.execPolicy
@@ -205,7 +248,13 @@ function resolveCodexAppServerRuntimeOptions(params = {}) {
205
248
  } : void 0;
206
249
  const policyMode = ignoreLegacyYoloPolicyMode ? normalizedPolicyMode : explicitPolicyMode ?? normalizedPolicyMode ?? defaultPolicy?.mode ?? "yolo";
207
250
  const serviceTier = normalizeCodexServiceTier(config.serviceTier);
251
+ const resolvedSandbox = forcedPolicy?.sandbox ?? configuredSandbox ?? defaultPolicy?.sandbox ?? (policyMode === "guardian" ? "workspace-write" : "danger-full-access");
208
252
  if (transport === "websocket" && !url) throw new Error("plugins.entries.codex.config.appServer.url is required when appServer.transport is websocket");
253
+ assertCodexAppServerConnectionClassConfig({
254
+ connectionClass,
255
+ authToken,
256
+ headers
257
+ });
209
258
  const configApprovalPolicy = resolveApprovalPolicy(config.approvalPolicy);
210
259
  const envApprovalPolicy = resolveApprovalPolicy(env.OPENCLAW_CODEX_APP_SERVER_APPROVAL_POLICY);
211
260
  const approvalPolicy = configApprovalPolicy ?? envApprovalPolicy ?? defaultPolicy?.approvalPolicy ?? (policyMode === "guardian" ? "on-request" : "never");
@@ -225,15 +274,19 @@ function resolveCodexAppServerRuntimeOptions(params = {}) {
225
274
  headers,
226
275
  ...transport === "stdio" && clearEnv.length > 0 ? { clearEnv } : {}
227
276
  },
277
+ connectionClass,
278
+ remoteAppsSubstrate,
279
+ ...remoteWorkspaceRoot ? { remoteWorkspaceRoot } : {},
228
280
  codeModeOnly: config.codeModeOnly === true,
229
281
  requestTimeoutMs: normalizePositiveNumber(config.requestTimeoutMs, 6e4),
230
282
  turnCompletionIdleTimeoutMs: normalizePositiveNumber(config.turnCompletionIdleTimeoutMs, 6e4),
231
283
  ...config.postToolRawAssistantCompletionIdleTimeoutMs !== void 0 ? { postToolRawAssistantCompletionIdleTimeoutMs: normalizePositiveNumber(config.postToolRawAssistantCompletionIdleTimeoutMs, 6e4) } : {},
232
284
  approvalPolicy: forcedPolicy?.approvalPolicy ?? approvalPolicy,
233
285
  approvalPolicySource,
234
- sandbox: forcedPolicy?.sandbox ?? configuredSandbox ?? defaultPolicy?.sandbox ?? (policyMode === "guardian" ? "workspace-write" : "danger-full-access"),
286
+ sandbox: resolvedSandbox,
235
287
  approvalsReviewer: forcedPolicy?.approvalsReviewer ?? explicitApprovalsReviewer ?? defaultPolicy?.approvalsReviewer ?? (policyMode === "guardian" ? "auto_review" : "user"),
236
- ...serviceTier ? { serviceTier } : {}
288
+ ...serviceTier ? { serviceTier } : {},
289
+ ...resolveCodexAppServerNetworkProxy(config.networkProxy, resolvedSandbox)
237
290
  };
238
291
  }
239
292
  function isCodexAppServerApprovalPolicyAllowedByRequirements(policy, params = {}) {
@@ -333,6 +386,65 @@ function codexSandboxPolicyForTurn(mode, cwd) {
333
386
  excludeSlashTmp: false
334
387
  };
335
388
  }
389
+ function resolveCodexAppServerNetworkProxy(config, sandbox) {
390
+ if (config?.enabled !== true) return {};
391
+ const fileSystemMode = config.baseProfile === "read-only" || !config.baseProfile && sandbox === "read-only" ? "read" : "write";
392
+ const networkConfig = removeUndefinedJsonFields({
393
+ enabled: true,
394
+ mode: config.mode,
395
+ domains: normalizeNetworkProxyPermissionMap(config.domains),
396
+ unix_sockets: normalizeNetworkProxyPermissionMap(config.unixSockets),
397
+ proxy_url: readNonEmptyString(config.proxyUrl),
398
+ socks_url: readNonEmptyString(config.socksUrl),
399
+ enable_socks5: config.enableSocks5,
400
+ enable_socks5_udp: config.enableSocks5Udp,
401
+ allow_upstream_proxy: config.allowUpstreamProxy,
402
+ allow_local_binding: config.allowLocalBinding,
403
+ dangerously_allow_non_loopback_proxy: config.dangerouslyAllowNonLoopbackProxy,
404
+ dangerously_allow_all_unix_sockets: config.dangerouslyAllowAllUnixSockets
405
+ });
406
+ const profile = {
407
+ filesystem: {
408
+ ":minimal": "read",
409
+ ":project_roots": { ".": fileSystemMode }
410
+ },
411
+ network: networkConfig
412
+ };
413
+ const profileName = resolveNetworkProxyPermissionProfileName(config, profile);
414
+ const configPatch = {
415
+ "features.network_proxy.enabled": true,
416
+ default_permissions: profileName,
417
+ permissions: { [profileName]: profile }
418
+ };
419
+ return { networkProxy: {
420
+ profileName,
421
+ configFingerprint: fingerprintCodexAppServerNetworkProxyConfigPatch(configPatch),
422
+ configPatch
423
+ } };
424
+ }
425
+ function resolveNetworkProxyPermissionProfileName(config, profile) {
426
+ const explicitProfileName = readNonEmptyString(config.profileName);
427
+ if (explicitProfileName) return explicitProfileName;
428
+ return `${DEFAULT_CODEX_APP_SERVER_NETWORK_PROXY_PROFILE_PREFIX}-${createHash("sha256").update(stableStringifyJson({
429
+ version: 1,
430
+ profile
431
+ })).digest("hex").slice(0, 16)}`;
432
+ }
433
+ function fingerprintCodexAppServerNetworkProxyConfigPatch(configPatch) {
434
+ return createHash("sha256").update(stableStringifyJson(configPatch)).digest("hex");
435
+ }
436
+ function normalizeNetworkProxyPermissionMap(value) {
437
+ const entries = Object.entries(value ?? {}).map(([key, permission]) => [key.trim(), permission]).filter(([key]) => key.length > 0);
438
+ return entries.length > 0 ? Object.fromEntries(entries) : void 0;
439
+ }
440
+ function removeUndefinedJsonFields(value) {
441
+ return Object.fromEntries(Object.entries(value).filter((entry) => entry[1] !== void 0));
442
+ }
443
+ function stableStringifyJson(value) {
444
+ if (Array.isArray(value)) return `[${value.map((item) => stableStringifyJson(item)).join(",")}]`;
445
+ if (value && typeof value === "object") return `{${Object.entries(value).toSorted(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${stableStringifyJson(item)}`).join(",")}}`;
446
+ return JSON.stringify(value);
447
+ }
336
448
  function withMcpElicitationsApprovalPolicy(policy) {
337
449
  if (typeof policy !== "string") return { granular: {
338
450
  ...policy.granular,
@@ -352,6 +464,34 @@ function withMcpElicitationsApprovalPolicy(policy) {
352
464
  function resolveTransport(value) {
353
465
  return value === "websocket" ? "websocket" : "stdio";
354
466
  }
467
+ function normalizeRemoteWorkspaceRoot(value) {
468
+ return readNonEmptyString(value);
469
+ }
470
+ function inferCodexAppServerConnectionClass(params) {
471
+ if (params.transport !== "websocket") return "local-loopback";
472
+ return params.url && isLoopbackWebSocketUrl(params.url) ? "local-loopback" : "remote";
473
+ }
474
+ function assertCodexAppServerConnectionClassConfig(params) {
475
+ if (params.connectionClass === "remote" && !hasIdentityBearingWebSocketAuth({
476
+ authToken: params.authToken,
477
+ headers: params.headers
478
+ })) throw new Error("remote Codex app-server WebSocket URLs require appServer.authToken or an Authorization header");
479
+ }
480
+ function isLoopbackWebSocketUrl(value) {
481
+ let parsed;
482
+ try {
483
+ parsed = new URL(value);
484
+ } catch {
485
+ return false;
486
+ }
487
+ if (parsed.protocol !== "ws:" && parsed.protocol !== "wss:") return false;
488
+ const host = parsed.hostname.toLowerCase();
489
+ return host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "[::1]" || host.startsWith("127.");
490
+ }
491
+ function hasIdentityBearingWebSocketAuth(params) {
492
+ if (readNonEmptyString(params.authToken)) return true;
493
+ return Object.entries(params.headers).some(([key, value]) => key.trim().toLowerCase() === "authorization" && Boolean(readNonEmptyString(value)));
494
+ }
355
495
  function resolvePolicyMode(value) {
356
496
  return value === "guardian" || value === "yolo" ? value : void 0;
357
497
  }