use serde_json::Value;
use crate::domain::agent::{AgentKind, AgentModel, ReasoningLevel};
use crate::domain::permission::PermissionMode;
pub(super) struct PermissionModePolicy {
approval_policy: &'static str,
legacy_pre_action_decision: &'static str,
pre_action_decision: &'static str,
thread_sandbox_mode: &'static str,
turn_network_access: bool,
turn_sandbox_type: &'static str,
web_search_mode: &'static str,
}
const AUTO_EDIT_POLICY: PermissionModePolicy = PermissionModePolicy {
approval_policy: "on-request",
legacy_pre_action_decision: "approved",
pre_action_decision: "accept",
thread_sandbox_mode: "workspace-write",
turn_network_access: true,
turn_sandbox_type: "workspaceWrite",
web_search_mode: "live",
};
pub(super) const AUTO_COMPACT_INPUT_TOKEN_THRESHOLD_400K_CONTEXT: u64 = 300_000;
pub(super) const AUTO_COMPACT_INPUT_TOKEN_THRESHOLD_128K_CONTEXT: u64 = 120_000;
pub(super) fn auto_compact_input_token_threshold(model: &str) -> u64 {
let is_400k_context_model =
matches!(AgentKind::Codex.parse_model(model), Some(AgentModel::Gpt54));
if is_400k_context_model {
return AUTO_COMPACT_INPUT_TOKEN_THRESHOLD_400K_CONTEXT;
}
AUTO_COMPACT_INPUT_TOKEN_THRESHOLD_128K_CONTEXT
}
pub(super) fn approval_policy() -> &'static str {
permission_mode_policy(PermissionMode::default()).approval_policy
}
pub(super) fn thread_sandbox_mode() -> &'static str {
permission_mode_policy(PermissionMode::default()).thread_sandbox_mode
}
pub(super) fn turn_sandbox_policy() -> Value {
let policy = permission_mode_policy(PermissionMode::default());
let mut turn_sandbox_policy = serde_json::json!({
"type": policy.turn_sandbox_type
});
if policy.turn_sandbox_type == "workspaceWrite"
&& let Some(policy_object) = turn_sandbox_policy.as_object_mut()
{
policy_object.insert(
"networkAccess".to_string(),
Value::Bool(policy.turn_network_access),
);
}
turn_sandbox_policy
}
pub(super) fn thread_config(reasoning_level: ReasoningLevel) -> Value {
serde_json::json!({
"web_search": web_search_mode(),
"model_reasoning_effort": reasoning_level.codex(),
})
}
pub(super) fn web_search_mode() -> &'static str {
permission_mode_policy(PermissionMode::default()).web_search_mode
}
pub(super) fn build_pre_action_approval_response(response_value: &Value) -> Option<Value> {
let method = response_value.get("method")?.as_str()?;
let request_id = response_value.get("id")?.clone();
let decision = match method {
"item/commandExecution/requestApproval" | "item/fileChange/requestApproval" => {
pre_action_approval_decision()
}
"execCommandApproval" | "applyPatchApproval" => legacy_pre_action_approval_decision(),
_ => return None,
};
Some(serde_json::json!({
"id": request_id,
"result": {
"decision": decision
}
}))
}
fn pre_action_approval_decision() -> &'static str {
permission_mode_policy(PermissionMode::default()).pre_action_decision
}
fn legacy_pre_action_approval_decision() -> &'static str {
permission_mode_policy(PermissionMode::default()).legacy_pre_action_decision
}
fn permission_mode_policy(permission_mode: PermissionMode) -> &'static PermissionModePolicy {
match permission_mode {
PermissionMode::AutoEdit => &AUTO_EDIT_POLICY,
}
}