修复结构体和函数的更变

This commit is contained in:
fengmengqi 2026-04-03 22:09:03 +08:00
parent 0d12ca9854
commit 0782159ecd
4 changed files with 119 additions and 11 deletions

1
Cargo.lock generated
View File

@ -1357,6 +1357,7 @@ dependencies = [
"commands", "commands",
"compat-harness", "compat-harness",
"crossterm", "crossterm",
"plugins",
"pulldown-cmark", "pulldown-cmark",
"runtime", "runtime",
"serde_json", "serde_json",

View File

@ -807,6 +807,7 @@ mod tests {
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::fs; use std::fs;
use std::io::ErrorKind; use std::io::ErrorKind;
#[cfg(unix)]
use std::os::unix::fs::PermissionsExt; use std::os::unix::fs::PermissionsExt;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::process::Command; use std::process::Command;
@ -846,9 +847,12 @@ mod tests {
"#!/bin/sh\nprintf 'READY:%s\\n' \"$MCP_TEST_TOKEN\"\nIFS= read -r line\nprintf 'ECHO:%s\\n' \"$line\"\n", "#!/bin/sh\nprintf 'READY:%s\\n' \"$MCP_TEST_TOKEN\"\nIFS= read -r line\nprintf 'ECHO:%s\\n' \"$line\"\n",
) )
.expect("write script"); .expect("write script");
let mut permissions = fs::metadata(&script_path).expect("metadata").permissions(); #[cfg(unix)]
permissions.set_mode(0o755); {
fs::set_permissions(&script_path, permissions).expect("chmod"); let mut permissions = fs::metadata(&script_path).expect("metadata").permissions();
permissions.set_mode(0o755);
fs::set_permissions(&script_path, permissions).expect("chmod");
}
script_path script_path
} }

View File

@ -15,6 +15,7 @@ commands = { path = "../commands" }
compat-harness = { path = "../compat-harness" } compat-harness = { path = "../compat-harness" }
crossterm = "0.28" crossterm = "0.28"
pulldown-cmark = "0.13" pulldown-cmark = "0.13"
plugins = { path = "../plugins" }
runtime = { path = "../runtime" } runtime = { path = "../runtime" }
serde_json = "1" serde_json = "1"
syntect = "5" syntect = "5"

View File

@ -12,12 +12,14 @@ use std::process::Command;
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{SystemTime, UNIX_EPOCH};
use api::{ use api::{
resolve_startup_auth_source, AnthropicClient, AuthSource, ContentBlockDelta, InputContentBlock, resolve_startup_auth_source, AuthSource, ClawApiClient, ContentBlockDelta, InputContentBlock,
InputMessage, MessageRequest, MessageResponse, OutputContentBlock, InputMessage, MessageRequest, MessageResponse, OutputContentBlock,
StreamEvent as ApiStreamEvent, ToolChoice, ToolDefinition, ToolResultContentBlock, StreamEvent as ApiStreamEvent, ToolChoice, ToolDefinition, ToolResultContentBlock,
}; };
use commands::{ use commands::{
handle_agents_slash_command, handle_branch_slash_command, handle_commit_slash_command,
handle_plugins_slash_command, handle_skills_slash_command, handle_worktree_slash_command,
render_slash_command_help, resume_supported_slash_commands, slash_command_specs, SlashCommand, render_slash_command_help, resume_supported_slash_commands, slash_command_specs, SlashCommand,
}; };
use compat_harness::{extract_manifest, UpstreamPaths}; use compat_harness::{extract_manifest, UpstreamPaths};
@ -33,6 +35,7 @@ use runtime::{
}; };
use serde_json::json; use serde_json::json;
use tools::{execute_tool, mvp_tool_specs, ToolSpec}; use tools::{execute_tool, mvp_tool_specs, ToolSpec};
use plugins::{self, PluginManager, PluginManagerConfig};
const DEFAULT_MODEL: &str = "claude-opus-4-6"; const DEFAULT_MODEL: &str = "claude-opus-4-6";
const DEFAULT_MAX_TOKENS: u32 = 32; const DEFAULT_MAX_TOKENS: u32 = 32;
@ -404,7 +407,7 @@ fn dump_manifests() {
} }
fn print_bootstrap_plan() { fn print_bootstrap_plan() {
for phase in runtime::BootstrapPlan::claude_code_default().phases() { for phase in runtime::BootstrapPlan::claw_default().phases() {
println!("- {phase:?}"); println!("- {phase:?}");
} }
} }
@ -450,7 +453,7 @@ fn run_login() -> Result<(), Box<dyn std::error::Error>> {
return Err(io::Error::new(io::ErrorKind::InvalidData, "oauth state mismatch").into()); return Err(io::Error::new(io::ErrorKind::InvalidData, "oauth state mismatch").into());
} }
let client = AnthropicClient::from_auth(AuthSource::None).with_base_url(api::read_base_url()); let client = ClawApiClient::from_auth(AuthSource::None).with_base_url(api::read_base_url());
let exchange_request = let exchange_request =
OAuthTokenExchangeRequest::from_config(oauth, code, state, pkce.verifier, redirect_uri); OAuthTokenExchangeRequest::from_config(oauth, code, state, pkce.verifier, redirect_uri);
let runtime = tokio::runtime::Runtime::new()?; let runtime = tokio::runtime::Runtime::new()?;
@ -864,10 +867,35 @@ fn run_resume_command(
)), )),
}) })
} }
SlashCommand::Resume { .. } SlashCommand::Agents { args } => Ok(ResumeCommandOutcome {
session: session.clone(),
message: Some(
handle_agents_slash_command(args.as_deref(), &env::current_dir()?)
.map_err(|error| error.to_string())?,
),
}),
SlashCommand::Skills { args } => Ok(ResumeCommandOutcome {
session: session.clone(),
message: Some(
handle_skills_slash_command(args.as_deref(), &env::current_dir()?)
.map_err(|error| error.to_string())?,
),
}),
SlashCommand::Branch { .. }
| SlashCommand::Bughunter { .. }
| SlashCommand::Worktree { .. }
| SlashCommand::Commit
| SlashCommand::CommitPushPr { .. }
| SlashCommand::Pr { .. }
| SlashCommand::Issue { .. }
| SlashCommand::Ultraplan { .. }
| SlashCommand::Teleport { .. }
| SlashCommand::DebugToolCall
| SlashCommand::Resume { .. }
| SlashCommand::Model { .. } | SlashCommand::Model { .. }
| SlashCommand::Permissions { .. } | SlashCommand::Permissions { .. }
| SlashCommand::Session { .. } | SlashCommand::Session { .. }
| SlashCommand::Plugins { .. }
| SlashCommand::Unknown(_) => Err("unsupported resumed slash command".into()), | SlashCommand::Unknown(_) => Err("unsupported resumed slash command".into()),
} }
} }
@ -1033,7 +1061,7 @@ impl LiveCli {
} }
fn run_prompt_json(&mut self, input: &str) -> Result<(), Box<dyn std::error::Error>> { fn run_prompt_json(&mut self, input: &str) -> Result<(), Box<dyn std::error::Error>> {
let client = AnthropicClient::from_auth(resolve_cli_auth_source()?).with_base_url(api::read_base_url()); let client = ClawApiClient::from_auth(resolve_cli_auth_source()?).with_base_url(api::read_base_url());
let request = MessageRequest { let request = MessageRequest {
model: self.model.clone(), model: self.model.clone(),
max_tokens: DEFAULT_MAX_TOKENS, max_tokens: DEFAULT_MAX_TOKENS,
@ -1055,7 +1083,9 @@ impl LiveCli {
.iter() .iter()
.filter_map(|block| match block { .filter_map(|block| match block {
OutputContentBlock::Text { text } => Some(text.as_str()), OutputContentBlock::Text { text } => Some(text.as_str()),
OutputContentBlock::ToolUse { .. } => None, OutputContentBlock::ToolUse { .. }
| OutputContentBlock::Thinking { .. }
| OutputContentBlock::RedactedThinking { .. } => None,
}) })
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join(""); .join("");
@ -1124,6 +1154,75 @@ impl LiveCli {
self.export_session(path.as_deref())?; self.export_session(path.as_deref())?;
false false
} }
SlashCommand::Branch { action, target } => {
println!(
"{}",
handle_branch_slash_command(
action.as_deref(),
target.as_deref(),
&env::current_dir()?
)?
);
false
}
SlashCommand::Worktree {
action,
path,
branch,
} => {
println!(
"{}",
handle_worktree_slash_command(
action.as_deref(),
path.as_deref(),
branch.as_deref(),
&env::current_dir()?
)?
);
false
}
SlashCommand::Commit => {
println!(
"{}",
handle_commit_slash_command("resume commit", &env::current_dir()?)?
);
false
}
SlashCommand::Agents { args } => {
println!(
"{}",
handle_agents_slash_command(args.as_deref(), &env::current_dir()?)?
);
false
}
SlashCommand::Skills { args } => {
println!(
"{}",
handle_skills_slash_command(args.as_deref(), &env::current_dir()?)?
);
false
}
SlashCommand::Plugins { action, target } => {
let config = plugins::PluginManagerConfig::new(env::current_dir()?);
let mut manager = plugins::PluginManager::new(config);
let result = handle_plugins_slash_command(
action.as_deref(),
target.as_deref(),
&mut manager,
)?;
println!("{}", result.message);
result.reload_runtime
}
SlashCommand::Bughunter { .. }
| SlashCommand::CommitPushPr { .. }
| SlashCommand::Pr { .. }
| SlashCommand::Issue { .. }
| SlashCommand::Ultraplan { .. }
| SlashCommand::Teleport { .. }
| SlashCommand::DebugToolCall => {
eprintln!("slash command not yet implemented in REPL: {command:?}");
false
}
SlashCommand::Session { action, target } => { SlashCommand::Session { action, target } => {
self.handle_session_command(action.as_deref(), target.as_deref())? self.handle_session_command(action.as_deref(), target.as_deref())?
} }
@ -1920,7 +2019,7 @@ impl runtime::PermissionPrompter for CliPermissionPrompter {
struct AnthropicRuntimeClient { struct AnthropicRuntimeClient {
runtime: tokio::runtime::Runtime, runtime: tokio::runtime::Runtime,
client: AnthropicClient, client: ClawApiClient,
model: String, model: String,
enable_tools: bool, enable_tools: bool,
allowed_tools: Option<AllowedToolSet>, allowed_tools: Option<AllowedToolSet>,
@ -1934,7 +2033,7 @@ impl AnthropicRuntimeClient {
) -> Result<Self, Box<dyn std::error::Error>> { ) -> Result<Self, Box<dyn std::error::Error>> {
Ok(Self { Ok(Self {
runtime: tokio::runtime::Runtime::new()?, runtime: tokio::runtime::Runtime::new()?,
client: AnthropicClient::from_auth(resolve_cli_auth_source()?).with_base_url(api::read_base_url()), client: ClawApiClient::from_auth(resolve_cli_auth_source()?).with_base_url(api::read_base_url()),
model, model,
enable_tools, enable_tools,
allowed_tools, allowed_tools,
@ -2018,6 +2117,8 @@ impl ApiClient for AnthropicRuntimeClient {
input.push_str(&partial_json); input.push_str(&partial_json);
} }
} }
ContentBlockDelta::ThinkingDelta { .. }
| ContentBlockDelta::SignatureDelta { .. } => {}
}, },
ApiStreamEvent::ContentBlockStop(_) => { ApiStreamEvent::ContentBlockStop(_) => {
if let Some((id, name, input)) = pending_tool.take() { if let Some((id, name, input)) = pending_tool.take() {
@ -2151,6 +2252,7 @@ fn push_output_block(
.map_err(|error| RuntimeError::new(error.to_string()))?; .map_err(|error| RuntimeError::new(error.to_string()))?;
*pending_tool = Some((id, name, input.to_string())); *pending_tool = Some((id, name, input.to_string()));
} }
OutputContentBlock::Thinking { .. } | OutputContentBlock::RedactedThinking { .. } => {}
} }
Ok(()) Ok(())
} }