mirror of
https://github.com/instructkr/claw-code.git
synced 2026-04-10 10:04:50 +08:00
feat(cli): wire --reasoning-effort flag end-to-end — closes ROADMAP #34
Parse --reasoning-effort <low|medium|high> in parse_args, thread through CliAction::Prompt and CliAction::Repl, LiveCli::set_reasoning_effort(), AnthropicRuntimeClient.reasoning_effort field, and MessageRequest.reasoning_effort. Changes: - parse_args: new --reasoning-effort / --reasoning-effort=VAL flag arms - AnthropicRuntimeClient: new reasoning_effort field + set_reasoning_effort() method - LiveCli: new set_reasoning_effort() that reaches through BuiltRuntime -> ConversationRuntime -> api_client_mut() - runtime::ConversationRuntime: new pub api_client_mut() accessor - MessageRequest construction: reasoning_effort: self.reasoning_effort.clone() - run_repl(): accepts and applies reasoning_effort parameter - parse_direct_slash_cli_action(): propagates reasoning_effort All 156 CLI tests pass, all api tests pass, cargo fmt clean.
This commit is contained in:
@@ -504,6 +504,10 @@ where
|
|||||||
&self.session
|
&self.session
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn api_client_mut(&mut self) -> &mut C {
|
||||||
|
&mut self.api_client
|
||||||
|
}
|
||||||
|
|
||||||
pub fn session_mut(&mut self) -> &mut Session {
|
pub fn session_mut(&mut self) -> &mut Session {
|
||||||
&mut self.session
|
&mut self.session
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ fn run() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
permission_mode,
|
permission_mode,
|
||||||
compact,
|
compact,
|
||||||
base_commit,
|
base_commit,
|
||||||
..
|
reasoning_effort,
|
||||||
} => {
|
} => {
|
||||||
run_stale_base_preflight(base_commit.as_deref());
|
run_stale_base_preflight(base_commit.as_deref());
|
||||||
// Only consume piped stdin as prompt context when the permission
|
// Only consume piped stdin as prompt context when the permission
|
||||||
@@ -223,11 +223,9 @@ fn run() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
let effective_prompt = merge_prompt_with_stdin(&prompt, stdin_context.as_deref());
|
let effective_prompt = merge_prompt_with_stdin(&prompt, stdin_context.as_deref());
|
||||||
LiveCli::new(model, true, allowed_tools, permission_mode)?.run_turn_with_output(
|
let mut cli = LiveCli::new(model, true, allowed_tools, permission_mode)?;
|
||||||
&effective_prompt,
|
cli.set_reasoning_effort(reasoning_effort);
|
||||||
output_format,
|
cli.run_turn_with_output(&effective_prompt, output_format, compact)?;
|
||||||
compact,
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
CliAction::Login { output_format } => run_login(output_format)?,
|
CliAction::Login { output_format } => run_login(output_format)?,
|
||||||
CliAction::Logout { output_format } => run_logout(output_format)?,
|
CliAction::Logout { output_format } => run_logout(output_format)?,
|
||||||
@@ -244,8 +242,14 @@ fn run() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
allowed_tools,
|
allowed_tools,
|
||||||
permission_mode,
|
permission_mode,
|
||||||
base_commit,
|
base_commit,
|
||||||
..
|
reasoning_effort,
|
||||||
} => run_repl(model, allowed_tools, permission_mode, base_commit)?,
|
} => run_repl(
|
||||||
|
model,
|
||||||
|
allowed_tools,
|
||||||
|
permission_mode,
|
||||||
|
base_commit,
|
||||||
|
reasoning_effort,
|
||||||
|
)?,
|
||||||
CliAction::HelpTopic(topic) => print_help_topic(topic),
|
CliAction::HelpTopic(topic) => print_help_topic(topic),
|
||||||
CliAction::Help { output_format } => print_help(output_format)?,
|
CliAction::Help { output_format } => print_help(output_format)?,
|
||||||
}
|
}
|
||||||
@@ -377,6 +381,7 @@ fn parse_args(args: &[String]) -> Result<CliAction, String> {
|
|||||||
let mut allowed_tool_values = Vec::new();
|
let mut allowed_tool_values = Vec::new();
|
||||||
let mut compact = false;
|
let mut compact = false;
|
||||||
let mut base_commit: Option<String> = None;
|
let mut base_commit: Option<String> = None;
|
||||||
|
let mut reasoning_effort: Option<String> = None;
|
||||||
let mut rest = Vec::new();
|
let mut rest = Vec::new();
|
||||||
let mut index = 0;
|
let mut index = 0;
|
||||||
|
|
||||||
@@ -442,6 +447,17 @@ fn parse_args(args: &[String]) -> Result<CliAction, String> {
|
|||||||
base_commit = Some(flag[14..].to_string());
|
base_commit = Some(flag[14..].to_string());
|
||||||
index += 1;
|
index += 1;
|
||||||
}
|
}
|
||||||
|
"--reasoning-effort" => {
|
||||||
|
let value = args
|
||||||
|
.get(index + 1)
|
||||||
|
.ok_or_else(|| "missing value for --reasoning-effort".to_string())?;
|
||||||
|
reasoning_effort = Some(value.clone());
|
||||||
|
index += 2;
|
||||||
|
}
|
||||||
|
flag if flag.starts_with("--reasoning-effort=") => {
|
||||||
|
reasoning_effort = Some(flag[19..].to_string());
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
"-p" => {
|
"-p" => {
|
||||||
// Claw Code compat: -p "prompt" = one-shot prompt
|
// Claw Code compat: -p "prompt" = one-shot prompt
|
||||||
let prompt = args[index + 1..].join(" ");
|
let prompt = args[index + 1..].join(" ");
|
||||||
@@ -457,7 +473,7 @@ fn parse_args(args: &[String]) -> Result<CliAction, String> {
|
|||||||
.unwrap_or_else(default_permission_mode),
|
.unwrap_or_else(default_permission_mode),
|
||||||
compact,
|
compact,
|
||||||
base_commit: base_commit.clone(),
|
base_commit: base_commit.clone(),
|
||||||
reasoning_effort: None,
|
reasoning_effort: reasoning_effort.clone(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
"--print" => {
|
"--print" => {
|
||||||
@@ -516,7 +532,7 @@ fn parse_args(args: &[String]) -> Result<CliAction, String> {
|
|||||||
allowed_tools,
|
allowed_tools,
|
||||||
permission_mode,
|
permission_mode,
|
||||||
base_commit,
|
base_commit,
|
||||||
reasoning_effort: None,
|
reasoning_effort: reasoning_effort.clone(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if rest.first().map(String::as_str) == Some("--resume") {
|
if rest.first().map(String::as_str) == Some("--resume") {
|
||||||
@@ -555,7 +571,7 @@ fn parse_args(args: &[String]) -> Result<CliAction, String> {
|
|||||||
permission_mode,
|
permission_mode,
|
||||||
compact,
|
compact,
|
||||||
base_commit,
|
base_commit,
|
||||||
reasoning_effort: None,
|
reasoning_effort: reasoning_effort.clone(),
|
||||||
}),
|
}),
|
||||||
SkillSlashDispatch::Local => Ok(CliAction::Skills {
|
SkillSlashDispatch::Local => Ok(CliAction::Skills {
|
||||||
args,
|
args,
|
||||||
@@ -581,7 +597,7 @@ fn parse_args(args: &[String]) -> Result<CliAction, String> {
|
|||||||
permission_mode,
|
permission_mode,
|
||||||
compact,
|
compact,
|
||||||
base_commit: base_commit.clone(),
|
base_commit: base_commit.clone(),
|
||||||
reasoning_effort: None,
|
reasoning_effort: reasoning_effort.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
other if other.starts_with('/') => parse_direct_slash_cli_action(
|
other if other.starts_with('/') => parse_direct_slash_cli_action(
|
||||||
@@ -592,6 +608,7 @@ fn parse_args(args: &[String]) -> Result<CliAction, String> {
|
|||||||
permission_mode,
|
permission_mode,
|
||||||
compact,
|
compact,
|
||||||
base_commit,
|
base_commit,
|
||||||
|
reasoning_effort,
|
||||||
),
|
),
|
||||||
_other => Ok(CliAction::Prompt {
|
_other => Ok(CliAction::Prompt {
|
||||||
prompt: rest.join(" "),
|
prompt: rest.join(" "),
|
||||||
@@ -601,7 +618,7 @@ fn parse_args(args: &[String]) -> Result<CliAction, String> {
|
|||||||
permission_mode,
|
permission_mode,
|
||||||
compact,
|
compact,
|
||||||
base_commit,
|
base_commit,
|
||||||
reasoning_effort: None,
|
reasoning_effort: reasoning_effort.clone(),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -695,6 +712,7 @@ fn parse_direct_slash_cli_action(
|
|||||||
permission_mode: PermissionMode,
|
permission_mode: PermissionMode,
|
||||||
compact: bool,
|
compact: bool,
|
||||||
base_commit: Option<String>,
|
base_commit: Option<String>,
|
||||||
|
reasoning_effort: Option<String>,
|
||||||
) -> Result<CliAction, String> {
|
) -> Result<CliAction, String> {
|
||||||
let raw = rest.join(" ");
|
let raw = rest.join(" ");
|
||||||
match SlashCommand::parse(&raw) {
|
match SlashCommand::parse(&raw) {
|
||||||
@@ -722,7 +740,7 @@ fn parse_direct_slash_cli_action(
|
|||||||
permission_mode,
|
permission_mode,
|
||||||
compact,
|
compact,
|
||||||
base_commit,
|
base_commit,
|
||||||
reasoning_effort: None,
|
reasoning_effort: reasoning_effort.clone(),
|
||||||
}),
|
}),
|
||||||
SkillSlashDispatch::Local => Ok(CliAction::Skills {
|
SkillSlashDispatch::Local => Ok(CliAction::Skills {
|
||||||
args,
|
args,
|
||||||
@@ -2772,10 +2790,12 @@ fn run_repl(
|
|||||||
allowed_tools: Option<AllowedToolSet>,
|
allowed_tools: Option<AllowedToolSet>,
|
||||||
permission_mode: PermissionMode,
|
permission_mode: PermissionMode,
|
||||||
base_commit: Option<String>,
|
base_commit: Option<String>,
|
||||||
|
reasoning_effort: Option<String>,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
run_stale_base_preflight(base_commit.as_deref());
|
run_stale_base_preflight(base_commit.as_deref());
|
||||||
let resolved_model = resolve_repl_model(model);
|
let resolved_model = resolve_repl_model(model);
|
||||||
let mut cli = LiveCli::new(resolved_model, true, allowed_tools, permission_mode)?;
|
let mut cli = LiveCli::new(resolved_model, true, allowed_tools, permission_mode)?;
|
||||||
|
cli.set_reasoning_effort(reasoning_effort);
|
||||||
let mut editor =
|
let mut editor =
|
||||||
input::LineEditor::new("> ", cli.repl_completion_candidates().unwrap_or_default());
|
input::LineEditor::new("> ", cli.repl_completion_candidates().unwrap_or_default());
|
||||||
println!("{}", cli.startup_banner());
|
println!("{}", cli.startup_banner());
|
||||||
@@ -3358,6 +3378,12 @@ impl LiveCli {
|
|||||||
Ok(cli)
|
Ok(cli)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_reasoning_effort(&mut self, effort: Option<String>) {
|
||||||
|
if let Some(rt) = self.runtime.runtime.as_mut() {
|
||||||
|
rt.api_client_mut().set_reasoning_effort(effort);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn startup_banner(&self) -> String {
|
fn startup_banner(&self) -> String {
|
||||||
let cwd = env::current_dir().map_or_else(
|
let cwd = env::current_dir().map_or_else(
|
||||||
|_| "<unknown>".to_string(),
|
|_| "<unknown>".to_string(),
|
||||||
@@ -6380,6 +6406,7 @@ struct AnthropicRuntimeClient {
|
|||||||
allowed_tools: Option<AllowedToolSet>,
|
allowed_tools: Option<AllowedToolSet>,
|
||||||
tool_registry: GlobalToolRegistry,
|
tool_registry: GlobalToolRegistry,
|
||||||
progress_reporter: Option<InternalPromptProgressReporter>,
|
progress_reporter: Option<InternalPromptProgressReporter>,
|
||||||
|
reasoning_effort: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AnthropicRuntimeClient {
|
impl AnthropicRuntimeClient {
|
||||||
@@ -6444,8 +6471,13 @@ impl AnthropicRuntimeClient {
|
|||||||
allowed_tools,
|
allowed_tools,
|
||||||
tool_registry,
|
tool_registry,
|
||||||
progress_reporter,
|
progress_reporter,
|
||||||
|
reasoning_effort: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_reasoning_effort(&mut self, effort: Option<String>) {
|
||||||
|
self.reasoning_effort = effort;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_cli_auth_source() -> Result<AuthSource, Box<dyn std::error::Error>> {
|
fn resolve_cli_auth_source() -> Result<AuthSource, Box<dyn std::error::Error>> {
|
||||||
@@ -6491,6 +6523,7 @@ impl ApiClient for AnthropicRuntimeClient {
|
|||||||
.then(|| filter_tool_specs(&self.tool_registry, self.allowed_tools.as_ref())),
|
.then(|| filter_tool_specs(&self.tool_registry, self.allowed_tools.as_ref())),
|
||||||
tool_choice: self.enable_tools.then_some(ToolChoice::Auto),
|
tool_choice: self.enable_tools.then_some(ToolChoice::Auto),
|
||||||
stream: true,
|
stream: true,
|
||||||
|
reasoning_effort: self.reasoning_effort.clone(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user