use std::path::PathBuf;
use codewhale_core::request::{Message, SystemPrompt};
use crate::*;
struct Session;
impl CommandSessionContext for Session {
fn session_id(&self) -> Option<String> {
Some("session".into())
}
fn api_messages(&self) -> Vec<Message> {
vec![]
}
fn add_message(&mut self, _message: Message) {}
fn queued_message_count(&self) -> usize {
0
}
fn remove_queued_message(&mut self, _index: usize) -> Result<(), String> {
Ok(())
}
fn total_tokens(&self) -> u64 {
42
}
}
struct Model;
impl CommandModelContext for Model {
fn current_model(&self) -> String {
"auto".into()
}
fn auto_model(&self) -> bool {
true
}
fn set_model_selection(&mut self, _model: String, _provider: Option<CommandProviderId>) {}
fn reasoning_effort(&self) -> CommandReasoningEffort {
CommandReasoningEffort::Auto
}
fn provider_identity(&self) -> Option<CommandProviderId> {
None
}
fn fallback_chain(&self) -> Vec<CommandProviderId> {
vec![]
}
}
struct Cost;
impl CommandCostContext for Cost {
fn display_currency(&self) -> CommandCurrency {
CommandCurrency::Usd
}
fn session_cost_for_currency(&self, _currency: CommandCurrency) -> f64 {
1.0
}
fn subagent_cost_for_currency(&self, _currency: CommandCurrency) -> f64 {
0.5
}
fn accrue_cost_estimate(&mut self, _amount: f64, _currency: CommandCurrency) {}
fn record_turn_cost(&mut self, _amount: f64, _currency: CommandCurrency, _receipt: bool) {}
}
struct Policy;
impl CommandModePolicyContext for Policy {
fn mode(&self) -> CommandMode {
CommandMode::Plan
}
fn set_mode(&mut self, _mode: CommandMode) {}
fn approval_mode(&self) -> CommandApprovalMode {
CommandApprovalMode::Suggest
}
fn allow_shell(&self) -> bool {
false
}
fn set_shell_access(&mut self, _allow: bool) {}
fn policy_locked(&self) -> bool {
false
}
}
struct Prompt;
impl CommandSystemPromptContext for Prompt {
fn system_prompt(&self) -> Option<SystemPrompt> {
None
}
}
struct Skills;
impl CommandSkillsContext for Skills {
fn active_skill(&self) -> Option<String> {
None
}
fn active_skill_provenance(&self) -> Option<String> {
None
}
fn refresh_skill_cache(&mut self) {}
}
struct Workspace;
impl CommandWorkspaceContext for Workspace {
fn workspace(&self) -> PathBuf {
PathBuf::from(".")
}
fn work_state_snapshot(&self) -> Result<Option<String>, String> {
Ok(None)
}
}
#[test]
fn all_seven_shapes_are_object_safe() {
fn session(_: &dyn CommandSessionContext) {}
fn model(_: &dyn CommandModelContext) {}
fn cost(_: &dyn CommandCostContext) {}
fn policy(_: &dyn CommandModePolicyContext) {}
fn prompt(_: &dyn CommandSystemPromptContext) {}
fn skills(_: &dyn CommandSkillsContext) {}
fn workspace(_: &dyn CommandWorkspaceContext) {}
session(&Session);
model(&Model);
cost(&Cost);
policy(&Policy);
prompt(&Prompt);
skills(&Skills);
workspace(&Workspace);
}
#[test]
fn envelope_carries_independent_facets() {
let mut session = Session;
let mut model = Model;
let parts = CommandContexts::empty()
.with_session(&mut session)
.with_model(&mut model)
.into_parts();
assert_eq!(parts.session.expect("session").total_tokens(), 42);
assert!(parts.model.expect("model").auto_model());
assert!(parts.cost.is_none());
}
fn pure(value: Option<&str>) -> String {
value.unwrap_or_default().to_owned()
}
fn contextual(_contexts: CommandContexts<'_>, value: Option<&str>) -> String {
value.unwrap_or_default().to_owned()
}
#[test]
fn handlers_are_plain_function_pointers() {
let pure_handler = CommandHandler::Pure(pure);
let contextual_handler = CommandHandler::Contextual(contextual);
match pure_handler {
CommandHandler::Pure(handler) => assert_eq!(handler(Some("x")), "x"),
_ => unreachable!(),
}
match contextual_handler {
CommandHandler::Contextual(handler) => {
assert_eq!(handler(CommandContexts::empty(), Some("y")), "y")
}
_ => unreachable!(),
}
}
struct Sample;
impl RegisterCommand<String> for Sample {
fn info() -> &'static CommandInfo {
static INFO: CommandInfo = CommandInfo {
name: "sample",
aliases: &["s"],
usage: "/sample",
description_key: "command.sample",
};
&INFO
}
fn handler() -> CommandHandler<String> {
CommandHandler::Pure(pure)
}
}
#[test]
fn registration_shape_has_no_app_dependency() {
assert_eq!(Sample::info().name, "sample");
assert!(matches!(Sample::handler(), CommandHandler::Pure(_)));
}