Skip to content

Commit 42428d0

Browse files
CopilotKSemenenko
andcommitted
Changes before error encountered
Co-authored-by: KSemenenko <4385716+KSemenenko@users.noreply.github.com>
1 parent 6a2bce9 commit 42428d0

File tree

4 files changed

+192
-2
lines changed

4 files changed

+192
-2
lines changed
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
using System.Reflection;
2+
using System.Text.Json;
3+
using ManagedCode.CodexSharpSDK.Models;
4+
5+
namespace ManagedCode.CodexSharpSDK.Tests.Unit;
6+
7+
public class CodexFeaturesTests
8+
{
9+
private const string SolutionFileName = "ManagedCode.CodexSharpSDK.slnx";
10+
private const string BundledConfigSchemaFileName = "config.schema.json";
11+
12+
[Test]
13+
public async Task CodexFeatures_NewUpstreamFlags_ArePresent()
14+
{
15+
// These two flags were added in upstream commit 3b5fe5c and are the primary
16+
// motivation for this sync. Verify the constants are present and map to the correct
17+
// upstream key strings by resolving them via reflection (avoiding a constant-vs-constant
18+
// comparison that the analyzer rightly flags as a no-op assertion).
19+
var sdkValues = GetSdkFeatureValues();
20+
await Assert.That(sdkValues).Contains("guardian_approval");
21+
await Assert.That(sdkValues).Contains("tool_call_mcp_elicitation");
22+
}
23+
24+
[Test]
25+
public async Task CodexFeatures_AllConstantsAreValidUpstreamFeatureKeys()
26+
{
27+
var schemaFeatureKeys = await ReadBundledSchemaFeatureKeysAsync();
28+
var sdkFeatureValues = GetSdkFeatureValues();
29+
var invalidKeys = sdkFeatureValues
30+
.Except(schemaFeatureKeys, StringComparer.Ordinal)
31+
.ToArray();
32+
33+
await Assert.That(invalidKeys).IsEmpty();
34+
}
35+
36+
[Test]
37+
public async Task CodexFeatures_CoversAllCanonicalUpstreamFeatureKeys()
38+
{
39+
// The canonical (non-alias) keys from features.rs must all have an SDK constant so
40+
// that callers can reference them without magic strings.
41+
var schemaFeatureKeys = await ReadBundledSchemaFeatureKeysAsync();
42+
var sdkFeatureValues = GetSdkFeatureValues();
43+
44+
// Legacy alias keys that exist in config.schema.json but are NOT canonical feature
45+
// keys in features.rs; they are intentionally excluded from CodexFeatures.
46+
var knownAliases = new HashSet<string>(StringComparer.Ordinal)
47+
{
48+
"collab",
49+
"connectors",
50+
"enable_experimental_windows_sandbox",
51+
"experimental_use_freeform_apply_patch",
52+
"experimental_use_unified_exec_tool",
53+
"include_apply_patch_tool",
54+
"memory_tool",
55+
"web_search",
56+
};
57+
58+
var canonicalKeys = schemaFeatureKeys
59+
.Except(knownAliases, StringComparer.Ordinal)
60+
.ToArray();
61+
62+
var missingKeys = canonicalKeys
63+
.Except(sdkFeatureValues, StringComparer.Ordinal)
64+
.ToArray();
65+
66+
await Assert.That(missingKeys).IsEmpty();
67+
}
68+
69+
private static string[] GetSdkFeatureValues()
70+
{
71+
return typeof(CodexFeatures)
72+
.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly)
73+
.Where(field => field is { IsLiteral: true, IsInitOnly: false } && field.FieldType == typeof(string))
74+
.Select(field => (string)field.GetRawConstantValue()!)
75+
.ToArray();
76+
}
77+
78+
private static async Task<string[]> ReadBundledSchemaFeatureKeysAsync()
79+
{
80+
var schemaPath = ResolveBundledConfigSchemaFilePath();
81+
using var stream = File.OpenRead(schemaPath);
82+
using var document = await JsonDocument.ParseAsync(stream);
83+
84+
return document.RootElement
85+
.GetProperty("properties")
86+
.GetProperty("features")
87+
.GetProperty("properties")
88+
.EnumerateObject()
89+
.Select(p => p.Name)
90+
.ToArray();
91+
}
92+
93+
private static string ResolveBundledConfigSchemaFilePath()
94+
{
95+
return Path.Combine(
96+
ResolveRepositoryRootPath(),
97+
"submodules",
98+
"openai-codex",
99+
"codex-rs",
100+
"core",
101+
BundledConfigSchemaFileName);
102+
}
103+
104+
private static string ResolveRepositoryRootPath()
105+
{
106+
var current = new DirectoryInfo(AppContext.BaseDirectory);
107+
while (current is not null)
108+
{
109+
if (File.Exists(Path.Combine(current.FullName, SolutionFileName)))
110+
{
111+
return current.FullName;
112+
}
113+
114+
current = current.Parent;
115+
}
116+
117+
throw new InvalidOperationException("Could not locate repository root from test execution directory.");
118+
}
119+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
namespace ManagedCode.CodexSharpSDK.Models;
2+
3+
/// <summary>
4+
/// Canonical feature flag keys for use with <see cref="Client.ThreadOptions.EnabledFeatures"/>
5+
/// and <see cref="Client.ThreadOptions.DisabledFeatures"/> (and their equivalents in
6+
/// <see cref="Execution.CodexExecArgs"/>). Values match the keys accepted by the Codex CLI
7+
/// <c>--enable</c> / <c>--disable</c> flags and the <c>[features]</c> section of
8+
/// <c>config.toml</c>. Sourced from the bundled upstream
9+
/// <c>codex-rs/core/src/features.rs</c>.
10+
/// </summary>
11+
public static class CodexFeatures
12+
{
13+
public const string ApplyPatchFreeform = "apply_patch_freeform";
14+
public const string Apps = "apps";
15+
public const string AppsMcpGateway = "apps_mcp_gateway";
16+
public const string Artifact = "artifact";
17+
public const string ChildAgentsMd = "child_agents_md";
18+
public const string CodexGitCommit = "codex_git_commit";
19+
public const string CollaborationModes = "collaboration_modes";
20+
public const string DefaultModeRequestUserInput = "default_mode_request_user_input";
21+
public const string ElevatedWindowsSandbox = "elevated_windows_sandbox";
22+
public const string EnableRequestCompression = "enable_request_compression";
23+
public const string ExperimentalWindowsSandbox = "experimental_windows_sandbox";
24+
public const string FastMode = "fast_mode";
25+
26+
/// <summary>
27+
/// Guardian subagent approval: lets a guardian subagent review <c>on-request</c> approval
28+
/// prompts instead of surfacing them to the user, including sandbox escapes and blocked
29+
/// network access. Experimental feature added in upstream commit 3b5fe5c.
30+
/// </summary>
31+
public const string GuardianApproval = "guardian_approval";
32+
33+
public const string ImageDetailOriginal = "image_detail_original";
34+
public const string ImageGeneration = "image_generation";
35+
public const string JsRepl = "js_repl";
36+
public const string JsReplToolsOnly = "js_repl_tools_only";
37+
public const string Memories = "memories";
38+
public const string MultiAgent = "multi_agent";
39+
public const string Personality = "personality";
40+
public const string Plugins = "plugins";
41+
public const string PowershellUtf8 = "powershell_utf8";
42+
public const string PreventIdleSleep = "prevent_idle_sleep";
43+
public const string RealtimeConversation = "realtime_conversation";
44+
public const string RemoteModels = "remote_models";
45+
public const string RequestPermissions = "request_permissions";
46+
public const string RequestRule = "request_rule";
47+
public const string ResponsesWebsockets = "responses_websockets";
48+
public const string ResponsesWebsocketsV2 = "responses_websockets_v2";
49+
public const string RuntimeMetrics = "runtime_metrics";
50+
public const string SearchTool = "search_tool";
51+
public const string ShellSnapshot = "shell_snapshot";
52+
public const string ShellTool = "shell_tool";
53+
public const string ShellZshFork = "shell_zsh_fork";
54+
public const string SkillEnvVarDependencyPrompt = "skill_env_var_dependency_prompt";
55+
public const string SkillMcpDependencyInstall = "skill_mcp_dependency_install";
56+
public const string Sqlite = "sqlite";
57+
public const string Steer = "steer";
58+
59+
/// <summary>
60+
/// Routes MCP tool approval prompts through the MCP elicitation request path.
61+
/// Under-development feature added in upstream commit 3b5fe5c.
62+
/// </summary>
63+
public const string ToolCallMcpElicitation = "tool_call_mcp_elicitation";
64+
65+
public const string Undo = "undo";
66+
public const string UnifiedExec = "unified_exec";
67+
public const string UseLinuxSandboxBwrap = "use_linux_sandbox_bwrap";
68+
public const string VoiceTranscription = "voice_transcription";
69+
public const string WebSearchCached = "web_search_cached";
70+
public const string WebSearchRequest = "web_search_request";
71+
}

global.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"sdk": {
3-
"version": "10.0.103",
3+
"version": "10.0.102",
44
"rollForward": "latestFeature"
55
},
66
"test": {

submodules/openai-codex

Submodule openai-codex updated 323 files

0 commit comments

Comments
 (0)