mirror of
https://github.com/lWolvesl/claw-code.git
synced 2026-04-02 21:51:51 +08:00
feat: anthropic SDK header matching + request profile
This commit is contained in:
@@ -439,6 +439,19 @@ impl AnthropicClient {
|
|||||||
"beta_count".to_string(),
|
"beta_count".to_string(),
|
||||||
Value::from(u64::try_from(self.request_profile.betas.len()).unwrap_or(u64::MAX)),
|
Value::from(u64::try_from(self.request_profile.betas.len()).unwrap_or(u64::MAX)),
|
||||||
);
|
);
|
||||||
|
if !self.request_profile.betas.is_empty() {
|
||||||
|
attributes.insert(
|
||||||
|
"betas".to_string(),
|
||||||
|
Value::Array(
|
||||||
|
self.request_profile
|
||||||
|
.betas
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.map(Value::String)
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
if !self.request_profile.extra_body.is_empty() {
|
if !self.request_profile.extra_body.is_empty() {
|
||||||
attributes.insert(
|
attributes.insert(
|
||||||
"extra_body_keys".to_string(),
|
"extra_body_keys".to_string(),
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ async fn send_message_posts_json_and_parses_response() {
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
request.headers.get("anthropic-beta").map(String::as_str),
|
request.headers.get("anthropic-beta").map(String::as_str),
|
||||||
Some("claude-code-20250219")
|
Some("claude-code-20250219,prompt-caching-scope-2026-01-05")
|
||||||
);
|
);
|
||||||
let body: serde_json::Value =
|
let body: serde_json::Value =
|
||||||
serde_json::from_str(&request.body).expect("request body should be json");
|
serde_json::from_str(&request.body).expect("request body should be json");
|
||||||
@@ -86,7 +86,10 @@ async fn send_message_posts_json_and_parses_response() {
|
|||||||
assert!(body.get("stream").is_none());
|
assert!(body.get("stream").is_none());
|
||||||
assert_eq!(body["tools"][0]["name"], json!("get_weather"));
|
assert_eq!(body["tools"][0]["name"], json!("get_weather"));
|
||||||
assert_eq!(body["tool_choice"]["type"], json!("auto"));
|
assert_eq!(body["tool_choice"]["type"], json!("auto"));
|
||||||
assert_eq!(body["betas"], json!(["claude-code-20250219"]));
|
assert_eq!(
|
||||||
|
body["betas"],
|
||||||
|
json!(["claude-code-20250219", "prompt-caching-scope-2026-01-05"])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
@@ -133,7 +136,7 @@ async fn send_message_applies_request_profile_and_records_telemetry() {
|
|||||||
let request = captured.first().expect("server should capture request");
|
let request = captured.first().expect("server should capture request");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
request.headers.get("anthropic-beta").map(String::as_str),
|
request.headers.get("anthropic-beta").map(String::as_str),
|
||||||
Some("claude-code-20250219,tools-2026-04-01")
|
Some("claude-code-20250219,prompt-caching-scope-2026-01-05,tools-2026-04-01")
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
request.headers.get("user-agent").map(String::as_str),
|
request.headers.get("user-agent").map(String::as_str),
|
||||||
@@ -144,7 +147,11 @@ async fn send_message_applies_request_profile_and_records_telemetry() {
|
|||||||
assert_eq!(body["metadata"]["source"], json!("clawd-code"));
|
assert_eq!(body["metadata"]["source"], json!("clawd-code"));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
body["betas"],
|
body["betas"],
|
||||||
json!(["claude-code-20250219", "tools-2026-04-01"])
|
json!([
|
||||||
|
"claude-code-20250219",
|
||||||
|
"prompt-caching-scope-2026-01-05",
|
||||||
|
"tools-2026-04-01"
|
||||||
|
])
|
||||||
);
|
);
|
||||||
|
|
||||||
let events = sink.events();
|
let events = sink.events();
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ pub const DEFAULT_ANTHROPIC_VERSION: &str = "2023-06-01";
|
|||||||
pub const DEFAULT_APP_NAME: &str = "claude-code";
|
pub const DEFAULT_APP_NAME: &str = "claude-code";
|
||||||
pub const DEFAULT_RUNTIME: &str = "rust";
|
pub const DEFAULT_RUNTIME: &str = "rust";
|
||||||
pub const DEFAULT_AGENTIC_BETA: &str = "claude-code-20250219";
|
pub const DEFAULT_AGENTIC_BETA: &str = "claude-code-20250219";
|
||||||
|
pub const DEFAULT_PROMPT_CACHING_SCOPE_BETA: &str = "prompt-caching-scope-2026-01-05";
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct ClientIdentity {
|
pub struct ClientIdentity {
|
||||||
@@ -65,7 +66,10 @@ impl AnthropicRequestProfile {
|
|||||||
Self {
|
Self {
|
||||||
anthropic_version: DEFAULT_ANTHROPIC_VERSION.to_string(),
|
anthropic_version: DEFAULT_ANTHROPIC_VERSION.to_string(),
|
||||||
client_identity,
|
client_identity,
|
||||||
betas: vec![DEFAULT_AGENTIC_BETA.to_string()],
|
betas: vec![
|
||||||
|
DEFAULT_AGENTIC_BETA.to_string(),
|
||||||
|
DEFAULT_PROMPT_CACHING_SCOPE_BETA.to_string(),
|
||||||
|
],
|
||||||
extra_body: Map::new(),
|
extra_body: Map::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -445,7 +449,8 @@ mod tests {
|
|||||||
("user-agent".to_string(), "claude-code/1.2.3".to_string()),
|
("user-agent".to_string(), "claude-code/1.2.3".to_string()),
|
||||||
(
|
(
|
||||||
"anthropic-beta".to_string(),
|
"anthropic-beta".to_string(),
|
||||||
"claude-code-20250219,tools-2026-04-01".to_string(),
|
"claude-code-20250219,prompt-caching-scope-2026-01-05,tools-2026-04-01"
|
||||||
|
.to_string(),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
@@ -459,7 +464,11 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
body["betas"],
|
body["betas"],
|
||||||
serde_json::json!(["claude-code-20250219", "tools-2026-04-01"])
|
serde_json::json!([
|
||||||
|
"claude-code-20250219",
|
||||||
|
"prompt-caching-scope-2026-01-05",
|
||||||
|
"tools-2026-04-01"
|
||||||
|
])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user