mirror of
https://github.com/openai/codex.git
synced 2026-05-28 23:10:20 +00:00
## Why Long `/goal` definitions currently reach lower-level goal validation and can produce an opaque failure. This bug was reported by a user. Pasted instruction blocks are especially confusing because the composer can still contain a paste placeholder before expansion, which may otherwise fall into the generic prompt-size error path. There was also a related paste edge case where `/goal ` followed by a multiline block whose first pasted line was blank looked like a bare `/goal` command. That showed the goal usage/summary instead of setting the pasted objective. ## What Changed This adds TUI-side preflight validation for `/goal <objective>` using the shared `MAX_THREAD_GOAL_OBJECTIVE_CHARS` limit. Oversized typed, queued, and pasted goal objectives now fail locally with a goal-specific message that recommends putting longer instructions in a file and referencing that file from the goal. The TUI now also lets inline-argument slash commands consume later-line arguments before treating the first line as a bare command, so `/goal ` followed by blank lines and then objective text sets the goal instead of opening the bare `/goal` flow. ## Manual Testing 1. Start the TUI with goals enabled and an active session. 2. Submit `/goal ` followed by exactly 4,000 objective characters. It should continue through the normal goal-setting path. 3. Submit `/goal ` followed by 4,001 objective characters. It should not set a goal, and should show `Goal objective is too long: 4,001 characters. Limit: 4,000 characters.` followed by the guidance to put longer instructions in a file and reference that file from the goal. 4. Type `/goal `, paste a large block that becomes a `[Pasted Content ... chars]` placeholder, then submit. It should validate the expanded pasted text and show the goal-specific file guidance rather than the generic prompt-size error. 5. Type `/goal `, paste a multiline block whose first line is blank, then submit. It should set the objective from the non-blank pasted content instead of showing `Usage: /goal <objective>` or the bare goal summary. 6. While a turn is running, queue an oversized `/goal` command. When the queue drains, it should show the same goal-specific error and should not emit a goal-setting request.
249 lines
14 KiB
Rust
249 lines
14 KiB
Rust
//! Exercises `ChatWidget` event handling and rendering invariants.
|
|
//!
|
|
//! These tests cover both app-server-native inputs and focused widget helpers. Many assertions are
|
|
//! snapshot-based so that layout regressions and status/header changes show up as stable,
|
|
//! reviewable diffs.
|
|
|
|
pub(super) use super::*;
|
|
pub(super) use crate::app_command::AppCommand as Op;
|
|
pub(super) use crate::app_event::AppEvent;
|
|
pub(super) use crate::app_event::ExitMode;
|
|
#[cfg(not(target_os = "linux"))]
|
|
pub(super) use crate::app_event::RealtimeAudioDeviceKind;
|
|
pub(super) use crate::app_event_sender::AppEventSender;
|
|
pub(super) use crate::approval_events::ApplyPatchApprovalRequestEvent;
|
|
pub(super) use crate::approval_events::ExecApprovalRequestEvent;
|
|
pub(super) use crate::bottom_pane::LocalImageAttachment;
|
|
pub(super) use crate::bottom_pane::MentionBinding;
|
|
pub(super) use crate::bottom_pane::QueuedInputAction;
|
|
pub(super) use crate::chatwidget::realtime::RealtimeConversationPhase;
|
|
pub(super) use crate::diff_model::FileChange;
|
|
pub(super) use crate::history_cell::UserHistoryCell;
|
|
pub(super) use crate::legacy_core::config::Config;
|
|
pub(super) use crate::legacy_core::config::ConfigBuilder;
|
|
pub(super) use crate::legacy_core::config::Constrained;
|
|
pub(super) use crate::legacy_core::config::ConstraintError;
|
|
pub(super) use crate::model_catalog::ModelCatalog;
|
|
pub(super) use crate::test_backend::VT100Backend;
|
|
pub(super) use crate::test_support::PathBufExt;
|
|
pub(super) use crate::test_support::test_path_buf;
|
|
pub(super) use crate::test_support::test_path_display;
|
|
pub(super) use crate::token_usage::TokenUsage;
|
|
pub(super) use crate::token_usage::TokenUsageInfo;
|
|
pub(super) use crate::tui::FrameRequester;
|
|
pub(super) use assert_matches::assert_matches;
|
|
pub(super) use codex_app_server_protocol::AddCreditsNudgeCreditType;
|
|
pub(super) use codex_app_server_protocol::AddCreditsNudgeEmailStatus;
|
|
pub(super) use codex_app_server_protocol::AdditionalFileSystemPermissions as AppServerAdditionalFileSystemPermissions;
|
|
pub(super) use codex_app_server_protocol::AdditionalNetworkPermissions as AppServerAdditionalNetworkPermissions;
|
|
pub(super) use codex_app_server_protocol::AdditionalPermissionProfile as AppServerAdditionalPermissionProfile;
|
|
pub(super) use codex_app_server_protocol::AppSummary;
|
|
pub(super) use codex_app_server_protocol::AutoReviewDecisionSource as AppServerGuardianApprovalReviewDecisionSource;
|
|
pub(super) use codex_app_server_protocol::CodexErrorInfo;
|
|
pub(super) use codex_app_server_protocol::CollabAgentState as AppServerCollabAgentState;
|
|
pub(super) use codex_app_server_protocol::CollabAgentStatus as AppServerCollabAgentStatus;
|
|
pub(super) use codex_app_server_protocol::CollabAgentTool as AppServerCollabAgentTool;
|
|
pub(super) use codex_app_server_protocol::CollabAgentToolCallStatus as AppServerCollabAgentToolCallStatus;
|
|
pub(super) use codex_app_server_protocol::CommandAction as AppServerCommandAction;
|
|
pub(super) use codex_app_server_protocol::CommandExecutionRequestApprovalParams as AppServerCommandExecutionRequestApprovalParams;
|
|
pub(super) use codex_app_server_protocol::CommandExecutionSource as ExecCommandSource;
|
|
pub(super) use codex_app_server_protocol::CommandExecutionSource as AppServerCommandExecutionSource;
|
|
pub(super) use codex_app_server_protocol::CommandExecutionStatus as AppServerCommandExecutionStatus;
|
|
pub(super) use codex_app_server_protocol::ConfigWarningNotification;
|
|
pub(super) use codex_app_server_protocol::CreditsSnapshot;
|
|
pub(super) use codex_app_server_protocol::ErrorNotification;
|
|
pub(super) use codex_app_server_protocol::ExecPolicyAmendment;
|
|
pub(super) use codex_app_server_protocol::FileUpdateChange;
|
|
pub(super) use codex_app_server_protocol::GuardianApprovalReview;
|
|
pub(super) use codex_app_server_protocol::GuardianApprovalReviewAction as AppServerGuardianApprovalReviewAction;
|
|
pub(super) use codex_app_server_protocol::GuardianApprovalReviewStatus;
|
|
pub(super) use codex_app_server_protocol::GuardianCommandSource as AppServerGuardianCommandSource;
|
|
pub(super) use codex_app_server_protocol::GuardianRiskLevel as AppServerGuardianRiskLevel;
|
|
pub(super) use codex_app_server_protocol::GuardianUserAuthorization as AppServerGuardianUserAuthorization;
|
|
pub(super) use codex_app_server_protocol::GuardianWarningNotification;
|
|
pub(super) use codex_app_server_protocol::HookCompletedNotification as AppServerHookCompletedNotification;
|
|
pub(super) use codex_app_server_protocol::HookEventName as AppServerHookEventName;
|
|
pub(super) use codex_app_server_protocol::HookExecutionMode as AppServerHookExecutionMode;
|
|
pub(super) use codex_app_server_protocol::HookHandlerType as AppServerHookHandlerType;
|
|
pub(super) use codex_app_server_protocol::HookOutputEntry as AppServerHookOutputEntry;
|
|
pub(super) use codex_app_server_protocol::HookOutputEntryKind as AppServerHookOutputEntryKind;
|
|
pub(super) use codex_app_server_protocol::HookRunStatus as AppServerHookRunStatus;
|
|
pub(super) use codex_app_server_protocol::HookRunSummary as AppServerHookRunSummary;
|
|
pub(super) use codex_app_server_protocol::HookScope as AppServerHookScope;
|
|
pub(super) use codex_app_server_protocol::HookStartedNotification as AppServerHookStartedNotification;
|
|
pub(super) use codex_app_server_protocol::ItemCompletedNotification;
|
|
pub(super) use codex_app_server_protocol::ItemGuardianApprovalReviewCompletedNotification;
|
|
pub(super) use codex_app_server_protocol::ItemGuardianApprovalReviewStartedNotification;
|
|
pub(super) use codex_app_server_protocol::ItemStartedNotification;
|
|
pub(super) use codex_app_server_protocol::MarketplaceAddResponse;
|
|
pub(super) use codex_app_server_protocol::MarketplaceInterface;
|
|
pub(super) use codex_app_server_protocol::MarketplaceUpgradeErrorInfo;
|
|
pub(super) use codex_app_server_protocol::MarketplaceUpgradeResponse;
|
|
pub(super) use codex_app_server_protocol::McpServerStartupState;
|
|
pub(super) use codex_app_server_protocol::McpServerStatusDetail;
|
|
pub(super) use codex_app_server_protocol::McpServerStatusUpdatedNotification;
|
|
pub(super) use codex_app_server_protocol::ModelVerification as AppServerModelVerification;
|
|
pub(super) use codex_app_server_protocol::ModelVerificationNotification;
|
|
pub(super) use codex_app_server_protocol::NonSteerableTurnKind;
|
|
pub(super) use codex_app_server_protocol::PatchApplyStatus as AppServerPatchApplyStatus;
|
|
pub(super) use codex_app_server_protocol::PatchChangeKind;
|
|
pub(super) use codex_app_server_protocol::PermissionsRequestApprovalParams as AppServerPermissionsRequestApprovalParams;
|
|
pub(super) use codex_app_server_protocol::PluginAuthPolicy;
|
|
pub(super) use codex_app_server_protocol::PluginDetail;
|
|
pub(super) use codex_app_server_protocol::PluginInstallPolicy;
|
|
pub(super) use codex_app_server_protocol::PluginInterface;
|
|
pub(super) use codex_app_server_protocol::PluginListResponse;
|
|
pub(super) use codex_app_server_protocol::PluginMarketplaceEntry;
|
|
pub(super) use codex_app_server_protocol::PluginReadResponse;
|
|
pub(super) use codex_app_server_protocol::PluginSource;
|
|
pub(super) use codex_app_server_protocol::PluginSummary;
|
|
pub(super) use codex_app_server_protocol::RateLimitReachedType;
|
|
pub(super) use codex_app_server_protocol::RateLimitSnapshot;
|
|
pub(super) use codex_app_server_protocol::RateLimitWindow;
|
|
pub(super) use codex_app_server_protocol::ReasoningSummaryTextDeltaNotification;
|
|
pub(super) use codex_app_server_protocol::ReviewTarget;
|
|
pub(super) use codex_app_server_protocol::ServerNotification;
|
|
pub(super) use codex_app_server_protocol::SkillSummary;
|
|
pub(super) use codex_app_server_protocol::ThreadClosedNotification;
|
|
pub(super) use codex_app_server_protocol::ThreadItem as AppServerThreadItem;
|
|
pub(super) use codex_app_server_protocol::ThreadRealtimeClosedNotification;
|
|
pub(super) use codex_app_server_protocol::ThreadRealtimeErrorNotification;
|
|
pub(super) use codex_app_server_protocol::ToolRequestUserInputOption;
|
|
pub(super) use codex_app_server_protocol::ToolRequestUserInputParams;
|
|
pub(super) use codex_app_server_protocol::ToolRequestUserInputQuestion;
|
|
pub(super) use codex_app_server_protocol::Turn as AppServerTurn;
|
|
pub(super) use codex_app_server_protocol::TurnCompletedNotification;
|
|
pub(super) use codex_app_server_protocol::TurnError as AppServerTurnError;
|
|
pub(super) use codex_app_server_protocol::TurnStartedNotification;
|
|
pub(super) use codex_app_server_protocol::TurnStatus as AppServerTurnStatus;
|
|
pub(super) use codex_app_server_protocol::UserInput;
|
|
pub(super) use codex_app_server_protocol::UserInput as AppServerUserInput;
|
|
pub(super) use codex_app_server_protocol::WarningNotification;
|
|
pub(super) use codex_config::AppRequirementToml;
|
|
pub(super) use codex_config::AppsRequirementsToml;
|
|
pub(super) use codex_config::ConfigLayerStack;
|
|
pub(super) use codex_config::ConfigRequirements;
|
|
pub(super) use codex_config::ConfigRequirementsToml;
|
|
pub(super) use codex_config::RequirementSource;
|
|
pub(super) use codex_config::types::ApprovalsReviewer;
|
|
pub(super) use codex_config::types::Notifications;
|
|
#[cfg(target_os = "windows")]
|
|
pub(super) use codex_config::types::WindowsSandboxModeToml;
|
|
pub(super) use codex_core_plugins::OPENAI_CURATED_MARKETPLACE_NAME;
|
|
pub(super) use codex_core_skills::model::SkillMetadata;
|
|
pub(super) use codex_features::FEATURES;
|
|
pub(super) use codex_features::Feature;
|
|
pub(super) use codex_git_utils::CommitLogEntry;
|
|
pub(super) use codex_otel::RuntimeMetricsSummary;
|
|
pub(super) use codex_otel::SessionTelemetry;
|
|
pub(super) use codex_protocol::ThreadId;
|
|
pub(super) use codex_protocol::account::PlanType;
|
|
pub(super) use codex_protocol::approvals::GuardianAssessmentAction;
|
|
pub(super) use codex_protocol::approvals::GuardianAssessmentDecisionSource;
|
|
pub(super) use codex_protocol::approvals::GuardianAssessmentEvent;
|
|
pub(super) use codex_protocol::approvals::GuardianAssessmentStatus;
|
|
pub(super) use codex_protocol::approvals::GuardianCommandSource;
|
|
pub(super) use codex_protocol::approvals::GuardianRiskLevel;
|
|
pub(super) use codex_protocol::approvals::GuardianUserAuthorization;
|
|
pub(super) use codex_protocol::config_types::CollaborationMode;
|
|
pub(super) use codex_protocol::config_types::ModeKind;
|
|
pub(super) use codex_protocol::config_types::Personality;
|
|
pub(super) use codex_protocol::config_types::ServiceTier;
|
|
pub(super) use codex_protocol::config_types::Settings;
|
|
pub(super) use codex_protocol::models::FileSystemPermissions;
|
|
pub(super) use codex_protocol::models::MessagePhase;
|
|
pub(super) use codex_protocol::models::NetworkPermissions;
|
|
pub(super) use codex_protocol::models::PermissionProfile;
|
|
pub(super) use codex_protocol::openai_models::ModelInfo;
|
|
pub(super) use codex_protocol::openai_models::ModelPreset;
|
|
pub(super) use codex_protocol::openai_models::ModelsResponse;
|
|
pub(super) use codex_protocol::openai_models::ReasoningEffortPreset;
|
|
pub(super) use codex_protocol::openai_models::default_input_modalities;
|
|
pub(super) use codex_protocol::parse_command::ParsedCommand;
|
|
pub(super) use codex_protocol::plan_tool::PlanItemArg;
|
|
pub(super) use codex_protocol::plan_tool::StepStatus;
|
|
pub(super) use codex_protocol::plan_tool::UpdatePlanArgs;
|
|
pub(super) use codex_protocol::request_permissions::RequestPermissionProfile;
|
|
pub(super) use codex_protocol::user_input::TextElement;
|
|
pub(super) use codex_terminal_detection::Multiplexer;
|
|
pub(super) use codex_terminal_detection::TerminalInfo;
|
|
pub(super) use codex_terminal_detection::TerminalName;
|
|
pub(super) use codex_utils_absolute_path::AbsolutePathBuf;
|
|
pub(super) use codex_utils_approval_presets::builtin_approval_presets;
|
|
pub(super) use crossterm::event::KeyCode;
|
|
pub(super) use crossterm::event::KeyEvent;
|
|
pub(super) use crossterm::event::KeyModifiers;
|
|
pub(super) use insta::assert_snapshot;
|
|
pub(super) use serde_json::json;
|
|
#[cfg(target_os = "windows")]
|
|
pub(super) use serial_test::serial;
|
|
pub(super) use std::collections::BTreeMap;
|
|
pub(super) use std::collections::HashMap;
|
|
pub(super) use std::collections::HashSet;
|
|
pub(super) use std::path::PathBuf;
|
|
pub(super) use tempfile::NamedTempFile;
|
|
pub(super) use tempfile::tempdir;
|
|
pub(super) use tokio::sync::mpsc::error::TryRecvError;
|
|
pub(super) use tokio::sync::mpsc::unbounded_channel;
|
|
pub(super) use toml::Value as TomlValue;
|
|
|
|
pub(super) fn chatwidget_snapshot_dir() -> PathBuf {
|
|
let snapshot_file = codex_utils_cargo_bin::find_resource!(
|
|
"src/chatwidget/snapshots/codex_tui__chatwidget__tests__chatwidget_tall.snap"
|
|
)
|
|
.expect("snapshot file");
|
|
snapshot_file
|
|
.parent()
|
|
.unwrap_or_else(|| panic!("snapshot file has no parent: {}", snapshot_file.display()))
|
|
.to_path_buf()
|
|
}
|
|
|
|
macro_rules! assert_chatwidget_snapshot {
|
|
($name:expr, $value:expr $(,)?) => {{
|
|
let mut settings = insta::Settings::clone_current();
|
|
settings.set_prepend_module_to_snapshot(false);
|
|
settings.set_snapshot_path(crate::chatwidget::tests::chatwidget_snapshot_dir());
|
|
settings.bind(|| {
|
|
insta::assert_snapshot!(format!("codex_tui__chatwidget__tests__{}", $name), $value);
|
|
});
|
|
}};
|
|
($name:expr, $value:expr, @$snapshot:literal $(,)?) => {{
|
|
let mut settings = insta::Settings::clone_current();
|
|
settings.set_prepend_module_to_snapshot(false);
|
|
settings.set_snapshot_path(crate::chatwidget::tests::chatwidget_snapshot_dir());
|
|
settings.bind(|| {
|
|
insta::assert_snapshot!(
|
|
format!("codex_tui__chatwidget__tests__{}", $name),
|
|
&($value),
|
|
@$snapshot
|
|
);
|
|
});
|
|
}};
|
|
}
|
|
|
|
mod app_server;
|
|
mod approval_requests;
|
|
mod composer_submission;
|
|
mod exec_flow;
|
|
mod goal_menu;
|
|
mod goal_validation;
|
|
mod guardian;
|
|
mod helpers;
|
|
mod history_replay;
|
|
mod mcp_startup;
|
|
mod permissions;
|
|
mod plan_mode;
|
|
mod popups_and_settings;
|
|
mod review_mode;
|
|
mod side;
|
|
mod slash_commands;
|
|
mod status_and_layout;
|
|
mod status_command_tests;
|
|
mod status_surface_previews;
|
|
mod terminal_title;
|
|
|
|
pub(crate) use helpers::make_chatwidget_manual_with_sender;
|
|
pub(crate) use helpers::set_chatgpt_auth;
|
|
pub(crate) use helpers::set_fast_mode_test_catalog;
|
|
pub(super) use helpers::*;
|