mirror of
https://github.com/codewhale-hq/Codewhale.git
synced 2026-11-11 01:51:34 -10:00
c03: delete the four re-export shims and migrate their last consumers
`docs/design/TUI_DECONSTRUCTION.md:176,185-186` forbids landing temporary re-export shims whose last consumers are deferred: "do not land temporary re-export shims with their last consumers left for an unspecified future migration. Keep shims only for genuine external compatibility contracts and identify that contract." Four survived the earlier C03 slices — `tui/app/types.rs`, `tui/file_mention.rs`, `tui/agent_roster.rs`, `tui/approval.rs` — and none named such a contract. There was nothing to protect: no crate outside `crates/tui` referenced the moved symbols. So this migrates every remaining internal consumer to the owning crate and removes all four in one commit, because landing three of four is precisely the deferred-consumer state the rule exists to prevent. `crates/tui/src/turn_route_plan.rs` now imports `codewhale_config::AppMode` directly. `AppModeUi` stays in `tui::app` — it is genuinely UI-specific and not a shim. `docs/design/TUI_DECONSTRUCTION.md` is updated in the same commit so the dependency list describes the tree as it now is rather than as it was. Also closes the coverage gap this packet's own done-evidence depended on. `cargo test -p codewhale-config --lib app_mode` previously reported `0 passed; 0 failed` with 693 filtered out — a filter matching nothing, which the repo's rules count as a gap and not a pass — while C03 claimed "unchanged serialization behavior". `AppMode`'s new owner now carries focused tests for the setting round-trip, parse/label/cycle order, and the fallback for unknown values. cargo test -p codewhale-config --lib --locked app_mode test result: ok. 5 passed; 0 failed; 693 filtered out (was 0 passed) cargo test -p codewhale-tui --lib --locked -- approval agent_roster context_reference app_mode test result: ok. 298 passed; 0 failed; 12317 filtered out cargo test -p codewhale-execpolicy -p codewhale-config --locked test result: ok. 697 passed; 0 failed; 1 ignored test result: ok. 112 passed; 0 failed (plus 10, 5, 1, 1 passed across the remaining targets) cargo check --workspace --all-targets --locked: 0 errors, 0 unused warnings The fallback test deserves a note, since its first draft asserted the opposite: `from_setting` returns `Agent` for an empty or unrecognized value, which is the long-standing shipped behavior and is unchanged here. Mode is not the permission surface — as `AppMode::parse` documents, the bypass posture the legacy YOLO spellings imply travels on the permission surface, not on a mode. Refs: Linear C03 / SHA-6179, GitHub #5316. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01X57KRgwqYkmmtVQScczqiL
This commit is contained in:
1 parent
7ad4e661cd
commit
15b140e1ca
36 files changed
+264
-174
No files matched your search
@@ -122,3 +122,102 @@ impl AppMode {
|
||||
Self::CYCLE[(index + Self::CYCLE.len() - 1) % Self::CYCLE.len()]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn app_mode_helpers_centralize_parse_labels_and_cycle_order() {
|
||||
assert_eq!(AppMode::parse("agent"), Some(AppMode::Agent));
|
||||
assert_eq!(AppMode::parse("act"), Some(AppMode::Agent));
|
||||
assert_eq!(AppMode::parse("work"), Some(AppMode::Agent));
|
||||
assert_eq!(AppMode::parse("2"), Some(AppMode::Plan));
|
||||
assert_eq!(AppMode::parse("auto"), Some(AppMode::Agent));
|
||||
assert_eq!(AppMode::parse("3"), Some(AppMode::Operate));
|
||||
assert_eq!(AppMode::parse("operate"), Some(AppMode::Operate));
|
||||
// Legacy YOLO spellings resolve to Act; the bypass posture they imply
|
||||
// travels on the permission surface, not on a mode.
|
||||
assert_eq!(AppMode::parse("YOLO"), Some(AppMode::Agent));
|
||||
assert_eq!(AppMode::parse("4"), Some(AppMode::Agent));
|
||||
assert_eq!(AppMode::parse("bypass"), Some(AppMode::Agent));
|
||||
assert_eq!(AppMode::parse("bypass-permissions"), Some(AppMode::Agent));
|
||||
assert_eq!(AppMode::parse("multitask"), None);
|
||||
assert_eq!(AppMode::parse("5"), None);
|
||||
assert_eq!(AppMode::parse("fast"), None);
|
||||
assert_eq!(AppMode::from_setting("multitask"), AppMode::Operate);
|
||||
assert_eq!(AppMode::from_setting("5"), AppMode::Operate);
|
||||
|
||||
assert_eq!(AppMode::Agent.as_setting(), "agent");
|
||||
assert_eq!(AppMode::Plan.display_name(), "Plan");
|
||||
assert_eq!(AppMode::Agent.number(), '1');
|
||||
assert_eq!(AppMode::Operate.number(), '3');
|
||||
assert_eq!(
|
||||
AppMode::CYCLE,
|
||||
[AppMode::Plan, AppMode::Agent, AppMode::Operate]
|
||||
);
|
||||
|
||||
assert_eq!(AppMode::Plan.next(), AppMode::Agent);
|
||||
assert_eq!(AppMode::Agent.next(), AppMode::Operate);
|
||||
assert_eq!(AppMode::Operate.next(), AppMode::Plan);
|
||||
assert_eq!(AppMode::Plan.previous(), AppMode::Operate);
|
||||
assert_eq!(AppMode::Agent.previous(), AppMode::Plan);
|
||||
assert_eq!(AppMode::Operate.previous(), AppMode::Agent);
|
||||
}
|
||||
|
||||
/// The durable form of a mode is the `as_setting()` string persisted into
|
||||
/// settings and session records — `AppMode` derives no `Serialize`, so the
|
||||
/// round-trip that has to hold is string -> mode -> string.
|
||||
#[test]
|
||||
fn setting_strings_round_trip_for_every_mode() {
|
||||
for mode in AppMode::CYCLE {
|
||||
let setting = mode.as_setting();
|
||||
assert_eq!(
|
||||
AppMode::from_setting(setting),
|
||||
mode,
|
||||
"from_setting({setting})"
|
||||
);
|
||||
assert_eq!(AppMode::parse(setting), Some(mode), "parse({setting})");
|
||||
}
|
||||
|
||||
assert_eq!(AppMode::Agent.as_setting(), "agent");
|
||||
assert_eq!(AppMode::Plan.as_setting(), "plan");
|
||||
assert_eq!(AppMode::Operate.as_setting(), "operate");
|
||||
}
|
||||
|
||||
/// `from_setting` is the de-facto default: an absent, empty, or unreadable
|
||||
/// stored value must land on Act rather than panicking or picking Operate.
|
||||
#[test]
|
||||
fn from_setting_falls_back_to_act_for_unknown_values() {
|
||||
assert_eq!(AppMode::from_setting(""), AppMode::Agent);
|
||||
assert_eq!(AppMode::from_setting(" "), AppMode::Agent);
|
||||
assert_eq!(AppMode::from_setting("nonsense"), AppMode::Agent);
|
||||
assert_eq!(AppMode::from_setting("OPERATE"), AppMode::Operate);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn labels_and_descriptions_cover_every_mode() {
|
||||
assert_eq!(AppMode::Agent.label(), "ACT");
|
||||
assert_eq!(AppMode::Plan.label(), "PLAN");
|
||||
assert_eq!(AppMode::Operate.label(), "OPERATE");
|
||||
|
||||
assert_eq!(AppMode::Agent.display_name(), "Act");
|
||||
assert_eq!(AppMode::Plan.display_name(), "Plan");
|
||||
assert_eq!(AppMode::Operate.display_name(), "Operate");
|
||||
|
||||
for mode in AppMode::CYCLE {
|
||||
assert!(!mode.description().is_empty());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn operate_shares_the_agent_baseline_and_raises_the_launch_floor() {
|
||||
assert!(AppMode::Agent.uses_agent_baseline());
|
||||
assert!(AppMode::Operate.uses_agent_baseline());
|
||||
assert!(!AppMode::Plan.uses_agent_baseline());
|
||||
|
||||
assert_eq!(AppMode::Operate.mode_delegation_launch_floor(), 4);
|
||||
assert_eq!(AppMode::Agent.mode_delegation_launch_floor(), 1);
|
||||
assert_eq!(AppMode::Plan.mode_delegation_launch_floor(), 1);
|
||||
}
|
||||
}
|
||||
@@ -62,3 +62,71 @@ impl ApprovalMode {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_approval_mode_labels() {
|
||||
assert_eq!(ApprovalMode::Auto.label(), "AUTO");
|
||||
assert_eq!(ApprovalMode::Suggest.label(), "SUGGEST");
|
||||
assert_eq!(ApprovalMode::Never.label(), "NEVER");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_approval_mode_from_config_value_accepts_aliases() {
|
||||
assert_eq!(
|
||||
ApprovalMode::from_config_value("auto"),
|
||||
Some(ApprovalMode::Auto)
|
||||
);
|
||||
assert_eq!(
|
||||
ApprovalMode::from_config_value("on-request"),
|
||||
Some(ApprovalMode::Suggest)
|
||||
);
|
||||
assert_eq!(
|
||||
ApprovalMode::from_config_value("full_access"),
|
||||
Some(ApprovalMode::Bypass)
|
||||
);
|
||||
assert_eq!(
|
||||
ApprovalMode::from_config_value("deny"),
|
||||
Some(ApprovalMode::Never)
|
||||
);
|
||||
assert_eq!(ApprovalMode::from_config_value("unknown"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn permission_cycle_is_a_closed_loop_and_never_is_off_cycle() {
|
||||
assert_eq!(
|
||||
ApprovalMode::PERMISSION_CYCLE,
|
||||
[
|
||||
ApprovalMode::Suggest,
|
||||
ApprovalMode::Auto,
|
||||
ApprovalMode::Bypass
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
ApprovalMode::Suggest.cycle_permission_next(),
|
||||
ApprovalMode::Auto
|
||||
);
|
||||
assert_eq!(
|
||||
ApprovalMode::Auto.cycle_permission_next(),
|
||||
ApprovalMode::Bypass
|
||||
);
|
||||
assert_eq!(
|
||||
ApprovalMode::Bypass.cycle_permission_next(),
|
||||
ApprovalMode::Suggest
|
||||
);
|
||||
// Never is deliberately outside the Shift+Tab cycle; stepping from it
|
||||
// must land on the safest posture rather than panicking or wrapping.
|
||||
assert_eq!(
|
||||
ApprovalMode::Never.cycle_permission_next(),
|
||||
ApprovalMode::Suggest
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_posture_is_suggest() {
|
||||
assert_eq!(ApprovalMode::default(), ApprovalMode::Suggest);
|
||||
}
|
||||
}
|
||||
@@ -19,8 +19,9 @@ use crate::config_persistence::{
|
||||
use crate::localization::{MessageId, resolve_locale, tr};
|
||||
use crate::reasoning_preference::ReasoningEffort;
|
||||
use crate::settings::Settings;
|
||||
use crate::tui::app::{App, AppAction, AppMode, OnboardingState, ScreenMode, SettingSelection, VimMode};
|
||||
use crate::tui::app::{App, AppAction, OnboardingState, ScreenMode, SettingSelection, VimMode};
|
||||
use anyhow::Result;
|
||||
use codewhale_config::AppMode;
|
||||
use codewhale_execpolicy::ApprovalMode;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
|
||||
@@ -526,8 +526,9 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::config::{ApiProvider, Config};
|
||||
use crate::models::{ContentBlock, Message};
|
||||
use crate::tui::app::{AppMode, TuiOptions};
|
||||
use crate::tui::app::TuiOptions;
|
||||
use crate::tui::history::HistoryCell;
|
||||
use codewhale_config::AppMode;
|
||||
|
||||
#[test]
|
||||
fn status_keeps_current_session_snapshot_remedy_after_notice_delivery() {
|
||||
|
||||
@@ -10,8 +10,9 @@ use crate::config::{
|
||||
use crate::localization::{Locale, MessageId, tr};
|
||||
#[cfg(test)]
|
||||
use crate::reasoning_preference::ReasoningEffort;
|
||||
use crate::tui::app::{App, AppAction, AppMode};
|
||||
use crate::tui::app::{App, AppAction};
|
||||
use crate::tui::views::{HelpView, ModalKind, SubAgentsView, subagent_view_agents};
|
||||
use codewhale_config::AppMode;
|
||||
|
||||
use super::CommandResult;
|
||||
|
||||
@@ -754,8 +755,9 @@ mod tests {
|
||||
use crate::config::Config;
|
||||
use crate::models::Message;
|
||||
use crate::models::Role;
|
||||
use crate::tui::app::{App, AppMode, TuiOptions, TurnCacheRecord};
|
||||
use crate::tui::app::{App, TuiOptions, TurnCacheRecord};
|
||||
use crate::tui::history::HistoryCell;
|
||||
use codewhale_config::AppMode;
|
||||
use std::ffi::OsString;
|
||||
use std::path::PathBuf;
|
||||
use std::time::Instant;
|
||||
|
||||
@@ -13,7 +13,8 @@ use crate::commands::traits::{CommandInfo, RegisterCommand};
|
||||
use crate::localization::MessageId;
|
||||
use crate::models::ContentBlock;
|
||||
use crate::tui::app::WORKFLOW_DRAFT_INSTRUCTION_PREFIX;
|
||||
use crate::tui::app::{App, AppAction, AppMode};
|
||||
use crate::tui::app::{App, AppAction};
|
||||
use codewhale_config::AppMode;
|
||||
#[cfg(test)]
|
||||
use codewhale_execpolicy::ApprovalMode;
|
||||
|
||||
|
||||
@@ -17,7 +17,8 @@ use crate::localization::{Locale, MessageId, tr};
|
||||
use crate::models::{ContentBlock, Message, Role, SystemPrompt};
|
||||
use crate::session_manager::{SessionManager, create_saved_session_with_mode};
|
||||
use crate::test_support::{EnvVarGuard, TestEnvLock};
|
||||
use crate::tui::app::{App, AppAction, AppMode, TuiOptions};
|
||||
use crate::tui::app::{App, AppAction, TuiOptions};
|
||||
use codewhale_config::AppMode;
|
||||
|
||||
/// Owns the global environment lock for as long as its CODEWHALE_HOME guard.
|
||||
/// Fields are ordered so the guard restores the environment before the lock
|
||||
|
||||
@@ -14,8 +14,9 @@ use crate::models::Role;
|
||||
use crate::reasoning_preference::ReasoningEffort;
|
||||
use crate::session_manager::create_saved_session_with_id_and_mode;
|
||||
use crate::test_support::EnvVarGuard;
|
||||
use crate::tui::app::{App, AppAction, AppMode, TuiOptions, TurnCacheRecord};
|
||||
use crate::tui::app::{App, AppAction, TuiOptions, TurnCacheRecord};
|
||||
use crate::tui::history::HistoryCell;
|
||||
use codewhale_config::AppMode;
|
||||
|
||||
fn dispatch_lifecycle(app: &mut App, name: &str, arg: Option<&str>) -> CommandResult {
|
||||
let command = match arg {
|
||||
@@ -548,9 +549,9 @@ fn test_load_valid_session_defers_state_restore_to_event_loop() {
|
||||
app2.session_context_references
|
||||
.push(crate::session_manager::SessionContextReference {
|
||||
message_index: 0,
|
||||
reference: crate::tui::file_mention::ContextReference {
|
||||
kind: crate::tui::file_mention::ContextReferenceKind::File,
|
||||
source: crate::tui::file_mention::ContextReferenceSource::AtMention,
|
||||
reference: codewhale_core::ContextReference {
|
||||
kind: codewhale_core::ContextReferenceKind::File,
|
||||
source: codewhale_core::ContextReferenceSource::AtMention,
|
||||
badge: "file".to_string(),
|
||||
label: "stale.rs".to_string(),
|
||||
target: tmpdir.path().join("stale.rs").display().to_string(),
|
||||
|
||||
@@ -5,10 +5,8 @@
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
pub use crate::agent_roster::{
|
||||
AgentRosterRow, RosterState, all_rows_have_usage, build_agent_roster, display_name,
|
||||
format_duration, format_tokens, one_line, roster_totals, wall_millis,
|
||||
use crate::agent_roster::{
|
||||
AgentRosterRow, all_rows_have_usage, format_duration, format_tokens, roster_totals,
|
||||
};
|
||||
|
||||
/// Absent receipts render as `—`. See the truth rule in the module docs.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use super::*;
|
||||
|
||||
use crate::agent_roster::{RosterState, build_agent_roster};
|
||||
use crate::tools::subagent::{
|
||||
AgentRunUsage, AgentWorkerEvent, AgentWorkerRecord, AgentWorkerSpec, AgentWorkerStatus,
|
||||
AgentWorkerToolProfile, FleetRole,
|
||||
|
||||
@@ -11,7 +11,9 @@ use ratatui::layout::Rect;
|
||||
use ratatui::style::Color;
|
||||
use serde_json::Value;
|
||||
|
||||
use codewhale_config::{ProviderChain, route::RouteLimits};
|
||||
use codewhale_config::{AppMode, ProviderChain, route::RouteLimits};
|
||||
use codewhale_core::ContextReference;
|
||||
use codewhale_execpolicy::ApprovalMode;
|
||||
|
||||
use crate::artifacts::ArtifactRecord;
|
||||
use crate::client::{CacheWarmupKey, PromptInspection};
|
||||
@@ -35,9 +37,7 @@ use crate::tools::spec::RuntimeToolServices;
|
||||
use crate::tools::subagent::{AgentWorkerStatus, SubAgentResult};
|
||||
use crate::tools::todo::{SharedTodoList, TodoList, new_shared_todo_list};
|
||||
use crate::tui::active_cell::ActiveCell;
|
||||
use crate::tui::approval::ApprovalMode;
|
||||
use crate::tui::clipboard::{ClipboardContent, ClipboardHandler};
|
||||
use crate::tui::file_mention::ContextReference;
|
||||
use crate::tui::history::{HistoryCell, TranscriptActionOwner, TranscriptRenderOptions};
|
||||
use crate::tui::hotbar::HotbarActionRegistry;
|
||||
use crate::tui::motion::MotionPolicy;
|
||||
@@ -69,7 +69,7 @@ pub(crate) enum RedactionGateNotice {
|
||||
WriteFailure,
|
||||
}
|
||||
pub use types::{
|
||||
AppAction, AppMode, AppModeUi, AutomationAction, ComposerDensity, ComposerSubmitAction,
|
||||
AppAction, AppModeUi, AutomationAction, ComposerDensity, ComposerSubmitAction,
|
||||
ComposerSubmitChord, InitialInput, McpUiAction, QueuedMessage, ScreenMode, SettingSelection,
|
||||
ShellJobAction, SubmitDisposition, TaskPanelEntry, TaskPanelEntryKind, ToolCollapseMode,
|
||||
ToolDetailRecord, TranscriptSpacing, TuiOptions, VimMode,
|
||||
@@ -1912,7 +1912,7 @@ pub struct App {
|
||||
/// Receipts-only roster of every agent that ran this session (#5479).
|
||||
/// Refreshed wholesale on each `AgentList` event; shared by `/agents`,
|
||||
/// the Agents register and the Price view.
|
||||
pub agent_roster: Vec<crate::tui::agent_roster::AgentRosterRow>,
|
||||
pub agent_roster: Vec<crate::agent_roster::AgentRosterRow>,
|
||||
/// Original conversation owner of the retained snapshot. A process boot
|
||||
/// marker or a worker's parent run is not a conversation identity.
|
||||
pub agent_roster_session_id: Option<String>,
|
||||
@@ -2560,7 +2560,7 @@ fn push_enabled_provider_model(
|
||||
|
||||
impl App {
|
||||
/// A retained roster remains readable only in its owning conversation.
|
||||
pub(crate) fn current_agent_roster(&self) -> &[crate::tui::agent_roster::AgentRosterRow] {
|
||||
pub(crate) fn current_agent_roster(&self) -> &[crate::agent_roster::AgentRosterRow] {
|
||||
if self
|
||||
.current_session_id
|
||||
.as_deref()
|
||||
|
||||
@@ -510,7 +510,7 @@ impl ComposerState {
|
||||
}
|
||||
|
||||
pub fn composer_attachment_count(&self) -> usize {
|
||||
crate::tui::file_mention::media_attachment_references(&self.input).len()
|
||||
codewhale_core::media_attachment_references(&self.input).len()
|
||||
}
|
||||
|
||||
pub fn selected_composer_attachment_index(&self) -> Option<usize> {
|
||||
@@ -809,7 +809,7 @@ impl App {
|
||||
}
|
||||
|
||||
pub fn remove_selected_composer_attachment(&mut self) -> bool {
|
||||
let references = crate::tui::file_mention::media_attachment_references(&self.input);
|
||||
let references = codewhale_core::media_attachment_references(&self.input);
|
||||
let Some(index) = self
|
||||
.selected_composer_attachment_index()
|
||||
.filter(|index| *index < references.len())
|
||||
|
||||
@@ -3469,44 +3469,6 @@ fn entering_operate_preserves_user_rail_panel() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn app_mode_helpers_centralize_parse_labels_and_cycle_order() {
|
||||
assert_eq!(AppMode::parse("agent"), Some(AppMode::Agent));
|
||||
assert_eq!(AppMode::parse("act"), Some(AppMode::Agent));
|
||||
assert_eq!(AppMode::parse("work"), Some(AppMode::Agent));
|
||||
assert_eq!(AppMode::parse("2"), Some(AppMode::Plan));
|
||||
assert_eq!(AppMode::parse("auto"), Some(AppMode::Agent));
|
||||
assert_eq!(AppMode::parse("3"), Some(AppMode::Operate));
|
||||
assert_eq!(AppMode::parse("operate"), Some(AppMode::Operate));
|
||||
// Legacy YOLO spellings resolve to Act; the bypass posture they imply
|
||||
// travels on the permission surface, not on a mode.
|
||||
assert_eq!(AppMode::parse("YOLO"), Some(AppMode::Agent));
|
||||
assert_eq!(AppMode::parse("4"), Some(AppMode::Agent));
|
||||
assert_eq!(AppMode::parse("bypass"), Some(AppMode::Agent));
|
||||
assert_eq!(AppMode::parse("bypass-permissions"), Some(AppMode::Agent));
|
||||
assert_eq!(AppMode::parse("multitask"), None);
|
||||
assert_eq!(AppMode::parse("5"), None);
|
||||
assert_eq!(AppMode::parse("fast"), None);
|
||||
assert_eq!(AppMode::from_setting("multitask"), AppMode::Operate);
|
||||
assert_eq!(AppMode::from_setting("5"), AppMode::Operate);
|
||||
|
||||
assert_eq!(AppMode::Agent.as_setting(), "agent");
|
||||
assert_eq!(AppMode::Plan.display_name(), "Plan");
|
||||
assert_eq!(AppMode::Agent.number(), '1');
|
||||
assert_eq!(AppMode::Operate.number(), '3');
|
||||
assert_eq!(
|
||||
AppMode::CYCLE,
|
||||
[AppMode::Plan, AppMode::Agent, AppMode::Operate]
|
||||
);
|
||||
|
||||
assert_eq!(AppMode::Plan.next(), AppMode::Agent);
|
||||
assert_eq!(AppMode::Agent.next(), AppMode::Operate);
|
||||
assert_eq!(AppMode::Operate.next(), AppMode::Plan);
|
||||
assert_eq!(AppMode::Plan.previous(), AppMode::Operate);
|
||||
assert_eq!(AppMode::Agent.previous(), AppMode::Plan);
|
||||
assert_eq!(AppMode::Operate.previous(), AppMode::Agent);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cycle_scenario() {
|
||||
// Scenario consolidation of: test_cycle_mode_transitions, test_cycle_mode_reverse_transitions
|
||||
|
||||
@@ -3,11 +3,14 @@
|
||||
//! and the action enums drained by the event loop.
|
||||
//!
|
||||
//! Everything here is pure data (plus parsing/labeling helpers that need no
|
||||
//! `App` state). All items are re-exported from `app.rs` so existing
|
||||
//! `crate::tui::app::X` paths are unchanged.
|
||||
//! `App` state). The TUI-owned items are re-exported from `app.rs` so existing
|
||||
//! `crate::tui::app::X` paths are unchanged; types owned by another crate
|
||||
//! (such as [`AppMode`]) are named at their own crate path instead.
|
||||
|
||||
use super::*;
|
||||
|
||||
use codewhale_config::AppMode;
|
||||
|
||||
/// What an interactive setting selection actually did.
|
||||
///
|
||||
/// The three cases are genuinely different to the user, and the boolean this
|
||||
@@ -44,10 +47,6 @@ impl SettingSelection {
|
||||
}
|
||||
}
|
||||
|
||||
/// The user-facing operating mode. Defined in codewhale-config; re-exported
|
||||
/// here so `crate::tui::app::types::AppMode` keeps working.
|
||||
pub use codewhale_config::AppMode;
|
||||
|
||||
/// Localized, TUI-only presentation of [`AppMode`]. Kept out of
|
||||
/// codewhale-config so the mode type does not depend on the locale packs.
|
||||
pub trait AppModeUi {
|
||||
|
||||
@@ -75,11 +75,6 @@ pub use policy::{
|
||||
get_tool_category_for_call,
|
||||
};
|
||||
|
||||
/// Determines when tool executions require user approval. Defined in
|
||||
/// codewhale-execpolicy (next to `AskForApproval`); re-exported here so
|
||||
/// `crate::tui::approval::ApprovalMode` keeps working.
|
||||
pub use codewhale_execpolicy::ApprovalMode;
|
||||
|
||||
/// User's decision for a pending approval
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum ReviewDecision {
|
||||
|
||||
@@ -2476,38 +2476,6 @@ fn workflow_plan_card_edit_plan_and_cancel_keys() {
|
||||
}
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// ApprovalMode Tests
|
||||
// ========================================================================
|
||||
|
||||
#[test]
|
||||
fn test_approval_mode_labels() {
|
||||
assert_eq!(ApprovalMode::Auto.label(), "AUTO");
|
||||
assert_eq!(ApprovalMode::Suggest.label(), "SUGGEST");
|
||||
assert_eq!(ApprovalMode::Never.label(), "NEVER");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_approval_mode_from_config_value_accepts_aliases() {
|
||||
assert_eq!(
|
||||
ApprovalMode::from_config_value("auto"),
|
||||
Some(ApprovalMode::Auto)
|
||||
);
|
||||
assert_eq!(
|
||||
ApprovalMode::from_config_value("on-request"),
|
||||
Some(ApprovalMode::Suggest)
|
||||
);
|
||||
assert_eq!(
|
||||
ApprovalMode::from_config_value("full_access"),
|
||||
Some(ApprovalMode::Bypass)
|
||||
);
|
||||
assert_eq!(
|
||||
ApprovalMode::from_config_value("deny"),
|
||||
Some(ApprovalMode::Never)
|
||||
);
|
||||
assert_eq!(ApprovalMode::from_config_value("unknown"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn canonical_bash_keeps_original_name_but_uses_shell_approval_semantics() {
|
||||
let request = ApprovalRequest::new_with_intent(
|
||||
|
||||
@@ -6,9 +6,8 @@
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
use crate::tui::approval::{
|
||||
ApprovalMode, RiskLevel, ToolCategory, classify_risk, get_tool_category_for_call,
|
||||
};
|
||||
use crate::tui::approval::{RiskLevel, ToolCategory, classify_risk, get_tool_category_for_call};
|
||||
use codewhale_execpolicy::ApprovalMode;
|
||||
use serde_json::{Value, json};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
|
||||
@@ -9,7 +9,8 @@ use std::hash::{DefaultHasher, Hash, Hasher};
|
||||
|
||||
use crate::localization::{Locale, MessageId, tr};
|
||||
use crate::settings::Settings;
|
||||
use crate::tui::app::{App, AppMode, StatusToast, StatusToastKind, StatusToastLevel};
|
||||
use crate::tui::app::{App, StatusToast, StatusToastKind, StatusToastLevel};
|
||||
use codewhale_config::AppMode;
|
||||
|
||||
const MAX_TIPS_PER_SESSION: u8 = 1;
|
||||
const MAX_LIFETIME_IMPRESSIONS: u8 = 2;
|
||||
|
||||
@@ -23,12 +23,12 @@ use crate::models::{SystemPrompt, Tool};
|
||||
use crate::palette;
|
||||
use crate::session_manager::SessionContextReference;
|
||||
use crate::tui::app::{App, ToolDetailRecord};
|
||||
use crate::tui::file_mention::ContextReferenceSource;
|
||||
use crate::tui::menu_style;
|
||||
use crate::tui::views::{
|
||||
ActionHint, ModalKind, ModalView, ViewAction, ViewEvent, render_modal_footer,
|
||||
render_underwater_surface,
|
||||
};
|
||||
use codewhale_core::ContextReferenceSource;
|
||||
|
||||
/// Marker used by per-turn working-set metadata. Replicated here so the
|
||||
/// context inspector can distinguish stable prompt blocks from volatile
|
||||
@@ -1018,10 +1018,8 @@ mod tests {
|
||||
use crate::models::{ContentBlock, Message, Tool};
|
||||
use crate::session_manager::SessionContextReference;
|
||||
use crate::tui::app::TuiOptions;
|
||||
use crate::tui::file_mention::{
|
||||
ContextReference, ContextReferenceKind, ContextReferenceSource,
|
||||
};
|
||||
use crate::tui::history::HistoryCell;
|
||||
use codewhale_core::{ContextReference, ContextReferenceKind, ContextReferenceSource};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::localization::Locale;
|
||||
|
||||
@@ -29,6 +29,10 @@ use crate::tui::app::{App, MentionCompletionCache};
|
||||
use crate::tui::git_mention::{self, GitMentionCache, GitMentionKind};
|
||||
use crate::tui::mention_completion::{MentionDiscoveryBehavior, MentionDiscoveryKey};
|
||||
use crate::working_set::Workspace;
|
||||
use codewhale_core::{
|
||||
ContextReference, ContextReferenceKind, ContextReferenceSource, MediaAttachmentReference,
|
||||
media_attachment_references,
|
||||
};
|
||||
|
||||
/// Maximum number of `@`-mentions whose contents are inlined into one user
|
||||
/// message. Beyond this we stop appending blocks but the raw `@token` text
|
||||
@@ -54,12 +58,6 @@ pub struct FileMentionPreview {
|
||||
pub removable: bool,
|
||||
}
|
||||
|
||||
/// Durable, compact metadata for a user-visible context reference.
|
||||
pub use codewhale_core::{
|
||||
ContextReference, ContextReferenceKind, ContextReferenceSource, MediaAttachmentReference,
|
||||
media_attachment_references,
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Tab-completion
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -20,9 +20,9 @@ use std::path::{Path, PathBuf};
|
||||
|
||||
use crate::tui::app::App;
|
||||
use crate::tui::app::ToolDetailRecord;
|
||||
use crate::tui::file_mention::{ContextReferenceKind, ContextReferenceSource};
|
||||
use crate::tui::file_picker::FilePickerRelevance;
|
||||
use crate::tui::file_picker::FilePickerView;
|
||||
use codewhale_core::{ContextReferenceKind, ContextReferenceSource};
|
||||
|
||||
/// Push the `/files` picker onto the view stack, pre-populated with
|
||||
/// per-session relevance ranks (modified, @-mentioned, tool-touched).
|
||||
|
||||
@@ -3,12 +3,13 @@ use std::collections::{BTreeMap, BTreeSet, HashMap};
|
||||
use std::sync::Arc;
|
||||
|
||||
use anyhow::Result;
|
||||
use codewhale_config::AppMode;
|
||||
|
||||
use crate::commands::{self, CommandInfo, CommandResult};
|
||||
use crate::config::{ApiProvider, Config};
|
||||
use crate::localization::{Locale, MessageId, tr};
|
||||
use crate::provider_lake::all_catalog_models_for_provider;
|
||||
use crate::tui::app::{App, AppAction, AppMode};
|
||||
use crate::tui::app::{App, AppAction};
|
||||
use crate::tui::command_palette::{
|
||||
CommandPaletteView, build_entries as build_command_palette_entries,
|
||||
};
|
||||
|
||||
@@ -115,7 +115,7 @@ use std::collections::VecDeque;
|
||||
use std::sync::{Arc, Mutex, MutexGuard};
|
||||
|
||||
use crate::settings::Settings;
|
||||
use crate::tui::app::AppMode;
|
||||
use codewhale_config::AppMode;
|
||||
|
||||
/// One user selection's worth of startup-default writes.
|
||||
///
|
||||
|
||||
@@ -9,8 +9,7 @@ use crate::tools::subagent::{
|
||||
};
|
||||
use crate::tui::app::{
|
||||
AgentCurrentActivity, AgentCurrentActivityStatus, AgentProgressMeta, AgentRecentAction, App,
|
||||
AppMode, MAX_AGENT_RECENT_ACTIONS, TaskPanelEntry, TaskPanelEntryKind,
|
||||
bound_agent_activity_text,
|
||||
MAX_AGENT_RECENT_ACTIONS, TaskPanelEntry, TaskPanelEntryKind, bound_agent_activity_text,
|
||||
};
|
||||
use crate::tui::history::{HistoryCell, SubAgentCell, summarize_tool_output};
|
||||
use crate::tui::pager::PagerView;
|
||||
@@ -19,6 +18,7 @@ use crate::tui::widgets::agent_card::{
|
||||
AgentLifecycle, DelegateCard, FanoutCard, apply_to_delegate, apply_to_fanout,
|
||||
};
|
||||
use crate::tui::workspace_context;
|
||||
use codewhale_config::AppMode;
|
||||
|
||||
/// Keep settled cards visible briefly, then archive them from the compact
|
||||
/// live projection. Their transcript card and persisted agent record remain
|
||||
|
||||
@@ -15,6 +15,9 @@ use std::time::{Duration, Instant};
|
||||
use crate::error_taxonomy::{ErrorCategory, ErrorEnvelope, ErrorSeverity};
|
||||
use crate::resource_telemetry::estimate_output_tokens_from_text;
|
||||
use anyhow::{Context, Result};
|
||||
use codewhale_config::AppMode;
|
||||
use codewhale_core::ContextReference;
|
||||
use codewhale_execpolicy::ApprovalMode;
|
||||
use codewhale_release::InstallMethod;
|
||||
// On Windows the push/pop helpers write the escapes directly; crossterm's
|
||||
// PushKeyboardEnhancementFlags / PopKeyboardEnhancementFlags commands are
|
||||
@@ -88,7 +91,6 @@ use crate::tui::command_palette::{
|
||||
use crate::tui::composer_ui::*;
|
||||
use crate::tui::context_inspector::ContextInspectorView;
|
||||
use crate::tui::event_broker::EventBroker;
|
||||
use crate::tui::file_mention::ContextReference;
|
||||
use crate::tui::file_picker_relevance;
|
||||
use crate::tui::footer_ui::{friendly_subagent_progress, is_noisy_subagent_progress};
|
||||
use crate::tui::format_helpers;
|
||||
@@ -136,7 +138,7 @@ use crate::reasoning_preference::{EffectiveReasoningEffort, ReasoningEffort};
|
||||
use super::key_actions;
|
||||
|
||||
use super::app::{
|
||||
ActiveCompaction, ActiveTurnMetadata, AgentCurrentActivity, App, AppAction, AppMode,
|
||||
ActiveCompaction, ActiveTurnMetadata, AgentCurrentActivity, App, AppAction,
|
||||
ComposerSubmitAction, ComposerSubmitChord, GoalControlIntent, OnboardingState,
|
||||
PendingGoalControl, PendingProviderSwitch, QueuedMessage, RedactionGateNotice, ScreenMode,
|
||||
StatusToast, StatusToastLevel, SubmitDisposition, TaskPanelEntry, TaskPanelEntryKind,
|
||||
@@ -144,7 +146,7 @@ use super::app::{
|
||||
looks_like_slash_command_input, shell_command_from_bang_input,
|
||||
};
|
||||
use super::approval::{
|
||||
ApprovalMode, ApprovalRequest, ApprovalView, ElevationRequest, ElevationView, ReviewDecision,
|
||||
ApprovalRequest, ApprovalView, ElevationRequest, ElevationView, ReviewDecision,
|
||||
};
|
||||
use super::history::{
|
||||
ExecCell, HistoryCell, ReasoningAction, ToolCell, ToolStatus, history_cells_from_message,
|
||||
|
||||
@@ -622,7 +622,7 @@ pub(crate) fn apply_goal_snapshot_to_app(app: &mut App, snapshot: &GoalSnapshot)
|
||||
// Operate set it from the prompt (or the model did while operating);
|
||||
// the objective is the prompt the user just typed, so the receipt
|
||||
// says what Operate will do with it instead of echoing it.
|
||||
let content = if app.mode == crate::tui::app::AppMode::Operate {
|
||||
let content = if app.mode == AppMode::Operate {
|
||||
app.tr(crate::localization::MessageId::GoalReceiptSetOperate)
|
||||
.into_owned()
|
||||
} else {
|
||||
|
||||
@@ -4,8 +4,8 @@ use crate::audit::log_sensitive_event;
|
||||
use crate::core::engine::EngineHandle;
|
||||
use crate::localization::MessageId;
|
||||
use crate::tui::app::{App, StatusToastLevel};
|
||||
use crate::tui::approval::ApprovalMode;
|
||||
use crate::tui::history::HistoryCell;
|
||||
use codewhale_execpolicy::ApprovalMode;
|
||||
|
||||
pub(super) fn is_session_approved_for_tool(
|
||||
app: &App,
|
||||
|
||||
@@ -8548,7 +8548,7 @@ async fn model_change_update_syncs_engine_model_before_compaction() {
|
||||
#[tokio::test]
|
||||
async fn mode_change_update_notifies_engine() {
|
||||
let mut app = create_test_app();
|
||||
let _ = app.set_mode(crate::tui::app::AppMode::Plan);
|
||||
let _ = app.set_mode(AppMode::Plan);
|
||||
let mut engine = crate::core::engine::mock_engine_handle();
|
||||
|
||||
assert!(
|
||||
@@ -8566,11 +8566,11 @@ async fn mode_change_update_notifies_engine() {
|
||||
} => {
|
||||
// The deprecated YOLO alias lands in Agent mode with full-access
|
||||
// compat policies (M6 shim); the engine sees the remapped mode.
|
||||
assert_eq!(mode, crate::tui::app::AppMode::Agent);
|
||||
assert_eq!(mode, AppMode::Agent);
|
||||
assert!(allow_shell);
|
||||
assert!(trust_mode);
|
||||
assert!(auto_approve);
|
||||
assert_eq!(approval_mode, crate::tui::approval::ApprovalMode::Bypass);
|
||||
assert_eq!(approval_mode, ApprovalMode::Bypass);
|
||||
assert_eq!(configured_sandbox_mode, app.configured_sandbox_mode);
|
||||
}
|
||||
other => panic!("expected ChangeMode, got {other:?}"),
|
||||
@@ -8582,8 +8582,8 @@ async fn mode_change_update_sends_restored_agent_policy() {
|
||||
let mut app = create_test_app();
|
||||
app.allow_shell = true;
|
||||
app.trust_mode = false;
|
||||
app.approval_mode = crate::tui::approval::ApprovalMode::Never;
|
||||
let _ = app.set_mode(crate::tui::app::AppMode::Plan);
|
||||
app.approval_mode = ApprovalMode::Never;
|
||||
let _ = app.set_mode(AppMode::Plan);
|
||||
let mut engine = crate::core::engine::mock_engine_handle();
|
||||
|
||||
assert!(
|
||||
@@ -8591,7 +8591,7 @@ async fn mode_change_update_sends_restored_agent_policy() {
|
||||
&mut app,
|
||||
&engine.handle,
|
||||
&crate::config::Config::default(),
|
||||
crate::tui::app::AppMode::Agent
|
||||
AppMode::Agent
|
||||
)
|
||||
.await
|
||||
);
|
||||
@@ -8605,11 +8605,11 @@ async fn mode_change_update_sends_restored_agent_policy() {
|
||||
approval_mode,
|
||||
configured_sandbox_mode,
|
||||
} => {
|
||||
assert_eq!(mode, crate::tui::app::AppMode::Agent);
|
||||
assert_eq!(mode, AppMode::Agent);
|
||||
assert!(allow_shell);
|
||||
assert!(!trust_mode);
|
||||
assert!(!auto_approve);
|
||||
assert_eq!(approval_mode, crate::tui::approval::ApprovalMode::Never);
|
||||
assert_eq!(approval_mode, ApprovalMode::Never);
|
||||
assert_eq!(configured_sandbox_mode, app.configured_sandbox_mode);
|
||||
}
|
||||
other => panic!("expected ChangeMode, got {other:?}"),
|
||||
@@ -8667,13 +8667,7 @@ async fn operate_entry_preserves_live_custom_identity_and_auto_over_startup_rout
|
||||
app.set_model_selection(selected.to_string());
|
||||
app.last_effective_model = Some("previous-turn-model".to_string());
|
||||
let engine = mock_engine_handle();
|
||||
apply_mode_update(
|
||||
&mut app,
|
||||
&engine.handle,
|
||||
&config,
|
||||
crate::tui::app::AppMode::Operate,
|
||||
)
|
||||
.await;
|
||||
apply_mode_update(&mut app, &engine.handle, &config, AppMode::Operate).await;
|
||||
let record = automations
|
||||
.lock()
|
||||
.await
|
||||
@@ -8743,13 +8737,7 @@ async fn operate_rejected_attach_does_not_reactivate_saved_keepalive() {
|
||||
);
|
||||
app.set_model_selection("startup-model".into());
|
||||
let engine = mock_engine_handle();
|
||||
apply_mode_update(
|
||||
&mut app,
|
||||
&engine.handle,
|
||||
&config,
|
||||
crate::tui::app::AppMode::Operate,
|
||||
)
|
||||
.await;
|
||||
apply_mode_update(&mut app, &engine.handle, &config, AppMode::Operate).await;
|
||||
let record = automations
|
||||
.lock()
|
||||
.await
|
||||
@@ -8800,7 +8788,7 @@ async fn operate_mode_entry_attaches_to_recorded_operation() {
|
||||
&mut app,
|
||||
&engine.handle,
|
||||
&Config::default(),
|
||||
crate::tui::app::AppMode::Operate
|
||||
AppMode::Operate
|
||||
)
|
||||
.await
|
||||
);
|
||||
@@ -20124,7 +20112,7 @@ fn auto_route_receipt_survives_session_snapshot_and_restore() {
|
||||
#[test]
|
||||
fn apply_loaded_session_restores_saved_mode() {
|
||||
let mut app = create_test_app();
|
||||
app.set_mode(crate::tui::app::AppMode::Agent);
|
||||
app.set_mode(AppMode::Agent);
|
||||
let mut session = saved_session_with_messages(vec![
|
||||
text_message("user", "draft a plan"),
|
||||
text_message("assistant", "plan response"),
|
||||
@@ -20132,7 +20120,7 @@ fn apply_loaded_session_restores_saved_mode() {
|
||||
session.metadata.mode = Some("plan".to_string());
|
||||
|
||||
apply_loaded_session(&mut app, &mut Config::default(), &session).expect("restore session");
|
||||
assert_eq!(app.mode, crate::tui::app::AppMode::Plan);
|
||||
assert_eq!(app.mode, AppMode::Plan);
|
||||
assert!(!app.allow_shell);
|
||||
assert!(!app.trust_mode);
|
||||
}
|
||||
|
||||
@@ -24,12 +24,13 @@ use crate::localization::{Locale, MessageId, tr};
|
||||
use crate::palette::{ChromeInk, chrome_style};
|
||||
use crate::tui::ui_text::{semantic_truncate, text_display_width};
|
||||
use crate::tui::{
|
||||
app::{App, AppMode, HeaderActionTarget, HeaderHitbox, OnboardingState},
|
||||
approval::ApprovalMode,
|
||||
app::{App, HeaderActionTarget, HeaderHitbox, OnboardingState},
|
||||
footer_ui::format_token_count_compact,
|
||||
ocean::COMPLETION_BREATH_MS,
|
||||
views::ModalKind,
|
||||
};
|
||||
use codewhale_config::AppMode;
|
||||
use codewhale_execpolicy::ApprovalMode;
|
||||
|
||||
/// Responsive density tier. It changes how much truth is shown, never the
|
||||
/// underlying state grammar.
|
||||
@@ -2380,9 +2381,10 @@ mod header_tests {
|
||||
render_header_with_git_status,
|
||||
};
|
||||
use crate::palette::ChromeInk;
|
||||
use crate::tui::app::{App, AppMode};
|
||||
use crate::tui::approval::ApprovalMode;
|
||||
use crate::tui::app::App;
|
||||
use crate::tui::widgets::workflow_panel::{WorkflowPanel, WorkflowPanelLifecycle};
|
||||
use codewhale_config::AppMode;
|
||||
use codewhale_execpolicy::ApprovalMode;
|
||||
use ratatui::{buffer::Buffer, layout::Rect};
|
||||
|
||||
fn app() -> App {
|
||||
|
||||
@@ -885,7 +885,7 @@ pub enum ViewEvent {
|
||||
},
|
||||
/// Emitted by the `/mode` picker when the user chooses a mode.
|
||||
ModeSelected {
|
||||
mode: crate::tui::app::AppMode,
|
||||
mode: codewhale_config::AppMode,
|
||||
},
|
||||
/// Emitted by the `/statusline` picker every time the user toggles an
|
||||
/// item (live preview) and once more on Enter (final). The handler
|
||||
|
||||
@@ -14,13 +14,13 @@ use unicode_width::UnicodeWidthStr;
|
||||
|
||||
use crate::localization::Locale;
|
||||
use crate::palette;
|
||||
use crate::tui::app::AppMode;
|
||||
use crate::tui::app::AppModeUi;
|
||||
use crate::tui::menu_style;
|
||||
use crate::tui::views::{
|
||||
ActionHint, ModalKind, ModalView, ViewAction, ViewEvent, centered_modal_area,
|
||||
render_modal_footer, render_modal_surface,
|
||||
};
|
||||
use codewhale_config::AppMode;
|
||||
|
||||
// Operate is visible because the engine now enforces a coordinator/worker
|
||||
// boundary while allowing ordinary conversation and asynchronous dispatch.
|
||||
|
||||
@@ -20,16 +20,17 @@ use crate::localization::{Locale, MessageId, tr};
|
||||
use crate::palette;
|
||||
#[cfg(test)]
|
||||
use crate::provider_lake::all_catalog_models_for_provider;
|
||||
use crate::tui::app::{App, AppMode, ComposerDensity, ViewportState};
|
||||
use crate::tui::app::{App, ComposerDensity, ViewportState};
|
||||
use crate::tui::approval::{
|
||||
ApprovalMode, ApprovalRequest, ApprovalView, ElevationOption, ElevationRequest, RiskLevel,
|
||||
ToolCategory,
|
||||
ApprovalRequest, ApprovalView, ElevationOption, ElevationRequest, RiskLevel, ToolCategory,
|
||||
};
|
||||
use crate::tui::history::{GenericToolCell, HistoryCell, ToolCell, ToolRun, ToolStatus};
|
||||
use crate::tui::menu_style;
|
||||
use crate::tui::scrolling::TranscriptLineMeta;
|
||||
use crate::tui::ui_text::{grapheme_display_width, text_display_width};
|
||||
use crate::tui::underwater::ShellPhase;
|
||||
use codewhale_config::AppMode;
|
||||
use codewhale_execpolicy::ApprovalMode;
|
||||
use ratatui::{
|
||||
buffer::Buffer,
|
||||
layout::Rect,
|
||||
@@ -4601,13 +4602,14 @@ mod tests {
|
||||
use crate::palette;
|
||||
use crate::tui::active_cell::ActiveCell;
|
||||
use crate::tui::app::{
|
||||
App, AppMode, ComposerDensity, QueuedMessage, TaskPanelEntry, TaskPanelEntryKind,
|
||||
ToolCollapseMode, TranscriptSpacing, TuiOptions,
|
||||
App, ComposerDensity, QueuedMessage, TaskPanelEntry, TaskPanelEntryKind, ToolCollapseMode,
|
||||
TranscriptSpacing, TuiOptions,
|
||||
};
|
||||
use crate::tui::history::{
|
||||
ExecCell, ExecSource, GenericToolCell, HistoryCell, ToolCell, ToolRun, ToolStatus,
|
||||
};
|
||||
use crate::tui::scrolling::{TranscriptLineMeta, TranscriptScroll};
|
||||
use codewhale_config::AppMode;
|
||||
use crossterm::event::{KeyModifiers, MouseButton, MouseEvent, MouseEventKind};
|
||||
use ratatui::{
|
||||
buffer::Buffer,
|
||||
|
||||
@@ -717,7 +717,7 @@ fn agents_view_rows(app: &mut App) -> Vec<WorkRow> {
|
||||
retained.push(agents.remove(index));
|
||||
continue;
|
||||
}
|
||||
let parked = receipt.state == crate::tui::agent_roster::RosterState::Parked;
|
||||
let parked = receipt.state == crate::agent_roster::RosterState::Parked;
|
||||
let status = if parked {
|
||||
current_activity_status_label(AgentCurrentActivityStatus::Parked, app.ui_locale)
|
||||
} else {
|
||||
@@ -2924,9 +2924,9 @@ mod tests {
|
||||
fn retained_agent_receipt(
|
||||
id: &str,
|
||||
status: AgentWorkerStatus,
|
||||
state: crate::tui::agent_roster::RosterState,
|
||||
) -> crate::tui::agent_roster::AgentRosterRow {
|
||||
crate::tui::agent_roster::AgentRosterRow {
|
||||
state: crate::agent_roster::RosterState,
|
||||
) -> crate::agent_roster::AgentRosterRow {
|
||||
crate::agent_roster::AgentRosterRow {
|
||||
worker_id: id.to_string(),
|
||||
display_name: format!("retained {id}"),
|
||||
model: "test-model".to_string(),
|
||||
@@ -2945,7 +2945,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn agents_register_retains_expired_receipts_alongside_fresh_live_rows() {
|
||||
use crate::tui::agent_roster::RosterState;
|
||||
use crate::agent_roster::RosterState;
|
||||
use crate::tui::subagent_routing::reconcile_subagent_activity_state_at;
|
||||
use std::time::Duration;
|
||||
|
||||
@@ -3002,7 +3002,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn retained_agents_register_is_bound_to_the_exact_parent_session() {
|
||||
use crate::tui::agent_roster::RosterState;
|
||||
use crate::agent_roster::RosterState;
|
||||
|
||||
let mut app = test_app();
|
||||
app.agent_roster_session_id = Some("original-session".to_string());
|
||||
@@ -3039,7 +3039,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn retained_agents_register_distinguishes_parked_from_waiting_for_input() {
|
||||
use crate::tui::agent_roster::RosterState;
|
||||
use crate::agent_roster::RosterState;
|
||||
|
||||
let mut app = test_app();
|
||||
app.current_session_id = Some("roster-owner".to_string());
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
//! like a to-do or a sub-agent — a view is a subset of one row grammar, not
|
||||
//! a second widget system.
|
||||
|
||||
use crate::tui::agent_roster::format_tokens;
|
||||
use crate::agent_roster::format_tokens;
|
||||
use crate::tui::app::{App, SidebarRowAction};
|
||||
|
||||
use super::model::{RailPanel, WorkRow, WorkRowId, WorkTone};
|
||||
|
||||
@@ -23,7 +23,7 @@ use crate::reasoning_preference::ReasoningEffort;
|
||||
use crate::route_runtime::{
|
||||
ResolvedRuntimeRoute, resolve_runtime_route, resolve_runtime_route_for_identity,
|
||||
};
|
||||
use crate::tui::app::AppMode;
|
||||
use codewhale_config::AppMode;
|
||||
|
||||
/// Everything the shared turn-route planner needs.
|
||||
///
|
||||
|
||||
@@ -29,8 +29,10 @@ The current dependencies explain the blockage:
|
||||
- CLI imports TUI for runtime dispatch and route preferences.
|
||||
- `core/engine.rs` imports approval policy, context thresholds, attachment
|
||||
parsing, and roster construction from `tui/`.
|
||||
- `core/events.rs` carries `tui::agent_roster::AgentRosterRow`.
|
||||
- `session_manager.rs` persists `tui::file_mention::ContextReference`.
|
||||
- `core/events.rs` carries the roster row and `session_manager.rs` persists
|
||||
the durable context reference; both now name their owning crate
|
||||
(`crate::agent_roster::AgentRosterRow`, `codewhale_core::ContextReference`)
|
||||
rather than a `tui::` re-export.
|
||||
- `tools/subagent` imports engine policy/catalog functions, and implements
|
||||
its own repeated model-request/tool-result cycle in `run_subagent`.
|
||||
- `crates/core` owns request construction and some runtime/session services;
|
||||
|
||||
Reference in new issue
Block a user