mirror of
https://github.com/openai/codex.git
synced 2026-05-01 03:42:05 +03:00
[codex] allow disabling prompt instruction blocks (#16735)
This PR adds root and profile config switches to omit the generated `<permissions instructions>` and `<apps_instructions>` prompt blocks while keeping both enabled by default, and it gates both the initial developer-context injection and later permissions diff injection so turning the permissions block off stays effective across turn-context overrides. Also added a prompt debug tool that can be used as `codex debug prompt-input "hello"` and dumps the constructed items list.
This commit is contained in:
committed by
GitHub
parent
f263607c60
commit
8d19646861
@@ -51,6 +51,8 @@ use codex_core::config::find_codex_home;
|
||||
use codex_features::FEATURES;
|
||||
use codex_features::Stage;
|
||||
use codex_features::is_known_feature_key;
|
||||
use codex_protocol::protocol::AskForApproval;
|
||||
use codex_protocol::user_input::UserInput;
|
||||
use codex_terminal_detection::TerminalName;
|
||||
|
||||
/// Codex CLI
|
||||
@@ -170,6 +172,9 @@ enum DebugSubcommand {
|
||||
/// Tooling: helps debug the app server.
|
||||
AppServer(DebugAppServerCommand),
|
||||
|
||||
/// Render the model-visible prompt input list as JSON.
|
||||
PromptInput(DebugPromptInputCommand),
|
||||
|
||||
/// Internal: reset local memory state for a fresh start.
|
||||
#[clap(hide = true)]
|
||||
ClearMemories,
|
||||
@@ -193,6 +198,17 @@ struct DebugAppServerSendMessageV2Command {
|
||||
user_message: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
struct DebugPromptInputCommand {
|
||||
/// Optional user prompt to append after session context.
|
||||
#[arg(value_name = "PROMPT")]
|
||||
prompt: Option<String>,
|
||||
|
||||
/// Optional image(s) to attach to the user prompt.
|
||||
#[arg(long = "image", short = 'i', value_name = "FILE", value_delimiter = ',', num_args = 1..)]
|
||||
images: Vec<PathBuf>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
struct ResumeCommand {
|
||||
/// Conversation/session id (UUID) or thread name. UUIDs take precedence if it parses.
|
||||
@@ -915,6 +931,20 @@ async fn cli_main(arg0_paths: Arg0DispatchPaths) -> anyhow::Result<()> {
|
||||
)?;
|
||||
run_debug_app_server_command(cmd).await?;
|
||||
}
|
||||
DebugSubcommand::PromptInput(cmd) => {
|
||||
reject_remote_mode_for_subcommand(
|
||||
root_remote.as_deref(),
|
||||
root_remote_auth_token_env.as_deref(),
|
||||
"debug prompt-input",
|
||||
)?;
|
||||
run_debug_prompt_input_command(
|
||||
cmd,
|
||||
root_config_overrides,
|
||||
interactive,
|
||||
arg0_paths.clone(),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
DebugSubcommand::ClearMemories => {
|
||||
reject_remote_mode_for_subcommand(
|
||||
root_remote.as_deref(),
|
||||
@@ -1083,6 +1113,72 @@ fn maybe_print_under_development_feature_warning(
|
||||
);
|
||||
}
|
||||
|
||||
async fn run_debug_prompt_input_command(
|
||||
cmd: DebugPromptInputCommand,
|
||||
root_config_overrides: CliConfigOverrides,
|
||||
interactive: TuiCli,
|
||||
arg0_paths: Arg0DispatchPaths,
|
||||
) -> anyhow::Result<()> {
|
||||
let mut cli_kv_overrides = root_config_overrides
|
||||
.parse_overrides()
|
||||
.map_err(anyhow::Error::msg)?;
|
||||
if interactive.web_search {
|
||||
cli_kv_overrides.push((
|
||||
"web_search".to_string(),
|
||||
toml::Value::String("live".to_string()),
|
||||
));
|
||||
}
|
||||
|
||||
let approval_policy = if interactive.full_auto {
|
||||
Some(AskForApproval::OnRequest)
|
||||
} else if interactive.dangerously_bypass_approvals_and_sandbox {
|
||||
Some(AskForApproval::Never)
|
||||
} else {
|
||||
interactive.approval_policy.map(Into::into)
|
||||
};
|
||||
let sandbox_mode = if interactive.full_auto {
|
||||
Some(codex_protocol::config_types::SandboxMode::WorkspaceWrite)
|
||||
} else if interactive.dangerously_bypass_approvals_and_sandbox {
|
||||
Some(codex_protocol::config_types::SandboxMode::DangerFullAccess)
|
||||
} else {
|
||||
interactive.sandbox_mode.map(Into::into)
|
||||
};
|
||||
let overrides = ConfigOverrides {
|
||||
model: interactive.model,
|
||||
config_profile: interactive.config_profile,
|
||||
approval_policy,
|
||||
sandbox_mode,
|
||||
cwd: interactive.cwd,
|
||||
codex_self_exe: arg0_paths.codex_self_exe,
|
||||
codex_linux_sandbox_exe: arg0_paths.codex_linux_sandbox_exe,
|
||||
main_execve_wrapper_exe: arg0_paths.main_execve_wrapper_exe,
|
||||
show_raw_agent_reasoning: interactive.oss.then_some(true),
|
||||
ephemeral: Some(true),
|
||||
additional_writable_roots: interactive.add_dir,
|
||||
..Default::default()
|
||||
};
|
||||
let config =
|
||||
Config::load_with_cli_overrides_and_harness_overrides(cli_kv_overrides, overrides).await?;
|
||||
|
||||
let mut input = interactive
|
||||
.images
|
||||
.into_iter()
|
||||
.chain(cmd.images)
|
||||
.map(|path| UserInput::LocalImage { path })
|
||||
.collect::<Vec<_>>();
|
||||
if let Some(prompt) = cmd.prompt.or(interactive.prompt) {
|
||||
input.push(UserInput::Text {
|
||||
text: prompt.replace("\r\n", "\n").replace('\r', "\n"),
|
||||
text_elements: Vec::new(),
|
||||
});
|
||||
}
|
||||
|
||||
let prompt_input = codex_core::prompt_debug::build_prompt_input(config, input).await?;
|
||||
println!("{}", serde_json::to_string_pretty(&prompt_input)?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn run_debug_clear_memories_command(
|
||||
root_config_overrides: &CliConfigOverrides,
|
||||
interactive: &TuiCli,
|
||||
@@ -1489,6 +1585,32 @@ mod tests {
|
||||
app_server
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn debug_prompt_input_parses_prompt_and_images() {
|
||||
let cli = MultitoolCli::try_parse_from([
|
||||
"codex",
|
||||
"debug",
|
||||
"prompt-input",
|
||||
"hello",
|
||||
"--image",
|
||||
"/tmp/a.png,/tmp/b.png",
|
||||
])
|
||||
.expect("parse");
|
||||
|
||||
let Some(Subcommand::Debug(DebugCommand {
|
||||
subcommand: DebugSubcommand::PromptInput(cmd),
|
||||
})) = cli.subcommand
|
||||
else {
|
||||
panic!("expected debug prompt-input subcommand");
|
||||
};
|
||||
|
||||
assert_eq!(cmd.prompt.as_deref(), Some("hello"));
|
||||
assert_eq!(
|
||||
cmd.images,
|
||||
vec![PathBuf::from("/tmp/a.png"), PathBuf::from("/tmp/b.png")]
|
||||
);
|
||||
}
|
||||
|
||||
fn sample_exit_info(conversation_id: Option<&str>, thread_name: Option<&str>) -> AppExitInfo {
|
||||
let token_usage = TokenUsage {
|
||||
output_tokens: 2,
|
||||
|
||||
Reference in New Issue
Block a user