@openclaw/codex 2026.7.2-beta.5 → 2026.7.33

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 (66) hide show
  1. package/README.md +3 -27
  2. package/dist/{command-formatters-ico4ZFnk.js → .setup/app-server-policy-C_qTMEMy.mjs} +51 -9
  3. package/dist/{attempt-notifications-CMR2_fmR.js → .setup/attempt-notifications-F8krwWL4.mjs} +6 -3
  4. package/dist/{command-handlers-CRmnwI2N.js → .setup/command-handlers-DSRFfor4.mjs} +1156 -1319
  5. package/dist/.setup/command-rpc-BvYsfQ7G.mjs +786 -0
  6. package/dist/{compact-dEN49UH6.js → .setup/compact-BNgh7I4t.mjs} +10 -40
  7. package/dist/.setup/computer-use-C3QkmSO3.mjs +377 -0
  8. package/dist/.setup/config-CYEDnLJ2.mjs +1138 -0
  9. package/dist/{conversation-binding-data-BHRpYbX3.js → .setup/conversation-binding-data-CrRxtDBu.mjs} +1 -1
  10. package/dist/{bounded-turn-FEbUXoYT.js → .setup/media-understanding-provider-EbJCyDqe.mjs} +193 -92
  11. package/dist/{models-BA01NEez.js → .setup/models-C_aZk03A.mjs} +11 -6
  12. package/dist/.setup/notification-correlation-iYs4WieS.mjs +35 -0
  13. package/dist/.setup/plugin-app-cache-key-DR8jV9oS.mjs +99 -0
  14. package/dist/.setup/protocol-2POPqAY4.mjs +13 -0
  15. package/dist/{protocol-validators-Dm4eXZmt.js → .setup/protocol-validators-dZQ-UTOa.mjs} +111 -334
  16. package/dist/{rate-limits-S_PXs0ul.js → .setup/provider-DGxDs6g8.mjs} +269 -13
  17. package/dist/{dynamic-tools-LIt9ojep.js → .setup/provider-capabilities-DS2N_zc1.mjs} +5465 -3399
  18. package/dist/.setup/request-DFR0JyoV.mjs +36 -0
  19. package/dist/.setup/run-attempt-C7xEKFVB.mjs +8180 -0
  20. package/dist/{sandbox-guard-D1Wky__S.js → .setup/sandbox-guard-DA2TQfZW.mjs} +1 -10
  21. package/dist/.setup/session-binding-DuihlMJc.mjs +628 -0
  22. package/dist/.setup/shared-client-B2KmLPRw.mjs +1854 -0
  23. package/dist/{side-question-CO12sHxo.js → .setup/side-question-Cv6JXWCS.mjs} +84 -159
  24. package/dist/{thread-lifecycle-DRg_FdzC.js → .setup/thread-lifecycle-u6CZdOOH.mjs} +1159 -1799
  25. package/dist/{web-search-provider.runtime-CaQMYDbp.js → .setup/web-search-provider.runtime-Ce2zOHxW.mjs} +3 -3
  26. package/dist/doctor-contract-api.js +122 -88
  27. package/dist/harness.js +20 -85
  28. package/dist/index.js +381 -1537
  29. package/dist/media-understanding-provider.js +1 -173
  30. package/dist/prompt-overlay.js +15 -0
  31. package/dist/provider-catalog.js +79 -0
  32. package/dist/provider-discovery.js +34 -0
  33. package/dist/provider.js +2 -0
  34. package/dist/web-search-contract-api.js +1 -1
  35. package/openclaw.plugin.json +178 -221
  36. package/package.json +8 -10
  37. package/dist/app-server-policy-BmDgseo_.js +0 -49
  38. package/dist/attempt-client-cleanup-Ia52yRWc.js +0 -127
  39. package/dist/auth-binding-B4FfbcCg.js +0 -62
  40. package/dist/capabilities-BHRSI6Cn.js +0 -36
  41. package/dist/cli-metadata.js +0 -20
  42. package/dist/computer-use-BjGylO-E.js +0 -695
  43. package/dist/conversation-control-DE7d9DOj.js +0 -287
  44. package/dist/event-projector-assistant-message-DTgnPPVF.js +0 -101
  45. package/dist/event-projector-usage-tvgb1NCX.js +0 -69
  46. package/dist/incognito-session-ET_ufDH-.js +0 -2
  47. package/dist/notification-correlation-Bj_Ak_jI.js +0 -67
  48. package/dist/plugin-app-cache-key-DSXX-rXO.js +0 -315
  49. package/dist/realtime-voice-api-BPcA1uN9.js +0 -494
  50. package/dist/realtime-voice-api.js +0 -2
  51. package/dist/request-CXpPennK.js +0 -157
  52. package/dist/run-attempt-C5GTPJOE.js +0 -11935
  53. package/dist/runtime-artifact-C2ITXdhM.js +0 -488
  54. package/dist/session-binding-DlVQ-Pxs.js +0 -2161
  55. package/dist/session-catalog-CP2oCcEb.js +0 -2444
  56. package/dist/session-cli-CqZ0Fp2a.js +0 -175
  57. package/dist/session-upstream-marker-QE-m5QFG.js +0 -82
  58. package/dist/settled-turn-finalizer-CA_2QXIE.js +0 -303
  59. package/dist/shared-client-BVKE40c-.js +0 -2952
  60. package/dist/transcript-mirror-uKA-A4tB.js +0 -550
  61. package/dist/transport-stdio-DXgGZ7Ib.js +0 -88
  62. package/dist/upstream-session-fork-_Vrz4WJr.js +0 -320
  63. package/dist/usage-UpVbdX5G.js +0 -25
  64. /package/dist/{rolldown-runtime-8H4AJuhK.js → .setup/rolldown-runtime-8H4AJuhK.mjs} +0 -0
  65. /package/dist/{session-binding-meta-B7aEMU7g.js → .setup/session-binding-meta-B7aEMU7g.mjs} +0 -0
  66. /package/dist/{web-search-provider.shared-BrZmlqyR.js → .setup/web-search-provider.shared-BrZmlqyR.mjs} +0 -0
@@ -1,2161 +0,0 @@
1
- import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
- import { n as CODEX_APP_SERVER_BINDING_NAMESPACE, t as CODEX_APP_SERVER_BINDING_MAX_ENTRIES } from "./session-binding-meta-B7aEMU7g.js";
3
- import path from "node:path";
4
- import { resolvePositiveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
5
- import { AgentHarnessSessionSupersededError, embeddedAgentLog } from "openclaw/plugin-sdk/agent-harness-runtime";
6
- import { createHash, createHmac, randomBytes, randomUUID } from "node:crypto";
7
- import { ensureAuthProfileStore, resolveDefaultAgentDir, resolveProviderIdForAuth, resolveSessionAgentIds as resolveSessionAgentIds$1 } from "openclaw/plugin-sdk/agent-runtime";
8
- import { readFileSync } from "node:fs";
9
- import { homedir, hostname } from "node:os";
10
- import { resolveExecApprovalsFromFile } from "openclaw/plugin-sdk/exec-approvals-runtime";
11
- import { normalizeAgentId } from "openclaw/plugin-sdk/routing";
12
- import { buildSecretInputSchema, normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-input";
13
- import { normalizeTrimmedStringList } from "openclaw/plugin-sdk/string-coerce-runtime";
14
- import { detectWindowsSpawnCommandInlineArgs } from "openclaw/plugin-sdk/windows-spawn";
15
- import { z } from "zod";
16
- import { parse } from "smol-toml";
17
- import { AsyncLocalStorage } from "node:async_hooks";
18
- import { getSessionEntry, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
19
- //#region extensions/codex/src/app-server/config-contracts.ts
20
- const CODEX_PLUGINS_MARKETPLACE_NAME = "openai-curated";
21
- const CODEX_PLUGINS_WORKSPACE_MARKETPLACE_NAME = "workspace-directory";
22
- //#endregion
23
- //#region extensions/codex/src/app-server/config-utils.ts
24
- const START_OPTIONS_KEY_SECRET_SYMBOL = Symbol.for("openclaw.codexAppServerStartOptionsKeySecret");
25
- const START_OPTIONS_KEY_SECRET = getStartOptionsKeySecret();
26
- const PLAIN_DECIMAL_NUMBER_RE = /^[+-]?(?:(?:\d+\.?\d*)|(?:\.\d+))$/;
27
- function readRecord(value) {
28
- return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
29
- }
30
- function normalizeCodexServiceTier(value) {
31
- if (typeof value !== "string") return;
32
- const trimmed = value.trim();
33
- if (!trimmed) return;
34
- const normalized = trimmed.toLowerCase();
35
- if (normalized === "fast" || normalized === "priority") return "priority";
36
- if (normalized === "flex") return "flex";
37
- return trimmed;
38
- }
39
- function isCodexFastServiceTier(value) {
40
- return normalizeCodexServiceTier(value) === "priority";
41
- }
42
- function normalizePositiveNumber(value, fallback) {
43
- return resolvePositiveTimerTimeoutMs(value, fallback);
44
- }
45
- function normalizeHeaders(value) {
46
- if (!value || typeof value !== "object" || Array.isArray(value)) return {};
47
- return Object.fromEntries(Object.entries(value).map(([key, child]) => [key.trim(), normalizeCodexAppServerSecretInput({
48
- value: child,
49
- path: `plugins.entries.codex.config.appServer.headers.${key}`
50
- })]).filter((entry) => Boolean(entry[0] && entry[1])));
51
- }
52
- function normalizeCodexAppServerSecretInput(params) {
53
- return normalizeResolvedSecretInputString(params);
54
- }
55
- function normalizeStringList(value) {
56
- return normalizeTrimmedStringList(value);
57
- }
58
- function readBooleanEnv(value) {
59
- if (value === void 0) return;
60
- const normalized = value.trim().toLowerCase();
61
- if ([
62
- "1",
63
- "true",
64
- "yes",
65
- "on"
66
- ].includes(normalized)) return true;
67
- if ([
68
- "0",
69
- "false",
70
- "no",
71
- "off"
72
- ].includes(normalized)) return false;
73
- }
74
- function readExecSecurity(value) {
75
- return value === "deny" || value === "allowlist" || value === "full" ? value : void 0;
76
- }
77
- function readExecAsk(value) {
78
- return value === "off" || value === "on-miss" || value === "always" ? value : void 0;
79
- }
80
- function readNumberEnv(value) {
81
- const trimmed = value?.trim();
82
- if (!trimmed || !PLAIN_DECIMAL_NUMBER_RE.test(trimmed)) return;
83
- const parsed = Number(trimmed);
84
- return Number.isFinite(parsed) ? parsed : void 0;
85
- }
86
- function resolveArgs(configArgs, envArgs) {
87
- if (Array.isArray(configArgs)) return configArgs.map((entry) => readNonEmptyString(entry)).filter((entry) => entry !== void 0);
88
- if (typeof configArgs === "string") return splitShellWords(configArgs);
89
- return splitShellWords(envArgs ?? "");
90
- }
91
- function readNonEmptyString(value) {
92
- if (typeof value !== "string") return;
93
- return value.trim() || void 0;
94
- }
95
- function hashSecretForKey(value, label) {
96
- if (!value) return null;
97
- return createHmac("sha256", START_OPTIONS_KEY_SECRET).update(label).update("\0").update(value).digest("hex");
98
- }
99
- function getStartOptionsKeySecret() {
100
- const globalState = globalThis;
101
- globalState[START_OPTIONS_KEY_SECRET_SYMBOL] ??= randomBytes(32);
102
- return globalState[START_OPTIONS_KEY_SECRET_SYMBOL];
103
- }
104
- function splitShellWords(value) {
105
- const words = [];
106
- let current = "";
107
- let quote = null;
108
- for (const char of value) {
109
- if (quote) {
110
- if (char === quote) quote = null;
111
- else current += char;
112
- continue;
113
- }
114
- if (char === "\"" || char === "'") {
115
- quote = char;
116
- continue;
117
- }
118
- if (/\s/.test(char)) {
119
- if (current) {
120
- words.push(current);
121
- current = "";
122
- }
123
- continue;
124
- }
125
- current += char;
126
- }
127
- if (current) words.push(current);
128
- return words;
129
- }
130
- //#endregion
131
- //#region extensions/codex/src/app-server/config-exec-policy.ts
132
- function selectForcedPromptingSandbox(params) {
133
- if (params.configuredSandbox === "read-only" || params.defaultSandbox === "read-only") return "read-only";
134
- return params.defaultSandbox ?? "workspace-write";
135
- }
136
- function selectForcedDangerFullAccessSandbox(params) {
137
- if (params.configuredSandbox === "read-only") return "read-only";
138
- if (params.defaultPolicy?.dangerFullAccessAllowed === false) {
139
- if (params.openClawSandboxActive) return params.defaultPolicy.sandbox ?? "workspace-write";
140
- throw new Error("legacy full exec security with ask requires Codex app-server danger-full-access");
141
- }
142
- return "danger-full-access";
143
- }
144
- function selectGuardianSandbox(allowedSandboxModes) {
145
- if (allowedSandboxModes === void 0 || allowedSandboxModes.has("workspace-write")) return "workspace-write";
146
- if (allowedSandboxModes.has("read-only")) return "read-only";
147
- if (allowedSandboxModes.has("danger-full-access")) return "danger-full-access";
148
- return "workspace-write";
149
- }
150
- function resolveApprovalPolicy(value) {
151
- if (value === "on-failure") return "on-request";
152
- return value === "on-request" || value === "untrusted" || value === "never" ? value : void 0;
153
- }
154
- function resolveSandbox(value) {
155
- return value === "read-only" || value === "workspace-write" || value === "danger-full-access" ? value : void 0;
156
- }
157
- function resolveApprovalsReviewer(value) {
158
- return value === "auto_review" || value === "guardian_subagent" || value === "user" ? value : void 0;
159
- }
160
- function resolveOpenClawExecPolicyFromConfig(params) {
161
- const root = readRecord(params.config);
162
- const globalExec = readRecord(readRecord(root?.tools)?.exec);
163
- const globalPolicy = applyOpenClawExecPolicyLayer(createDefaultOpenClawExecPolicy(), globalExec);
164
- const agentId = params.agentId?.trim();
165
- if (!agentId) return globalPolicy;
166
- const agents = readRecord(root?.agents);
167
- const agentList = Array.isArray(agents?.list) ? agents.list : [];
168
- const normalizedAgentId = normalizeAgentId(agentId);
169
- return applyOpenClawExecPolicyLayer(globalPolicy, readRecord(readRecord(readRecord(agentList.find((entry) => {
170
- const id = readRecord(entry)?.id;
171
- return typeof id === "string" && normalizeAgentId(id) === normalizedAgentId;
172
- }))?.tools)?.exec));
173
- }
174
- function resolveOpenClawExecPolicyForCodexAppServer(params) {
175
- const overridePolicy = applyOpenClawExecPolicyLayer(resolveOpenClawExecPolicyFromConfig({
176
- config: params.config,
177
- agentId: params.agentId
178
- }), params.execOverrides);
179
- return applyOpenClawExecApprovalFloors(overridePolicy, resolveOpenClawExecApprovalFloorsForCodexAppServer({
180
- approvals: params.approvals,
181
- agentId: params.agentId,
182
- policy: overridePolicy
183
- }));
184
- }
185
- function resolveEffectiveOpenClawExecModeForCodexAppServer(params) {
186
- if (params.execPolicy?.touched === true) return params.execPolicy.mode;
187
- return params.execMode;
188
- }
189
- function resolveCodexPolicyModeForOpenClawExecMode(mode) {
190
- if (!mode || mode === "full") return;
191
- return "guardian";
192
- }
193
- function assertCodexAppServerAllowedForOpenClawExecMode(mode) {
194
- if (mode === "deny" || mode === "allowlist") throw new Error(`Codex app-server local execution is not available when tools.exec.mode=${mode}`);
195
- }
196
- function createDefaultOpenClawExecPolicy() {
197
- return {
198
- security: "full",
199
- ask: "off",
200
- touched: false
201
- };
202
- }
203
- function applyOpenClawExecPolicyLayer(base, exec) {
204
- if (!exec) return base;
205
- const mode = readExecMode(exec.mode);
206
- if (mode !== void 0) return {
207
- ...resolveOpenClawExecPolicyForMode(mode),
208
- touched: true
209
- };
210
- const security = readExecSecurity(exec.security);
211
- const ask = readExecAsk(exec.ask);
212
- if (security === void 0 && ask === void 0) return base;
213
- const nextSecurity = security ?? base.security;
214
- const nextAsk = ask ?? base.ask;
215
- return {
216
- mode: resolveOpenClawExecModeFromPolicy({
217
- security: nextSecurity,
218
- ask: nextAsk
219
- }),
220
- security: nextSecurity,
221
- ask: nextAsk,
222
- touched: true
223
- };
224
- }
225
- function resolveOpenClawExecApprovalFloorsForCodexAppServer(params) {
226
- if (!params.approvals) return;
227
- return resolveExecApprovalsFromFile({
228
- file: params.approvals,
229
- agentId: params.agentId,
230
- overrides: {
231
- security: params.policy.security,
232
- ask: params.policy.ask
233
- }
234
- }).agent;
235
- }
236
- function applyOpenClawExecApprovalFloors(base, approvalFloors) {
237
- if (!approvalFloors) return base;
238
- const nextSecurity = approvalFloors.security ? minOpenClawExecSecurity(base.security, approvalFloors.security) : base.security;
239
- const nextAsk = approvalFloors.ask ? maxOpenClawExecAsk(base.ask, approvalFloors.ask) : base.ask;
240
- if (nextSecurity === base.security && nextAsk === base.ask) return base;
241
- return {
242
- mode: resolveOpenClawExecModeFromPolicy({
243
- security: nextSecurity,
244
- ask: nextAsk
245
- }),
246
- security: nextSecurity,
247
- ask: nextAsk,
248
- touched: true
249
- };
250
- }
251
- function resolveOpenClawExecPolicyForMode(mode) {
252
- switch (mode) {
253
- case "deny": return {
254
- mode,
255
- security: "deny",
256
- ask: "off"
257
- };
258
- case "allowlist": return {
259
- mode,
260
- security: "allowlist",
261
- ask: "off"
262
- };
263
- case "ask":
264
- case "auto": return {
265
- mode,
266
- security: "allowlist",
267
- ask: "on-miss"
268
- };
269
- case "full": return {
270
- mode,
271
- security: "full",
272
- ask: "off"
273
- };
274
- }
275
- return mode;
276
- }
277
- function resolveOpenClawExecModeFromPolicy(params) {
278
- if (params.security === "deny") return "deny";
279
- if (params.security === "allowlist" && params.ask === "off") return "allowlist";
280
- if (params.security === "full" && params.ask !== "always") return "full";
281
- return "ask";
282
- }
283
- function minOpenClawExecSecurity(left, right) {
284
- const order = {
285
- deny: 0,
286
- allowlist: 1,
287
- full: 2
288
- };
289
- return order[left] <= order[right] ? left : right;
290
- }
291
- function maxOpenClawExecAsk(left, right) {
292
- const order = {
293
- off: 0,
294
- "on-miss": 1,
295
- always: 2
296
- };
297
- return order[left] >= order[right] ? left : right;
298
- }
299
- function readExecMode(value) {
300
- return value === "deny" || value === "allowlist" || value === "ask" || value === "auto" || value === "full" ? value : void 0;
301
- }
302
- //#endregion
303
- //#region extensions/codex/src/app-server/session-discovery-config.ts
304
- const codexSessionCatalogConfigSchema = z.object({ enabled: z.boolean().optional() }).strict();
305
- const codexDiscoveryConfigSchema = z.object({
306
- enabled: z.boolean().optional(),
307
- timeoutMs: z.number().positive().optional()
308
- }).strict();
309
- //#endregion
310
- //#region extensions/codex/src/app-server/config-parsing.ts
311
- const DEFAULT_CODEX_COMPUTER_USE_PLUGIN_NAME = "computer-use";
312
- const DEFAULT_CODEX_COMPUTER_USE_MARKETPLACE_DISCOVERY_TIMEOUT_MS = 6e4;
313
- const DEFAULT_CODEX_COMPUTER_USE_LIVE_TEST_TIMEOUT_MS = 6e4;
314
- const DEFAULT_CODEX_COMPUTER_USE_TOOL_CALL_TIMEOUT_MS = 6e4;
315
- const DEFAULT_CODEX_APP_SERVER_NETWORK_PROXY_PROFILE_PREFIX = "openclaw-network";
316
- const codexAppServerTransportSchema = z.enum([
317
- "stdio",
318
- "websocket",
319
- "unix"
320
- ]);
321
- const codexAppServerHomeScopeSchema = z.enum(["agent", "user"]);
322
- const SecretInputSchema = buildSecretInputSchema();
323
- const codexAppServerPolicyModeSchema = z.enum(["yolo", "guardian"]);
324
- const codexAppServerApprovalPolicySchema = z.preprocess((value) => value === "on-failure" ? "on-request" : value, z.enum([
325
- "never",
326
- "on-request",
327
- "untrusted"
328
- ]));
329
- const codexAppServerSandboxSchema = z.enum([
330
- "read-only",
331
- "workspace-write",
332
- "danger-full-access"
333
- ]);
334
- const codexAppServerApprovalsReviewerSchema = z.enum([
335
- "user",
336
- "auto_review",
337
- "guardian_subagent"
338
- ]);
339
- const codexDynamicToolsLoadingSchema = z.enum(["searchable", "direct"]);
340
- const codexComputerUseHealthIntervalSchema = z.union([
341
- z.literal(30),
342
- z.literal(60),
343
- z.literal(120),
344
- z.literal(240)
345
- ]);
346
- const codexComputerUsePluginCacheModeSchema = z.enum(["shared", "independent"]);
347
- const codexPluginDestructivePolicySchema = z.union([
348
- z.boolean(),
349
- z.literal("auto"),
350
- z.literal("ask")
351
- ]);
352
- const codexAppServerServiceTierSchema = z.preprocess((value) => value === null ? null : normalizeCodexServiceTier(value), z.string().trim().min(1).nullable().optional()).optional();
353
- const codexAppServerExperimentalSchema = z.object({ sandboxExecServer: z.boolean().optional() }).strict();
354
- const codexAppServerRemoteWorkspaceRootSchema = z.string().trim().min(1);
355
- const codexAppServerNetworkProxyDomainPermissionSchema = z.enum(["allow", "deny"]);
356
- const codexAppServerNetworkProxyUnixSocketPermissionSchema = z.enum(["allow", "none"]);
357
- const codexAppServerNetworkProxySchema = z.object({
358
- enabled: z.boolean().optional(),
359
- profileName: z.string().trim().min(1).optional(),
360
- baseProfile: z.enum(["read-only", "workspace"]).optional(),
361
- mode: z.enum(["limited", "full"]).optional(),
362
- domains: z.record(z.string(), codexAppServerNetworkProxyDomainPermissionSchema).optional(),
363
- unixSockets: z.record(z.string(), codexAppServerNetworkProxyUnixSocketPermissionSchema).optional(),
364
- proxyUrl: z.string().trim().min(1).optional(),
365
- socksUrl: z.string().trim().min(1).optional(),
366
- enableSocks5: z.boolean().optional(),
367
- enableSocks5Udp: z.boolean().optional(),
368
- allowUpstreamProxy: z.boolean().optional(),
369
- allowLocalBinding: z.boolean().optional(),
370
- dangerouslyAllowNonLoopbackProxy: z.boolean().optional(),
371
- dangerouslyAllowAllUnixSockets: z.boolean().optional()
372
- }).strict();
373
- const codexPluginEntryConfigSchema = z.object({
374
- enabled: z.boolean().optional(),
375
- marketplaceName: z.enum([CODEX_PLUGINS_MARKETPLACE_NAME, CODEX_PLUGINS_WORKSPACE_MARKETPLACE_NAME]).optional(),
376
- pluginName: z.string().trim().min(1).optional(),
377
- allow_destructive_actions: codexPluginDestructivePolicySchema.optional()
378
- }).strict();
379
- const codexPluginsConfigSchema = z.object({
380
- enabled: z.boolean().optional(),
381
- allow_all_plugins: z.boolean().optional(),
382
- allow_destructive_actions: codexPluginDestructivePolicySchema.optional(),
383
- plugins: z.record(z.string(), codexPluginEntryConfigSchema).optional()
384
- }).strict();
385
- const codexSupervisionEndpointSchema = z.union([z.object({
386
- id: z.string().optional(),
387
- label: z.string().optional(),
388
- transport: z.literal("stdio-proxy").optional(),
389
- command: z.string().optional(),
390
- args: z.array(z.string()).optional(),
391
- cwd: z.string().optional()
392
- }).strict(), z.object({
393
- id: z.string().optional(),
394
- label: z.string().optional(),
395
- transport: z.literal("websocket"),
396
- url: z.string(),
397
- authTokenEnv: z.string().optional()
398
- }).strict()]);
399
- const codexSupervisionConfigSchema = z.object({
400
- enabled: z.boolean().optional(),
401
- endpoints: z.array(codexSupervisionEndpointSchema).optional(),
402
- allowRawTranscripts: z.boolean().optional(),
403
- allowWriteControls: z.boolean().optional()
404
- }).strict();
405
- const codexPluginConfigSchema = z.object({
406
- codexDynamicToolsLoading: codexDynamicToolsLoadingSchema.optional(),
407
- codexDynamicToolsExclude: z.array(z.string()).optional(),
408
- sessionCatalog: codexSessionCatalogConfigSchema.optional(),
409
- discovery: codexDiscoveryConfigSchema.optional(),
410
- computerUse: z.object({
411
- enabled: z.boolean().optional(),
412
- autoInstall: z.boolean().optional(),
413
- marketplaceDiscoveryTimeoutMs: z.number().positive().optional(),
414
- liveTestTimeoutMs: z.number().positive().optional(),
415
- toolCallTimeoutMs: z.number().positive().optional(),
416
- healthCheckEnabled: z.boolean().optional(),
417
- healthCheckIntervalMinutes: codexComputerUseHealthIntervalSchema.optional(),
418
- pluginCacheMode: codexComputerUsePluginCacheModeSchema.optional(),
419
- strictReadiness: z.boolean().optional(),
420
- autoRepair: z.boolean().optional(),
421
- marketplaceSource: z.string().optional(),
422
- marketplacePath: z.string().optional(),
423
- marketplaceName: z.string().optional(),
424
- pluginName: z.string().optional(),
425
- mcpServerName: z.string().optional()
426
- }).strict().optional(),
427
- codexPlugins: z.unknown().optional(),
428
- supervision: codexSupervisionConfigSchema.optional(),
429
- appServer: z.object({
430
- mode: codexAppServerPolicyModeSchema.optional(),
431
- transport: codexAppServerTransportSchema.optional(),
432
- homeScope: codexAppServerHomeScopeSchema.optional(),
433
- command: z.string().optional(),
434
- args: z.union([z.array(z.string()), z.string()]).optional(),
435
- url: z.string().optional(),
436
- authToken: SecretInputSchema.optional(),
437
- headers: z.record(z.string(), SecretInputSchema).optional(),
438
- clearEnv: z.array(z.string()).optional(),
439
- remoteWorkspaceRoot: codexAppServerRemoteWorkspaceRootSchema.optional(),
440
- codeModeOnly: z.boolean().optional(),
441
- loopDetectionPreToolUseRelay: z.boolean().optional(),
442
- requestTimeoutMs: z.number().positive().optional(),
443
- turnCompletionIdleTimeoutMs: z.number().positive().optional(),
444
- turnAssistantCompletionIdleTimeoutMs: z.number().positive().optional(),
445
- postToolRawAssistantCompletionIdleTimeoutMs: z.number().positive().optional(),
446
- approvalPolicy: codexAppServerApprovalPolicySchema.optional(),
447
- sandbox: codexAppServerSandboxSchema.optional(),
448
- approvalsReviewer: codexAppServerApprovalsReviewerSchema.optional(),
449
- serviceTier: codexAppServerServiceTierSchema,
450
- networkProxy: codexAppServerNetworkProxySchema.optional(),
451
- defaultWorkspaceDir: z.string().optional(),
452
- experimental: codexAppServerExperimentalSchema.optional()
453
- }).strict().optional()
454
- }).strict();
455
- function readCodexPluginConfig(value) {
456
- const parsed = codexPluginConfigSchema.safeParse(value);
457
- if (!parsed.success) return {};
458
- const { codexPlugins: rawCodexPlugins, ...config } = parsed.data;
459
- const plugins = codexPluginsConfigSchema.safeParse(rawCodexPlugins);
460
- if (!plugins.success) return config;
461
- return {
462
- ...config,
463
- ...plugins.data ? { codexPlugins: plugins.data } : {}
464
- };
465
- }
466
- function isCodexSandboxExecServerEnabled(pluginConfig) {
467
- return readCodexPluginConfig(pluginConfig).appServer?.experimental?.sandboxExecServer === true;
468
- }
469
- function assertCodexAppServerCommandHasNoInlineArgs(params) {
470
- const inlineArgs = detectWindowsSpawnCommandInlineArgs(params.command);
471
- if (!inlineArgs) return;
472
- const sourceLabel = params.source === "env" ? "OPENCLAW_CODEX_APP_SERVER_BIN" : "plugins.entries.codex.config.appServer.command";
473
- const argsLabel = params.source === "env" ? "OPENCLAW_CODEX_APP_SERVER_ARGS" : "plugins.entries.codex.config.appServer.args";
474
- 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.`);
475
- }
476
- function resolveCodexPluginsPolicy(pluginConfig) {
477
- const config = readCodexPluginConfig(pluginConfig).codexPlugins;
478
- const configured = config !== void 0;
479
- const enabled = config?.enabled === true;
480
- const destructivePolicy = resolveCodexPluginDestructivePolicy(config?.allow_destructive_actions ?? true);
481
- const pluginPolicies = Object.entries(config?.plugins ?? {}).flatMap(([configKey, entry]) => {
482
- if (!isCodexPluginMarketplaceName(entry.marketplaceName) || !entry.pluginName) return [];
483
- const entryDestructivePolicy = resolveCodexPluginDestructivePolicy(entry.allow_destructive_actions ?? config?.allow_destructive_actions ?? true);
484
- return [{
485
- configKey,
486
- marketplaceName: entry.marketplaceName,
487
- pluginName: entry.pluginName,
488
- enabled: enabled && entry.enabled !== false,
489
- allowDestructiveActions: entryDestructivePolicy.allowDestructiveActions,
490
- destructiveApprovalMode: entryDestructivePolicy.destructiveApprovalMode
491
- }];
492
- }).toSorted((left, right) => left.configKey.localeCompare(right.configKey));
493
- return {
494
- configured,
495
- enabled,
496
- allowAllPlugins: enabled && config?.allow_all_plugins === true,
497
- allowDestructiveActions: destructivePolicy.allowDestructiveActions,
498
- destructiveApprovalMode: destructivePolicy.destructiveApprovalMode,
499
- pluginPolicies
500
- };
501
- }
502
- function isCodexPluginMarketplaceName(value) {
503
- return value === "openai-curated" || value === "workspace-directory";
504
- }
505
- function resolveCodexPluginDestructivePolicy(policy) {
506
- if (policy === "auto" || policy === "ask") return {
507
- allowDestructiveActions: true,
508
- destructiveApprovalMode: policy
509
- };
510
- return {
511
- allowDestructiveActions: policy,
512
- destructiveApprovalMode: policy ? "allow" : "deny"
513
- };
514
- }
515
- //#endregion
516
- //#region extensions/codex/src/app-server/config-requirements.ts
517
- const UNIX_CODEX_REQUIREMENTS_PATH = "/etc/codex/requirements.toml";
518
- const WINDOWS_CODEX_REQUIREMENTS_SUFFIX = "\\OpenAI\\Codex\\requirements.toml";
519
- function isCodexAppServerApprovalPolicyAllowedByRequirements(policy, params = {}) {
520
- const content = readCodexRequirementsToml(params);
521
- if (content === void 0) return true;
522
- const allowedApprovalPolicies = parseAllowedApprovalPoliciesFromCodexRequirements(content);
523
- return allowedApprovalPolicies === void 0 || allowedApprovalPolicies.has(policy);
524
- }
525
- function readCodexRequirementsToml(params) {
526
- if (params.requirementsToml !== void 0) return params.requirementsToml ?? void 0;
527
- const requirementsPath = readNonEmptyString(params.requirementsPath) ?? resolveCodexRequirementsPath(params.env ?? process.env, params.platform ?? process.platform);
528
- try {
529
- if (params.readRequirementsFile) return params.readRequirementsFile(requirementsPath);
530
- return readFileSync(requirementsPath, "utf8");
531
- } catch {
532
- return;
533
- }
534
- }
535
- function resolveCodexRequirementsPath(env, platform) {
536
- if (platform === "win32") return `${(readNonEmptyString(env.ProgramData) ?? "C:\\ProgramData").replace(/[\\/]+$/, "")}${WINDOWS_CODEX_REQUIREMENTS_SUFFIX}`;
537
- return UNIX_CODEX_REQUIREMENTS_PATH;
538
- }
539
- function parseAllowedSandboxModesFromCodexRequirements(content, hostName) {
540
- const remoteSandboxModes = parseMatchingRemoteSandboxModesFromCodexRequirements(content, hostName);
541
- if (remoteSandboxModes !== void 0) return remoteSandboxModes;
542
- return parseRequirementsSandboxModes(parseTopLevelRequirementsStringArray(content, "allowed_sandbox_modes"));
543
- }
544
- function parseAllowedApprovalPoliciesFromCodexRequirements(content) {
545
- const values = parseTopLevelRequirementsStringArray(content, "allowed_approval_policies");
546
- if (values === void 0) return;
547
- const normalizedPolicies = values.map((entry) => normalizeRequirementsApprovalPolicy(entry)).filter((entry) => entry !== void 0);
548
- return normalizedPolicies.length > 0 ? new Set(normalizedPolicies) : void 0;
549
- }
550
- function parseAllowedApprovalsReviewersFromCodexRequirements(content) {
551
- const values = parseTopLevelRequirementsStringArray(content, "allowed_approvals_reviewers");
552
- if (values === void 0) return;
553
- const normalizedReviewers = values.map((entry) => normalizeRequirementsApprovalsReviewer(entry)).filter((entry) => entry !== void 0);
554
- return normalizedReviewers.length > 0 ? new Set(normalizedReviewers) : void 0;
555
- }
556
- function parseMatchingRemoteSandboxModesFromCodexRequirements(content, hostName) {
557
- const normalizedHostName = normalizeRequirementsHostName(hostName);
558
- if (normalizedHostName === void 0) return;
559
- for (const section of parseTomlArrayTableSections(content, "remote_sandbox_config")) {
560
- const patterns = parseRequirementsStringArray(section, "hostname_patterns");
561
- if (!patterns || !requirementsHostNameMatchesAnyPattern(normalizedHostName, patterns)) continue;
562
- return parseRequirementsSandboxModes(parseRequirementsStringArray(section, "allowed_sandbox_modes"));
563
- }
564
- }
565
- function parseRequirementsSandboxModes(values) {
566
- if (values === void 0) return;
567
- const normalizedModes = values.map((entry) => normalizeRequirementsSandboxMode(entry)).filter((entry) => entry !== void 0);
568
- return normalizedModes.length > 0 ? new Set(normalizedModes) : void 0;
569
- }
570
- function parseTopLevelRequirementsStringArray(content, key) {
571
- return parseRequirementsStringArray(stripTomlLineComments(content).slice(0, firstTomlTableOffset(content)), key);
572
- }
573
- function parseTomlStringValue(content, key) {
574
- return parseTomlStringAssignmentValue(content, tomlDottedKeyPattern(key));
575
- }
576
- function parseInlineOpenAIModelProviderBaseUrl(content) {
577
- return parseTomlStringAssignmentValue(content, `${tomlKeyPattern("model_providers")}\\s*=\\s*\\{[\\s\\S]*?${tomlKeyPattern("openai")}\\s*=\\s*\\{[\\s\\S]*?${tomlKeyPattern("base_url")}`);
578
- }
579
- function parseTomlStringAssignmentValue(content, keyPattern) {
580
- const assignment = content.match(new RegExp(`(?:^|\\n)\\s*${keyPattern}\\s*=\\s*([^\\r\\n]*)`));
581
- if (!assignment) return;
582
- const rawValue = assignment[1]?.trimStart() ?? "";
583
- if (rawValue.startsWith("\"\"\"") || rawValue.startsWith("'''")) return false;
584
- const match = parseTomlStringAssignment(content, keyPattern);
585
- return match ? match[1] ?? match[2] ?? "" : false;
586
- }
587
- function parseTomlStringAssignment(content, keyPattern) {
588
- return content.match(new RegExp(`(?:^|\\n)\\s*${keyPattern}\\s*=\\s*(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|'([^']*)')`));
589
- }
590
- function tomlDottedKeyPattern(key) {
591
- return key.split(".").map(tomlKeyPattern).join("\\s*\\.\\s*");
592
- }
593
- function tomlKeyPattern(key) {
594
- const escaped = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
595
- return `(?:"${escaped}"|'${escaped}'|${escaped})`;
596
- }
597
- function parseRequirementsStringArray(content, key) {
598
- const match = content.match(new RegExp(`(?:^|\\n)\\s*${key}\\s*=\\s*\\[([\\s\\S]*?)\\]`));
599
- if (!match) return;
600
- const arrayBody = match[1] ?? "";
601
- const stringMatches = [...arrayBody.matchAll(/"([^"\\]*(?:\\.[^"\\]*)*)"|'([^']*)'/g)];
602
- if (stringMatches.length === 0 && arrayBody.trim().length > 0) return;
603
- return stringMatches.map((entry) => entry[1] ?? entry[2] ?? "");
604
- }
605
- function parseTomlTableSection(content, table) {
606
- const strippedContent = stripTomlLineComments(content);
607
- const tablePattern = tomlDottedKeyPattern(table);
608
- const match = new RegExp(`^\\s*\\[\\s*${tablePattern}\\s*\\]\\s*$`, "m").exec(strippedContent);
609
- if (!match) return;
610
- const sectionStart = match.index + match[0].length;
611
- const rest = strippedContent.slice(sectionStart);
612
- const nextTableOffset = rest.search(/^\s*\[/m);
613
- return nextTableOffset === -1 ? rest : rest.slice(0, nextTableOffset);
614
- }
615
- function parseTomlArrayTableSections(content, table) {
616
- const strippedContent = stripTomlLineComments(content);
617
- const escapedTable = table.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
618
- const headerPattern = new RegExp(`^\\s*\\[\\[\\s*${escapedTable}\\s*\\]\\]\\s*$`, "gm");
619
- const sections = [];
620
- for (let match = headerPattern.exec(strippedContent); match; match = headerPattern.exec(strippedContent)) {
621
- const sectionStart = headerPattern.lastIndex;
622
- const rest = strippedContent.slice(sectionStart);
623
- const nextTableOffset = rest.search(/^\s*\[/m);
624
- sections.push(nextTableOffset === -1 ? rest : rest.slice(0, nextTableOffset));
625
- }
626
- return sections;
627
- }
628
- function firstTomlTableOffset(content) {
629
- return content.match(/^\s*\[[^\]\n]/m)?.index ?? content.length;
630
- }
631
- function stripTomlLineComments(value) {
632
- let output = "";
633
- let quote;
634
- let escaped = false;
635
- for (let index = 0; index < value.length; index += 1) {
636
- const char = value[index] ?? "";
637
- if (quote) {
638
- output += char;
639
- if (quote === "\"" && escaped) {
640
- escaped = false;
641
- continue;
642
- }
643
- if (quote === "\"" && char === "\\") {
644
- escaped = true;
645
- continue;
646
- }
647
- if (char === quote) quote = void 0;
648
- continue;
649
- }
650
- if (char === "\"" || char === "'") {
651
- quote = char;
652
- output += char;
653
- continue;
654
- }
655
- if (char === "#") {
656
- while (index < value.length && value[index] !== "\n") index += 1;
657
- if (value[index] === "\n") output += "\n";
658
- continue;
659
- }
660
- output += char;
661
- }
662
- return output;
663
- }
664
- function normalizeRequirementsSandboxMode(value) {
665
- const compact = value.replace(/[\s_-]/g, "").toLowerCase();
666
- if (compact === "readonly") return "read-only";
667
- if (compact === "workspacewrite") return "workspace-write";
668
- if (compact === "dangerfullaccess") return "danger-full-access";
669
- }
670
- function normalizeRequirementsHostName(value) {
671
- const normalized = value.trim().replace(/\.+$/g, "").toLowerCase();
672
- return normalized.length > 0 ? normalized : void 0;
673
- }
674
- function requirementsHostNameMatchesAnyPattern(hostName, patterns) {
675
- return patterns.some((pattern) => {
676
- const normalizedPattern = normalizeRequirementsHostName(pattern);
677
- return normalizedPattern !== void 0 && globPatternMatches(hostName, normalizedPattern);
678
- });
679
- }
680
- function globPatternMatches(value, pattern) {
681
- let regex = "^";
682
- for (const char of pattern) if (char === "*") regex += ".*";
683
- else if (char === "?") regex += ".";
684
- else regex += char.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
685
- regex += "$";
686
- return new RegExp(regex).test(value);
687
- }
688
- function normalizeRequirementsApprovalPolicy(value) {
689
- const normalized = value.trim().toLowerCase();
690
- if (normalized === "on-failure") return "on-request";
691
- return resolveApprovalPolicy(normalized);
692
- }
693
- function normalizeRequirementsApprovalsReviewer(value) {
694
- return resolveApprovalsReviewer(value.trim().toLowerCase());
695
- }
696
- function selectGuardianApprovalPolicy(allowedApprovalPolicies, execModeRequiringPromptingApprovals) {
697
- if (allowedApprovalPolicies === void 0 || allowedApprovalPolicies.has("on-request")) return "on-request";
698
- if (execModeRequiringPromptingApprovals) throw new Error(`tools.exec.mode=${execModeRequiringPromptingApprovals} requires Codex app-server prompting approvals`);
699
- if (allowedApprovalPolicies.has("untrusted")) return "untrusted";
700
- if (allowedApprovalPolicies.has("never")) return "never";
701
- return "on-request";
702
- }
703
- function selectGuardianApprovalsReviewer(allowedApprovalsReviewers, execModeRequiringAutoReviewer) {
704
- if (allowedApprovalsReviewers === void 0 || allowedApprovalsReviewers.has("auto_review")) return "auto_review";
705
- if (allowedApprovalsReviewers.has("guardian_subagent")) return "guardian_subagent";
706
- if (execModeRequiringAutoReviewer) throw new Error(`tools.exec.mode=${execModeRequiringAutoReviewer} requires Codex app-server auto approvals`);
707
- if (allowedApprovalsReviewers.has("user")) return "user";
708
- return "auto_review";
709
- }
710
- function selectUserApprovalsReviewer(allowedApprovalsReviewers, execModeRequiringUserReviewer) {
711
- if (allowedApprovalsReviewers === void 0 || allowedApprovalsReviewers.has("user")) return "user";
712
- throw new Error(`tools.exec.mode=${execModeRequiringUserReviewer ?? "ask"} requires Codex app-server user approvals`);
713
- }
714
- //#endregion
715
- //#region extensions/codex/src/app-server/config-reviewer.ts
716
- const CODEX_APP_SERVER_HOME_DIRNAME = "codex-home";
717
- const CODEX_CONFIG_TOML_FILENAME = "config.toml";
718
- function canUseCodexModelBackedApprovalsReviewerForModel(params) {
719
- const explicitProvider = params.modelProvider?.trim().toLowerCase();
720
- const inferredProvider = inferProviderFromModelRef(params.model);
721
- if (explicitProvider && explicitProvider !== "codex") return isTrustedCodexModelBackedApprovalsReviewerProvider(explicitProvider, params) && (inferredProvider === void 0 || isTrustedCodexModelBackedApprovalsReviewerProvider(inferredProvider, params));
722
- if (inferredProvider !== void 0) return isTrustedCodexModelBackedApprovalsReviewerProvider(inferredProvider, params);
723
- return isTrustedCodexModelBackedApprovalsReviewerProvider(explicitProvider, params);
724
- }
725
- function isTrustedCodexModelBackedOpenAIProvider(params) {
726
- if (!openAIBaseUrlEnvOverridesAreTrustedForModelBackedReview(params.env)) return false;
727
- const codexBaseUrlOverrides = readCodexBaseUrlOverridesForModelBackedReview(params);
728
- if (codexBaseUrlOverrides === false || !codexBaseUrlOverrides.openAI.every(isNativeOpenAIBaseUrl) || !codexBaseUrlOverrides.chatGPT.every(isNativeChatGPTBaseUrl)) return false;
729
- const openAIProviders = readConfiguredOpenAIProvidersForModelBackedReview(params.config);
730
- if (openAIProviders.length === 0) return true;
731
- return openAIProviders.every((openAIProvider) => configuredOpenAIProviderIsTrustedForModelBackedReview(openAIProvider, params.model));
732
- }
733
- function resolveCodexModelBackedReviewerPolicyContext(params) {
734
- const provider = params.provider?.trim();
735
- if (provider && provider.toLowerCase() !== "codex") return {
736
- modelProvider: normalizeCodexModelBackedReviewerPolicyProvider(provider),
737
- model: params.model
738
- };
739
- const bindingModelProvider = params.bindingModelProvider?.trim();
740
- const currentModel = params.model?.trim();
741
- const bindingModel = params.bindingModel?.trim();
742
- if (bindingModelProvider && currentModel && bindingModel && currentModel === bindingModel) return {
743
- modelProvider: normalizeCodexModelBackedReviewerPolicyProvider(bindingModelProvider),
744
- model: params.model ?? params.bindingModel
745
- };
746
- const currentModelProvider = inferProviderFromModelRef(params.model);
747
- if (currentModelProvider) return {
748
- modelProvider: normalizeCodexModelBackedReviewerPolicyProvider(currentModelProvider),
749
- model: params.model
750
- };
751
- if (bindingModelProvider) return {
752
- modelProvider: normalizeCodexModelBackedReviewerPolicyProvider(bindingModelProvider),
753
- model: params.model ?? params.bindingModel
754
- };
755
- return {
756
- modelProvider: params.nativeAuthProfile === true ? "openai" : void 0,
757
- model: params.model ?? params.bindingModel
758
- };
759
- }
760
- function isCodexModelBackedApprovalsReviewerProvider(provider) {
761
- return provider?.trim().toLowerCase() === "openai";
762
- }
763
- function isTrustedCodexModelBackedApprovalsReviewerProvider(provider, params) {
764
- return isCodexModelBackedApprovalsReviewerProvider(provider) && isTrustedCodexModelBackedOpenAIProvider({
765
- config: params.config,
766
- env: params.env,
767
- model: params.model,
768
- agentDir: params.agentDir,
769
- codexConfigToml: params.codexConfigToml,
770
- homeScope: params.homeScope
771
- });
772
- }
773
- function readCodexBaseUrlOverridesForModelBackedReview(params) {
774
- const configToml = readCodexAppServerConfigToml(params);
775
- if (configToml === false) return false;
776
- if (configToml === void 0) return {
777
- openAI: [],
778
- chatGPT: []
779
- };
780
- const topLevelContent = stripTomlLineComments(configToml).slice(0, firstTomlTableOffset(configToml));
781
- const modelProviderOpenAISection = parseTomlTableSection(configToml, "model_providers.openai");
782
- const openAIBaseUrl = parseTomlStringValue(topLevelContent, "openai_base_url");
783
- const chatGPTBaseUrl = parseTomlStringValue(topLevelContent, "chatgpt_base_url");
784
- const openAI = [
785
- openAIBaseUrl,
786
- parseTomlStringValue(topLevelContent, "model_providers.openai.base_url"),
787
- parseInlineOpenAIModelProviderBaseUrl(topLevelContent),
788
- modelProviderOpenAISection ? parseTomlStringValue(modelProviderOpenAISection, "base_url") : void 0
789
- ];
790
- const chatGPT = [chatGPTBaseUrl];
791
- if ([...openAI, ...chatGPT].includes(false)) return false;
792
- return {
793
- openAI: openAI.filter((entry) => typeof entry === "string"),
794
- chatGPT: chatGPT.filter((entry) => typeof entry === "string")
795
- };
796
- }
797
- function readCodexAppServerConfigToml(params) {
798
- if (params.codexConfigToml !== void 0) return params.codexConfigToml ?? void 0;
799
- const configPath = resolveCodexAppServerConfigPath(params);
800
- if (!configPath) return;
801
- try {
802
- return readFileSync(configPath, "utf8");
803
- } catch (error) {
804
- return readErrorCode(error) === "ENOENT" ? void 0 : false;
805
- }
806
- }
807
- function codexConfigEnablesNativeComputerUse(params) {
808
- const configToml = readCodexAppServerConfigToml(params);
809
- if (configToml === false) return true;
810
- if (configToml === void 0) return false;
811
- let parsedConfig;
812
- try {
813
- parsedConfig = parse(configToml, { integersAsBigInt: true });
814
- } catch {
815
- return true;
816
- }
817
- const rawPlugins = parsedConfig.plugins;
818
- if (rawPlugins === void 0) return false;
819
- const plugins = readRecord(rawPlugins);
820
- if (!plugins) return true;
821
- for (const [pluginId, rawPluginConfig] of Object.entries(plugins)) {
822
- if (!params.pluginNames.some((pluginName) => pluginId === pluginName || pluginId.startsWith(`${pluginName}@`))) continue;
823
- const pluginConfig = readRecord(rawPluginConfig);
824
- if (!pluginConfig) return true;
825
- if (pluginConfig.enabled === false) continue;
826
- return true;
827
- }
828
- return false;
829
- }
830
- function resolveCodexAppServerConfigPath(params) {
831
- if (params.homeScope === "user") return path.join(resolveCodexAppServerUserHomeDir(params.env), CODEX_CONFIG_TOML_FILENAME);
832
- const agentDir = readNonEmptyString(params.agentDir);
833
- const codexHome = agentDir ? path.join(path.resolve(agentDir), CODEX_APP_SERVER_HOME_DIRNAME) : void 0;
834
- return codexHome ? path.join(codexHome, CODEX_CONFIG_TOML_FILENAME) : void 0;
835
- }
836
- /** Resolves the native user Codex home used by Desktop and the CLI. */
837
- function resolveCodexAppServerUserHomeDir(env = process.env, homedir$1 = homedir) {
838
- const configured = readNonEmptyString(env.CODEX_HOME);
839
- return path.resolve(configured ?? path.join(homedir$1(), ".codex"));
840
- }
841
- function readErrorCode(error) {
842
- return error && typeof error === "object" && "code" in error ? String(error.code) : void 0;
843
- }
844
- function readConfiguredOpenAIProvidersForModelBackedReview(config) {
845
- const providerRecords = readRecord(readRecord(readRecord(config)?.models)?.providers);
846
- if (!providerRecords) return [];
847
- const openAIProviders = [];
848
- for (const [providerId, providerConfig] of Object.entries(providerRecords)) {
849
- if (resolveProviderIdForAuth(providerId, { config }) !== "openai") continue;
850
- const record = readRecord(providerConfig);
851
- if (record) openAIProviders.push(record);
852
- }
853
- return openAIProviders;
854
- }
855
- function configuredOpenAIProviderIsTrustedForModelBackedReview(openAIProvider, modelInput) {
856
- if (readRecord(openAIProvider.localService) || hasNonEmptyRecord(openAIProvider.headers) || hasNonEmptyRecord(openAIProvider.request) || typeof openAIProvider.authHeader === "boolean" || !isNativeOpenAIBaseUrl(openAIProvider.baseUrl)) return false;
857
- const models = openAIProvider.models;
858
- if (!Array.isArray(models)) return true;
859
- const modelId = normalizeOpenAIModelBackedReviewerModelId(modelInput);
860
- if (!modelId) return false;
861
- for (const entry of models) {
862
- const model = readRecord(entry);
863
- if (typeof model?.id !== "string" || !matchesConfiguredOpenAIModelId(modelId, model.id)) continue;
864
- if (hasNonEmptyRecord(model.headers) || hasNonEmptyRecord(model.request) || !isNativeOpenAIBaseUrl(model.baseUrl)) return false;
865
- }
866
- return true;
867
- }
868
- function normalizeOpenAIModelBackedReviewerModelId(modelInput) {
869
- const normalized = modelInput?.trim() ?? "";
870
- const authProfileIndex = normalized.indexOf("@");
871
- const withoutAuthProfile = authProfileIndex > 0 ? normalized.slice(0, authProfileIndex) : normalized;
872
- const slashIndex = withoutAuthProfile.indexOf("/");
873
- return slashIndex > 0 ? withoutAuthProfile.slice(slashIndex + 1).trim() : withoutAuthProfile;
874
- }
875
- function matchesConfiguredOpenAIModelId(modelId, configuredModelId) {
876
- const configured = normalizeOpenAIModelBackedReviewerModelId(configuredModelId);
877
- return Boolean(configured) && (modelId === configured || modelId.startsWith(`${configured}@`));
878
- }
879
- function hasNonEmptyRecord(value) {
880
- const record = readRecord(value);
881
- return record !== void 0 && Object.keys(record).length > 0;
882
- }
883
- function isNativeOpenAIBaseUrl(value) {
884
- if (typeof value !== "string" || !value.trim()) return true;
885
- try {
886
- const url = new URL(value);
887
- return url.protocol === "https:" && url.hostname.toLowerCase() === "api.openai.com";
888
- } catch {
889
- return false;
890
- }
891
- }
892
- function openAIBaseUrlEnvOverridesAreTrustedForModelBackedReview(env) {
893
- return [env?.OPENAI_BASE_URL, env?.OPENAI_API_BASE].every(isNativeOpenAIBaseUrl);
894
- }
895
- function isNativeChatGPTBaseUrl(value) {
896
- if (typeof value !== "string" || !value.trim()) return true;
897
- try {
898
- const url = new URL(value);
899
- return url.protocol === "https:" && url.hostname.toLowerCase() === "chatgpt.com";
900
- } catch {
901
- return false;
902
- }
903
- }
904
- function normalizeCodexModelBackedReviewerPolicyProvider(provider) {
905
- return provider.toLowerCase() === "openai" ? "openai" : provider;
906
- }
907
- function inferProviderFromModelRef(model) {
908
- const normalized = model?.trim().toLowerCase();
909
- const slashIndex = normalized?.indexOf("/") ?? -1;
910
- return slashIndex > 0 ? normalized?.slice(0, slashIndex) : void 0;
911
- }
912
- //#endregion
913
- //#region extensions/codex/src/app-server/config-security.ts
914
- function shouldAutoApproveCodexAppServerApprovals(appServer) {
915
- return appServer.networkProxy === void 0 && appServer.approvalPolicy === "never" && appServer.sandbox === "danger-full-access";
916
- }
917
- function resolveCodexAppServerNetworkProxy(config, sandbox) {
918
- if (config?.enabled !== true) return {};
919
- const fileSystemMode = config.baseProfile === "read-only" || !config.baseProfile && sandbox === "read-only" ? "read" : "write";
920
- const networkConfig = removeUndefinedJsonFields({
921
- enabled: true,
922
- mode: config.mode,
923
- domains: normalizeNetworkProxyPermissionMap(config.domains),
924
- unix_sockets: normalizeNetworkProxyPermissionMap(config.unixSockets),
925
- proxy_url: readNonEmptyString(config.proxyUrl),
926
- socks_url: readNonEmptyString(config.socksUrl),
927
- enable_socks5: config.enableSocks5,
928
- enable_socks5_udp: config.enableSocks5Udp,
929
- allow_upstream_proxy: config.allowUpstreamProxy,
930
- allow_local_binding: config.allowLocalBinding,
931
- dangerously_allow_non_loopback_proxy: config.dangerouslyAllowNonLoopbackProxy,
932
- dangerously_allow_all_unix_sockets: config.dangerouslyAllowAllUnixSockets
933
- });
934
- const profile = {
935
- filesystem: {
936
- ":minimal": "read",
937
- ":project_roots": { ".": fileSystemMode }
938
- },
939
- network: networkConfig
940
- };
941
- const profileName = resolveNetworkProxyPermissionProfileName(config, profile);
942
- const configPatch = {
943
- "features.network_proxy.enabled": true,
944
- default_permissions: profileName,
945
- permissions: { [profileName]: profile }
946
- };
947
- return { networkProxy: {
948
- profileName,
949
- configFingerprint: fingerprintCodexAppServerNetworkProxyConfigPatch(configPatch),
950
- configPatch
951
- } };
952
- }
953
- function resolveNetworkProxyPermissionProfileName(config, profile) {
954
- const explicitProfileName = readNonEmptyString(config.profileName);
955
- if (explicitProfileName) return explicitProfileName;
956
- return `${DEFAULT_CODEX_APP_SERVER_NETWORK_PROXY_PROFILE_PREFIX}-${createHash("sha256").update(stableStringifyJson({
957
- version: 1,
958
- profile
959
- })).digest("hex").slice(0, 16)}`;
960
- }
961
- function fingerprintCodexAppServerNetworkProxyConfigPatch(configPatch) {
962
- return createHash("sha256").update(stableStringifyJson(configPatch)).digest("hex");
963
- }
964
- function normalizeNetworkProxyPermissionMap(value) {
965
- const entries = Object.entries(value ?? {}).map(([key, permission]) => [key.trim(), permission]).filter(([key]) => key.length > 0);
966
- return entries.length > 0 ? Object.fromEntries(entries) : void 0;
967
- }
968
- function removeUndefinedJsonFields(value) {
969
- return Object.fromEntries(Object.entries(value).filter((entry) => entry[1] !== void 0));
970
- }
971
- function stableStringifyJson(value) {
972
- if (Array.isArray(value)) return `[${value.map((item) => stableStringifyJson(item)).join(",")}]`;
973
- if (value && typeof value === "object") return `{${Object.entries(value).toSorted(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${stableStringifyJson(item)}`).join(",")}}`;
974
- return JSON.stringify(value);
975
- }
976
- function withMcpElicitationsApprovalPolicy(policy) {
977
- if (typeof policy !== "string") return { granular: {
978
- ...policy.granular,
979
- mcp_elicitations: true
980
- } };
981
- if (policy === "never") return { granular: {
982
- mcp_elicitations: true,
983
- rules: false,
984
- sandbox_approval: false,
985
- request_permissions: false,
986
- skill_approval: false
987
- } };
988
- return { granular: {
989
- mcp_elicitations: true,
990
- rules: true,
991
- sandbox_approval: true,
992
- request_permissions: true,
993
- skill_approval: true
994
- } };
995
- }
996
- function resolveTransport(value) {
997
- return value === "websocket" || value === "unix" ? value : "stdio";
998
- }
999
- function normalizeRemoteWorkspaceRoot(value) {
1000
- return readNonEmptyString(value);
1001
- }
1002
- function inferCodexAppServerConnectionClass(params) {
1003
- if (params.transport !== "websocket") return "local-loopback";
1004
- return params.url && isLoopbackWebSocketUrl(params.url) ? "local-loopback" : "remote";
1005
- }
1006
- function assertCodexAppServerConnectionClassConfig(params) {
1007
- if (params.connectionClass === "remote" && !hasIdentityBearingWebSocketAuth({
1008
- authToken: params.authToken,
1009
- headers: params.headers
1010
- })) throw new Error("remote Codex app-server WebSocket URLs require appServer.authToken or an Authorization header");
1011
- }
1012
- /** Applies the canonical remote-auth boundary to any Codex AppServer transport. */
1013
- function assertCodexAppServerConnectionSecurity(params) {
1014
- assertCodexAppServerConnectionClassConfig({
1015
- connectionClass: inferCodexAppServerConnectionClass(params),
1016
- authToken: params.authToken,
1017
- headers: params.headers
1018
- });
1019
- }
1020
- function isLoopbackWebSocketUrl(value) {
1021
- let parsed;
1022
- try {
1023
- parsed = new URL(value);
1024
- } catch {
1025
- return false;
1026
- }
1027
- if (parsed.protocol !== "ws:" && parsed.protocol !== "wss:") return false;
1028
- const host = parsed.hostname.toLowerCase();
1029
- return host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "[::1]" || host.startsWith("127.");
1030
- }
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)));
1034
- }
1035
- function resolvePolicyMode(value) {
1036
- return value === "guardian" || value === "yolo" ? value : void 0;
1037
- }
1038
- function resolveDefaultCodexAppServerPolicy(params) {
1039
- if (params.transport !== "stdio") return {
1040
- mode: "yolo",
1041
- dangerFullAccessAllowed: true
1042
- };
1043
- const content = readCodexRequirementsToml(params);
1044
- if (content === void 0) {
1045
- if (!params.forceGuardian) return {
1046
- mode: "yolo",
1047
- dangerFullAccessAllowed: true
1048
- };
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)
1055
- };
1056
- }
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
- };
1074
- }
1075
- //#endregion
1076
- //#region extensions/codex/src/app-server/config-runtime.ts
1077
- function resolveCodexAppServerRuntimeOptions(params = {}) {
1078
- const env = params.env ?? process.env;
1079
- const config = readCodexPluginConfig(params.pluginConfig).appServer ?? {};
1080
- const transport = resolveTransport(config.transport);
1081
- const homeScope = config.homeScope ?? "agent";
1082
- const configCommand = readNonEmptyString(config.command);
1083
- const envCommand = readNonEmptyString(env.OPENCLAW_CODEX_APP_SERVER_BIN);
1084
- const command = configCommand ?? envCommand ?? "codex";
1085
- const commandSource = configCommand ? "config" : envCommand ? "env" : "managed";
1086
- if (commandSource === "config" || commandSource === "env") assertCodexAppServerCommandHasNoInlineArgs({
1087
- command,
1088
- source: commandSource
1089
- });
1090
- const args = resolveArgs(config.args, env.OPENCLAW_CODEX_APP_SERVER_ARGS);
1091
- const headers = normalizeHeaders(config.headers);
1092
- const clearEnv = normalizeStringList(config.clearEnv);
1093
- const authToken = normalizeCodexAppServerSecretInput({
1094
- value: config.authToken,
1095
- path: "plugins.entries.codex.config.appServer.authToken"
1096
- });
1097
- const url = readNonEmptyString(config.url) ?? (transport === "unix" ? "unix://" : void 0);
1098
- const connectionClass = inferCodexAppServerConnectionClass({
1099
- transport,
1100
- url
1101
- });
1102
- const remoteAppsSubstrate = "preconfigured";
1103
- const remoteWorkspaceRoot = normalizeRemoteWorkspaceRoot(config.remoteWorkspaceRoot);
1104
- const execMode = resolveEffectiveOpenClawExecModeForCodexAppServer({
1105
- execMode: params.execMode,
1106
- execPolicy: params.execPolicy
1107
- });
1108
- assertCodexAppServerAllowedForOpenClawExecMode(execMode);
1109
- const explicitPolicyMode = resolvePolicyMode(config.mode) ?? resolvePolicyMode(env.OPENCLAW_CODEX_APP_SERVER_MODE);
1110
- const configuredSandbox = resolveSandbox(config.sandbox) ?? resolveSandbox(env.OPENCLAW_CODEX_APP_SERVER_SANDBOX);
1111
- const explicitApprovalsReviewer = resolveApprovalsReviewer(config.approvalsReviewer);
1112
- const normalizedPolicyMode = resolveCodexPolicyModeForOpenClawExecMode(execMode);
1113
- const ignoreLegacyYoloPolicyMode = normalizedPolicyMode === "guardian" && explicitPolicyMode === "yolo";
1114
- const canUseModelBackedReviewer = canUseCodexModelBackedApprovalsReviewerForModel({
1115
- modelProvider: params.modelProvider,
1116
- model: params.model,
1117
- config: params.config,
1118
- env,
1119
- agentDir: params.agentDir,
1120
- codexConfigToml: params.codexConfigToml,
1121
- homeScope
1122
- });
1123
- const forceUserReviewer = !canUseModelBackedReviewer && (explicitApprovalsReviewer === "auto_review" || explicitApprovalsReviewer === "guardian_subagent" || explicitPolicyMode === "guardian" && explicitApprovalsReviewer !== "user") || execMode !== void 0 && execMode !== "full" && (execMode !== "auto" || !canUseModelBackedReviewer);
1124
- const forceGuardianReviewer = execMode === "auto" && canUseModelBackedReviewer;
1125
- const execModeRequiringPromptingApprovals = execMode === "auto" || execMode === "ask" ? execMode : forceUserReviewer ? "ask" : void 0;
1126
- const forceDangerFullAccessSandbox = params.execPolicy?.touched === true && params.execPolicy.security === "full" && params.execPolicy.ask === "always";
1127
- const forceRuntimePolicy = forceUserReviewer || forceGuardianReviewer || forceDangerFullAccessSandbox;
1128
- const defaultPolicy = explicitPolicyMode && !forceRuntimePolicy && !ignoreLegacyYoloPolicyMode ? void 0 : resolveDefaultCodexAppServerPolicy({
1129
- transport,
1130
- env,
1131
- forceGuardian: normalizedPolicyMode === "guardian",
1132
- forceUserReviewer: forceUserReviewer || !canUseModelBackedReviewer,
1133
- execModeRequiringPromptingApprovals,
1134
- requirementsToml: params.requirementsToml,
1135
- requirementsPath: params.requirementsPath,
1136
- readRequirementsFile: params.readRequirementsFile,
1137
- platform: params.platform,
1138
- hostName: params.hostName,
1139
- execModeRequiringUserReviewer: forceUserReviewer ? execMode : void 0
1140
- });
1141
- const preserveExplicitAutoSandbox = forceGuardianReviewer && configuredSandbox === "read-only";
1142
- const forcedPolicy = forceRuntimePolicy ? {
1143
- approvalPolicy: defaultPolicy?.approvalPolicy ?? "on-request",
1144
- sandbox: preserveExplicitAutoSandbox ? void 0 : forceDangerFullAccessSandbox ? selectForcedDangerFullAccessSandbox({
1145
- configuredSandbox,
1146
- defaultPolicy,
1147
- openClawSandboxActive: Boolean(params.openClawSandboxActive)
1148
- }) : selectForcedPromptingSandbox({
1149
- configuredSandbox,
1150
- defaultSandbox: defaultPolicy?.sandbox
1151
- }),
1152
- approvalsReviewer: defaultPolicy?.approvalsReviewer ?? (forceUserReviewer ? "user" : "auto_review")
1153
- } : void 0;
1154
- const policyMode = ignoreLegacyYoloPolicyMode ? normalizedPolicyMode : explicitPolicyMode ?? normalizedPolicyMode ?? defaultPolicy?.mode ?? "yolo";
1155
- const serviceTier = normalizeCodexServiceTier(config.serviceTier);
1156
- const resolvedSandbox = forcedPolicy?.sandbox ?? configuredSandbox ?? defaultPolicy?.sandbox ?? (policyMode === "guardian" ? "workspace-write" : "danger-full-access");
1157
- if (transport === "websocket" && !url) throw new Error("plugins.entries.codex.config.appServer.url is required when appServer.transport is websocket");
1158
- if (transport === "websocket" && homeScope === "user") throw new Error("plugins.entries.codex.config.appServer.homeScope=user requires appServer.transport=stdio or unix");
1159
- if (transport === "unix" && homeScope !== "user") throw new Error("plugins.entries.codex.config.appServer.transport=unix requires appServer.homeScope=user");
1160
- if (transport === "unix" && !url?.startsWith("unix://")) throw new Error("plugins.entries.codex.config.appServer.url must use unix:// when appServer.transport is unix");
1161
- assertCodexAppServerConnectionSecurity({
1162
- transport,
1163
- url,
1164
- authToken,
1165
- headers
1166
- });
1167
- const configApprovalPolicy = resolveApprovalPolicy(config.approvalPolicy);
1168
- const envApprovalPolicy = resolveApprovalPolicy(env.OPENCLAW_CODEX_APP_SERVER_APPROVAL_POLICY);
1169
- const approvalPolicy = configApprovalPolicy ?? envApprovalPolicy ?? defaultPolicy?.approvalPolicy ?? (policyMode === "guardian" ? "on-request" : "never");
1170
- const approvalPolicySource = configApprovalPolicy ? "config" : envApprovalPolicy ? "env" : defaultPolicy?.approvalPolicy ? "requirements" : "implicit";
1171
- const computerUseConfig = resolveCodexComputerUseConfig({
1172
- pluginConfig: params.pluginConfig,
1173
- env
1174
- });
1175
- const managedCommandOrder = params.managedCommandOrder ?? (homeScope === "user" || computerUseConfig.enabled ? "desktop-first" : "package-first");
1176
- const includeManagedCommandOrder = commandSource === "managed" && (managedCommandOrder === "desktop-first" || params.managedCommandOrder === "package-first");
1177
- const managedComputerUsePluginNames = [.../* @__PURE__ */ new Set([DEFAULT_CODEX_COMPUTER_USE_PLUGIN_NAME, computerUseConfig.pluginName])];
1178
- return {
1179
- start: {
1180
- transport,
1181
- homeScope,
1182
- command,
1183
- commandSource,
1184
- ...includeManagedCommandOrder ? { managedCommandOrder } : {},
1185
- ...commandSource === "managed" ? { managedComputerUsePluginNames } : {},
1186
- args: args.length > 0 ? args : [
1187
- "app-server",
1188
- "--listen",
1189
- "stdio://"
1190
- ],
1191
- ...url ? { url } : {},
1192
- ...authToken ? { authToken } : {},
1193
- headers,
1194
- ...transport === "stdio" && clearEnv.length > 0 ? { clearEnv } : {}
1195
- },
1196
- connectionClass,
1197
- remoteAppsSubstrate,
1198
- ...remoteWorkspaceRoot ? { remoteWorkspaceRoot } : {},
1199
- codeModeOnly: config.codeModeOnly === true,
1200
- loopDetectionPreToolUseRelay: config.loopDetectionPreToolUseRelay !== false,
1201
- requestTimeoutMs: normalizePositiveNumber(config.requestTimeoutMs, 6e4),
1202
- turnCompletionIdleTimeoutMs: normalizePositiveNumber(config.turnCompletionIdleTimeoutMs, 6e4),
1203
- turnAssistantCompletionIdleTimeoutMs: normalizePositiveNumber(config.turnAssistantCompletionIdleTimeoutMs, 1e4),
1204
- ...config.postToolRawAssistantCompletionIdleTimeoutMs !== void 0 ? { postToolRawAssistantCompletionIdleTimeoutMs: normalizePositiveNumber(config.postToolRawAssistantCompletionIdleTimeoutMs, 6e4) } : {},
1205
- approvalPolicy: forcedPolicy?.approvalPolicy ?? approvalPolicy,
1206
- approvalPolicySource,
1207
- sandbox: resolvedSandbox,
1208
- approvalsReviewer: forcedPolicy?.approvalsReviewer ?? explicitApprovalsReviewer ?? defaultPolicy?.approvalsReviewer ?? (policyMode === "guardian" ? "auto_review" : "user"),
1209
- ...serviceTier ? { serviceTier } : {},
1210
- ...resolveCodexAppServerNetworkProxy(config.networkProxy, resolvedSandbox)
1211
- };
1212
- }
1213
- /**
1214
- * Rechecks Codex-owned plugin state at the final spawn boundary, where the
1215
- * effective agent home is known, so Computer Use keeps the desktop app's TCC ownership.
1216
- */
1217
- function resolveCodexAppServerStartOptionsForAgent(params) {
1218
- const startOptions = params.startOptions;
1219
- if (startOptions.transport !== "stdio" || startOptions.commandSource !== "managed" || startOptions.managedCommandOrder !== void 0) return startOptions;
1220
- if (startOptions.homeScope === "user") return {
1221
- ...startOptions,
1222
- managedCommandOrder: "desktop-first"
1223
- };
1224
- return codexConfigEnablesNativeComputerUse({
1225
- agentDir: params.agentDir,
1226
- codexConfigToml: params.codexConfigToml,
1227
- env: params.env,
1228
- homeScope: "agent",
1229
- pluginNames: startOptions.managedComputerUsePluginNames ?? ["computer-use"]
1230
- }) ? {
1231
- ...startOptions,
1232
- managedCommandOrder: "desktop-first"
1233
- } : startOptions;
1234
- }
1235
- function resolveCodexComputerUseConfig(params = {}) {
1236
- const env = params.env ?? process.env;
1237
- const config = readCodexPluginConfig(params.pluginConfig).computerUse ?? {};
1238
- const marketplaceSource = readNonEmptyString(params.overrides?.marketplaceSource) ?? readNonEmptyString(config.marketplaceSource) ?? readNonEmptyString(env.OPENCLAW_CODEX_COMPUTER_USE_MARKETPLACE_SOURCE);
1239
- const marketplacePath = readNonEmptyString(params.overrides?.marketplacePath) ?? readNonEmptyString(config.marketplacePath) ?? readNonEmptyString(env.OPENCLAW_CODEX_COMPUTER_USE_MARKETPLACE_PATH);
1240
- const marketplaceName = readNonEmptyString(params.overrides?.marketplaceName) ?? readNonEmptyString(config.marketplaceName) ?? readNonEmptyString(env.OPENCLAW_CODEX_COMPUTER_USE_MARKETPLACE_NAME);
1241
- const configuredPluginName = readNonEmptyString(params.overrides?.pluginName) ?? readNonEmptyString(config.pluginName) ?? readNonEmptyString(env.OPENCLAW_CODEX_COMPUTER_USE_PLUGIN_NAME);
1242
- const configuredMcpServerName = readNonEmptyString(params.overrides?.mcpServerName) ?? readNonEmptyString(config.mcpServerName) ?? readNonEmptyString(env.OPENCLAW_CODEX_COMPUTER_USE_MCP_SERVER_NAME);
1243
- const autoInstall = params.overrides?.autoInstall ?? config.autoInstall ?? readBooleanEnv(env.OPENCLAW_CODEX_COMPUTER_USE_AUTO_INSTALL) ?? false;
1244
- 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);
1245
- 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);
1246
- 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);
1247
- const healthCheckIntervalMinutes = normalizeComputerUseHealthCheckIntervalMinutes(params.overrides?.healthCheckIntervalMinutes ?? config.healthCheckIntervalMinutes ?? readNumberEnv(env.OPENCLAW_CODEX_COMPUTER_USE_HEALTH_CHECK_INTERVAL_MINUTES));
1248
- const healthCheckEnabled = params.overrides?.healthCheckEnabled ?? config.healthCheckEnabled ?? readBooleanEnv(env.OPENCLAW_CODEX_COMPUTER_USE_HEALTH_CHECK_ENABLED) ?? false;
1249
- const pluginCacheMode = normalizeComputerUsePluginCacheMode(params.overrides?.pluginCacheMode) ?? normalizeComputerUsePluginCacheMode(config.pluginCacheMode) ?? normalizeComputerUsePluginCacheMode(env.OPENCLAW_CODEX_COMPUTER_USE_PLUGIN_CACHE_MODE) ?? "independent";
1250
- const strictReadiness = params.overrides?.strictReadiness ?? config.strictReadiness ?? readBooleanEnv(env.OPENCLAW_CODEX_COMPUTER_USE_STRICT_READINESS) ?? false;
1251
- const autoRepair = params.overrides?.autoRepair ?? config.autoRepair ?? readBooleanEnv(env.OPENCLAW_CODEX_COMPUTER_USE_AUTO_REPAIR) ?? false;
1252
- return {
1253
- enabled: params.overrides?.enabled ?? config.enabled ?? readBooleanEnv(env.OPENCLAW_CODEX_COMPUTER_USE) ?? Boolean(autoInstall || marketplaceSource || marketplacePath || marketplaceName || configuredPluginName || configuredMcpServerName),
1254
- autoInstall,
1255
- marketplaceDiscoveryTimeoutMs,
1256
- liveTestTimeoutMs,
1257
- toolCallTimeoutMs,
1258
- healthCheckEnabled,
1259
- healthCheckIntervalMinutes,
1260
- pluginCacheMode,
1261
- strictReadiness,
1262
- autoRepair,
1263
- pluginName: configuredPluginName ?? "computer-use",
1264
- mcpServerName: configuredMcpServerName ?? "computer-use",
1265
- ...marketplaceSource ? { marketplaceSource } : {},
1266
- ...marketplacePath ? { marketplacePath } : {},
1267
- ...marketplaceName ? { marketplaceName } : {}
1268
- };
1269
- }
1270
- function normalizeComputerUseHealthCheckIntervalMinutes(value) {
1271
- return value === 30 || value === 60 || value === 120 || value === 240 ? value : 60;
1272
- }
1273
- function normalizeComputerUsePluginCacheMode(value) {
1274
- return value === "shared" || value === "independent" ? value : null;
1275
- }
1276
- function codexAppServerStartOptionsKey(options, params = {}) {
1277
- return JSON.stringify({
1278
- transport: options.transport,
1279
- command: options.command,
1280
- commandSource: options.commandSource ?? null,
1281
- managedCommandOrder: options.managedCommandOrder ?? "package-first",
1282
- managedComputerUsePluginNames: [...options.managedComputerUsePluginNames ?? []].toSorted(),
1283
- managedFallbackCommandPaths: [...options.managedFallbackCommandPaths ?? []],
1284
- args: options.args,
1285
- cwd: options.cwd ?? null,
1286
- url: options.url ?? null,
1287
- authToken: hashSecretForKey(options.authToken, "authToken"),
1288
- headers: Object.entries(options.headers).toSorted(([left], [right]) => left.localeCompare(right)).map(([key, value]) => [key, hashSecretForKey(value, `header:${key}`)]),
1289
- env: Object.entries(options.env ?? {}).toSorted(([left], [right]) => left.localeCompare(right)).map(([key, value]) => [key, hashSecretForKey(value, `env:${key}`)]),
1290
- clearEnv: [...options.clearEnv ?? []].toSorted(),
1291
- authProfileId: params.authProfileId ?? null,
1292
- authBindingFingerprint: params.authBindingFingerprint ?? null,
1293
- agentDir: params.agentDir ?? null,
1294
- fallbackApiKeyCacheKey: params.fallbackApiKeyCacheKey ?? null
1295
- });
1296
- }
1297
- function codexSandboxPolicyForTurn(mode, cwd, nativeArgs = []) {
1298
- if (mode === "danger-full-access") return { type: "dangerFullAccess" };
1299
- if (mode === "read-only") return {
1300
- type: "readOnly",
1301
- networkAccess: false
1302
- };
1303
- let excludeTmpdirEnvVar = false;
1304
- let excludeSlashTmp = false;
1305
- for (let index = 0; index < nativeArgs.length; index += 1) {
1306
- const arg = nativeArgs[index];
1307
- const override = arg === "-c" || arg === "--config" ? nativeArgs[++index] : arg?.startsWith("--config=") ? arg.slice(9) : void 0;
1308
- if (!override) continue;
1309
- const separator = override.indexOf("=");
1310
- if (separator < 0) continue;
1311
- const key = override.slice(0, separator).trim();
1312
- const value = override.slice(separator + 1).trim();
1313
- if (value !== "true" && value !== "false") continue;
1314
- if (key === "sandbox_workspace_write.exclude_tmpdir_env_var") excludeTmpdirEnvVar = value === "true";
1315
- else if (key === "sandbox_workspace_write.exclude_slash_tmp") excludeSlashTmp = value === "true";
1316
- }
1317
- return {
1318
- type: "workspaceWrite",
1319
- writableRoots: [cwd],
1320
- networkAccess: false,
1321
- excludeTmpdirEnvVar,
1322
- excludeSlashTmp
1323
- };
1324
- }
1325
- /** Resolves the passive supervision control connection without changing harness defaults. */
1326
- function resolveCodexSupervisionAppServerRuntimeOptions(params = {}) {
1327
- const pluginConfig = readCodexPluginConfig(params.pluginConfig);
1328
- const appServer = pluginConfig.appServer ?? {};
1329
- const transport = resolveTransport(appServer.transport);
1330
- const homeScope = appServer.homeScope ?? (transport === "websocket" ? "agent" : "user");
1331
- return resolveCodexAppServerRuntimeOptions({
1332
- ...params,
1333
- pluginConfig: {
1334
- ...pluginConfig,
1335
- appServer: {
1336
- ...appServer,
1337
- homeScope
1338
- }
1339
- }
1340
- });
1341
- }
1342
- //#endregion
1343
- //#region extensions/codex/src/app-server/session-binding.ts
1344
- /** SQLite-backed Codex app-server thread bindings. */
1345
- var session_binding_exports = /* @__PURE__ */ __exportAll({
1346
- CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS: () => CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS,
1347
- CODEX_APP_SERVER_BINDING_MAX_ENTRIES: () => CODEX_APP_SERVER_BINDING_MAX_ENTRIES,
1348
- CODEX_APP_SERVER_BINDING_NAMESPACE: () => CODEX_APP_SERVER_BINDING_NAMESPACE,
1349
- CodexSupervisionBindingReplacementError: () => CodexSupervisionBindingReplacementError,
1350
- assertCodexBindingMayBeReplaced: () => assertCodexBindingMayBeReplaced,
1351
- bindingStoreKey: () => bindingStoreKey,
1352
- createCodexAppServerBindingStore: () => createCodexAppServerBindingStore,
1353
- createCodexSessionGenerationSupersededError: () => createCodexSessionGenerationSupersededError,
1354
- createStoredCodexAppServerBinding: () => createStoredCodexAppServerBinding,
1355
- hashCodexAppServerBindingFingerprint: () => hashCodexAppServerBindingFingerprint,
1356
- isCodexAppServerNativeAuthProfile: () => isCodexAppServerNativeAuthProfile,
1357
- normalizeCodexAppServerBindingModelProvider: () => normalizeCodexAppServerBindingModelProvider,
1358
- normalizeStoredCodexAppServerBindingFingerprints: () => normalizeStoredCodexAppServerBindingFingerprints,
1359
- readCodexAppServerThreadBinding: () => readCodexAppServerThreadBinding,
1360
- readStoredCodexAppServerBinding: () => readStoredCodexAppServerBinding,
1361
- reclaimCurrentCodexSessionGeneration: () => reclaimCurrentCodexSessionGeneration,
1362
- resolveCodexAppServerBindingModelProvider: () => resolveCodexAppServerBindingModelProvider,
1363
- sessionBindingIdentity: () => sessionBindingIdentity
1364
- });
1365
- const CODEX_APP_SERVER_NATIVE_AUTH_PROVIDER = "openai";
1366
- const PUBLIC_OPENAI_MODEL_PROVIDER = "openai";
1367
- const BINDING_LEASE_RETRY_INTERVAL_MS = 1e3;
1368
- const BOUNDED_BINDING_FINGERPRINT_PATTERN = /^sha256:[a-f0-9]{64}$/i;
1369
- const CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS = 6e4;
1370
- const BINDING_LEASE_STALE_MS = 65e3;
1371
- const BINDING_LEASE_WAIT_MS = 7e4;
1372
- const BINDING_LEASE_RENEW_INTERVAL_MS = Math.floor(BINDING_LEASE_STALE_MS / 3);
1373
- const PHYSICAL_SESSION_RETIRE_TTL_MS = BINDING_LEASE_WAIT_MS;
1374
- /** Resolves the same agent scope OpenClaw uses for transcript/session ownership. */
1375
- function sessionBindingIdentity(params) {
1376
- const { sessionAgentId } = resolveSessionAgentIds$1(params);
1377
- const sessionKey = params.sessionKey?.trim();
1378
- return {
1379
- kind: "session",
1380
- agentId: sessionAgentId,
1381
- sessionId: params.sessionId,
1382
- ...sessionKey ? { sessionKey } : {}
1383
- };
1384
- }
1385
- /** Builds the terminal coordination error used when a newer OpenClaw session owns the binding. */
1386
- function createCodexSessionGenerationSupersededError(sessionId) {
1387
- return new AgentHarnessSessionSupersededError(`Codex session generation is no longer current: ${sessionId}`);
1388
- }
1389
- const optionalStringSchema = z.string().optional().catch(void 0);
1390
- const optionalBooleanSchema = z.boolean().optional().catch(void 0);
1391
- const optionalNonBlankStringSchema = z.string().refine((value) => Boolean(value.trim())).optional().catch(void 0);
1392
- const optionalTimestampSchema = z.string().refine((value) => Number.isFinite(Date.parse(value))).optional().catch(void 0);
1393
- const pendingSupervisionBranchSchema = z.object({
1394
- sourceThreadId: z.string().trim().min(1),
1395
- connectionFingerprint: z.string().trim().min(1).optional(),
1396
- lastTurnId: z.string().trim().min(1).optional(),
1397
- cleanupThreadIds: z.array(z.string().trim().min(1)).max(2).optional()
1398
- }).strict().superRefine((pending, context) => {
1399
- const cleanupThreadIds = pending.cleanupThreadIds ?? [];
1400
- if (new Set(cleanupThreadIds).size !== cleanupThreadIds.length) context.addIssue({
1401
- code: "custom",
1402
- message: "pending supervision cleanup thread ids must be unique"
1403
- });
1404
- if (cleanupThreadIds.includes(pending.sourceThreadId)) context.addIssue({
1405
- code: "custom",
1406
- message: "pending supervision cleanup cannot target its source"
1407
- });
1408
- });
1409
- const contextEngineProjectionSchema = z.object({
1410
- schemaVersion: z.literal(1),
1411
- mode: z.literal("thread_bootstrap"),
1412
- epoch: z.string().refine((value) => Boolean(value.trim())),
1413
- fingerprint: optionalStringSchema
1414
- }).strict();
1415
- const contextEngineSchema = z.object({
1416
- schemaVersion: z.literal(1),
1417
- engineId: z.string(),
1418
- policyFingerprint: z.string(),
1419
- projection: contextEngineProjectionSchema.optional().catch(void 0)
1420
- }).strict();
1421
- const destructiveApprovalModeSchema = z.enum([
1422
- "allow",
1423
- "deny",
1424
- "auto",
1425
- "ask"
1426
- ]).optional().catch(void 0);
1427
- const accountAppPolicyEntrySchema = z.object({
1428
- source: z.literal("account"),
1429
- appName: z.string(),
1430
- allowDestructiveActions: z.boolean(),
1431
- destructiveApprovalMode: destructiveApprovalModeSchema,
1432
- mcpServerNames: z.array(z.string())
1433
- }).strict();
1434
- const pluginAppPolicyEntrySchema = z.object({
1435
- source: z.literal("plugin").optional(),
1436
- configKey: z.string(),
1437
- marketplaceName: z.enum([CODEX_PLUGINS_MARKETPLACE_NAME, CODEX_PLUGINS_WORKSPACE_MARKETPLACE_NAME]),
1438
- pluginName: z.string(),
1439
- allowDestructiveActions: z.boolean(),
1440
- destructiveApprovalMode: destructiveApprovalModeSchema,
1441
- mcpServerNames: z.array(z.string())
1442
- }).strict();
1443
- const pluginAppPolicyContextSchema = z.object({
1444
- fingerprint: z.string(),
1445
- apps: z.record(z.string(), z.union([accountAppPolicyEntrySchema, pluginAppPolicyEntrySchema])),
1446
- pluginAppIds: z.record(z.string(), z.array(z.string())).default({})
1447
- }).strict();
1448
- const threadBindingSchema = z.object({
1449
- threadId: z.string().refine((value) => Boolean(value.trim())),
1450
- clientId: optionalStringSchema,
1451
- cwd: z.string(),
1452
- connectionScope: z.literal("supervision").optional(),
1453
- supervisionSourceThreadId: z.string().trim().min(1).optional(),
1454
- authProfileId: optionalStringSchema,
1455
- model: optionalStringSchema,
1456
- preserveNativeModel: z.literal(true).optional().catch(void 0),
1457
- pendingSupervisionBranch: pendingSupervisionBranchSchema.optional(),
1458
- modelProvider: z.string().transform((value) => value.trim()).pipe(z.string().min(1)).optional().catch(void 0),
1459
- approvalPolicy: z.preprocess((value) => value === "on-failure" ? "on-request" : value, z.enum([
1460
- "never",
1461
- "on-request",
1462
- "untrusted"
1463
- ]).optional()).catch(void 0),
1464
- sandbox: z.enum([
1465
- "read-only",
1466
- "workspace-write",
1467
- "danger-full-access"
1468
- ]).optional().catch(void 0),
1469
- serviceTier: z.preprocess(normalizeCodexServiceTier, z.custom((value) => typeof value === "string").optional()).optional().catch(void 0),
1470
- networkProxyProfileName: optionalStringSchema,
1471
- networkProxyConfigFingerprint: optionalStringSchema,
1472
- dynamicToolsFingerprint: optionalStringSchema,
1473
- dynamicToolsContainDeferred: optionalBooleanSchema,
1474
- webSearchThreadConfigFingerprint: optionalStringSchema,
1475
- userMcpServersFingerprint: optionalStringSchema,
1476
- mcpServersFingerprint: optionalStringSchema,
1477
- ringZeroConfigFingerprint: optionalStringSchema,
1478
- ringZeroClientInstanceId: optionalStringSchema,
1479
- nativeHookRelayGeneration: optionalNonBlankStringSchema,
1480
- appServerRuntimeFingerprint: optionalStringSchema,
1481
- pluginAppsFingerprint: optionalStringSchema,
1482
- pluginAppsInputFingerprint: optionalStringSchema,
1483
- pluginAppPolicyContext: pluginAppPolicyContextSchema.optional().catch(void 0),
1484
- contextEngine: contextEngineSchema.optional().catch(void 0),
1485
- environmentSelectionFingerprint: optionalStringSchema,
1486
- conversationStartId: optionalStringSchema,
1487
- conversationSourceTransferComplete: z.literal(true).optional().catch(void 0),
1488
- historyCoveredThrough: optionalTimestampSchema
1489
- }).superRefine((binding, context) => {
1490
- if (binding.connectionScope === "supervision") {
1491
- if (!binding.supervisionSourceThreadId) context.addIssue({
1492
- code: "custom",
1493
- message: "supervision connection ownership requires its native source thread id"
1494
- });
1495
- if (binding.preserveNativeModel !== true) context.addIssue({
1496
- code: "custom",
1497
- message: "supervision connection ownership requires native model ownership"
1498
- });
1499
- if (binding.conversationSourceTransferComplete !== true) context.addIssue({
1500
- code: "custom",
1501
- message: "supervision connection ownership requires a completed source transfer"
1502
- });
1503
- if (!binding.pendingSupervisionBranch && (!binding.model?.trim() || !binding.modelProvider)) context.addIssue({
1504
- code: "custom",
1505
- message: "materialized supervision bindings require a native model and provider"
1506
- });
1507
- }
1508
- if (binding.supervisionSourceThreadId && binding.connectionScope !== "supervision") context.addIssue({
1509
- code: "custom",
1510
- message: "a supervision source thread id requires supervision connection ownership"
1511
- });
1512
- if (!binding.pendingSupervisionBranch) return;
1513
- if (binding.threadId !== binding.pendingSupervisionBranch.sourceThreadId) context.addIssue({
1514
- code: "custom",
1515
- message: "pending supervision source must match the provisional thread binding"
1516
- });
1517
- if (binding.supervisionSourceThreadId !== binding.pendingSupervisionBranch.sourceThreadId) context.addIssue({
1518
- code: "custom",
1519
- message: "pending supervision source must match its durable source identity"
1520
- });
1521
- if (binding.preserveNativeModel !== true) context.addIssue({
1522
- code: "custom",
1523
- message: "pending supervision bindings must defer model selection to Codex App Server"
1524
- });
1525
- if (binding.connectionScope !== "supervision") context.addIssue({
1526
- code: "custom",
1527
- message: "pending supervision bindings require supervision connection ownership"
1528
- });
1529
- });
1530
- var CodexSupervisionBindingReplacementError = class extends Error {
1531
- constructor(threadId, operation) {
1532
- super(`Refusing to replace supervised Codex thread ${threadId} while ${operation}; its native user-home connection and model ownership must be preserved`);
1533
- this.name = "CodexSupervisionBindingReplacementError";
1534
- }
1535
- };
1536
- function assertCodexBindingMayBeReplaced(binding, operation) {
1537
- if (binding?.connectionScope === "supervision") throw new CodexSupervisionBindingReplacementError(binding.threadId, operation);
1538
- }
1539
- const bindingLeaseSchema = z.object({
1540
- token: z.string().refine((value) => Boolean(value.trim())),
1541
- expiresAt: z.number().finite()
1542
- });
1543
- const storedSessionIdSchema = z.string().transform((value) => value.trim()).pipe(z.string().min(1)).optional().catch(void 0);
1544
- const storedBindingSchema = z.discriminatedUnion("state", [z.object({
1545
- version: z.literal(1),
1546
- state: z.literal("active"),
1547
- binding: threadBindingSchema,
1548
- sessionId: storedSessionIdSchema,
1549
- lease: bindingLeaseSchema.optional().catch(void 0)
1550
- }), z.object({
1551
- version: z.literal(1),
1552
- state: z.literal("cleared"),
1553
- sessionId: storedSessionIdSchema,
1554
- lease: bindingLeaseSchema.optional().catch(void 0),
1555
- retired: z.literal(true).optional().catch(void 0)
1556
- })]);
1557
- function hashCodexAppServerBindingFingerprint(canonical) {
1558
- return `sha256:${createHash("sha256").update(canonical).digest("hex")}`;
1559
- }
1560
- function normalizeLegacyBindingFingerprint(value) {
1561
- if (typeof value !== "string" || value === "" || value === "[]" || BOUNDED_BINDING_FINGERPRINT_PATTERN.test(value)) return value;
1562
- return hashCodexAppServerBindingFingerprint(value);
1563
- }
1564
- function normalizeLegacyBindingFingerprints(record) {
1565
- let normalized = record;
1566
- for (const key of ["dynamicToolsFingerprint", "userMcpServersFingerprint"]) {
1567
- const value = record[key];
1568
- const next = normalizeLegacyBindingFingerprint(value);
1569
- if (next === value) continue;
1570
- if (normalized === record) normalized = { ...record };
1571
- normalized[key] = next;
1572
- }
1573
- return normalized;
1574
- }
1575
- function normalizeStoredCodexAppServerBindingFingerprints(value) {
1576
- const stored = readStoredCodexAppServerBinding(value);
1577
- if (!stored || stored.state !== "active") return stored;
1578
- const binding = normalizeLegacyBindingFingerprints(stored.binding);
1579
- return binding === stored.binding ? stored : readStoredCodexAppServerBinding({
1580
- ...stored,
1581
- binding
1582
- });
1583
- }
1584
- /** Encodes a migrated sidecar binding as one canonical plugin-state row. */
1585
- function createStoredCodexAppServerBinding(value, options = {}) {
1586
- const rawRecord = asRecord(value);
1587
- if (!rawRecord) return;
1588
- const record = normalizeLegacyBindingFingerprints(rawRecord);
1589
- if (record.schemaVersion !== 1 && record.schemaVersion !== 2) return;
1590
- const pluginAppPolicyContext = readPluginAppPolicyContext(record.pluginAppPolicyContext, record.schemaVersion);
1591
- const historyCoveredThrough = readTimestamp(record.historyCoveredThrough) ?? readTimestamp(record.updatedAt) ?? readTimestamp(record.createdAt) ?? readTimestamp(options.now) ?? (/* @__PURE__ */ new Date()).toISOString();
1592
- const authProfileId = typeof record.authProfileId === "string" ? record.authProfileId : void 0;
1593
- const binding = readCodexAppServerThreadBinding({
1594
- ...record,
1595
- modelProvider: normalizeCodexAppServerBindingModelProvider({
1596
- ...options.lookup,
1597
- authProfileId,
1598
- modelProvider: typeof record.modelProvider === "string" ? record.modelProvider : void 0
1599
- }),
1600
- cwd: typeof record.cwd === "string" ? record.cwd : "",
1601
- pluginAppPolicyContext,
1602
- historyCoveredThrough
1603
- });
1604
- return binding ? {
1605
- version: 1,
1606
- state: "active",
1607
- binding: stripUndefinedBinding(binding)
1608
- } : void 0;
1609
- }
1610
- function bindingLeaseLostError(key, cause) {
1611
- return new Error(`Lost Codex binding lease: ${key}`, cause === void 0 ? void 0 : { cause });
1612
- }
1613
- /** Lets the authoritative OpenClaw session generation claim a stale stable binding row. */
1614
- async function reclaimCurrentCodexSessionGeneration(params) {
1615
- const sessionKey = params.identity.sessionKey?.trim();
1616
- if (!sessionKey) return true;
1617
- const plan = await params.bindingStore.prepareSessionGenerationReclaim(params.identity);
1618
- if (plan.kind === "resolved") return plan.result;
1619
- try {
1620
- const storePath = resolveStorePath(params.config?.session?.store, { agentId: params.identity.agentId });
1621
- if (getSessionEntry({
1622
- agentId: params.identity.agentId,
1623
- hydrateSkillPromptRefs: false,
1624
- readConsistency: "latest",
1625
- sessionKey,
1626
- storePath
1627
- })?.sessionId !== params.identity.sessionId) return false;
1628
- } catch {
1629
- return false;
1630
- }
1631
- return await params.bindingStore.mutate(params.identity, {
1632
- kind: "reclaim-generation",
1633
- expectedPreviousSessionId: plan.expectedPreviousSessionId
1634
- });
1635
- }
1636
- /** Creates the single binding facade owned by the Codex plugin runtime. */
1637
- function createCodexAppServerBindingStore(state) {
1638
- const update = state.update?.bind(state);
1639
- if (!update) throw new Error("Codex app-server bindings require atomic plugin-state updates");
1640
- const leaseContext = new AsyncLocalStorage();
1641
- const archiveContext = new AsyncLocalStorage();
1642
- let activeBindingMutations = 0;
1643
- let pendingArchives = 0;
1644
- let archiveTail = Promise.resolve();
1645
- let bindingMutationsDrained = [];
1646
- const waitForBindingMutations = async () => {
1647
- if (activeBindingMutations === 0) return;
1648
- await new Promise((resolve) => {
1649
- bindingMutationsDrained.push(resolve);
1650
- });
1651
- };
1652
- const runBindingMutation = async (run) => {
1653
- if (archiveContext.getStore() === true) return await run();
1654
- if (pendingArchives > 0) throw new Error("Codex binding mutation blocked while a native archive is in progress; retry");
1655
- activeBindingMutations += 1;
1656
- try {
1657
- return await run();
1658
- } finally {
1659
- activeBindingMutations -= 1;
1660
- if (activeBindingMutations === 0) {
1661
- const drained = bindingMutationsDrained;
1662
- bindingMutationsDrained = [];
1663
- for (const resolve of drained) resolve();
1664
- }
1665
- }
1666
- };
1667
- const renewLease = (key, owner) => {
1668
- if (owner.failure) return;
1669
- try {
1670
- let renewed = false;
1671
- const stored = update(key, (raw) => {
1672
- const current = readStoredCodexAppServerBinding(raw);
1673
- if (raw !== void 0 && !current) throw new Error(`Invalid Codex app-server binding row: ${key}`);
1674
- const lease = current?.lease;
1675
- const now = Date.now();
1676
- if (!lease || lease.token !== owner.token || lease.expiresAt <= now) return;
1677
- renewed = true;
1678
- return {
1679
- ...current,
1680
- lease: {
1681
- token: owner.token,
1682
- expiresAt: now + BINDING_LEASE_STALE_MS
1683
- }
1684
- };
1685
- });
1686
- if (!renewed || !stored) owner.failure = bindingLeaseLostError(key);
1687
- } catch (error) {
1688
- owner.failure = bindingLeaseLostError(key, error);
1689
- }
1690
- };
1691
- const transactKey = async (key, apply, ttlMs) => {
1692
- const deadline = Date.now() + BINDING_LEASE_WAIT_MS;
1693
- while (true) {
1694
- let busy = false;
1695
- let leaseLost = false;
1696
- let result;
1697
- const ownedLease = leaseContext.getStore()?.get(key);
1698
- if (ownedLease?.failure) throw ownedLease.failure;
1699
- const ownedToken = ownedLease?.token;
1700
- update(key, (raw) => {
1701
- const current = readStoredCodexAppServerBinding(raw);
1702
- if (raw !== void 0 && !current) throw new Error(`Invalid Codex app-server binding row: ${key}`);
1703
- const activeLease = current?.lease;
1704
- const now = Date.now();
1705
- if (ownedToken && (!activeLease || activeLease.token !== ownedToken || activeLease.expiresAt <= now)) {
1706
- leaseLost = true;
1707
- return;
1708
- }
1709
- if (activeLease && activeLease.token !== ownedToken && activeLease.expiresAt > now) {
1710
- busy = true;
1711
- return;
1712
- }
1713
- const applied = apply(current, ownedToken);
1714
- result = applied.result;
1715
- return applied.next;
1716
- }, ttlMs == null ? void 0 : { ttlMs });
1717
- if (leaseLost) {
1718
- const failure = bindingLeaseLostError(key);
1719
- if (ownedLease) ownedLease.failure = failure;
1720
- throw failure;
1721
- }
1722
- if (!busy) return result;
1723
- if (Date.now() >= deadline) throw new Error(`Timed out waiting for Codex binding lease: ${key}`);
1724
- await sleep(BINDING_LEASE_RETRY_INTERVAL_MS);
1725
- }
1726
- };
1727
- return {
1728
- async read(identity) {
1729
- const key = bindingStoreKey(identity);
1730
- const raw = state.lookup(key);
1731
- const stored = readStoredCodexAppServerBinding(raw);
1732
- if (raw !== void 0 && !stored) throw new Error(`Invalid Codex app-server binding row: ${key}`);
1733
- return stored?.state === "active" && ownsStoredSessionGeneration(identity, stored) ? stored.binding : void 0;
1734
- },
1735
- async hasOtherThreadOwner(threadId, currentIdentity) {
1736
- const currentKey = currentIdentity ? bindingStoreKey(currentIdentity) : void 0;
1737
- return state.entries().some(({ key, value }) => {
1738
- const stored = readStoredCodexAppServerBinding(value);
1739
- if (!stored) throw new Error(`Invalid Codex app-server binding row: ${key}`);
1740
- const isCurrentOwner = currentIdentity !== void 0 && key === currentKey && (currentIdentity.kind === "conversation" || stored.sessionId === currentIdentity.sessionId.trim());
1741
- if (stored.state !== "active" || stored.binding.threadId !== threadId || isCurrentOwner) return false;
1742
- return true;
1743
- });
1744
- },
1745
- async prepareSessionGenerationReclaim(identity) {
1746
- const key = bindingStoreKey(identity);
1747
- const raw = state.lookup(key);
1748
- const current = readStoredCodexAppServerBinding(raw);
1749
- if (raw !== void 0 && !current) throw new Error(`Invalid Codex app-server binding row: ${key}`);
1750
- if (!current) return {
1751
- kind: "resolved",
1752
- result: true
1753
- };
1754
- const currentSessionId = current.sessionId;
1755
- if (!currentSessionId) return {
1756
- kind: "resolved",
1757
- result: current.state !== "cleared" || current.retired !== true
1758
- };
1759
- if (currentSessionId === identity.sessionId) return current.state === "cleared" && current.retired === true ? {
1760
- kind: "verify",
1761
- expectedPreviousSessionId: currentSessionId
1762
- } : {
1763
- kind: "resolved",
1764
- result: true
1765
- };
1766
- return {
1767
- kind: "verify",
1768
- expectedPreviousSessionId: currentSessionId
1769
- };
1770
- },
1771
- async mutate(identity, mutation) {
1772
- return await runBindingMutation(async () => {
1773
- const key = bindingStoreKey(identity);
1774
- const retainLegacyClear = mutation.kind === "clear" && key.startsWith("conversation:legacy-");
1775
- return await transactKey(key, (current, leaseToken) => {
1776
- const ownsGeneration = ownsStoredSessionGeneration(identity, current);
1777
- const ownedLease = current?.lease && current.lease.token === leaseToken ? { lease: current.lease } : {};
1778
- if (mutation.kind === "reclaim-generation") {
1779
- if (identity.kind !== "session" || !identity.sessionKey?.trim()) return { result: false };
1780
- if (!current) return { result: true };
1781
- if (ownsGeneration) {
1782
- if (current.state === "cleared" && current.retired === true && current.sessionId === mutation.expectedPreviousSessionId) return {
1783
- result: true,
1784
- next: {
1785
- version: 1,
1786
- state: "cleared",
1787
- sessionId: identity.sessionId,
1788
- ...ownedLease
1789
- }
1790
- };
1791
- return { result: current.state !== "cleared" || current.retired !== true };
1792
- }
1793
- if (current.sessionId !== mutation.expectedPreviousSessionId) return { result: false };
1794
- if (current.state === "active" && current.binding.connectionScope === "supervision") return { result: false };
1795
- return {
1796
- result: true,
1797
- next: {
1798
- version: 1,
1799
- state: "cleared",
1800
- sessionId: identity.sessionId,
1801
- ...ownedLease
1802
- }
1803
- };
1804
- }
1805
- const storedActive = current?.state === "active" ? current : void 0;
1806
- const active = ownsGeneration ? storedActive : void 0;
1807
- const retiredGeneration = current?.state === "cleared" && current.retired === true && ownsGeneration;
1808
- const preservesSupervisionOwner = mutation.kind === "set" && active?.binding.connectionScope === "supervision" && isSameSupervisionOwner(active.binding, mutation.binding);
1809
- const clearsPendingSupervisionOwner = mutation.kind === "clear" && active?.binding.connectionScope === "supervision" && matchesPendingSupervisionClear(active.binding, mutation.threadId, mutation.expectedPendingSupervisionBranch);
1810
- if (mutation.kind === "set" && (mutation.if?.kind === "absent" && storedActive || current !== void 0 && !ownsGeneration || retiredGeneration || active?.binding.connectionScope === "supervision" && !preservesSupervisionOwner) || mutation.kind === "patch" && active?.binding.threadId !== mutation.threadId || (mutation.kind === "patch-pending-supervision-branch" || mutation.kind === "commit-pending-supervision-branch") && !matchesPendingSupervisionBranch(active?.binding, mutation.expected) || mutation.kind === "clear" && (mutation.threadId !== void 0 && active?.binding.threadId !== mutation.threadId || !ownsGeneration || active?.binding.connectionScope === "supervision" && !clearsPendingSupervisionOwner)) return { result: false };
1811
- if (mutation.kind === "clear" && retiredGeneration) return { result: true };
1812
- if (mutation.kind === "clear") return {
1813
- result: true,
1814
- next: {
1815
- version: 1,
1816
- state: "cleared",
1817
- ...storedSessionGeneration(identity, current),
1818
- ...ownedLease
1819
- }
1820
- };
1821
- let binding;
1822
- if (mutation.kind === "set") binding = validateBindingForWrite(mutation.binding);
1823
- else if (mutation.kind === "patch-pending-supervision-branch") binding = validateBindingForWrite({
1824
- ...active.binding,
1825
- pendingSupervisionBranch: mutation.pending
1826
- });
1827
- else if (mutation.kind === "commit-pending-supervision-branch") binding = validateBindingForWrite({
1828
- ...active.binding,
1829
- ...mutation.patch,
1830
- threadId: mutation.threadId,
1831
- pendingSupervisionBranch: void 0
1832
- });
1833
- else binding = validateBindingForWrite({
1834
- ...active.binding,
1835
- ...mutation.patch,
1836
- threadId: mutation.threadId
1837
- });
1838
- return {
1839
- result: true,
1840
- next: {
1841
- version: 1,
1842
- state: "active",
1843
- binding,
1844
- ...storedSessionGeneration(identity, current),
1845
- ...ownedLease
1846
- }
1847
- };
1848
- }, mutation.kind === "clear" && !retainLegacyClear && !leaseContext.getStore()?.has(key) ? 1 : void 0);
1849
- });
1850
- },
1851
- async adoptSessionGeneration(identity, expectedPreviousSessionId) {
1852
- return await runBindingMutation(async () => {
1853
- const key = bindingStoreKey(identity);
1854
- const expectedSessionId = expectedPreviousSessionId.trim();
1855
- const targetSessionId = identity.sessionId.trim();
1856
- if (!expectedSessionId) throw new Error("Codex session generation adoption requires the previous session id");
1857
- return await transactKey(key, (current) => {
1858
- if (current?.state !== "active") return { result: "absent" };
1859
- if (current.sessionId === targetSessionId) return { result: "current" };
1860
- if (current.sessionId !== expectedSessionId) return { result: "conflict" };
1861
- return {
1862
- result: "adopted",
1863
- next: {
1864
- ...current,
1865
- sessionId: targetSessionId
1866
- }
1867
- };
1868
- });
1869
- });
1870
- },
1871
- async resetSessionGeneration(identity) {
1872
- return await runBindingMutation(async () => {
1873
- const key = bindingStoreKey(identity);
1874
- return await transactKey(key, (current, leaseToken) => {
1875
- if (!current) return { result: "absent" };
1876
- if (!ownsStoredSessionGeneration(identity, current)) return { result: "conflict" };
1877
- if (current.state === "cleared" && current.retired === true) return { result: "conflict" };
1878
- return {
1879
- result: "applied",
1880
- next: {
1881
- version: 1,
1882
- state: "cleared",
1883
- ...storedSessionGeneration(identity, current),
1884
- ...current.lease && current.lease.token === leaseToken ? { lease: current.lease } : {}
1885
- }
1886
- };
1887
- }, leaseContext.getStore()?.has(key) ? void 0 : 1);
1888
- });
1889
- },
1890
- async retireSessionGeneration(identity) {
1891
- return await runBindingMutation(async () => {
1892
- const key = bindingStoreKey(identity);
1893
- return await transactKey(key, (current, leaseToken) => {
1894
- if (!current) return { result: "absent" };
1895
- if (!ownsStoredSessionGeneration(identity, current)) return { result: "conflict" };
1896
- if (current.state === "cleared" && current.retired === true) return { result: "applied" };
1897
- return {
1898
- result: "applied",
1899
- next: {
1900
- version: 1,
1901
- state: "cleared",
1902
- retired: true,
1903
- ...storedSessionGeneration(identity, current),
1904
- ...current.lease && current.lease.token === leaseToken ? { lease: current.lease } : {}
1905
- }
1906
- };
1907
- }, identity.sessionKey?.trim() ? void 0 : PHYSICAL_SESSION_RETIRE_TTL_MS);
1908
- });
1909
- },
1910
- async withThreadArchiveFence(run) {
1911
- pendingArchives += 1;
1912
- const operation = archiveTail.then(async () => {
1913
- await waitForBindingMutations();
1914
- return await archiveContext.run(true, run);
1915
- });
1916
- archiveTail = operation.then(() => void 0, () => void 0);
1917
- try {
1918
- return await operation;
1919
- } finally {
1920
- pendingArchives -= 1;
1921
- }
1922
- },
1923
- async withLease(identity, run) {
1924
- const key = bindingStoreKey(identity);
1925
- const owned = leaseContext.getStore();
1926
- const existingOwner = owned?.get(key);
1927
- if (existingOwner) {
1928
- const failureBeforeRun = existingOwner.failure;
1929
- if (failureBeforeRun) throw failureBeforeRun;
1930
- const result = await run();
1931
- const failureAfterRun = existingOwner.failure;
1932
- if (failureAfterRun) throw failureAfterRun;
1933
- return result;
1934
- }
1935
- const token = randomUUID();
1936
- if (!await transactKey(key, (current) => {
1937
- if (current?.state === "cleared" && current.retired === true && ownsStoredSessionGeneration(identity, current)) return { result: false };
1938
- const lease = {
1939
- token,
1940
- expiresAt: Date.now() + BINDING_LEASE_STALE_MS
1941
- };
1942
- if (current?.state === "active") return {
1943
- result: true,
1944
- next: {
1945
- ...current,
1946
- ...preservedSessionGeneration(identity, current),
1947
- lease
1948
- }
1949
- };
1950
- if (current?.state === "cleared" && current.retired === true) return {
1951
- result: true,
1952
- next: {
1953
- ...current,
1954
- lease
1955
- }
1956
- };
1957
- return {
1958
- result: true,
1959
- next: {
1960
- version: 1,
1961
- state: "cleared",
1962
- ...preservedSessionGeneration(identity, current),
1963
- lease
1964
- }
1965
- };
1966
- })) throw new Error(`Codex binding generation was retired: ${key}`);
1967
- const owner = { token };
1968
- const nested = new Map(owned);
1969
- nested.set(key, owner);
1970
- const heartbeat = setInterval(() => renewLease(key, owner), BINDING_LEASE_RENEW_INTERVAL_MS);
1971
- heartbeat.unref();
1972
- try {
1973
- const result = await leaseContext.run(nested, run);
1974
- if (owner.failure) throw owner.failure;
1975
- return result;
1976
- } finally {
1977
- clearInterval(heartbeat);
1978
- try {
1979
- const removeOwnedLease = (raw, matches) => {
1980
- const current = readStoredCodexAppServerBinding(raw);
1981
- if (!current || !matches(current) || current.lease?.token !== token) return;
1982
- const { lease: _lease, ...released } = current;
1983
- return released;
1984
- };
1985
- if (!update(key, (raw) => removeOwnedLease(raw, (current) => current.state === "active"))) {
1986
- if (!update(key, (raw) => removeOwnedLease(raw, (current) => current.state === "cleared" && current.retired === true), key.startsWith("session:") ? { ttlMs: PHYSICAL_SESSION_RETIRE_TTL_MS } : void 0)) update(key, (raw) => removeOwnedLease(raw, (current) => current.state === "cleared"), { ttlMs: 1 });
1987
- }
1988
- } catch (error) {
1989
- embeddedAgentLog.warn("failed to release codex app-server binding lease", {
1990
- key,
1991
- error
1992
- });
1993
- }
1994
- }
1995
- }
1996
- };
1997
- }
1998
- function matchesPendingSupervisionBranch(binding, expected) {
1999
- const pending = binding?.pendingSupervisionBranch;
2000
- if (!pending || binding?.threadId !== expected.sourceThreadId) return false;
2001
- if (pending.sourceThreadId !== expected.sourceThreadId || pending.connectionFingerprint !== expected.connectionFingerprint || pending.lastTurnId !== expected.lastTurnId) return false;
2002
- const currentCleanup = pending.cleanupThreadIds ?? [];
2003
- const expectedCleanup = expected.cleanupThreadIds ?? [];
2004
- return currentCleanup.length === expectedCleanup.length && currentCleanup.every((threadId, index) => threadId === expectedCleanup[index]);
2005
- }
2006
- function isSameSupervisionOwner(current, replacement) {
2007
- return replacement.connectionScope === "supervision" && replacement.threadId === current.threadId && replacement.supervisionSourceThreadId === current.supervisionSourceThreadId;
2008
- }
2009
- function matchesPendingSupervisionClear(binding, threadId, expected) {
2010
- if (!expected) return false;
2011
- const sourceThreadId = expected.sourceThreadId;
2012
- return threadId === sourceThreadId && binding.supervisionSourceThreadId === sourceThreadId && matchesPendingSupervisionBranch(binding, expected);
2013
- }
2014
- /** Stable plugin-state key for one current binding owner. */
2015
- function bindingStoreKey(identity) {
2016
- if (identity.kind === "session") {
2017
- const rawAgentId = identity.agentId.trim();
2018
- const sessionId = identity.sessionId.trim();
2019
- if (!rawAgentId) throw new Error("Codex app-server binding requires an agent id");
2020
- if (!sessionId) throw new Error("Codex app-server binding requires a session id");
2021
- const agentId = resolveSessionAgentIds$1({ agentId: rawAgentId }).sessionAgentId;
2022
- const sessionKey = identity.sessionKey?.trim();
2023
- if (sessionKey) return `session-key:${agentId}:${createHash("sha256").update(sessionKey).digest("base64url")}`;
2024
- return `session:${agentId}:${sessionId}`;
2025
- }
2026
- const bindingId = identity.bindingId.trim();
2027
- if (!bindingId) throw new Error("Codex app-server conversation binding requires a binding id");
2028
- return `conversation:${bindingId}`;
2029
- }
2030
- function readStoredCodexAppServerBinding(value) {
2031
- const result = storedBindingSchema.safeParse(value);
2032
- return result.success ? stripUndefinedValue(result.data) : void 0;
2033
- }
2034
- function storedSessionGeneration(identity, current) {
2035
- if (identity.kind === "session") return { sessionId: identity.sessionId };
2036
- return current?.sessionId ? { sessionId: current.sessionId } : {};
2037
- }
2038
- function preservedSessionGeneration(identity, current) {
2039
- if (current?.sessionId) return { sessionId: current.sessionId };
2040
- return storedSessionGeneration(identity, current);
2041
- }
2042
- function ownsStoredSessionGeneration(identity, current) {
2043
- return identity.kind !== "session" || !current?.sessionId || current.sessionId === identity.sessionId;
2044
- }
2045
- function validateBindingForWrite(binding) {
2046
- const validated = readCodexAppServerThreadBinding(binding);
2047
- if (!validated) throw new Error("Invalid Codex app-server thread binding");
2048
- return stripUndefinedBinding(validated);
2049
- }
2050
- /** Parses stored or shipped sidecar data into the current domain value. */
2051
- function readCodexAppServerThreadBinding(value) {
2052
- const result = threadBindingSchema.safeParse(value);
2053
- if (!result.success) return;
2054
- return result.data;
2055
- }
2056
- function stripUndefinedBinding(binding) {
2057
- return stripUndefinedValue(binding);
2058
- }
2059
- function stripUndefinedValue(value) {
2060
- if (Array.isArray(value)) return value.map(stripUndefinedValue);
2061
- if (!value || typeof value !== "object") return value;
2062
- return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== void 0).map(([key, entry]) => [key, stripUndefinedValue(entry)]));
2063
- }
2064
- function asRecord(value) {
2065
- return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
2066
- }
2067
- function readTimestamp(value) {
2068
- return optionalTimestampSchema.parse(value);
2069
- }
2070
- function readPluginAppPolicyContext(value, bindingSchemaVersion) {
2071
- const record = asRecord(value);
2072
- if (!record || typeof record.fingerprint !== "string") return;
2073
- const apps = asRecord(record.apps);
2074
- if (!apps) return;
2075
- const parsedApps = {};
2076
- for (const [appId, rawEntry] of Object.entries(apps)) {
2077
- const entry = asRecord(rawEntry);
2078
- if (!entry) return;
2079
- const destructiveApprovalMode = readDestructiveApprovalMode(entry.destructiveApprovalMode, bindingSchemaVersion);
2080
- const mcpServerNamesValid = Array.isArray(entry.mcpServerNames) && entry.mcpServerNames.every((serverName) => typeof serverName === "string");
2081
- if (entry.source === "account") {
2082
- if ("appId" in entry || typeof entry.appName !== "string" || typeof entry.allowDestructiveActions !== "boolean" || destructiveApprovalMode === "invalid" || !mcpServerNamesValid) return;
2083
- parsedApps[appId] = {
2084
- source: "account",
2085
- appName: entry.appName,
2086
- allowDestructiveActions: entry.allowDestructiveActions,
2087
- ...destructiveApprovalMode ? { destructiveApprovalMode } : {},
2088
- mcpServerNames: entry.mcpServerNames
2089
- };
2090
- continue;
2091
- }
2092
- if ("appId" in entry || entry.source !== void 0 && entry.source !== "plugin" || typeof entry.configKey !== "string" || entry.marketplaceName !== "openai-curated" && entry.marketplaceName !== "workspace-directory" || typeof entry.pluginName !== "string" || typeof entry.allowDestructiveActions !== "boolean" || destructiveApprovalMode === "invalid" || !mcpServerNamesValid) return;
2093
- parsedApps[appId] = {
2094
- configKey: entry.configKey,
2095
- marketplaceName: entry.marketplaceName,
2096
- pluginName: entry.pluginName,
2097
- allowDestructiveActions: entry.allowDestructiveActions,
2098
- ...destructiveApprovalMode ? { destructiveApprovalMode } : {},
2099
- mcpServerNames: entry.mcpServerNames
2100
- };
2101
- }
2102
- const parsedPluginAppIds = {};
2103
- if (record.pluginAppIds !== void 0 && (!record.pluginAppIds || typeof record.pluginAppIds !== "object" || Array.isArray(record.pluginAppIds))) return;
2104
- if (record.pluginAppIds && typeof record.pluginAppIds === "object") for (const [configKey, appIds] of Object.entries(record.pluginAppIds)) {
2105
- if (!Array.isArray(appIds) || appIds.some((appId) => typeof appId !== "string")) return;
2106
- parsedPluginAppIds[configKey] = appIds;
2107
- }
2108
- return {
2109
- fingerprint: record.fingerprint,
2110
- apps: parsedApps,
2111
- pluginAppIds: parsedPluginAppIds
2112
- };
2113
- }
2114
- function readDestructiveApprovalMode(value, bindingSchemaVersion) {
2115
- if (value === void 0) return;
2116
- if (value === "allow" || value === "deny") return value;
2117
- if (value === "auto") return bindingSchemaVersion === 1 ? "allow" : "auto";
2118
- if (value === "ask" && bindingSchemaVersion === 2) return "ask";
2119
- if (value === "on-request" && bindingSchemaVersion === 1) return "auto";
2120
- return "invalid";
2121
- }
2122
- function sleep(ms) {
2123
- return new Promise((resolve) => {
2124
- setTimeout(resolve, ms);
2125
- });
2126
- }
2127
- /** Returns true when an auth profile uses native Codex/OpenAI app-server auth. */
2128
- function isCodexAppServerNativeAuthProfile(lookup) {
2129
- const authProfileId = lookup.authProfileId?.trim();
2130
- if (!authProfileId) return false;
2131
- try {
2132
- const credential = (lookup.authProfileStore ?? ensureAuthProfileStore(lookup.agentDir?.trim() || resolveDefaultAgentDir(lookup.config ?? {}), {
2133
- allowKeychainPrompt: false,
2134
- config: lookup.config,
2135
- externalCliProviderIds: [CODEX_APP_SERVER_NATIVE_AUTH_PROVIDER],
2136
- externalCliProfileIds: [authProfileId]
2137
- })).profiles[authProfileId];
2138
- if (!credential || credential.type === "api_key") return false;
2139
- const provider = credential.provider?.trim();
2140
- return Boolean(provider && resolveProviderIdForAuth(provider, { config: lookup.config }) === CODEX_APP_SERVER_NATIVE_AUTH_PROVIDER);
2141
- } catch (error) {
2142
- embeddedAgentLog.debug("failed to resolve codex app-server auth profile provider", {
2143
- authProfileId,
2144
- error
2145
- });
2146
- return false;
2147
- }
2148
- }
2149
- /** Hides redundant OpenAI provider attribution for native Codex auth bindings. */
2150
- function normalizeCodexAppServerBindingModelProvider(params) {
2151
- const modelProvider = params.modelProvider?.trim();
2152
- if (!modelProvider) return;
2153
- if (isCodexAppServerNativeAuthProfile(params) && modelProvider.toLowerCase() === PUBLIC_OPENAI_MODEL_PROVIDER) return;
2154
- return modelProvider;
2155
- }
2156
- /** Restores the sole provider intentionally omitted from canonical binding rows. */
2157
- function resolveCodexAppServerBindingModelProvider(params) {
2158
- return params.modelProvider?.trim() || (isCodexAppServerNativeAuthProfile(params) ? PUBLIC_OPENAI_MODEL_PROVIDER : void 0);
2159
- }
2160
- //#endregion
2161
- export { CODEX_PLUGINS_WORKSPACE_MARKETPLACE_NAME as A, isCodexAppServerApprovalPolicyAllowedByRequirements as C, resolveOpenClawExecPolicyForCodexAppServer as D, resolveCodexPluginsPolicy as E, isCodexFastServiceTier as O, resolveCodexModelBackedReviewerPolicyContext as S, readCodexPluginConfig as T, assertCodexAppServerConnectionSecurity as _, hashCodexAppServerBindingFingerprint as a, canUseCodexModelBackedApprovalsReviewerForModel as b, reclaimCurrentCodexSessionGeneration as c, codexAppServerStartOptionsKey as d, codexSandboxPolicyForTurn as f, resolveCodexSupervisionAppServerRuntimeOptions as g, resolveCodexComputerUseConfig as h, createCodexSessionGenerationSupersededError as i, CODEX_PLUGINS_MARKETPLACE_NAME as k, sessionBindingIdentity as l, resolveCodexAppServerStartOptionsForAgent as m, assertCodexBindingMayBeReplaced as n, isCodexAppServerNativeAuthProfile as o, resolveCodexAppServerRuntimeOptions as p, bindingStoreKey as r, normalizeCodexAppServerBindingModelProvider as s, CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS as t, session_binding_exports as u, shouldAutoApproveCodexAppServerApprovals as v, isCodexSandboxExecServerEnabled as w, resolveCodexAppServerUserHomeDir as x, withMcpElicitationsApprovalPolicy as y };