Skip to content

Commit 49a1f9b

Browse files
CopilotKSemenenko
andcommitted
Changes before error encountered
Co-authored-by: KSemenenko <4385716+KSemenenko@users.noreply.github.com>
1 parent ef992d0 commit 49a1f9b

File tree

4 files changed

+348
-5
lines changed

4 files changed

+348
-5
lines changed

CodexSharpSDK.Tests/Unit/CodexExecTests.cs

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,8 @@ public async Task BuildCommandArgs_MapsExtendedCliFlags()
128128
Color = ExecOutputColor.Never,
129129
ProgressCursor = true,
130130
OutputLastMessageFile = "/tmp/last-message.txt",
131-
EnabledFeatures = ["multi_agent", "unified_exec"],
132-
DisabledFeatures = ["steer"],
131+
EnabledFeatures = [CodexFeatureFlags.MultiAgent, CodexFeatureFlags.UnifiedExec],
132+
DisabledFeatures = [CodexFeatureFlags.Steer],
133133
AdditionalCliArguments = ["--some-future-flag", "custom-value"],
134134
});
135135

@@ -144,13 +144,38 @@ public async Task BuildCommandArgs_MapsExtendedCliFlags()
144144
await Assert.That(commandArgs.Contains("--ephemeral")).IsTrue();
145145
await Assert.That(commandArgs.Contains("--progress-cursor")).IsTrue();
146146

147-
await Assert.That(CollectFlagValues(commandArgs, "--enable")).IsEquivalentTo(["multi_agent", "unified_exec"]);
148-
await Assert.That(CollectFlagValues(commandArgs, "--disable")).IsEquivalentTo(["steer"]);
147+
await Assert.That(CollectFlagValues(commandArgs, "--enable")).IsEquivalentTo([CodexFeatureFlags.MultiAgent, CodexFeatureFlags.UnifiedExec]);
148+
await Assert.That(CollectFlagValues(commandArgs, "--disable")).IsEquivalentTo([CodexFeatureFlags.Steer]);
149149

150150
await Assert.That(commandArgs.Contains("--some-future-flag")).IsTrue();
151151
await Assert.That(commandArgs.Contains("custom-value")).IsTrue();
152152
}
153153

154+
[Test]
155+
public async Task BuildCommandArgs_MapsNewUpstreamFeatureFlags()
156+
{
157+
var exec = new CodexExec("codex", null, null);
158+
159+
var commandArgs = exec.BuildCommandArgs(new CodexExecArgs
160+
{
161+
Input = "test",
162+
EnabledFeatures =
163+
[
164+
CodexFeatureFlags.GuardianApproval,
165+
CodexFeatureFlags.RequestPermissionsTool,
166+
CodexFeatureFlags.ToolCallMcpElicitation,
167+
],
168+
});
169+
170+
await Assert.That(CollectFlagValues(commandArgs, "--enable"))
171+
.IsEquivalentTo(
172+
[
173+
CodexFeatureFlags.GuardianApproval,
174+
CodexFeatureFlags.RequestPermissionsTool,
175+
CodexFeatureFlags.ToolCallMcpElicitation,
176+
]);
177+
}
178+
154179
[Test]
155180
public async Task BuildCommandArgs_KeepsConfiguredWebSearchWhenThreadOverridesMissing()
156181
{
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
namespace ManagedCode.CodexSharpSDK.Models;
2+
3+
/// <summary>
4+
/// Known Codex CLI feature flag identifiers for use with
5+
/// <see cref="ManagedCode.CodexSharpSDK.Client.ThreadOptions.EnabledFeatures"/> and
6+
/// <see cref="ManagedCode.CodexSharpSDK.Client.ThreadOptions.DisabledFeatures"/>.
7+
/// Feature flags are passed to the CLI via <c>--enable</c> and <c>--disable</c>.
8+
/// </summary>
9+
public static class CodexFeatureFlags
10+
{
11+
// --- Approval / sandbox ---
12+
public const string GuardianApproval = "guardian_approval";
13+
public const string RequestPermissions = "request_permissions";
14+
public const string RequestPermissionsTool = "request_permissions_tool";
15+
16+
// --- Execution ---
17+
public const string UnifiedExec = "unified_exec";
18+
public const string ExperimentalUseUnifiedExecTool = "experimental_use_unified_exec_tool";
19+
public const string ShellTool = "shell_tool";
20+
public const string ShellSnapshot = "shell_snapshot";
21+
public const string ShellZshFork = "shell_zsh_fork";
22+
public const string UseLinuxSandboxBwrap = "use_linux_sandbox_bwrap";
23+
24+
// --- Apply patch ---
25+
public const string ApplyPatchFreeform = "apply_patch_freeform";
26+
public const string ExperimentalUseFreeformApplyPatch = "experimental_use_freeform_apply_patch";
27+
public const string IncludeApplyPatchTool = "include_apply_patch_tool";
28+
29+
// --- MCP / tool calling ---
30+
public const string ToolCallMcpElicitation = "tool_call_mcp_elicitation";
31+
32+
// --- Multi-agent / collaboration ---
33+
public const string MultiAgent = "multi_agent";
34+
public const string Collab = "collab";
35+
public const string CollaborationModes = "collaboration_modes";
36+
public const string ChildAgentsMd = "child_agents_md";
37+
public const string Steer = "steer";
38+
39+
// --- Search ---
40+
public const string SearchTool = "search_tool";
41+
public const string WebSearch = "web_search";
42+
public const string WebSearchCached = "web_search_cached";
43+
public const string WebSearchRequest = "web_search_request";
44+
45+
// --- Memory ---
46+
public const string Memories = "memories";
47+
public const string MemoryTool = "memory_tool";
48+
49+
// --- Image ---
50+
public const string ImageGeneration = "image_generation";
51+
public const string ImageDetailOriginal = "image_detail_original";
52+
53+
// --- Plugins / apps ---
54+
public const string Plugins = "plugins";
55+
public const string Apps = "apps";
56+
public const string AppsMcpGateway = "apps_mcp_gateway";
57+
public const string Connectors = "connectors";
58+
59+
// --- JS REPL ---
60+
public const string JsRepl = "js_repl";
61+
public const string JsReplToolsOnly = "js_repl_tools_only";
62+
63+
// --- Realtime ---
64+
public const string RealtimeConversation = "realtime_conversation";
65+
public const string VoiceTranscription = "voice_transcription";
66+
67+
// --- Windows sandbox ---
68+
public const string ExperimentalWindowsSandbox = "experimental_windows_sandbox";
69+
public const string EnableExperimentalWindowsSandbox = "enable_experimental_windows_sandbox";
70+
public const string ElevatedWindowsSandbox = "elevated_windows_sandbox";
71+
public const string PowershellUtf8 = "powershell_utf8";
72+
73+
// --- Storage / DB ---
74+
public const string Sqlite = "sqlite";
75+
public const string RemoteModels = "remote_models";
76+
77+
// --- Networking / transport ---
78+
public const string ResponsesWebsockets = "responses_websockets";
79+
public const string ResponsesWebsocketsV2 = "responses_websockets_v2";
80+
public const string EnableRequestCompression = "enable_request_compression";
81+
82+
// --- Misc ---
83+
public const string FastMode = "fast_mode";
84+
public const string Artifact = "artifact";
85+
public const string RequestRule = "request_rule";
86+
public const string RuntimeMetrics = "runtime_metrics";
87+
public const string Undo = "undo";
88+
public const string Personality = "personality";
89+
public const string SkillEnvVarDependencyPrompt = "skill_env_var_dependency_prompt";
90+
public const string SkillMcpDependencyInstall = "skill_mcp_dependency_install";
91+
public const string CodexGitCommit = "codex_git_commit";
92+
public const string DefaultModeRequestUserInput = "default_mode_request_user_input";
93+
public const string PreventIdleSleep = "prevent_idle_sleep";
94+
}

docs/Features/feature-flags.md

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
# Feature: Feature Flags
2+
3+
Links:
4+
Architecture: [docs/Architecture/Overview.md](../Architecture/Overview.md)
5+
Modules: [CodexSharpSDK/Models/CodexFeatureFlags.cs](../../CodexSharpSDK/Models/CodexFeatureFlags.cs), [CodexSharpSDK/Client/ThreadOptions.cs](../../CodexSharpSDK/Client/ThreadOptions.cs)
6+
ADRs: [001-codex-cli-wrapper.md](../ADR/001-codex-cli-wrapper.md)
7+
8+
---
9+
10+
## Purpose
11+
12+
Expose Codex CLI feature flags through the SDK so consumers can enable or disable experimental and optional capabilities without relying on magic string literals.
13+
14+
---
15+
16+
## Scope
17+
18+
### In scope
19+
20+
- `CodexFeatureFlags` constants class mirroring the `features` block from `codex-rs/core/config.schema.json`
21+
- `ThreadOptions.EnabledFeatures` / `ThreadOptions.DisabledFeatures` accepting these constants
22+
- `CodexExecArgs.EnabledFeatures` / `CodexExecArgs.DisabledFeatures` for low-level exec control
23+
24+
### Out of scope
25+
26+
- Deciding which flags to enable at runtime (consumer responsibility)
27+
- Feature flag semantics (controlled entirely by the Codex CLI)
28+
29+
---
30+
31+
## Business Rules
32+
33+
- Feature flag identifiers must match the Codex CLI's `config.schema.json` exactly; never invent new names.
34+
- SDK ships constants for every known flag at the pinned submodule commit so consumers have compile-time safety.
35+
- New flags added by upstream syncs must be added to `CodexFeatureFlags` in the same PR that updates the submodule.
36+
- Raw string literals for feature flags are not permitted in SDK production code or tests; always use `CodexFeatureFlags` constants.
37+
38+
---
39+
40+
## Usage
41+
42+
```csharp
43+
using ManagedCode.CodexSharpSDK.Models;
44+
45+
var thread = client.StartThread(new ThreadOptions
46+
{
47+
// Enable guardian approval and request-permissions tool (added in upstream sync 06f82c1)
48+
EnabledFeatures = [
49+
CodexFeatureFlags.GuardianApproval,
50+
CodexFeatureFlags.RequestPermissionsTool,
51+
],
52+
// Disable MCP elicitation
53+
DisabledFeatures = [
54+
CodexFeatureFlags.ToolCallMcpElicitation,
55+
],
56+
});
57+
```
58+
59+
---
60+
61+
## Known Feature Flags
62+
63+
Sourced from `submodules/openai-codex/codex-rs/core/config.schema.json` at pinned commit.
64+
65+
### Approval / sandbox
66+
67+
| Constant | CLI string | Notes |
68+
|---|---|---|
69+
| `GuardianApproval` | `guardian_approval` | Guardian-based approval gate |
70+
| `RequestPermissions` | `request_permissions` | Permission request flow |
71+
| `RequestPermissionsTool` | `request_permissions_tool` | Request-permissions as a tool call |
72+
73+
### Execution
74+
75+
| Constant | CLI string |
76+
|---|---|
77+
| `UnifiedExec` | `unified_exec` |
78+
| `ExperimentalUseUnifiedExecTool` | `experimental_use_unified_exec_tool` |
79+
| `ShellTool` | `shell_tool` |
80+
| `ShellSnapshot` | `shell_snapshot` |
81+
| `ShellZshFork` | `shell_zsh_fork` |
82+
| `UseLinuxSandboxBwrap` | `use_linux_sandbox_bwrap` |
83+
84+
### Apply patch
85+
86+
| Constant | CLI string |
87+
|---|---|
88+
| `ApplyPatchFreeform` | `apply_patch_freeform` |
89+
| `ExperimentalUseFreeformApplyPatch` | `experimental_use_freeform_apply_patch` |
90+
| `IncludeApplyPatchTool` | `include_apply_patch_tool` |
91+
92+
### MCP / tool calling
93+
94+
| Constant | CLI string | Notes |
95+
|---|---|---|
96+
| `ToolCallMcpElicitation` | `tool_call_mcp_elicitation` | MCP-style elicitation for tool approvals |
97+
98+
### Multi-agent / collaboration
99+
100+
| Constant | CLI string |
101+
|---|---|
102+
| `MultiAgent` | `multi_agent` |
103+
| `Collab` | `collab` |
104+
| `CollaborationModes` | `collaboration_modes` |
105+
| `ChildAgentsMd` | `child_agents_md` |
106+
| `Steer` | `steer` |
107+
108+
### Search
109+
110+
| Constant | CLI string |
111+
|---|---|
112+
| `SearchTool` | `search_tool` |
113+
| `WebSearch` | `web_search` |
114+
| `WebSearchCached` | `web_search_cached` |
115+
| `WebSearchRequest` | `web_search_request` |
116+
117+
### Memory
118+
119+
| Constant | CLI string |
120+
|---|---|
121+
| `Memories` | `memories` |
122+
| `MemoryTool` | `memory_tool` |
123+
124+
### Image
125+
126+
| Constant | CLI string |
127+
|---|---|
128+
| `ImageGeneration` | `image_generation` |
129+
| `ImageDetailOriginal` | `image_detail_original` |
130+
131+
### Plugins / apps
132+
133+
| Constant | CLI string |
134+
|---|---|
135+
| `Plugins` | `plugins` |
136+
| `Apps` | `apps` |
137+
| `AppsMcpGateway` | `apps_mcp_gateway` |
138+
| `Connectors` | `connectors` |
139+
140+
### JS REPL
141+
142+
| Constant | CLI string |
143+
|---|---|
144+
| `JsRepl` | `js_repl` |
145+
| `JsReplToolsOnly` | `js_repl_tools_only` |
146+
147+
### Realtime
148+
149+
| Constant | CLI string |
150+
|---|---|
151+
| `RealtimeConversation` | `realtime_conversation` |
152+
| `VoiceTranscription` | `voice_transcription` |
153+
154+
### Windows sandbox
155+
156+
| Constant | CLI string |
157+
|---|---|
158+
| `ExperimentalWindowsSandbox` | `experimental_windows_sandbox` |
159+
| `EnableExperimentalWindowsSandbox` | `enable_experimental_windows_sandbox` |
160+
| `ElevatedWindowsSandbox` | `elevated_windows_sandbox` |
161+
| `PowershellUtf8` | `powershell_utf8` |
162+
163+
### Storage / DB
164+
165+
| Constant | CLI string |
166+
|---|---|
167+
| `Sqlite` | `sqlite` |
168+
| `RemoteModels` | `remote_models` |
169+
170+
### Networking / transport
171+
172+
| Constant | CLI string |
173+
|---|---|
174+
| `ResponsesWebsockets` | `responses_websockets` |
175+
| `ResponsesWebsocketsV2` | `responses_websockets_v2` |
176+
| `EnableRequestCompression` | `enable_request_compression` |
177+
178+
### Miscellaneous
179+
180+
| Constant | CLI string |
181+
|---|---|
182+
| `FastMode` | `fast_mode` |
183+
| `Artifact` | `artifact` |
184+
| `RequestRule` | `request_rule` |
185+
| `RuntimeMetrics` | `runtime_metrics` |
186+
| `Undo` | `undo` |
187+
| `Personality` | `personality` |
188+
| `SkillEnvVarDependencyPrompt` | `skill_env_var_dependency_prompt` |
189+
| `SkillMcpDependencyInstall` | `skill_mcp_dependency_install` |
190+
| `CodexGitCommit` | `codex_git_commit` |
191+
| `DefaultModeRequestUserInput` | `default_mode_request_user_input` |
192+
| `PreventIdleSleep` | `prevent_idle_sleep` |
193+
194+
---
195+
196+
## Diagrams
197+
198+
```mermaid
199+
flowchart LR
200+
Consumer["Consumer code"] -->|"EnabledFeatures / DisabledFeatures"| ThreadOptions
201+
ThreadOptions --> CodexExec["CodexExec.BuildCommandArgs()"]
202+
CodexExec -->|"--enable guardian_approval\n--disable steer"| CLI["codex exec CLI"]
203+
CodexFeatureFlags["CodexFeatureFlags constants"] -.->|"type-safe identifiers"| Consumer
204+
```
205+
206+
---
207+
208+
## Upstream sync
209+
210+
Feature flags are kept in sync with the pinned `submodules/openai-codex` submodule.
211+
When the submodule is updated, compare `codex-rs/core/config.schema.json` `.properties.features.properties` against `CodexFeatureFlags` and add any new entries.
212+
213+
Flags added by upstream sync `6638558b88 → 06f82c123c` (2026-03-08):
214+
- `guardian_approval` — guardian approval MVP
215+
- `request_permissions_tool` — request permissions as a tool call
216+
- `tool_call_mcp_elicitation` — MCP-style elicitation for tool-call approvals
217+
218+
---
219+
220+
## Definition of Done
221+
222+
- `CodexFeatureFlags` constants match all `features` entries in pinned `config.schema.json`.
223+
- Tests in `CodexExecTests` use `CodexFeatureFlags` constants (no raw string literals).
224+
- Documentation table is complete and up to date.

submodules/openai-codex

Submodule openai-codex updated 390 files

0 commit comments

Comments
 (0)