Mirror @openai/codex-sdk's `codex exec --experimental-json` invocation.
(
options: TextOptions<CodexTextProviderOptions>,
resume: string | undefined,
bridge: HostToolBridge | undefined,
policyFlags: CodexPolicyFlags,
)
| 121 | |
| 122 | /** Mirror @openai/codex-sdk's `codex exec --experimental-json` invocation. */ |
| 123 | private buildCommand( |
| 124 | options: TextOptions<CodexTextProviderOptions>, |
| 125 | resume: string | undefined, |
| 126 | bridge: HostToolBridge | undefined, |
| 127 | policyFlags: CodexPolicyFlags, |
| 128 | ): string { |
| 129 | const config = this.adapterConfig |
| 130 | const modelOptions = options.modelOptions |
| 131 | const exe = config.codexExecutable ?? 'codex' |
| 132 | const args: Array<string> = ['exec', '--experimental-json'] |
| 133 | |
| 134 | // Precedence: per-call modelOptions > adapter config > sandbox policy > default. |
| 135 | const sandboxMode = |
| 136 | modelOptions?.sandboxMode ?? |
| 137 | config.sandboxMode ?? |
| 138 | policyFlags.sandboxMode ?? |
| 139 | 'workspace-write' |
| 140 | const approvalPolicy = |
| 141 | modelOptions?.approvalPolicy ?? |
| 142 | config.approvalPolicy ?? |
| 143 | policyFlags.approvalPolicy ?? |
| 144 | 'never' |
| 145 | const networkAccessEnabled = |
| 146 | config.networkAccessEnabled ?? policyFlags.networkAccessEnabled |
| 147 | const reasoning = |
| 148 | modelOptions?.modelReasoningEffort ?? config.modelReasoningEffort |
| 149 | const skipGitRepoCheck = |
| 150 | modelOptions?.skipGitRepoCheck ?? config.skipGitRepoCheck |
| 151 | |
| 152 | args.push('--model', q(this.model)) |
| 153 | args.push('--sandbox', q(sandboxMode)) |
| 154 | // NOTE: do NOT pass `--cd <cwd>`. `cwd` is the VIRTUAL `/workspace` root; the |
| 155 | // provider handle already maps it to the sandbox's real workdir and runs the |
| 156 | // process there (e.g. Daytona's `/home/daytona/workspace`). Passing it as a |
| 157 | // literal `--cd` makes codex chdir to a path that doesn't exist on the real |
| 158 | // filesystem → "No such file or directory (os error 2)". Codex inherits the |
| 159 | // handle-set process cwd instead. |
| 160 | if (skipGitRepoCheck !== false) args.push('--skip-git-repo-check') |
| 161 | for (const dir of config.additionalDirectories ?? []) { |
| 162 | args.push('--add-dir', q(dir)) |
| 163 | } |
| 164 | |
| 165 | const cfg: Record<string, string> = { |
| 166 | approval_policy: `"${approvalPolicy}"`, |
| 167 | ...(reasoning ? { model_reasoning_effort: `"${reasoning}"` } : {}), |
| 168 | ...(networkAccessEnabled !== undefined |
| 169 | ? { |
| 170 | 'sandbox_workspace_write.network_access': |
| 171 | String(networkAccessEnabled), |
| 172 | } |
| 173 | : {}), |
| 174 | ...(config.webSearchMode |
| 175 | ? { web_search: `"${config.webSearchMode}"` } |
| 176 | : {}), |
| 177 | // Bridge chat()-provided tools via a streamable-HTTP MCP server. A `url` |
| 178 | // makes codex use its streamable-HTTP transport, which authenticates via an |
| 179 | // `Authorization` header — codex REJECTS inline `bearer_token` for this |
| 180 | // transport ("bearer_token is not supported for streamable_http"; that field |
no test coverage detected