mirror of
https://github.com/openai/codex.git
synced 2026-04-24 22:54:54 +00:00
feat(tui) /personality (#9718)
## Summary Adds /personality selector in the TUI, which leverages the new core interface in #9644 Notes: - We are doing some of our own state management for model_info loading here, but not sure if that's ideal. open to opinions on simpler approach, but would like to avoid blocking on a larger refactor - Right now, the `/personality` selector just hides when the model doesn't support it. we can update this behavior down the line ## Testing - [x] Tested locally - [x] Added snapshot tests
This commit is contained in:
@@ -2,6 +2,7 @@ use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use strum_macros::Display;
|
||||
use strum_macros::EnumIter;
|
||||
use ts_rs::TS;
|
||||
|
||||
use crate::openai_models::ReasoningEffort;
|
||||
@@ -78,6 +79,7 @@ pub enum SandboxMode {
|
||||
TS,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
EnumIter,
|
||||
)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
#[strum(serialize_all = "lowercase")]
|
||||
|
||||
@@ -78,6 +78,9 @@ pub struct ModelPreset {
|
||||
pub default_reasoning_effort: ReasoningEffort,
|
||||
/// Supported reasoning effort options.
|
||||
pub supported_reasoning_efforts: Vec<ReasoningEffortPreset>,
|
||||
/// Whether this model supports personality-specific instructions.
|
||||
#[serde(default)]
|
||||
pub supports_personality: bool,
|
||||
/// Whether this is the default model for new users.
|
||||
pub is_default: bool,
|
||||
/// recommended upgrade model
|
||||
@@ -214,6 +217,12 @@ impl ModelInfo {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn supports_personality(&self) -> bool {
|
||||
self.model_instructions_template
|
||||
.as_ref()
|
||||
.is_some_and(ModelInstructionsTemplate::supports_personality)
|
||||
}
|
||||
|
||||
pub fn get_model_instructions(&self, personality: Option<Personality>) -> String {
|
||||
if let Some(personality) = personality
|
||||
&& let Some(template) = &self.model_instructions_template
|
||||
@@ -249,6 +258,13 @@ impl ModelInstructionsTemplate {
|
||||
fn has_personality_placeholder(&self) -> bool {
|
||||
self.template.contains(PERSONALITY_PLACEHOLDER)
|
||||
}
|
||||
|
||||
fn supports_personality(&self) -> bool {
|
||||
self.has_personality_placeholder()
|
||||
&& self.personality_messages.as_ref().is_some_and(|messages| {
|
||||
Personality::iter().all(|personality| messages.0.contains_key(&personality))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// serializes as a dictionary from personality to message
|
||||
@@ -280,6 +296,7 @@ pub struct ModelsResponse {
|
||||
// convert ModelInfo to ModelPreset
|
||||
impl From<ModelInfo> for ModelPreset {
|
||||
fn from(info: ModelInfo) -> Self {
|
||||
let supports_personality = info.supports_personality();
|
||||
ModelPreset {
|
||||
id: info.slug.clone(),
|
||||
model: info.slug.clone(),
|
||||
@@ -289,6 +306,7 @@ impl From<ModelInfo> for ModelPreset {
|
||||
.default_reasoning_level
|
||||
.unwrap_or(ReasoningEffort::None),
|
||||
supported_reasoning_efforts: info.supported_reasoning_levels.clone(),
|
||||
supports_personality,
|
||||
is_default: false, // default is the highest priority available model
|
||||
upgrade: info.upgrade.as_ref().map(|upgrade| ModelUpgrade {
|
||||
id: upgrade.model.clone(),
|
||||
|
||||
Reference in New Issue
Block a user