mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
Sync collaboration mode naming across Default prompt, tools, and TUI (#10666)
## Summary
- add shared `ModeKind` helpers for display names, TUI visibility, and
`request_user_input` availability
- derive TUI mode filtering/labels from shared `ModeKind` metadata
instead of local hardcoded matches
- derive `request_user_input` availability text and unavailable error
mode names from shared mode metadata
- replace hardcoded known mode names in the Default collaboration-mode
template with `{{KNOWN_MODE_NAMES}}` and fill it from
`TUI_VISIBLE_COLLABORATION_MODES`
- add regression tests for mode metadata sync and placeholder
replacement
## Notes
- `cargo test -p codex-core` integration target (`tests/all`) still
shows pre-existing env-specific failures in this environment due missing
`test_stdio_server` binary resolution; core unit tests are green.
## Codex author
`codex resume 019c26ff-dfe7-7173-bc04-c9e1fff1e447`
This commit is contained in:
committed by
GitHub
Unverified
parent
e482978261
commit
41b4962b0a
@@ -1,10 +1,13 @@
|
||||
use codex_protocol::config_types::CollaborationModeMask;
|
||||
use codex_protocol::config_types::ModeKind;
|
||||
use codex_protocol::config_types::TUI_VISIBLE_COLLABORATION_MODES;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
|
||||
const COLLABORATION_MODE_PLAN: &str = include_str!("../../templates/collaboration_mode/plan.md");
|
||||
const COLLABORATION_MODE_DEFAULT: &str =
|
||||
include_str!("../../templates/collaboration_mode/default.md");
|
||||
const KNOWN_MODE_NAMES_PLACEHOLDER: &str = "{{KNOWN_MODE_NAMES}}";
|
||||
const REQUEST_USER_INPUT_AVAILABILITY_PLACEHOLDER: &str = "{{REQUEST_USER_INPUT_AVAILABILITY}}";
|
||||
|
||||
pub(super) fn builtin_collaboration_mode_presets() -> Vec<CollaborationModeMask> {
|
||||
vec![plan_preset(), default_preset()]
|
||||
@@ -17,7 +20,7 @@ pub fn test_builtin_collaboration_mode_presets() -> Vec<CollaborationModeMask> {
|
||||
|
||||
fn plan_preset() -> CollaborationModeMask {
|
||||
CollaborationModeMask {
|
||||
name: "Plan".to_string(),
|
||||
name: ModeKind::Plan.display_name().to_string(),
|
||||
mode: Some(ModeKind::Plan),
|
||||
model: None,
|
||||
reasoning_effort: Some(Some(ReasoningEffort::Medium)),
|
||||
@@ -27,10 +30,74 @@ fn plan_preset() -> CollaborationModeMask {
|
||||
|
||||
fn default_preset() -> CollaborationModeMask {
|
||||
CollaborationModeMask {
|
||||
name: "Default".to_string(),
|
||||
name: ModeKind::Default.display_name().to_string(),
|
||||
mode: Some(ModeKind::Default),
|
||||
model: None,
|
||||
reasoning_effort: None,
|
||||
developer_instructions: Some(Some(COLLABORATION_MODE_DEFAULT.to_string())),
|
||||
developer_instructions: Some(Some(default_mode_instructions())),
|
||||
}
|
||||
}
|
||||
|
||||
fn default_mode_instructions() -> String {
|
||||
let known_mode_names = format_mode_names(&TUI_VISIBLE_COLLABORATION_MODES);
|
||||
let request_user_input_availability =
|
||||
request_user_input_availability_message(ModeKind::Default);
|
||||
COLLABORATION_MODE_DEFAULT
|
||||
.replace(KNOWN_MODE_NAMES_PLACEHOLDER, &known_mode_names)
|
||||
.replace(
|
||||
REQUEST_USER_INPUT_AVAILABILITY_PLACEHOLDER,
|
||||
&request_user_input_availability,
|
||||
)
|
||||
}
|
||||
|
||||
fn format_mode_names(modes: &[ModeKind]) -> String {
|
||||
let mode_names: Vec<&str> = modes.iter().map(|mode| mode.display_name()).collect();
|
||||
match mode_names.as_slice() {
|
||||
[] => "none".to_string(),
|
||||
[mode_name] => (*mode_name).to_string(),
|
||||
[first, second] => format!("{first} and {second}"),
|
||||
[..] => mode_names.join(", "),
|
||||
}
|
||||
}
|
||||
|
||||
fn request_user_input_availability_message(mode: ModeKind) -> String {
|
||||
let mode_name = mode.display_name();
|
||||
if mode.allows_request_user_input() {
|
||||
format!("The `request_user_input` tool is available in {mode_name} mode.")
|
||||
} else {
|
||||
format!(
|
||||
"The `request_user_input` tool is unavailable in {mode_name} mode. If you call it while in {mode_name} mode, it will return an error."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn preset_names_use_mode_display_names() {
|
||||
assert_eq!(plan_preset().name, ModeKind::Plan.display_name());
|
||||
assert_eq!(default_preset().name, ModeKind::Default.display_name());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_mode_instructions_replace_mode_names_placeholder() {
|
||||
let default_instructions = default_preset()
|
||||
.developer_instructions
|
||||
.expect("default preset should include instructions")
|
||||
.expect("default instructions should be set");
|
||||
|
||||
assert!(!default_instructions.contains(KNOWN_MODE_NAMES_PLACEHOLDER));
|
||||
assert!(!default_instructions.contains(REQUEST_USER_INPUT_AVAILABILITY_PLACEHOLDER));
|
||||
|
||||
let known_mode_names = format_mode_names(&TUI_VISIBLE_COLLABORATION_MODES);
|
||||
let expected_snippet = format!("Known mode names are {known_mode_names}.");
|
||||
assert!(default_instructions.contains(&expected_snippet));
|
||||
|
||||
let expected_availability_message =
|
||||
request_user_input_availability_message(ModeKind::Default);
|
||||
assert!(default_instructions.contains(&expected_availability_message));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,27 +9,15 @@ use crate::tools::handlers::parse_arguments;
|
||||
use crate::tools::registry::ToolHandler;
|
||||
use crate::tools::registry::ToolKind;
|
||||
use codex_protocol::config_types::ModeKind;
|
||||
use codex_protocol::config_types::TUI_VISIBLE_COLLABORATION_MODES;
|
||||
use codex_protocol::request_user_input::RequestUserInputArgs;
|
||||
|
||||
const REQUEST_USER_INPUT_ALLOWED_MODES: [ModeKind; 1] = [ModeKind::Plan];
|
||||
|
||||
fn request_user_input_mode_name(mode: ModeKind) -> &'static str {
|
||||
match mode {
|
||||
ModeKind::Plan => "Plan",
|
||||
ModeKind::Default => "Default",
|
||||
ModeKind::Execute => "Execute",
|
||||
ModeKind::PairProgramming => "Pair Programming",
|
||||
}
|
||||
}
|
||||
|
||||
fn format_allowed_modes() -> String {
|
||||
let mut mode_names = Vec::with_capacity(REQUEST_USER_INPUT_ALLOWED_MODES.len());
|
||||
for mode in REQUEST_USER_INPUT_ALLOWED_MODES {
|
||||
let name = request_user_input_mode_name(mode);
|
||||
if !mode_names.contains(&name) {
|
||||
mode_names.push(name);
|
||||
}
|
||||
}
|
||||
let mode_names: Vec<&str> = TUI_VISIBLE_COLLABORATION_MODES
|
||||
.into_iter()
|
||||
.filter(|mode| mode.allows_request_user_input())
|
||||
.map(ModeKind::display_name)
|
||||
.collect();
|
||||
|
||||
match mode_names.as_slice() {
|
||||
[] => "no modes".to_string(),
|
||||
@@ -39,15 +27,11 @@ fn format_allowed_modes() -> String {
|
||||
}
|
||||
}
|
||||
|
||||
fn request_user_input_is_available_in_mode(mode: ModeKind) -> bool {
|
||||
REQUEST_USER_INPUT_ALLOWED_MODES.contains(&mode)
|
||||
}
|
||||
|
||||
pub(crate) fn request_user_input_unavailable_message(mode: ModeKind) -> Option<String> {
|
||||
if request_user_input_is_available_in_mode(mode) {
|
||||
if mode.allows_request_user_input() {
|
||||
None
|
||||
} else {
|
||||
let mode_name = request_user_input_mode_name(mode);
|
||||
let mode_name = mode.display_name();
|
||||
Some(format!(
|
||||
"request_user_input is unavailable in {mode_name} mode"
|
||||
))
|
||||
@@ -134,22 +118,10 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn request_user_input_mode_availability_is_plan_only() {
|
||||
assert_eq!(
|
||||
request_user_input_is_available_in_mode(ModeKind::Plan),
|
||||
true
|
||||
);
|
||||
assert_eq!(
|
||||
request_user_input_is_available_in_mode(ModeKind::Default),
|
||||
false
|
||||
);
|
||||
assert_eq!(
|
||||
request_user_input_is_available_in_mode(ModeKind::Execute),
|
||||
false
|
||||
);
|
||||
assert_eq!(
|
||||
request_user_input_is_available_in_mode(ModeKind::PairProgramming),
|
||||
false
|
||||
);
|
||||
assert!(ModeKind::Plan.allows_request_user_input());
|
||||
assert!(!ModeKind::Default.allows_request_user_input());
|
||||
assert!(!ModeKind::Execute.allows_request_user_input());
|
||||
assert!(!ModeKind::PairProgramming.allows_request_user_input());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user