Skip to content

session/new response omits modes config due to SandboxPolicy struct equality failure #201

@liaowang11

Description

@liaowang11

Description

In v0.10.0, the session/new response unexpectedly omits the modes object (which contains currentModeId and availableModes) for trusted projects.

This happens because SandboxPolicy::ReadOnly was changed from a unit variant to a struct variant containing fields like access and network_access.

In src/thread.rs, the agent attempts to determine the current mode by doing a strict equality check against the predefined APPROVAL_PRESETS:

let current_mode_id = APPROVAL_PRESETS
    .iter()
    .find(|preset| {
        &preset.approval == self.config.permissions.approval_policy.get()
            && &preset.sandbox == self.config.permissions.sandbox_policy.get()
    })
// ...

Because the active SandboxPolicy::ReadOnly instance dynamically evaluates local workspace conditions (such as specific directory paths it's allowed to read from), it will almost never structurally equate (==) to the generic default instance constructed by codex_utils_approval_presets::builtin_approval_presets().

As a result, the .find() method fails and falls through to the .or_else() block:

    .or_else(|| {
        if self.config.active_project.is_untrusted() {
            APPROVAL_PRESETS
                .iter()
                .find(|preset| preset.id == "read-only")
        } else {
            None // <--- Fails here for trusted projects
        }
    })

Because the project is trusted, the fallback block returns None. This cascades into a None return for the entire fn modes(&self) method due to the ? operator, which subsequently omits the entire modes payload from the NewSessionResponse.

Expected Behavior

The modes configuration should be present in the session/new response, matching the currently active approval preset, regardless of internal struct field variations of SandboxPolicy.

Proposed Solution

The equality check for the sandbox policy shouldn't rely on strict structural equality, but rather enum variant matching (e.g. std::mem::discriminant or an explicit is_same_variant helper method), ignoring the internal fields.

Alternatively, consider having SandboxPolicy implement a customized PartialEq that only compares the variant types for these specific preset checks, or write a dedicated helper for preset comparison.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions