mirror of
https://github.com/instructkr/claude-code.git
synced 2026-04-03 17:08:47 +03:00
feat: provider abstraction layer + Grok API support
This commit is contained in:
@@ -12,8 +12,9 @@ use std::process::Command;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
use api::{
|
||||
resolve_startup_auth_source, AnthropicClient, AuthSource, ContentBlockDelta, InputContentBlock,
|
||||
InputMessage, MessageRequest, MessageResponse, OutputContentBlock,
|
||||
detect_provider_kind, max_tokens_for_model, resolve_model_alias, resolve_startup_auth_source,
|
||||
AnthropicClient, AuthSource, ContentBlockDelta, InputContentBlock, InputMessage,
|
||||
MessageRequest, MessageResponse, OutputContentBlock, ProviderClient, ProviderKind,
|
||||
StreamEvent as ApiStreamEvent, ToolChoice, ToolDefinition, ToolResultContentBlock,
|
||||
};
|
||||
|
||||
@@ -35,13 +36,6 @@ use serde_json::json;
|
||||
use tools::{execute_tool, mvp_tool_specs, ToolSpec};
|
||||
|
||||
const DEFAULT_MODEL: &str = "claude-opus-4-6";
|
||||
fn max_tokens_for_model(model: &str) -> u32 {
|
||||
if model.contains("opus") {
|
||||
32_000
|
||||
} else {
|
||||
64_000
|
||||
}
|
||||
}
|
||||
const DEFAULT_DATE: &str = "2026-03-31";
|
||||
const DEFAULT_OAUTH_CALLBACK_PORT: u16 = 4545;
|
||||
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
@@ -288,15 +282,6 @@ fn parse_args(args: &[String]) -> Result<CliAction, String> {
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_model_alias(model: &str) -> &str {
|
||||
match model {
|
||||
"opus" => "claude-opus-4-6",
|
||||
"sonnet" => "claude-sonnet-4-6",
|
||||
"haiku" => "claude-haiku-4-5-20251213",
|
||||
_ => model,
|
||||
}
|
||||
}
|
||||
|
||||
fn normalize_allowed_tools(values: &[String]) -> Result<Option<AllowedToolSet>, String> {
|
||||
if values.is_empty() {
|
||||
return Ok(None);
|
||||
@@ -980,7 +965,7 @@ struct LiveCli {
|
||||
allowed_tools: Option<AllowedToolSet>,
|
||||
permission_mode: PermissionMode,
|
||||
system_prompt: Vec<String>,
|
||||
runtime: ConversationRuntime<AnthropicRuntimeClient, CliToolExecutor>,
|
||||
runtime: ConversationRuntime<ProviderRuntimeClient, CliToolExecutor>,
|
||||
session: SessionHandle,
|
||||
}
|
||||
|
||||
@@ -1920,11 +1905,11 @@ fn build_runtime(
|
||||
emit_output: bool,
|
||||
allowed_tools: Option<AllowedToolSet>,
|
||||
permission_mode: PermissionMode,
|
||||
) -> Result<ConversationRuntime<AnthropicRuntimeClient, CliToolExecutor>, Box<dyn std::error::Error>>
|
||||
) -> Result<ConversationRuntime<ProviderRuntimeClient, CliToolExecutor>, Box<dyn std::error::Error>>
|
||||
{
|
||||
Ok(ConversationRuntime::new_with_features(
|
||||
session,
|
||||
AnthropicRuntimeClient::new(model, enable_tools, emit_output, allowed_tools.clone())?,
|
||||
ProviderRuntimeClient::new(model, enable_tools, emit_output, allowed_tools.clone())?,
|
||||
CliToolExecutor::new(allowed_tools, emit_output),
|
||||
permission_policy(permission_mode),
|
||||
system_prompt,
|
||||
@@ -1978,26 +1963,33 @@ impl runtime::PermissionPrompter for CliPermissionPrompter {
|
||||
}
|
||||
}
|
||||
|
||||
struct AnthropicRuntimeClient {
|
||||
struct ProviderRuntimeClient {
|
||||
runtime: tokio::runtime::Runtime,
|
||||
client: AnthropicClient,
|
||||
client: ProviderClient,
|
||||
model: String,
|
||||
enable_tools: bool,
|
||||
emit_output: bool,
|
||||
allowed_tools: Option<AllowedToolSet>,
|
||||
}
|
||||
|
||||
impl AnthropicRuntimeClient {
|
||||
impl ProviderRuntimeClient {
|
||||
fn new(
|
||||
model: String,
|
||||
enable_tools: bool,
|
||||
emit_output: bool,
|
||||
allowed_tools: Option<AllowedToolSet>,
|
||||
) -> Result<Self, Box<dyn std::error::Error>> {
|
||||
let model = resolve_model_alias(&model).to_string();
|
||||
let client = match detect_provider_kind(&model) {
|
||||
ProviderKind::Anthropic => ProviderClient::from_model_with_anthropic_auth(
|
||||
&model,
|
||||
Some(resolve_cli_auth_source()?),
|
||||
)?,
|
||||
ProviderKind::Xai | ProviderKind::OpenAi => ProviderClient::from_model(&model)?,
|
||||
};
|
||||
Ok(Self {
|
||||
runtime: tokio::runtime::Runtime::new()?,
|
||||
client: AnthropicClient::from_auth(resolve_cli_auth_source()?)
|
||||
.with_base_url(api::read_base_url()),
|
||||
client,
|
||||
model,
|
||||
enable_tools,
|
||||
emit_output,
|
||||
@@ -2016,7 +2008,7 @@ fn resolve_cli_auth_source() -> Result<AuthSource, Box<dyn std::error::Error>> {
|
||||
})?)
|
||||
}
|
||||
|
||||
impl ApiClient for AnthropicRuntimeClient {
|
||||
impl ApiClient for ProviderRuntimeClient {
|
||||
#[allow(clippy::too_many_lines)]
|
||||
fn stream(&mut self, request: ApiRequest) -> Result<Vec<AssistantEvent>, RuntimeError> {
|
||||
let message_request = MessageRequest {
|
||||
@@ -2911,6 +2903,9 @@ mod tests {
|
||||
assert_eq!(resolve_model_alias("opus"), "claude-opus-4-6");
|
||||
assert_eq!(resolve_model_alias("sonnet"), "claude-sonnet-4-6");
|
||||
assert_eq!(resolve_model_alias("haiku"), "claude-haiku-4-5-20251213");
|
||||
assert_eq!(resolve_model_alias("grok"), "grok-3");
|
||||
assert_eq!(resolve_model_alias("grok-mini"), "grok-3-mini");
|
||||
assert_eq!(resolve_model_alias("grok-2"), "grok-2");
|
||||
assert_eq!(resolve_model_alias("claude-opus"), "claude-opus");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user