Skip to content

Commit ef523b0

Browse files
committed
refactor: error handling and parsing
1 parent af19eaf commit ef523b0

File tree

1 file changed

+13
-8
lines changed

1 file changed

+13
-8
lines changed

src/llm/anthropic.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,15 @@ impl LlmGenerationClient for Client {
4949
payload["system"] = serde_json::json!(system);
5050
}
5151

52-
let OutputFormat::JsonSchema { schema, .. } = request.output_format.as_ref().expect("Anthropic client expects OutputFormat::JsonSchema for all requests");
52+
// Extract schema from output_format, error if not JsonSchema
53+
let schema = match request.output_format.as_ref() {
54+
Some(OutputFormat::JsonSchema { schema, .. }) => schema,
55+
_ => api_bail!("Anthropic client expects OutputFormat::JsonSchema for all requests"),
56+
};
57+
5358
let schema_json = serde_json::to_value(schema)?;
5459
payload["tools"] = serde_json::json!([
55-
{ "type": "custom", "name": "extraction", "input_schema": schema_json }
60+
{ "type": "custom", "name": "report_result", "input_schema": schema_json }
5661
]);
5762

5863
let url = "https://api.anthropic.com/v1/messages";
@@ -67,7 +72,7 @@ impl LlmGenerationClient for Client {
6772
.send()
6873
.await
6974
.context("HTTP error")?;
70-
let resp_json: Value = resp.json().await.context("Invalid JSON")?;
75+
let mut resp_json: Value = resp.json().await.context("Invalid JSON")?;
7176
if let Some(error) = resp_json.get("error") {
7277
bail!("Anthropic API error: {:?}", error);
7378
}
@@ -76,7 +81,7 @@ impl LlmGenerationClient for Client {
7681
// println!("Anthropic API full response: {resp_json:?}");
7782

7883
let resp_content = &resp_json["content"];
79-
let tool_name = "extraction";
84+
let tool_name = "report_result";
8085
let mut extracted_json: Option<Value> = None;
8186
if let Some(array) = resp_content.as_array() {
8287
for item in array {
@@ -95,17 +100,17 @@ impl LlmGenerationClient for Client {
95100
serde_json::to_string(&json)?
96101
} else {
97102
// Fallback: try text if no tool output found
98-
match &resp_json["content"][0]["text"] {
103+
match &mut resp_json["content"][0]["text"] {
99104
Value::String(s) => {
100105
// Try strict JSON parsing first
101106
match serde_json::from_str::<serde_json::Value>(s) {
102-
Ok(_) => s.clone(),
107+
Ok(_) => std::mem::take(s),
103108
Err(e) => {
104109
// Try permissive json5 parsing as fallback
105110
match json5::from_str::<serde_json::Value>(s) {
106-
Ok(_) => {
111+
Ok(value) => {
107112
println!("[Anthropic] Used permissive JSON5 parser for output");
108-
s.clone()
113+
serde_json::to_string(&value)?
109114
},
110115
Err(e2) => return Err(anyhow::anyhow!(format!("No structured tool output or text found in response, and permissive JSON5 parsing also failed: {e}; {e2}")))
111116
}

0 commit comments

Comments
 (0)