mirror of
https://github.com/openai/codex.git
synced 2026-02-01 22:47:52 +00:00
chore(config) personality as a feature (#10116)
## Summary Sets up an explicit Feature flag for `/personality`, so users can now opt in to it via `/experimental`. #10114 also updates the config ## Testing - [x] Tested locally
This commit is contained in:
@@ -180,6 +180,9 @@
|
||||
"include_apply_patch_tool": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"personality": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"powershell_utf8": {
|
||||
"type": "boolean"
|
||||
},
|
||||
@@ -1198,6 +1201,9 @@
|
||||
"include_apply_patch_tool": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"personality": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"powershell_utf8": {
|
||||
"type": "boolean"
|
||||
},
|
||||
|
||||
@@ -119,6 +119,8 @@ pub enum Feature {
|
||||
Steer,
|
||||
/// Enable collaboration modes (Plan, Code, Pair Programming, Execute).
|
||||
CollaborationModes,
|
||||
/// Enable personality selection in the TUI.
|
||||
Personality,
|
||||
/// Use the Responses API WebSocket transport for OpenAI by default.
|
||||
ResponsesWebsockets,
|
||||
}
|
||||
@@ -543,6 +545,16 @@ pub const FEATURES: &[FeatureSpec] = &[
|
||||
stage: Stage::UnderDevelopment,
|
||||
default_enabled: false,
|
||||
},
|
||||
FeatureSpec {
|
||||
id: Feature::Personality,
|
||||
key: "personality",
|
||||
stage: Stage::Experimental {
|
||||
name: "Personality",
|
||||
menu_description: "Choose a communication style for Codex.",
|
||||
announcement: "NEW! Update codex's communication style with /personality. Enable in /experimental!",
|
||||
},
|
||||
default_enabled: false,
|
||||
},
|
||||
FeatureSpec {
|
||||
id: Feature::ResponsesWebsockets,
|
||||
key: "responses_websockets",
|
||||
|
||||
@@ -213,6 +213,16 @@ pub(crate) fn find_model_info_for_slug(slug: &str) -> ModelInfo {
|
||||
truncation_policy: TruncationPolicyConfig::tokens(10_000),
|
||||
context_window: Some(CONTEXT_WINDOW_272K),
|
||||
supported_reasoning_levels: supported_reasoning_level_low_medium_high_xhigh(),
|
||||
model_instructions_template: Some(ModelInstructionsTemplate {
|
||||
template: GPT_5_2_CODEX_INSTRUCTIONS_TEMPLATE.to_string(),
|
||||
personality_messages: Some(PersonalityMessages(BTreeMap::from([(
|
||||
Personality::Friendly,
|
||||
PERSONALITY_FRIENDLY.to_string(),
|
||||
), (
|
||||
Personality::Pragmatic,
|
||||
PERSONALITY_PRAGMATIC.to_string(),
|
||||
)]))),
|
||||
}),
|
||||
)
|
||||
} else if slug.starts_with("gpt-5.1-codex-max") {
|
||||
model_info!(
|
||||
|
||||
@@ -2892,6 +2892,7 @@ impl ChatWidget {
|
||||
let personality = self
|
||||
.config
|
||||
.model_personality
|
||||
.filter(|_| self.config.features.enabled(Feature::Personality))
|
||||
.filter(|_| self.current_model_supports_personality());
|
||||
let op = Op::UserTurn {
|
||||
items,
|
||||
@@ -3455,19 +3456,23 @@ impl ChatWidget {
|
||||
);
|
||||
return;
|
||||
}
|
||||
if !self.current_model_supports_personality() {
|
||||
let current_model = self.current_model();
|
||||
self.add_error_message(format!(
|
||||
"Current model ({current_model}) doesn't support personalities. Try /model to pick a different model."
|
||||
));
|
||||
return;
|
||||
}
|
||||
self.open_personality_popup_for_current_model();
|
||||
}
|
||||
|
||||
fn open_personality_popup_for_current_model(&mut self) {
|
||||
let current_model = self.current_model();
|
||||
let current_personality = self.config.model_personality;
|
||||
let current_personality = self
|
||||
.config
|
||||
.model_personality
|
||||
.unwrap_or(Personality::Friendly);
|
||||
let personalities = [Personality::Friendly, Personality::Pragmatic];
|
||||
let supports_personality = self.current_model_supports_personality();
|
||||
let disabled_message = (!supports_personality).then(|| {
|
||||
format!(
|
||||
"Current model ({current_model}) doesn't support personalities. Try /model to switch to a newer model."
|
||||
)
|
||||
});
|
||||
|
||||
let items: Vec<SelectionItem> = personalities
|
||||
.into_iter()
|
||||
@@ -3492,7 +3497,7 @@ impl ChatWidget {
|
||||
SelectionItem {
|
||||
name,
|
||||
description,
|
||||
is_current: current_personality == Some(personality),
|
||||
is_current: current_personality == personality,
|
||||
is_disabled: !supports_personality,
|
||||
actions,
|
||||
dismiss_on_select: true,
|
||||
@@ -3504,11 +3509,8 @@ impl ChatWidget {
|
||||
let mut header = ColumnRenderable::new();
|
||||
header.push(Line::from("Select Personality".bold()));
|
||||
header.push(Line::from(
|
||||
"Choose a communication style for future responses.".dim(),
|
||||
"Choose a communication style for Codex. Disable in /experimental.".dim(),
|
||||
));
|
||||
if let Some(message) = disabled_message {
|
||||
header.push(Line::from(message.red()));
|
||||
}
|
||||
|
||||
self.bottom_pane.show_selection_view(SelectionViewParams {
|
||||
header: Box::new(header),
|
||||
@@ -4714,6 +4716,9 @@ impl ChatWidget {
|
||||
self.refresh_model_display();
|
||||
self.request_redraw();
|
||||
}
|
||||
if feature == Feature::Personality {
|
||||
self.sync_personality_command_enabled();
|
||||
}
|
||||
#[cfg(target_os = "windows")]
|
||||
if matches!(
|
||||
feature,
|
||||
@@ -4780,7 +4785,6 @@ impl ChatWidget {
|
||||
mask.model = Some(model.to_string());
|
||||
}
|
||||
self.refresh_model_display();
|
||||
self.sync_personality_command_enabled();
|
||||
}
|
||||
|
||||
pub(crate) fn current_model(&self) -> &str {
|
||||
@@ -4795,7 +4799,7 @@ impl ChatWidget {
|
||||
|
||||
fn sync_personality_command_enabled(&mut self) {
|
||||
self.bottom_pane
|
||||
.set_personality_command_enabled(self.current_model_supports_personality());
|
||||
.set_personality_command_enabled(self.config.features.enabled(Feature::Personality));
|
||||
}
|
||||
|
||||
fn current_model_supports_personality(&self) -> bool {
|
||||
|
||||
@@ -3,9 +3,9 @@ source: tui/src/chatwidget/tests.rs
|
||||
expression: popup
|
||||
---
|
||||
Select Personality
|
||||
Choose a communication style for future responses.
|
||||
Choose a communication style for Codex. Disable in /experimental.
|
||||
|
||||
› 1. Friendly Warm, collaborative, and helpful.
|
||||
2. Pragmatic Concise, task-focused, and direct.
|
||||
› 1. Friendly (current) Warm, collaborative, and helpful.
|
||||
2. Pragmatic Concise, task-focused, and direct.
|
||||
|
||||
Press enter to confirm or esc to go back
|
||||
|
||||
@@ -2408,6 +2408,7 @@ async fn collab_mode_enabling_keeps_custom_until_selected() {
|
||||
#[tokio::test]
|
||||
async fn user_turn_includes_personality_from_config() {
|
||||
let (mut chat, _rx, mut op_rx) = make_chatwidget_manual(Some("bengalfox")).await;
|
||||
chat.set_feature_enabled(Feature::Personality, true);
|
||||
chat.thread_id = Some(ThreadId::new());
|
||||
chat.set_model("bengalfox");
|
||||
chat.set_personality(Personality::Friendly);
|
||||
|
||||
@@ -61,7 +61,7 @@ impl SlashCommand {
|
||||
SlashCommand::Status => "show current session configuration and token usage",
|
||||
SlashCommand::Ps => "list background terminals",
|
||||
SlashCommand::Model => "choose what model and reasoning effort to use",
|
||||
SlashCommand::Personality => "choose a communication style for responses",
|
||||
SlashCommand::Personality => "choose a communication style for Codex",
|
||||
SlashCommand::Collab => "change collaboration mode (experimental)",
|
||||
SlashCommand::Agent => "switch the active agent thread",
|
||||
SlashCommand::Approvals => "choose what Codex can do without approval",
|
||||
|
||||
Reference in New Issue
Block a user