@openclaw/codex 2026.8.1-beta.2 → 2026.9.1-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/dist/api.js +147 -0
  2. package/dist/{attempt-client-cleanup-DMLXUfa8.js → attempt-client-cleanup-bfsmcQ6m.js} +21 -2
  3. package/dist/{binding-connection-I5Bo-AsX.js → binding-connection-BMvPX73o.js} +15 -3
  4. package/dist/{bounded-turn-qgZmzy_4.js → bounded-turn-B7iBUcuP.js} +22 -16
  5. package/dist/{capabilities-CybGI1oz.js → capabilities-BRMh0aIq.js} +1 -1
  6. package/dist/cli-metadata.js +1 -1
  7. package/dist/{command-formatters-B1AEz8ZA.js → command-formatters-DEsIufkt.js} +2 -2
  8. package/dist/{command-handlers-Db8pu_ds.js → command-handlers-D_-1_qRp.js} +65 -37
  9. package/dist/command-rpc-CCeCkf_v.js +90 -0
  10. package/dist/{compact-LspQaGfl.js → compact-BglNFZrQ.js} +35 -29
  11. package/dist/{session-binding-DPxIvMgE.js → config-giW8X0QA.js} +108 -914
  12. package/dist/context-compaction-activity-BOeJf7yo.js +58 -0
  13. package/dist/doctor-contract-api.js +23 -21
  14. package/dist/{dynamic-tools-BVdyWkUD.js → dynamic-tools-Dnlfa--w.js} +1345 -1424
  15. package/dist/{effective-mcp-catalog-DIIhAtOZ.js → effective-mcp-catalog-CTeGrnfO.js} +2 -2
  16. package/dist/elicitation-input-DMkeki8d.js +71 -0
  17. package/dist/{event-projector-assistant-message-BwxV4d6N.js → event-projector-assistant-message-C5-Ds8mA.js} +18 -1
  18. package/dist/{event-projector-usage-e5huIQWu.js → event-projector-usage-Bk1I90Bg.js} +18 -18
  19. package/dist/harness-Csz0F-DK.js +258 -0
  20. package/dist/harness.js +2 -226
  21. package/dist/index.js +262 -181
  22. package/dist/{isolated-completion-C58NbL40.js → isolated-completion-Cv6FqygM.js} +4 -4
  23. package/dist/managed-binary-DFYK4DWq.js +248 -0
  24. package/dist/media-understanding-provider.js +2 -2
  25. package/dist/model-catalog-i9rNBthX.js +48 -0
  26. package/dist/{models-BFlpn1Ex.js → models-TS3HBU-q.js} +4 -3
  27. package/dist/{native-subagent-monitor-DyTGmTUx.js → native-subagent-monitor-4Mfq2HDs.js} +354 -83
  28. package/dist/node-exec-server.runtime-BpWqJO1V.js +192 -0
  29. package/dist/{plugin-app-cache-key-C3H2CVp6.js → plugin-app-cache-key-C1CAdfcP.js} +19 -4
  30. package/dist/plugin-approval-roundtrip-bUm777tR.js +95 -0
  31. package/dist/{plugin-marketplace-discovery-CzrGJdCR.js → plugin-marketplace-discovery-B9DvaAG-.js} +59 -54
  32. package/dist/{plugin-metadata-cache-CNJPj4_b.js → plugin-metadata-cache-CTCT3w5L.js} +164 -134
  33. package/dist/{protocol-validators-B4F7L8Rf.js → protocol-validators-VeJxxJ0U.js} +80 -5
  34. package/dist/{rate-limits-DZXmOL8-.js → rate-limits-C5_D8Gmb.js} +1 -1
  35. package/dist/{request-BRl5_UfX.js → request-DXXGHko0.js} +2 -2
  36. package/dist/{run-attempt-P8BdxC1I.js → run-attempt-DYc0QCBF.js} +1276 -765
  37. package/dist/{runtime-artifact-BVSPdd6g.js → runtime-artifact-BvyT1uyd.js} +4 -7
  38. package/dist/{sandbox-guard-Cmwc9eIk.js → sandbox-guard-kuWTn9C5.js} +25 -19
  39. package/dist/session-binding-Bcynfd-_.js +874 -0
  40. package/dist/{session-catalog-xwNi_SDM.js → session-catalog-DaLKVtpH.js} +1534 -1288
  41. package/dist/session-catalog-home-id-BNwAJ9D7.js +18 -0
  42. package/dist/{session-cli-7hgXZDV7.js → session-cli-DMc4oS2w.js} +20 -7
  43. package/dist/session-permission-policy-BrNH1bjy.js +160 -0
  44. package/dist/{session-retirement-DoMMJFKm.js → session-retirement-CcNC3YSY.js} +3 -3
  45. package/dist/{session-upstream-marker-CrIFX06J.js → session-upstream-marker-BIkusb95.js} +1 -1
  46. package/dist/{settled-turn-finalizer-BRWBO4MO.js → settled-turn-finalizer-Dc3ApjU4.js} +24 -20
  47. package/dist/{shared-client-kIBbGjk4.js → shared-client-DKz23hHY.js} +1632 -372
  48. package/dist/{side-question-9HAL26l9.js → side-question-DjA_jsNe.js} +105 -54
  49. package/dist/{thread-lifecycle-Bu1BTDXr.js → thread-lifecycle-L7oEkTlq.js} +1147 -114
  50. package/dist/{thread-ownership-6kOQHlyC.js → thread-ownership-DZeuKH1j.js} +2 -2
  51. package/dist/{thread-resume-CPrJNQVM.js → thread-resume-BE9qNEW0.js} +3 -3
  52. package/dist/{transcript-mirror-B9gGgnJS.js → transcript-mirror-DsCMWBca.js} +137 -38
  53. package/dist/{transport-stdio-DIImwDVS.js → transport-stdio-DhoGy33Z.js} +2 -2
  54. package/dist/{upstream-prompt-provenance-ClRBije0.js → upstream-prompt-provenance-CFmsKwr9.js} +12 -14
  55. package/dist/{upstream-session-fork-CE-_LdnP.js → upstream-session-fork-DlaHxSLC.js} +12 -6
  56. package/dist/{usage-CHlV0e-o.js → usage-ROIaW3wo.js} +3 -3
  57. package/dist/{web-search-provider.runtime-DRw2Vl42.js → web-search-provider.runtime-ClaNPV7N.js} +3 -3
  58. package/openclaw.plugin.json +49 -2
  59. package/package.json +9 -8
  60. package/dist/app-server-policy-zcBDc1JU.js +0 -49
@@ -1,22 +1,18 @@
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 { asOptionalRecord, asOptionalRecord as readRecord, normalizeOptionalString as readNonEmptyString, normalizeTrimmedStringList, parseBooleanValue } from "openclaw/plugin-sdk/string-coerce-runtime";
1
+ import { asNullableRecord, asOptionalRecord as readRecord, normalizeOptionalString as readNonEmptyString, normalizeTrimmedStringList, parseBooleanValue } from "openclaw/plugin-sdk/string-coerce-runtime";
4
2
  import path from "node:path";
5
3
  import { resolvePositiveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
6
- import { AgentHarnessPreflightError, AgentHarnessSessionSupersededError, embeddedAgentLog } from "openclaw/plugin-sdk/agent-harness-runtime";
7
- import { createHash, createHmac, randomBytes, randomUUID } from "node:crypto";
4
+ import { AgentHarnessPreflightError } from "openclaw/plugin-sdk/agent-harness-runtime";
5
+ import { createHash, createHmac, randomBytes } from "node:crypto";
8
6
  import { readFileSync } from "node:fs";
9
7
  import { homedir, hostname } from "node:os";
10
- import { ensureAuthProfileStore, resolveDefaultAgentDir, resolveProviderIdForAuth, resolveSessionAgentIds as resolveSessionAgentIds$1 } from "openclaw/plugin-sdk/agent-runtime";
8
+ import { resolveProviderIdForAuth } from "openclaw/plugin-sdk/agent-runtime";
11
9
  import { parse } from "smol-toml";
10
+ import { resolveAgentConfig as resolveAgentConfig$1 } from "openclaw/plugin-sdk/agent-scope-runtime";
12
11
  import { resolveExecApprovalsFromFile } from "openclaw/plugin-sdk/exec-approvals-runtime";
13
- import { normalizeAgentId } from "openclaw/plugin-sdk/routing";
14
12
  import { buildSecretInputSchema, normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-input";
15
13
  import { detectWindowsSpawnCommandInlineArgs } from "openclaw/plugin-sdk/windows-spawn";
16
14
  import { z } from "zod";
17
15
  import { isLoopbackHost } from "openclaw/plugin-sdk/ssrf-runtime";
18
- import { AsyncLocalStorage } from "node:async_hooks";
19
- import { getSessionEntry, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
20
16
  //#region extensions/codex/src/app-server/config-utils.ts
21
17
  const START_OPTIONS_KEY_SECRET_SYMBOL = Symbol.for("openclaw.codexAppServerStartOptionsKeySecret");
22
18
  const START_OPTIONS_KEY_SECRET = getStartOptionsKeySecret();
@@ -122,8 +118,9 @@ function selectGuardianSandbox(allowedSandboxModes) {
122
118
  return "workspace-write";
123
119
  }
124
120
  function resolveApprovalPolicy(value) {
121
+ if (value === "untrusted") throw new Error("Codex app-server approval policy \"untrusted\" is retired; run \"openclaw doctor --fix\" and use \"on-request\".");
125
122
  if (value === "on-failure") return "on-request";
126
- return value === "on-request" || value === "untrusted" || value === "never" ? value : void 0;
123
+ return value === "on-request" || value === "never" ? value : void 0;
127
124
  }
128
125
  function resolveSandbox(value) {
129
126
  return value === "read-only" || value === "workspace-write" || value === "danger-full-access" ? value : void 0;
@@ -132,20 +129,16 @@ function resolveApprovalsReviewer(value) {
132
129
  return value === "auto_review" || value === "guardian_subagent" || value === "user" ? value : void 0;
133
130
  }
134
131
  function resolveOpenClawExecPolicyFromConfig(params) {
135
- const root = readRecord(params.config);
136
- const globalExec = readRecord(readRecord(root?.tools)?.exec);
132
+ const globalExec = readRecord(params.config?.tools?.exec);
137
133
  const globalPolicy = applyOpenClawExecPolicyLayer(createDefaultOpenClawExecPolicy(), globalExec);
138
134
  const agentId = params.agentId?.trim();
139
- if (!agentId) return globalPolicy;
140
- const agents = readRecord(root?.agents);
141
- const agentList = Array.isArray(agents?.list) ? agents.list : [];
142
- const normalizedAgentId = normalizeAgentId(agentId);
143
- return applyOpenClawExecPolicyLayer(globalPolicy, readRecord(readRecord(readRecord(agentList.find((entry) => {
144
- const id = readRecord(entry)?.id;
145
- return typeof id === "string" && normalizeAgentId(id) === normalizedAgentId;
146
- }))?.tools)?.exec));
135
+ return applyOpenClawExecPolicyLayer(globalPolicy, agentId ? readRecord(resolveAgentConfig$1(params.config ?? {}, agentId)?.tools?.exec) : void 0);
147
136
  }
148
137
  function resolveOpenClawExecPolicyForCodexAppServer(params) {
138
+ if (params.permissionMode === "full") return {
139
+ ...resolveOpenClawExecPolicyForMode("full"),
140
+ touched: true
141
+ };
149
142
  const overridePolicy = applyOpenClawExecPolicyLayer(resolveOpenClawExecPolicyFromConfig({
150
143
  config: params.config,
151
144
  agentId: params.agentId
@@ -169,8 +162,7 @@ function assertCodexAppServerAllowedForOpenClawExecMode(mode) {
169
162
  }
170
163
  function createDefaultOpenClawExecPolicy() {
171
164
  return {
172
- security: "full",
173
- ask: "off",
165
+ ...resolveOpenClawExecPolicyForMode("full"),
174
166
  touched: false
175
167
  };
176
168
  }
@@ -277,12 +269,6 @@ function readExecMode(value) {
277
269
  //#region extensions/codex/src/app-server/config-requirements.ts
278
270
  const UNIX_CODEX_REQUIREMENTS_PATH = "/etc/codex/requirements.toml";
279
271
  const WINDOWS_CODEX_REQUIREMENTS_SUFFIX = "\\OpenAI\\Codex\\requirements.toml";
280
- function isCodexAppServerApprovalPolicyAllowedByRequirements(policy, params = {}) {
281
- const content = readCodexRequirementsToml(params);
282
- if (content === void 0) return true;
283
- const allowedApprovalPolicies = parseAllowedApprovalPoliciesFromCodexRequirements(content);
284
- return allowedApprovalPolicies === void 0 || allowedApprovalPolicies.has(policy);
285
- }
286
272
  function readCodexRequirementsToml(params) {
287
273
  if (params.requirementsToml !== void 0) return params.requirementsToml ?? void 0;
288
274
  const requirementsPath = readNonEmptyString(params.requirementsPath) ?? resolveCodexRequirementsPath(params.env ?? process.env, params.platform ?? process.platform);
@@ -449,6 +435,7 @@ function globPatternMatches(value, pattern) {
449
435
  function normalizeRequirementsApprovalPolicy(value) {
450
436
  const normalized = value.trim().toLowerCase();
451
437
  if (normalized === "on-failure") return "on-request";
438
+ if (normalized === "untrusted") return normalized;
452
439
  return resolveApprovalPolicy(normalized);
453
440
  }
454
441
  function normalizeRequirementsApprovalsReviewer(value) {
@@ -456,8 +443,8 @@ function normalizeRequirementsApprovalsReviewer(value) {
456
443
  }
457
444
  function selectGuardianApprovalPolicy(allowedApprovalPolicies, execModeRequiringPromptingApprovals) {
458
445
  if (allowedApprovalPolicies === void 0 || allowedApprovalPolicies.has("on-request")) return "on-request";
459
- if (execModeRequiringPromptingApprovals) throw new Error(`tools.exec.mode=${execModeRequiringPromptingApprovals} requires Codex app-server prompting approvals`);
460
446
  if (allowedApprovalPolicies.has("untrusted")) return "untrusted";
447
+ if (execModeRequiringPromptingApprovals) throw new Error(`tools.exec.mode=${execModeRequiringPromptingApprovals} requires Codex app-server prompting approvals`);
461
448
  if (allowedApprovalPolicies.has("never")) return "never";
462
449
  return "on-request";
463
450
  }
@@ -476,6 +463,24 @@ function selectUserApprovalsReviewer(allowedApprovalsReviewers, execModeRequirin
476
463
  //#region extensions/codex/src/app-server/config-reviewer.ts
477
464
  const CODEX_APP_SERVER_HOME_DIRNAME = "codex-home";
478
465
  const CODEX_CONFIG_TOML_FILENAME = "config.toml";
466
+ /** Cloud/system config can redirect reviews after local home/profile checks have passed. */
467
+ async function assertCodexModelBackedReviewerEffectiveConfig(params) {
468
+ if (params.approvalsReviewer !== "auto_review" && params.approvalsReviewer !== "guardian_subagent") return;
469
+ const effectiveConfig = readRecord(readRecord(await params.client.request("config/read", {
470
+ cwd: path.resolve(params.cwd),
471
+ includeLayers: false
472
+ }, { signal: params.signal }))?.config);
473
+ if (!effectiveConfig) throw new Error("Codex config/read returned an invalid model-backed reviewer config");
474
+ const modelProvider = effectiveConfig.model_provider;
475
+ const providers = effectiveConfig.model_providers;
476
+ const providerRecords = providers == null ? void 0 : readRecord(providers);
477
+ const provider = providerRecords?.openai;
478
+ const openAIProvider = provider == null ? void 0 : readRecord(provider);
479
+ if (modelProvider != null && modelProvider !== "openai" || providers != null && !providerRecords || provider != null && !openAIProvider || !isTrustedOptionalReviewerEndpoint(effectiveConfig.openai_base_url, isNativeOpenAIBaseUrl) || !isTrustedOptionalReviewerEndpoint(effectiveConfig.chatgpt_base_url, isNativeChatGPTBaseUrl) || !isTrustedOptionalReviewerEndpoint(openAIProvider?.base_url, isNativeOpenAIBaseUrl)) throw new Error("Codex model-backed approval reviewer requires the running server to use a trusted OpenAI endpoint");
480
+ }
481
+ function isTrustedOptionalReviewerEndpoint(value, isTrusted) {
482
+ return value == null || typeof value === "string" && isTrusted(value);
483
+ }
479
484
  function canUseCodexModelBackedApprovalsReviewerForModel(params) {
480
485
  const explicitProvider = params.modelProvider?.trim().toLowerCase();
481
486
  const inferredProvider = inferProviderFromModelRef(params.model);
@@ -528,33 +533,60 @@ function isTrustedCodexModelBackedApprovalsReviewerProvider(provider, params) {
528
533
  model: params.model,
529
534
  agentDir: params.agentDir,
530
535
  codexConfigToml: params.codexConfigToml,
531
- homeScope: params.homeScope
536
+ homeScope: params.homeScope,
537
+ codexArgs: params.codexArgs
532
538
  });
533
539
  }
534
540
  function readCodexBaseUrlOverridesForModelBackedReview(params) {
535
541
  const configToml = readCodexAppServerConfigToml(params);
536
542
  if (configToml === false) return false;
537
- if (configToml === void 0) return {
538
- openAI: [],
539
- chatGPT: []
540
- };
541
- const topLevelContent = stripTomlLineComments(configToml).slice(0, firstTomlTableOffset(configToml));
542
- const modelProviderOpenAISection = parseTomlTableSection(configToml, "model_providers.openai");
543
- const openAIBaseUrl = parseTomlStringValue(topLevelContent, "openai_base_url");
544
- const chatGPTBaseUrl = parseTomlStringValue(topLevelContent, "chatgpt_base_url");
545
- const openAI = [
546
- openAIBaseUrl,
547
- parseTomlStringValue(topLevelContent, "model_providers.openai.base_url"),
548
- parseInlineOpenAIModelProviderBaseUrl(topLevelContent),
549
- modelProviderOpenAISection ? parseTomlStringValue(modelProviderOpenAISection, "base_url") : void 0
550
- ];
551
- const chatGPT = [chatGPTBaseUrl];
543
+ const configTomls = configToml === void 0 ? [] : [configToml];
544
+ const nativeOverrides = readNativeCodexReviewerConfigOverrides(params);
545
+ if (nativeOverrides === false) return false;
546
+ configTomls.push(...nativeOverrides);
547
+ const openAI = [];
548
+ const chatGPT = [];
549
+ for (const content of configTomls) {
550
+ const topLevelContent = stripTomlLineComments(content).slice(0, firstTomlTableOffset(content));
551
+ const modelProviderOpenAISection = parseTomlTableSection(content, "model_providers.openai");
552
+ const modelProvider = parseTomlStringValue(topLevelContent, "model_provider");
553
+ if (modelProvider === false || modelProvider && modelProvider !== "openai") return false;
554
+ openAI.push(parseTomlStringValue(topLevelContent, "openai_base_url"), parseTomlStringValue(topLevelContent, "model_providers.openai.base_url"), parseInlineOpenAIModelProviderBaseUrl(topLevelContent), modelProviderOpenAISection ? parseTomlStringValue(modelProviderOpenAISection, "base_url") : void 0);
555
+ chatGPT.push(parseTomlStringValue(topLevelContent, "chatgpt_base_url"));
556
+ }
552
557
  if ([...openAI, ...chatGPT].includes(false)) return false;
553
558
  return {
554
559
  openAI: openAI.filter((entry) => typeof entry === "string"),
555
560
  chatGPT: chatGPT.filter((entry) => typeof entry === "string")
556
561
  };
557
562
  }
563
+ function readNativeCodexReviewerConfigOverrides(params) {
564
+ const overrides = [];
565
+ let profile;
566
+ const args = params.codexArgs ?? [];
567
+ for (let index = 0; index < args.length; index += 1) {
568
+ const arg = args[index];
569
+ if (!arg) return false;
570
+ if (arg === "--profile" || arg === "-p") profile = args[++index];
571
+ else if (arg.startsWith("--profile=")) profile = arg.slice(10);
572
+ else if (arg === "-c" || arg === "--config") {
573
+ const override = args[++index];
574
+ if (!override) return false;
575
+ overrides.push(`${override}\n`);
576
+ } else if (arg.startsWith("--config=")) overrides.push(`${arg.slice(9)}\n`);
577
+ }
578
+ if (profile) {
579
+ if (path.basename(profile) !== profile || profile === "." || profile === "..") return false;
580
+ const configPath = resolveCodexAppServerConfigPath(params);
581
+ if (!configPath) return false;
582
+ try {
583
+ overrides.unshift(readFileSync(path.join(path.dirname(configPath), `${profile}.config.toml`), "utf8"));
584
+ } catch (error) {
585
+ if (readErrorCode(error) !== "ENOENT") return false;
586
+ }
587
+ }
588
+ return overrides;
589
+ }
558
590
  function readCodexAppServerConfigToml(params) {
559
591
  if (params.codexConfigToml !== void 0) return params.codexConfigToml ?? void 0;
560
592
  const configPath = resolveCodexAppServerConfigPath(params);
@@ -677,7 +709,14 @@ const CODEX_PLUGINS_WORKSPACE_MARKETPLACE_NAME = "workspace-directory";
677
709
  const CODEX_PLUGIN_MARKETPLACE_NAME_PATTERN = /^[A-Za-z0-9_-]+$/;
678
710
  //#endregion
679
711
  //#region extensions/codex/src/app-server/session-discovery-config.ts
680
- const codexSessionCatalogConfigSchema = z.object({ enabled: z.boolean().optional() }).strict();
712
+ const codexSessionCatalogHomeSchema = z.union([z.string().trim().min(1), z.object({
713
+ path: z.string().trim().min(1),
714
+ label: z.string().trim().min(1).optional()
715
+ }).strict()]);
716
+ const codexSessionCatalogConfigSchema = z.object({
717
+ enabled: z.boolean().optional(),
718
+ homes: z.array(codexSessionCatalogHomeSchema).optional()
719
+ }).strict();
681
720
  const codexDiscoveryConfigSchema = z.object({
682
721
  enabled: z.boolean().optional(),
683
722
  timeoutMs: z.number().positive().optional()
@@ -697,11 +736,7 @@ const codexAppServerTransportSchema = z.enum([
697
736
  const codexAppServerHomeScopeSchema = z.enum(["agent", "user"]);
698
737
  const SecretInputSchema = buildSecretInputSchema();
699
738
  const codexAppServerPolicyModeSchema = z.enum(["yolo", "guardian"]);
700
- const codexAppServerApprovalPolicySchema = z.preprocess((value) => value === "on-failure" ? "on-request" : value, z.enum([
701
- "never",
702
- "on-request",
703
- "untrusted"
704
- ]));
739
+ const codexAppServerApprovalPolicySchema = z.preprocess((value) => value === "on-failure" ? "on-request" : value, z.enum(["never", "on-request"]));
705
740
  const codexAppServerSandboxSchema = z.enum([
706
741
  "read-only",
707
742
  "workspace-write",
@@ -829,6 +864,7 @@ const codexPluginConfigSchema = z.object({
829
864
  }).strict().optional()
830
865
  }).strict();
831
866
  function readCodexPluginConfig(value) {
867
+ if (asNullableRecord(asNullableRecord(value)?.appServer)?.approvalPolicy === "untrusted") throw new Error("plugins.entries.codex.config.appServer.approvalPolicy=\"untrusted\" is retired; run \"openclaw doctor --fix\" to migrate it to \"on-request\".");
832
868
  const parsed = codexPluginConfigSchema.safeParse(value);
833
869
  if (!parsed.success) return {};
834
870
  const { codexPlugins: rawCodexPlugins, ...config } = parsed.data;
@@ -845,6 +881,9 @@ function isCodexSandboxExecServerEnabled(pluginConfig, sandbox) {
845
881
  function isCodexRemoteExecPlacementSandbox(sandbox) {
846
882
  return typeof sandbox === "object" && sandbox !== null && "placementExecutionMode" in sandbox && sandbox.placementExecutionMode === "remote-exec";
847
883
  }
884
+ function isCodexPairedNodeRemoteExecPlacementSandbox(sandbox) {
885
+ return isCodexRemoteExecPlacementSandbox(sandbox) && typeof sandbox === "object" && sandbox !== null && "placementNodeId" in sandbox && typeof sandbox.placementNodeId === "string" && sandbox.placementNodeId.length > 0;
886
+ }
848
887
  function assertCodexAppServerCommandHasNoInlineArgs(params) {
849
888
  const inlineArgs = detectWindowsSpawnCommandInlineArgs(params.command);
850
889
  if (!inlineArgs) return;
@@ -956,6 +995,7 @@ function stableStringifyJson(value) {
956
995
  return JSON.stringify(value);
957
996
  }
958
997
  function withMcpElicitationsApprovalPolicy(policy) {
998
+ if (policy === "untrusted") return policy;
959
999
  if (typeof policy !== "string") return { granular: {
960
1000
  ...policy.granular,
961
1001
  mcp_elicitations: true
@@ -1039,7 +1079,7 @@ function resolveDefaultCodexAppServerPolicy(params) {
1039
1079
  const allowedApprovalPolicies = parseAllowedApprovalPoliciesFromCodexRequirements(content);
1040
1080
  const allowedApprovalsReviewers = parseAllowedApprovalsReviewersFromCodexRequirements(content);
1041
1081
  const yoloSandboxAllowed = allowedSandboxModes === void 0 || allowedSandboxModes.has("danger-full-access");
1042
- const yoloApprovalAllowed = allowedApprovalPolicies === void 0 || allowedApprovalPolicies.has("never");
1082
+ const yoloApprovalAllowed = allowedApprovalPolicies === void 0 || allowedApprovalPolicies.has("never") && !allowedApprovalPolicies.has("untrusted");
1043
1083
  const yoloReviewerAllowed = allowedApprovalsReviewers === void 0 || allowedApprovalsReviewers.has("user");
1044
1084
  if (!params.forceGuardian && yoloSandboxAllowed && yoloApprovalAllowed && yoloReviewerAllowed) return {
1045
1085
  mode: "yolo",
@@ -1069,9 +1109,11 @@ function resolveCodexAppServerHomeScope(params) {
1069
1109
  }
1070
1110
  function resolveCodexAppServerRuntimeOptions(params = {}) {
1071
1111
  const env = params.env ?? process.env;
1072
- const config = readCodexPluginConfig(params.pluginConfig).appServer ?? {};
1112
+ const pluginConfig = readCodexPluginConfig(params.pluginConfig);
1113
+ const config = pluginConfig.appServer ?? {};
1073
1114
  const transport = resolveTransport(config.transport);
1074
1115
  const homeScope = resolveCodexAppServerHomeScope({ appServer: config });
1116
+ if (transport !== "stdio" && pluginConfig.sessionCatalog?.homes?.length) throw new Error("plugins.entries.codex.config.sessionCatalog.homes requires appServer.transport=stdio");
1075
1117
  const configCommand = readNonEmptyString(config.command);
1076
1118
  const envCommand = readNonEmptyString(env.OPENCLAW_CODEX_APP_SERVER_BIN);
1077
1119
  const command = configCommand ?? envCommand ?? "codex";
@@ -1098,7 +1140,7 @@ function resolveCodexAppServerRuntimeOptions(params = {}) {
1098
1140
  execMode: params.execMode,
1099
1141
  execPolicy: params.execPolicy
1100
1142
  });
1101
- assertCodexAppServerAllowedForOpenClawExecMode(execMode);
1143
+ if (!params.sessionPermissionMode) assertCodexAppServerAllowedForOpenClawExecMode(execMode);
1102
1144
  const explicitPolicyMode = resolvePolicyMode(config.mode) ?? resolvePolicyMode(env.OPENCLAW_CODEX_APP_SERVER_MODE);
1103
1145
  const configuredSandbox = resolveSandbox(config.sandbox) ?? resolveSandbox(env.OPENCLAW_CODEX_APP_SERVER_SANDBOX);
1104
1146
  const explicitApprovalsReviewer = resolveApprovalsReviewer(config.approvalsReviewer);
@@ -1117,6 +1159,15 @@ function resolveCodexAppServerRuntimeOptions(params = {}) {
1117
1159
  const forceGuardianReviewer = execMode === "auto" && canUseModelBackedReviewer;
1118
1160
  const execModeRequiringPromptingApprovals = execMode === "auto" || execMode === "ask" ? execMode : forceUserReviewer ? "ask" : void 0;
1119
1161
  const forceDangerFullAccessSandbox = params.execPolicy?.touched === true && params.execPolicy.security === "full" && params.execPolicy.ask === "always";
1162
+ const forcePerCommandApprovals = params.execPolicy?.ask === "always";
1163
+ const requirementsToml = forcePerCommandApprovals ? readCodexRequirementsToml({
1164
+ env,
1165
+ requirementsToml: params.requirementsToml,
1166
+ requirementsPath: params.requirementsPath,
1167
+ readRequirementsFile: params.readRequirementsFile,
1168
+ platform: params.platform
1169
+ }) ?? null : params.requirementsToml;
1170
+ if (forcePerCommandApprovals && requirementsToml && parseAllowedApprovalPoliciesFromCodexRequirements(requirementsToml)?.has("untrusted") === false) throw new Error("tools.exec.ask=always requires Codex app-server per-command approvals");
1120
1171
  const forceRuntimePolicy = forceUserReviewer || forceGuardianReviewer || forceDangerFullAccessSandbox;
1121
1172
  const defaultPolicy = explicitPolicyMode && !forceRuntimePolicy && !ignoreLegacyYoloPolicyMode ? void 0 : resolveDefaultCodexAppServerPolicy({
1122
1173
  transport,
@@ -1124,7 +1175,7 @@ function resolveCodexAppServerRuntimeOptions(params = {}) {
1124
1175
  forceGuardian: normalizedPolicyMode === "guardian",
1125
1176
  forceUserReviewer: forceUserReviewer || !canUseModelBackedReviewer,
1126
1177
  execModeRequiringPromptingApprovals,
1127
- requirementsToml: params.requirementsToml,
1178
+ requirementsToml,
1128
1179
  requirementsPath: params.requirementsPath,
1129
1180
  readRequirementsFile: params.readRequirementsFile,
1130
1181
  platform: params.platform,
@@ -1133,7 +1184,7 @@ function resolveCodexAppServerRuntimeOptions(params = {}) {
1133
1184
  });
1134
1185
  const preserveExplicitAutoSandbox = forceGuardianReviewer && configuredSandbox === "read-only";
1135
1186
  const forcedPolicy = forceRuntimePolicy ? {
1136
- approvalPolicy: defaultPolicy?.approvalPolicy ?? "on-request",
1187
+ approvalPolicy: forcePerCommandApprovals ? "untrusted" : defaultPolicy?.approvalPolicy ?? "on-request",
1137
1188
  sandbox: preserveExplicitAutoSandbox ? void 0 : forceDangerFullAccessSandbox ? selectForcedDangerFullAccessSandbox({
1138
1189
  configuredSandbox,
1139
1190
  defaultPolicy,
@@ -1335,861 +1386,4 @@ function resolveCodexSupervisionAppServerRuntimeOptions(params = {}) {
1335
1386
  });
1336
1387
  }
1337
1388
  //#endregion
1338
- //#region extensions/codex/src/app-server/session-binding.ts
1339
- /** SQLite-backed Codex app-server thread bindings. */
1340
- var session_binding_exports = /* @__PURE__ */ __exportAll({
1341
- CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS: () => CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS,
1342
- CODEX_APP_SERVER_BINDING_MAX_ENTRIES: () => CODEX_APP_SERVER_BINDING_MAX_ENTRIES,
1343
- CODEX_APP_SERVER_BINDING_NAMESPACE: () => CODEX_APP_SERVER_BINDING_NAMESPACE,
1344
- CodexSupervisionBindingReplacementError: () => CodexSupervisionBindingReplacementError,
1345
- assertCodexBindingMayBeReplaced: () => assertCodexBindingMayBeReplaced,
1346
- bindingStoreKey: () => bindingStoreKey,
1347
- createCodexAppServerBindingStore: () => createCodexAppServerBindingStore,
1348
- createCodexSessionGenerationSupersededError: () => createCodexSessionGenerationSupersededError,
1349
- createStoredCodexAppServerBinding: () => createStoredCodexAppServerBinding,
1350
- hashCodexAppServerBindingFingerprint: () => hashCodexAppServerBindingFingerprint,
1351
- isCodexAppServerNativeAuthProfile: () => isCodexAppServerNativeAuthProfile,
1352
- normalizeCodexAppServerBindingModelProvider: () => normalizeCodexAppServerBindingModelProvider,
1353
- normalizeStoredCodexAppServerBindingFingerprints: () => normalizeStoredCodexAppServerBindingFingerprints,
1354
- readCodexAppServerThreadBinding: () => readCodexAppServerThreadBinding,
1355
- readStoredCodexAppServerBinding: () => readStoredCodexAppServerBinding,
1356
- reclaimCurrentCodexSessionGeneration: () => reclaimCurrentCodexSessionGeneration,
1357
- resolveCodexRunSessionBindingAuthority: () => resolveCodexRunSessionBindingAuthority,
1358
- scopeCodexRunBindingStore: () => scopeCodexRunBindingStore,
1359
- sessionBindingIdentity: () => sessionBindingIdentity
1360
- });
1361
- const CODEX_APP_SERVER_NATIVE_AUTH_PROVIDER = "openai";
1362
- const PUBLIC_OPENAI_MODEL_PROVIDER = "openai";
1363
- const BINDING_LEASE_RETRY_INTERVAL_MS = 1e3;
1364
- const BOUNDED_BINDING_FINGERPRINT_PATTERN = /^sha256:[a-f0-9]{64}$/i;
1365
- const CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS = 6e4;
1366
- const BINDING_LEASE_STALE_MS = 65e3;
1367
- const BINDING_LEASE_WAIT_MS = 7e4;
1368
- const BINDING_LEASE_RENEW_INTERVAL_MS = Math.floor(BINDING_LEASE_STALE_MS / 3);
1369
- const PHYSICAL_SESSION_RETIRE_TTL_MS = BINDING_LEASE_WAIT_MS;
1370
- /** Resolves the same agent scope OpenClaw uses for transcript/session ownership. */
1371
- function sessionBindingIdentity(params) {
1372
- const { sessionAgentId } = resolveSessionAgentIds$1(params);
1373
- const sessionKey = params.sessionKey?.trim();
1374
- return {
1375
- kind: "session",
1376
- agentId: sessionAgentId,
1377
- sessionId: params.sessionId,
1378
- ...sessionKey ? { sessionKey } : {}
1379
- };
1380
- }
1381
- /** Decides whether a run may share the durable stable-key binding owner. */
1382
- function resolveCodexRunSessionBindingAuthority(params) {
1383
- const sessionKey = params.identity.sessionKey?.trim();
1384
- if (!sessionKey) return "ephemeral";
1385
- try {
1386
- const storePath = params.storePath?.trim() || resolveStorePath(params.config?.session?.store, { agentId: params.identity.agentId });
1387
- const entry = getSessionEntry({
1388
- agentId: params.identity.agentId,
1389
- hydrateSkillPromptRefs: false,
1390
- readConsistency: "latest",
1391
- sessionKey,
1392
- storePath
1393
- });
1394
- if (!entry) return "ephemeral";
1395
- return entry.sessionId === params.identity.sessionId ? "current" : "superseded";
1396
- } catch {
1397
- return "superseded";
1398
- }
1399
- }
1400
- /** Builds the terminal coordination error used when a newer OpenClaw session owns the binding. */
1401
- function createCodexSessionGenerationSupersededError(sessionId) {
1402
- return new AgentHarnessSessionSupersededError(`Codex session generation is no longer current: ${sessionId}`);
1403
- }
1404
- const optionalStringSchema = z.string().optional().catch(void 0);
1405
- const optionalBooleanSchema = z.boolean().optional().catch(void 0);
1406
- const optionalNonBlankStringSchema = z.string().refine((value) => Boolean(value.trim())).optional().catch(void 0);
1407
- const optionalTimestampSchema = z.string().refine((value) => Number.isFinite(Date.parse(value))).optional().catch(void 0);
1408
- const pendingSupervisionBranchSchema = z.object({
1409
- sourceThreadId: z.string().trim().min(1),
1410
- connectionFingerprint: z.string().trim().min(1).optional(),
1411
- lastTurnId: z.string().trim().min(1).optional(),
1412
- cleanupThreadIds: z.array(z.string().trim().min(1)).max(2).optional()
1413
- }).strict().superRefine((pending, context) => {
1414
- const cleanupThreadIds = pending.cleanupThreadIds ?? [];
1415
- if (new Set(cleanupThreadIds).size !== cleanupThreadIds.length) context.addIssue({
1416
- code: "custom",
1417
- message: "pending supervision cleanup thread ids must be unique"
1418
- });
1419
- if (cleanupThreadIds.includes(pending.sourceThreadId)) context.addIssue({
1420
- code: "custom",
1421
- message: "pending supervision cleanup cannot target its source"
1422
- });
1423
- });
1424
- const contextEngineProjectionSchema = z.object({
1425
- schemaVersion: z.literal(1),
1426
- mode: z.literal("thread_bootstrap"),
1427
- epoch: z.string().refine((value) => Boolean(value.trim())),
1428
- fingerprint: optionalStringSchema
1429
- }).strict();
1430
- const contextEngineSchema = z.object({
1431
- schemaVersion: z.literal(1),
1432
- engineId: z.string(),
1433
- policyFingerprint: z.string(),
1434
- projection: contextEngineProjectionSchema.optional().catch(void 0)
1435
- }).strict();
1436
- const destructiveApprovalModeSchema = z.enum([
1437
- "allow",
1438
- "deny",
1439
- "auto",
1440
- "ask"
1441
- ]).optional().catch(void 0);
1442
- const accountAppPolicyEntrySchema = z.object({
1443
- source: z.literal("account"),
1444
- appName: z.string(),
1445
- allowDestructiveActions: z.boolean(),
1446
- allowOpenWorld: z.boolean().optional(),
1447
- destructiveApprovalMode: destructiveApprovalModeSchema,
1448
- mcpServerNames: z.array(z.string())
1449
- }).strict();
1450
- const pluginAppPolicyEntrySchema = z.object({
1451
- source: z.literal("plugin").optional(),
1452
- configKey: z.string(),
1453
- marketplaceName: z.string().regex(CODEX_PLUGIN_MARKETPLACE_NAME_PATTERN),
1454
- pluginName: z.string(),
1455
- allowDestructiveActions: z.boolean(),
1456
- allowOpenWorld: z.boolean().optional(),
1457
- destructiveApprovalMode: destructiveApprovalModeSchema,
1458
- mcpServerNames: z.array(z.string())
1459
- }).strict();
1460
- const pluginAppPolicyContextSchema = z.object({
1461
- fingerprint: z.string(),
1462
- apps: z.record(z.string(), z.union([accountAppPolicyEntrySchema, pluginAppPolicyEntrySchema])),
1463
- pluginAppIds: z.record(z.string(), z.array(z.string())).default({})
1464
- }).strict();
1465
- const threadBindingSchema = z.object({
1466
- threadId: z.string().refine((value) => Boolean(value.trim())),
1467
- clientId: optionalStringSchema,
1468
- cwd: z.string(),
1469
- rolloutPath: optionalNonBlankStringSchema,
1470
- connectionScope: z.literal("supervision").optional(),
1471
- supervisionSourceThreadId: z.string().trim().min(1).optional(),
1472
- authProfileId: optionalStringSchema,
1473
- model: optionalStringSchema,
1474
- preserveNativeModel: z.literal(true).optional().catch(void 0),
1475
- pendingSupervisionBranch: pendingSupervisionBranchSchema.optional(),
1476
- modelProvider: z.string().transform((value) => value.trim()).pipe(z.string().min(1)).optional().catch(void 0),
1477
- approvalPolicy: z.preprocess((value) => value === "on-failure" ? "on-request" : value, z.enum([
1478
- "never",
1479
- "on-request",
1480
- "untrusted"
1481
- ]).optional()).catch(void 0),
1482
- sandbox: z.enum([
1483
- "read-only",
1484
- "workspace-write",
1485
- "danger-full-access"
1486
- ]).optional().catch(void 0),
1487
- serviceTier: z.preprocess(normalizeCodexServiceTier, z.custom((value) => typeof value === "string").optional()).optional().catch(void 0),
1488
- networkProxyProfileName: optionalStringSchema,
1489
- networkProxyConfigFingerprint: optionalStringSchema,
1490
- dynamicToolsFingerprint: optionalStringSchema,
1491
- dynamicToolsContainDeferred: optionalBooleanSchema,
1492
- webSearchThreadConfigFingerprint: optionalStringSchema,
1493
- nativeSkillIsolationFingerprint: optionalStringSchema,
1494
- userMcpServersFingerprint: optionalStringSchema,
1495
- mcpServersFingerprint: optionalStringSchema,
1496
- configuredMcpOwnershipVersion: z.literal(1).optional().catch(void 0),
1497
- ringZeroConfigFingerprint: optionalStringSchema,
1498
- ringZeroClientInstanceId: optionalStringSchema,
1499
- /** Durable fact preventing a later unrestricted turn from widening this thread. */
1500
- nativeToolPolicyRestricted: z.literal(true).optional().catch(void 0),
1501
- nativeHookRelayGeneration: optionalNonBlankStringSchema,
1502
- appServerRuntimeFingerprint: optionalStringSchema,
1503
- pluginAppsFingerprint: optionalStringSchema,
1504
- pluginAppsInputFingerprint: optionalStringSchema,
1505
- pluginAppPolicyContext: pluginAppPolicyContextSchema.optional().catch(void 0),
1506
- contextEngine: contextEngineSchema.optional().catch(void 0),
1507
- environmentSelectionFingerprint: optionalStringSchema,
1508
- conversationStartId: optionalStringSchema,
1509
- conversationSourceTransferComplete: z.literal(true).optional().catch(void 0),
1510
- historyCoveredThrough: optionalTimestampSchema
1511
- }).superRefine((binding, context) => {
1512
- if (binding.connectionScope === "supervision") {
1513
- if (!binding.supervisionSourceThreadId) context.addIssue({
1514
- code: "custom",
1515
- message: "supervision connection ownership requires its native source thread id"
1516
- });
1517
- if (binding.preserveNativeModel !== true) context.addIssue({
1518
- code: "custom",
1519
- message: "supervision connection ownership requires native model ownership"
1520
- });
1521
- if (binding.conversationSourceTransferComplete !== true) context.addIssue({
1522
- code: "custom",
1523
- message: "supervision connection ownership requires a completed source transfer"
1524
- });
1525
- if (!binding.pendingSupervisionBranch && (!binding.model?.trim() || !binding.modelProvider)) context.addIssue({
1526
- code: "custom",
1527
- message: "materialized supervision bindings require a native model and provider"
1528
- });
1529
- }
1530
- if (binding.supervisionSourceThreadId && binding.connectionScope !== "supervision") context.addIssue({
1531
- code: "custom",
1532
- message: "a supervision source thread id requires supervision connection ownership"
1533
- });
1534
- if (!binding.pendingSupervisionBranch) return;
1535
- if (binding.threadId !== binding.pendingSupervisionBranch.sourceThreadId) context.addIssue({
1536
- code: "custom",
1537
- message: "pending supervision source must match the provisional thread binding"
1538
- });
1539
- if (binding.supervisionSourceThreadId !== binding.pendingSupervisionBranch.sourceThreadId) context.addIssue({
1540
- code: "custom",
1541
- message: "pending supervision source must match its durable source identity"
1542
- });
1543
- if (binding.preserveNativeModel !== true) context.addIssue({
1544
- code: "custom",
1545
- message: "pending supervision bindings must defer model selection to Codex App Server"
1546
- });
1547
- if (binding.connectionScope !== "supervision") context.addIssue({
1548
- code: "custom",
1549
- message: "pending supervision bindings require supervision connection ownership"
1550
- });
1551
- });
1552
- var CodexSupervisionBindingReplacementError = class extends Error {
1553
- constructor(threadId, operation) {
1554
- super(`Refusing to replace supervised Codex thread ${threadId} while ${operation}; its native user-home connection and model ownership must be preserved`);
1555
- this.name = "CodexSupervisionBindingReplacementError";
1556
- }
1557
- };
1558
- function assertCodexBindingMayBeReplaced(binding, operation) {
1559
- if (binding?.connectionScope === "supervision") throw new CodexSupervisionBindingReplacementError(binding.threadId, operation);
1560
- }
1561
- const bindingLeaseSchema = z.object({
1562
- token: z.string().refine((value) => Boolean(value.trim())),
1563
- expiresAt: z.number().finite()
1564
- });
1565
- const storedSessionIdSchema = z.string().transform((value) => value.trim()).pipe(z.string().min(1)).optional().catch(void 0);
1566
- const storedBindingSchema = z.discriminatedUnion("state", [z.object({
1567
- version: z.literal(1),
1568
- state: z.literal("active"),
1569
- binding: threadBindingSchema,
1570
- sessionId: storedSessionIdSchema,
1571
- lease: bindingLeaseSchema.optional().catch(void 0)
1572
- }), z.object({
1573
- version: z.literal(1),
1574
- state: z.literal("cleared"),
1575
- sessionId: storedSessionIdSchema,
1576
- lease: bindingLeaseSchema.optional().catch(void 0),
1577
- retired: z.literal(true).optional().catch(void 0)
1578
- })]);
1579
- function hashCodexAppServerBindingFingerprint(canonical) {
1580
- return `sha256:${createHash("sha256").update(canonical).digest("hex")}`;
1581
- }
1582
- function normalizeLegacyBindingFingerprint(value) {
1583
- if (typeof value !== "string" || value === "" || value === "[]" || BOUNDED_BINDING_FINGERPRINT_PATTERN.test(value)) return value;
1584
- return hashCodexAppServerBindingFingerprint(value);
1585
- }
1586
- function normalizeLegacyBindingFingerprints(record) {
1587
- let normalized = record;
1588
- for (const key of ["dynamicToolsFingerprint", "userMcpServersFingerprint"]) {
1589
- const value = record[key];
1590
- const next = normalizeLegacyBindingFingerprint(value);
1591
- if (next === value) continue;
1592
- if (normalized === record) normalized = { ...record };
1593
- normalized[key] = next;
1594
- }
1595
- return normalized;
1596
- }
1597
- function normalizeStoredCodexAppServerBindingFingerprints(value) {
1598
- const stored = readStoredCodexAppServerBinding(value);
1599
- if (!stored || stored.state !== "active") return stored;
1600
- const binding = normalizeLegacyBindingFingerprints(stored.binding);
1601
- return binding === stored.binding ? stored : readStoredCodexAppServerBinding({
1602
- ...stored,
1603
- binding
1604
- });
1605
- }
1606
- /** Encodes a migrated sidecar binding as one canonical plugin-state row. */
1607
- function createStoredCodexAppServerBinding(value, options = {}) {
1608
- const rawRecord = asOptionalRecord(value);
1609
- if (!rawRecord) return;
1610
- const record = normalizeLegacyBindingFingerprints(rawRecord);
1611
- if (record.schemaVersion !== 1 && record.schemaVersion !== 2) return;
1612
- const pluginAppPolicyContext = readPluginAppPolicyContext(record.pluginAppPolicyContext, record.schemaVersion);
1613
- const historyCoveredThrough = readTimestamp(record.historyCoveredThrough) ?? readTimestamp(record.updatedAt) ?? readTimestamp(record.createdAt) ?? readTimestamp(options.now) ?? (/* @__PURE__ */ new Date()).toISOString();
1614
- const authProfileId = typeof record.authProfileId === "string" ? record.authProfileId : void 0;
1615
- const binding = readCodexAppServerThreadBinding({
1616
- ...record,
1617
- modelProvider: normalizeCodexAppServerBindingModelProvider({
1618
- ...options.lookup,
1619
- authProfileId,
1620
- modelProvider: typeof record.modelProvider === "string" ? record.modelProvider : void 0
1621
- }),
1622
- cwd: typeof record.cwd === "string" ? record.cwd : "",
1623
- pluginAppPolicyContext,
1624
- historyCoveredThrough
1625
- });
1626
- return binding ? {
1627
- version: 1,
1628
- state: "active",
1629
- binding: stripUndefinedBinding(binding)
1630
- } : void 0;
1631
- }
1632
- function bindingLeaseLostError(key, cause) {
1633
- return new Error(`Lost Codex binding lease: ${key}`, cause === void 0 ? void 0 : { cause });
1634
- }
1635
- /** Carries one prepared run identity through callers that rederive it from public params. */
1636
- function scopeCodexRunBindingStore(params) {
1637
- const mapSessionIdentity = (identity) => identity.agentId === params.logicalIdentity.agentId && identity.sessionId === params.logicalIdentity.sessionId && identity.sessionKey?.trim() === params.logicalIdentity.sessionKey?.trim() ? params.physicalIdentity : identity;
1638
- const mapIdentity = (identity) => identity.kind === "session" ? mapSessionIdentity(identity) : identity;
1639
- return {
1640
- read: (identity) => params.bindingStore.read(mapIdentity(identity)),
1641
- hasOtherThreadOwner: (threadId, identity) => params.bindingStore.hasOtherThreadOwner(threadId, identity ? mapIdentity(identity) : void 0),
1642
- mutate: (identity, mutation) => params.bindingStore.mutate(mapIdentity(identity), mutation),
1643
- prepareSessionGenerationReclaim: (identity) => params.bindingStore.prepareSessionGenerationReclaim(mapSessionIdentity(identity)),
1644
- adoptSessionGeneration: (identity, expectedPreviousSessionId) => params.bindingStore.adoptSessionGeneration(mapSessionIdentity(identity), expectedPreviousSessionId),
1645
- resetSessionGeneration: (identity) => params.bindingStore.resetSessionGeneration(mapSessionIdentity(identity)),
1646
- retireSessionGeneration: (identity) => params.bindingStore.retireSessionGeneration(mapSessionIdentity(identity)),
1647
- withThreadArchiveFence: (run) => params.bindingStore.withThreadArchiveFence(run),
1648
- withLease: (identity, run) => params.bindingStore.withLease(mapIdentity(identity), run)
1649
- };
1650
- }
1651
- /** Lets the authoritative OpenClaw session generation claim a stale stable binding row. */
1652
- async function reclaimCurrentCodexSessionGeneration(params) {
1653
- const sessionKey = params.identity.sessionKey?.trim();
1654
- if (!sessionKey) return true;
1655
- const plan = await params.bindingStore.prepareSessionGenerationReclaim(params.identity);
1656
- if (plan.kind === "resolved") return plan.result;
1657
- try {
1658
- const storePath = params.storePath?.trim() || resolveStorePath(params.config?.session?.store, { agentId: params.identity.agentId });
1659
- if (getSessionEntry({
1660
- agentId: params.identity.agentId,
1661
- hydrateSkillPromptRefs: false,
1662
- readConsistency: "latest",
1663
- sessionKey,
1664
- storePath
1665
- })?.sessionId !== params.identity.sessionId) return false;
1666
- } catch {
1667
- return false;
1668
- }
1669
- return await params.bindingStore.mutate(params.identity, {
1670
- kind: "reclaim-generation",
1671
- expectedPreviousSessionId: plan.expectedPreviousSessionId
1672
- });
1673
- }
1674
- /** Creates the single binding facade owned by the Codex plugin runtime. */
1675
- function createCodexAppServerBindingStore(state) {
1676
- const update = state.update?.bind(state);
1677
- if (!update) throw new Error("Codex app-server bindings require atomic plugin-state updates");
1678
- const leaseContext = new AsyncLocalStorage();
1679
- const archiveContext = new AsyncLocalStorage();
1680
- let activeBindingMutations = 0;
1681
- let pendingArchives = 0;
1682
- let archiveTail = Promise.resolve();
1683
- let bindingMutationsDrained = [];
1684
- const waitForBindingMutations = async () => {
1685
- if (activeBindingMutations === 0) return;
1686
- await new Promise((resolve) => {
1687
- bindingMutationsDrained.push(resolve);
1688
- });
1689
- };
1690
- const runBindingMutation = async (run) => {
1691
- if (archiveContext.getStore() === true) return await run();
1692
- if (pendingArchives > 0) throw new Error("Codex binding mutation blocked while a native archive is in progress; retry");
1693
- activeBindingMutations += 1;
1694
- try {
1695
- return await run();
1696
- } finally {
1697
- activeBindingMutations -= 1;
1698
- if (activeBindingMutations === 0) {
1699
- const drained = bindingMutationsDrained;
1700
- bindingMutationsDrained = [];
1701
- for (const resolve of drained) resolve();
1702
- }
1703
- }
1704
- };
1705
- const renewLease = (key, owner) => {
1706
- if (owner.failure) return;
1707
- try {
1708
- let renewed = false;
1709
- const stored = update(key, (raw) => {
1710
- const current = readStoredCodexAppServerBinding(raw);
1711
- if (raw !== void 0 && !current) throw new Error(`Invalid Codex app-server binding row: ${key}`);
1712
- const lease = current?.lease;
1713
- const now = Date.now();
1714
- if (!lease || lease.token !== owner.token || lease.expiresAt <= now) return;
1715
- renewed = true;
1716
- return {
1717
- ...current,
1718
- lease: {
1719
- token: owner.token,
1720
- expiresAt: now + BINDING_LEASE_STALE_MS
1721
- }
1722
- };
1723
- });
1724
- if (!renewed || !stored) owner.failure = bindingLeaseLostError(key);
1725
- } catch (error) {
1726
- owner.failure = bindingLeaseLostError(key, error);
1727
- }
1728
- };
1729
- const transactKey = async (key, apply, ttlMs) => {
1730
- const deadline = Date.now() + BINDING_LEASE_WAIT_MS;
1731
- while (true) {
1732
- let busy = false;
1733
- let leaseLost = false;
1734
- let result;
1735
- const ownedLease = leaseContext.getStore()?.get(key);
1736
- if (ownedLease?.failure) throw ownedLease.failure;
1737
- const ownedToken = ownedLease?.token;
1738
- update(key, (raw) => {
1739
- const current = readStoredCodexAppServerBinding(raw);
1740
- if (raw !== void 0 && !current) throw new Error(`Invalid Codex app-server binding row: ${key}`);
1741
- const activeLease = current?.lease;
1742
- const now = Date.now();
1743
- if (ownedToken && (!activeLease || activeLease.token !== ownedToken || activeLease.expiresAt <= now)) {
1744
- leaseLost = true;
1745
- return;
1746
- }
1747
- if (activeLease && activeLease.token !== ownedToken && activeLease.expiresAt > now) {
1748
- busy = true;
1749
- return;
1750
- }
1751
- const applied = apply(current, ownedToken);
1752
- result = applied.result;
1753
- return applied.next;
1754
- }, ttlMs == null ? void 0 : { ttlMs });
1755
- if (leaseLost) {
1756
- const failure = bindingLeaseLostError(key);
1757
- if (ownedLease) ownedLease.failure = failure;
1758
- throw failure;
1759
- }
1760
- if (!busy) return result;
1761
- if (Date.now() >= deadline) throw new Error(`Timed out waiting for Codex binding lease: ${key}`);
1762
- await sleep(BINDING_LEASE_RETRY_INTERVAL_MS);
1763
- }
1764
- };
1765
- return {
1766
- async read(identity) {
1767
- const key = bindingStoreKey(identity);
1768
- const raw = state.lookup(key);
1769
- const stored = readStoredCodexAppServerBinding(raw);
1770
- if (raw !== void 0 && !stored) throw new Error(`Invalid Codex app-server binding row: ${key}`);
1771
- return stored?.state === "active" && ownsStoredSessionGeneration(identity, stored) ? stored.binding : void 0;
1772
- },
1773
- async hasOtherThreadOwner(threadId, currentIdentity) {
1774
- const currentKey = currentIdentity ? bindingStoreKey(currentIdentity) : void 0;
1775
- return state.entries().some(({ key, value }) => {
1776
- const stored = readStoredCodexAppServerBinding(value);
1777
- if (!stored) throw new Error(`Invalid Codex app-server binding row: ${key}`);
1778
- const isCurrentOwner = currentIdentity !== void 0 && key === currentKey && (currentIdentity.kind === "conversation" || stored.sessionId === currentIdentity.sessionId.trim());
1779
- if (stored.state !== "active" || stored.binding.threadId !== threadId || isCurrentOwner) return false;
1780
- return true;
1781
- });
1782
- },
1783
- async prepareSessionGenerationReclaim(identity) {
1784
- const key = bindingStoreKey(identity);
1785
- const raw = state.lookup(key);
1786
- const current = readStoredCodexAppServerBinding(raw);
1787
- if (raw !== void 0 && !current) throw new Error(`Invalid Codex app-server binding row: ${key}`);
1788
- if (!current) return {
1789
- kind: "resolved",
1790
- result: true
1791
- };
1792
- const currentSessionId = current.sessionId;
1793
- if (!currentSessionId) return {
1794
- kind: "resolved",
1795
- result: current.state !== "cleared" || current.retired !== true
1796
- };
1797
- if (currentSessionId === identity.sessionId) return current.state === "cleared" && current.retired === true ? {
1798
- kind: "verify",
1799
- expectedPreviousSessionId: currentSessionId
1800
- } : {
1801
- kind: "resolved",
1802
- result: true
1803
- };
1804
- return {
1805
- kind: "verify",
1806
- expectedPreviousSessionId: currentSessionId
1807
- };
1808
- },
1809
- async mutate(identity, mutation) {
1810
- return await runBindingMutation(async () => {
1811
- const key = bindingStoreKey(identity);
1812
- const retainLegacyClear = mutation.kind === "clear" && key.startsWith("conversation:legacy-");
1813
- return await transactKey(key, (current, leaseToken) => {
1814
- const ownsGeneration = ownsStoredSessionGeneration(identity, current);
1815
- const ownedLease = current?.lease && current.lease.token === leaseToken ? { lease: current.lease } : {};
1816
- if (mutation.kind === "reclaim-generation") {
1817
- if (identity.kind !== "session" || !identity.sessionKey?.trim()) return { result: false };
1818
- if (!current) return { result: true };
1819
- if (ownsGeneration) {
1820
- if (current.state === "cleared" && current.retired === true && current.sessionId === mutation.expectedPreviousSessionId) return {
1821
- result: true,
1822
- next: {
1823
- version: 1,
1824
- state: "cleared",
1825
- sessionId: identity.sessionId,
1826
- ...ownedLease
1827
- }
1828
- };
1829
- return { result: current.state !== "cleared" || current.retired !== true };
1830
- }
1831
- if (current.sessionId !== mutation.expectedPreviousSessionId) return { result: false };
1832
- if (current.state === "active" && current.binding.connectionScope === "supervision") return { result: false };
1833
- return {
1834
- result: true,
1835
- next: {
1836
- version: 1,
1837
- state: "cleared",
1838
- sessionId: identity.sessionId,
1839
- ...ownedLease
1840
- }
1841
- };
1842
- }
1843
- const storedActive = current?.state === "active" ? current : void 0;
1844
- const active = ownsGeneration ? storedActive : void 0;
1845
- const retiredGeneration = current?.state === "cleared" && current.retired === true && ownsGeneration;
1846
- const preservesSupervisionOwner = mutation.kind === "set" && active?.binding.connectionScope === "supervision" && isSameSupervisionOwner(active.binding, mutation.binding);
1847
- const clearsPendingSupervisionOwner = mutation.kind === "clear" && active?.binding.connectionScope === "supervision" && matchesPendingSupervisionClear(active.binding, mutation.threadId, mutation.expectedPendingSupervisionBranch);
1848
- const replacesExpectedOrdinaryOwner = mutation.kind === "replace-thread" && active?.binding.threadId === mutation.expectedThreadId && active.binding.connectionScope !== "supervision" && mutation.binding.connectionScope !== "supervision" && mutation.binding.threadId !== mutation.expectedThreadId;
1849
- 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 === "replace-thread" && !replacesExpectedOrdinaryOwner || (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 };
1850
- if (mutation.kind === "clear" && retiredGeneration) return { result: true };
1851
- if (mutation.kind === "clear") return {
1852
- result: true,
1853
- next: {
1854
- version: 1,
1855
- state: "cleared",
1856
- ...storedSessionGeneration(identity, current),
1857
- ...ownedLease
1858
- }
1859
- };
1860
- let binding;
1861
- if (mutation.kind === "set" || mutation.kind === "replace-thread") binding = validateBindingForWrite(mutation.binding);
1862
- else if (mutation.kind === "patch-pending-supervision-branch") binding = validateBindingForWrite({
1863
- ...active.binding,
1864
- pendingSupervisionBranch: mutation.pending
1865
- });
1866
- else if (mutation.kind === "commit-pending-supervision-branch") binding = validateBindingForWrite({
1867
- ...active.binding,
1868
- ...mutation.patch,
1869
- threadId: mutation.threadId,
1870
- pendingSupervisionBranch: void 0
1871
- });
1872
- else binding = validateBindingForWrite({
1873
- ...active.binding,
1874
- ...mutation.patch,
1875
- threadId: mutation.threadId
1876
- });
1877
- return {
1878
- result: true,
1879
- next: {
1880
- version: 1,
1881
- state: "active",
1882
- binding,
1883
- ...storedSessionGeneration(identity, current),
1884
- ...ownedLease
1885
- }
1886
- };
1887
- }, mutation.kind === "clear" && !retainLegacyClear && !leaseContext.getStore()?.has(key) ? 1 : void 0);
1888
- });
1889
- },
1890
- async adoptSessionGeneration(identity, expectedPreviousSessionId) {
1891
- return await runBindingMutation(async () => {
1892
- const key = bindingStoreKey(identity);
1893
- const expectedSessionId = expectedPreviousSessionId.trim();
1894
- const targetSessionId = identity.sessionId.trim();
1895
- if (!expectedSessionId) throw new Error("Codex session generation adoption requires the previous session id");
1896
- return await transactKey(key, (current) => {
1897
- if (current?.state !== "active") return { result: "absent" };
1898
- if (current.sessionId === targetSessionId) return { result: "current" };
1899
- if (current.sessionId !== expectedSessionId) return { result: "conflict" };
1900
- return {
1901
- result: "adopted",
1902
- next: {
1903
- ...current,
1904
- sessionId: targetSessionId
1905
- }
1906
- };
1907
- });
1908
- });
1909
- },
1910
- async resetSessionGeneration(identity) {
1911
- return await runBindingMutation(async () => {
1912
- const key = bindingStoreKey(identity);
1913
- return await transactKey(key, (current, leaseToken) => {
1914
- if (!current) return { result: "absent" };
1915
- if (!ownsStoredSessionGeneration(identity, current)) return { result: "conflict" };
1916
- if (current.state === "cleared" && current.retired === true) return { result: "conflict" };
1917
- return {
1918
- result: "applied",
1919
- next: {
1920
- version: 1,
1921
- state: "cleared",
1922
- ...storedSessionGeneration(identity, current),
1923
- ...current.lease && current.lease.token === leaseToken ? { lease: current.lease } : {}
1924
- }
1925
- };
1926
- }, leaseContext.getStore()?.has(key) ? void 0 : 1);
1927
- });
1928
- },
1929
- async retireSessionGeneration(identity) {
1930
- return await runBindingMutation(async () => {
1931
- const key = bindingStoreKey(identity);
1932
- return await transactKey(key, (current, leaseToken) => {
1933
- if (!current) return { result: "absent" };
1934
- if (!ownsStoredSessionGeneration(identity, current)) return { result: "conflict" };
1935
- if (current.state === "cleared" && current.retired === true) return { result: "applied" };
1936
- return {
1937
- result: "applied",
1938
- next: {
1939
- version: 1,
1940
- state: "cleared",
1941
- retired: true,
1942
- ...storedSessionGeneration(identity, current),
1943
- ...current.lease && current.lease.token === leaseToken ? { lease: current.lease } : {}
1944
- }
1945
- };
1946
- }, identity.sessionKey?.trim() ? void 0 : PHYSICAL_SESSION_RETIRE_TTL_MS);
1947
- });
1948
- },
1949
- async withThreadArchiveFence(run) {
1950
- pendingArchives += 1;
1951
- const operation = archiveTail.then(async () => {
1952
- await waitForBindingMutations();
1953
- return await archiveContext.run(true, run);
1954
- });
1955
- archiveTail = operation.then(() => void 0, () => void 0);
1956
- try {
1957
- return await operation;
1958
- } finally {
1959
- pendingArchives -= 1;
1960
- }
1961
- },
1962
- async withLease(identity, run) {
1963
- const key = bindingStoreKey(identity);
1964
- const owned = leaseContext.getStore();
1965
- const existingOwner = owned?.get(key);
1966
- if (existingOwner) {
1967
- const failureBeforeRun = existingOwner.failure;
1968
- if (failureBeforeRun) throw failureBeforeRun;
1969
- const result = await run();
1970
- const failureAfterRun = existingOwner.failure;
1971
- if (failureAfterRun) throw failureAfterRun;
1972
- return result;
1973
- }
1974
- const token = randomUUID();
1975
- if (!await transactKey(key, (current) => {
1976
- if (current?.state === "cleared" && current.retired === true && ownsStoredSessionGeneration(identity, current)) return { result: false };
1977
- const lease = {
1978
- token,
1979
- expiresAt: Date.now() + BINDING_LEASE_STALE_MS
1980
- };
1981
- if (current?.state === "active") return {
1982
- result: true,
1983
- next: {
1984
- ...current,
1985
- ...preservedSessionGeneration(identity, current),
1986
- lease
1987
- }
1988
- };
1989
- if (current?.state === "cleared" && current.retired === true) return {
1990
- result: true,
1991
- next: {
1992
- ...current,
1993
- lease
1994
- }
1995
- };
1996
- return {
1997
- result: true,
1998
- next: {
1999
- version: 1,
2000
- state: "cleared",
2001
- ...preservedSessionGeneration(identity, current),
2002
- lease
2003
- }
2004
- };
2005
- })) throw new Error(`Codex binding generation was retired: ${key}`);
2006
- const owner = { token };
2007
- const nested = new Map(owned);
2008
- nested.set(key, owner);
2009
- const heartbeat = setInterval(() => renewLease(key, owner), BINDING_LEASE_RENEW_INTERVAL_MS);
2010
- heartbeat.unref();
2011
- try {
2012
- const result = await leaseContext.run(nested, run);
2013
- if (owner.failure) throw owner.failure;
2014
- return result;
2015
- } finally {
2016
- clearInterval(heartbeat);
2017
- try {
2018
- const removeOwnedLease = (raw, matches) => {
2019
- const current = readStoredCodexAppServerBinding(raw);
2020
- if (!current || !matches(current) || current.lease?.token !== token) return;
2021
- const { lease: _lease, ...released } = current;
2022
- return released;
2023
- };
2024
- if (!update(key, (raw) => removeOwnedLease(raw, (current) => current.state === "active"))) {
2025
- 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 });
2026
- }
2027
- } catch (error) {
2028
- embeddedAgentLog.warn("failed to release codex app-server binding lease", {
2029
- key,
2030
- error
2031
- });
2032
- }
2033
- }
2034
- }
2035
- };
2036
- }
2037
- function matchesPendingSupervisionBranch(binding, expected) {
2038
- const pending = binding?.pendingSupervisionBranch;
2039
- if (!pending || binding?.threadId !== expected.sourceThreadId) return false;
2040
- if (pending.sourceThreadId !== expected.sourceThreadId || pending.connectionFingerprint !== expected.connectionFingerprint || pending.lastTurnId !== expected.lastTurnId) return false;
2041
- const currentCleanup = pending.cleanupThreadIds ?? [];
2042
- const expectedCleanup = expected.cleanupThreadIds ?? [];
2043
- return currentCleanup.length === expectedCleanup.length && currentCleanup.every((threadId, index) => threadId === expectedCleanup[index]);
2044
- }
2045
- function isSameSupervisionOwner(current, replacement) {
2046
- return replacement.connectionScope === "supervision" && replacement.threadId === current.threadId && replacement.supervisionSourceThreadId === current.supervisionSourceThreadId;
2047
- }
2048
- function matchesPendingSupervisionClear(binding, threadId, expected) {
2049
- if (!expected) return false;
2050
- const sourceThreadId = expected.sourceThreadId;
2051
- return threadId === sourceThreadId && binding.supervisionSourceThreadId === sourceThreadId && matchesPendingSupervisionBranch(binding, expected);
2052
- }
2053
- /** Stable plugin-state key for one current binding owner. */
2054
- function bindingStoreKey(identity) {
2055
- if (identity.kind === "session") {
2056
- const rawAgentId = identity.agentId.trim();
2057
- const sessionId = identity.sessionId.trim();
2058
- if (!rawAgentId) throw new Error("Codex app-server binding requires an agent id");
2059
- if (!sessionId) throw new Error("Codex app-server binding requires a session id");
2060
- const agentId = resolveSessionAgentIds$1({ agentId: rawAgentId }).sessionAgentId;
2061
- const sessionKey = identity.sessionKey?.trim();
2062
- if (sessionKey) return `session-key:${agentId}:${createHash("sha256").update(sessionKey).digest("base64url")}`;
2063
- return `session:${agentId}:${sessionId}`;
2064
- }
2065
- const bindingId = identity.bindingId.trim();
2066
- if (!bindingId) throw new Error("Codex app-server conversation binding requires a binding id");
2067
- return `conversation:${bindingId}`;
2068
- }
2069
- function readStoredCodexAppServerBinding(value) {
2070
- const result = storedBindingSchema.safeParse(value);
2071
- return result.success ? stripUndefinedValue(result.data) : void 0;
2072
- }
2073
- function storedSessionGeneration(identity, current) {
2074
- if (identity.kind === "session") return { sessionId: identity.sessionId };
2075
- return current?.sessionId ? { sessionId: current.sessionId } : {};
2076
- }
2077
- function preservedSessionGeneration(identity, current) {
2078
- if (current?.sessionId) return { sessionId: current.sessionId };
2079
- return storedSessionGeneration(identity, current);
2080
- }
2081
- function ownsStoredSessionGeneration(identity, current) {
2082
- return identity.kind !== "session" || !current?.sessionId || current.sessionId === identity.sessionId;
2083
- }
2084
- function validateBindingForWrite(binding) {
2085
- const validated = readCodexAppServerThreadBinding(binding);
2086
- if (!validated) throw new Error("Invalid Codex app-server thread binding");
2087
- return stripUndefinedBinding(validated);
2088
- }
2089
- /** Parses stored or shipped sidecar data into the current domain value. */
2090
- function readCodexAppServerThreadBinding(value) {
2091
- const result = threadBindingSchema.safeParse(value);
2092
- if (!result.success) return;
2093
- return result.data;
2094
- }
2095
- function stripUndefinedBinding(binding) {
2096
- return stripUndefinedValue(binding);
2097
- }
2098
- function stripUndefinedValue(value) {
2099
- if (Array.isArray(value)) return value.map(stripUndefinedValue);
2100
- if (!value || typeof value !== "object") return value;
2101
- return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== void 0).map(([key, entry]) => [key, stripUndefinedValue(entry)]));
2102
- }
2103
- function readTimestamp(value) {
2104
- return optionalTimestampSchema.parse(value);
2105
- }
2106
- function readPluginAppPolicyContext(value, bindingSchemaVersion) {
2107
- const record = asOptionalRecord(value);
2108
- if (!record || typeof record.fingerprint !== "string") return;
2109
- const apps = asOptionalRecord(record.apps);
2110
- if (!apps) return;
2111
- const parsedApps = {};
2112
- for (const [appId, rawEntry] of Object.entries(apps)) {
2113
- const entry = asOptionalRecord(rawEntry);
2114
- if (!entry) return;
2115
- const destructiveApprovalMode = readDestructiveApprovalMode(entry.destructiveApprovalMode, bindingSchemaVersion);
2116
- const mcpServerNamesValid = Array.isArray(entry.mcpServerNames) && entry.mcpServerNames.every((serverName) => typeof serverName === "string");
2117
- if (entry.source === "account") {
2118
- if ("appId" in entry || typeof entry.appName !== "string" || typeof entry.allowDestructiveActions !== "boolean" || entry.allowOpenWorld !== void 0 && typeof entry.allowOpenWorld !== "boolean" || destructiveApprovalMode === "invalid" || !mcpServerNamesValid) return;
2119
- parsedApps[appId] = {
2120
- source: "account",
2121
- appName: entry.appName,
2122
- allowDestructiveActions: entry.allowDestructiveActions,
2123
- ...typeof entry.allowOpenWorld === "boolean" ? { allowOpenWorld: entry.allowOpenWorld } : {},
2124
- ...destructiveApprovalMode ? { destructiveApprovalMode } : {},
2125
- mcpServerNames: entry.mcpServerNames
2126
- };
2127
- continue;
2128
- }
2129
- if ("appId" in entry || entry.source !== void 0 && entry.source !== "plugin" || typeof entry.configKey !== "string" || typeof entry.marketplaceName !== "string" || !CODEX_PLUGIN_MARKETPLACE_NAME_PATTERN.test(entry.marketplaceName) || typeof entry.pluginName !== "string" || typeof entry.allowDestructiveActions !== "boolean" || entry.allowOpenWorld !== void 0 && typeof entry.allowOpenWorld !== "boolean" || destructiveApprovalMode === "invalid" || !mcpServerNamesValid) return;
2130
- parsedApps[appId] = {
2131
- configKey: entry.configKey,
2132
- marketplaceName: entry.marketplaceName,
2133
- pluginName: entry.pluginName,
2134
- allowDestructiveActions: entry.allowDestructiveActions,
2135
- ...typeof entry.allowOpenWorld === "boolean" ? { allowOpenWorld: entry.allowOpenWorld } : {},
2136
- ...destructiveApprovalMode ? { destructiveApprovalMode } : {},
2137
- mcpServerNames: entry.mcpServerNames
2138
- };
2139
- }
2140
- const parsedPluginAppIds = {};
2141
- if (record.pluginAppIds !== void 0 && (!record.pluginAppIds || typeof record.pluginAppIds !== "object" || Array.isArray(record.pluginAppIds))) return;
2142
- if (record.pluginAppIds && typeof record.pluginAppIds === "object") for (const [configKey, appIds] of Object.entries(record.pluginAppIds)) {
2143
- if (!Array.isArray(appIds) || appIds.some((appId) => typeof appId !== "string")) return;
2144
- parsedPluginAppIds[configKey] = appIds;
2145
- }
2146
- return {
2147
- fingerprint: record.fingerprint,
2148
- apps: parsedApps,
2149
- pluginAppIds: parsedPluginAppIds
2150
- };
2151
- }
2152
- function readDestructiveApprovalMode(value, bindingSchemaVersion) {
2153
- if (value === void 0) return;
2154
- if (value === "allow" || value === "deny") return value;
2155
- if (value === "auto") return bindingSchemaVersion === 1 ? "allow" : "auto";
2156
- if (value === "ask" && bindingSchemaVersion === 2) return "ask";
2157
- if (value === "on-request" && bindingSchemaVersion === 1) return "auto";
2158
- return "invalid";
2159
- }
2160
- function sleep(ms) {
2161
- return new Promise((resolve) => {
2162
- setTimeout(resolve, ms);
2163
- });
2164
- }
2165
- /** Returns true when an auth profile uses native Codex/OpenAI app-server auth. */
2166
- function isCodexAppServerNativeAuthProfile(lookup) {
2167
- const authProfileId = lookup.authProfileId?.trim();
2168
- if (!authProfileId) return false;
2169
- try {
2170
- const credential = (lookup.authProfileStore ?? ensureAuthProfileStore(lookup.agentDir?.trim() || resolveDefaultAgentDir(lookup.config ?? {}), {
2171
- allowKeychainPrompt: false,
2172
- config: lookup.config,
2173
- externalCliProviderIds: [CODEX_APP_SERVER_NATIVE_AUTH_PROVIDER],
2174
- externalCliProfileIds: [authProfileId]
2175
- })).profiles[authProfileId];
2176
- if (!credential || credential.type === "api_key") return false;
2177
- const provider = credential.provider?.trim();
2178
- return Boolean(provider && resolveProviderIdForAuth(provider, { config: lookup.config }) === CODEX_APP_SERVER_NATIVE_AUTH_PROVIDER);
2179
- } catch (error) {
2180
- embeddedAgentLog.debug("failed to resolve codex app-server auth profile provider", {
2181
- authProfileId,
2182
- error
2183
- });
2184
- return false;
2185
- }
2186
- }
2187
- /** Hides redundant OpenAI provider attribution for native Codex auth bindings. */
2188
- function normalizeCodexAppServerBindingModelProvider(params) {
2189
- const modelProvider = params.modelProvider?.trim();
2190
- if (!modelProvider) return;
2191
- if (isCodexAppServerNativeAuthProfile(params) && modelProvider.toLowerCase() === PUBLIC_OPENAI_MODEL_PROVIDER) return;
2192
- return modelProvider;
2193
- }
2194
- //#endregion
2195
- export { resolveCodexAppServerUserHomeDir as A, isCodexRemoteExecPlacementSandbox as C, CODEX_PLUGINS_MARKETPLACE_NAME as D, resolveCodexPluginsPolicy as E, isCodexAppServerApprovalPolicyAllowedByRequirements as M, resolveOpenClawExecPolicyForCodexAppServer as N, CODEX_PLUGINS_WORKSPACE_MARKETPLACE_NAME as O, isCodexFastServiceTier as P, withMcpElicitationsApprovalPolicy as S, readCodexPluginConfig as T, resolveCodexAppServerStartOptionsForAgent as _, hashCodexAppServerBindingFingerprint as a, assertCodexAppServerConnectionSecurity as b, reclaimCurrentCodexSessionGeneration as c, sessionBindingIdentity as d, session_binding_exports as f, resolveCodexAppServerRuntimeOptions as g, resolveCodexAppServerHomeScope as h, createCodexSessionGenerationSupersededError as i, resolveCodexModelBackedReviewerPolicyContext as j, canUseCodexModelBackedApprovalsReviewerForModel as k, resolveCodexRunSessionBindingAuthority as l, codexSandboxPolicyForTurn as m, assertCodexBindingMayBeReplaced as n, isCodexAppServerNativeAuthProfile as o, codexAppServerStartOptionsKey as p, bindingStoreKey as r, normalizeCodexAppServerBindingModelProvider as s, CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS as t, scopeCodexRunBindingStore as u, resolveCodexComputerUseConfig as v, isCodexSandboxExecServerEnabled as w, shouldAutoApproveCodexAppServerApprovals as x, resolveCodexSupervisionAppServerRuntimeOptions as y };
1389
+ export { selectUserApprovalsReviewer as A, resolveCodexModelBackedReviewerPolicyContext as C, readCodexRequirementsToml as D, parseAllowedSandboxModesFromCodexRequirements as E, selectGuardianSandbox as M, isCodexFastServiceTier as N, selectGuardianApprovalPolicy as O, normalizeCodexServiceTier as P, resolveCodexAppServerUserHomeDir as S, parseAllowedApprovalsReviewersFromCodexRequirements as T, CODEX_PLUGINS_MARKETPLACE_NAME as _, resolveCodexAppServerStartOptionsForAgent as a, assertCodexModelBackedReviewerEffectiveConfig as b, assertCodexAppServerConnectionSecurity as c, withMcpElicitationsApprovalPolicy as d, isCodexPairedNodeRemoteExecPlacementSandbox as f, resolveCodexPluginsPolicy as g, readCodexPluginConfig as h, resolveCodexAppServerRuntimeOptions as i, resolveOpenClawExecPolicyForCodexAppServer as j, selectGuardianApprovalsReviewer as k, resolveCodexAppServerNetworkProxy as l, isCodexSandboxExecServerEnabled as m, codexSandboxPolicyForTurn as n, resolveCodexComputerUseConfig as o, isCodexRemoteExecPlacementSandbox as p, resolveCodexAppServerHomeScope as r, resolveCodexSupervisionAppServerRuntimeOptions as s, codexAppServerStartOptionsKey as t, shouldAutoApproveCodexAppServerApprovals as u, CODEX_PLUGINS_WORKSPACE_MARKETPLACE_NAME as v, parseAllowedApprovalPoliciesFromCodexRequirements as w, canUseCodexModelBackedApprovalsReviewerForModel as x, CODEX_PLUGIN_MARKETPLACE_NAME_PATTERN as y };