Compare commits
3
Commits
9540345ec7
...
e606eb7c49
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e606eb7c49
|
||
|
|
a8fb32b6bd
|
||
|
|
1f7b8417fa
|
@@ -88,7 +88,6 @@ nodes:
|
|||||||
prompt: |
|
prompt: |
|
||||||
Research prompt: {{initial_prompt}}
|
Research prompt: {{initial_prompt}}
|
||||||
tools: []
|
tools: []
|
||||||
temperature: 0.1
|
|
||||||
output_schema:
|
output_schema:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
@@ -180,7 +179,6 @@ nodes:
|
|||||||
tools:
|
tools:
|
||||||
- mcp:ddg-search
|
- mcp:ddg-search
|
||||||
max_iterations: 15
|
max_iterations: 15
|
||||||
temperature: 0.1
|
|
||||||
state_updates:
|
state_updates:
|
||||||
search_output: "{{output}}"
|
search_output: "{{output}}"
|
||||||
fallback: synthesize
|
fallback: synthesize
|
||||||
@@ -251,7 +249,6 @@ nodes:
|
|||||||
tools:
|
tools:
|
||||||
- mcp:personal-github
|
- mcp:personal-github
|
||||||
max_iterations: 15
|
max_iterations: 15
|
||||||
temperature: 0.1
|
|
||||||
state_updates:
|
state_updates:
|
||||||
oss_output: "{{output}}"
|
oss_output: "{{output}}"
|
||||||
fallback: synthesize
|
fallback: synthesize
|
||||||
@@ -338,7 +335,6 @@ nodes:
|
|||||||
tools:
|
tools:
|
||||||
- fetch_url_via_curl
|
- fetch_url_via_curl
|
||||||
max_iterations: 20
|
max_iterations: 20
|
||||||
temperature: 0.1
|
|
||||||
state_updates:
|
state_updates:
|
||||||
findings: "{{output}}"
|
findings: "{{output}}"
|
||||||
fallback: final_format
|
fallback: final_format
|
||||||
|
|||||||
+10
-3
@@ -1,3 +1,5 @@
|
|||||||
|
use std::mem;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use crate::utils::{base64_decode, encode_uri, hex_encode, hmac_sha256, sha256, strip_think_tag};
|
use crate::utils::{base64_decode, encode_uri, hex_encode, hmac_sha256, sha256, strip_think_tag};
|
||||||
@@ -275,10 +277,11 @@ async fn chat_completions_streaming(
|
|||||||
format!("Tool call '{function_name}' has non-JSON arguments '{function_arguments}'")
|
format!("Tool call '{function_name}' has non-JSON arguments '{function_arguments}'")
|
||||||
})?;
|
})?;
|
||||||
handler.tool_call(ToolCall::new(
|
handler.tool_call(ToolCall::new(
|
||||||
function_name.clone(),
|
mem::take(&mut function_name),
|
||||||
arguments,
|
arguments,
|
||||||
Some(function_id.clone()),
|
Some(mem::take(&mut function_id)),
|
||||||
))?;
|
))?;
|
||||||
|
function_arguments.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
@@ -529,7 +532,11 @@ fn extract_chat_completions(data: &Value) -> Result<ChatCompletionsOutput> {
|
|||||||
bail!("Invalid response data: {data}");
|
bail!("Invalid response data: {data}");
|
||||||
}
|
}
|
||||||
|
|
||||||
let output = ChatCompletionsOutput { text, tool_calls, ..Default::default() };
|
let output = ChatCompletionsOutput {
|
||||||
|
text,
|
||||||
|
tool_calls,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
Ok(output)
|
Ok(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use std::mem;
|
||||||
|
|
||||||
use super::access_token::get_access_token;
|
use super::access_token::get_access_token;
|
||||||
use super::claude_oauth::ClaudeOAuthProvider;
|
use super::claude_oauth::ClaudeOAuthProvider;
|
||||||
use super::oauth::{self, OAuthProvider};
|
use super::oauth::{self, OAuthProvider};
|
||||||
@@ -232,8 +234,8 @@ pub async fn claude_chat_completions_streaming(
|
|||||||
handler.text("\n</think>\n\n")?;
|
handler.text("\n</think>\n\n")?;
|
||||||
reasoning_state = 0;
|
reasoning_state = 0;
|
||||||
handler.thinking_block(ThinkingBlock::Thinking {
|
handler.thinking_block(ThinkingBlock::Thinking {
|
||||||
thinking: std::mem::take(&mut thinking_text),
|
thinking: mem::take(&mut thinking_text),
|
||||||
signature: std::mem::take(&mut thinking_signature),
|
signature: mem::take(&mut thinking_signature),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if !function_name.is_empty() {
|
if !function_name.is_empty() {
|
||||||
@@ -245,10 +247,11 @@ pub async fn claude_chat_completions_streaming(
|
|||||||
})?
|
})?
|
||||||
};
|
};
|
||||||
handler.tool_call(ToolCall::new(
|
handler.tool_call(ToolCall::new(
|
||||||
function_name.clone(),
|
mem::take(&mut function_name),
|
||||||
arguments,
|
arguments,
|
||||||
Some(function_id.clone()),
|
Some(mem::take(&mut function_id)),
|
||||||
))?;
|
))?;
|
||||||
|
function_arguments.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|||||||
+44
-2
@@ -88,11 +88,21 @@ async fn run_one_shot(prompt: &str, ctx: &mut RequestContext) -> Result<String>
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn try_parse_json(raw: &str) -> Option<Value> {
|
fn try_parse_json(raw: &str) -> Option<Value> {
|
||||||
let cleaned = strip_code_fences(raw.trim());
|
let cleaned = strip_code_fences(strip_thinking_blocks(raw.trim()));
|
||||||
|
|
||||||
serde_json::from_str(cleaned).ok()
|
serde_json::from_str(cleaned).ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn strip_thinking_blocks(s: &str) -> &str {
|
||||||
|
let mut s = s.trim_start();
|
||||||
|
while s.starts_with("<think>") {
|
||||||
|
match s.find("</think>") {
|
||||||
|
Some(end) => s = s[end + "</think>".len()..].trim_start(),
|
||||||
|
None => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s
|
||||||
|
}
|
||||||
|
|
||||||
fn strip_code_fences(s: &str) -> &str {
|
fn strip_code_fences(s: &str) -> &str {
|
||||||
let after_open = s
|
let after_open = s
|
||||||
.strip_prefix("```json")
|
.strip_prefix("```json")
|
||||||
@@ -148,6 +158,38 @@ mod tests {
|
|||||||
assert_eq!(v, json!({"x": true}));
|
assert_eq!(v, json!({"x": true}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn try_parse_json_strips_thinking_blocks() {
|
||||||
|
let raw = "<think>\nsome reasoning\n</think>\n{\"a\": 1}";
|
||||||
|
|
||||||
|
let v = try_parse_json(raw).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(v, json!({"a": 1}));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn try_parse_json_strips_empty_thinking_block() {
|
||||||
|
let raw = "<think>\n\n</think>\n{\"a\": 1}";
|
||||||
|
|
||||||
|
let v = try_parse_json(raw).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(v, json!({"a": 1}));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn try_parse_json_strips_multiple_thinking_blocks() {
|
||||||
|
let raw = "<think>first</think>\n<think>second</think>\n{\"a\": 1}";
|
||||||
|
|
||||||
|
let v = try_parse_json(raw).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(v, json!({"a": 1}));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn try_parse_json_unclosed_think_tag_returns_none() {
|
||||||
|
assert!(try_parse_json("<think>unclosed {\"a\": 1}").is_none());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn try_parse_json_returns_none_on_prose() {
|
fn try_parse_json_returns_none_on_prose() {
|
||||||
assert!(try_parse_json("Here is the result: it's good").is_none());
|
assert!(try_parse_json("Here is the result: it's good").is_none());
|
||||||
|
|||||||
Reference in New Issue
Block a user