mirror of
https://github.com/openai/codex.git
synced 2026-11-02 19:43:24 +00:00
Merge 73a84c7447 into sapling-pr-archive-bolinfest
This commit is contained in:
@@ -6493,6 +6493,14 @@ fn collect_resume_override_mismatches(
|
||||
config_snapshot.model_provider_id
|
||||
));
|
||||
}
|
||||
if let Some(requested_service_tier) = request.service_tier.as_ref()
|
||||
&& requested_service_tier != &config_snapshot.service_tier
|
||||
{
|
||||
mismatch_details.push(format!(
|
||||
"service_tier requested={requested_service_tier:?} active={:?}",
|
||||
config_snapshot.service_tier
|
||||
));
|
||||
}
|
||||
if let Some(requested_cwd) = request.cwd.as_deref() {
|
||||
let requested_cwd_path = std::path::PathBuf::from(requested_cwd);
|
||||
if requested_cwd_path != config_snapshot.cwd {
|
||||
@@ -7259,6 +7267,43 @@ mod tests {
|
||||
validate_dynamic_tools(&tools).expect("valid schema");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn collect_resume_override_mismatches_includes_service_tier() {
|
||||
let request = ThreadResumeParams {
|
||||
thread_id: "thread-1".to_string(),
|
||||
history: None,
|
||||
path: None,
|
||||
model: None,
|
||||
model_provider: None,
|
||||
service_tier: Some(Some(codex_protocol::config_types::ServiceTier::Fast)),
|
||||
cwd: None,
|
||||
approval_policy: None,
|
||||
sandbox: None,
|
||||
config: None,
|
||||
base_instructions: None,
|
||||
developer_instructions: None,
|
||||
personality: None,
|
||||
persist_extended_history: false,
|
||||
};
|
||||
let config_snapshot = ThreadConfigSnapshot {
|
||||
model: "gpt-5".to_string(),
|
||||
model_provider_id: "openai".to_string(),
|
||||
service_tier: Some(codex_protocol::config_types::ServiceTier::Flex),
|
||||
approval_policy: codex_protocol::protocol::AskForApproval::OnRequest,
|
||||
sandbox_policy: codex_protocol::protocol::SandboxPolicy::DangerFullAccess,
|
||||
cwd: PathBuf::from("/tmp"),
|
||||
ephemeral: false,
|
||||
reasoning_effort: None,
|
||||
personality: None,
|
||||
session_source: SessionSource::Cli,
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
collect_resume_override_mismatches(&request, &config_snapshot),
|
||||
vec!["service_tier requested=Some(Fast) active=Some(Flex)".to_string()]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extract_conversation_summary_prefers_plain_user_messages() -> Result<()> {
|
||||
let conversation_id = ThreadId::from_string("3f941c35-29b3-493b-b0a4-e25800d9aeb0")?;
|
||||
|
||||
@@ -36,6 +36,7 @@ fn preset_to_info(preset: &ModelPreset, priority: i32) -> ModelInfo {
|
||||
default_verbosity: None,
|
||||
availability_nux: None,
|
||||
apply_patch_tool_type: None,
|
||||
web_search_tool_type: Default::default(),
|
||||
truncation_policy: TruncationPolicyConfig::bytes(10_000),
|
||||
supports_parallel_tool_calls: false,
|
||||
supports_image_detail_original: false,
|
||||
|
||||
@@ -84,6 +84,7 @@ async fn models_client_hits_models_endpoint() {
|
||||
default_verbosity: None,
|
||||
availability_nux: None,
|
||||
apply_patch_tool_type: None,
|
||||
web_search_tool_type: Default::default(),
|
||||
truncation_policy: TruncationPolicyConfig::bytes(10_000),
|
||||
supports_parallel_tool_calls: false,
|
||||
supports_image_detail_original: false,
|
||||
|
||||
@@ -176,6 +176,8 @@ pub(crate) mod tools {
|
||||
WebSearch {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
external_web_access: Option<bool>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
search_content_types: Option<Vec<String>>,
|
||||
},
|
||||
#[serde(rename = "custom")]
|
||||
Freeform(FreeformTool),
|
||||
|
||||
@@ -6,6 +6,7 @@ use codex_protocol::openai_models::ModelMessages;
|
||||
use codex_protocol::openai_models::ModelVisibility;
|
||||
use codex_protocol::openai_models::TruncationMode;
|
||||
use codex_protocol::openai_models::TruncationPolicyConfig;
|
||||
use codex_protocol::openai_models::WebSearchToolType;
|
||||
use codex_protocol::openai_models::default_input_modalities;
|
||||
|
||||
use crate::config::Config;
|
||||
@@ -78,6 +79,7 @@ pub(crate) fn model_info_from_slug(slug: &str) -> ModelInfo {
|
||||
support_verbosity: false,
|
||||
default_verbosity: None,
|
||||
apply_patch_tool_type: None,
|
||||
web_search_tool_type: WebSearchToolType::Text,
|
||||
truncation_policy: TruncationPolicyConfig::bytes(10_000),
|
||||
supports_parallel_tool_calls: false,
|
||||
supports_image_detail_original: false,
|
||||
|
||||
@@ -25,6 +25,7 @@ use codex_protocol::openai_models::ApplyPatchToolType;
|
||||
use codex_protocol::openai_models::ConfigShellToolType;
|
||||
use codex_protocol::openai_models::InputModality;
|
||||
use codex_protocol::openai_models::ModelInfo;
|
||||
use codex_protocol::openai_models::WebSearchToolType;
|
||||
use codex_protocol::protocol::SessionSource;
|
||||
use codex_protocol::protocol::SubAgentSource;
|
||||
use serde::Deserialize;
|
||||
@@ -36,6 +37,7 @@ use std::collections::HashMap;
|
||||
|
||||
const SEARCH_TOOL_BM25_DESCRIPTION_TEMPLATE: &str =
|
||||
include_str!("../../templates/search_tool/tool_description.md");
|
||||
const WEB_SEARCH_CONTENT_TYPES: [&str; 2] = ["text", "image"];
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub enum ShellCommandBackendConfig {
|
||||
Classic,
|
||||
@@ -56,6 +58,7 @@ pub(crate) struct ToolsConfig {
|
||||
pub allow_login_shell: bool,
|
||||
pub apply_patch_tool_type: Option<ApplyPatchToolType>,
|
||||
pub web_search_mode: Option<WebSearchMode>,
|
||||
pub web_search_tool_type: WebSearchToolType,
|
||||
pub image_gen_tool: bool,
|
||||
pub agent_roles: BTreeMap<String, AgentRoleConfig>,
|
||||
pub search_tool: bool,
|
||||
@@ -154,6 +157,7 @@ impl ToolsConfig {
|
||||
allow_login_shell: true,
|
||||
apply_patch_tool_type,
|
||||
web_search_mode: *web_search_mode,
|
||||
web_search_tool_type: model_info.web_search_tool_type,
|
||||
image_gen_tool: include_image_gen_tool,
|
||||
agent_roles: BTreeMap::new(),
|
||||
search_tool: include_search_tool,
|
||||
@@ -1891,18 +1895,27 @@ pub(crate) fn build_specs(
|
||||
builder.register_handler("test_sync_tool", test_sync_handler);
|
||||
}
|
||||
|
||||
match config.web_search_mode {
|
||||
Some(WebSearchMode::Cached) => {
|
||||
builder.push_spec(ToolSpec::WebSearch {
|
||||
external_web_access: Some(false),
|
||||
});
|
||||
}
|
||||
Some(WebSearchMode::Live) => {
|
||||
builder.push_spec(ToolSpec::WebSearch {
|
||||
external_web_access: Some(true),
|
||||
});
|
||||
}
|
||||
Some(WebSearchMode::Disabled) | None => {}
|
||||
let external_web_access = match config.web_search_mode {
|
||||
Some(WebSearchMode::Cached) => Some(false),
|
||||
Some(WebSearchMode::Live) => Some(true),
|
||||
Some(WebSearchMode::Disabled) | None => None,
|
||||
};
|
||||
|
||||
if let Some(external_web_access) = external_web_access {
|
||||
let search_content_types = match config.web_search_tool_type {
|
||||
WebSearchToolType::Text => None,
|
||||
WebSearchToolType::TextAndImage => Some(
|
||||
WEB_SEARCH_CONTENT_TYPES
|
||||
.into_iter()
|
||||
.map(str::to_string)
|
||||
.collect(),
|
||||
),
|
||||
};
|
||||
|
||||
builder.push_spec(ToolSpec::WebSearch {
|
||||
external_web_access: Some(external_web_access),
|
||||
search_content_types,
|
||||
});
|
||||
}
|
||||
|
||||
if config.image_gen_tool {
|
||||
@@ -2186,6 +2199,7 @@ mod tests {
|
||||
create_apply_patch_freeform_tool(),
|
||||
ToolSpec::WebSearch {
|
||||
external_web_access: Some(true),
|
||||
search_content_types: None,
|
||||
},
|
||||
create_view_image_tool(),
|
||||
] {
|
||||
@@ -2500,6 +2514,7 @@ mod tests {
|
||||
tool.spec,
|
||||
ToolSpec::WebSearch {
|
||||
external_web_access: Some(false),
|
||||
search_content_types: None,
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -2524,6 +2539,38 @@ mod tests {
|
||||
tool.spec,
|
||||
ToolSpec::WebSearch {
|
||||
external_web_access: Some(true),
|
||||
search_content_types: None,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn web_search_tool_type_text_and_image_sets_search_content_types() {
|
||||
let config = test_config();
|
||||
let mut model_info =
|
||||
ModelsManager::construct_model_info_offline_for_tests("gpt-5-codex", &config);
|
||||
model_info.web_search_tool_type = WebSearchToolType::TextAndImage;
|
||||
let features = Features::with_defaults();
|
||||
|
||||
let tools_config = ToolsConfig::new(&ToolsConfigParams {
|
||||
model_info: &model_info,
|
||||
features: &features,
|
||||
web_search_mode: Some(WebSearchMode::Live),
|
||||
session_source: SessionSource::Cli,
|
||||
});
|
||||
let (tools, _) = build_specs(&tools_config, None, None, &[]).build();
|
||||
|
||||
let tool = find_tool(&tools, "web_search");
|
||||
assert_eq!(
|
||||
tool.spec,
|
||||
ToolSpec::WebSearch {
|
||||
external_web_access: Some(true),
|
||||
search_content_types: Some(
|
||||
WEB_SEARCH_CONTENT_TYPES
|
||||
.into_iter()
|
||||
.map(str::to_string)
|
||||
.collect()
|
||||
),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ fn test_model_info(
|
||||
default_verbosity: None,
|
||||
availability_nux: None,
|
||||
apply_patch_tool_type: None,
|
||||
web_search_tool_type: Default::default(),
|
||||
truncation_policy: TruncationPolicyConfig::bytes(10_000),
|
||||
supports_parallel_tool_calls: false,
|
||||
supports_image_detail_original: false,
|
||||
@@ -684,6 +685,7 @@ async fn model_switch_to_smaller_model_updates_token_context_window() -> Result<
|
||||
default_verbosity: None,
|
||||
availability_nux: None,
|
||||
apply_patch_tool_type: None,
|
||||
web_search_tool_type: Default::default(),
|
||||
truncation_policy: TruncationPolicyConfig::bytes(10_000),
|
||||
supports_parallel_tool_calls: false,
|
||||
supports_image_detail_original: false,
|
||||
|
||||
@@ -342,6 +342,7 @@ fn test_remote_model(slug: &str, priority: i32) -> ModelInfo {
|
||||
default_verbosity: None,
|
||||
availability_nux: None,
|
||||
apply_patch_tool_type: None,
|
||||
web_search_tool_type: Default::default(),
|
||||
truncation_policy: TruncationPolicyConfig::bytes(10_000),
|
||||
supports_parallel_tool_calls: false,
|
||||
supports_image_detail_original: false,
|
||||
|
||||
@@ -647,6 +647,7 @@ async fn remote_model_friendly_personality_instructions_with_feature() -> anyhow
|
||||
default_verbosity: None,
|
||||
availability_nux: None,
|
||||
apply_patch_tool_type: None,
|
||||
web_search_tool_type: Default::default(),
|
||||
truncation_policy: TruncationPolicyConfig::bytes(10_000),
|
||||
supports_parallel_tool_calls: false,
|
||||
supports_image_detail_original: false,
|
||||
@@ -761,6 +762,7 @@ async fn user_turn_personality_remote_model_template_includes_update_message() -
|
||||
default_verbosity: None,
|
||||
availability_nux: None,
|
||||
apply_patch_tool_type: None,
|
||||
web_search_tool_type: Default::default(),
|
||||
truncation_policy: TruncationPolicyConfig::bytes(10_000),
|
||||
supports_parallel_tool_calls: false,
|
||||
supports_image_detail_original: false,
|
||||
|
||||
@@ -301,6 +301,7 @@ async fn remote_models_remote_model_uses_unified_exec() -> Result<()> {
|
||||
default_verbosity: None,
|
||||
availability_nux: None,
|
||||
apply_patch_tool_type: None,
|
||||
web_search_tool_type: Default::default(),
|
||||
truncation_policy: TruncationPolicyConfig::bytes(10_000),
|
||||
supports_parallel_tool_calls: false,
|
||||
supports_image_detail_original: false,
|
||||
@@ -542,6 +543,7 @@ async fn remote_models_apply_remote_base_instructions() -> Result<()> {
|
||||
default_verbosity: None,
|
||||
availability_nux: None,
|
||||
apply_patch_tool_type: None,
|
||||
web_search_tool_type: Default::default(),
|
||||
truncation_policy: TruncationPolicyConfig::bytes(10_000),
|
||||
supports_parallel_tool_calls: false,
|
||||
supports_image_detail_original: false,
|
||||
@@ -1007,6 +1009,7 @@ fn test_remote_model_with_policy(
|
||||
default_verbosity: None,
|
||||
availability_nux: None,
|
||||
apply_patch_tool_type: None,
|
||||
web_search_tool_type: Default::default(),
|
||||
truncation_policy,
|
||||
supports_parallel_tool_calls: false,
|
||||
supports_image_detail_original: false,
|
||||
|
||||
@@ -407,6 +407,7 @@ async fn stdio_image_responses_are_sanitized_for_text_only_model() -> anyhow::Re
|
||||
default_verbosity: None,
|
||||
availability_nux: None,
|
||||
apply_patch_tool_type: None,
|
||||
web_search_tool_type: Default::default(),
|
||||
truncation_policy: TruncationPolicyConfig::bytes(10_000),
|
||||
supports_parallel_tool_calls: false,
|
||||
supports_image_detail_original: false,
|
||||
|
||||
@@ -1003,6 +1003,7 @@ async fn view_image_tool_returns_unsupported_message_for_text_only_model() -> an
|
||||
default_verbosity: None,
|
||||
availability_nux: None,
|
||||
apply_patch_tool_type: None,
|
||||
web_search_tool_type: Default::default(),
|
||||
truncation_policy: TruncationPolicyConfig::bytes(10_000),
|
||||
supports_parallel_tool_calls: false,
|
||||
supports_image_detail_original: false,
|
||||
|
||||
@@ -181,6 +181,16 @@ pub enum ApplyPatchToolType {
|
||||
Function,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash, TS, JsonSchema, Default,
|
||||
)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum WebSearchToolType {
|
||||
#[default]
|
||||
Text,
|
||||
TextAndImage,
|
||||
}
|
||||
|
||||
/// Server-provided truncation policy metadata for a model.
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, TS, JsonSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
@@ -243,6 +253,8 @@ pub struct ModelInfo {
|
||||
pub support_verbosity: bool,
|
||||
pub default_verbosity: Option<Verbosity>,
|
||||
pub apply_patch_tool_type: Option<ApplyPatchToolType>,
|
||||
#[serde(default)]
|
||||
pub web_search_tool_type: WebSearchToolType,
|
||||
pub truncation_policy: TruncationPolicyConfig,
|
||||
pub supports_parallel_tool_calls: bool,
|
||||
#[serde(default)]
|
||||
@@ -515,6 +527,7 @@ mod tests {
|
||||
support_verbosity: false,
|
||||
default_verbosity: None,
|
||||
apply_patch_tool_type: None,
|
||||
web_search_tool_type: WebSearchToolType::Text,
|
||||
truncation_policy: TruncationPolicyConfig::bytes(10_000),
|
||||
supports_parallel_tool_calls: false,
|
||||
supports_image_detail_original: false,
|
||||
@@ -718,6 +731,7 @@ mod tests {
|
||||
|
||||
assert_eq!(model.availability_nux, None);
|
||||
assert!(!model.supports_image_detail_original);
|
||||
assert_eq!(model.web_search_tool_type, WebSearchToolType::Text);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -806,6 +806,8 @@ impl App {
|
||||
history_cell::SessionHeaderHistoryCell::new(
|
||||
self.chat_widget.current_model().to_string(),
|
||||
self.chat_widget.current_reasoning_effort(),
|
||||
self.chat_widget
|
||||
.should_show_fast_status(self.chat_widget.current_service_tier()),
|
||||
self.config.cwd.clone(),
|
||||
version,
|
||||
)
|
||||
@@ -5178,6 +5180,7 @@ mod tests {
|
||||
is_first,
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
)) as Arc<dyn HistoryCell>
|
||||
};
|
||||
|
||||
@@ -5827,6 +5830,7 @@ mod tests {
|
||||
is_first,
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
)) as Arc<dyn HistoryCell>
|
||||
};
|
||||
|
||||
|
||||
@@ -1224,6 +1224,7 @@ impl ChatWidget {
|
||||
self.sync_fast_command_enabled();
|
||||
self.sync_personality_command_enabled();
|
||||
let startup_tooltip_override = self.startup_tooltip_override.take();
|
||||
let show_fast_status = self.should_show_fast_status(event.service_tier);
|
||||
let session_info_cell = history_cell::new_session_info(
|
||||
&self.config,
|
||||
&model_for_header,
|
||||
@@ -1233,6 +1234,7 @@ impl ChatWidget {
|
||||
self.auth_manager
|
||||
.auth_cached()
|
||||
.and_then(|auth| auth.account_plan_type()),
|
||||
show_fast_status,
|
||||
);
|
||||
self.apply_session_info_cell(session_info_cell);
|
||||
|
||||
@@ -7221,6 +7223,15 @@ impl ChatWidget {
|
||||
self.config.service_tier
|
||||
}
|
||||
|
||||
pub(crate) fn should_show_fast_status(&self, service_tier: Option<ServiceTier>) -> bool {
|
||||
matches!(service_tier, Some(ServiceTier::Fast))
|
||||
&& self
|
||||
.auth_manager
|
||||
.auth_cached()
|
||||
.as_ref()
|
||||
.is_some_and(CodexAuth::is_chatgpt_auth)
|
||||
}
|
||||
|
||||
fn fast_mode_enabled(&self) -> bool {
|
||||
self.config.features.enabled(Feature::FastMode)
|
||||
}
|
||||
@@ -7555,6 +7566,7 @@ impl ChatWidget {
|
||||
DEFAULT_MODEL_DISPLAY_NAME.to_string(),
|
||||
placeholder_style,
|
||||
None,
|
||||
false,
|
||||
config.cwd.clone(),
|
||||
CODEX_CLI_VERSION,
|
||||
))
|
||||
|
||||
@@ -7458,6 +7458,26 @@ async fn user_turn_carries_service_tier_after_fast_toggle() {
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn fast_status_indicator_requires_chatgpt_auth() {
|
||||
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(Some("gpt-5.3-codex")).await;
|
||||
chat.set_service_tier(Some(ServiceTier::Fast));
|
||||
|
||||
assert!(!chat.should_show_fast_status(chat.current_service_tier()));
|
||||
|
||||
set_chatgpt_auth(&mut chat);
|
||||
|
||||
assert!(chat.should_show_fast_status(chat.current_service_tier()));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn fast_status_indicator_is_hidden_when_fast_mode_is_off() {
|
||||
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(Some("gpt-5.3-codex")).await;
|
||||
set_chatgpt_auth(&mut chat);
|
||||
|
||||
assert!(!chat.should_show_fast_status(chat.current_service_tier()));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn approvals_popup_shows_disabled_presets() {
|
||||
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(None).await;
|
||||
|
||||
@@ -1047,6 +1047,7 @@ pub(crate) fn new_session_info(
|
||||
is_first_event: bool,
|
||||
tooltip_override: Option<String>,
|
||||
auth_plan: Option<PlanType>,
|
||||
show_fast_status: bool,
|
||||
) -> SessionInfoCell {
|
||||
let SessionConfiguredEvent {
|
||||
model,
|
||||
@@ -1057,6 +1058,7 @@ pub(crate) fn new_session_info(
|
||||
let header = SessionHeaderHistoryCell::new(
|
||||
model.clone(),
|
||||
reasoning_effort,
|
||||
show_fast_status,
|
||||
config.cwd.clone(),
|
||||
CODEX_CLI_VERSION,
|
||||
);
|
||||
@@ -1143,6 +1145,7 @@ pub(crate) struct SessionHeaderHistoryCell {
|
||||
model: String,
|
||||
model_style: Style,
|
||||
reasoning_effort: Option<ReasoningEffortConfig>,
|
||||
show_fast_status: bool,
|
||||
directory: PathBuf,
|
||||
}
|
||||
|
||||
@@ -1150,6 +1153,7 @@ impl SessionHeaderHistoryCell {
|
||||
pub(crate) fn new(
|
||||
model: String,
|
||||
reasoning_effort: Option<ReasoningEffortConfig>,
|
||||
show_fast_status: bool,
|
||||
directory: PathBuf,
|
||||
version: &'static str,
|
||||
) -> Self {
|
||||
@@ -1157,6 +1161,7 @@ impl SessionHeaderHistoryCell {
|
||||
model,
|
||||
Style::default(),
|
||||
reasoning_effort,
|
||||
show_fast_status,
|
||||
directory,
|
||||
version,
|
||||
)
|
||||
@@ -1166,6 +1171,7 @@ impl SessionHeaderHistoryCell {
|
||||
model: String,
|
||||
model_style: Style,
|
||||
reasoning_effort: Option<ReasoningEffortConfig>,
|
||||
show_fast_status: bool,
|
||||
directory: PathBuf,
|
||||
version: &'static str,
|
||||
) -> Self {
|
||||
@@ -1174,6 +1180,7 @@ impl SessionHeaderHistoryCell {
|
||||
model,
|
||||
model_style,
|
||||
reasoning_effort,
|
||||
show_fast_status,
|
||||
directory,
|
||||
}
|
||||
}
|
||||
@@ -1253,6 +1260,10 @@ impl HistoryCell for SessionHeaderHistoryCell {
|
||||
spans.push(Span::from(" "));
|
||||
spans.push(Span::from(reasoning));
|
||||
}
|
||||
if self.show_fast_status {
|
||||
spans.push(" ".into());
|
||||
spans.push(Span::styled("fast", self.model_style.magenta()));
|
||||
}
|
||||
spans.push(" ".dim());
|
||||
spans.push(CHANGE_MODEL_HINT_COMMAND.cyan());
|
||||
spans.push(CHANGE_MODEL_HINT_EXPLANATION.dim());
|
||||
@@ -2612,6 +2623,7 @@ mod tests {
|
||||
false,
|
||||
Some("Model just became available".to_string()),
|
||||
Some(PlanType::Free),
|
||||
false,
|
||||
);
|
||||
|
||||
let rendered = render_transcript(&cell).join("\n");
|
||||
@@ -2629,6 +2641,7 @@ mod tests {
|
||||
false,
|
||||
Some("Model just became available".to_string()),
|
||||
Some(PlanType::Free),
|
||||
false,
|
||||
);
|
||||
|
||||
let rendered = render_transcript(&cell).join("\n");
|
||||
@@ -2645,6 +2658,7 @@ mod tests {
|
||||
true,
|
||||
Some("Model just became available".to_string()),
|
||||
Some(PlanType::Free),
|
||||
false,
|
||||
);
|
||||
|
||||
let rendered = render_transcript(&cell).join("\n");
|
||||
@@ -2663,6 +2677,7 @@ mod tests {
|
||||
false,
|
||||
Some("Model just became available".to_string()),
|
||||
Some(PlanType::Free),
|
||||
false,
|
||||
);
|
||||
|
||||
let rendered = render_transcript(&cell).join("\n");
|
||||
@@ -3295,18 +3310,39 @@ mod tests {
|
||||
let cell = SessionHeaderHistoryCell::new(
|
||||
"gpt-4o".to_string(),
|
||||
Some(ReasoningEffortConfig::High),
|
||||
true,
|
||||
std::env::temp_dir(),
|
||||
"test",
|
||||
);
|
||||
|
||||
let lines = render_lines(&cell.display_lines(80));
|
||||
let model_line = lines
|
||||
.into_iter()
|
||||
.iter()
|
||||
.find(|line| line.contains("model:"))
|
||||
.expect("model line");
|
||||
|
||||
assert!(model_line.contains("gpt-4o high fast"));
|
||||
assert!(model_line.contains("/model to change"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn session_header_hides_fast_status_when_disabled() {
|
||||
let cell = SessionHeaderHistoryCell::new(
|
||||
"gpt-4o".to_string(),
|
||||
Some(ReasoningEffortConfig::High),
|
||||
false,
|
||||
std::env::temp_dir(),
|
||||
"test",
|
||||
);
|
||||
|
||||
let lines = render_lines(&cell.display_lines(80));
|
||||
let model_line = lines
|
||||
.iter()
|
||||
.find(|line| line.contains("model:"))
|
||||
.expect("model line");
|
||||
|
||||
assert!(model_line.contains("gpt-4o high"));
|
||||
assert!(model_line.contains("/model to change"));
|
||||
assert!(!model_line.contains("fast"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
---
|
||||
source: tui/src/app.rs
|
||||
assertion_line: 3452
|
||||
expression: rendered
|
||||
---
|
||||
╭─────────────────────────────────────────────╮
|
||||
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
---
|
||||
source: tui/src/history_cell.rs
|
||||
assertion_line: 2608
|
||||
expression: rendered
|
||||
---
|
||||
╭─────────────────────────────────────╮
|
||||
|
||||
Reference in New Issue
Block a user