From 1ae5ee5f9fd875f064bb14f839dada74239f637c Mon Sep 17 00:00:00 2001 From: Jean Mertz Date: Fri, 11 Sep 2026 11:28:28 +0200 Subject: [PATCH 1/2] fix(llm, openai, openrouter, llamacpp): Decode nulls Optional tool arguments encoded as null by strict providers reach tools as omitted fields. This lets Bookworm apply its defaults rather than rejecting `kinds: null`. Explicit values, source-accepted nulls, and required arguments retain their meaning. Pair schema conversion with request-local decoding plans, consumed when streamed arguments become a complete tool call. Cover OpenAI's streaming and non-streaming paths, OpenRouter, and llama.cpp without changing MCP transport or persisted event types. Keep reference resolution and schema composition behavior unchanged. Decoding through references and general unions remains deferred to T-0h28vbn; shared dispatch validation remains tracked by T-063sw1z. Signed-off-by: Jean Mertz --- crates/jp_cli/src/cmd/query/turn_loop.rs | 2 +- crates/jp_llm/src/event.rs | 8 + crates/jp_llm/src/event_builder.rs | 25 +- crates/jp_llm/src/event_builder_tests.rs | 6 + crates/jp_llm/src/provider.rs | 4 + crates/jp_llm/src/provider/llamacpp.rs | 47 +-- crates/jp_llm/src/provider/llamacpp_tests.rs | 2 +- crates/jp_llm/src/provider/openai.rs | 132 ++++++-- crates/jp_llm/src/provider/openai_tests.rs | 2 +- crates/jp_llm/src/provider/openrouter.rs | 55 ++-- .../jp_llm/src/provider/openrouter_tests.rs | 4 +- .../src/provider/tool_decoding_tests.rs | 302 ++++++++++++++++++ crates/jp_llm/src/stream.rs | 2 +- crates/jp_llm/src/tool.rs | 1 + crates/jp_llm/src/tool/decoding.rs | 91 ++++++ crates/jp_llm/src/tool/decoding_tests.rs | 115 +++++++ ...5_forced_tool_soft_forces__raw_events.snap | 2 + ...t_multi_turn_conversation__raw_events.snap | 2 + .../test_tool_call_auto__raw_events.snap | 2 + .../test_tool_call_function__raw_events.snap | 2 + .../test_tool_call_reasoning__raw_events.snap | 2 + ...all_required_no_reasoning__raw_events.snap | 2 + ...l_call_required_reasoning__raw_events.snap | 2 + .../test_tool_call_stream__raw_events.snap | 2 + ...t_multi_turn_conversation__raw_events.snap | 2 + .../test_tool_call_auto__raw_events.snap | 2 + .../test_tool_call_function__raw_events.snap | 2 + .../test_tool_call_reasoning__raw_events.snap | 2 + ...all_required_no_reasoning__raw_events.snap | 2 + ...l_call_required_reasoning__raw_events.snap | 2 + .../test_tool_call_stream__raw_events.snap | 2 + ...t_multi_turn_conversation__raw_events.snap | 2 + .../test_tool_call_auto__raw_events.snap | 2 + .../test_tool_call_function__raw_events.snap | 2 + .../test_tool_call_reasoning__raw_events.snap | 2 + ...all_required_no_reasoning__raw_events.snap | 2 + ...l_call_required_reasoning__raw_events.snap | 2 + .../test_tool_call_stream__raw_events.snap | 2 + ...t_multi_turn_conversation__raw_events.snap | 10 + .../test_tool_call_auto__raw_events.snap | 10 + .../test_tool_call_function__raw_events.snap | 10 + .../test_tool_call_reasoning__raw_events.snap | 10 + ...all_required_no_reasoning__raw_events.snap | 10 + ...l_call_required_reasoning__raw_events.snap | 10 + .../test_tool_call_stream__raw_events.snap | 10 + ...t_multi_turn_conversation__raw_events.snap | 2 + .../test_tool_call_auto__raw_events.snap | 2 + .../test_tool_call_function__raw_events.snap | 2 + .../test_tool_call_reasoning__raw_events.snap | 2 + ...all_required_no_reasoning__raw_events.snap | 2 + ...l_call_required_reasoning__raw_events.snap | 2 + .../test_tool_call_stream__raw_events.snap | 2 + ...t_multi_turn_conversation__raw_events.snap | 10 + .../test_tool_call_auto__raw_events.snap | 10 + .../test_tool_call_function__raw_events.snap | 10 + .../test_tool_call_reasoning__raw_events.snap | 10 + ...all_required_no_reasoning__raw_events.snap | 10 + .../test_tool_call_stream__raw_events.snap | 10 + ..._parallel_tool_round_trip__raw_events.snap | 3 + ...t_multi_turn_conversation__raw_events.snap | 10 + .../test_tool_call_auto__raw_events.snap | 10 + .../test_tool_call_function__raw_events.snap | 10 + .../test_tool_call_reasoning__raw_events.snap | 10 + ...all_required_no_reasoning__raw_events.snap | 10 + .../test_tool_call_stream__raw_events.snap | 10 + ...-argument-constraints-before-every-disp.md | 22 ++ ...issions-through-references-and-composed.md | 37 +++ 67 files changed, 1032 insertions(+), 76 deletions(-) create mode 100644 crates/jp_llm/src/provider/tool_decoding_tests.rs create mode 100644 crates/jp_llm/src/tool/decoding.rs create mode 100644 crates/jp_llm/src/tool/decoding_tests.rs create mode 100644 docs/ticket/0h28vbn-decode-strict-tool-omissions-through-references-and-composed.md diff --git a/crates/jp_cli/src/cmd/query/turn_loop.rs b/crates/jp_cli/src/cmd/query/turn_loop.rs index 739ff2657..de13794d7 100644 --- a/crates/jp_cli/src/cmd/query/turn_loop.rs +++ b/crates/jp_cli/src/cmd/query/turn_loop.rs @@ -556,7 +556,7 @@ pub(super) async fn run_turn_loop( // buffer first so buffered text appears before the // "Calling tool" line (fixes Issue 1). if let Event::Part { - part: EventPart::ToolCall(ToolCallPart::Start { id, name }), + part: EventPart::ToolCall(ToolCallPart::Start { id, name, .. }), .. } = &event { diff --git a/crates/jp_llm/src/event.rs b/crates/jp_llm/src/event.rs index e12d2b0e5..1e988928b 100644 --- a/crates/jp_llm/src/event.rs +++ b/crates/jp_llm/src/event.rs @@ -1,6 +1,10 @@ +use std::sync::Arc; + use jp_conversation::{ConversationStream, OverlayAction, OverlayMatcher, OverlayPatch}; use serde_json::{Map, Value}; +use crate::tool::decoding::ArgumentDecoding; + /// Represents a completed event from the LLM. /// /// In the context of [`crate::Provider::chat_completion_stream`], individual @@ -110,6 +114,9 @@ pub enum ToolCallPart { /// Name of the tool to execute. name: String, + + /// Request-local decoding instructions, consumed before persistence. + decoding: Option>, }, /// A raw JSON chunk of tool call arguments. @@ -281,6 +288,7 @@ impl Event { part: EventPart::ToolCall(ToolCallPart::Start { id: id.into(), name: name.into(), + decoding: None, }), metadata: Map::new(), } diff --git a/crates/jp_llm/src/event_builder.rs b/crates/jp_llm/src/event_builder.rs index a01939e1b..430e1c176 100644 --- a/crates/jp_llm/src/event_builder.rs +++ b/crates/jp_llm/src/event_builder.rs @@ -31,7 +31,10 @@ //! arrives. //! The Flush after the last chunk marks the tool call as complete. -use std::collections::{HashMap, hash_map::Entry}; +use std::{ + collections::{HashMap, hash_map::Entry}, + sync::Arc, +}; use jp_conversation::{ ConversationEvent, @@ -40,7 +43,10 @@ use jp_conversation::{ use serde_json::{Map, Value}; use tracing::warn; -use crate::event::{Event, EventPart, ToolCallPart}; +use crate::{ + event::{Event, EventPart, ToolCallPart}, + tool::decoding::ArgumentDecoding, +}; /// Extract the structured JSON payload from a completed list of stream events. /// @@ -163,14 +169,16 @@ impl EventBuilder { Entry::Occupied(mut e) => e.get_mut().merge_tool_call_part(tool_call_part), Entry::Vacant(e) => { let buffer = match tool_call_part { - ToolCallPart::Start { id, name } => IndexBuffer::ToolCall { + ToolCallPart::Start { id, name, decoding } => IndexBuffer::ToolCall { id, name, + decoding, arguments_json: String::new(), }, ToolCallPart::ArgumentChunk(json) => IndexBuffer::ToolCall { id: String::new(), name: String::new(), + decoding: None, arguments_json: json, }, }; @@ -217,8 +225,9 @@ impl EventBuilder { id, name, arguments_json, + decoding, } => { - let arguments = if arguments_json.trim().is_empty() { + let mut arguments = if arguments_json.trim().is_empty() { serde_json::Map::new() } else { serde_json::from_str(&arguments_json).unwrap_or_else(|e| { @@ -226,6 +235,9 @@ impl EventBuilder { serde_json::Map::new() }) }; + if let Some(decoding) = decoding { + decoding.apply(&mut arguments); + } ConversationEvent::now(ToolCallRequest { id, name, @@ -361,6 +373,8 @@ enum IndexBuffer { name: String, /// Raw JSON arguments accumulated from chunks. arguments_json: String, + /// Decoding chosen by the first non-empty tool name. + decoding: Option>, }, /// Accumulates streamed JSON chunks for a structured response. /// @@ -380,6 +394,7 @@ impl IndexBuffer { id, name, arguments_json, + decoding, } = self else { warn!( @@ -393,12 +408,14 @@ impl IndexBuffer { ToolCallPart::Start { id: incoming_id, name: incoming_name, + decoding: incoming_decoding, } => { if id.is_empty() && !incoming_id.is_empty() { *id = incoming_id; } if name.is_empty() && !incoming_name.is_empty() { *name = incoming_name; + *decoding = incoming_decoding; } } ToolCallPart::ArgumentChunk(json) => { diff --git a/crates/jp_llm/src/event_builder_tests.rs b/crates/jp_llm/src/event_builder_tests.rs index 53c29896a..bea39af3e 100644 --- a/crates/jp_llm/src/event_builder_tests.rs +++ b/crates/jp_llm/src/event_builder_tests.rs @@ -45,6 +45,7 @@ fn test_handles_tool_call() { EventPart::ToolCall(ToolCallPart::Start { id: "call_1".into(), name: "test_tool".into(), + decoding: None, }), Map::new(), ); @@ -68,6 +69,7 @@ fn test_incomplete_tool_calls_skips_unnamed_buffers() { EventPart::ToolCall(ToolCallPart::Start { id: "call_1".into(), name: "fs_modify_file".into(), + decoding: None, }), Map::new(), ); @@ -95,6 +97,7 @@ fn test_merges_multi_part_tool_call() { EventPart::ToolCall(ToolCallPart::Start { id: "call_42".into(), name: "fs_create_file".into(), + decoding: None, }), Map::new(), ); @@ -128,6 +131,7 @@ fn test_multi_part_tool_call_first_write_wins_for_id_and_name() { EventPart::ToolCall(ToolCallPart::Start { id: "first_id".into(), name: "first_name".into(), + decoding: None, }), Map::new(), ); @@ -138,6 +142,7 @@ fn test_multi_part_tool_call_first_write_wins_for_id_and_name() { EventPart::ToolCall(ToolCallPart::Start { id: "second_id".into(), name: "second_name".into(), + decoding: None, }), Map::new(), ); @@ -437,6 +442,7 @@ fn drain_drops_incomplete_tool_call_but_keeps_partial_text() { EventPart::ToolCall(ToolCallPart::Start { id: "toolu_incomplete".into(), name: "some_tool".into(), + decoding: None, }), Map::new(), ); diff --git a/crates/jp_llm/src/provider.rs b/crates/jp_llm/src/provider.rs index caff8699f..ce1fb1003 100644 --- a/crates/jp_llm/src/provider.rs +++ b/crates/jp_llm/src/provider.rs @@ -140,6 +140,10 @@ pub(crate) fn trace_to_tmpfile(prefix: &str, value: &impl serde::Serialize) -> S } } +#[cfg(test)] +#[path = "provider/tool_decoding_tests.rs"] +mod tool_decoding_tests; + #[cfg(test)] #[path = "provider_tests.rs"] mod tests; diff --git a/crates/jp_llm/src/provider/llamacpp.rs b/crates/jp_llm/src/provider/llamacpp.rs index 35e244718..1a3f8013d 100644 --- a/crates/jp_llm/src/provider/llamacpp.rs +++ b/crates/jp_llm/src/provider/llamacpp.rs @@ -24,7 +24,7 @@ use tracing::{debug, trace, warn}; use super::{ EventStream, ModelDetails, - openai::parameters_with_strict_mode, + openai::parameters_with_decoding, openai_compat::{merge_consecutive_assistant_messages, parse_chunk}, }; use crate::{ @@ -33,7 +33,7 @@ use crate::{ provider::Provider, query::ChatQuery, stream::{aggregator::reasoning::ReasoningExtractor, with_tool_call_keepalive}, - tool::ToolDefinition, + tool::{ToolDefinition, decoding::ArgumentDecoders}, }; static PROVIDER: ProviderId = ProviderId::Llamacpp; @@ -93,7 +93,7 @@ impl Provider for Llamacpp { "Starting Llamacpp chat completion stream." ); - let (body, is_structured) = create_request(model, query)?; + let (body, is_structured, decoders) = create_request(model, query)?; trace!( body = serde_json::to_string(&body).unwrap_or_default(), @@ -113,10 +113,10 @@ impl Provider for Llamacpp { // silently re-issuing the request. es.set_retry_policy(Box::new(Never)); - Ok(with_tool_call_keepalive( + Ok(decoders.attach(with_tool_call_keepalive( assemble_event_stream(es, is_structured), TOOL_CALL_KEEPALIVE_INTERVAL, - )) + ))) } } @@ -414,7 +414,7 @@ impl Llamacpp { model: &ModelDetails, query: ChatQuery, ) -> Result { - let (request, _) = create_request(model, query)?; + let (request, ..) = create_request(model, query)?; Ok(request) } } @@ -422,8 +422,12 @@ impl Llamacpp { /// Build the JSON request body for the llama.cpp `/v1/chat/completions` /// endpoint. /// -/// Returns `(body, is_structured)`. -fn create_request(model: &ModelDetails, query: ChatQuery) -> Result<(Value, bool), Error> { +/// Returns the request, structured-output flag, and tool argument decoding +/// plans. +fn create_request( + model: &ModelDetails, + query: ChatQuery, +) -> Result<(Value, bool, ArgumentDecoders), Error> { let ChatQuery { thread, tools, @@ -483,7 +487,7 @@ fn create_request(model: &ModelDetails, query: ChatQuery) -> Result<(Value, bool } messages.extend(convert_events(parts.events)); - let converted_tools = convert_tools(tools, &tool_choice); + let (converted_tools, decoders) = convert_tools(tools, &tool_choice); let tool_choice_val = convert_tool_choice(&tool_choice); trace!( @@ -543,7 +547,7 @@ fn create_request(model: &ModelDetails, query: ChatQuery) -> Result<(Value, bool }); } - Ok((body, is_structured)) + Ok((body, is_structured, decoders)) } /// Convert system prompt parts into a list of JSON message values. @@ -608,25 +612,32 @@ fn convert_events(events: ConversationStream) -> Vec { /// If [`ToolChoice::Function`] is set, only include the named tool. llama.cpp /// doesn't support calling a specific tool by name, but it supports `required` /// mode, so we limit the tool list instead. -fn convert_tools(tools: Vec, tool_choice: &ToolChoice) -> Vec { - tools +fn convert_tools( + tools: Vec, + tool_choice: &ToolChoice, +) -> (Vec, ArgumentDecoders) { + let mut decoders = ArgumentDecoders::default(); + let tools = tools .into_iter() + .filter(|tool| match tool_choice { + ToolChoice::Function(req) => &tool.name == req, + _ => true, + }) .map(|tool| { + let (parameters, decoding) = parameters_with_decoding(&tool.parameters, true); + decoders.insert(&tool.name, decoding); json!({ "type": "function", "function": { "name": tool.name, "description": tool.docs.schema_description().unwrap_or_default(), - "parameters": parameters_with_strict_mode(&tool.parameters, true), + "parameters": parameters, "strict": true, }, }) }) - .filter(|tool| match tool_choice { - ToolChoice::Function(req) => tool["function"]["name"].as_str() == Some(req.as_str()), - _ => true, - }) - .collect() + .collect(); + (tools, decoders) } fn convert_tool_choice(choice: &ToolChoice) -> &str { diff --git a/crates/jp_llm/src/provider/llamacpp_tests.rs b/crates/jp_llm/src/provider/llamacpp_tests.rs index c6921ced0..fef58be2b 100644 --- a/crates/jp_llm/src/provider/llamacpp_tests.rs +++ b/crates/jp_llm/src/provider/llamacpp_tests.rs @@ -77,7 +77,7 @@ fn request_body( reasoning: Option, ) -> serde_json::Value { let details = ModelDetails::empty((PROVIDER, "Qwen3.5-9B-GGUF").try_into().unwrap()); - let (request, _) = create_request(&details, reasoning_query(reasoning)).unwrap(); + let (request, ..) = create_request(&details, reasoning_query(reasoning)).unwrap(); request } diff --git a/crates/jp_llm/src/provider/openai.rs b/crates/jp_llm/src/provider/openai.rs index e9e7409f3..5d78584e3 100644 --- a/crates/jp_llm/src/provider/openai.rs +++ b/crates/jp_llm/src/provider/openai.rs @@ -38,7 +38,11 @@ use crate::{ provider::trace_to_tmpfile, query::ChatQuery, stream::with_tool_call_keepalive, - tool::{ToolDefinition, json_schema}, + tool::{ + ToolDefinition, + decoding::{ArgumentDecoders, ArgumentDecoding}, + json_schema, + }, }; static PROVIDER: ProviderId = ProviderId::Openai; @@ -123,13 +127,15 @@ impl Provider for Openai { model: &ModelDetails, query: ChatQuery, ) -> Result { - let (request, is_structured, reasoning_enabled) = create_request(model, query)?; + let (request, is_structured, reasoning_enabled, decoders) = create_request(model, query)?; if model.features.contains(&STREAMING_UNSUPPORTED) { let response = self.client.create(request).await??; let events = map_non_streaming_response(response, is_structured, reasoning_enabled)?; - return Ok(stream::iter(events.into_iter().map(Ok::<_, StreamError>)).boxed()); + return Ok( + decoders.attach(stream::iter(events.into_iter().map(Ok::<_, StreamError>)).boxed()) + ); } let raw_stream = self @@ -141,10 +147,10 @@ impl Provider for Openai { .try_flatten() .boxed(); - Ok(with_tool_call_keepalive( + Ok(decoders.attach(with_tool_call_keepalive( raw_stream, TOOL_CALL_KEEPALIVE_INTERVAL, - )) + ))) } } @@ -346,9 +352,13 @@ impl Openai { /// Create a request for the given model and query details. /// -/// Returns `(request, is_structured, reasoning_enabled)`. +/// Returns the request, structured-output and reasoning flags, and tool +/// argument decoding plans. #[expect(clippy::too_many_lines)] -fn create_request(model: &ModelDetails, query: ChatQuery) -> Result<(Request, bool, bool)> { +fn create_request( + model: &ModelDetails, + query: ChatQuery, +) -> Result<(Request, bool, bool, ArgumentDecoders)> { let ChatQuery { thread, tools, @@ -572,13 +582,14 @@ fn create_request(model: &ModelDetails, query: ChatQuery) -> Result<(Request, bo }; messages.extend(convert_events(parts.events)); + let (tools, decoders) = convert_tools(tools); let request = Request { model: types::Model::Other(model.id.name.to_string()), input: types::Input::List(messages), include: reasoning_enabled.then_some(vec![Include::ReasoningEncryptedContent]), store: Some(false), tool_choice: Some(convert_tool_choice(tool_choice)), - tools: Some(convert_tools(tools)), + tools: Some(tools), temperature, reasoning, max_output_tokens: parameters.max_tokens.map(Into::into), @@ -614,7 +625,7 @@ fn create_request(model: &ModelDetails, query: ChatQuery) -> Result<(Request, bo "Request payload." ); - Ok((request, is_structured, reasoning_enabled)) + Ok((request, is_structured, reasoning_enabled, decoders)) } #[expect(clippy::too_many_lines)] @@ -1687,10 +1698,22 @@ fn ensure_strict_schema(schema: &mut Value) { process_strict(schema, &root); } -fn process_strict(schema: &mut Value, root: &Value) { +#[expect( + clippy::too_many_lines, + reason = "schema rewriting and its decoding instructions share one traversal" +)] +fn process_strict(schema: &mut Value, root: &Value) -> ArgumentDecoding { let Value::Object(map) = schema else { - return; + return ArgumentDecoding::default(); }; + let mut decoding = ArgumentDecoding::default(); + // Decoding references and general composition needs a branch-aware schema + // walk (T-0h28vbn). Leave those arguments untouched to avoid deleting nulls + // accepted by the source schema. + let skip_decoding = ["$ref", "allOf", "oneOf"] + .iter() + .any(|key| map.contains_key(*key)) + || map.get("anyOf").is_some_and(|v| !is_nullable_pair(v)); // 1. Recurse into $defs / definitions. for key in ["$defs", "definitions"] { @@ -1734,7 +1757,12 @@ fn process_strict(schema: &mut Value, root: &Value) { if let Some(Value::Object(props)) = map.get_mut("properties") { for key in &newly_required { if let Some(prop_schema) = props.get_mut(key) { - make_schema_nullable(prop_schema); + let can_decode = ["$ref", "allOf", "anyOf", "oneOf"] + .iter() + .all(|key| prop_schema.get(*key).is_none()); + if make_schema_nullable(prop_schema) && can_decode { + decoding.omit_null.push(key.clone()); + } } } } @@ -1743,16 +1771,27 @@ fn process_strict(schema: &mut Value, root: &Value) { // 3. Recurse into property values, items, and anyOf variants. if let Some(Value::Object(props)) = map.get_mut("properties") { - for prop_schema in props.values_mut() { - process_strict(prop_schema, root); + for (name, prop_schema) in props { + let plan = process_strict(prop_schema, root); + if !plan.is_empty() { + decoding.properties.insert(name.clone(), plan); + } } } if let Some(items) = map.get_mut("items") { - process_strict(items, root); + let plan = process_strict(items, root); + if !plan.is_empty() { + decoding.items = Some(Box::new(plan)); + } } if let Some(Value::Array(variants)) = map.get_mut("anyOf") { for variant in variants.iter_mut() { - process_strict(variant, root); + let plan = process_strict(variant, root); + if !skip_decoding { + decoding.omit_null.extend(plan.omit_null); + decoding.properties.extend(plan.properties); + decoding.items = decoding.items.or(plan.items); + } } } @@ -1792,11 +1831,29 @@ fn process_strict(schema: &mut Value, root: &Value) { *map = merged; // Re-run on the inlined result. process_strict(schema, root); - return; + return ArgumentDecoding::default(); } // Failed to resolve — put it back. map.insert("$ref".to_owned(), Value::String(ref_path)); } + if skip_decoding { + return ArgumentDecoding::default(); + } + decoding +} + +// A schema paired with bare null needs no branch selection for object or array +// values. This includes the wrappers introduced by make_schema_nullable. +fn is_nullable_pair(value: &Value) -> bool { + let Some(variants) = value.as_array() else { + return false; + }; + variants.len() == 2 + && variants.iter().any(|v| { + v.as_object().is_some_and(|m| { + m.len() == 1 && m.get("type").and_then(Value::as_str) == Some("null") + }) + }) } /// Resolve a JSON pointer against the root schema. @@ -1834,6 +1891,14 @@ fn convert_tool_choice(choice: ToolChoice) -> types::ToolChoice { /// /// See: pub(crate) fn parameters_with_strict_mode(parameters: &Value, strict: bool) -> Map { + parameters_with_decoding(parameters, strict).0 +} + +/// Encode parameters and retain the instructions for restoring omissions. +pub(crate) fn parameters_with_decoding( + parameters: &Value, + strict: bool, +) -> (Map, ArgumentDecoding) { let mut document = parameters.as_object().cloned().unwrap_or_default(); document.insert("type".to_owned(), "object".into()); @@ -1846,12 +1911,13 @@ pub(crate) fn parameters_with_strict_mode(parameters: &Value, strict: bool) -> M document.insert("additionalProperties".to_owned(), (!strict).into()); if !strict { - return document; + return (document, ArgumentDecoding::default()); } let mut document = Value::Object(document); - ensure_strict_schema(&mut document); - document.as_object().cloned().unwrap_or_default() + let root = document.clone(); + let decoding = process_strict(&mut document, &root); + (document.as_object().cloned().unwrap_or_default(), decoding) } /// Check whether a JSON schema `type` value includes `"object"`. @@ -1891,15 +1957,16 @@ const NULLABLE_OUTER_KEYS: &[&str] = &["description", "title", "default", "examp /// /// Idempotent: a schema that's already nullable (via either encoding) is /// returned unchanged. -fn make_schema_nullable(schema: &mut Value) { +/// Returns whether nullability was injected. +fn make_schema_nullable(schema: &mut Value) -> bool { let Value::Object(map) = schema else { - return; + return false; }; let Some(type_val) = map.get("type").cloned() else { // No `type` key — could be `anyOf` (already nullable) or `$ref`. // Nothing for us to inject here. - return; + return false; }; let already_nullable = match &type_val { @@ -1908,7 +1975,7 @@ fn make_schema_nullable(schema: &mut Value) { _ => false, }; if already_nullable { - return; + return false; } let is_structured = |t: &str| matches!(t, "array" | "object"); @@ -1930,9 +1997,9 @@ fn make_schema_nullable(schema: &mut Value) { arr.push("null".into()); map.insert("type".to_owned(), Value::Array(arr)); } - _ => {} + _ => return false, } - return; + return true; } // Structured: split the schema into a typed variant (everything @@ -1951,10 +2018,12 @@ fn make_schema_nullable(schema: &mut Value) { Value::Object(Map::from_iter([("type".to_owned(), "null".into())])), ]), ); + true } -fn convert_tools(tools: Vec) -> Vec { - tools +fn convert_tools(tools: Vec) -> (Vec, ArgumentDecoders) { + let mut decoders = ArgumentDecoders::default(); + let tools = tools .into_iter() .map(|tool| { // The strict subset requires a type on every property, which a @@ -1963,15 +2032,18 @@ fn convert_tools(tools: Vec) -> Vec { // sending it strict costs the whole request, and every other tool // in it. let strict = !json_schema::has_unconstrained_node(&tool.parameters); + let (parameters, decoding) = parameters_with_decoding(&tool.parameters, strict); + decoders.insert(&tool.name, decoding); types::Tool::Function { name: tool.name, strict, description: tool.docs.schema_description().map(str::to_owned), - parameters: parameters_with_strict_mode(&tool.parameters, strict).into(), + parameters: parameters.into(), } }) - .collect() + .collect(); + (tools, decoders) } /// Parse an OpenAI reasoning execution mode value (`standard` or `pro`). diff --git a/crates/jp_llm/src/provider/openai_tests.rs b/crates/jp_llm/src/provider/openai_tests.rs index 3ac6c7b8d..960ab20f2 100644 --- a/crates/jp_llm/src/provider/openai_tests.rs +++ b/crates/jp_llm/src/provider/openai_tests.rs @@ -328,7 +328,7 @@ mod convert_tools { /// One converted tool, as it goes on the wire. fn converted(parameters: serde_json::Value) -> serde_json::Value { - let tools = convert_tools(vec![ToolDefinition { + let (tools, _) = convert_tools(vec![ToolDefinition { name: "store".to_owned(), docs: ToolDocs::default(), parameters, diff --git a/crates/jp_llm/src/provider/openrouter.rs b/crates/jp_llm/src/provider/openrouter.rs index be47d0ca3..781fd1de1 100644 --- a/crates/jp_llm/src/provider/openrouter.rs +++ b/crates/jp_llm/src/provider/openrouter.rs @@ -43,9 +43,10 @@ use crate::{ event::{self, Event, EventPart, ToolCallPart}, event_builder::EventBuilder, model::ReasoningDetails as ModelReasoningDetails, - provider::{Provider, openai::parameters_with_strict_mode, trace_to_tmpfile}, + provider::{Provider, openai::parameters_with_decoding, trace_to_tmpfile}, query::ChatQuery, stream::with_tool_call_keepalive, + tool::{ToolDefinition, decoding::ArgumentDecoders}, }; static PROVIDER: ProviderId = ProviderId::Openrouter; @@ -141,14 +142,15 @@ impl Provider for Openrouter { model: &ModelDetails, query: ChatQuery, ) -> Result { - let (request, is_structured, forced_tool_fallback) = create_request(model, query)?; + let (request, is_structured, forced_tool_fallback, decoders) = + create_request(model, query)?; - Ok(call( + Ok(decoders.attach(call( self.client.clone(), request, is_structured, forced_tool_fallback, - )) + ))) } } @@ -667,7 +669,7 @@ impl Openrouter { model: &ModelDetails, query: ChatQuery, ) -> Result { - let (request, _, _) = create_request(model, query)?; + let (request, ..) = create_request(model, query)?; Ok(serde_json::to_value(request)?) } } @@ -732,14 +734,40 @@ fn force_nudge(choice: &tool::ToolChoice) -> String { } } +fn convert_tools(tools: Vec) -> (Vec, ArgumentDecoders) { + let mut decoders = ArgumentDecoders::default(); + let tools = tools + .into_iter() + .map(|tool| { + let (parameters, decoding) = parameters_with_decoding(&tool.parameters, true); + decoders.insert(&tool.name, decoding); + Tool::Function { + function: ToolFunction { + parameters, + name: tool.name, + description: tool.docs.schema_description().map(str::to_owned), + strict: true, + }, + } + }) + .collect(); + (tools, decoders) +} + /// Create the request for the OpenRouter API. /// /// Returns the request, whether structured output is active, and any fallback -/// required because reasoning prevents a forced tool choice on the wire. +/// required because reasoning prevents a forced tool choice on the wire, +/// followed by the tool argument decoding plans. fn create_request( model: &ModelDetails, query: ChatQuery, -) -> Result<(request::ChatCompletion, bool, Option)> { +) -> Result<( + request::ChatCompletion, + bool, + Option, + ArgumentDecoders, +)> { let ChatQuery { thread, tools, @@ -766,17 +794,7 @@ fn create_request( let reasoning = model.custom_reasoning_config(parameters.reasoning); let mut messages: RequestMessages = (&model.id, thread).try_into()?; - let tools = tools - .into_iter() - .map(|tool| Tool::Function { - function: ToolFunction { - parameters: parameters_with_strict_mode(&tool.parameters, true), - name: tool.name, - description: tool.docs.schema_description().map(str::to_owned), - strict: true, - }, - }) - .collect::>(); + let (tools, decoders) = convert_tools(tools); let thinking_active = reasoning.is_some() || model .reasoning @@ -852,6 +870,7 @@ fn create_request( }, is_structured, forced_tool_fallback, + decoders, )) } diff --git a/crates/jp_llm/src/provider/openrouter_tests.rs b/crates/jp_llm/src/provider/openrouter_tests.rs index 3540ae7d9..6656dd6b2 100644 --- a/crates/jp_llm/src/provider/openrouter_tests.rs +++ b/crates/jp_llm/src/provider/openrouter_tests.rs @@ -170,7 +170,7 @@ fn request_preserves_integer_tool_parameter_type() -> Result { unreachable!(); }; - let (request, _, _) = create_request(&model, query)?; + let (request, ..) = create_request(&model, query)?; let request = serde_json::to_value(request)?; assert_eq!( @@ -369,7 +369,7 @@ fn forced_tool_request( }; model.reasoning = Some(reasoning); - let (request, _, fallback) = create_request(&model, query).unwrap(); + let (request, _, fallback, _) = create_request(&model, query).unwrap(); (request, fallback) } diff --git a/crates/jp_llm/src/provider/tool_decoding_tests.rs b/crates/jp_llm/src/provider/tool_decoding_tests.rs new file mode 100644 index 000000000..0d15bcd13 --- /dev/null +++ b/crates/jp_llm/src/provider/tool_decoding_tests.rs @@ -0,0 +1,302 @@ +use futures::{StreamExt as _, stream}; +use jp_config::{model::id::ProviderId, providers::llm::LlmProviderConfig}; +use jp_conversation::{ConversationStream, thread::ThreadBuilder}; +use jp_test::mock::{MockServer, POST}; +use serde_json::{Value, json}; + +use super::{get_provider, openai::parameters_with_decoding}; +use crate::{ + EventStream, + event::Event, + event_builder::EventBuilder, + model::ModelDetails, + query::ChatQuery, + tool::{ToolDefinition, ToolDocs, decoding::ArgumentDecoders}, +}; + +async fn assemble(schema: &Value, strict: bool, arguments: &str) -> Value { + let (_parameters, decoding) = parameters_with_decoding(schema, strict); + let mut decoders = ArgumentDecoders::default(); + decoders.insert("search", decoding); + let events: EventStream = stream::iter(vec![ + Ok(Event::tool_call_start(0, "call_1", "search")), + Ok(Event::tool_call_args(0, arguments)), + Ok(Event::flush(0)), + ]) + .boxed(); + let mut events = decoders.attach(events); + let mut builder = EventBuilder::new(); + let mut requests = vec![]; + while let Some(event) = events.next().await { + match event.unwrap() { + Event::Part { + index, + part, + metadata, + } => builder.handle_part(index, part, metadata), + Event::Flush { index, metadata } => { + let event = builder.handle_flush(index, metadata).unwrap(); + let request = event.into_tool_call_request().unwrap(); + assert_eq!(request.id, "call_1"); + assert_eq!(request.name, "search"); + requests.push(Value::Object(request.arguments)); + } + _ => panic!("unexpected event"), + } + } + assert_eq!(requests.len(), 1); + requests.remove(0) +} + +#[tokio::test] +async fn strict_tool_omission_round_trip() { + let schema = json!({ + "type": "object", + "required": ["query"], + "properties": { + "query": {"type": "string"}, + "kinds": {"type": "array", "items": {"type": "string"}, "default": ["Function"]}, + "version": {"type": "string", "default": "latest"} + } + }); + assert_eq!( + assemble( + &schema, + true, + r#"{"query":"parse_document","kinds":null,"version":null}"# + ) + .await, + json!({"query": "parse_document"}) + ); +} + +#[tokio::test] +async fn strict_tool_preserves_source_nulls_and_explicit_values() { + let schema = json!({ + "type": "object", + "required": ["required"], + "properties": { + "required": {"type": "string"}, + "nullable": {"type": ["string", "null"], "default": "fallback"}, + "union": {"anyOf": [{"type": "string"}, {"type": "null"}]}, + "kinds": {"type": "array", "items": {"type": "string"}} + } + }); + assert_eq!( + assemble( + &schema, + true, + r#"{"required":null,"nullable":null,"union":null,"kinds":[]}"# + ) + .await, + json!({"required": null, "nullable": null, "union": null, "kinds": []}) + ); +} + +#[tokio::test] +async fn strict_tool_decodes_nested_objects_and_array_items() { + let schema = json!({ + "type": "object", + "properties": { + "options": {"type": "object", "properties": {"limit": {"type": "integer"}}}, + "rows": {"type": "array", "items": { + "type": "object", "properties": {"label": {"type": "string"}} + }} + } + }); + assert_eq!( + assemble( + &schema, + true, + r#"{"options":{"limit":null},"rows":[{"label":null},{"label":"kept"},null]}"# + ) + .await, + json!({"options": {}, "rows": [{}, {"label": "kept"}, null]}) + ); +} + +const OPENAI_CALL: &str = r#"event: response.output_item.added +data: {"type":"response.output_item.added","output_index":0,"sequence_number":0,"item":{"type":"function_call","id":"fc_1","call_id":"call_1","name":"search","arguments":""}} + +event: response.function_call_arguments.delta +data: {"type":"response.function_call_arguments.delta","item_id":"fc_1","output_index":0,"sequence_number":1,"delta":"{\"query\":\"parse_document\",\"kinds\":null}"} + +event: response.output_item.done +data: {"type":"response.output_item.done","output_index":0,"sequence_number":2,"item":{"type":"function_call","id":"fc_1","call_id":"call_1","name":"search","arguments":"{\"query\":\"parse_document\",\"kinds\":null}","status":"completed"}} + +"#; + +const CHAT_CALL: &str = r#"data: {"id":"chat_1","object":"chat.completion.chunk","created":0,"model":"test","provider":"test","choices":[{"index":0,"delta":{"role":"assistant","tool_calls":[{"index":0,"id":"call_1","type":"function","function":{"name":"search","arguments":"{\"query\":\"parse_document\",\"kinds\":null}"}}]},"finish_reason":null}]} + +data: {"id":"chat_1","object":"chat.completion.chunk","created":0,"model":"test","provider":"test","choices":[{"index":0,"delta":{},"finish_reason":"tool_calls"}]} + +data: [DONE] + +"#; + +async fn provider_round_trip(provider_id: ProviderId, body: &'static str, streaming: bool) { + let server = MockServer::start_async().await; + let endpoint = server + .mock_async(|when, then| { + when.method(POST); + then.status(200) + .header( + "content-type", + if streaming { + "text/event-stream" + } else { + "application/json" + }, + ) + .body(body); + }) + .await; + let mut config = LlmProviderConfig::default(); + let key_env = if cfg!(windows) { "USERNAME" } else { "USER" }; + config.openai.api_key_env = key_env.to_owned(); + config.openai.base_url_env = String::new(); + config.openai.base_url = server.base_url(); + config.openrouter.api_key_env = key_env.to_owned(); + config.openrouter.base_url = server.base_url(); + config.llamacpp.base_url = server.base_url(); + let provider = get_provider(provider_id, &config).unwrap(); + let mut model = ModelDetails::empty((provider_id, "test").try_into().unwrap()); + if !streaming { + model.features.push("streaming_unsupported"); + } + let thread = ThreadBuilder::new() + .with_events(ConversationStream::new_test().with_turn("search")) + .build() + .unwrap(); + let mut query = ChatQuery::from(thread); + query.tools.push(ToolDefinition { + name: "search".to_owned(), + docs: ToolDocs::default(), + parameters: json!({ + "type": "object", "required": ["query"], + "properties": { + "query": {"type": "string"}, + "kinds": {"type": "array", "items": {"$ref": "#/$defs/Kind"}} + }, + "$defs": {"Kind": {"type": "string", "enum": ["Function"]}} + }), + }); + let mut events = provider + .chat_completion_stream(&model, query) + .await + .unwrap(); + let mut builder = EventBuilder::new(); + let mut requests = vec![]; + while let Some(event) = events.next().await { + match event.unwrap() { + Event::Part { + index, + part, + metadata, + } => builder.handle_part(index, part, metadata), + Event::Flush { index, metadata } => { + if let Some(event) = builder.handle_flush(index, metadata) { + assert!(event.metadata.is_empty()); + requests.push(event.into_tool_call_request().unwrap().arguments); + } + } + Event::Finished(_) | Event::KeepAlive => {} + Event::Patch(_) => panic!("unexpected patch"), + } + } + assert_eq!(endpoint.calls_async().await, 1); + assert_eq!(requests, vec![ + json!({"query": "parse_document"}) + .as_object() + .unwrap() + .clone() + ]); +} + +#[tokio::test] +async fn openai_decodes_before_tool_dispatch() { + provider_round_trip(ProviderId::Openai, OPENAI_CALL, true).await; +} + +#[tokio::test] +async fn openrouter_decodes_before_tool_dispatch() { + provider_round_trip(ProviderId::Openrouter, CHAT_CALL, true).await; +} + +#[tokio::test] +async fn llamacpp_decodes_before_tool_dispatch() { + provider_round_trip(ProviderId::Llamacpp, CHAT_CALL, true).await; +} + +#[tokio::test] +async fn openai_non_streaming_decodes_before_tool_dispatch() { + provider_round_trip( + ProviderId::Openai, + r#"{ + "id": "resp_1", "object": "response", "created_at": 0, + "status": "completed", "model": "test", "error": null, + "incomplete_details": null, "instructions": null, "metadata": {}, + "output": [{"type": "function_call", "id": "fc_1", "call_id": "call_1", + "name": "search", "arguments": "{\"query\":\"parse_document\",\"kinds\":null}", + "status": "completed"}], + "parallel_tool_calls": true, "temperature": 1, "top_p": 1, + "tool_choice": "auto", "tools": [], "usage": null, + "reasoning": {}, "text": {"format": {"type": "text"}}, + "truncation": "disabled", "store": false + }"#, + false, + ) + .await; +} + +#[tokio::test] +async fn reference_and_composition_paths_remain_undecoded() { + let schema = json!({ + "type": "object", + "properties": { + "inline": {"type": "string"}, + "referenced": {"$ref": "#/$defs/Options"}, + "composed": {"anyOf": [ + {"type": "object", "properties": {"value": {"type": "string"}}}, + {"type": "object", "required": ["value"], "properties": {"value": {"type": "null"}}} + ]} + }, + "$defs": {"Options": {"type": "object", "properties": {"value": {"type": "string"}}}} + }); + assert_eq!( + assemble( + &schema, + true, + r#"{"inline":null,"referenced":{"value":null},"composed":{"value":null}}"# + ) + .await, + json!({"referenced": {"value": null}, "composed": {"value": null}}) + ); +} + +#[tokio::test] +async fn nullable_object_preserves_null_but_decodes_its_properties() { + let schema = json!({ + "type": "object", "properties": { + "absent": {"anyOf": [ + {"type": "object", "properties": {"value": {"type": "string"}}}, {"type": "null"} + ]}, + "present": {"anyOf": [ + {"type": "object", "properties": {"value": {"type": "string"}}}, {"type": "null"} + ]} + } + }); + assert_eq!( + assemble(&schema, true, r#"{"absent":null,"present":{"value":null}}"#).await, + json!({"absent": null, "present": {}}) + ); +} + +#[tokio::test] +async fn non_strict_tool_keeps_nulls() { + let schema = json!({"type": "object", "properties": {"query": {"type": "string"}}}); + assert_eq!( + assemble(&schema, false, r#"{"query":null}"#).await, + json!({"query": null}) + ); +} diff --git a/crates/jp_llm/src/stream.rs b/crates/jp_llm/src/stream.rs index 3fb887bf0..c12c9725d 100644 --- a/crates/jp_llm/src/stream.rs +++ b/crates/jp_llm/src/stream.rs @@ -164,7 +164,7 @@ fn content_byte_size(item: &Result) -> u64 { | EventPart::Reasoning(text) | EventPart::Structured(text) => text.len(), EventPart::ToolCall(ToolCallPart::ArgumentChunk(json)) => json.len(), - EventPart::ToolCall(ToolCallPart::Start { id, name }) => id.len() + name.len(), + EventPart::ToolCall(ToolCallPart::Start { id, name, .. }) => id.len() + name.len(), }; content + metadata_byte_size(metadata) diff --git a/crates/jp_llm/src/tool.rs b/crates/jp_llm/src/tool.rs index da9db388f..ff21bf5d3 100644 --- a/crates/jp_llm/src/tool.rs +++ b/crates/jp_llm/src/tool.rs @@ -1,6 +1,7 @@ //! Tool call utilities. pub mod builtin; +pub mod decoding; pub mod executor; pub mod json_schema; diff --git a/crates/jp_llm/src/tool/decoding.rs b/crates/jp_llm/src/tool/decoding.rs new file mode 100644 index 000000000..afb11cb5b --- /dev/null +++ b/crates/jp_llm/src/tool/decoding.rs @@ -0,0 +1,91 @@ +//! Request-local instructions for decoding provider tool arguments. +//! +//! Providers attach a plan to a tool call's start. +//! The event builder applies it to the completed JSON object before +//! constructing the tool call request. + +use std::{collections::BTreeMap, sync::Arc}; + +use futures::StreamExt as _; +use serde_json::{Map, Value}; + +use crate::{ + EventStream, + event::{Event, EventPart, ToolCallPart}, +}; + +/// Removes null placeholders introduced by a provider's schema encoding. +/// +/// This is transient request state, not part of a persisted tool call. +/// Fields not named by the plan retain their values, including explicit nulls. +#[derive(Debug, Clone, Default, PartialEq)] +pub struct ArgumentDecoding { + pub(crate) omit_null: Vec, + pub(crate) properties: BTreeMap, + pub(crate) items: Option>, +} + +impl ArgumentDecoding { + pub(crate) fn is_empty(&self) -> bool { + self.omit_null.is_empty() && self.properties.is_empty() && self.items.is_none() + } + + pub(crate) fn apply(&self, arguments: &mut Map) { + for name in &self.omit_null { + if arguments.get(name) == Some(&Value::Null) { + arguments.remove(name); + } + } + for (name, plan) in &self.properties { + if let Some(value) = arguments.get_mut(name) { + plan.apply_value(value); + } + } + } + + fn apply_value(&self, value: &mut Value) { + match value { + Value::Object(arguments) => self.apply(arguments), + Value::Array(values) => { + if let Some(items) = &self.items { + for value in values { + items.apply_value(value); + } + } + } + _ => {} + } + } +} + +/// Decoding plans for the tools advertised in one provider request. +#[derive(Debug, Default)] +pub(crate) struct ArgumentDecoders(BTreeMap>); + +impl ArgumentDecoders { + pub(crate) fn insert(&mut self, name: &str, plan: ArgumentDecoding) { + if !plan.is_empty() { + self.0.insert(name.to_owned(), Arc::new(plan)); + } + } + + /// Attach plans without buffering or changing generated argument chunks. + pub(crate) fn attach(self, stream: EventStream) -> EventStream { + stream + .map(move |mut event| { + if let Ok(Event::Part { + part: EventPart::ToolCall(ToolCallPart::Start { name, decoding, .. }), + .. + }) = &mut event + { + *decoding = self.0.get(name).cloned(); + } + event + }) + .boxed() + } +} + +#[cfg(test)] +#[path = "decoding_tests.rs"] +mod tests; diff --git a/crates/jp_llm/src/tool/decoding_tests.rs b/crates/jp_llm/src/tool/decoding_tests.rs new file mode 100644 index 000000000..62aea2666 --- /dev/null +++ b/crates/jp_llm/src/tool/decoding_tests.rs @@ -0,0 +1,115 @@ +use futures::{StreamExt as _, stream}; +use serde_json::{Map, Value, json}; + +use super::*; +use crate::{StreamError, StreamErrorKind, event::FinishReason, event_builder::EventBuilder}; + +#[tokio::test] +async fn plans_follow_tool_names_across_interleaved_calls() { + let mut decoders = ArgumentDecoders::default(); + decoders.insert("search", ArgumentDecoding { + omit_null: vec!["kinds".to_owned()], + ..ArgumentDecoding::default() + }); + let mut events = decoders.attach( + stream::iter(vec![ + Ok(Event::tool_call_start(0, "call_1", "search")), + Ok(Event::tool_call_start(1, "call_2", "other")), + Ok(Event::tool_call_args(0, r#"{"kinds":"#)), + Ok(Event::tool_call_args(1, r#"{"kinds":null}"#)), + Ok(Event::tool_call_start(0, "ignored", "other")), + Ok(Event::tool_call_args(0, "null}")), + Ok(Event::flush(1)), + Ok(Event::flush(0)), + ]) + .boxed(), + ); + let mut builder = EventBuilder::new(); + let mut calls = vec![]; + while let Some(event) = events.next().await { + match event.unwrap() { + Event::Part { + index, + part, + metadata, + } => builder.handle_part(index, part, metadata), + Event::Flush { index, metadata } => { + let event = builder.handle_flush(index, metadata).unwrap(); + assert_eq!(event.metadata, Map::new()); + let call = event.into_tool_call_request().unwrap(); + calls.push(json!({"id": call.id, "name": call.name, "arguments": call.arguments})); + } + _ => panic!("unexpected event"), + } + } + assert_eq!(calls, vec![ + json!({"id": "call_2", "name": "other", "arguments": {"kinds": null}}), + json!({"id": "call_1", "name": "search", "arguments": {}}), + ]); +} + +#[tokio::test] +async fn decoding_does_not_hide_chunks_errors_or_incomplete_calls() { + let mut decoders = ArgumentDecoders::default(); + decoders.insert("search", ArgumentDecoding { + omit_null: vec!["kinds".to_owned()], + ..ArgumentDecoding::default() + }); + let mut events = decoders.attach( + stream::iter(vec![ + Ok(Event::tool_call_start(0, "call_1", "search")), + Ok(Event::tool_call_args(0, r#"{"kinds":n"#)), + Err(StreamError::timeout("fixture timeout")), + Ok(Event::Finished(FinishReason::MaxTokens)), + ]) + .boxed(), + ); + let mut builder = EventBuilder::new(); + let Event::Part { + index, + part, + metadata, + } = events.next().await.unwrap().unwrap() + else { + panic!("expected start"); + }; + builder.handle_part(index, part, metadata); + let chunk = events.next().await.unwrap().unwrap(); + assert_eq!(chunk, Event::tool_call_args(0, r#"{"kinds":n"#)); + let Event::Part { + index, + part, + metadata, + } = chunk + else { + panic!("expected chunk"); + }; + builder.handle_part(index, part, metadata); + let error = events.next().await.unwrap().unwrap_err(); + assert_eq!(error.kind, StreamErrorKind::Timeout); + assert_eq!(error.message(), "fixture timeout"); + assert_eq!( + events.next().await.unwrap().unwrap(), + Event::Finished(FinishReason::MaxTokens) + ); + assert!(events.next().await.is_none()); + assert_eq!(builder.incomplete_tool_calls(), vec!["search"]); + assert_eq!(builder.drain(), vec![]); +} + +#[test] +fn explicit_values_are_preserved() { + let plan = ArgumentDecoding { + omit_null: vec!["kinds".to_owned()], + ..ArgumentDecoding::default() + }; + let mut arguments = json!({"kinds": ["Function"], "nullable": null}) + .as_object() + .unwrap() + .clone(); + plan.apply(&mut arguments); + assert_eq!( + Value::Object(arguments), + json!({"kinds": ["Function"], "nullable": null}) + ); +} diff --git a/crates/jp_llm/tests/fixtures/anthropic/test_fable_5_forced_tool_soft_forces__raw_events.snap b/crates/jp_llm/tests/fixtures/anthropic/test_fable_5_forced_tool_soft_forces__raw_events.snap index 536d06c7d..5173db49e 100644 --- a/crates/jp_llm/tests/fixtures/anthropic/test_fable_5_forced_tool_soft_forces__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/anthropic/test_fable_5_forced_tool_soft_forces__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -10,6 +11,7 @@ expression: v Start { id: "toolu_01DYRwPNeF44tkkTHK9GZLXv", name: "run_me", + decoding: None, }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/anthropic/test_multi_turn_conversation__raw_events.snap b/crates/jp_llm/tests/fixtures/anthropic/test_multi_turn_conversation__raw_events.snap index 8fa1d01b0..aac5f3e16 100644 --- a/crates/jp_llm/tests/fixtures/anthropic/test_multi_turn_conversation__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/anthropic/test_multi_turn_conversation__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -99,6 +100,7 @@ expression: v Start { id: "toolu_01XwmS4LqFiZwtZ7Myyhc48y", name: "run_me", + decoding: None, }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/anthropic/test_tool_call_auto__raw_events.snap b/crates/jp_llm/tests/fixtures/anthropic/test_tool_call_auto__raw_events.snap index e547eb9ed..258cf4fa2 100644 --- a/crates/jp_llm/tests/fixtures/anthropic/test_tool_call_auto__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/anthropic/test_tool_call_auto__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -10,6 +11,7 @@ expression: v Start { id: "toolu_01JAHJz5uuvrjHRutexsopKE", name: "run_me", + decoding: None, }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/anthropic/test_tool_call_function__raw_events.snap b/crates/jp_llm/tests/fixtures/anthropic/test_tool_call_function__raw_events.snap index 06a06821a..56b12fc1e 100644 --- a/crates/jp_llm/tests/fixtures/anthropic/test_tool_call_function__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/anthropic/test_tool_call_function__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -10,6 +11,7 @@ expression: v Start { id: "toolu_015nmxweBaM2MUfdypoenU31", name: "run_me", + decoding: None, }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/anthropic/test_tool_call_reasoning__raw_events.snap b/crates/jp_llm/tests/fixtures/anthropic/test_tool_call_reasoning__raw_events.snap index d3a0c3a1f..f6830b2f3 100644 --- a/crates/jp_llm/tests/fixtures/anthropic/test_tool_call_reasoning__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/anthropic/test_tool_call_reasoning__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -129,6 +130,7 @@ expression: v Start { id: "toolu_01R35dJ1FaGkcNPmGqF2NfSA", name: "run_me", + decoding: None, }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/anthropic/test_tool_call_required_no_reasoning__raw_events.snap b/crates/jp_llm/tests/fixtures/anthropic/test_tool_call_required_no_reasoning__raw_events.snap index 93423f07d..a8fa82f4f 100644 --- a/crates/jp_llm/tests/fixtures/anthropic/test_tool_call_required_no_reasoning__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/anthropic/test_tool_call_required_no_reasoning__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -10,6 +11,7 @@ expression: v Start { id: "toolu_019hRf3U5xzJoV7ufpEPgXT2", name: "run_me", + decoding: None, }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/anthropic/test_tool_call_required_reasoning__raw_events.snap b/crates/jp_llm/tests/fixtures/anthropic/test_tool_call_required_reasoning__raw_events.snap index 9ff6ca97f..5980714be 100644 --- a/crates/jp_llm/tests/fixtures/anthropic/test_tool_call_required_reasoning__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/anthropic/test_tool_call_required_reasoning__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -80,6 +81,7 @@ expression: v Start { id: "toolu_015TdjGwt7Sj5EmKZmHcjmqC", name: "run_me", + decoding: None, }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/anthropic/test_tool_call_stream__raw_events.snap b/crates/jp_llm/tests/fixtures/anthropic/test_tool_call_stream__raw_events.snap index 9b939162b..a2a864faa 100644 --- a/crates/jp_llm/tests/fixtures/anthropic/test_tool_call_stream__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/anthropic/test_tool_call_stream__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -10,6 +11,7 @@ expression: v Start { id: "toolu_0133DM77y4tmYgkWRtGNPpxa", name: "run_me", + decoding: None, }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/cerebras/test_multi_turn_conversation__raw_events.snap b/crates/jp_llm/tests/fixtures/cerebras/test_multi_turn_conversation__raw_events.snap index 7e4674584..982c1bb56 100644 --- a/crates/jp_llm/tests/fixtures/cerebras/test_multi_turn_conversation__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/cerebras/test_multi_turn_conversation__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -250,6 +251,7 @@ expression: v Start { id: "0bb7d840a", name: "run_me", + decoding: None, }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/cerebras/test_tool_call_auto__raw_events.snap b/crates/jp_llm/tests/fixtures/cerebras/test_tool_call_auto__raw_events.snap index 9d331c4b9..3a61bd820 100644 --- a/crates/jp_llm/tests/fixtures/cerebras/test_tool_call_auto__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/cerebras/test_tool_call_auto__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -84,6 +85,7 @@ expression: v Start { id: "ad7b0fd0d", name: "run_me", + decoding: None, }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/cerebras/test_tool_call_function__raw_events.snap b/crates/jp_llm/tests/fixtures/cerebras/test_tool_call_function__raw_events.snap index ad9126d8b..645485e07 100644 --- a/crates/jp_llm/tests/fixtures/cerebras/test_tool_call_function__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/cerebras/test_tool_call_function__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -84,6 +85,7 @@ expression: v Start { id: "ebed658c3", name: "run_me", + decoding: None, }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/cerebras/test_tool_call_reasoning__raw_events.snap b/crates/jp_llm/tests/fixtures/cerebras/test_tool_call_reasoning__raw_events.snap index 6ef4d08ca..833cf3c53 100644 --- a/crates/jp_llm/tests/fixtures/cerebras/test_tool_call_reasoning__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/cerebras/test_tool_call_reasoning__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -35,6 +36,7 @@ expression: v Start { id: "f8afbdfcc", name: "run_me", + decoding: None, }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/cerebras/test_tool_call_required_no_reasoning__raw_events.snap b/crates/jp_llm/tests/fixtures/cerebras/test_tool_call_required_no_reasoning__raw_events.snap index 467ce0041..69c8dd113 100644 --- a/crates/jp_llm/tests/fixtures/cerebras/test_tool_call_required_no_reasoning__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/cerebras/test_tool_call_required_no_reasoning__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -84,6 +85,7 @@ expression: v Start { id: "9ad7c9ddd", name: "run_me", + decoding: None, }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/cerebras/test_tool_call_required_reasoning__raw_events.snap b/crates/jp_llm/tests/fixtures/cerebras/test_tool_call_required_reasoning__raw_events.snap index 8ce0d3538..4f7d48707 100644 --- a/crates/jp_llm/tests/fixtures/cerebras/test_tool_call_required_reasoning__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/cerebras/test_tool_call_required_reasoning__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -35,6 +36,7 @@ expression: v Start { id: "885f4bbdf", name: "run_me", + decoding: None, }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/cerebras/test_tool_call_stream__raw_events.snap b/crates/jp_llm/tests/fixtures/cerebras/test_tool_call_stream__raw_events.snap index 3a79bf081..4f96e6d46 100644 --- a/crates/jp_llm/tests/fixtures/cerebras/test_tool_call_stream__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/cerebras/test_tool_call_stream__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -91,6 +92,7 @@ expression: v Start { id: "08d59c72f", name: "run_me", + decoding: None, }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/google/test_multi_turn_conversation__raw_events.snap b/crates/jp_llm/tests/fixtures/google/test_multi_turn_conversation__raw_events.snap index 2e0dc9dc2..fa62c57d5 100644 --- a/crates/jp_llm/tests/fixtures/google/test_multi_turn_conversation__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/google/test_multi_turn_conversation__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -53,6 +54,7 @@ expression: v Start { id: "run_me_0", name: "run_me", + decoding: None, }, ), metadata: { diff --git a/crates/jp_llm/tests/fixtures/google/test_tool_call_auto__raw_events.snap b/crates/jp_llm/tests/fixtures/google/test_tool_call_auto__raw_events.snap index 09cd89b2e..40b1c46c8 100644 --- a/crates/jp_llm/tests/fixtures/google/test_tool_call_auto__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/google/test_tool_call_auto__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -10,6 +11,7 @@ expression: v Start { id: "run_me_0", name: "run_me", + decoding: None, }, ), metadata: { diff --git a/crates/jp_llm/tests/fixtures/google/test_tool_call_function__raw_events.snap b/crates/jp_llm/tests/fixtures/google/test_tool_call_function__raw_events.snap index 6e5f44456..c781b310a 100644 --- a/crates/jp_llm/tests/fixtures/google/test_tool_call_function__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/google/test_tool_call_function__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -10,6 +11,7 @@ expression: v Start { id: "run_me_0", name: "run_me", + decoding: None, }, ), metadata: { diff --git a/crates/jp_llm/tests/fixtures/google/test_tool_call_reasoning__raw_events.snap b/crates/jp_llm/tests/fixtures/google/test_tool_call_reasoning__raw_events.snap index c6ad98fde..9e5500347 100644 --- a/crates/jp_llm/tests/fixtures/google/test_tool_call_reasoning__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/google/test_tool_call_reasoning__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -28,6 +29,7 @@ expression: v Start { id: "run_me_1", name: "run_me", + decoding: None, }, ), metadata: { diff --git a/crates/jp_llm/tests/fixtures/google/test_tool_call_required_no_reasoning__raw_events.snap b/crates/jp_llm/tests/fixtures/google/test_tool_call_required_no_reasoning__raw_events.snap index 2da957bb1..712a30538 100644 --- a/crates/jp_llm/tests/fixtures/google/test_tool_call_required_no_reasoning__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/google/test_tool_call_required_no_reasoning__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -10,6 +11,7 @@ expression: v Start { id: "run_me_0", name: "run_me", + decoding: None, }, ), metadata: { diff --git a/crates/jp_llm/tests/fixtures/google/test_tool_call_required_reasoning__raw_events.snap b/crates/jp_llm/tests/fixtures/google/test_tool_call_required_reasoning__raw_events.snap index 193f1aa2a..3b69db2c0 100644 --- a/crates/jp_llm/tests/fixtures/google/test_tool_call_required_reasoning__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/google/test_tool_call_required_reasoning__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -28,6 +29,7 @@ expression: v Start { id: "run_me_1", name: "run_me", + decoding: None, }, ), metadata: { diff --git a/crates/jp_llm/tests/fixtures/google/test_tool_call_stream__raw_events.snap b/crates/jp_llm/tests/fixtures/google/test_tool_call_stream__raw_events.snap index ed48bdc05..d516aca1c 100644 --- a/crates/jp_llm/tests/fixtures/google/test_tool_call_stream__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/google/test_tool_call_stream__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -10,6 +11,7 @@ expression: v Start { id: "run_me_0", name: "run_me", + decoding: None, }, ), metadata: { diff --git a/crates/jp_llm/tests/fixtures/llamacpp/test_multi_turn_conversation__raw_events.snap b/crates/jp_llm/tests/fixtures/llamacpp/test_multi_turn_conversation__raw_events.snap index 35ec6b84f..935792fdb 100644 --- a/crates/jp_llm/tests/fixtures/llamacpp/test_multi_turn_conversation__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/llamacpp/test_multi_turn_conversation__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -1923,6 +1924,15 @@ expression: v Start { id: "3025kzfSjn1Q76fmpkjrrvhmMOFjumOt", name: "run_me", + decoding: Some( + ArgumentDecoding { + omit_null: [ + "foo", + ], + properties: {}, + items: None, + }, + ), }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/llamacpp/test_tool_call_auto__raw_events.snap b/crates/jp_llm/tests/fixtures/llamacpp/test_tool_call_auto__raw_events.snap index 8ba92a7a8..51cdf7920 100644 --- a/crates/jp_llm/tests/fixtures/llamacpp/test_tool_call_auto__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/llamacpp/test_tool_call_auto__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -14,6 +15,15 @@ expression: v Start { id: "XKlv3S6qUhMOu2TFBjOi50mehedlfHVg", name: "run_me", + decoding: Some( + ArgumentDecoding { + omit_null: [ + "foo", + ], + properties: {}, + items: None, + }, + ), }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/llamacpp/test_tool_call_function__raw_events.snap b/crates/jp_llm/tests/fixtures/llamacpp/test_tool_call_function__raw_events.snap index 0cb60e311..64dcdf46a 100644 --- a/crates/jp_llm/tests/fixtures/llamacpp/test_tool_call_function__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/llamacpp/test_tool_call_function__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -14,6 +15,15 @@ expression: v Start { id: "10C5kzdXGxswu3Mf4kc59YGXJwe2Wh6Q", name: "run_me", + decoding: Some( + ArgumentDecoding { + omit_null: [ + "foo", + ], + properties: {}, + items: None, + }, + ), }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/llamacpp/test_tool_call_reasoning__raw_events.snap b/crates/jp_llm/tests/fixtures/llamacpp/test_tool_call_reasoning__raw_events.snap index 81d173729..a23a67540 100644 --- a/crates/jp_llm/tests/fixtures/llamacpp/test_tool_call_reasoning__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/llamacpp/test_tool_call_reasoning__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -833,6 +834,15 @@ expression: v Start { id: "qCRtO6khmonFfDo1uuz8gSBVczLWJhCp", name: "run_me", + decoding: Some( + ArgumentDecoding { + omit_null: [ + "foo", + ], + properties: {}, + items: None, + }, + ), }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/llamacpp/test_tool_call_required_no_reasoning__raw_events.snap b/crates/jp_llm/tests/fixtures/llamacpp/test_tool_call_required_no_reasoning__raw_events.snap index 09d41092a..e07b320bd 100644 --- a/crates/jp_llm/tests/fixtures/llamacpp/test_tool_call_required_no_reasoning__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/llamacpp/test_tool_call_required_no_reasoning__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -14,6 +15,15 @@ expression: v Start { id: "YVmI1CdVad59bsgXRfMOXYcxpo9gAv88", name: "run_me", + decoding: Some( + ArgumentDecoding { + omit_null: [ + "foo", + ], + properties: {}, + items: None, + }, + ), }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/llamacpp/test_tool_call_required_reasoning__raw_events.snap b/crates/jp_llm/tests/fixtures/llamacpp/test_tool_call_required_reasoning__raw_events.snap index 64edb2d30..fe273138d 100644 --- a/crates/jp_llm/tests/fixtures/llamacpp/test_tool_call_required_reasoning__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/llamacpp/test_tool_call_required_reasoning__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -1036,6 +1037,15 @@ expression: v Start { id: "n19Zg7uRIClo8uT6BobGdBU6pPoBmbMu", name: "run_me", + decoding: Some( + ArgumentDecoding { + omit_null: [ + "foo", + ], + properties: {}, + items: None, + }, + ), }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/llamacpp/test_tool_call_stream__raw_events.snap b/crates/jp_llm/tests/fixtures/llamacpp/test_tool_call_stream__raw_events.snap index dc6456595..d8efbdb59 100644 --- a/crates/jp_llm/tests/fixtures/llamacpp/test_tool_call_stream__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/llamacpp/test_tool_call_stream__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -14,6 +15,15 @@ expression: v Start { id: "FpyxzrUobenAo9FIhFP3Z8FnxbvMV4L9", name: "run_me", + decoding: Some( + ArgumentDecoding { + omit_null: [ + "foo", + ], + properties: {}, + items: None, + }, + ), }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/ollama/test_multi_turn_conversation__raw_events.snap b/crates/jp_llm/tests/fixtures/ollama/test_multi_turn_conversation__raw_events.snap index a4963dec1..9a785a366 100644 --- a/crates/jp_llm/tests/fixtures/ollama/test_multi_turn_conversation__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/ollama/test_multi_turn_conversation__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -103059,6 +103060,7 @@ expression: v Start { id: "run_me_2", name: "run_me", + decoding: None, }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/ollama/test_tool_call_auto__raw_events.snap b/crates/jp_llm/tests/fixtures/ollama/test_tool_call_auto__raw_events.snap index 957c09833..55fcae839 100644 --- a/crates/jp_llm/tests/fixtures/ollama/test_tool_call_auto__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/ollama/test_tool_call_auto__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -14,6 +15,7 @@ expression: v Start { id: "run_me_2", name: "run_me", + decoding: None, }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/ollama/test_tool_call_function__raw_events.snap b/crates/jp_llm/tests/fixtures/ollama/test_tool_call_function__raw_events.snap index bb9288dec..cbcba472e 100644 --- a/crates/jp_llm/tests/fixtures/ollama/test_tool_call_function__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/ollama/test_tool_call_function__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -14,6 +15,7 @@ expression: v Start { id: "run_me_2", name: "run_me", + decoding: None, }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/ollama/test_tool_call_reasoning__raw_events.snap b/crates/jp_llm/tests/fixtures/ollama/test_tool_call_reasoning__raw_events.snap index bdbb83183..dc0707fe2 100644 --- a/crates/jp_llm/tests/fixtures/ollama/test_tool_call_reasoning__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/ollama/test_tool_call_reasoning__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -1736,6 +1737,7 @@ expression: v Start { id: "run_me_2", name: "run_me", + decoding: None, }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/ollama/test_tool_call_required_no_reasoning__raw_events.snap b/crates/jp_llm/tests/fixtures/ollama/test_tool_call_required_no_reasoning__raw_events.snap index e05853177..3debbe294 100644 --- a/crates/jp_llm/tests/fixtures/ollama/test_tool_call_required_no_reasoning__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/ollama/test_tool_call_required_no_reasoning__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -14,6 +15,7 @@ expression: v Start { id: "run_me_2", name: "run_me", + decoding: None, }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/ollama/test_tool_call_required_reasoning__raw_events.snap b/crates/jp_llm/tests/fixtures/ollama/test_tool_call_required_reasoning__raw_events.snap index 02372d67b..aaa3b866f 100644 --- a/crates/jp_llm/tests/fixtures/ollama/test_tool_call_required_reasoning__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/ollama/test_tool_call_required_reasoning__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -1645,6 +1646,7 @@ expression: v Start { id: "run_me_2", name: "run_me", + decoding: None, }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/ollama/test_tool_call_stream__raw_events.snap b/crates/jp_llm/tests/fixtures/ollama/test_tool_call_stream__raw_events.snap index d1a3d3963..929da8d03 100644 --- a/crates/jp_llm/tests/fixtures/ollama/test_tool_call_stream__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/ollama/test_tool_call_stream__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -14,6 +15,7 @@ expression: v Start { id: "run_me_2", name: "run_me", + decoding: None, }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/openai/test_multi_turn_conversation__raw_events.snap b/crates/jp_llm/tests/fixtures/openai/test_multi_turn_conversation__raw_events.snap index fa16b006a..8043857cf 100644 --- a/crates/jp_llm/tests/fixtures/openai/test_multi_turn_conversation__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/openai/test_multi_turn_conversation__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -697,6 +698,15 @@ expression: v Start { id: "call_aGqFUSwEmeqvj7EMW7rPrTsW", name: "run_me", + decoding: Some( + ArgumentDecoding { + omit_null: [ + "foo", + ], + properties: {}, + items: None, + }, + ), }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/openai/test_tool_call_auto__raw_events.snap b/crates/jp_llm/tests/fixtures/openai/test_tool_call_auto__raw_events.snap index 72b1c84c5..ff202998a 100644 --- a/crates/jp_llm/tests/fixtures/openai/test_tool_call_auto__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/openai/test_tool_call_auto__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -10,6 +11,15 @@ expression: v Start { id: "call_9pIO9rxD5iBgHYWii3HGpW8u", name: "run_me", + decoding: Some( + ArgumentDecoding { + omit_null: [ + "foo", + ], + properties: {}, + items: None, + }, + ), }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/openai/test_tool_call_function__raw_events.snap b/crates/jp_llm/tests/fixtures/openai/test_tool_call_function__raw_events.snap index fab321309..0d64eb201 100644 --- a/crates/jp_llm/tests/fixtures/openai/test_tool_call_function__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/openai/test_tool_call_function__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -10,6 +11,15 @@ expression: v Start { id: "call_O3ByNtUdUxXx7MatyW9beYgO", name: "run_me", + decoding: Some( + ArgumentDecoding { + omit_null: [ + "foo", + ], + properties: {}, + items: None, + }, + ), }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/openai/test_tool_call_reasoning__raw_events.snap b/crates/jp_llm/tests/fixtures/openai/test_tool_call_reasoning__raw_events.snap index 0a309ea52..e30b41704 100644 --- a/crates/jp_llm/tests/fixtures/openai/test_tool_call_reasoning__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/openai/test_tool_call_reasoning__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -24,6 +25,15 @@ expression: v Start { id: "call_S4y869TTmCcKjpUrCzlx64iI", name: "run_me", + decoding: Some( + ArgumentDecoding { + omit_null: [ + "foo", + ], + properties: {}, + items: None, + }, + ), }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/openai/test_tool_call_required_no_reasoning__raw_events.snap b/crates/jp_llm/tests/fixtures/openai/test_tool_call_required_no_reasoning__raw_events.snap index b139a39e2..66df76ca8 100644 --- a/crates/jp_llm/tests/fixtures/openai/test_tool_call_required_no_reasoning__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/openai/test_tool_call_required_no_reasoning__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -10,6 +11,15 @@ expression: v Start { id: "call_JJxtV1WBiRq4s9iMKiH2Hv5s", name: "run_me", + decoding: Some( + ArgumentDecoding { + omit_null: [ + "foo", + ], + properties: {}, + items: None, + }, + ), }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/openai/test_tool_call_stream__raw_events.snap b/crates/jp_llm/tests/fixtures/openai/test_tool_call_stream__raw_events.snap index 99775e0c3..ee29dc047 100644 --- a/crates/jp_llm/tests/fixtures/openai/test_tool_call_stream__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/openai/test_tool_call_stream__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -10,6 +11,15 @@ expression: v Start { id: "call_QVPVzLo15uyHKtD1NPj8MGFL", name: "run_me", + decoding: Some( + ArgumentDecoding { + omit_null: [ + "foo", + ], + properties: {}, + items: None, + }, + ), }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/openrouter/test_anthropic_opus_5_parallel_tool_round_trip__raw_events.snap b/crates/jp_llm/tests/fixtures/openrouter/test_anthropic_opus_5_parallel_tool_round_trip__raw_events.snap index 57463f722..0f2194679 100644 --- a/crates/jp_llm/tests/fixtures/openrouter/test_anthropic_opus_5_parallel_tool_round_trip__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/openrouter/test_anthropic_opus_5_parallel_tool_round_trip__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -24,6 +25,7 @@ expression: v Start { id: "toolu_01Uo9BabQqLmAaDofViBHLT3", name: "list_items", + decoding: None, }, ), metadata: {}, @@ -61,6 +63,7 @@ expression: v Start { id: "toolu_01KpNDwzcdeVXYC3VR9x8Rcu", name: "search_items", + decoding: None, }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/openrouter/test_multi_turn_conversation__raw_events.snap b/crates/jp_llm/tests/fixtures/openrouter/test_multi_turn_conversation__raw_events.snap index b8610a607..8051d6348 100644 --- a/crates/jp_llm/tests/fixtures/openrouter/test_multi_turn_conversation__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/openrouter/test_multi_turn_conversation__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -196,6 +197,15 @@ expression: v Start { id: "call_ASyCmpktnp9V9J73QldUIcMS", name: "run_me", + decoding: Some( + ArgumentDecoding { + omit_null: [ + "foo", + ], + properties: {}, + items: None, + }, + ), }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_auto__raw_events.snap b/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_auto__raw_events.snap index c65cd31b8..015e30894 100644 --- a/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_auto__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_auto__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -26,6 +27,15 @@ expression: v Start { id: "call_LpP8nONS14vigHaa7spwH7CP", name: "run_me", + decoding: Some( + ArgumentDecoding { + omit_null: [ + "foo", + ], + properties: {}, + items: None, + }, + ), }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_function__raw_events.snap b/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_function__raw_events.snap index be1f72bbe..b2336f0b3 100644 --- a/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_function__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_function__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -26,6 +27,15 @@ expression: v Start { id: "call_hc6YFtXUxRuIeZQJpV6PxwL1", name: "run_me", + decoding: Some( + ArgumentDecoding { + omit_null: [ + "foo", + ], + properties: {}, + items: None, + }, + ), }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_reasoning__raw_events.snap b/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_reasoning__raw_events.snap index 172d9ec0d..a0c447cfe 100644 --- a/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_reasoning__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_reasoning__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -26,6 +27,15 @@ expression: v Start { id: "call_rOan8lBVArGt59QeqLVYGJRB", name: "run_me", + decoding: Some( + ArgumentDecoding { + omit_null: [ + "foo", + ], + properties: {}, + items: None, + }, + ), }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_required_no_reasoning__raw_events.snap b/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_required_no_reasoning__raw_events.snap index d3d53ab15..e4de99bef 100644 --- a/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_required_no_reasoning__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_required_no_reasoning__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -26,6 +27,15 @@ expression: v Start { id: "call_WKBmpxCWQlHgotW4KaaM3jsY", name: "run_me", + decoding: Some( + ArgumentDecoding { + omit_null: [ + "foo", + ], + properties: {}, + items: None, + }, + ), }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_stream__raw_events.snap b/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_stream__raw_events.snap index 7c661c62d..93df8cb08 100644 --- a/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_stream__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_stream__raw_events.snap @@ -1,5 +1,6 @@ --- source: crates/jp_test/src/mock.rs +assertion_line: 134 expression: v --- [ @@ -26,6 +27,15 @@ expression: v Start { id: "call_tCr2HKeu326bnT2x94xswLYz", name: "run_me", + decoding: Some( + ArgumentDecoding { + omit_null: [ + "foo", + ], + properties: {}, + items: None, + }, + ), }, ), metadata: {}, diff --git a/docs/ticket/063sw1z-enforce-resolved-tool-argument-constraints-before-every-disp.md b/docs/ticket/063sw1z-enforce-resolved-tool-argument-constraints-before-every-disp.md index 98f49dbd0..bc35dd80a 100644 --- a/docs/ticket/063sw1z-enforce-resolved-tool-argument-constraints-before-every-disp.md +++ b/docs/ticket/063sw1z-enforce-resolved-tool-argument-constraints-before-every-disp.md @@ -39,3 +39,25 @@ Acceptance criteria: - Add tests using invalid calls taken from the Cerebras, Google, and llama.cpp fixtures. - Add tests proving MCP and built-in parameter overrides are enforced. + +## Comments + +----- + +- **From**: jp +- **Date**: 2026-09-11T09:24:02Z + +Implemented the strict-provider omission-decoding portion in the working tree: +request-local plans are produced by schema conversion, attached to transient +tool-call starts, and consumed by EventBuilder before constructing +ToolCallRequest. +OpenAI (streaming and non-streaming), OpenRouter, and llama.cpp are wired. +Source-nullable values and required properties are preserved; no generic null +repair or MCP default injection was added. + +Reference and general composition decoding remains explicitly deferred to +T-0h28vbn. +Shared dispatch validation and default-policy work in this ticket remain open. + +The new decoding tests were observed failing before the fix and pass after it. +Existing strict-schema, event-builder, and CLI turn-loop tests pass. diff --git a/docs/ticket/0h28vbn-decode-strict-tool-omissions-through-references-and-composed.md b/docs/ticket/0h28vbn-decode-strict-tool-omissions-through-references-and-composed.md new file mode 100644 index 000000000..57fa2b51e --- /dev/null +++ b/docs/ticket/0h28vbn-decode-strict-tool-omissions-through-references-and-composed.md @@ -0,0 +1,37 @@ +# Decode strict-tool omissions through references and composed schemas + +- **Status**: Todo +- **Kind**: Bug +- **Authors**: jp +- **Date**: 2026-09-11 +- **Label**: domain=llm +- **Label**: package=jp_llm +- **Label**: type=follow-up + +Strict-provider tool argument decoding currently covers inline properties, +nested objects, array items, and a simple anyOf nullable wrapper. +It deliberately leaves decoding paths through `$ref`, `allOf`, `oneOf`, and +general `anyOf` unions untouched. +An optional inline array whose item schema uses `$ref` can still be omitted; the +gap is decoding within the referenced schema or an optional property itself +declared through a reference. + +Address this in a separate PR that reviews reference resolution and composition +handling together across the existing schema reader and strict-provider +conversion. +Do not introduce a second reference resolver solely for argument decoding. + +Preserve source-accepted null values and required fields. +Record omission instructions only where the outgoing provider encoding actually +introduces an omission placeholder. +Cover shared and recursive definitions, reference siblings, escaped JSON +pointers, and branch-dependent property requirements. +Keep the source schema unchanged and pin provider schema output alongside +decoded argument outcomes. + +The existing strict converter also cannot inject nullability into a standalone +`$ref` or an untyped general union. +Review that encoding gap together with decoding rather than treating every null +at a referenced optional property as omission. + +Related: T-063sw1z (shared argument validation). From fc412af16be97e1fc3554e10c2a7d215ad1cf6ca Mon Sep 17 00:00:00 2001 From: Jean Mertz Date: Fri, 11 Sep 2026 12:50:34 +0200 Subject: [PATCH 2/2] fixup! fix(llm, openai, openrouter, llamacpp): Decode nulls Signed-off-by: Jean Mertz --- .../test_tool_call_required_reasoning.snap | 14 +- .../test_tool_call_required_reasoning.yml | 365 ++-------- ...quired_reasoning__conversation_stream.snap | 16 +- ...l_call_required_reasoning__raw_events.snap | 679 +----------------- .../test_tool_call_required_reasoning.snap | 13 +- .../test_tool_call_required_reasoning.yml | 138 ++-- ...quired_reasoning__conversation_stream.snap | 15 +- ...l_call_required_reasoning__raw_events.snap | 216 ++---- 8 files changed, 205 insertions(+), 1251 deletions(-) diff --git a/crates/jp_llm/tests/fixtures/openai/test_tool_call_required_reasoning.snap b/crates/jp_llm/tests/fixtures/openai/test_tool_call_required_reasoning.snap index 0189862ab..1c0fc98eb 100644 --- a/crates/jp_llm/tests/fixtures/openai/test_tool_call_required_reasoning.snap +++ b/crates/jp_llm/tests/fixtures/openai/test_tool_call_required_reasoning.snap @@ -9,12 +9,12 @@ expression: v timestamp: 2020-01-01 0:00:00.0 +00, kind: ChatResponse( Reasoning { - reasoning: "**Analyzing tool call options**\n\nI need to call a tool, specifically functions.run_me, which requires setting the \"bar\" parameter as \"foo,\" but \"foo\" can be null or a string. I’m considering whether to use multi_tool_use.parallel for multiple calls, but it only works for functions tools. Since it seems simpler, I'll just call functions.run_me directly and use the commentary channel for this. My plan is to call it with \"foo\" set to null.", + reasoning: "", }, ), metadata: { - "openai_item_id": String("rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27"), - "openai_encrypted_content": String("gAAAAABqiG2xnaWTAwVx7x04cr5y6QDQVOvd0elZQTGi27BcEUr3BIG0OaUr9VTFqfuknzmuUOavCeWmcVTREMX-RQg5Y8TrIutPPGnT7yBlav4wNbnt0YEw_xf-TD5pHla9ZMNaMkxEDkfqfBVpc_y22tSXK4bku-LzAqdkjwX6dVehYXW0RYScYXn0iyPNoObad6kD74ijzhATuTjGtzH-l4aXN2L-7cVy5HmNo15lm_XSwyyya1NN7_Ao-i9yl8C7rKi9GvZwSsuT34h8RL5jRxiBx6-pTir687fabzxY4yh4XwnmUFFn_VWahwklsH_w7K5as_fT4LkDffQsY8xl9tM_yALD3iRcobeE_EXGZvbBmyC7X2s19Q5LCSYKMsWS15c6sYQNUSMQE5fCyOIxruJbDzTBwRdFKM9ZAM5UaY8QZYFXKpQpKQ-KnzSCyj7JFiohHNVnrGnQ0kRmtO759gRah49w1sait_tY2UKhS6DP18XDOw1PlznJTNto_uDNLSxNZg6z87wbu1jbuT2EBeiPXQ_hXrRk0HbFo6cx3W8YdAoIBJaFZS-3o6NhtHmLdsv2x2pH54AZ9VIz2lLS2J5E5O3bwKSRPAFu8PPAyKNZrs3oZe6LxXburqbNDtn_-9P2SEPLy_LJLDTBtoumsI3OWhxI-2-z8YIzdXjM1hqY_klki_nQDxRZTeRA2PHT7i_0mGEB2m16fId4AuNrRRetO_GBW55Tq1pNddZTNrPVEX9iT2CM5OB5fI6mV9kxAnxIszBMC8ffsho3FUgTpdyBjDn0Rw6PpDCBg543CV2QR_1rGujxMUqgLdydxT5VM0QlnoiWS9KcMZssvCCwkGvjXJjllynbNWuuK62K9IWXV3skFXXD5wuc2LbzbcwUczDzkeO0Bbu6et-P4fRDd5ZxMFz_uzE1ZK1MHIpQ0kX_DDsFi1frDziQ9yi4pXg7j4S1IoyCSXwqEQDf7KTnVW1KU70J1SLND_5dxNk_UZDRVvHItBHwykE1udDh-4xB_YUX9ifWM0NI6QkCoG1HgwdTQY_l3rxLDG4ISE5arr_Tw5CjfhpX19wBwPhqtB3ESeQH6utkPkKg1Z2A7ouf2VbXkV6prHR9sNmOrAe2RvZzqRor4cft3TfHVp-euRKDL3iPVjrwLC-OVsHPGniIiS6U3wsdi67JDEQrLoparVTSIMi3A8NMed371UrjLWlGGfICGJPy6TV9YJzQx4zhFhTNvueKBZrMlts8DF9GVKqv8UDsfxEW_xxIGkSwSl2UjmRzkFEWLGov-q5D_g7_0cEFCN2bo3ui5AZI5lv12EoM7P9pbORxh71hT0cn7GTm7Avl1_lJdlBhlSu1-pT_jWgpJAtem_6T0sUrB9kcgu3jFJbWhuD6KM1ZG_0xB35F-u7UzKO1H4yVlWQDMTje3OXZwpFE7fhVwTWHfa80EriyB9ZHKMdAkNI0baeB59lZrx1FPu9YLxvtp0793KLM4J7_qIKJhp0ZVR4Dxy9UE1lInJUXeqTN0mm5t3fBN6HayQjxZ-P5P-gbXm8xUxgrP69PvdBb32Hggs4hzw0KwGRsRED-nR_PVY5MTGILs7mV_Me9EPLrisJdAqE0d3Km7zrc643HY9_rpuLiAzqxr35ZbP8pzkCQlXoxPB-Zam_pxq8EJ1RoX3BGukvoo1D83VulqsCFS_yQpUat-mq40nNfeSquHs0="), + "openai_item_id": String("rs_025af4c5cac58077016aa3da898c1c87d2884e863491b22f1e"), + "openai_encrypted_content": String("gAAAAABqo9qNBxdNxVsQFw3IkPtx5IABI1oS9N0q9ZETVVaMQ9cndEcwqgj4DPO3BetQ7QFz-_M4Tq9mnBhUWVOXnH0bnpG6-TUTl-hp891X6tA8UcS4GZ-IJN367seyr8fw_NdlASDZxk4udZ9s74lMPIBpknpXXAYyb3zPuW4NEkaihiavxPIVct8_4-UqgPhdcOC5MIQcb1SbYCVuSY9UEjf4f0MSsIdyWkkseoyWQ0IxxDD9WwxBU9lfidHUIa2XiNBoC0RvaUHD0qMYXCO21SGLbgpDzUuvOw9vU1Uv3Xx9_YXkw3k8PO0tSs0gn2ssoA1p8qaZBQ7i1q8LbWfnHKtupjf6X3svacq9ZNuviqmpCtTBEN_IHbwMg79hSMQ6ua7Fmnbfjx6x-6PRCuqO-Babp_cGKsEEx04D87xj5gg3xMxUIWEBV8uBxxfyUfVjQ5wIYaCYxfGVQlQbYAQfnUzVy36KPCearWOgLUFSnbufcFBylbwTo98PIx4I9yjc-MH3Hr_ZnhNWBx3SRudQ1R6L_HX9VdjUhuNyZUHFEbxWztQ45waQDkqR-6dv2ZX4Dvks_vy93WvqeFJSH4u8zB5CesLjNv8fe5n3tlNywKXwk2mEttMAmTENeYqiZIorcHQngPwOBTkRElJYpK9xZkll1QAIffgVdQF7-pV83PNgyLJU2aOzFS30iUsfKGv_A4YHsX5q1xjAmF20-r7oGMRnDHTyVQc1ucMMyudDbtJMrn6jAAp-eVZrZY2kJsfGI4XlMYLzDtAKz1zwkaPVkjDzcElBG9yUKHcnYgEEs5PSVUpqGz-tdzv4K_qtfhTG58E3_hRTco3IlGizrOn6W_HL8OKgsn-QmwQnetHaraeKM8vBUYjxpwEL9o3E6zG0wCsldhCferQ1UnCDrjtP8xi3X7Qq2JWgoZ5fA0BG0TQLaDOQF0dm-JPxN0SD1PC5f3I3UbVd7cdSfSx-8tipbq81xRDuoDikQv2oBhfxFZUkKtffvz8F45NJSrnK3m5pLosYavq8sLLFCkSs1u5k8KcHsvllV0L0cVA4EGxcZ2u2WcvFUhxM7wYwk3d6C6UmlOP1GB0aUZmUgPt4R9o8wLoS9_srWWWpIQ04WQn9p-qroX59bBnUConqlXJR3edcN9U2Np3P_b7xvDNwjHV3FLe7kq0bE31iZDPMJCiDcy8axHs4-OcDapHsPCn5wzLvOjjAssM9HCE_NDA_uOuazBGYDkZyLqxqRze5QBlqiO8_skgjBUsAkCKrhCXEaVrAVGoIxRi0uj-d9XnuBaay5fRiy69n2bySeR9uNqYXlPb-ZvOAJSRgwlf5KEIywq_-c_BMlMngj7hzx_TmXTdTxd5CnICuFYX6zbVFsOHwF5s7hSM1HFaKf10Kkm0HNrrl_einA8i-xpq5djHV0bhBmqVEPVdgUwvSXHoASRjkcAbj72PPE464NLieXJrMRCsQ5d9VTyOOPIjgscY6xwNfOtUrMmBHIeR54DqWn3Vumf9hJs8u_htWxUWvJnUWDLo8kxEiKfnB_I5Mjw5xwYlWzQ26iBWUisBBLSrH5m7xHjwfuc0-pNs4A0oOE8Ud2S7XTFEIUOX92VAjFwDga3sUiCgVWvGed1FwIdOTZvuI_Tu6wHfkuBrKHKacX7G4WCGX9qlGVG3mtf5iP06cGK-mfdyfK6xhICY4WDefitSsPJss0NpI5vqT0N_gLBEZU5kl_7EFp1TIr593MYp9cb0C9UmLZ3ReaLZXbPwFyXOCT6ipgn2Homo="), }, }, ), @@ -23,10 +23,10 @@ expression: v timestamp: 2020-01-01 0:00:00.0 +00, kind: ToolCallRequest( ToolCallRequest { - id: "call_i95it8x7WlrY7fZeliTs6shY", + id: "call_1W5hSpB0eF8Xllvo5dyLR65p", name: "run_me", arguments: { - "foo": Null, + "foo": String("example input"), "bar": String("foo"), }, }, @@ -44,11 +44,11 @@ expression: v timestamp: 2020-01-01 0:00:00.0 +00, kind: ChatResponse( Message { - message: "Done — the tool returned: \"working!\"", + message: "Tool run completed. Output: \"working!\"", }, ), metadata: { - "openai_item_id": String("msg_02702adc8fbb7a3a016a886db2cc3487d293743440c7837e04"), + "openai_item_id": String("msg_025af4c5cac58077016aa3da8db40887d2ae1be5affa1d6db4"), }, }, ), diff --git a/crates/jp_llm/tests/fixtures/openai/test_tool_call_required_reasoning.yml b/crates/jp_llm/tests/fixtures/openai/test_tool_call_required_reasoning.yml index 2f3c4829e..d91730fcb 100644 --- a/crates/jp_llm/tests/fixtures/openai/test_tool_call_required_reasoning.yml +++ b/crates/jp_llm/tests/fixtures/openai/test_tool_call_required_reasoning.yml @@ -87,337 +87,58 @@ then: value: text/event-stream; charset=utf-8 body: |+ event: response.created - data: {"type":"response.created","response":{"id":"resp_02702adc8fbb7a3a016a886dad9d9487d2a68983a3b99abd6f","object":"response","created_at":1787325869,"status":"in_progress","background":false,"completed_at":null,"error":null,"frequency_penalty":0.0,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"max_tool_calls":null,"model":"gpt-5-mini-2025-08-07","moderation":null,"output":[],"parallel_tool_calls":true,"presence_penalty":0.0,"previous_response_id":null,"prompt_cache_key":"jp:conversation:1577836800000000","prompt_cache_retention":"in_memory","reasoning":{"context":"current_turn","effort":"low","mode":"standard","summary":"detailed"},"safety_identifier":null,"service_tier":"auto","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"required","tool_usage":{"image_gen":{"input_tokens":0,"input_tokens_details":{"image_tokens":0,"text_tokens":0},"output_tokens":0,"output_tokens_details":{"image_tokens":0,"text_tokens":0},"total_tokens":0},"web_search":{"num_requests":0}},"tools":[{"type":"function","description":null,"name":"run_me","output_schema":null,"parameters":{"type":"object","properties":{"foo":{"type":["string","null"],"default":"foo"},"bar":{"type":["string","array"],"enum":["foo"],"items":{"type":"string","enum":["foo","bar"]}}},"required":["foo","bar"],"additionalProperties":false},"strict":true}],"top_logprobs":0,"top_p":1.0,"truncation":"auto","usage":null,"user":null,"metadata":{}},"sequence_number":0} + data: {"type":"response.created","response":{"id":"resp_025af4c5cac58077016aa3da88e8bc87d2b70d6deed2655855","object":"response","created_at":1789123208,"status":"in_progress","background":false,"completed_at":null,"error":null,"frequency_penalty":0.0,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"max_tool_calls":null,"model":"gpt-5-mini-2025-08-07","moderation":null,"output":[],"parallel_tool_calls":true,"presence_penalty":0.0,"previous_response_id":null,"prompt_cache_key":"jp:conversation:1577836800000000","prompt_cache_retention":"in_memory","reasoning":{"context":"current_turn","effort":"low","mode":"standard","summary":"detailed"},"safety_identifier":null,"service_tier":"auto","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"required","tool_usage":{"image_gen":{"input_tokens":0,"input_tokens_details":{"image_tokens":0,"text_tokens":0},"output_tokens":0,"output_tokens_details":{"image_tokens":0,"text_tokens":0},"total_tokens":0},"web_search":{"num_requests":0}},"tools":[{"type":"function","description":null,"name":"run_me","output_schema":null,"parameters":{"type":"object","properties":{"foo":{"type":["string","null"],"default":"foo"},"bar":{"type":["string","array"],"enum":["foo"],"items":{"type":"string","enum":["foo","bar"]}}},"required":["foo","bar"],"additionalProperties":false},"strict":true}],"top_logprobs":0,"top_p":1.0,"truncation":"auto","usage":null,"user":null,"metadata":{}},"sequence_number":0} event: response.in_progress - data: {"type":"response.in_progress","response":{"id":"resp_02702adc8fbb7a3a016a886dad9d9487d2a68983a3b99abd6f","object":"response","created_at":1787325869,"status":"in_progress","background":false,"completed_at":null,"error":null,"frequency_penalty":0.0,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"max_tool_calls":null,"model":"gpt-5-mini-2025-08-07","moderation":null,"output":[],"parallel_tool_calls":true,"presence_penalty":0.0,"previous_response_id":null,"prompt_cache_key":"jp:conversation:1577836800000000","prompt_cache_retention":"in_memory","reasoning":{"context":"current_turn","effort":"low","mode":"standard","summary":"detailed"},"safety_identifier":null,"service_tier":"auto","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"required","tool_usage":{"image_gen":{"input_tokens":0,"input_tokens_details":{"image_tokens":0,"text_tokens":0},"output_tokens":0,"output_tokens_details":{"image_tokens":0,"text_tokens":0},"total_tokens":0},"web_search":{"num_requests":0}},"tools":[{"type":"function","description":null,"name":"run_me","output_schema":null,"parameters":{"type":"object","properties":{"foo":{"type":["string","null"],"default":"foo"},"bar":{"type":["string","array"],"enum":["foo"],"items":{"type":"string","enum":["foo","bar"]}}},"required":["foo","bar"],"additionalProperties":false},"strict":true}],"top_logprobs":0,"top_p":1.0,"truncation":"auto","usage":null,"user":null,"metadata":{}},"sequence_number":1} + data: {"type":"response.in_progress","response":{"id":"resp_025af4c5cac58077016aa3da88e8bc87d2b70d6deed2655855","object":"response","created_at":1789123208,"status":"in_progress","background":false,"completed_at":null,"error":null,"frequency_penalty":0.0,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"max_tool_calls":null,"model":"gpt-5-mini-2025-08-07","moderation":null,"output":[],"parallel_tool_calls":true,"presence_penalty":0.0,"previous_response_id":null,"prompt_cache_key":"jp:conversation:1577836800000000","prompt_cache_retention":"in_memory","reasoning":{"context":"current_turn","effort":"low","mode":"standard","summary":"detailed"},"safety_identifier":null,"service_tier":"auto","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"required","tool_usage":{"image_gen":{"input_tokens":0,"input_tokens_details":{"image_tokens":0,"text_tokens":0},"output_tokens":0,"output_tokens_details":{"image_tokens":0,"text_tokens":0},"total_tokens":0},"web_search":{"num_requests":0}},"tools":[{"type":"function","description":null,"name":"run_me","output_schema":null,"parameters":{"type":"object","properties":{"foo":{"type":["string","null"],"default":"foo"},"bar":{"type":["string","array"],"enum":["foo"],"items":{"type":"string","enum":["foo","bar"]}}},"required":["foo","bar"],"additionalProperties":false},"strict":true}],"top_logprobs":0,"top_p":1.0,"truncation":"auto","usage":null,"user":null,"metadata":{}},"sequence_number":1} event: response.output_item.added - data: {"type":"response.output_item.added","item":{"id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","type":"reasoning","content":[],"encrypted_content":"gAAAAABqiG2taJlWKR9z-pqazNeiWd_MxViwCQfg-pAMk8UKVfSQMPJCWrgszFvZcdh0Ic36XFDGBOAzsDSQtD8ZUzQSkwvDoS5f8UwNaEY3f7JIubea3Hc1s1D8WjIUByZTLXS4rJ_LUKOfkJj6j3AyJwfzf4pN5Z5Ewit3UTpvBmQIbvtOvLkA96LVBBMrKqKx6QyQH7oR1aknQp4HuIe68b7kBYXV5RaR7gtJRwYakCZP08L3WmCqXNtDkb5lNvJHVCXVQ-W2R5Pa5EgUNv6xpQbrVMqPwYU_dp2CFMIQjc_azLSqC7NIi9a0UYnl8-wsjeowJODn5fXlY0lZ06_iW-jZwgA2YirGdDXGREo0OFm3ktEckMYwN_Cz-xyJBw-iaApVc1oe-yADYrm7MnMh7_OgYmq4iDM9agIIaLl3tRP72xm79j0U4kq-boC5dGVf36_FFRWP5uHF0_tT6whH1r0wdGNIxDcD2veIqYV--35H6nQW2iIzG8yBO9MbGE1OP9FGp0KwSPWplCIteMqE-0Gf5ioUqW8EY7mSh7sjoemgtvMiY5SJ3iteGR6QvstyIWRjUZAGEEshAXp7un4LDM8ltpxaHHjJ9XK2rrLy9ELrP-Z7tKwiFYbaKLszsoADDUN0Vv6Z01WcSFS0OJBkui11LM9bmwre2obighK54gdoGI-_ZiXI0vNcfVFYcWJ3v7snVosQRjgF2LNBQCylImwJp_AhDINwpyFT1nHLxffZ-Da9KmLjPrmChS__lCvgLeys_DtZJHfMe29VciqqLvY28Xdj3js-5XSbmEqkXb7HR_J4L2Fn3a0B88TUaSFidV03ik7GDfsBO1FFaNlG_XDs-HYCtORFIDOoipgbAB-wQq9PiyuVmZjSxGsQ1xx-VVWDBXovcpmhrrcWJShbju9bUo4mQ6WxmuODaKtvmw8lQDTOpJmrtdY0GfDgD17F39Et9Dpbwnhhaate_5vpd7Uek85-mrmY9SyUIRiIaCT5JVPGVb5gSIe3sY_vXB19dwxN3aS0PCOWCh6FwBDWfxiNYGjlvKVrXa5Zr99fSGSukL_molBiHFxbHFdCNOu5-rflhqDs376s5Qq9jwT2ix25ctUT7SduXMSzpIH1jNnRa6i2cCOkr33xpoQUfO-1WWsHRbQZmtXsRQBcKMmjVvXedQYyGZIJSCVn669xXd5OK_hA-TE=","summary":[]},"output_index":0,"sequence_number":2} - - event: response.reasoning_summary_part.added - data: {"type":"response.reasoning_summary_part.added","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","output_index":0,"part":{"type":"summary_text","text":""},"sequence_number":3,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":"**Analyzing tool call options**\n\nI","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"A1N1gYzMh4WBXG","output_index":0,"sequence_number":4,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" need","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"f2aOBCNKXTx","output_index":0,"sequence_number":5,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" to","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"8DYdckjKfpGre","output_index":0,"sequence_number":6,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" call","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"Qb4U75tLsIH","output_index":0,"sequence_number":7,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" a","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"7ChcKUPDHpUj3O","output_index":0,"sequence_number":8,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" tool","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"ElXaoTVuD1P","output_index":0,"sequence_number":9,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":",","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"wGw9pLlEo4oWgMe","output_index":0,"sequence_number":10,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" specifically","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"NnP","output_index":0,"sequence_number":11,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" functions","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"xK2hGX","output_index":0,"sequence_number":12,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":".run","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"Ke6Czq29GDKE","output_index":0,"sequence_number":13,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":"_me","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"koekYmF1jGB7j","output_index":0,"sequence_number":14,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":",","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"SnlXhPUNNoJWZLs","output_index":0,"sequence_number":15,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" which","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"qlCgnlsmy9","output_index":0,"sequence_number":16,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" requires","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"jWb7RSL","output_index":0,"sequence_number":17,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" setting","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"SBFWe2oZ","output_index":0,"sequence_number":18,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" the","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"28umIce1hOwZ","output_index":0,"sequence_number":19,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" \"","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"SpG4Ez1pRVncvq","output_index":0,"sequence_number":20,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":"bar","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"yi7zw68wcymWK","output_index":0,"sequence_number":21,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":"\"","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"eFN6hMqR2EAY5QE","output_index":0,"sequence_number":22,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" parameter","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"meyc5O","output_index":0,"sequence_number":23,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" as","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"lAiFdFy87FHSR","output_index":0,"sequence_number":24,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" \"","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"RXhjsaxv12KfJe","output_index":0,"sequence_number":25,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":"foo","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"XMSXzKGGRJfyy","output_index":0,"sequence_number":26,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":",\"","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"lGZ0AZ1ZQgXwtl","output_index":0,"sequence_number":27,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" but","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"JfboHey9XukK","output_index":0,"sequence_number":28,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" \"","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"NofxoSAliw2nux","output_index":0,"sequence_number":29,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":"foo","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"JSCNsAxwj4BQq","output_index":0,"sequence_number":30,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":"\"","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"QQIIcbYqteA0RDd","output_index":0,"sequence_number":31,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" can","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"MWv3JIlLuSAk","output_index":0,"sequence_number":32,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" be","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"D6bKK5SnCGtku","output_index":0,"sequence_number":33,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" null","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"iT5AKoUzdZf","output_index":0,"sequence_number":34,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" or","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"foDxC7d5MrLjI","output_index":0,"sequence_number":35,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" a","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"J2J7cpPpmNbPs3","output_index":0,"sequence_number":36,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" string","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"SJDXNmm8l","output_index":0,"sequence_number":37,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":".","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"lNRkdMudidYb0R3","output_index":0,"sequence_number":38,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" I","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"2CGqFdovi2PQ4N","output_index":0,"sequence_number":39,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":"’m","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"dbr0zYwEZcdk5E","output_index":0,"sequence_number":40,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" considering","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"6uAk","output_index":0,"sequence_number":41,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" whether","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"0u4LTMsN","output_index":0,"sequence_number":42,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" to","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"mR6hlr0st7yc8","output_index":0,"sequence_number":43,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" use","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"UFg4mInGXUwa","output_index":0,"sequence_number":44,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" multi","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"YXJzhcnp53","output_index":0,"sequence_number":45,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":"_tool","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"Pb4V97SVhw7","output_index":0,"sequence_number":46,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":"_use","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"x7ivQFZeZO2o","output_index":0,"sequence_number":47,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":".parallel","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"blx5EDl","output_index":0,"sequence_number":48,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" for","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"wPCikyS7K5sp","output_index":0,"sequence_number":49,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" multiple","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"A5rFPnh","output_index":0,"sequence_number":50,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" calls","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"pICduDA2KK","output_index":0,"sequence_number":51,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":",","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"D0YRVYfJZKbXfbs","output_index":0,"sequence_number":52,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" but","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"YbzxbrBvbXft","output_index":0,"sequence_number":53,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" it","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"ZqKxxUWSHZDLR","output_index":0,"sequence_number":54,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" only","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"oP7byCkHdqA","output_index":0,"sequence_number":55,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" works","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"ic08i7uGpz","output_index":0,"sequence_number":56,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" for","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"PPNSSL4B8sGN","output_index":0,"sequence_number":57,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" functions","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"PW7kb8","output_index":0,"sequence_number":58,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" tools","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"tAziKcRjFF","output_index":0,"sequence_number":59,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":".","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"lsg2YZkLNihX6yA","output_index":0,"sequence_number":60,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" Since","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"nUZTlGn2ZH","output_index":0,"sequence_number":61,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" it","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"J6fD3BAQcKlUM","output_index":0,"sequence_number":62,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" seems","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"2BRG7IAw5D","output_index":0,"sequence_number":63,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" simpler","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"4aoMN848","output_index":0,"sequence_number":64,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":",","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"1IUIQREwo5QW3eB","output_index":0,"sequence_number":65,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" I'll","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"LbCVHvap0tq","output_index":0,"sequence_number":66,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" just","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"hfWhV6or5x2","output_index":0,"sequence_number":67,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" call","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"Q0xQFML0Tkz","output_index":0,"sequence_number":68,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" functions","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"uzua3V","output_index":0,"sequence_number":69,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":".run","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"7HPVv1nSDdfW","output_index":0,"sequence_number":70,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":"_me","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"kLx91mkM55TG4","output_index":0,"sequence_number":71,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" directly","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"YckT0y9","output_index":0,"sequence_number":72,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" and","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"xnQdixkUrJL6","output_index":0,"sequence_number":73,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" use","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"T9Mt9xJkDo2t","output_index":0,"sequence_number":74,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" the","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"LzRmF5WQwKmI","output_index":0,"sequence_number":75,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" commentary","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"PNGVt","output_index":0,"sequence_number":76,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" channel","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"8OKgjDb0","output_index":0,"sequence_number":77,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" for","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"yESMfKbpMwCv","output_index":0,"sequence_number":78,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" this","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"7uqouZInbYN","output_index":0,"sequence_number":79,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":".","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"Pt0muXBwLvfnRMi","output_index":0,"sequence_number":80,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" My","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"30xTSCKqmf9Gm","output_index":0,"sequence_number":81,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" plan","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"FohTioCeAOd","output_index":0,"sequence_number":82,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" is","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"DR3BOWmf9cqD5","output_index":0,"sequence_number":83,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" to","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"vSJBnU1VmV1xg","output_index":0,"sequence_number":84,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" call","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"CmklfxpOB3k","output_index":0,"sequence_number":85,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" it","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"ut2xzi73QeShh","output_index":0,"sequence_number":86,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" with","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"HRU6JvMjq2v","output_index":0,"sequence_number":87,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" \"","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"MipEZrpPet9Asy","output_index":0,"sequence_number":88,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":"foo","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"XotOK8OKXW8yn","output_index":0,"sequence_number":89,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":"\"","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"aQx6gLgfYLm4ToE","output_index":0,"sequence_number":90,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" set","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"TqjNQ2Cbd8E7","output_index":0,"sequence_number":91,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" to","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"jXMNVtdgIiPVx","output_index":0,"sequence_number":92,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":" null","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"sEgj2yw54eJ","output_index":0,"sequence_number":93,"summary_index":0} - - event: response.reasoning_summary_text.delta - data: {"type":"response.reasoning_summary_text.delta","delta":".","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","obfuscation":"cqeef9JLXcI2vmD","output_index":0,"sequence_number":94,"summary_index":0} - - event: response.reasoning_summary_text.done - data: {"type":"response.reasoning_summary_text.done","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","output_index":0,"sequence_number":95,"summary_index":0,"text":"**Analyzing tool call options**\n\nI need to call a tool, specifically functions.run_me, which requires setting the \"bar\" parameter as \"foo,\" but \"foo\" can be null or a string. I’m considering whether to use multi_tool_use.parallel for multiple calls, but it only works for functions tools. Since it seems simpler, I'll just call functions.run_me directly and use the commentary channel for this. My plan is to call it with \"foo\" set to null."} - - event: response.reasoning_summary_part.done - data: {"type":"response.reasoning_summary_part.done","item_id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","output_index":0,"part":{"type":"summary_text","text":"**Analyzing tool call options**\n\nI need to call a tool, specifically functions.run_me, which requires setting the \"bar\" parameter as \"foo,\" but \"foo\" can be null or a string. I’m considering whether to use multi_tool_use.parallel for multiple calls, but it only works for functions tools. Since it seems simpler, I'll just call functions.run_me directly and use the commentary channel for this. My plan is to call it with \"foo\" set to null."},"sequence_number":96,"summary_index":0} + data: {"type":"response.output_item.added","item":{"id":"rs_025af4c5cac58077016aa3da898c1c87d2884e863491b22f1e","type":"reasoning","content":[],"encrypted_content":"gAAAAABqo9qJRdRVoq_OGt87RVPtHK-dxdJZxNn_8-ZS1UJ3Ue3BUV4jNtAQ-c0flecOsi8NdlwqvNioDlhTz6JLwL74e_4rEuRJFRFiswXKfbeYKZn7gLlNVy-1qYTMM4pLlhI9pK-51w3fp3bm3D8wAWNdbC4gAIjKHz17Bo-kdmlSLpZlx2qTugcEUBVpSA5BsKVzi-JhyQERUWtj64-ufXPHd-IEDduazgQAo6WMLd88Abr0p91qEBAb1G8401_4v7JkjPefvSUeX2gxpp4LegnhA_YUEwHA-ueLE16XYvT-vw2nT15Annu5bwKopFaYpEIr4m3mGCISjMQeK1a1XjP01zsI1qdqpuz8O846eMO1rGtoZY8DUchgZ1MBxGh0qTH_MmmQZSRe2f3qxEkVU1ZUWrSlqhxP19ds5u_ARBBwat1BXb1Y4ojB6X7W-u5e-SXfPVbs_Uc8r5Y2wUehgX5C0veL_MeqsOgxfgJLwHV3YLoOqL1rD91QcD-4RAtRWcDze6eTdyy4aZGs_xosLnlZ-fU0-hpyT_D_239rUWSIV5-6Q7W11O_x4uCnlnNvKmn_iKUrSz7OnCcWPYBvGY3UfMNBpaFID5xButk8s4OrcOuGJLIW6I3UQPI03vEuhhlf8nKsgmmDf8gvmoNUPc6qnhBXnPTm77ZU-vqv-HvAtNwdT-8Kkl47SGMHlZpWgSOtwRTAmW-cVJBjhh32faYwwDQz_OQfN-eSXPJ6q8g7_Hz0PwJ9KnYUS8nnj60rZFwDzn9HuwAhZhswWeHC8iUxQkxBJlWwWngY_FK1K9GKeNcVoMFkHsXOfDLsLVsarBRkNlHfrWE6vHKTbWRTevQmTgUMlUI9s5vf90yt3PJ4g4z14Pg9l13kjVo4YO0SMlOUOcYcv2fCW4GeHZonLLlucOakcthBS11rYPIeeKod_IQkyJEMfNwcF9O1F5CRDclAUxL_jQPne5opPSNUbSzXK9I17-B3eCDda7ivY7GL-_9cI8QFGwKD2qgqcKOHE_wM3GcM4BiHWy9m312tZQVTyfH3ON19p0w6NT6tJYjLeGN9cguh_sjW2_7Tka2M3qC-rK3Pty6ngEDUojD3oHRUTmP8-XzHglbJ6oBL1dZpeEV_q9NTs6cHR1jey3s5-zwdfC71ikQBFcIuJxEHXHWQm2TCI0ZNn_gUi7kCQ-HCE8uskxE=","summary":[]},"output_index":0,"sequence_number":2} event: response.output_item.done - data: {"type":"response.output_item.done","item":{"id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","type":"reasoning","content":[],"encrypted_content":"gAAAAABqiG2xnaWTAwVx7x04cr5y6QDQVOvd0elZQTGi27BcEUr3BIG0OaUr9VTFqfuknzmuUOavCeWmcVTREMX-RQg5Y8TrIutPPGnT7yBlav4wNbnt0YEw_xf-TD5pHla9ZMNaMkxEDkfqfBVpc_y22tSXK4bku-LzAqdkjwX6dVehYXW0RYScYXn0iyPNoObad6kD74ijzhATuTjGtzH-l4aXN2L-7cVy5HmNo15lm_XSwyyya1NN7_Ao-i9yl8C7rKi9GvZwSsuT34h8RL5jRxiBx6-pTir687fabzxY4yh4XwnmUFFn_VWahwklsH_w7K5as_fT4LkDffQsY8xl9tM_yALD3iRcobeE_EXGZvbBmyC7X2s19Q5LCSYKMsWS15c6sYQNUSMQE5fCyOIxruJbDzTBwRdFKM9ZAM5UaY8QZYFXKpQpKQ-KnzSCyj7JFiohHNVnrGnQ0kRmtO759gRah49w1sait_tY2UKhS6DP18XDOw1PlznJTNto_uDNLSxNZg6z87wbu1jbuT2EBeiPXQ_hXrRk0HbFo6cx3W8YdAoIBJaFZS-3o6NhtHmLdsv2x2pH54AZ9VIz2lLS2J5E5O3bwKSRPAFu8PPAyKNZrs3oZe6LxXburqbNDtn_-9P2SEPLy_LJLDTBtoumsI3OWhxI-2-z8YIzdXjM1hqY_klki_nQDxRZTeRA2PHT7i_0mGEB2m16fId4AuNrRRetO_GBW55Tq1pNddZTNrPVEX9iT2CM5OB5fI6mV9kxAnxIszBMC8ffsho3FUgTpdyBjDn0Rw6PpDCBg543CV2QR_1rGujxMUqgLdydxT5VM0QlnoiWS9KcMZssvCCwkGvjXJjllynbNWuuK62K9IWXV3skFXXD5wuc2LbzbcwUczDzkeO0Bbu6et-P4fRDd5ZxMFz_uzE1ZK1MHIpQ0kX_DDsFi1frDziQ9yi4pXg7j4S1IoyCSXwqEQDf7KTnVW1KU70J1SLND_5dxNk_UZDRVvHItBHwykE1udDh-4xB_YUX9ifWM0NI6QkCoG1HgwdTQY_l3rxLDG4ISE5arr_Tw5CjfhpX19wBwPhqtB3ESeQH6utkPkKg1Z2A7ouf2VbXkV6prHR9sNmOrAe2RvZzqRor4cft3TfHVp-euRKDL3iPVjrwLC-OVsHPGniIiS6U3wsdi67JDEQrLoparVTSIMi3A8NMed371UrjLWlGGfICGJPy6TV9YJzQx4zhFhTNvueKBZrMlts8DF9GVKqv8UDsfxEW_xxIGkSwSl2UjmRzkFEWLGov-q5D_g7_0cEFCN2bo3ui5AZI5lv12EoM7P9pbORxh71hT0cn7GTm7Avl1_lJdlBhlSu1-pT_jWgpJAtem_6T0sUrB9kcgu3jFJbWhuD6KM1ZG_0xB35F-u7UzKO1H4yVlWQDMTje3OXZwpFE7fhVwTWHfa80EriyB9ZHKMdAkNI0baeB59lZrx1FPu9YLxvtp0793KLM4J7_qIKJhp0ZVR4Dxy9UE1lInJUXeqTN0mm5t3fBN6HayQjxZ-P5P-gbXm8xUxgrP69PvdBb32Hggs4hzw0KwGRsRED-nR_PVY5MTGILs7mV_Me9EPLrisJdAqE0d3Km7zrc643HY9_rpuLiAzqxr35ZbP8pzkCQlXoxPB-Zam_pxq8EJ1RoX3BGukvoo1D83VulqsCFS_yQpUat-mq40nNfeSquHs0=","summary":[{"type":"summary_text","text":"**Analyzing tool call options**\n\nI need to call a tool, specifically functions.run_me, which requires setting the \"bar\" parameter as \"foo,\" but \"foo\" can be null or a string. I’m considering whether to use multi_tool_use.parallel for multiple calls, but it only works for functions tools. Since it seems simpler, I'll just call functions.run_me directly and use the commentary channel for this. My plan is to call it with \"foo\" set to null."}]},"output_index":0,"sequence_number":97} + data: {"type":"response.output_item.done","item":{"id":"rs_025af4c5cac58077016aa3da898c1c87d2884e863491b22f1e","type":"reasoning","content":[],"encrypted_content":"gAAAAABqo9qNBxdNxVsQFw3IkPtx5IABI1oS9N0q9ZETVVaMQ9cndEcwqgj4DPO3BetQ7QFz-_M4Tq9mnBhUWVOXnH0bnpG6-TUTl-hp891X6tA8UcS4GZ-IJN367seyr8fw_NdlASDZxk4udZ9s74lMPIBpknpXXAYyb3zPuW4NEkaihiavxPIVct8_4-UqgPhdcOC5MIQcb1SbYCVuSY9UEjf4f0MSsIdyWkkseoyWQ0IxxDD9WwxBU9lfidHUIa2XiNBoC0RvaUHD0qMYXCO21SGLbgpDzUuvOw9vU1Uv3Xx9_YXkw3k8PO0tSs0gn2ssoA1p8qaZBQ7i1q8LbWfnHKtupjf6X3svacq9ZNuviqmpCtTBEN_IHbwMg79hSMQ6ua7Fmnbfjx6x-6PRCuqO-Babp_cGKsEEx04D87xj5gg3xMxUIWEBV8uBxxfyUfVjQ5wIYaCYxfGVQlQbYAQfnUzVy36KPCearWOgLUFSnbufcFBylbwTo98PIx4I9yjc-MH3Hr_ZnhNWBx3SRudQ1R6L_HX9VdjUhuNyZUHFEbxWztQ45waQDkqR-6dv2ZX4Dvks_vy93WvqeFJSH4u8zB5CesLjNv8fe5n3tlNywKXwk2mEttMAmTENeYqiZIorcHQngPwOBTkRElJYpK9xZkll1QAIffgVdQF7-pV83PNgyLJU2aOzFS30iUsfKGv_A4YHsX5q1xjAmF20-r7oGMRnDHTyVQc1ucMMyudDbtJMrn6jAAp-eVZrZY2kJsfGI4XlMYLzDtAKz1zwkaPVkjDzcElBG9yUKHcnYgEEs5PSVUpqGz-tdzv4K_qtfhTG58E3_hRTco3IlGizrOn6W_HL8OKgsn-QmwQnetHaraeKM8vBUYjxpwEL9o3E6zG0wCsldhCferQ1UnCDrjtP8xi3X7Qq2JWgoZ5fA0BG0TQLaDOQF0dm-JPxN0SD1PC5f3I3UbVd7cdSfSx-8tipbq81xRDuoDikQv2oBhfxFZUkKtffvz8F45NJSrnK3m5pLosYavq8sLLFCkSs1u5k8KcHsvllV0L0cVA4EGxcZ2u2WcvFUhxM7wYwk3d6C6UmlOP1GB0aUZmUgPt4R9o8wLoS9_srWWWpIQ04WQn9p-qroX59bBnUConqlXJR3edcN9U2Np3P_b7xvDNwjHV3FLe7kq0bE31iZDPMJCiDcy8axHs4-OcDapHsPCn5wzLvOjjAssM9HCE_NDA_uOuazBGYDkZyLqxqRze5QBlqiO8_skgjBUsAkCKrhCXEaVrAVGoIxRi0uj-d9XnuBaay5fRiy69n2bySeR9uNqYXlPb-ZvOAJSRgwlf5KEIywq_-c_BMlMngj7hzx_TmXTdTxd5CnICuFYX6zbVFsOHwF5s7hSM1HFaKf10Kkm0HNrrl_einA8i-xpq5djHV0bhBmqVEPVdgUwvSXHoASRjkcAbj72PPE464NLieXJrMRCsQ5d9VTyOOPIjgscY6xwNfOtUrMmBHIeR54DqWn3Vumf9hJs8u_htWxUWvJnUWDLo8kxEiKfnB_I5Mjw5xwYlWzQ26iBWUisBBLSrH5m7xHjwfuc0-pNs4A0oOE8Ud2S7XTFEIUOX92VAjFwDga3sUiCgVWvGed1FwIdOTZvuI_Tu6wHfkuBrKHKacX7G4WCGX9qlGVG3mtf5iP06cGK-mfdyfK6xhICY4WDefitSsPJss0NpI5vqT0N_gLBEZU5kl_7EFp1TIr593MYp9cb0C9UmLZ3ReaLZXbPwFyXOCT6ipgn2Homo=","summary":[]},"output_index":0,"sequence_number":3} event: response.output_item.added - data: {"type":"response.output_item.added","item":{"id":"fc_02702adc8fbb7a3a016a886db1593c87d2acdaa38fd4458fe3","type":"function_call","status":"in_progress","arguments":"","call_id":"call_i95it8x7WlrY7fZeliTs6shY","name":"run_me"},"output_index":1,"sequence_number":98} + data: {"type":"response.output_item.added","item":{"id":"fc_025af4c5cac58077016aa3da8d050487d28e4bc03df2ce0cce","type":"function_call","status":"in_progress","arguments":"","call_id":"call_1W5hSpB0eF8Xllvo5dyLR65p","name":"run_me"},"output_index":1,"sequence_number":4} + + event: response.function_call_arguments.delta + data: {"type":"response.function_call_arguments.delta","delta":"{\"","item_id":"fc_025af4c5cac58077016aa3da8d050487d28e4bc03df2ce0cce","obfuscation":"bnarhf6rlNjTp9","output_index":1,"sequence_number":5} event: response.function_call_arguments.delta - data: {"type":"response.function_call_arguments.delta","delta":"{\"","item_id":"fc_02702adc8fbb7a3a016a886db1593c87d2acdaa38fd4458fe3","obfuscation":"ceLPFjsQ8A5Y3m","output_index":1,"sequence_number":99} + data: {"type":"response.function_call_arguments.delta","delta":"foo","item_id":"fc_025af4c5cac58077016aa3da8d050487d28e4bc03df2ce0cce","obfuscation":"I1OLeu2vHg8WB","output_index":1,"sequence_number":6} event: response.function_call_arguments.delta - data: {"type":"response.function_call_arguments.delta","delta":"foo","item_id":"fc_02702adc8fbb7a3a016a886db1593c87d2acdaa38fd4458fe3","obfuscation":"6ehaVnbhABf1z","output_index":1,"sequence_number":100} + data: {"type":"response.function_call_arguments.delta","delta":"\":\"","item_id":"fc_025af4c5cac58077016aa3da8d050487d28e4bc03df2ce0cce","obfuscation":"XjXNNyHCUcmYe","output_index":1,"sequence_number":7} event: response.function_call_arguments.delta - data: {"type":"response.function_call_arguments.delta","delta":"\":","item_id":"fc_02702adc8fbb7a3a016a886db1593c87d2acdaa38fd4458fe3","obfuscation":"s1cw8l0IQihHyE","output_index":1,"sequence_number":101} + data: {"type":"response.function_call_arguments.delta","delta":"example","item_id":"fc_025af4c5cac58077016aa3da8d050487d28e4bc03df2ce0cce","obfuscation":"8c6b5jmR1","output_index":1,"sequence_number":8} event: response.function_call_arguments.delta - data: {"type":"response.function_call_arguments.delta","delta":"null","item_id":"fc_02702adc8fbb7a3a016a886db1593c87d2acdaa38fd4458fe3","obfuscation":"s0xF6Ofuos1R","output_index":1,"sequence_number":102} + data: {"type":"response.function_call_arguments.delta","delta":" input","item_id":"fc_025af4c5cac58077016aa3da8d050487d28e4bc03df2ce0cce","obfuscation":"OXUbXAj2lR","output_index":1,"sequence_number":9} event: response.function_call_arguments.delta - data: {"type":"response.function_call_arguments.delta","delta":",\"","item_id":"fc_02702adc8fbb7a3a016a886db1593c87d2acdaa38fd4458fe3","obfuscation":"dfYjE57QfFqCkd","output_index":1,"sequence_number":103} + data: {"type":"response.function_call_arguments.delta","delta":"\",\"","item_id":"fc_025af4c5cac58077016aa3da8d050487d28e4bc03df2ce0cce","obfuscation":"stIx3F6xcXZKS","output_index":1,"sequence_number":10} event: response.function_call_arguments.delta - data: {"type":"response.function_call_arguments.delta","delta":"bar","item_id":"fc_02702adc8fbb7a3a016a886db1593c87d2acdaa38fd4458fe3","obfuscation":"CLjLea1TLjSh6","output_index":1,"sequence_number":104} + data: {"type":"response.function_call_arguments.delta","delta":"bar","item_id":"fc_025af4c5cac58077016aa3da8d050487d28e4bc03df2ce0cce","obfuscation":"gg9LntSeCumcq","output_index":1,"sequence_number":11} event: response.function_call_arguments.delta - data: {"type":"response.function_call_arguments.delta","delta":"\":\"","item_id":"fc_02702adc8fbb7a3a016a886db1593c87d2acdaa38fd4458fe3","obfuscation":"FQ3RmNU68ZMn8","output_index":1,"sequence_number":105} + data: {"type":"response.function_call_arguments.delta","delta":"\":\"","item_id":"fc_025af4c5cac58077016aa3da8d050487d28e4bc03df2ce0cce","obfuscation":"tURoDeIBHgbNI","output_index":1,"sequence_number":12} event: response.function_call_arguments.delta - data: {"type":"response.function_call_arguments.delta","delta":"foo","item_id":"fc_02702adc8fbb7a3a016a886db1593c87d2acdaa38fd4458fe3","obfuscation":"kMKjRm1DFr73d","output_index":1,"sequence_number":106} + data: {"type":"response.function_call_arguments.delta","delta":"foo","item_id":"fc_025af4c5cac58077016aa3da8d050487d28e4bc03df2ce0cce","obfuscation":"JfmeKNpVvNivb","output_index":1,"sequence_number":13} event: response.function_call_arguments.delta - data: {"type":"response.function_call_arguments.delta","delta":"\"}","item_id":"fc_02702adc8fbb7a3a016a886db1593c87d2acdaa38fd4458fe3","obfuscation":"kETmwkzmzaZ659","output_index":1,"sequence_number":107} + data: {"type":"response.function_call_arguments.delta","delta":"\"}","item_id":"fc_025af4c5cac58077016aa3da8d050487d28e4bc03df2ce0cce","obfuscation":"KFaQIS88mDWBcM","output_index":1,"sequence_number":14} event: response.function_call_arguments.done - data: {"type":"response.function_call_arguments.done","arguments":"{\"foo\":null,\"bar\":\"foo\"}","item_id":"fc_02702adc8fbb7a3a016a886db1593c87d2acdaa38fd4458fe3","output_index":1,"sequence_number":108} + data: {"type":"response.function_call_arguments.done","arguments":"{\"foo\":\"example input\",\"bar\":\"foo\"}","item_id":"fc_025af4c5cac58077016aa3da8d050487d28e4bc03df2ce0cce","output_index":1,"sequence_number":15} event: response.output_item.done - data: {"type":"response.output_item.done","item":{"id":"fc_02702adc8fbb7a3a016a886db1593c87d2acdaa38fd4458fe3","type":"function_call","status":"completed","arguments":"{\"foo\":null,\"bar\":\"foo\"}","call_id":"call_i95it8x7WlrY7fZeliTs6shY","name":"run_me"},"output_index":1,"sequence_number":109} + data: {"type":"response.output_item.done","item":{"id":"fc_025af4c5cac58077016aa3da8d050487d28e4bc03df2ce0cce","type":"function_call","status":"completed","arguments":"{\"foo\":\"example input\",\"bar\":\"foo\"}","call_id":"call_1W5hSpB0eF8Xllvo5dyLR65p","name":"run_me"},"output_index":1,"sequence_number":16} event: response.completed - data: {"type":"response.completed","response":{"id":"resp_02702adc8fbb7a3a016a886dad9d9487d2a68983a3b99abd6f","object":"response","created_at":1787325869,"status":"completed","background":false,"completed_at":1787325873,"error":null,"frequency_penalty":0.0,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"max_tool_calls":null,"model":"gpt-5-mini-2025-08-07","moderation":null,"output":[{"id":"rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27","type":"reasoning","content":[],"encrypted_content":"gAAAAABqiG2xxLcuWKce4yLakXcZzDYnpAiXrCprSqkWB2lKRoL85wco90nvTfEn776pGyCHZlFQcOqtl_XFEzmu2dwwrapyr9toa0YRhgfT1ffl5fLIFwK9Z2AtFNPrSROO-e0--gibCofgI00H--EZN-3KzqEzTtRe6_scFZ11t61PFBNCGY0nhusmFMupOpvsbHfUA8G56d6T6JynSTB_UYeulrJcF-PT8HKpND1lsCSaQx2ZHSxnH7-e_gLTujC1e4C6zGQz_cYROYrub64lcn2BTSgn8-_BU7EOeECfCGnXn7UXiPYnJZUL1UuxGvdFsKLY28WNA_aN_f9lxgYVleCdh1n4FFRi2NvY6urTZ8ISxwbBL2Cd0FPP76ZMgXY4k4A0AijQsB8NbWEdsKJntovV8fWrWlwcJatJ5SNEtvfxNAlN3pG4MTUN9AtbxZxKKV8DnUZNmdD7YYc1NLcKsvvNM41iIKlRAtMeZ0LVM8caTDzITHykxKTqJfir2vrTjo_G4ekK0noVWMrSQBZ2heNUT0Fg7Pixg_zFls0AClA8CJkJvbXbIaKXuaYMvIX1Nwa14y9exvMcDA2BgAobOHywJNxrRzjG1tCEVrOTdDHZe6GJQsASURVJFV41T4H6qQdhSAOn6saplMcvMHIsIn1lATodMgOY5F-7eIq0xUpUvpasswBagKgT3Gsqh7bt-sRMwpe4hLwRarS-TtAEHMQK-j2XdVMnV0TOPJA6vY0fmcsKm-B8qhz0AAcRQegwT4aPhFrfrQmDolDX7r8IlZJfarraqPN2cPwNNZ0wm5L-4tQGzEVkpbiMvrngJWhTRRczp6UFZESVIe6RNAQalJC91k63XNuqV5tJH-7cfp4NR7aIvI9B8aKYVslJLaoHHgUoLQr-6_S74AK8ePswcw49JvbdI7aHsBL7_knxBUh5loTNJ8Xe2orOaAsj0LbiIy1cKRBvBwUyqsIFAixhKSYrYWPzsiTlmVoShaSznZ5oNGWwjwk_yniEzPkGvbk6zjB7P1xO44tY905c5bsjy0kcJKm2ZI6tu924Uh_aZCy8z6FaCkZl8QQicd0fFO87FxJK9xgWMvSgvhpxKpO99CxE-nlr7sJ5HYASVYgofjc0xFMKxrx45OCnjlIwE8ZoLBct2YA1tN7JnWoQA9a4n0VKmVnQVMJ14KvUasPY6FbupZhvCah0Ay5tlWauAPfdDNLaSUIxsGIoa1wS0kmhrWCrMw-_v-S7CyFdGJ-AzH-33zRZUd5Q7dW4oYdYbjQTCKUe8F4kQZimQ7VNeHzFNJS2sKzfhZGdWZbAZUdhlrskXNm0pC_nWqMpqizdsM3qQEAOQtRiFq0kSO79BU1MDio8z8M8AusJLxgOT71b0Sh_SFVRNPEQw80RLT4I2K4cx3jdPOX5-7TjOOM7CwljRttOVntf6QBqG8bTa5QgcSbU3GgJ0CX8phFTC7dO17YsZnGlqTKuIWlSN2DZehc9HTYN6EMdPJ9avDwYEScbNJ1xeRCU8fbvhmm2SZpYiTFzdCYCgr-kPDuByXcHpgbXK8XS7TnNaclOkREVacGo4QFUne0xBgyC95Wstd4Y3HV0EjtvO_P9VTmx42Y9XHRTZqbZ7D3SIJUfOP-hTZmUraLOQPPsmXYehQWDRqrxMjBKTKm-Ev9Vl224kp17naBjCfcCSA2UpC7j6y9KP5ag7BajLK9CEY8=","summary":[{"type":"summary_text","text":"**Analyzing tool call options**\n\nI need to call a tool, specifically functions.run_me, which requires setting the \"bar\" parameter as \"foo,\" but \"foo\" can be null or a string. I’m considering whether to use multi_tool_use.parallel for multiple calls, but it only works for functions tools. Since it seems simpler, I'll just call functions.run_me directly and use the commentary channel for this. My plan is to call it with \"foo\" set to null."}]},{"id":"fc_02702adc8fbb7a3a016a886db1593c87d2acdaa38fd4458fe3","type":"function_call","status":"completed","arguments":"{\"foo\":null,\"bar\":\"foo\"}","call_id":"call_i95it8x7WlrY7fZeliTs6shY","name":"run_me"}],"parallel_tool_calls":true,"presence_penalty":0.0,"previous_response_id":null,"prompt_cache_key":"jp:conversation:1577836800000000","prompt_cache_retention":"in_memory","reasoning":{"context":"current_turn","effort":"low","mode":"standard","summary":"detailed"},"safety_identifier":null,"service_tier":"default","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"required","tool_usage":{"image_gen":{"input_tokens":0,"input_tokens_details":{"image_tokens":0,"text_tokens":0},"output_tokens":0,"output_tokens_details":{"image_tokens":0,"text_tokens":0},"total_tokens":0},"web_search":{"num_requests":0}},"tools":[{"type":"function","description":null,"name":"run_me","output_schema":null,"parameters":{"type":"object","properties":{"foo":{"type":["string","null"],"default":"foo"},"bar":{"type":["string","array"],"enum":["foo"],"items":{"type":"string","enum":["foo","bar"]}}},"required":["foo","bar"],"additionalProperties":false},"strict":true}],"top_logprobs":0,"top_p":1.0,"truncation":"auto","usage":{"input_tokens":60,"input_tokens_details":{"cache_write_tokens":0,"cached_tokens":0},"output_tokens":109,"output_tokens_details":{"reasoning_tokens":64},"total_tokens":169},"user":null,"metadata":{}},"sequence_number":110} + data: {"type":"response.completed","response":{"id":"resp_025af4c5cac58077016aa3da88e8bc87d2b70d6deed2655855","object":"response","created_at":1789123208,"status":"completed","background":false,"completed_at":1789123213,"error":null,"frequency_penalty":0.0,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"max_tool_calls":null,"model":"gpt-5-mini-2025-08-07","moderation":null,"output":[{"id":"rs_025af4c5cac58077016aa3da898c1c87d2884e863491b22f1e","type":"reasoning","content":[],"encrypted_content":"gAAAAABqo9qNuIceghHYzLw-iQJRP7akss1EQg8s0qTC4AppNaB8XQv-lNNdwQK0HgfgC9Yle1m7Gv9ezU16WwZiB1pRUoc4MUIm7P9YI1OfP7QxfenwlpSxqGpMIv3in81TLvhZKyoFV5j9iDKVSyBuB8jD1YAQ683_eaocnJbQ8uQUtucqUcsqbH04xwbCLNaDLH2nFQeB7G9ExcRQTQkyumDlpdAJ04md4hz1CmXKiM0Lbah4gn4oZ40CSMRPPXd32zIfKiPUeqMFiikYPcJlmCfEVPbPM7-ke8PqZi0snHi7Zmr9Lod06OyRvwa7jCavwnfTxqnG5zi-MmITOh7veuZ49jrTJ9Z7GoyeZ1Jwz55RfN3Q99qcWejfRFHU51Nap-BmV4eeBMFvUzaj_2AZUJrUWgRLwNejijV4DhDO98aaO6xKcJp86HYh1EkTrzPRXu8XYjwyXyG6B6ng2kdXcIKJgOgqY5HouTgoHKBYqpqqT8OP1_8X1bRyUVRRQW_kBxDrabTDOfoVTPKAgiosWPpfn_zmObfnhA_O2xcX5w2QXBjzWvG-coNrlAPBpKYfGJAuOG6D1vgQrIm5xUDr6jRii_Yiy3eA60vYSiEClkavxqfc2nZ7RB4HZpGLjkpBC96NYgN-o8gQlu9RQZBRCN4eP9tCm8443liobPH9bsVsGfRE2fEMRdX-sLB5HxHqNgGX6_0UnNJTc58y2XaY4u-XICdFyYvyGck3MZqsrlyIlo9ls5wBuO3ACuwnPC7tdRbSLz_7NMCoWJX2KMReB2lRQFi0-X11ynU1uFaEEYSC2ngcONbDq0DJBHmF0nfX-J9-WhPUU_JzlaRNnpDvhF0iRCmQlBMkpHXVHKstCw3hiPmn3CRhezXQ3tfd98do4w--idm6yyPf_WB9A-7rvdEWkwUHGJfEDWV1LiGazon2zvLc4zsJi42_c7GD8MCs0W4v5g5HWPjOOFs0LzYdi7mV2-aDQoyfrNVpFOLzxoLtSWWBgsqOYakyhzp6Pzzft3yKyDftVZ3GPw57OPGGee8lHsI0lHlAHtUfdYjta8mKySHLSlTq5hXmS7uVbSC5--VWonXgEnjjKMGU_LAb5H_BHAHK1hQCUhWG3Xw4zSgNfzeTRyJNJ8fIw8-qd5t_Vcymm93d-KZRkewcKFhX3_mHAB8m-cjH9a2oyqFsv_vxhq7wRJ1x52bo3C1JWNdog87GpDyj__LNaQUuxT2cf4NBhFwSdmbUkFVWLid65pE8azKJPJad550o4RbSOc-j2iyCm2ulNjZzWVgRxVBNHQ6owr_dWoeloY4qSXk_Fulo4g-PxRCBGwgC-4yc7-rlMCErUZBYLL0UyXA8oTnVK5mvZd6riGoMY6383IjqY7C7Y98wZGraCgvk8w-w13tNR1bD9hqnU3EfHJZtnrWgR6_hZu1apLv2J6UIOyAsuRpkbYO_ePEfC1mwRYxNqkkj_yJokjYYkDcadJakImb7ZVUgV4BFpzRPbV-cNyCorb0uBk-Zw9DJOo73ZoM_23eD5rv5y6XxlaBckv1a5HUBqFnFdlY6t86TPzgGZY6CSLny0hgNaY5Sr39u2xopbuuTmcF2wa_BU2TkHioxZbd36Qcqb_0BbGKwXhAv--cnd_KXkaFiw4eYxV2jQXOPom8PIG8xtYo0EjwpB_5DWfoHs8Xt4waAa9OBETd25DspG2nJHCm76BPY6U77JdmUZQcEGNVHLDFxNod_5zJbZckKD8UfO7AJDCwPJ5fevq7CN1zYgJjMqVg=","summary":[]},{"id":"fc_025af4c5cac58077016aa3da8d050487d28e4bc03df2ce0cce","type":"function_call","status":"completed","arguments":"{\"foo\":\"example input\",\"bar\":\"foo\"}","call_id":"call_1W5hSpB0eF8Xllvo5dyLR65p","name":"run_me"}],"parallel_tool_calls":true,"presence_penalty":0.0,"previous_response_id":null,"prompt_cache_key":"jp:conversation:1577836800000000","prompt_cache_retention":"in_memory","reasoning":{"context":"current_turn","effort":"low","mode":"standard","summary":"detailed"},"safety_identifier":null,"service_tier":"default","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"required","tool_usage":{"image_gen":{"input_tokens":0,"input_tokens_details":{"image_tokens":0,"text_tokens":0},"output_tokens":0,"output_tokens_details":{"image_tokens":0,"text_tokens":0},"total_tokens":0},"web_search":{"num_requests":0}},"tools":[{"type":"function","description":null,"name":"run_me","output_schema":null,"parameters":{"type":"object","properties":{"foo":{"type":["string","null"],"default":"foo"},"bar":{"type":["string","array"],"enum":["foo"],"items":{"type":"string","enum":["foo","bar"]}}},"required":["foo","bar"],"additionalProperties":false},"strict":true}],"top_logprobs":0,"top_p":1.0,"truncation":"auto","usage":{"input_tokens":60,"input_tokens_details":{"cache_write_tokens":0,"cached_tokens":0},"output_tokens":119,"output_tokens_details":{"reasoning_tokens":64},"total_tokens":179},"user":null,"metadata":{}},"sequence_number":17} --- when: @@ -439,19 +160,19 @@ when: }, { "type": "reasoning", - "id": "rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27", + "id": "rs_025af4c5cac58077016aa3da898c1c87d2884e863491b22f1e", "summary": [ { "type": "summary_text", - "text": "**Analyzing tool call options**\n\nI need to call a tool, specifically functions.run_me, which requires setting the \"bar\" parameter as \"foo,\" but \"foo\" can be null or a string. I’m considering whether to use multi_tool_use.parallel for multiple calls, but it only works for functions tools. Since it seems simpler, I'll just call functions.run_me directly and use the commentary channel for this. My plan is to call it with \"foo\" set to null." + "text": "" } ], - "encrypted_content": "gAAAAABqiG2xnaWTAwVx7x04cr5y6QDQVOvd0elZQTGi27BcEUr3BIG0OaUr9VTFqfuknzmuUOavCeWmcVTREMX-RQg5Y8TrIutPPGnT7yBlav4wNbnt0YEw_xf-TD5pHla9ZMNaMkxEDkfqfBVpc_y22tSXK4bku-LzAqdkjwX6dVehYXW0RYScYXn0iyPNoObad6kD74ijzhATuTjGtzH-l4aXN2L-7cVy5HmNo15lm_XSwyyya1NN7_Ao-i9yl8C7rKi9GvZwSsuT34h8RL5jRxiBx6-pTir687fabzxY4yh4XwnmUFFn_VWahwklsH_w7K5as_fT4LkDffQsY8xl9tM_yALD3iRcobeE_EXGZvbBmyC7X2s19Q5LCSYKMsWS15c6sYQNUSMQE5fCyOIxruJbDzTBwRdFKM9ZAM5UaY8QZYFXKpQpKQ-KnzSCyj7JFiohHNVnrGnQ0kRmtO759gRah49w1sait_tY2UKhS6DP18XDOw1PlznJTNto_uDNLSxNZg6z87wbu1jbuT2EBeiPXQ_hXrRk0HbFo6cx3W8YdAoIBJaFZS-3o6NhtHmLdsv2x2pH54AZ9VIz2lLS2J5E5O3bwKSRPAFu8PPAyKNZrs3oZe6LxXburqbNDtn_-9P2SEPLy_LJLDTBtoumsI3OWhxI-2-z8YIzdXjM1hqY_klki_nQDxRZTeRA2PHT7i_0mGEB2m16fId4AuNrRRetO_GBW55Tq1pNddZTNrPVEX9iT2CM5OB5fI6mV9kxAnxIszBMC8ffsho3FUgTpdyBjDn0Rw6PpDCBg543CV2QR_1rGujxMUqgLdydxT5VM0QlnoiWS9KcMZssvCCwkGvjXJjllynbNWuuK62K9IWXV3skFXXD5wuc2LbzbcwUczDzkeO0Bbu6et-P4fRDd5ZxMFz_uzE1ZK1MHIpQ0kX_DDsFi1frDziQ9yi4pXg7j4S1IoyCSXwqEQDf7KTnVW1KU70J1SLND_5dxNk_UZDRVvHItBHwykE1udDh-4xB_YUX9ifWM0NI6QkCoG1HgwdTQY_l3rxLDG4ISE5arr_Tw5CjfhpX19wBwPhqtB3ESeQH6utkPkKg1Z2A7ouf2VbXkV6prHR9sNmOrAe2RvZzqRor4cft3TfHVp-euRKDL3iPVjrwLC-OVsHPGniIiS6U3wsdi67JDEQrLoparVTSIMi3A8NMed371UrjLWlGGfICGJPy6TV9YJzQx4zhFhTNvueKBZrMlts8DF9GVKqv8UDsfxEW_xxIGkSwSl2UjmRzkFEWLGov-q5D_g7_0cEFCN2bo3ui5AZI5lv12EoM7P9pbORxh71hT0cn7GTm7Avl1_lJdlBhlSu1-pT_jWgpJAtem_6T0sUrB9kcgu3jFJbWhuD6KM1ZG_0xB35F-u7UzKO1H4yVlWQDMTje3OXZwpFE7fhVwTWHfa80EriyB9ZHKMdAkNI0baeB59lZrx1FPu9YLxvtp0793KLM4J7_qIKJhp0ZVR4Dxy9UE1lInJUXeqTN0mm5t3fBN6HayQjxZ-P5P-gbXm8xUxgrP69PvdBb32Hggs4hzw0KwGRsRED-nR_PVY5MTGILs7mV_Me9EPLrisJdAqE0d3Km7zrc643HY9_rpuLiAzqxr35ZbP8pzkCQlXoxPB-Zam_pxq8EJ1RoX3BGukvoo1D83VulqsCFS_yQpUat-mq40nNfeSquHs0=" + "encrypted_content": "gAAAAABqo9qNBxdNxVsQFw3IkPtx5IABI1oS9N0q9ZETVVaMQ9cndEcwqgj4DPO3BetQ7QFz-_M4Tq9mnBhUWVOXnH0bnpG6-TUTl-hp891X6tA8UcS4GZ-IJN367seyr8fw_NdlASDZxk4udZ9s74lMPIBpknpXXAYyb3zPuW4NEkaihiavxPIVct8_4-UqgPhdcOC5MIQcb1SbYCVuSY9UEjf4f0MSsIdyWkkseoyWQ0IxxDD9WwxBU9lfidHUIa2XiNBoC0RvaUHD0qMYXCO21SGLbgpDzUuvOw9vU1Uv3Xx9_YXkw3k8PO0tSs0gn2ssoA1p8qaZBQ7i1q8LbWfnHKtupjf6X3svacq9ZNuviqmpCtTBEN_IHbwMg79hSMQ6ua7Fmnbfjx6x-6PRCuqO-Babp_cGKsEEx04D87xj5gg3xMxUIWEBV8uBxxfyUfVjQ5wIYaCYxfGVQlQbYAQfnUzVy36KPCearWOgLUFSnbufcFBylbwTo98PIx4I9yjc-MH3Hr_ZnhNWBx3SRudQ1R6L_HX9VdjUhuNyZUHFEbxWztQ45waQDkqR-6dv2ZX4Dvks_vy93WvqeFJSH4u8zB5CesLjNv8fe5n3tlNywKXwk2mEttMAmTENeYqiZIorcHQngPwOBTkRElJYpK9xZkll1QAIffgVdQF7-pV83PNgyLJU2aOzFS30iUsfKGv_A4YHsX5q1xjAmF20-r7oGMRnDHTyVQc1ucMMyudDbtJMrn6jAAp-eVZrZY2kJsfGI4XlMYLzDtAKz1zwkaPVkjDzcElBG9yUKHcnYgEEs5PSVUpqGz-tdzv4K_qtfhTG58E3_hRTco3IlGizrOn6W_HL8OKgsn-QmwQnetHaraeKM8vBUYjxpwEL9o3E6zG0wCsldhCferQ1UnCDrjtP8xi3X7Qq2JWgoZ5fA0BG0TQLaDOQF0dm-JPxN0SD1PC5f3I3UbVd7cdSfSx-8tipbq81xRDuoDikQv2oBhfxFZUkKtffvz8F45NJSrnK3m5pLosYavq8sLLFCkSs1u5k8KcHsvllV0L0cVA4EGxcZ2u2WcvFUhxM7wYwk3d6C6UmlOP1GB0aUZmUgPt4R9o8wLoS9_srWWWpIQ04WQn9p-qroX59bBnUConqlXJR3edcN9U2Np3P_b7xvDNwjHV3FLe7kq0bE31iZDPMJCiDcy8axHs4-OcDapHsPCn5wzLvOjjAssM9HCE_NDA_uOuazBGYDkZyLqxqRze5QBlqiO8_skgjBUsAkCKrhCXEaVrAVGoIxRi0uj-d9XnuBaay5fRiy69n2bySeR9uNqYXlPb-ZvOAJSRgwlf5KEIywq_-c_BMlMngj7hzx_TmXTdTxd5CnICuFYX6zbVFsOHwF5s7hSM1HFaKf10Kkm0HNrrl_einA8i-xpq5djHV0bhBmqVEPVdgUwvSXHoASRjkcAbj72PPE464NLieXJrMRCsQ5d9VTyOOPIjgscY6xwNfOtUrMmBHIeR54DqWn3Vumf9hJs8u_htWxUWvJnUWDLo8kxEiKfnB_I5Mjw5xwYlWzQ26iBWUisBBLSrH5m7xHjwfuc0-pNs4A0oOE8Ud2S7XTFEIUOX92VAjFwDga3sUiCgVWvGed1FwIdOTZvuI_Tu6wHfkuBrKHKacX7G4WCGX9qlGVG3mtf5iP06cGK-mfdyfK6xhICY4WDefitSsPJss0NpI5vqT0N_gLBEZU5kl_7EFp1TIr593MYp9cb0C9UmLZ3ReaLZXbPwFyXOCT6ipgn2Homo=" }, { "type": "function_call", - "arguments": "{\"foo\":null,\"bar\":\"foo\"}", - "call_id": "call_i95it8x7WlrY7fZeliTs6shY", + "arguments": "{\"foo\":\"example input\",\"bar\":\"foo\"}", + "call_id": "call_1W5hSpB0eF8Xllvo5dyLR65p", "id": null, "name": "run_me", "status": null @@ -460,7 +181,7 @@ when: "type": "function_call_output", "id": null, "status": null, - "call_id": "call_i95it8x7WlrY7fZeliTs6shY", + "call_id": "call_1W5hSpB0eF8Xllvo5dyLR65p", "output": "working!" } ], @@ -493,53 +214,53 @@ then: value: text/event-stream; charset=utf-8 body: |+ event: response.created - data: {"type":"response.created","response":{"id":"resp_02702adc8fbb7a3a016a886db26d2087d2a102898b55fe47fd","object":"response","created_at":1787325874,"status":"in_progress","background":false,"completed_at":null,"error":null,"frequency_penalty":0.0,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"max_tool_calls":null,"model":"gpt-5-mini-2025-08-07","moderation":null,"output":[],"parallel_tool_calls":true,"presence_penalty":0.0,"previous_response_id":null,"prompt_cache_key":"jp:conversation:1577836800000000","prompt_cache_retention":"in_memory","reasoning":{"context":"current_turn","effort":"minimal","mode":"standard","summary":"detailed"},"safety_identifier":null,"service_tier":"auto","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tool_usage":{"image_gen":{"input_tokens":0,"input_tokens_details":{"image_tokens":0,"text_tokens":0},"output_tokens":0,"output_tokens_details":{"image_tokens":0,"text_tokens":0},"total_tokens":0},"web_search":{"num_requests":0}},"tools":[],"top_logprobs":0,"top_p":1.0,"truncation":"auto","usage":null,"user":null,"metadata":{}},"sequence_number":0} + data: {"type":"response.created","response":{"id":"resp_025af4c5cac58077016aa3da8d52b887d29b745bd8355c325a","object":"response","created_at":1789123213,"status":"in_progress","background":false,"completed_at":null,"error":null,"frequency_penalty":0.0,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"max_tool_calls":null,"model":"gpt-5-mini-2025-08-07","moderation":null,"output":[],"parallel_tool_calls":true,"presence_penalty":0.0,"previous_response_id":null,"prompt_cache_key":"jp:conversation:1577836800000000","prompt_cache_retention":"in_memory","reasoning":{"context":"current_turn","effort":"minimal","mode":"standard","summary":"detailed"},"safety_identifier":null,"service_tier":"auto","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tool_usage":{"image_gen":{"input_tokens":0,"input_tokens_details":{"image_tokens":0,"text_tokens":0},"output_tokens":0,"output_tokens_details":{"image_tokens":0,"text_tokens":0},"total_tokens":0},"web_search":{"num_requests":0}},"tools":[],"top_logprobs":0,"top_p":1.0,"truncation":"auto","usage":null,"user":null,"metadata":{}},"sequence_number":0} event: response.in_progress - data: {"type":"response.in_progress","response":{"id":"resp_02702adc8fbb7a3a016a886db26d2087d2a102898b55fe47fd","object":"response","created_at":1787325874,"status":"in_progress","background":false,"completed_at":null,"error":null,"frequency_penalty":0.0,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"max_tool_calls":null,"model":"gpt-5-mini-2025-08-07","moderation":null,"output":[],"parallel_tool_calls":true,"presence_penalty":0.0,"previous_response_id":null,"prompt_cache_key":"jp:conversation:1577836800000000","prompt_cache_retention":"in_memory","reasoning":{"context":"current_turn","effort":"minimal","mode":"standard","summary":"detailed"},"safety_identifier":null,"service_tier":"auto","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tool_usage":{"image_gen":{"input_tokens":0,"input_tokens_details":{"image_tokens":0,"text_tokens":0},"output_tokens":0,"output_tokens_details":{"image_tokens":0,"text_tokens":0},"total_tokens":0},"web_search":{"num_requests":0}},"tools":[],"top_logprobs":0,"top_p":1.0,"truncation":"auto","usage":null,"user":null,"metadata":{}},"sequence_number":1} + data: {"type":"response.in_progress","response":{"id":"resp_025af4c5cac58077016aa3da8d52b887d29b745bd8355c325a","object":"response","created_at":1789123213,"status":"in_progress","background":false,"completed_at":null,"error":null,"frequency_penalty":0.0,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"max_tool_calls":null,"model":"gpt-5-mini-2025-08-07","moderation":null,"output":[],"parallel_tool_calls":true,"presence_penalty":0.0,"previous_response_id":null,"prompt_cache_key":"jp:conversation:1577836800000000","prompt_cache_retention":"in_memory","reasoning":{"context":"current_turn","effort":"minimal","mode":"standard","summary":"detailed"},"safety_identifier":null,"service_tier":"auto","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tool_usage":{"image_gen":{"input_tokens":0,"input_tokens_details":{"image_tokens":0,"text_tokens":0},"output_tokens":0,"output_tokens_details":{"image_tokens":0,"text_tokens":0},"total_tokens":0},"web_search":{"num_requests":0}},"tools":[],"top_logprobs":0,"top_p":1.0,"truncation":"auto","usage":null,"user":null,"metadata":{}},"sequence_number":1} event: response.output_item.added - data: {"type":"response.output_item.added","item":{"id":"msg_02702adc8fbb7a3a016a886db2cc3487d293743440c7837e04","type":"message","status":"in_progress","content":[],"role":"assistant"},"output_index":0,"sequence_number":2} + data: {"type":"response.output_item.added","item":{"id":"msg_025af4c5cac58077016aa3da8db40887d2ae1be5affa1d6db4","type":"message","status":"in_progress","content":[],"role":"assistant"},"output_index":0,"sequence_number":2} event: response.content_part.added - data: {"type":"response.content_part.added","content_index":0,"item_id":"msg_02702adc8fbb7a3a016a886db2cc3487d293743440c7837e04","output_index":0,"part":{"type":"output_text","annotations":[],"logprobs":[],"text":""},"sequence_number":3} + data: {"type":"response.content_part.added","content_index":0,"item_id":"msg_025af4c5cac58077016aa3da8db40887d2ae1be5affa1d6db4","output_index":0,"part":{"type":"output_text","annotations":[],"logprobs":[],"text":""},"sequence_number":3} event: response.output_text.delta - data: {"type":"response.output_text.delta","content_index":0,"delta":"Done","item_id":"msg_02702adc8fbb7a3a016a886db2cc3487d293743440c7837e04","logprobs":[],"obfuscation":"Lxurs9i6GOz4","output_index":0,"sequence_number":4} + data: {"type":"response.output_text.delta","content_index":0,"delta":"Tool","item_id":"msg_025af4c5cac58077016aa3da8db40887d2ae1be5affa1d6db4","logprobs":[],"obfuscation":"GLOg7U6Htyam","output_index":0,"sequence_number":4} event: response.output_text.delta - data: {"type":"response.output_text.delta","content_index":0,"delta":" —","item_id":"msg_02702adc8fbb7a3a016a886db2cc3487d293743440c7837e04","logprobs":[],"obfuscation":"ddtOEO5G8qFy8G","output_index":0,"sequence_number":5} + data: {"type":"response.output_text.delta","content_index":0,"delta":" run","item_id":"msg_025af4c5cac58077016aa3da8db40887d2ae1be5affa1d6db4","logprobs":[],"obfuscation":"TcsPhAyC8wu1","output_index":0,"sequence_number":5} event: response.output_text.delta - data: {"type":"response.output_text.delta","content_index":0,"delta":" the","item_id":"msg_02702adc8fbb7a3a016a886db2cc3487d293743440c7837e04","logprobs":[],"obfuscation":"vgqnnv1aITN8","output_index":0,"sequence_number":6} + data: {"type":"response.output_text.delta","content_index":0,"delta":" completed","item_id":"msg_025af4c5cac58077016aa3da8db40887d2ae1be5affa1d6db4","logprobs":[],"obfuscation":"ldIRGV","output_index":0,"sequence_number":6} event: response.output_text.delta - data: {"type":"response.output_text.delta","content_index":0,"delta":" tool","item_id":"msg_02702adc8fbb7a3a016a886db2cc3487d293743440c7837e04","logprobs":[],"obfuscation":"DCmQiYTM1Q7","output_index":0,"sequence_number":7} + data: {"type":"response.output_text.delta","content_index":0,"delta":".","item_id":"msg_025af4c5cac58077016aa3da8db40887d2ae1be5affa1d6db4","logprobs":[],"obfuscation":"hAplhvJDbiquS7Q","output_index":0,"sequence_number":7} event: response.output_text.delta - data: {"type":"response.output_text.delta","content_index":0,"delta":" returned","item_id":"msg_02702adc8fbb7a3a016a886db2cc3487d293743440c7837e04","logprobs":[],"obfuscation":"yFRGEh7","output_index":0,"sequence_number":8} + data: {"type":"response.output_text.delta","content_index":0,"delta":" Output","item_id":"msg_025af4c5cac58077016aa3da8db40887d2ae1be5affa1d6db4","logprobs":[],"obfuscation":"3CyKFe1Wu","output_index":0,"sequence_number":8} event: response.output_text.delta - data: {"type":"response.output_text.delta","content_index":0,"delta":":","item_id":"msg_02702adc8fbb7a3a016a886db2cc3487d293743440c7837e04","logprobs":[],"obfuscation":"RbHxTV8NggEyqdz","output_index":0,"sequence_number":9} + data: {"type":"response.output_text.delta","content_index":0,"delta":":","item_id":"msg_025af4c5cac58077016aa3da8db40887d2ae1be5affa1d6db4","logprobs":[],"obfuscation":"HBgSXXOzpZyvRO3","output_index":0,"sequence_number":9} event: response.output_text.delta - data: {"type":"response.output_text.delta","content_index":0,"delta":" \"","item_id":"msg_02702adc8fbb7a3a016a886db2cc3487d293743440c7837e04","logprobs":[],"obfuscation":"xp600Zk49yJIDo","output_index":0,"sequence_number":10} + data: {"type":"response.output_text.delta","content_index":0,"delta":" \"","item_id":"msg_025af4c5cac58077016aa3da8db40887d2ae1be5affa1d6db4","logprobs":[],"obfuscation":"EZoZmY55gSALY8","output_index":0,"sequence_number":10} event: response.output_text.delta - data: {"type":"response.output_text.delta","content_index":0,"delta":"working","item_id":"msg_02702adc8fbb7a3a016a886db2cc3487d293743440c7837e04","logprobs":[],"obfuscation":"0oZtDdTgR","output_index":0,"sequence_number":11} + data: {"type":"response.output_text.delta","content_index":0,"delta":"working","item_id":"msg_025af4c5cac58077016aa3da8db40887d2ae1be5affa1d6db4","logprobs":[],"obfuscation":"D64Dr5Ppc","output_index":0,"sequence_number":11} event: response.output_text.delta - data: {"type":"response.output_text.delta","content_index":0,"delta":"!\"","item_id":"msg_02702adc8fbb7a3a016a886db2cc3487d293743440c7837e04","logprobs":[],"obfuscation":"1FxVUej1XOOddG","output_index":0,"sequence_number":12} + data: {"type":"response.output_text.delta","content_index":0,"delta":"!\"","item_id":"msg_025af4c5cac58077016aa3da8db40887d2ae1be5affa1d6db4","logprobs":[],"obfuscation":"MGMvO7napGzwft","output_index":0,"sequence_number":12} event: response.output_text.done - data: {"type":"response.output_text.done","content_index":0,"item_id":"msg_02702adc8fbb7a3a016a886db2cc3487d293743440c7837e04","logprobs":[],"output_index":0,"sequence_number":13,"text":"Done — the tool returned: \"working!\""} + data: {"type":"response.output_text.done","content_index":0,"item_id":"msg_025af4c5cac58077016aa3da8db40887d2ae1be5affa1d6db4","logprobs":[],"output_index":0,"sequence_number":13,"text":"Tool run completed. Output: \"working!\""} event: response.content_part.done - data: {"type":"response.content_part.done","content_index":0,"item_id":"msg_02702adc8fbb7a3a016a886db2cc3487d293743440c7837e04","output_index":0,"part":{"type":"output_text","annotations":[],"logprobs":[],"text":"Done — the tool returned: \"working!\""},"sequence_number":14} + data: {"type":"response.content_part.done","content_index":0,"item_id":"msg_025af4c5cac58077016aa3da8db40887d2ae1be5affa1d6db4","output_index":0,"part":{"type":"output_text","annotations":[],"logprobs":[],"text":"Tool run completed. Output: \"working!\""},"sequence_number":14} event: response.output_item.done - data: {"type":"response.output_item.done","item":{"id":"msg_02702adc8fbb7a3a016a886db2cc3487d293743440c7837e04","type":"message","status":"completed","content":[{"type":"output_text","annotations":[],"logprobs":[],"text":"Done — the tool returned: \"working!\""}],"role":"assistant"},"output_index":0,"sequence_number":15} + data: {"type":"response.output_item.done","item":{"id":"msg_025af4c5cac58077016aa3da8db40887d2ae1be5affa1d6db4","type":"message","status":"completed","content":[{"type":"output_text","annotations":[],"logprobs":[],"text":"Tool run completed. Output: \"working!\""}],"role":"assistant"},"output_index":0,"sequence_number":15} event: response.completed - data: {"type":"response.completed","response":{"id":"resp_02702adc8fbb7a3a016a886db26d2087d2a102898b55fe47fd","object":"response","created_at":1787325874,"status":"completed","background":false,"completed_at":1787325874,"error":null,"frequency_penalty":0.0,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"max_tool_calls":null,"model":"gpt-5-mini-2025-08-07","moderation":null,"output":[{"id":"msg_02702adc8fbb7a3a016a886db2cc3487d293743440c7837e04","type":"message","status":"completed","content":[{"type":"output_text","annotations":[],"logprobs":[],"text":"Done — the tool returned: \"working!\""}],"role":"assistant"}],"parallel_tool_calls":true,"presence_penalty":0.0,"previous_response_id":null,"prompt_cache_key":"jp:conversation:1577836800000000","prompt_cache_retention":"in_memory","reasoning":{"context":"current_turn","effort":"minimal","mode":"standard","summary":"detailed"},"safety_identifier":null,"service_tier":"default","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tool_usage":{"image_gen":{"input_tokens":0,"input_tokens_details":{"image_tokens":0,"text_tokens":0},"output_tokens":0,"output_tokens_details":{"image_tokens":0,"text_tokens":0},"total_tokens":0},"web_search":{"num_requests":0}},"tools":[],"top_logprobs":0,"top_p":1.0,"truncation":"auto","usage":{"input_tokens":136,"input_tokens_details":{"cache_write_tokens":0,"cached_tokens":0},"output_tokens":13,"output_tokens_details":{"reasoning_tokens":0},"total_tokens":149},"user":null,"metadata":{}},"sequence_number":16} + data: {"type":"response.completed","response":{"id":"resp_025af4c5cac58077016aa3da8d52b887d29b745bd8355c325a","object":"response","created_at":1789123213,"status":"completed","background":false,"completed_at":1789123213,"error":null,"frequency_penalty":0.0,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"max_tool_calls":null,"model":"gpt-5-mini-2025-08-07","moderation":null,"output":[{"id":"msg_025af4c5cac58077016aa3da8db40887d2ae1be5affa1d6db4","type":"message","status":"completed","content":[{"type":"output_text","annotations":[],"logprobs":[],"text":"Tool run completed. Output: \"working!\""}],"role":"assistant"}],"parallel_tool_calls":true,"presence_penalty":0.0,"previous_response_id":null,"prompt_cache_key":"jp:conversation:1577836800000000","prompt_cache_retention":"in_memory","reasoning":{"context":"current_turn","effort":"minimal","mode":"standard","summary":"detailed"},"safety_identifier":null,"service_tier":"default","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tool_usage":{"image_gen":{"input_tokens":0,"input_tokens_details":{"image_tokens":0,"text_tokens":0},"output_tokens":0,"output_tokens_details":{"image_tokens":0,"text_tokens":0},"total_tokens":0},"web_search":{"num_requests":0}},"tools":[],"top_logprobs":0,"top_p":1.0,"truncation":"auto","usage":{"input_tokens":146,"input_tokens_details":{"cache_write_tokens":0,"cached_tokens":0},"output_tokens":13,"output_tokens_details":{"reasoning_tokens":0},"total_tokens":159},"user":null,"metadata":{}},"sequence_number":16} diff --git a/crates/jp_llm/tests/fixtures/openai/test_tool_call_required_reasoning__conversation_stream.snap b/crates/jp_llm/tests/fixtures/openai/test_tool_call_required_reasoning__conversation_stream.snap index e57be6444..81f030721 100644 --- a/crates/jp_llm/tests/fixtures/openai/test_tool_call_required_reasoning__conversation_stream.snap +++ b/crates/jp_llm/tests/fixtures/openai/test_tool_call_required_reasoning__conversation_stream.snap @@ -243,19 +243,19 @@ expression: v { "timestamp": "2020-01-01 00:00:00.0", "type": "chat_response", - "reasoning": "**Analyzing tool call options**\n\nI need to call a tool, specifically functions.run_me, which requires setting the \"bar\" parameter as \"foo,\" but \"foo\" can be null or a string. I’m considering whether to use multi_tool_use.parallel for multiple calls, but it only works for functions tools. Since it seems simpler, I'll just call functions.run_me directly and use the commentary channel for this. My plan is to call it with \"foo\" set to null.", + "reasoning": "", "metadata": { - "openai_item_id": "cnNfMDI3MDJhZGM4ZmJiN2EzYTAxNmE4ODZkYWRmODMwODdkMmI2NmYxOWFjNzQyZDRmMjc=", - "openai_encrypted_content": "Z0FBQUFBQnFpRzJ4bmFXVEF3Vng3eDA0Y3I1eTZRRFFWT3ZkMGVsWlFUR2kyN0JjRVVyM0JJRzBPYVVyOVZURnFmdWtuem11VU9hdkNlV21jVlRSRU1YLVJRZzVZOFRySXV0UFBHblQ3eUJsYXY0d05ibnQwWUV3X3hmLVRENXBIbGE5Wk1OYU1reEVEa2ZxZkJWcGNfeTIydFNYSzRia3UtTHpBcWRrandYNmRWZWhZWFcwUllTY1lYbjBpeVBOb09iYWQ2a0Q3NGlqemhBVHVUakd0ekgtbDRhWE4yTC03Y1Z5NUhtTm8xNWxtX1hTd3l5eWExTk43X0FvLWk5eWw4QzdyS2k5R3Zad1NzdVQzNGg4Ukw1alJ4aUJ4Ni1wVGlyNjg3ZmFienhZNHloNFh3bm1VRkZuX1ZXYWh3a2xzSF93N0s1YXNfZlQ0TGtEZmZRc1k4eGw5dE1feUFMRDNpUmNvYmVFX0VYR1p2YkJteUM3WDJzMTlRNUxDU1lLTXNXUzE1YzZzWVFOVVNNUUU1ZkN5T0l4cnVKYkR6VEJ3UmRGS005WkFNNVVhWThRWllGWEtwUXBLUS1LbnpTQ3lqN0pGaW9oSE5WbnJHblEwa1JtdE83NTlnUmFoNDl3MXNhaXRfdFkyVUtoUzZEUDE4WERPdzFQbHpuSlROdG9fdUROTFN4TlpnNno4N3didTFqYnVUMkVCZWlQWFFfaFhyUmswSGJGbzZjeDNXOFlkQW9JQkphRlpTLTNvNk5odEhtTGRzdjJ4MnBINTRBWjlWSXoybExTMko1RTVPM2J3S1NSUEFGdThQUEF5S05acnMzb1plNkx4WGJ1cnFiTkR0bl8tOVAyU0VQTHlfTEpMRFRCdG91bXNJM09XaHhJLTItejhZSXpkWGpNMWhxWV9rbGtpX25RRHhSWlRlUkEyUEhUN2lfMG1HRUIybTE2ZklkNEF1TnJSUmV0T19HQlc1NVRxMXBOZGRaVE5yUFZFWDlpVDJDTTVPQjVmSTZtVjlreEFueElzekJNQzhmZnNobzNGVWdUcGR5QmpEbjBSdzZQcERDQmc1NDNDVjJRUl8xckd1anhNVXFnTGR5ZHhUNVZNMFFsbm9pV1M5S2NNWnNzdkNDd2tHdmpYSmpsbHluYk5XdXVLNjJLOUlXWFYzc2tGWFhENXd1YzJMYnpiY3dVY3pEemtlTzBCYnU2ZXQtUDRmUkRkNVp4TUZ6X3V6RTFaSzFNSElwUTBrWF9ERHNGaTFmckR6aVE5eWk0cFhnN2o0UzFJb3lDU1h3cUVRRGY3S1RuVlcxS1U3MEoxU0xORF81ZHhOa19VWkRSVnZISXRCSHd5a0UxdWREaC00eEJfWVVYOWlmV00wTkk2UWtDb0cxSGd3ZFRRWV9sM3J4TERHNElTRTVhcnJfVHc1Q2pmaHBYMTl3QndQaHF0QjNFU2VRSDZ1dGtQa0tnMVoyQTdvdWYyVmJYa1Y2cHJIUjlzTm1PckFlMlJ2WnpxUm9yNGNmdDNUZkhWcC1ldVJLREwzaVBWanJ3TEMtT1ZzSFBHbmlJaVM2VTN3c2RpNjdKREVRckxvcGFyVlRTSU1pM0E4Tk1lZDM3MVVyakxXbEdHZklDR0pQeTZUVjlZSnpReDR6aEZoVE52dWVLQlpyTWx0czhERjlHVktxdjhVRHNmeEVXX3h4SUdrU3dTbDJVam1SemtGRVdMR292LXE1RF9nN18wY0VGQ04yYm8zdWk1QVpJNWx2MTJFb003UDlwYk9SeGg3MWhUMGNuN0dUbTdBdmwxX2xKZGxCaGxTdTEtcFRfaldncEpBdGVtXzZUMHNVckI5a2NndTNqRkpiV2h1RDZLTTFaR18weEIzNUYtdTdVektPMUg0eVZsV1FETVRqZTNPWFp3cEZFN2ZoVndUV0hmYTgwRXJpeUI5WkhLTWRBa05JMGJhZUI1OWxacngxRlB1OVlMeHZ0cDA3OTNLTE00SjdfcUlLSmhwMFpWUjREeHk5VUUxbEluSlVYZXFUTjBtbTV0M2ZCTjZIYXlRanhaLVA1UC1nYlhtOHhVeGdyUDY5UHZkQmIzMkhnZ3M0aHp3MEt3R1JzUkVELW5SX1BWWTVNVEdJTHM3bVZfTWU5RVBMcmlzSmRBcUUwZDNLbTd6cmM2NDNIWTlfcnB1TGlBenF4cjM1WmJQOHB6a0NRbFhveFBCLVphbV9weHE4RUoxUm9YM0JHdWt2b28xRDgzVnVscXNDRlNfeVFwVWF0LW1xNDBuTmZlU3F1SHMwPQ==" + "openai_item_id": "cnNfMDI1YWY0YzVjYWM1ODA3NzAxNmFhM2RhODk4YzFjODdkMjg4NGU4NjM0OTFiMjJmMWU=", + "openai_encrypted_content": "Z0FBQUFBQnFvOXFOQnhkTnhWc1FGdzNJa1B0eDVJQUJJMW9TOU4wcTlaRVRWVmFNUTljbmRFY3dxZ2o0RFBPM0JldFE3UUZ6LV9NNFRxOW1uQmhVV1ZPWG5IMGJucEc2LVRVVGwtaHA4OTFYNnRBOFVjUzRHWi1JSk4zNjdzZXlyOGZ3X05kbEFTRFp4azR1ZFo5czc0bE1QSUJwa25wWFhBWXliM3pQdVc0TkVrYWloaWF2eFBJVmN0OF80LVVxZ1BoZGNPQzVNSVFjYjFTYllDVnVTWTlVRWpmNGYwTVNzSWR5V2trc2VveVdRMEl4eEREOVd3eEJVOWxmaWRIVUlhMlhpTkJvQzBSdmFVSEQwcU1ZWENPMjFTR0xiZ3BEelV1dk93OXZVMVV2M1h4OV9ZWGt3M2s4UE8wdFNzMGduMnNzb0ExcDhxYVpCUTdpMXE4TGJXZm5IS3R1cGpmNlgzc3ZhY3E5Wk51dmlxbXBDdFRCRU5fSUhid01nNzloU01RNnVhN0ZtbmJmang2eC02UFJDdXFPLUJhYnBfY0dLc0VFeDA0RDg3eGo1Z2czeE14VUlXRUJWOHVCeHhmeVVmVmpRNXdJWWFDWXhmR1ZRbFFiWUFRZm5VelZ5MzZLUENlYXJXT2dMVUZTbmJ1ZmNGQnlsYndUbzk4UEl4NEk5eWpjLU1IM0hyX1puaE5XQngzU1J1ZFExUjZMX0hYOVZkalVodU55WlVIRkVieFd6dFE0NXdhUURrcVItNmR2MlpYNER2a3Nfdnk5M1d2cWVGSlNINHU4ekI1Q2VzTGpOdjhmZTVuM3RsTnl3S1h3azJtRXR0TUFtVEVOZVlxaVpJb3JjSFFuZ1B3T0JUa1JFbEpZcEs5eFprbGwxUUFJZmZnVmRRRjctcFY4M1BOZ3lMSlUyYU96RlMzMGlVc2ZLR3ZfQTRZSHNYNXExeGpBbUYyMC1yN29HTVJuREhUeVZRYzF1Y01NeXVkRGJ0Sk1ybjZqQUFwLWVWWnJaWTJrSnNmR0k0WGxNWUx6RHRBS3oxendrYVBWa2pEemNFbEJHOXlVS0hjbllnRUVzNVBTVlVwcUd6LXRkenY0S19xdGZoVEc1OEUzX2hSVGNvM0lsR2l6ck9uNldfSEw4T0tnc24tUW13UW5ldEhhcmFlS004dkJVWWp4cHdFTDlvM0U2ekcwd0NzbGRoQ2ZlclExVW5DRHJqdFA4eGkzWDdRcTJKV2dvWjVmQTBCRzBUUUxhRE9RRjBkbS1KUHhOMFNEMVBDNWYzSTNVYlZkN2NkU2ZTeC04dGlwYnE4MXhSRHVvRGlrUXYyb0JoZnhGWlVrS3RmZnZ6OEY0NU5KU3JuSzNtNXBMb3NZYXZxOHNMTEZDa1NzMXU1azhLY0hzdmxsVjBMMGNWQTRFR3hjWjJ1MldjdkZVaHhNN3dZd2szZDZDNlVtbE9QMUdCMGFVWm1VZ1B0NFI5bzh3TG9TOV9zcldXV3BJUTA0V1FuOXAtcXJvWDU5YkJuVUNvbnFsWEpSM2VkY045VTJOcDNQX2I3eHZETndqSFYzRkxlN2txMGJFMzFpWkRQTUpDaURjeThheEhzNC1PY0RhcEhzUENuNXd6THZPampBc3NNOUhDRV9OREFfdU91YXpCR1lEa1p5THF4cVJ6ZTVRQmxxaU84X3NrZ2pCVXNBa0NLcmhDWEVhVnJBVkdvSXhSaTB1ai1kOVhudUJhYXk1ZlJpeTY5bjJieVNlUjl1TnFZWGxQYi1adk9BSlNSZ3dsZjVLRUl5d3FfLWNfQk1sTW5najdoenhfVG1YVGRUeGQ1Q25JQ3VGWVg2emJWRnNPSHdGNXM3aFNNMUhGYUtmMTBLa20wSE5ycmxfZWluQThpLXhwcTVkakhWMGJoQm1xVkVQVmRnVXd2U1hIb0FTUmprY0FiajcyUFBFNDY0TkxpZVhKck1SQ3NRNWQ5VlR5T09QSWpnc2NZNnh3TmZPdFVyTW1CSEllUjU0RHFXbjNWdW1mOWhKczh1X2h0V3hVV3ZKblVXRExvOGt4RWlLZm5CX0k1TWp3NXh3WWxXelEyNmlCV1Vpc0JCTFNySDVtN3hIandmdWMwLXBOczRBMG9PRThVZDJTN1hURkVJVU9YOTJWQWpGd0RnYTNzVWlDZ1ZXdkdlZDFGd0lkT1RadnVJX1R1NndIZmt1QnJLSEthY1g3RzRXQ0dYOXFsR1ZHM210ZjVpUDA2Y0dLLW1mZHlmSzZ4aElDWTRXRGVmaXRTc1BKc3MwTnBJNXZxVDBOX2dMQkVaVTVrbF83RUZwMVRJcjU5M01ZcDljYjBDOVVtTFozUmVhTFpYYlB3RnlYT0NUNmlwZ24ySG9tbz0=" } }, { "timestamp": "2020-01-01 00:00:00.0", "type": "tool_call_request", - "id": "call_i95it8x7WlrY7fZeliTs6shY", + "id": "call_1W5hSpB0eF8Xllvo5dyLR65p", "name": "run_me", "arguments": { - "foo": null, + "foo": "ZXhhbXBsZSBpbnB1dA==", "bar": "Zm9v" } }, @@ -275,16 +275,16 @@ expression: v { "timestamp": "2020-01-01 00:00:00.0", "type": "tool_call_response", - "id": "call_i95it8x7WlrY7fZeliTs6shY", + "id": "call_1W5hSpB0eF8Xllvo5dyLR65p", "content": "d29ya2luZyE=", "is_error": false }, { "timestamp": "2020-01-01 00:00:00.0", "type": "chat_response", - "message": "Done — the tool returned: \"working!\"", + "message": "Tool run completed. Output: \"working!\"", "metadata": { - "openai_item_id": "bXNnXzAyNzAyYWRjOGZiYjdhM2EwMTZhODg2ZGIyY2MzNDg3ZDI5Mzc0MzQ0MGM3ODM3ZTA0" + "openai_item_id": "bXNnXzAyNWFmNGM1Y2FjNTgwNzcwMTZhYTNkYThkYjQwODg3ZDJhZTFiZTVhZmZhMWQ2ZGI0" } } ] diff --git a/crates/jp_llm/tests/fixtures/openai/test_tool_call_required_reasoning__raw_events.snap b/crates/jp_llm/tests/fixtures/openai/test_tool_call_required_reasoning__raw_events.snap index 54f9ed790..a6faf7a72 100644 --- a/crates/jp_llm/tests/fixtures/openai/test_tool_call_required_reasoning__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/openai/test_tool_call_required_reasoning__raw_events.snap @@ -11,656 +11,28 @@ expression: v ), metadata: {}, }, - Part { - index: 0, - part: Reasoning( - "**Analyzing tool call options**\n\nI", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " need", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " to", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " call", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " a", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " tool", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - ",", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " specifically", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " functions", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - ".run", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - "_me", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - ",", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " which", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " requires", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " setting", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " the", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " \"", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - "bar", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - "\"", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " parameter", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " as", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " \"", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - "foo", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - ",\"", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " but", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " \"", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - "foo", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - "\"", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " can", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " be", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " null", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " or", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " a", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " string", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - ".", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " I", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - "’m", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " considering", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " whether", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " to", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " use", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " multi", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - "_tool", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - "_use", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - ".parallel", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " for", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " multiple", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " calls", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - ",", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " but", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " it", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " only", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " works", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " for", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " functions", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " tools", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - ".", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " Since", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " it", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " seems", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " simpler", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - ",", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " I'll", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " just", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " call", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " functions", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - ".run", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - "_me", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " directly", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " and", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " use", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " the", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " commentary", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " channel", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " for", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " this", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - ".", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " My", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " plan", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " is", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " to", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " call", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " it", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " with", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " \"", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - "foo", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - "\"", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " set", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " to", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - " null", - ), - metadata: {}, - }, - Part { - index: 0, - part: Reasoning( - ".", - ), - metadata: {}, - }, Flush { index: 0, metadata: { - "openai_item_id": String("rs_02702adc8fbb7a3a016a886dadf83087d2b66f19ac742d4f27"), - "openai_encrypted_content": String("gAAAAABqiG2xnaWTAwVx7x04cr5y6QDQVOvd0elZQTGi27BcEUr3BIG0OaUr9VTFqfuknzmuUOavCeWmcVTREMX-RQg5Y8TrIutPPGnT7yBlav4wNbnt0YEw_xf-TD5pHla9ZMNaMkxEDkfqfBVpc_y22tSXK4bku-LzAqdkjwX6dVehYXW0RYScYXn0iyPNoObad6kD74ijzhATuTjGtzH-l4aXN2L-7cVy5HmNo15lm_XSwyyya1NN7_Ao-i9yl8C7rKi9GvZwSsuT34h8RL5jRxiBx6-pTir687fabzxY4yh4XwnmUFFn_VWahwklsH_w7K5as_fT4LkDffQsY8xl9tM_yALD3iRcobeE_EXGZvbBmyC7X2s19Q5LCSYKMsWS15c6sYQNUSMQE5fCyOIxruJbDzTBwRdFKM9ZAM5UaY8QZYFXKpQpKQ-KnzSCyj7JFiohHNVnrGnQ0kRmtO759gRah49w1sait_tY2UKhS6DP18XDOw1PlznJTNto_uDNLSxNZg6z87wbu1jbuT2EBeiPXQ_hXrRk0HbFo6cx3W8YdAoIBJaFZS-3o6NhtHmLdsv2x2pH54AZ9VIz2lLS2J5E5O3bwKSRPAFu8PPAyKNZrs3oZe6LxXburqbNDtn_-9P2SEPLy_LJLDTBtoumsI3OWhxI-2-z8YIzdXjM1hqY_klki_nQDxRZTeRA2PHT7i_0mGEB2m16fId4AuNrRRetO_GBW55Tq1pNddZTNrPVEX9iT2CM5OB5fI6mV9kxAnxIszBMC8ffsho3FUgTpdyBjDn0Rw6PpDCBg543CV2QR_1rGujxMUqgLdydxT5VM0QlnoiWS9KcMZssvCCwkGvjXJjllynbNWuuK62K9IWXV3skFXXD5wuc2LbzbcwUczDzkeO0Bbu6et-P4fRDd5ZxMFz_uzE1ZK1MHIpQ0kX_DDsFi1frDziQ9yi4pXg7j4S1IoyCSXwqEQDf7KTnVW1KU70J1SLND_5dxNk_UZDRVvHItBHwykE1udDh-4xB_YUX9ifWM0NI6QkCoG1HgwdTQY_l3rxLDG4ISE5arr_Tw5CjfhpX19wBwPhqtB3ESeQH6utkPkKg1Z2A7ouf2VbXkV6prHR9sNmOrAe2RvZzqRor4cft3TfHVp-euRKDL3iPVjrwLC-OVsHPGniIiS6U3wsdi67JDEQrLoparVTSIMi3A8NMed371UrjLWlGGfICGJPy6TV9YJzQx4zhFhTNvueKBZrMlts8DF9GVKqv8UDsfxEW_xxIGkSwSl2UjmRzkFEWLGov-q5D_g7_0cEFCN2bo3ui5AZI5lv12EoM7P9pbORxh71hT0cn7GTm7Avl1_lJdlBhlSu1-pT_jWgpJAtem_6T0sUrB9kcgu3jFJbWhuD6KM1ZG_0xB35F-u7UzKO1H4yVlWQDMTje3OXZwpFE7fhVwTWHfa80EriyB9ZHKMdAkNI0baeB59lZrx1FPu9YLxvtp0793KLM4J7_qIKJhp0ZVR4Dxy9UE1lInJUXeqTN0mm5t3fBN6HayQjxZ-P5P-gbXm8xUxgrP69PvdBb32Hggs4hzw0KwGRsRED-nR_PVY5MTGILs7mV_Me9EPLrisJdAqE0d3Km7zrc643HY9_rpuLiAzqxr35ZbP8pzkCQlXoxPB-Zam_pxq8EJ1RoX3BGukvoo1D83VulqsCFS_yQpUat-mq40nNfeSquHs0="), + "openai_item_id": String("rs_025af4c5cac58077016aa3da898c1c87d2884e863491b22f1e"), + "openai_encrypted_content": String("gAAAAABqo9qNBxdNxVsQFw3IkPtx5IABI1oS9N0q9ZETVVaMQ9cndEcwqgj4DPO3BetQ7QFz-_M4Tq9mnBhUWVOXnH0bnpG6-TUTl-hp891X6tA8UcS4GZ-IJN367seyr8fw_NdlASDZxk4udZ9s74lMPIBpknpXXAYyb3zPuW4NEkaihiavxPIVct8_4-UqgPhdcOC5MIQcb1SbYCVuSY9UEjf4f0MSsIdyWkkseoyWQ0IxxDD9WwxBU9lfidHUIa2XiNBoC0RvaUHD0qMYXCO21SGLbgpDzUuvOw9vU1Uv3Xx9_YXkw3k8PO0tSs0gn2ssoA1p8qaZBQ7i1q8LbWfnHKtupjf6X3svacq9ZNuviqmpCtTBEN_IHbwMg79hSMQ6ua7Fmnbfjx6x-6PRCuqO-Babp_cGKsEEx04D87xj5gg3xMxUIWEBV8uBxxfyUfVjQ5wIYaCYxfGVQlQbYAQfnUzVy36KPCearWOgLUFSnbufcFBylbwTo98PIx4I9yjc-MH3Hr_ZnhNWBx3SRudQ1R6L_HX9VdjUhuNyZUHFEbxWztQ45waQDkqR-6dv2ZX4Dvks_vy93WvqeFJSH4u8zB5CesLjNv8fe5n3tlNywKXwk2mEttMAmTENeYqiZIorcHQngPwOBTkRElJYpK9xZkll1QAIffgVdQF7-pV83PNgyLJU2aOzFS30iUsfKGv_A4YHsX5q1xjAmF20-r7oGMRnDHTyVQc1ucMMyudDbtJMrn6jAAp-eVZrZY2kJsfGI4XlMYLzDtAKz1zwkaPVkjDzcElBG9yUKHcnYgEEs5PSVUpqGz-tdzv4K_qtfhTG58E3_hRTco3IlGizrOn6W_HL8OKgsn-QmwQnetHaraeKM8vBUYjxpwEL9o3E6zG0wCsldhCferQ1UnCDrjtP8xi3X7Qq2JWgoZ5fA0BG0TQLaDOQF0dm-JPxN0SD1PC5f3I3UbVd7cdSfSx-8tipbq81xRDuoDikQv2oBhfxFZUkKtffvz8F45NJSrnK3m5pLosYavq8sLLFCkSs1u5k8KcHsvllV0L0cVA4EGxcZ2u2WcvFUhxM7wYwk3d6C6UmlOP1GB0aUZmUgPt4R9o8wLoS9_srWWWpIQ04WQn9p-qroX59bBnUConqlXJR3edcN9U2Np3P_b7xvDNwjHV3FLe7kq0bE31iZDPMJCiDcy8axHs4-OcDapHsPCn5wzLvOjjAssM9HCE_NDA_uOuazBGYDkZyLqxqRze5QBlqiO8_skgjBUsAkCKrhCXEaVrAVGoIxRi0uj-d9XnuBaay5fRiy69n2bySeR9uNqYXlPb-ZvOAJSRgwlf5KEIywq_-c_BMlMngj7hzx_TmXTdTxd5CnICuFYX6zbVFsOHwF5s7hSM1HFaKf10Kkm0HNrrl_einA8i-xpq5djHV0bhBmqVEPVdgUwvSXHoASRjkcAbj72PPE464NLieXJrMRCsQ5d9VTyOOPIjgscY6xwNfOtUrMmBHIeR54DqWn3Vumf9hJs8u_htWxUWvJnUWDLo8kxEiKfnB_I5Mjw5xwYlWzQ26iBWUisBBLSrH5m7xHjwfuc0-pNs4A0oOE8Ud2S7XTFEIUOX92VAjFwDga3sUiCgVWvGed1FwIdOTZvuI_Tu6wHfkuBrKHKacX7G4WCGX9qlGVG3mtf5iP06cGK-mfdyfK6xhICY4WDefitSsPJss0NpI5vqT0N_gLBEZU5kl_7EFp1TIr593MYp9cb0C9UmLZ3ReaLZXbPwFyXOCT6ipgn2Homo="), }, }, Part { index: 1, part: ToolCall( Start { - id: "call_i95it8x7WlrY7fZeliTs6shY", + id: "call_1W5hSpB0eF8Xllvo5dyLR65p", name: "run_me", + decoding: Some( + ArgumentDecoding { + omit_null: [ + "foo", + ], + properties: {}, + items: None, + }, + ), }, ), metadata: {}, @@ -687,7 +59,16 @@ expression: v index: 1, part: ToolCall( ArgumentChunk( - "\":", + "\":\"", + ), + ), + metadata: {}, + }, + Part { + index: 1, + part: ToolCall( + ArgumentChunk( + "example", ), ), metadata: {}, @@ -696,7 +77,7 @@ expression: v index: 1, part: ToolCall( ArgumentChunk( - "null", + " input", ), ), metadata: {}, @@ -705,7 +86,7 @@ expression: v index: 1, part: ToolCall( ArgumentChunk( - ",\"", + "\",\"", ), ), metadata: {}, @@ -765,35 +146,35 @@ expression: v Part { index: 0, part: Message( - "Done", + "Tool", ), metadata: {}, }, Part { index: 0, part: Message( - " —", + " run", ), metadata: {}, }, Part { index: 0, part: Message( - " the", + " completed", ), metadata: {}, }, Part { index: 0, part: Message( - " tool", + ".", ), metadata: {}, }, Part { index: 0, part: Message( - " returned", + " Output", ), metadata: {}, }, @@ -828,7 +209,7 @@ expression: v Flush { index: 0, metadata: { - "openai_item_id": String("msg_02702adc8fbb7a3a016a886db2cc3487d293743440c7837e04"), + "openai_item_id": String("msg_025af4c5cac58077016aa3da8db40887d2ae1be5affa1d6db4"), }, }, Finished( diff --git a/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_required_reasoning.snap b/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_required_reasoning.snap index cf77c86ee..6c63cc46d 100644 --- a/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_required_reasoning.snap +++ b/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_required_reasoning.snap @@ -13,10 +13,10 @@ expression: v }, ), metadata: { - "openai_encrypted_content": String("gAAAAABqiG25K01qfTbWlALE9KLuZO5uv_69IxBdl9djIR6du60aqGAOQnBooMRFBgKFWHUezx-zJWqPLMu6a6A5IHCesUr3nqSMfrODDbSEaUc4EPYwKkylaQomJiKW8fWXhcHpSNndayz1YabVw3foRQ3WkMCbDJDOqId14O7iNvxtdFi-q0zVWBDPJc3QnlyZkXSUIPvsGs0XN26rEuzrYYE8lCBSClZuk4bxapD5T0c3Ol1a46WMrjE5uqteJ0j4lm3s-eXgkER0TAodzKQrGlN0XEJv7wj-W10vMAdt_rjNgnX4DZNnBXZ3t7QsS2R8g7qHezWdkV2D9hIIaObfxyqbnjPiQ1F-1PThKhUhDkOG9h_cKJ-EBN-QGLk6e2Eg247icjSq1HpsrAU5mPZUPSSeVBKWD_T2y_iZalhgwJxHFNh4D7vaQnN6lfUUmDXOnDki49srtv_9bIj6uGLqZNIZZcxCZJ2gMXMmhrzmqr_ms8L3SuJvxGxUDd8toqDKAGsLhk_3KbDC0BWyr7lvFpn-H2RetMT67wKDmYM42HRxYuiA0h077kuvPFdT3ZECthu0Qap9SXUnbcAE3hXGIHf-239WiAS1J9BkxfaSqb0fToDpH5PHn4ZTLDncNQrG5U6RfMA6L1fkVcvbrmqWVLdIGA4sFEpLG580guBkBvuxj0pUbMhy1mSOIgWikH_FHlhbZCP4tbXnCbbCcSNghe-UlPP-rWoxqdL1I4OOe4zn99jg0cTZhhiRZ-ZfYG-MXywsFSpLt9_seN1RKE9nkm7gByoZ7YiXkqjplLMEhraa-KLNYoUK0-awMQaYctW_PKUm9dSn_TRHFxARdTmsS-vt28juOPoFxHKBL-MHG1PU8obM7E_YRGfJ2vBu44KTxOvciHp86jiRXWuIVJ3bV4mxmjjmHzOscsv-Zxj1QamfrFmVJA0lUCcZBY1AqYEQ0ugPAtlhkZmy3mrFtnjuNaYtL_mJyxt9YchPdifJKPsjZczrE5-nPCnWkcdtKhO72OkOgbva2X6nL-phGvmWursqZC9JG37jcmz1OLQklcLf0tw1acbWnN34nfIWtBmUlOwtLwpEA2TRdqJFG3fvcyxopoN-OF2CUETz2s4Lxqa3rQUrTwCu_KX6Ext38gmMTO5oP5XUBLL6jswj_4ZSwjrivIc41YSp9oahfEPivbGyfEWGySmrtJXgioqGwdLeSC57kz47ClXXEVDl5vtoUnrX5xVkZxdQn3MO2YTRQ30Fp7W7sP3XAxvfQr0nhLB0W2kcB0WUaOcsWyqHzfOd7TEB9_VKjPn_jfqakHFO8EvHxCGkVPNSPMXhMWhL0Z0vbOEgx9XGEHlgfdaUPSPNzoSdsgpRUCp2fQnyu9igUnOLJ76iHdnFJDr5WP6cK3Y0EGZRCrO7Mfhi-rb-M6HilU4rvyNleA-sl47N8Wy9_BRXOIY0b8KAgvP3Tu2Kbd1VLiUcgB4icEOZOOSS7VerFU5Hq5mbaLc5sTUnyAZG2uBISXe7xgk2350WP4JgWSE05GNbpRKFy969fCwY9VfNXT532fG-za76HRW21D8Q_XY-w0_IdpQdZiZDq0WeYQBkyagwZQ2SAl_BeXdvaHhb8aUHa-OY5bnEps5exIjChuiSG6LJQkAcUiYU292BNbJCY5L2IrC_zYgmZDV5bguoKEBTaiU02J5idzXqc3wkFhvrKMZqkRdTgFFhe4ArgiNwDfOAvgRVW4vUdL6cdTx4_6ezirZgAHqmVV9PqYwterkTd-HrioOdqURBMlirBjL2PqQdLl2QGRZM_kL57p0xL1oG4a_RfA==.eyJlbmRwb2ludF9zbHVnIjoib3BlbmFpL2dwdC01LW1pbmktMjAyNS0wOC0wN3xvcGVuYWkifQ"), + "openai_encrypted_content": String("gAAAAABqo9qVWVgVSs70JsmgeHy5uwfc1BUsd5iz5SS_x-dhR9X4-XKYOffk-ctbBFuNRVmQ_G5otogvIsf0A0MUxHKzLF0FDmVB_xgBUZjE8NhTD6dhjYv4S4WqiWAzBkLiCqeaXPx8Tftt5snFJmb7nPXFjaDc7F6G0PZB_3rzE28gJOe-GUBf66rwhuB-tFoDjIERRU7tWgvGRk02I-f5XEGbw8NJdLzwTAOPy3tjZ2bccfP_YD0n91XAcvMSdLLVWp0x8VmYWhV2-4lD_1sKOChkFyUIn_Njvt86WJqegNLA75PvLsy7rqq5Hp61noXD5QtYvczx2gyJ-noNwmQXaBFqqd7m0Ys-1fmp9JE7ky5etZN4J6LOlCkzEaVOECvZ_x6eBegQSr7FlIpVlae0uhQ5aYw73OUiLsoNb1vPuRakjQ4ReZJXNPTYjGDhOPZIIDt4IZaAX10WIJr-FuW8QKxK4wvX4-qojYr65fruC3qPbKdG8zj0CbDMokToDvgC7bUtiZiKIm3sh295WI0pvl9QEzEa3Bq3A4g_nzxU1qfBmBxV1qFDbW1lo27N4n3MQRl71a9nQb9FxJWxEnFEd78KS2gMCURPawIYC3TbgNmm7PR8hJaO6bxjfhyAktBcuRlFBo3mnffEsxuaF_yUNePeoCqBTWgC3SaA6KmDF_JUH961w_0_R-7uoVhaxaYTTwMvu9vJ-xsY-823_LR4GQUTswNLzxTnOptiCRx0VsLluu_1cqjzZzOMnXAWvHNWfQBn26VDDIdtyyjFKlKEfYH6n4_Z6MVGPomBXHD4o0Yz0vd3CQ3rNWAJhcP61sOrIcjLlg3h4vyBXVDveIzFHclyjbDnlPLFDqXuUuXbJ7dGux9a01pYvwMggDAUFhCdr1IsqQdXl70Yd0RRhThERjKSvZf5bvoWMn_xpjBWuZmolt1fiJY_giSvMEsA7KU9sc-i0mOm1sSht7Br5DIEswKOSYkb5POe8hIfgomabfDDdxFnKPbR9mcFSIVVRFc0mLgcyTlUFvaeJL_aauXBdmVrTepw-QIrHxgTg5pPeSSVWG1NhpZg2OnYJOJg7-93fUquRdzXilCKVLGdh-JfZ1-nDXHG9s3-HwLA6AHyLO4NCw8X87mcVS60DgZUC3aO-jMA1WPXRzoR0QCOYvqAD3a4eHNiErIcc29g7vwQL7h856YSFnBSeiPDcI_LY2BWmiDaq_rwC1_jm9vY5Nc6nQEXYTb0T3CSLW9pLrLjCir2pIgigW_zQt7w-K_4n_NNs1Ik4M1LeKyFhNe92y7e7wxxh3uDj9iDfsTqJooO0KSvQ7BnUta1LL8b6Gauxu5Lm7MVczOibnZYGNyV6cgC-3oIxdsoMMDvTobIVltkZNF9ynU1buWmTmiTysu140io8CI8VcLkC3PiwR2OwNaOi956UnROlcunuIkeIXqQmO9PH6jGQ1PbTO-_7vG8Eg2ZVGlDsDG3HYwQMPjINNuim3DA1F_HrZDKFXHRP7-U2Ful8ZTBV3ioUM7mFEi78hZVD_T3hngOpS6yjGFcM-A2MWLjKMlDsF9dCDGSGXYbn3UFxjQeQtAHTSMKQDlgr5KizSMEWWIMZS__lxuErK5Z3BKHo_NANpl0xYce2pfJnU7hiliNrfnQwSaDr7pXZZDcxWvVjKl8JozsXxvzSu-kSab67MajPbpxXzE9992oSXYOSrxR3iazQcoro9-8s2d74fzgpRkrIePZQyAYTPjd9GlR6c1M902pn4mCH6kP4fBwCux4lKm_iBwCgwWU-sqp2Kcu9JKUDMSKQhPSR-3QspuFYJJL_kBmL1Nr8rpL83B01sS9JsAnR4dXE7fe-aQK7a2rXyFG2_dIS3M4JHfXS1GUFlpLuZOveahn2_Ys_ZEOZEp9JFaa6FgG6fwnBX_hqQwVcy7Vpl8aGiDFMa2X6nHHC4XdAaVj2-QbND7Mm6pGHNAvYa9CjnpUrT0m-TwnAT6_8S4dpUoifILkiEiRRI-zSVvdSQ==.eyJlbmRwb2ludF9zbHVnIjoib3BlbmFpL2dwdC01LW1pbmktMjAyNS0wOC0wN3xvcGVuYWkifQ"), "openrouter_metadata": Array [ Object { - "id": String("rs_0848749866e247ea016a886db6fff087d1b5b6efd41ccac47f"), + "id": String("rs_0efd722f56d64447016aa3da9389c487d19b3ba847be53365c"), "index": Number(0), "field": String("openai_encrypted_content"), }, @@ -29,10 +29,9 @@ expression: v timestamp: 2020-01-01 0:00:00.0 +00, kind: ToolCallRequest( ToolCallRequest { - id: "call_KnvO99RwD3rjBcOEPnBpNQ7O", + id: "call_NjNRzmeNIFfEhIlY1DJt8Elg", name: "run_me", arguments: { - "foo": Null, "bar": String("foo"), }, }, @@ -54,10 +53,10 @@ expression: v }, ), metadata: { - "openai_encrypted_content": String("gAAAAABqiG26cwCaeVLhIDmyWh9QS5IOMJDoVAS5Rmk2C5l_uTWY1Bvl8Ezj3LOQuyNE429nXWiWolxw0qV2uWLiFUEUJGfSqPUsCGmD4p7XhcLVub26--oj7KcP9v1k0DbwAFZBpbrGYyGCAWMZCXv_QcG6pYO_SvRk4Q5qxOPs6rMYCfJi4Ts9NW1uRzjaxq3nM6VP8Bh5h1l35sgxzQ0_F9S_0ZsEcgaS8W8PI40RpqLCk92o1eO91H9K8rQitNnuyX6NQyI5g_S3p6TycqBipPygYqcgFfqah4F-p-mpDGR7Kz8XDW5rlu_HvUd_QiUxfI_GFmBj71uToKTVJMxOPZTP54GP8zDvnU9qfKJTZ1Ig_QFH54nYshOoyw4i1TpgwpQ4NY6FXkX2rPZoBuqm_gthOENYyyS6g4IW8b23UI98Uz0d92oeI7e090mg8Y3RNJAkJqnzr68sRVSBJtRABwqnhohskJPVDbMESHhKU-kA0pERO2ROHbgizAgbJ5QKCUBcX8cTPf4bcrIYTp453l5AYoImlr4695fSMiQynt6S-U8AiBKDdExEKmxWrxMewsVLvvZvngb_hje9eAht5jSqd9cHSb0MSLUil5egHwR4f19uvgB61pgJtuOaiU54biFYyxiVZV3FWP54PBOemegTCLVu9NzraIZlYacLPJuvFWFWvmHfYkAznogNGtgN6Pbsh3oclbdNc9dz55j40DWOHcLNn7zKf2rq0_UuOSDAjEL_BrFkHIIn-kgRHSpugXWWSu-lMVt1JjqR9ltkES_dmMmoZyJTMnpLNJRreyEqR-GxsA4irGD1Rt5LXKpbkBM7t6DGryAA5uNLDd2m47fjkvY0X9u-p1x4p11ZtOv9IkCJEu8Sgb06SbsH5Q1cN_hx4SXGnhM1EUoDGfeyyAmFxtxQczCeo1-P3hraGJM0TBbWJHIwNQi04OqSKJ7Qp_EUsRZTvi7Wxd4iExRUXADK0JsJw1HiK3LKa-YilPm5mdq6_U9TSRSsX7xwCsZTPCdFvGcpm9Jyf9xKELpHV8Gz5f6nZwHv3cuxrIMEmCU43OX3p-EoLRqjbk3DuSmUkAY07DnwJVdWmncTIaqV3koAbv1GEz0cLu6xnEy7iNiv3UZ6m0jpSi9xJpD2kDUodeGLZywcXxLhEwOqSwbECGr7yXahWJtQb0Y7rTaVVP1_iKVwwqXAcQZhr21JNBoQg-miF7EcrDc9Wa0KR8sGT4_sryiocSGIUuhN9jFbSgcHdOgXPLuwKkyNLvdEoMmkpm8qkmRW3xyo_6qeyDjnl7hoDctpakms3MlXrZ3-QefvOUN2et_Pn3kWNx0I6iqIofy0V9zxjGaGvcTWAVEGHdo0Ncc2PFGgDYpq1JWCn2aka1cKdwvuMZYtdTJKCT0w3L8FTUHW.eyJlbmRwb2ludF9zbHVnIjoib3BlbmFpL2dwdC01LW1pbmktMjAyNS0wOC0wN3xvcGVuYWkifQ"), + "openai_encrypted_content": String("gAAAAABqo9qWuWPlEk077GYV60QwAbJZz80at0wgJ06EL_r10a6s1cL2zr15893j6R_js_nmHN6gxIi3m9JHY0mB6CabO_MSNBH17ucryN8GnlwJSTumks5BsP1P6pirD2T5duzPD59HTlzZT1IZaX6qd1X4W7zeUy7CZoe48vtoBgdlaHgSuGtSFkT_HlmGqo9UciCvFT11HBx5-RMBR17SuUvn-3JqPyI8IolsQV7Di3B-QDFx5RIXFpXD8S8uUPD3Hnz1UKf6Tk4Cfs0OVffyS7Wb38aXKUmSqjKNbcFUlSX8kEpSuvPmgaWkUy4jZX9_oD_lkE3uHQwoTPmAJmpNne9n9pA9LRFGRuuBy0P6CTZjUKwWCOI6mME-Tfl41zaxEvJO2yL2SymSee7Yxyxftw9mPAfqz72JwcncRR1bRvkpcCTSXSJ-6UrT0IJXRYorAhWzcP-f71fiL8pjqIrT1uL7Ry01yHt2cFnQl5K926euu2HjCXjbznUvbEEIeAlc0YTdhQQvS1iHYjBVfX-NuFXjZVqN8oCFCytcJglllY5Qx0-8n9pAjlhw9o_pxzdD3zHU8rtA6adQp9_SR0Db1sk2e4r85dbT9AnnUb5zob9S1TQd2NZRdgZxqBF4idF6zwrlic86sqdLLcW1GH6EoY2jP4w3_1f6EDaGPFwpLvnQtGAWs0Efsl7tml6rzMsKBg5TnFNY8ADwlonk3P7LfsEebrx2gN0mut44h0wlifmzvxS3h4Rj_5NuF63vn5qrTJSFSEzPEFxjsRqaf_H6xq_rP2ttCWrsyXe-J5OXUtwusXATXRmKAm24Ksc-x9bR-C3fycXQAHuxEIc0M3KzgzveP-PcE5u0LSyPCQ3X1QtHkKpPk-qDK0YqHinRt-n6vMkAPiVQr7rElzeifCkib8qivpqBp_6uWoVS3-2h66T91T0hJGqybLoHEQbUoSP8WYX7kGNrE2y_maIgEbTUsC7f2KMmBIYNTO0mXvxFwCficXpa3KNS-_sSYKOGMs-eNi_048WvwQU3cXiqfRIG19AixBC4BzXEADa0VnizkIpBSRLDjoXqlr93-kB-x11nAeyMc2Hcx4vruS295q6mNOWBH5cicNloFcvkQDvYWNXl3g4v7u5y9xcOO9xb7_Q4HU2wjXX-lBP69_EcIjfn85ElHODHPyBnO_dK59KVkIobs0YmeADvpAFb9qAY7_uJh8u9QCgkAZb-LNK9lgcDKAA_dfaHuXhR2ygb6AZ_ogKRONVQWStWqkz2DqPYuXtq-UsDSNXD_IKa6Dixwf4Eh7zQdchmVYyFxPjzfDBz_VvZwEkgsI0T349wrXcLw4c4EYPxrG__5DidbJxV1dc26srw03WG0ytW-Yuo4EtP20mFiMXadrMpsOMyPPa8uKf1vytsjaq9TQ7uY8AMFbMSQz8spuy9VA==.eyJlbmRwb2ludF9zbHVnIjoib3BlbmFpL2dwdC01LW1pbmktMjAyNS0wOC0wN3xvcGVuYWkifQ"), "openrouter_metadata": Array [ Object { - "id": String("rs_052d8ffbb7051945016a886dba832487d1ab470a80f3e75c98"), + "id": String("rs_0c90c56a63d867fa016aa3da96bf2887d1b6861c01c7976c84"), "index": Number(0), "field": String("openai_encrypted_content"), }, @@ -70,7 +69,7 @@ expression: v timestamp: 2020-01-01 0:00:00.0 +00, kind: ChatResponse( Message { - message: "I ran the tool for you. Output returned: \"working!\"\n\nArguments used when calling the tool: {\"foo\": null, \"bar\": \"foo\"}\n\nDo you want me to run it again with different arguments or show more details?", + message: "Done — I ran the tool with the argument {\"bar\":\"foo\"} and it returned: \"working!\". Do you want me to run it again with different arguments or perform something else with the result?", }, ), metadata: {}, diff --git a/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_required_reasoning.yml b/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_required_reasoning.yml index c8ee00fc5..8ded2f92b 100644 --- a/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_required_reasoning.yml +++ b/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_required_reasoning.yml @@ -91,35 +91,17 @@ then: : OPENROUTER PROCESSING - : OPENROUTER PROCESSING - - data: {"id":"gen-1787325878-ik0WdMQeOFaS3u2d9DmF","object":"chat.completion.chunk","created":1787325878,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":"","role":"assistant","reasoning":null,"reasoning_details":[{"type":"reasoning.encrypted","data":"gAAAAABqiG25K01qfTbWlALE9KLuZO5uv_69IxBdl9djIR6du60aqGAOQnBooMRFBgKFWHUezx-zJWqPLMu6a6A5IHCesUr3nqSMfrODDbSEaUc4EPYwKkylaQomJiKW8fWXhcHpSNndayz1YabVw3foRQ3WkMCbDJDOqId14O7iNvxtdFi-q0zVWBDPJc3QnlyZkXSUIPvsGs0XN26rEuzrYYE8lCBSClZuk4bxapD5T0c3Ol1a46WMrjE5uqteJ0j4lm3s-eXgkER0TAodzKQrGlN0XEJv7wj-W10vMAdt_rjNgnX4DZNnBXZ3t7QsS2R8g7qHezWdkV2D9hIIaObfxyqbnjPiQ1F-1PThKhUhDkOG9h_cKJ-EBN-QGLk6e2Eg247icjSq1HpsrAU5mPZUPSSeVBKWD_T2y_iZalhgwJxHFNh4D7vaQnN6lfUUmDXOnDki49srtv_9bIj6uGLqZNIZZcxCZJ2gMXMmhrzmqr_ms8L3SuJvxGxUDd8toqDKAGsLhk_3KbDC0BWyr7lvFpn-H2RetMT67wKDmYM42HRxYuiA0h077kuvPFdT3ZECthu0Qap9SXUnbcAE3hXGIHf-239WiAS1J9BkxfaSqb0fToDpH5PHn4ZTLDncNQrG5U6RfMA6L1fkVcvbrmqWVLdIGA4sFEpLG580guBkBvuxj0pUbMhy1mSOIgWikH_FHlhbZCP4tbXnCbbCcSNghe-UlPP-rWoxqdL1I4OOe4zn99jg0cTZhhiRZ-ZfYG-MXywsFSpLt9_seN1RKE9nkm7gByoZ7YiXkqjplLMEhraa-KLNYoUK0-awMQaYctW_PKUm9dSn_TRHFxARdTmsS-vt28juOPoFxHKBL-MHG1PU8obM7E_YRGfJ2vBu44KTxOvciHp86jiRXWuIVJ3bV4mxmjjmHzOscsv-Zxj1QamfrFmVJA0lUCcZBY1AqYEQ0ugPAtlhkZmy3mrFtnjuNaYtL_mJyxt9YchPdifJKPsjZczrE5-nPCnWkcdtKhO72OkOgbva2X6nL-phGvmWursqZC9JG37jcmz1OLQklcLf0tw1acbWnN34nfIWtBmUlOwtLwpEA2TRdqJFG3fvcyxopoN-OF2CUETz2s4Lxqa3rQUrTwCu_KX6Ext38gmMTO5oP5XUBLL6jswj_4ZSwjrivIc41YSp9oahfEPivbGyfEWGySmrtJXgioqGwdLeSC57kz47ClXXEVDl5vtoUnrX5xVkZxdQn3MO2YTRQ30Fp7W7sP3XAxvfQr0nhLB0W2kcB0WUaOcsWyqHzfOd7TEB9_VKjPn_jfqakHFO8EvHxCGkVPNSPMXhMWhL0Z0vbOEgx9XGEHlgfdaUPSPNzoSdsgpRUCp2fQnyu9igUnOLJ76iHdnFJDr5WP6cK3Y0EGZRCrO7Mfhi-rb-M6HilU4rvyNleA-sl47N8Wy9_BRXOIY0b8KAgvP3Tu2Kbd1VLiUcgB4icEOZOOSS7VerFU5Hq5mbaLc5sTUnyAZG2uBISXe7xgk2350WP4JgWSE05GNbpRKFy969fCwY9VfNXT532fG-za76HRW21D8Q_XY-w0_IdpQdZiZDq0WeYQBkyagwZQ2SAl_BeXdvaHhb8aUHa-OY5bnEps5exIjChuiSG6LJQkAcUiYU292BNbJCY5L2IrC_zYgmZDV5bguoKEBTaiU02J5idzXqc3wkFhvrKMZqkRdTgFFhe4ArgiNwDfOAvgRVW4vUdL6cdTx4_6ezirZgAHqmVV9PqYwterkTd-HrioOdqURBMlirBjL2PqQdLl2QGRZM_kL57p0xL1oG4a_RfA==.eyJlbmRwb2ludF9zbHVnIjoib3BlbmFpL2dwdC01LW1pbmktMjAyNS0wOC0wN3xvcGVuYWkifQ","format":"openai-responses-v1","id":"rs_0848749866e247ea016a886db6fff087d1b5b6efd41ccac47f","index":0}]},"finish_reason":null,"native_finish_reason":null}]} - - data: {"id":"gen-1787325878-ik0WdMQeOFaS3u2d9DmF","object":"chat.completion.chunk","created":1787325878,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":null,"role":"assistant","tool_calls":[{"index":0,"id":"call_KnvO99RwD3rjBcOEPnBpNQ7O","type":"function","function":{"name":"run_me","arguments":""}}]},"finish_reason":null,"native_finish_reason":null}]} - - data: {"id":"gen-1787325878-ik0WdMQeOFaS3u2d9DmF","object":"chat.completion.chunk","created":1787325878,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":null,"role":"assistant","tool_calls":[{"index":0,"function":{"arguments":""}}]},"finish_reason":null,"native_finish_reason":null}]} - - data: {"id":"gen-1787325878-ik0WdMQeOFaS3u2d9DmF","object":"chat.completion.chunk","created":1787325878,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":null,"role":"assistant","tool_calls":[{"index":0,"function":{"arguments":"{\""}}]},"finish_reason":null,"native_finish_reason":null}]} - - data: {"id":"gen-1787325878-ik0WdMQeOFaS3u2d9DmF","object":"chat.completion.chunk","created":1787325878,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":null,"role":"assistant","tool_calls":[{"index":0,"function":{"arguments":"foo"}}]},"finish_reason":null,"native_finish_reason":null}]} - - data: {"id":"gen-1787325878-ik0WdMQeOFaS3u2d9DmF","object":"chat.completion.chunk","created":1787325878,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":null,"role":"assistant","tool_calls":[{"index":0,"function":{"arguments":"\":"}}]},"finish_reason":null,"native_finish_reason":null}]} - - data: {"id":"gen-1787325878-ik0WdMQeOFaS3u2d9DmF","object":"chat.completion.chunk","created":1787325878,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":null,"role":"assistant","tool_calls":[{"index":0,"function":{"arguments":"null"}}]},"finish_reason":null,"native_finish_reason":null}]} - - data: {"id":"gen-1787325878-ik0WdMQeOFaS3u2d9DmF","object":"chat.completion.chunk","created":1787325878,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":null,"role":"assistant","tool_calls":[{"index":0,"function":{"arguments":",\""}}]},"finish_reason":null,"native_finish_reason":null}]} - - data: {"id":"gen-1787325878-ik0WdMQeOFaS3u2d9DmF","object":"chat.completion.chunk","created":1787325878,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":null,"role":"assistant","tool_calls":[{"index":0,"function":{"arguments":"bar"}}]},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123218-lQJQblf9vt2mStfLMxVF","object":"chat.completion.chunk","created":1789123218,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":"","role":"assistant","reasoning":null,"reasoning_details":[{"type":"reasoning.encrypted","data":"gAAAAABqo9qVWVgVSs70JsmgeHy5uwfc1BUsd5iz5SS_x-dhR9X4-XKYOffk-ctbBFuNRVmQ_G5otogvIsf0A0MUxHKzLF0FDmVB_xgBUZjE8NhTD6dhjYv4S4WqiWAzBkLiCqeaXPx8Tftt5snFJmb7nPXFjaDc7F6G0PZB_3rzE28gJOe-GUBf66rwhuB-tFoDjIERRU7tWgvGRk02I-f5XEGbw8NJdLzwTAOPy3tjZ2bccfP_YD0n91XAcvMSdLLVWp0x8VmYWhV2-4lD_1sKOChkFyUIn_Njvt86WJqegNLA75PvLsy7rqq5Hp61noXD5QtYvczx2gyJ-noNwmQXaBFqqd7m0Ys-1fmp9JE7ky5etZN4J6LOlCkzEaVOECvZ_x6eBegQSr7FlIpVlae0uhQ5aYw73OUiLsoNb1vPuRakjQ4ReZJXNPTYjGDhOPZIIDt4IZaAX10WIJr-FuW8QKxK4wvX4-qojYr65fruC3qPbKdG8zj0CbDMokToDvgC7bUtiZiKIm3sh295WI0pvl9QEzEa3Bq3A4g_nzxU1qfBmBxV1qFDbW1lo27N4n3MQRl71a9nQb9FxJWxEnFEd78KS2gMCURPawIYC3TbgNmm7PR8hJaO6bxjfhyAktBcuRlFBo3mnffEsxuaF_yUNePeoCqBTWgC3SaA6KmDF_JUH961w_0_R-7uoVhaxaYTTwMvu9vJ-xsY-823_LR4GQUTswNLzxTnOptiCRx0VsLluu_1cqjzZzOMnXAWvHNWfQBn26VDDIdtyyjFKlKEfYH6n4_Z6MVGPomBXHD4o0Yz0vd3CQ3rNWAJhcP61sOrIcjLlg3h4vyBXVDveIzFHclyjbDnlPLFDqXuUuXbJ7dGux9a01pYvwMggDAUFhCdr1IsqQdXl70Yd0RRhThERjKSvZf5bvoWMn_xpjBWuZmolt1fiJY_giSvMEsA7KU9sc-i0mOm1sSht7Br5DIEswKOSYkb5POe8hIfgomabfDDdxFnKPbR9mcFSIVVRFc0mLgcyTlUFvaeJL_aauXBdmVrTepw-QIrHxgTg5pPeSSVWG1NhpZg2OnYJOJg7-93fUquRdzXilCKVLGdh-JfZ1-nDXHG9s3-HwLA6AHyLO4NCw8X87mcVS60DgZUC3aO-jMA1WPXRzoR0QCOYvqAD3a4eHNiErIcc29g7vwQL7h856YSFnBSeiPDcI_LY2BWmiDaq_rwC1_jm9vY5Nc6nQEXYTb0T3CSLW9pLrLjCir2pIgigW_zQt7w-K_4n_NNs1Ik4M1LeKyFhNe92y7e7wxxh3uDj9iDfsTqJooO0KSvQ7BnUta1LL8b6Gauxu5Lm7MVczOibnZYGNyV6cgC-3oIxdsoMMDvTobIVltkZNF9ynU1buWmTmiTysu140io8CI8VcLkC3PiwR2OwNaOi956UnROlcunuIkeIXqQmO9PH6jGQ1PbTO-_7vG8Eg2ZVGlDsDG3HYwQMPjINNuim3DA1F_HrZDKFXHRP7-U2Ful8ZTBV3ioUM7mFEi78hZVD_T3hngOpS6yjGFcM-A2MWLjKMlDsF9dCDGSGXYbn3UFxjQeQtAHTSMKQDlgr5KizSMEWWIMZS__lxuErK5Z3BKHo_NANpl0xYce2pfJnU7hiliNrfnQwSaDr7pXZZDcxWvVjKl8JozsXxvzSu-kSab67MajPbpxXzE9992oSXYOSrxR3iazQcoro9-8s2d74fzgpRkrIePZQyAYTPjd9GlR6c1M902pn4mCH6kP4fBwCux4lKm_iBwCgwWU-sqp2Kcu9JKUDMSKQhPSR-3QspuFYJJL_kBmL1Nr8rpL83B01sS9JsAnR4dXE7fe-aQK7a2rXyFG2_dIS3M4JHfXS1GUFlpLuZOveahn2_Ys_ZEOZEp9JFaa6FgG6fwnBX_hqQwVcy7Vpl8aGiDFMa2X6nHHC4XdAaVj2-QbND7Mm6pGHNAvYa9CjnpUrT0m-TwnAT6_8S4dpUoifILkiEiRRI-zSVvdSQ==.eyJlbmRwb2ludF9zbHVnIjoib3BlbmFpL2dwdC01LW1pbmktMjAyNS0wOC0wN3xvcGVuYWkifQ","format":"openai-responses-v1","id":"rs_0efd722f56d64447016aa3da9389c487d19b3ba847be53365c","index":0}]},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325878-ik0WdMQeOFaS3u2d9DmF","object":"chat.completion.chunk","created":1787325878,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":null,"role":"assistant","tool_calls":[{"index":0,"function":{"arguments":"\":\""}}]},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123218-lQJQblf9vt2mStfLMxVF","object":"chat.completion.chunk","created":1789123218,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":null,"role":"assistant","tool_calls":[{"index":0,"id":"call_NjNRzmeNIFfEhIlY1DJt8Elg","type":"function","function":{"name":"run_me","arguments":""}}]},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325878-ik0WdMQeOFaS3u2d9DmF","object":"chat.completion.chunk","created":1787325878,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":null,"role":"assistant","tool_calls":[{"index":0,"function":{"arguments":"foo"}}]},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123218-lQJQblf9vt2mStfLMxVF","object":"chat.completion.chunk","created":1789123218,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":null,"role":"assistant","tool_calls":[{"index":0,"function":{"arguments":""}}]},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325878-ik0WdMQeOFaS3u2d9DmF","object":"chat.completion.chunk","created":1787325878,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":null,"role":"assistant","tool_calls":[{"index":0,"function":{"arguments":"\"}"}}]},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123218-lQJQblf9vt2mStfLMxVF","object":"chat.completion.chunk","created":1789123218,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":null,"role":"assistant","tool_calls":[{"index":0,"function":{"arguments":"{\"foo\":null,\"bar\":\"foo\"}"}}]},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325878-ik0WdMQeOFaS3u2d9DmF","object":"chat.completion.chunk","created":1787325878,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":"","role":"assistant","reasoning":null},"finish_reason":"tool_calls","native_finish_reason":"completed"}]} + data: {"id":"gen-1789123218-lQJQblf9vt2mStfLMxVF","object":"chat.completion.chunk","created":1789123218,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":"","role":"assistant","reasoning":null},"finish_reason":"tool_calls","native_finish_reason":"completed"}]} - data: {"id":"gen-1787325878-ik0WdMQeOFaS3u2d9DmF","object":"chat.completion.chunk","created":1787325878,"model":"openai/gpt-5-mini","provider":"OpenAI","service_tier":"default","choices":[{"index":0,"delta":{"content":"","role":"assistant"},"finish_reason":"tool_calls","native_finish_reason":"completed"}],"usage":{"prompt_tokens":100,"completion_tokens":100,"total_tokens":200,"cost":0.000225,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"cache_write_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":0.000225,"upstream_inference_prompt_cost":0.000025,"upstream_inference_completions_cost":0.0002},"completion_tokens_details":{"reasoning_tokens":64,"image_tokens":0,"audio_tokens":0}}} + data: {"id":"gen-1789123218-lQJQblf9vt2mStfLMxVF","object":"chat.completion.chunk","created":1789123218,"model":"openai/gpt-5-mini","provider":"OpenAI","service_tier":"default","choices":[{"index":0,"delta":{"content":"","role":"assistant"},"finish_reason":"tool_calls","native_finish_reason":"completed"}],"usage":{"prompt_tokens":100,"completion_tokens":147,"total_tokens":247,"cost":0.000319,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"cache_write_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":0.000319,"upstream_inference_prompt_cost":0.000025,"upstream_inference_completions_cost":0.000294},"completion_tokens_details":{"reasoning_tokens":64,"image_tokens":0,"audio_tokens":0}}} data: [DONE] @@ -144,12 +126,12 @@ when: "role": "assistant", "tool_calls": [ { - "id": "call_KnvO99RwD3rjBcOEPnBpNQ7O", + "id": "call_NjNRzmeNIFfEhIlY1DJt8Elg", "index": 0, "type": "function", "function": { "name": "run_me", - "arguments": "{\"foo\":null,\"bar\":\"foo\"}" + "arguments": "{\"bar\":\"foo\"}" } } ] @@ -157,7 +139,7 @@ when: { "role": "tool", "content": "working!", - "tool_call_id": "call_KnvO99RwD3rjBcOEPnBpNQ7O" + "tool_call_id": "call_NjNRzmeNIFfEhIlY1DJt8Elg" } ], "reasoning": { @@ -174,107 +156,91 @@ then: body: |+ : OPENROUTER PROCESSING - : OPENROUTER PROCESSING - - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":"","role":"assistant","reasoning":null,"reasoning_details":[{"type":"reasoning.encrypted","data":"gAAAAABqiG26cwCaeVLhIDmyWh9QS5IOMJDoVAS5Rmk2C5l_uTWY1Bvl8Ezj3LOQuyNE429nXWiWolxw0qV2uWLiFUEUJGfSqPUsCGmD4p7XhcLVub26--oj7KcP9v1k0DbwAFZBpbrGYyGCAWMZCXv_QcG6pYO_SvRk4Q5qxOPs6rMYCfJi4Ts9NW1uRzjaxq3nM6VP8Bh5h1l35sgxzQ0_F9S_0ZsEcgaS8W8PI40RpqLCk92o1eO91H9K8rQitNnuyX6NQyI5g_S3p6TycqBipPygYqcgFfqah4F-p-mpDGR7Kz8XDW5rlu_HvUd_QiUxfI_GFmBj71uToKTVJMxOPZTP54GP8zDvnU9qfKJTZ1Ig_QFH54nYshOoyw4i1TpgwpQ4NY6FXkX2rPZoBuqm_gthOENYyyS6g4IW8b23UI98Uz0d92oeI7e090mg8Y3RNJAkJqnzr68sRVSBJtRABwqnhohskJPVDbMESHhKU-kA0pERO2ROHbgizAgbJ5QKCUBcX8cTPf4bcrIYTp453l5AYoImlr4695fSMiQynt6S-U8AiBKDdExEKmxWrxMewsVLvvZvngb_hje9eAht5jSqd9cHSb0MSLUil5egHwR4f19uvgB61pgJtuOaiU54biFYyxiVZV3FWP54PBOemegTCLVu9NzraIZlYacLPJuvFWFWvmHfYkAznogNGtgN6Pbsh3oclbdNc9dz55j40DWOHcLNn7zKf2rq0_UuOSDAjEL_BrFkHIIn-kgRHSpugXWWSu-lMVt1JjqR9ltkES_dmMmoZyJTMnpLNJRreyEqR-GxsA4irGD1Rt5LXKpbkBM7t6DGryAA5uNLDd2m47fjkvY0X9u-p1x4p11ZtOv9IkCJEu8Sgb06SbsH5Q1cN_hx4SXGnhM1EUoDGfeyyAmFxtxQczCeo1-P3hraGJM0TBbWJHIwNQi04OqSKJ7Qp_EUsRZTvi7Wxd4iExRUXADK0JsJw1HiK3LKa-YilPm5mdq6_U9TSRSsX7xwCsZTPCdFvGcpm9Jyf9xKELpHV8Gz5f6nZwHv3cuxrIMEmCU43OX3p-EoLRqjbk3DuSmUkAY07DnwJVdWmncTIaqV3koAbv1GEz0cLu6xnEy7iNiv3UZ6m0jpSi9xJpD2kDUodeGLZywcXxLhEwOqSwbECGr7yXahWJtQb0Y7rTaVVP1_iKVwwqXAcQZhr21JNBoQg-miF7EcrDc9Wa0KR8sGT4_sryiocSGIUuhN9jFbSgcHdOgXPLuwKkyNLvdEoMmkpm8qkmRW3xyo_6qeyDjnl7hoDctpakms3MlXrZ3-QefvOUN2et_Pn3kWNx0I6iqIofy0V9zxjGaGvcTWAVEGHdo0Ncc2PFGgDYpq1JWCn2aka1cKdwvuMZYtdTJKCT0w3L8FTUHW.eyJlbmRwb2ludF9zbHVnIjoib3BlbmFpL2dwdC01LW1pbmktMjAyNS0wOC0wN3xvcGVuYWkifQ","format":"openai-responses-v1","id":"rs_052d8ffbb7051945016a886dba832487d1ab470a80f3e75c98","index":0}]},"finish_reason":null,"native_finish_reason":null}]} - - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":"I","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" ran","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" the","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" tool","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" for","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" you","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":".","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":"","role":"assistant","reasoning":null,"reasoning_details":[{"type":"reasoning.encrypted","data":"gAAAAABqo9qWuWPlEk077GYV60QwAbJZz80at0wgJ06EL_r10a6s1cL2zr15893j6R_js_nmHN6gxIi3m9JHY0mB6CabO_MSNBH17ucryN8GnlwJSTumks5BsP1P6pirD2T5duzPD59HTlzZT1IZaX6qd1X4W7zeUy7CZoe48vtoBgdlaHgSuGtSFkT_HlmGqo9UciCvFT11HBx5-RMBR17SuUvn-3JqPyI8IolsQV7Di3B-QDFx5RIXFpXD8S8uUPD3Hnz1UKf6Tk4Cfs0OVffyS7Wb38aXKUmSqjKNbcFUlSX8kEpSuvPmgaWkUy4jZX9_oD_lkE3uHQwoTPmAJmpNne9n9pA9LRFGRuuBy0P6CTZjUKwWCOI6mME-Tfl41zaxEvJO2yL2SymSee7Yxyxftw9mPAfqz72JwcncRR1bRvkpcCTSXSJ-6UrT0IJXRYorAhWzcP-f71fiL8pjqIrT1uL7Ry01yHt2cFnQl5K926euu2HjCXjbznUvbEEIeAlc0YTdhQQvS1iHYjBVfX-NuFXjZVqN8oCFCytcJglllY5Qx0-8n9pAjlhw9o_pxzdD3zHU8rtA6adQp9_SR0Db1sk2e4r85dbT9AnnUb5zob9S1TQd2NZRdgZxqBF4idF6zwrlic86sqdLLcW1GH6EoY2jP4w3_1f6EDaGPFwpLvnQtGAWs0Efsl7tml6rzMsKBg5TnFNY8ADwlonk3P7LfsEebrx2gN0mut44h0wlifmzvxS3h4Rj_5NuF63vn5qrTJSFSEzPEFxjsRqaf_H6xq_rP2ttCWrsyXe-J5OXUtwusXATXRmKAm24Ksc-x9bR-C3fycXQAHuxEIc0M3KzgzveP-PcE5u0LSyPCQ3X1QtHkKpPk-qDK0YqHinRt-n6vMkAPiVQr7rElzeifCkib8qivpqBp_6uWoVS3-2h66T91T0hJGqybLoHEQbUoSP8WYX7kGNrE2y_maIgEbTUsC7f2KMmBIYNTO0mXvxFwCficXpa3KNS-_sSYKOGMs-eNi_048WvwQU3cXiqfRIG19AixBC4BzXEADa0VnizkIpBSRLDjoXqlr93-kB-x11nAeyMc2Hcx4vruS295q6mNOWBH5cicNloFcvkQDvYWNXl3g4v7u5y9xcOO9xb7_Q4HU2wjXX-lBP69_EcIjfn85ElHODHPyBnO_dK59KVkIobs0YmeADvpAFb9qAY7_uJh8u9QCgkAZb-LNK9lgcDKAA_dfaHuXhR2ygb6AZ_ogKRONVQWStWqkz2DqPYuXtq-UsDSNXD_IKa6Dixwf4Eh7zQdchmVYyFxPjzfDBz_VvZwEkgsI0T349wrXcLw4c4EYPxrG__5DidbJxV1dc26srw03WG0ytW-Yuo4EtP20mFiMXadrMpsOMyPPa8uKf1vytsjaq9TQ7uY8AMFbMSQz8spuy9VA==.eyJlbmRwb2ludF9zbHVnIjoib3BlbmFpL2dwdC01LW1pbmktMjAyNS0wOC0wN3xvcGVuYWkifQ","format":"openai-responses-v1","id":"rs_0c90c56a63d867fa016aa3da96bf2887d1b6861c01c7976c84","index":0}]},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" Output","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":"Done","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" returned","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" —","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":":","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" I","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" \"","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" ran","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":"working","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" the","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":"!\"\n\n","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" tool","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":"Arguments","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" with","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" used","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" the","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" when","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" argument","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" calling","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" {\"","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" the","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":"bar","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" tool","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":"\":\"","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":":","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":"foo","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" {\"","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":"\"}","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":"foo","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" and","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":"\":","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" it","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" null","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" returned","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":",","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":":","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" \"","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" \"","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":"bar","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":"working","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":"\":","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":"!\".","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" \"","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" Do","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":"foo","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" you","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":"\"}\n\n","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" want","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":"Do","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" me","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" you","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" to","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" want","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" run","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" me","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" it","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" to","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" again","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" run","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" with","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" it","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" different","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" again","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" arguments","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" with","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" or","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" different","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" perform","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" arguments","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" something","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" or","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" else","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" show","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" with","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" more","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" the","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" details","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":" result","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":"?","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":"?","role":"assistant"},"finish_reason":null,"native_finish_reason":null}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":"","role":"assistant","reasoning":null},"finish_reason":"stop","native_finish_reason":"completed"}]} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","choices":[{"index":0,"delta":{"content":"","role":"assistant","reasoning":null},"finish_reason":"stop","native_finish_reason":"completed"}]} - data: {"id":"gen-1787325881-C5KIRotkiPCY5ikQbku4","object":"chat.completion.chunk","created":1787325881,"model":"openai/gpt-5-mini","provider":"OpenAI","service_tier":"default","choices":[{"index":0,"delta":{"content":"","role":"assistant"},"finish_reason":"stop","native_finish_reason":"completed"}],"usage":{"prompt_tokens":49,"completion_tokens":65,"total_tokens":114,"cost":0.00014225,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"cache_write_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":0.00014225,"upstream_inference_prompt_cost":0.00001225,"upstream_inference_completions_cost":0.00013},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0,"audio_tokens":0}}} + data: {"id":"gen-1789123222-n9XMwDoAhEMbJuRO6ny9","object":"chat.completion.chunk","created":1789123222,"model":"openai/gpt-5-mini","provider":"OpenAI","service_tier":"default","choices":[{"index":0,"delta":{"content":"","role":"assistant"},"finish_reason":"stop","native_finish_reason":"completed"}],"usage":{"prompt_tokens":45,"completion_tokens":58,"total_tokens":103,"cost":0.00012725,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"cache_write_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":0.00012725,"upstream_inference_prompt_cost":0.00001125,"upstream_inference_completions_cost":0.000116},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0,"audio_tokens":0}}} data: [DONE] diff --git a/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_required_reasoning__conversation_stream.snap b/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_required_reasoning__conversation_stream.snap index e5926a447..7fc608c91 100644 --- a/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_required_reasoning__conversation_stream.snap +++ b/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_required_reasoning__conversation_stream.snap @@ -245,10 +245,10 @@ expression: v "type": "chat_response", "reasoning": "", "metadata": { - "openai_encrypted_content": "Z0FBQUFBQnFpRzI1SzAxcWZUYldsQUxFOUtMdVpPNXV2XzY5SXhCZGw5ZGpJUjZkdTYwYXFHQU9RbkJvb01SRkJnS0ZXSFVlengtekpXcVBMTXU2YTZBNUlIQ2VzVXIzbnFTTWZyT0REYlNFYVVjNEVQWXdLa3lsYVFvbUppS1c4ZldYaGNIcFNObmRheXoxWWFiVnczZm9SUTNXa01DYkRKRE9xSWQxNE83aU52eHRkRmktcTB6VldCRFBKYzNRbmx5WmtYU1VJUHZzR3MwWE4yNnJFdXpyWVlFOGxDQlNDbFp1azRieGFwRDVUMGMzT2wxYTQ2V01yakU1dXF0ZUowajRsbTNzLWVYZ2tFUjBUQW9kektRckdsTjBYRUp2N3dqLVcxMHZNQWR0X3JqTmduWDREWk5uQlhaM3Q3UXNTMlI4ZzdxSGV6V2RrVjJEOWhJSWFPYmZ4eXFibmpQaVExRi0xUFRoS2hVaERrT0c5aF9jS0otRUJOLVFHTGs2ZTJFZzI0N2ljalNxMUhwc3JBVTVtUFpVUFNTZVZCS1dEX1QyeV9pWmFsaGd3SnhIRk5oNEQ3dmFRbk42bGZVVW1EWE9uRGtpNDlzcnR2XzliSWo2dUdMcVpOSVpaY3hDWkoyZ01YTW1ocnptcXJfbXM4TDNTdUp2eEd4VURkOHRvcURLQUdzTGhrXzNLYkRDMEJXeXI3bHZGcG4tSDJSZXRNVDY3d0tEbVlNNDJIUnhZdWlBMGgwNzdrdXZQRmRUM1pFQ3RodTBRYXA5U1hVbmJjQUUzaFhHSUhmLTIzOVdpQVMxSjlCa3hmYVNxYjBmVG9EcEg1UEhuNFpUTERuY05Rckc1VTZSZk1BNkwxZmtWY3Zicm1xV1ZMZElHQTRzRkVwTEc1ODBndUJrQnZ1eGowcFViTWh5MW1TT0lnV2lrSF9GSGxoYlpDUDR0YlhuQ2JiQ2NTTmdoZS1VbFBQLXJXb3hxZEwxSTRPT2U0em45OWpnMGNUWmhoaVJaLVpmWUctTVh5d3NGU3BMdDlfc2VOMVJLRTlua203Z0J5b1o3WWlYa3FqcGxMTUVocmFhLUtMTllvVUswLWF3TVFhWWN0V19QS1VtOWRTbl9UUkhGeEFSZFRtc1MtdnQyOGp1T1BvRnhIS0JMLU1IRzFQVThvYk03RV9ZUkdmSjJ2QnU0NEtUeE92Y2lIcDg2amlSWFd1SVZKM2JWNG14bWpqbUh6T3Njc3YtWnhqMVFhbWZyRm1WSkEwbFVDY1pCWTFBcVlFUTB1Z1BBdGxoa1pteTNtckZ0bmp1TmFZdExfbUp5eHQ5WWNoUGRpZkpLUHNqWmN6ckU1LW5QQ25Xa2NkdEtoTzcyT2tPZ2J2YTJYNm5MLXBoR3ZtV3Vyc3FaQzlKRzM3amNtejFPTFFrbGNMZjB0dzFhY2JXbk4zNG5mSVd0Qm1VbE93dEx3cEVBMlRSZHFKRkczZnZjeXhvcG9OLU9GMkNVRVR6MnM0THhxYTNyUVVyVHdDdV9LWDZFeHQzOGdtTVRPNW9QNVhVQkxMNmpzd2pfNFpTd2pyaXZJYzQxWVNwOW9haGZFUGl2Ykd5ZkVXR3lTbXJ0SlhnaW9xR3dkTGVTQzU3a3o0N0NsWFhFVkRsNXZ0b1Vuclg1eFZrWnhkUW4zTU8yWVRSUTMwRnA3VzdzUDNYQXh2ZlFyMG5oTEIwVzJrY0IwV1VhT2NzV3lxSHpmT2Q3VEVCOV9WS2pQbl9qZnFha0hGTzhFdkh4Q0drVlBOU1BNWGhNV2hMMFowdmJPRWd4OVhHRUhsZ2ZkYVVQU1BOem9TZHNncFJVQ3AyZlFueXU5aWdVbk9MSjc2aUhkbkZKRHI1V1A2Y0szWTBFR1pSQ3JPN01maGktcmItTTZIaWxVNHJ2eU5sZUEtc2w0N044V3k5X0JSWE9JWTBiOEtBZ3ZQM1R1MktiZDFWTGlVY2dCNGljRU9aT09TUzdWZXJGVTVIcTVtYmFMYzVzVFVueUFaRzJ1QklTWGU3eGdrMjM1MFdQNEpnV1NFMDVHTmJwUktGeTk2OWZDd1k5VmZOWFQ1MzJmRy16YTc2SFJXMjFEOFFfWFktdzBfSWRwUWRaaVpEcTBXZVlRQmt5YWd3WlEyU0FsX0JlWGR2YUhoYjhhVUhhLU9ZNWJuRXBzNWV4SWpDaHVpU0c2TEpRa0FjVWlZVTI5MkJOYkpDWTVMMklyQ196WWdtWkRWNWJndW9LRUJUYWlVMDJKNWlkelhxYzN3a0ZodnJLTVpxa1JkVGdGRmhlNEFyZ2lOd0RmT0F2Z1JWVzR2VWRMNmNkVHg0XzZlemlyWmdBSHFtVlY5UHFZd3RlcmtUZC1IcmlvT2RxVVJCTWxpckJqTDJQcVFkTGwyUUdSWk1fa0w1N3AweEwxb0c0YV9SZkE9PS5leUpsYm1Sd2IybHVkRjl6YkhWbklqb2liM0JsYm1GcEwyZHdkQzAxTFcxcGJta3RNakF5TlMwd09DMHdOM3h2Y0dWdVlXa2lmUQ==", + "openai_encrypted_content": "Z0FBQUFBQnFvOXFWV1ZnVlNzNzBKc21nZUh5NXV3ZmMxQlVzZDVpejVTU194LWRoUjlYNC1YS1lPZmZrLWN0YkJGdU5SVm1RX0c1b3RvZ3ZJc2YwQTBNVXhIS3pMRjBGRG1WQl94Z0JVWmpFOE5oVEQ2ZGhqWXY0UzRXcWlXQXpCa0xpQ3FlYVhQeDhUZnR0NXNuRkptYjduUFhGamFEYzdGNkcwUFpCXzNyekUyOGdKT2UtR1VCZjY2cndodUItdEZvRGpJRVJSVTd0V2d2R1JrMDJJLWY1WEVHYnc4TkpkTHp3VEFPUHkzdGpaMmJjY2ZQX1lEMG45MVhBY3ZNU2RMTFZXcDB4OFZtWVdoVjItNGxEXzFzS09DaGtGeVVJbl9OanZ0ODZXSnFlZ05MQTc1UHZMc3k3cnFxNUhwNjFub1hENVF0WXZjengyZ3lKLW5vTndtUVhhQkZxcWQ3bTBZcy0xZm1wOUpFN2t5NWV0Wk40SjZMT2xDa3pFYVZPRUN2Wl94NmVCZWdRU3I3RmxJcFZsYWUwdWhRNWFZdzczT1VpTHNvTmIxdlB1UmFralE0UmVaSlhOUFRZakdEaE9QWklJRHQ0SVphQVgxMFdJSnItRnVXOFFLeEs0d3ZYNC1xb2pZcjY1ZnJ1QzNxUGJLZEc4emowQ2JETW9rVG9EdmdDN2JVdGlaaUtJbTNzaDI5NVdJMHB2bDlRRXpFYTNCcTNBNGdfbnp4VTFxZkJtQnhWMXFGRGJXMWxvMjdONG4zTVFSbDcxYTluUWI5RnhKV3hFbkZFZDc4S1MyZ01DVVJQYXdJWUMzVGJnTm1tN1BSOGhKYU82YnhqZmh5QWt0QmN1UmxGQm8zbW5mZkVzeHVhRl95VU5lUGVvQ3FCVFdnQzNTYUE2S21ERl9KVUg5NjF3XzBfUi03dW9WaGF4YVlUVHdNdnU5dkoteHNZLTgyM19MUjRHUVVUc3dOTHp4VG5PcHRpQ1J4MFZzTGx1dV8xY3Fqelp6T01uWEFXdkhOV2ZRQm4yNlZERElkdHl5akZLbEtFZllINm40X1o2TVZHUG9tQlhIRDRvMFl6MHZkM0NRM3JOV0FKaGNQNjFzT3JJY2pMbGczaDR2eUJYVkR2ZUl6RkhjbHlqYkRubFBMRkRxWHVVdVhiSjdkR3V4OWEwMXBZdndNZ2dEQVVGaENkcjFJc3FRZFhsNzBZZDBSUmhUaEVSaktTdlpmNWJ2b1dNbl94cGpCV3VabW9sdDFmaUpZX2dpU3ZNRXNBN0tVOXNjLWkwbU9tMXNTaHQ3QnI1RElFc3dLT1NZa2I1UE9lOGhJZmdvbWFiZkREZHhGbktQYlI5bWNGU0lWVlJGYzBtTGdjeVRsVUZ2YWVKTF9hYXVYQmRtVnJUZXB3LVFJckh4Z1RnNXBQZVNTVldHMU5ocFpnMk9uWUpPSmc3LTkzZlVxdVJkelhpbENLVkxHZGgtSmZaMS1uRFhIRzlzMy1Id0xBNkFIeUxPNE5DdzhYODdtY1ZTNjBEZ1pVQzNhTy1qTUExV1BYUnpvUjBRQ09ZdnFBRDNhNGVITmlFckljYzI5Zzd2d1FMN2g4NTZZU0ZuQlNlaVBEY0lfTFkyQldtaURhcV9yd0MxX2ptOXZZNU5jNm5RRVhZVGIwVDNDU0xXOXBMckxqQ2lyMnBJZ2lnV196UXQ3dy1LXzRuX05OczFJazRNMUxlS3lGaE5lOTJ5N2U3d3h4aDN1RGo5aURmc1RxSm9vTzBLU3ZRN0JuVXRhMUxMOGI2R2F1eHU1TG03TVZjek9pYm5aWUdOeVY2Y2dDLTNvSXhkc29NTUR2VG9iSVZsdGtaTkY5eW5VMWJ1V21UbWlUeXN1MTQwaW84Q0k4VmNMa0MzUGl3UjJPd05hT2k5NTZVblJPbGN1bnVJa2VJWHFRbU85UEg2akdRMVBiVE8tXzd2RzhFZzJaVkdsRHNERzNIWXdRTVBqSU5OdWltM0RBMUZfSHJaREtGWEhSUDctVTJGdWw4WlRCVjNpb1VNN21GRWk3OGhaVkRfVDNobmdPcFM2eWpHRmNNLUEyTVdMaktNbERzRjlkQ0RHU0dYWWJuM1VGeGpRZVF0QUhUU01LUURsZ3I1S2l6U01FV1dJTVpTX19seHVFcks1WjNCS0hvX05BTnBsMHhZY2UycGZKblU3aGlsaU5yZm5Rd1NhRHI3cFhaWkRjeFd2VmpLbDhKb3pzWHh2elN1LWtTYWI2N01halBicHhYekU5OTkyb1NYWU9TcnhSM2lhelFjb3JvOS04czJkNzRmemdwUmtySWVQWlF5QVlUUGpkOUdsUjZjMU05MDJwbjRtQ0g2a1A0ZkJ3Q3V4NGxLbV9pQndDZ3dXVS1zcXAyS2N1OUpLVURNU0tRaFBTUi0zUXNwdUZZSkpMX2tCbUwxTnI4cnBMODNCMDFzUzlKc0FuUjRkWEU3ZmUtYVFLN2Eyclh5RkcyX2RJUzNNNEpIZlhTMUdVRmxwTHVaT3ZlYWhuMl9Zc19aRU9aRXA5SkZhYTZGZ0c2ZnduQlhfaHFRd1ZjeTdWcGw4YUdpREZNYTJYNm5ISEM0WGRBYVZqMi1RYk5EN01tNnBHSE5BdllhOUNqbnBVclQwbS1Ud25BVDZfOFM0ZHBVb2lmSUxraUVpUlJJLXpTVnZkU1E9PS5leUpsYm1Sd2IybHVkRjl6YkhWbklqb2liM0JsYm1GcEwyZHdkQzAxTFcxcGJta3RNakF5TlMwd09DMHdOM3h2Y0dWdVlXa2lmUQ==", "openrouter_metadata": [ { - "id": "cnNfMDg0ODc0OTg2NmUyNDdlYTAxNmE4ODZkYjZmZmYwODdkMWI1YjZlZmQ0MWNjYWM0N2Y=", + "id": "cnNfMGVmZDcyMmY1NmQ2NDQ0NzAxNmFhM2RhOTM4OWM0ODdkMTliM2JhODQ3YmU1MzM2NWM=", "index": 0, "field": "b3BlbmFpX2VuY3J5cHRlZF9jb250ZW50" } @@ -258,10 +258,9 @@ expression: v { "timestamp": "2020-01-01 00:00:00.0", "type": "tool_call_request", - "id": "call_KnvO99RwD3rjBcOEPnBpNQ7O", + "id": "call_NjNRzmeNIFfEhIlY1DJt8Elg", "name": "run_me", "arguments": { - "foo": null, "bar": "Zm9v" } }, @@ -281,7 +280,7 @@ expression: v { "timestamp": "2020-01-01 00:00:00.0", "type": "tool_call_response", - "id": "call_KnvO99RwD3rjBcOEPnBpNQ7O", + "id": "call_NjNRzmeNIFfEhIlY1DJt8Elg", "content": "d29ya2luZyE=", "is_error": false }, @@ -290,10 +289,10 @@ expression: v "type": "chat_response", "reasoning": "", "metadata": { - "openai_encrypted_content": "Z0FBQUFBQnFpRzI2Y3dDYWVWTGhJRG15V2g5UVM1SU9NSkRvVkFTNVJtazJDNWxfdVRXWTFCdmw4RXpqM0xPUXV5TkU0MjluWFdpV29seHcwcVYydVdMaUZVRVVKR2ZTcVBVc0NHbUQ0cDdYaGNMVnViMjYtLW9qN0tjUDl2MWswRGJ3QUZaQnBickdZeUdDQVdNWkNYdl9RY0c2cFlPX1N2Ums0UTVxeE9QczZyTVlDZkppNFRzOU5XMXVSempheHEzbk02VlA4Qmg1aDFsMzVzZ3h6UTBfRjlTXzBac0VjZ2FTOFc4UEk0MFJwcUxDazkybzFlTzkxSDlLOHJRaXRObnV5WDZOUXlJNWdfUzNwNlR5Y3FCaXBQeWdZcWNnRmZxYWg0Ri1wLW1wREdSN0t6OFhEVzVybHVfSHZVZF9RaVV4ZklfR0ZtQmo3MXVUb0tUVkpNeE9QWlRQNTRHUDh6RHZuVTlxZktKVFoxSWdfUUZINTRuWXNoT295dzRpMVRwZ3dwUTROWTZGWGtYMnJQWm9CdXFtX2d0aE9FTll5eVM2ZzRJVzhiMjNVSTk4VXowZDkyb2VJN2UwOTBtZzhZM1JOSkFrSnFuenI2OHNSVlNCSnRSQUJ3cW5ob2hza0pQVkRiTUVTSGhLVS1rQTBwRVJPMlJPSGJnaXpBZ2JKNVFLQ1VCY1g4Y1RQZjRiY3JJWVRwNDUzbDVBWW9JbWxyNDY5NWZTTWlReW50NlMtVThBaUJLRGRFeEVLbXhXcnhNZXdzVkx2dlp2bmdiX2hqZTllQWh0NWpTcWQ5Y0hTYjBNU0xVaWw1ZWdId1I0ZjE5dXZnQjYxcGdKdHVPYWlVNTRiaUZZeXhpVlpWM0ZXUDU0UEJPZW1lZ1RDTFZ1OU56cmFJWmxZYWNMUEp1dkZXRld2bUhmWWtBem5vZ05HdGdONlBic2gzb2NsYmROYzlkejU1ajQwRFdPSGNMTm43ektmMnJxMF9VdU9TREFqRUxfQnJGa0hJSW4ta2dSSFNwdWdYV1dTdS1sTVZ0MUpqcVI5bHRrRVNfZG1NbW9aeUpUTW5wTE5KUnJleUVxUi1HeHNBNGlyR0QxUnQ1TFhLcGJrQk03dDZER3J5QUE1dU5MRGQybTQ3ZmprdlkwWDl1LXAxeDRwMTFadE92OUlrQ0pFdThTZ2IwNlNic0g1UTFjTl9oeDRTWEduaE0xRVVvREdmZXl5QW1GeHR4UWN6Q2VvMS1QM2hyYUdKTTBUQmJXSkhJd05RaTA0T3FTS0o3UXBfRVVzUlpUdmk3V3hkNGlFeFJVWEFESzBKc0p3MUhpSzNMS2EtWWlsUG01bWRxNl9VOVRTUlNzWDd4d0NzWlRQQ2RGdkdjcG05SnlmOXhLRUxwSFY4R3o1ZjZuWndIdjNjdXhySU1FbUNVNDNPWDNwLUVvTFJxamJrM0R1U21Va0FZMDdEbndKVmRXbW5jVElhcVYza29BYnYxR0V6MGNMdTZ4bkV5N2lOaXYzVVo2bTBqcFNpOXhKcEQya0RVb2RlR0xaeXdjWHhMaEV3T3FTd2JFQ0dyN3lYYWhXSnRRYjBZN3JUYVZWUDFfaUtWd3dxWEFjUVpocjIxSk5Cb1FnLW1pRjdFY3JEYzlXYTBLUjhzR1Q0X3NyeWlvY1NHSVV1aE45akZiU2djSGRPZ1hQTHV3S2t5Tkx2ZEVvTW1rcG04cWttUlczeHlvXzZxZXlEam5sN2hvRGN0cGFrbXMzTWxYclozLVFlZnZPVU4yZXRfUG4za1dOeDBJNmlxSW9meTBWOXp4akdhR3ZjVFdBVkVHSGRvME5jYzJQRkdnRFlwcTFKV0NuMmFrYTFjS2R3dnVNWll0ZFRKS0NUMHczTDhGVFVIVy5leUpsYm1Sd2IybHVkRjl6YkhWbklqb2liM0JsYm1GcEwyZHdkQzAxTFcxcGJta3RNakF5TlMwd09DMHdOM3h2Y0dWdVlXa2lmUQ==", + "openai_encrypted_content": "Z0FBQUFBQnFvOXFXdVdQbEVrMDc3R1lWNjBRd0FiSlp6ODBhdDB3Z0owNkVMX3IxMGE2czFjTDJ6cjE1ODkzajZSX2pzX25tSE42Z3hJaTNtOUpIWTBtQjZDYWJPX01TTkJIMTd1Y3J5TjhHbmx3SlNUdW1rczVCc1AxUDZwaXJEMlQ1ZHV6UEQ1OUhUbHpaVDFJWmFYNnFkMVg0Vzd6ZVV5N0Nab2U0OHZ0b0JnZGxhSGdTdUd0U0ZrVF9IbG1HcW85VWNpQ3ZGVDExSEJ4NS1STUJSMTdTdVV2bi0zSnFQeUk4SW9sc1FWN0RpM0ItUURGeDVSSVhGcFhEOFM4dVVQRDNIbnoxVUtmNlRrNENmczBPVmZmeVM3V2IzOGFYS1VtU3FqS05iY0ZVbFNYOGtFcFN1dlBtZ2FXa1V5NGpaWDlfb0RfbGtFM3VIUXdvVFBtQUptcE5uZTluOXBBOUxSRkdSdXVCeTBQNkNUWmpVS3dXQ09JNm1NRS1UZmw0MXpheEV2Sk8yeUwyU3ltU2VlN1l4eXhmdHc5bVBBZnF6NzJKd2NuY1JSMWJSdmtwY0NUU1hTSi02VXJUMElKWFJZb3JBaFd6Y1AtZjcxZmlMOHBqcUlyVDF1TDdSeTAxeUh0MmNGblFsNUs5MjZldXUySGpDWGpiem5VdmJFRUllQWxjMFlUZGhRUXZTMWlIWWpCVmZYLU51RlhqWlZxTjhvQ0ZDeXRjSmdsbGxZNVF4MC04bjlwQWpsaHc5b19weHpkRDN6SFU4cnRBNmFkUXA5X1NSMERiMXNrMmU0cjg1ZGJUOUFublViNXpvYjlTMVRRZDJOWlJkZ1p4cUJGNGlkRjZ6d3JsaWM4NnNxZExMY1cxR0g2RW9ZMmpQNHczXzFmNkVEYUdQRndwTHZuUXRHQVdzMEVmc2w3dG1sNnJ6TXNLQmc1VG5GTlk4QUR3bG9uazNQN0xmc0VlYnJ4MmdOMG11dDQ0aDB3bGlmbXp2eFMzaDRSal81TnVGNjN2bjVxclRKU0ZTRXpQRUZ4anNScWFmX0g2eHFfclAydHRDV3JzeVhlLUo1T1hVdHd1c1hBVFhSbUtBbTI0S3NjLXg5YlItQzNmeWNYUUFIdXhFSWMwTTNLemd6dmVQLVBjRTV1MExTeVBDUTNYMVF0SGtLcFBrLXFESzBZcUhpblJ0LW42dk1rQVBpVlFyN3JFbHplaWZDa2liOHFpdnBxQnBfNnVXb1ZTMy0yaDY2VDkxVDBoSkdxeWJMb0hFUWJVb1NQOFdZWDdrR05yRTJ5X21hSWdFYlRVc0M3ZjJLTW1CSVlOVE8wbVh2eEZ3Q2ZpY1hwYTNLTlMtX3NTWUtPR01zLWVOaV8wNDhXdndRVTNjWGlxZlJJRzE5QWl4QkM0QnpYRUFEYTBWbml6a0lwQlNSTERqb1hxbHI5My1rQi14MTFuQWV5TWMySGN4NHZydVMyOTVxNm1OT1dCSDVjaWNObG9GY3ZrUUR2WVdOWGwzZzR2N3U1eTl4Y09POXhiN19RNEhVMndqWFgtbEJQNjlfRWNJamZuODVFbEhPREhQeUJuT19kSzU5S1ZrSW9iczBZbWVBRHZwQUZiOXFBWTdfdUpoOHU5UUNna0FaYi1MTks5bGdjREtBQV9kZmFIdVhoUjJ5Z2I2QVpfb2dLUk9OVlFXU3RXcWt6MkRxUFl1WHRxLVVzRFNOWERfSUthNkRpeHdmNEVoN3pRZGNobVZZeUZ4UGp6ZkRCel9Wdlp3RWtnc0kwVDM0OXdyWGNMdzRjNEVZUHhyR19fNURpZGJKeFYxZGMyNnNydzAzV0cweXRXLVl1bzRFdFAyMG1GaU1YYWRyTXBzT015UFBhOHVLZjF2eXRzamFxOVRRN3VZOEFNRmJNU1F6OHNwdXk5VkE9PS5leUpsYm1Sd2IybHVkRjl6YkhWbklqb2liM0JsYm1GcEwyZHdkQzAxTFcxcGJta3RNakF5TlMwd09DMHdOM3h2Y0dWdVlXa2lmUQ==", "openrouter_metadata": [ { - "id": "cnNfMDUyZDhmZmJiNzA1MTk0NTAxNmE4ODZkYmE4MzI0ODdkMWFiNDcwYTgwZjNlNzVjOTg=", + "id": "cnNfMGM5MGM1NmE2M2Q4NjdmYTAxNmFhM2RhOTZiZjI4ODdkMWI2ODYxYzAxYzc5NzZjODQ=", "index": 0, "field": "b3BlbmFpX2VuY3J5cHRlZF9jb250ZW50" } @@ -303,7 +302,7 @@ expression: v { "timestamp": "2020-01-01 00:00:00.0", "type": "chat_response", - "message": "I ran the tool for you. Output returned: \"working!\"\n\nArguments used when calling the tool: {\"foo\": null, \"bar\": \"foo\"}\n\nDo you want me to run it again with different arguments or show more details?" + "message": "Done — I ran the tool with the argument {\"bar\":\"foo\"} and it returned: \"working!\". Do you want me to run it again with different arguments or perform something else with the result?" } ] } diff --git a/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_required_reasoning__raw_events.snap b/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_required_reasoning__raw_events.snap index c2cac18d0..83bf6f798 100644 --- a/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_required_reasoning__raw_events.snap +++ b/crates/jp_llm/tests/fixtures/openrouter/test_tool_call_required_reasoning__raw_events.snap @@ -10,10 +10,10 @@ expression: v "", ), metadata: { - "openai_encrypted_content": String("gAAAAABqiG25K01qfTbWlALE9KLuZO5uv_69IxBdl9djIR6du60aqGAOQnBooMRFBgKFWHUezx-zJWqPLMu6a6A5IHCesUr3nqSMfrODDbSEaUc4EPYwKkylaQomJiKW8fWXhcHpSNndayz1YabVw3foRQ3WkMCbDJDOqId14O7iNvxtdFi-q0zVWBDPJc3QnlyZkXSUIPvsGs0XN26rEuzrYYE8lCBSClZuk4bxapD5T0c3Ol1a46WMrjE5uqteJ0j4lm3s-eXgkER0TAodzKQrGlN0XEJv7wj-W10vMAdt_rjNgnX4DZNnBXZ3t7QsS2R8g7qHezWdkV2D9hIIaObfxyqbnjPiQ1F-1PThKhUhDkOG9h_cKJ-EBN-QGLk6e2Eg247icjSq1HpsrAU5mPZUPSSeVBKWD_T2y_iZalhgwJxHFNh4D7vaQnN6lfUUmDXOnDki49srtv_9bIj6uGLqZNIZZcxCZJ2gMXMmhrzmqr_ms8L3SuJvxGxUDd8toqDKAGsLhk_3KbDC0BWyr7lvFpn-H2RetMT67wKDmYM42HRxYuiA0h077kuvPFdT3ZECthu0Qap9SXUnbcAE3hXGIHf-239WiAS1J9BkxfaSqb0fToDpH5PHn4ZTLDncNQrG5U6RfMA6L1fkVcvbrmqWVLdIGA4sFEpLG580guBkBvuxj0pUbMhy1mSOIgWikH_FHlhbZCP4tbXnCbbCcSNghe-UlPP-rWoxqdL1I4OOe4zn99jg0cTZhhiRZ-ZfYG-MXywsFSpLt9_seN1RKE9nkm7gByoZ7YiXkqjplLMEhraa-KLNYoUK0-awMQaYctW_PKUm9dSn_TRHFxARdTmsS-vt28juOPoFxHKBL-MHG1PU8obM7E_YRGfJ2vBu44KTxOvciHp86jiRXWuIVJ3bV4mxmjjmHzOscsv-Zxj1QamfrFmVJA0lUCcZBY1AqYEQ0ugPAtlhkZmy3mrFtnjuNaYtL_mJyxt9YchPdifJKPsjZczrE5-nPCnWkcdtKhO72OkOgbva2X6nL-phGvmWursqZC9JG37jcmz1OLQklcLf0tw1acbWnN34nfIWtBmUlOwtLwpEA2TRdqJFG3fvcyxopoN-OF2CUETz2s4Lxqa3rQUrTwCu_KX6Ext38gmMTO5oP5XUBLL6jswj_4ZSwjrivIc41YSp9oahfEPivbGyfEWGySmrtJXgioqGwdLeSC57kz47ClXXEVDl5vtoUnrX5xVkZxdQn3MO2YTRQ30Fp7W7sP3XAxvfQr0nhLB0W2kcB0WUaOcsWyqHzfOd7TEB9_VKjPn_jfqakHFO8EvHxCGkVPNSPMXhMWhL0Z0vbOEgx9XGEHlgfdaUPSPNzoSdsgpRUCp2fQnyu9igUnOLJ76iHdnFJDr5WP6cK3Y0EGZRCrO7Mfhi-rb-M6HilU4rvyNleA-sl47N8Wy9_BRXOIY0b8KAgvP3Tu2Kbd1VLiUcgB4icEOZOOSS7VerFU5Hq5mbaLc5sTUnyAZG2uBISXe7xgk2350WP4JgWSE05GNbpRKFy969fCwY9VfNXT532fG-za76HRW21D8Q_XY-w0_IdpQdZiZDq0WeYQBkyagwZQ2SAl_BeXdvaHhb8aUHa-OY5bnEps5exIjChuiSG6LJQkAcUiYU292BNbJCY5L2IrC_zYgmZDV5bguoKEBTaiU02J5idzXqc3wkFhvrKMZqkRdTgFFhe4ArgiNwDfOAvgRVW4vUdL6cdTx4_6ezirZgAHqmVV9PqYwterkTd-HrioOdqURBMlirBjL2PqQdLl2QGRZM_kL57p0xL1oG4a_RfA==.eyJlbmRwb2ludF9zbHVnIjoib3BlbmFpL2dwdC01LW1pbmktMjAyNS0wOC0wN3xvcGVuYWkifQ"), + "openai_encrypted_content": String("gAAAAABqo9qVWVgVSs70JsmgeHy5uwfc1BUsd5iz5SS_x-dhR9X4-XKYOffk-ctbBFuNRVmQ_G5otogvIsf0A0MUxHKzLF0FDmVB_xgBUZjE8NhTD6dhjYv4S4WqiWAzBkLiCqeaXPx8Tftt5snFJmb7nPXFjaDc7F6G0PZB_3rzE28gJOe-GUBf66rwhuB-tFoDjIERRU7tWgvGRk02I-f5XEGbw8NJdLzwTAOPy3tjZ2bccfP_YD0n91XAcvMSdLLVWp0x8VmYWhV2-4lD_1sKOChkFyUIn_Njvt86WJqegNLA75PvLsy7rqq5Hp61noXD5QtYvczx2gyJ-noNwmQXaBFqqd7m0Ys-1fmp9JE7ky5etZN4J6LOlCkzEaVOECvZ_x6eBegQSr7FlIpVlae0uhQ5aYw73OUiLsoNb1vPuRakjQ4ReZJXNPTYjGDhOPZIIDt4IZaAX10WIJr-FuW8QKxK4wvX4-qojYr65fruC3qPbKdG8zj0CbDMokToDvgC7bUtiZiKIm3sh295WI0pvl9QEzEa3Bq3A4g_nzxU1qfBmBxV1qFDbW1lo27N4n3MQRl71a9nQb9FxJWxEnFEd78KS2gMCURPawIYC3TbgNmm7PR8hJaO6bxjfhyAktBcuRlFBo3mnffEsxuaF_yUNePeoCqBTWgC3SaA6KmDF_JUH961w_0_R-7uoVhaxaYTTwMvu9vJ-xsY-823_LR4GQUTswNLzxTnOptiCRx0VsLluu_1cqjzZzOMnXAWvHNWfQBn26VDDIdtyyjFKlKEfYH6n4_Z6MVGPomBXHD4o0Yz0vd3CQ3rNWAJhcP61sOrIcjLlg3h4vyBXVDveIzFHclyjbDnlPLFDqXuUuXbJ7dGux9a01pYvwMggDAUFhCdr1IsqQdXl70Yd0RRhThERjKSvZf5bvoWMn_xpjBWuZmolt1fiJY_giSvMEsA7KU9sc-i0mOm1sSht7Br5DIEswKOSYkb5POe8hIfgomabfDDdxFnKPbR9mcFSIVVRFc0mLgcyTlUFvaeJL_aauXBdmVrTepw-QIrHxgTg5pPeSSVWG1NhpZg2OnYJOJg7-93fUquRdzXilCKVLGdh-JfZ1-nDXHG9s3-HwLA6AHyLO4NCw8X87mcVS60DgZUC3aO-jMA1WPXRzoR0QCOYvqAD3a4eHNiErIcc29g7vwQL7h856YSFnBSeiPDcI_LY2BWmiDaq_rwC1_jm9vY5Nc6nQEXYTb0T3CSLW9pLrLjCir2pIgigW_zQt7w-K_4n_NNs1Ik4M1LeKyFhNe92y7e7wxxh3uDj9iDfsTqJooO0KSvQ7BnUta1LL8b6Gauxu5Lm7MVczOibnZYGNyV6cgC-3oIxdsoMMDvTobIVltkZNF9ynU1buWmTmiTysu140io8CI8VcLkC3PiwR2OwNaOi956UnROlcunuIkeIXqQmO9PH6jGQ1PbTO-_7vG8Eg2ZVGlDsDG3HYwQMPjINNuim3DA1F_HrZDKFXHRP7-U2Ful8ZTBV3ioUM7mFEi78hZVD_T3hngOpS6yjGFcM-A2MWLjKMlDsF9dCDGSGXYbn3UFxjQeQtAHTSMKQDlgr5KizSMEWWIMZS__lxuErK5Z3BKHo_NANpl0xYce2pfJnU7hiliNrfnQwSaDr7pXZZDcxWvVjKl8JozsXxvzSu-kSab67MajPbpxXzE9992oSXYOSrxR3iazQcoro9-8s2d74fzgpRkrIePZQyAYTPjd9GlR6c1M902pn4mCH6kP4fBwCux4lKm_iBwCgwWU-sqp2Kcu9JKUDMSKQhPSR-3QspuFYJJL_kBmL1Nr8rpL83B01sS9JsAnR4dXE7fe-aQK7a2rXyFG2_dIS3M4JHfXS1GUFlpLuZOveahn2_Ys_ZEOZEp9JFaa6FgG6fwnBX_hqQwVcy7Vpl8aGiDFMa2X6nHHC4XdAaVj2-QbND7Mm6pGHNAvYa9CjnpUrT0m-TwnAT6_8S4dpUoifILkiEiRRI-zSVvdSQ==.eyJlbmRwb2ludF9zbHVnIjoib3BlbmFpL2dwdC01LW1pbmktMjAyNS0wOC0wN3xvcGVuYWkifQ"), "openrouter_metadata": Array [ Object { - "id": String("rs_0848749866e247ea016a886db6fff087d1b5b6efd41ccac47f"), + "id": String("rs_0efd722f56d64447016aa3da9389c487d19b3ba847be53365c"), "index": Number(0), "field": String("openai_encrypted_content"), }, @@ -24,8 +24,17 @@ expression: v index: 2, part: ToolCall( Start { - id: "call_KnvO99RwD3rjBcOEPnBpNQ7O", + id: "call_NjNRzmeNIFfEhIlY1DJt8Elg", name: "run_me", + decoding: Some( + ArgumentDecoding { + omit_null: [ + "foo", + ], + properties: {}, + items: None, + }, + ), }, ), metadata: {}, @@ -52,79 +61,7 @@ expression: v index: 2, part: ToolCall( ArgumentChunk( - "{\"", - ), - ), - metadata: {}, - }, - Part { - index: 2, - part: ToolCall( - ArgumentChunk( - "foo", - ), - ), - metadata: {}, - }, - Part { - index: 2, - part: ToolCall( - ArgumentChunk( - "\":", - ), - ), - metadata: {}, - }, - Part { - index: 2, - part: ToolCall( - ArgumentChunk( - "null", - ), - ), - metadata: {}, - }, - Part { - index: 2, - part: ToolCall( - ArgumentChunk( - ",\"", - ), - ), - metadata: {}, - }, - Part { - index: 2, - part: ToolCall( - ArgumentChunk( - "bar", - ), - ), - metadata: {}, - }, - Part { - index: 2, - part: ToolCall( - ArgumentChunk( - "\":\"", - ), - ), - metadata: {}, - }, - Part { - index: 2, - part: ToolCall( - ArgumentChunk( - "foo", - ), - ), - metadata: {}, - }, - Part { - index: 2, - part: ToolCall( - ArgumentChunk( - "\"}", + "{\"foo\":null,\"bar\":\"foo\"}", ), ), metadata: {}, @@ -148,10 +85,10 @@ expression: v "", ), metadata: { - "openai_encrypted_content": String("gAAAAABqiG26cwCaeVLhIDmyWh9QS5IOMJDoVAS5Rmk2C5l_uTWY1Bvl8Ezj3LOQuyNE429nXWiWolxw0qV2uWLiFUEUJGfSqPUsCGmD4p7XhcLVub26--oj7KcP9v1k0DbwAFZBpbrGYyGCAWMZCXv_QcG6pYO_SvRk4Q5qxOPs6rMYCfJi4Ts9NW1uRzjaxq3nM6VP8Bh5h1l35sgxzQ0_F9S_0ZsEcgaS8W8PI40RpqLCk92o1eO91H9K8rQitNnuyX6NQyI5g_S3p6TycqBipPygYqcgFfqah4F-p-mpDGR7Kz8XDW5rlu_HvUd_QiUxfI_GFmBj71uToKTVJMxOPZTP54GP8zDvnU9qfKJTZ1Ig_QFH54nYshOoyw4i1TpgwpQ4NY6FXkX2rPZoBuqm_gthOENYyyS6g4IW8b23UI98Uz0d92oeI7e090mg8Y3RNJAkJqnzr68sRVSBJtRABwqnhohskJPVDbMESHhKU-kA0pERO2ROHbgizAgbJ5QKCUBcX8cTPf4bcrIYTp453l5AYoImlr4695fSMiQynt6S-U8AiBKDdExEKmxWrxMewsVLvvZvngb_hje9eAht5jSqd9cHSb0MSLUil5egHwR4f19uvgB61pgJtuOaiU54biFYyxiVZV3FWP54PBOemegTCLVu9NzraIZlYacLPJuvFWFWvmHfYkAznogNGtgN6Pbsh3oclbdNc9dz55j40DWOHcLNn7zKf2rq0_UuOSDAjEL_BrFkHIIn-kgRHSpugXWWSu-lMVt1JjqR9ltkES_dmMmoZyJTMnpLNJRreyEqR-GxsA4irGD1Rt5LXKpbkBM7t6DGryAA5uNLDd2m47fjkvY0X9u-p1x4p11ZtOv9IkCJEu8Sgb06SbsH5Q1cN_hx4SXGnhM1EUoDGfeyyAmFxtxQczCeo1-P3hraGJM0TBbWJHIwNQi04OqSKJ7Qp_EUsRZTvi7Wxd4iExRUXADK0JsJw1HiK3LKa-YilPm5mdq6_U9TSRSsX7xwCsZTPCdFvGcpm9Jyf9xKELpHV8Gz5f6nZwHv3cuxrIMEmCU43OX3p-EoLRqjbk3DuSmUkAY07DnwJVdWmncTIaqV3koAbv1GEz0cLu6xnEy7iNiv3UZ6m0jpSi9xJpD2kDUodeGLZywcXxLhEwOqSwbECGr7yXahWJtQb0Y7rTaVVP1_iKVwwqXAcQZhr21JNBoQg-miF7EcrDc9Wa0KR8sGT4_sryiocSGIUuhN9jFbSgcHdOgXPLuwKkyNLvdEoMmkpm8qkmRW3xyo_6qeyDjnl7hoDctpakms3MlXrZ3-QefvOUN2et_Pn3kWNx0I6iqIofy0V9zxjGaGvcTWAVEGHdo0Ncc2PFGgDYpq1JWCn2aka1cKdwvuMZYtdTJKCT0w3L8FTUHW.eyJlbmRwb2ludF9zbHVnIjoib3BlbmFpL2dwdC01LW1pbmktMjAyNS0wOC0wN3xvcGVuYWkifQ"), + "openai_encrypted_content": String("gAAAAABqo9qWuWPlEk077GYV60QwAbJZz80at0wgJ06EL_r10a6s1cL2zr15893j6R_js_nmHN6gxIi3m9JHY0mB6CabO_MSNBH17ucryN8GnlwJSTumks5BsP1P6pirD2T5duzPD59HTlzZT1IZaX6qd1X4W7zeUy7CZoe48vtoBgdlaHgSuGtSFkT_HlmGqo9UciCvFT11HBx5-RMBR17SuUvn-3JqPyI8IolsQV7Di3B-QDFx5RIXFpXD8S8uUPD3Hnz1UKf6Tk4Cfs0OVffyS7Wb38aXKUmSqjKNbcFUlSX8kEpSuvPmgaWkUy4jZX9_oD_lkE3uHQwoTPmAJmpNne9n9pA9LRFGRuuBy0P6CTZjUKwWCOI6mME-Tfl41zaxEvJO2yL2SymSee7Yxyxftw9mPAfqz72JwcncRR1bRvkpcCTSXSJ-6UrT0IJXRYorAhWzcP-f71fiL8pjqIrT1uL7Ry01yHt2cFnQl5K926euu2HjCXjbznUvbEEIeAlc0YTdhQQvS1iHYjBVfX-NuFXjZVqN8oCFCytcJglllY5Qx0-8n9pAjlhw9o_pxzdD3zHU8rtA6adQp9_SR0Db1sk2e4r85dbT9AnnUb5zob9S1TQd2NZRdgZxqBF4idF6zwrlic86sqdLLcW1GH6EoY2jP4w3_1f6EDaGPFwpLvnQtGAWs0Efsl7tml6rzMsKBg5TnFNY8ADwlonk3P7LfsEebrx2gN0mut44h0wlifmzvxS3h4Rj_5NuF63vn5qrTJSFSEzPEFxjsRqaf_H6xq_rP2ttCWrsyXe-J5OXUtwusXATXRmKAm24Ksc-x9bR-C3fycXQAHuxEIc0M3KzgzveP-PcE5u0LSyPCQ3X1QtHkKpPk-qDK0YqHinRt-n6vMkAPiVQr7rElzeifCkib8qivpqBp_6uWoVS3-2h66T91T0hJGqybLoHEQbUoSP8WYX7kGNrE2y_maIgEbTUsC7f2KMmBIYNTO0mXvxFwCficXpa3KNS-_sSYKOGMs-eNi_048WvwQU3cXiqfRIG19AixBC4BzXEADa0VnizkIpBSRLDjoXqlr93-kB-x11nAeyMc2Hcx4vruS295q6mNOWBH5cicNloFcvkQDvYWNXl3g4v7u5y9xcOO9xb7_Q4HU2wjXX-lBP69_EcIjfn85ElHODHPyBnO_dK59KVkIobs0YmeADvpAFb9qAY7_uJh8u9QCgkAZb-LNK9lgcDKAA_dfaHuXhR2ygb6AZ_ogKRONVQWStWqkz2DqPYuXtq-UsDSNXD_IKa6Dixwf4Eh7zQdchmVYyFxPjzfDBz_VvZwEkgsI0T349wrXcLw4c4EYPxrG__5DidbJxV1dc26srw03WG0ytW-Yuo4EtP20mFiMXadrMpsOMyPPa8uKf1vytsjaq9TQ7uY8AMFbMSQz8spuy9VA==.eyJlbmRwb2ludF9zbHVnIjoib3BlbmFpL2dwdC01LW1pbmktMjAyNS0wOC0wN3xvcGVuYWkifQ"), "openrouter_metadata": Array [ Object { - "id": String("rs_052d8ffbb7051945016a886dba832487d1ab470a80f3e75c98"), + "id": String("rs_0c90c56a63d867fa016aa3da96bf2887d1b6861c01c7976c84"), "index": Number(0), "field": String("openai_encrypted_content"), }, @@ -161,133 +98,119 @@ expression: v Part { index: 1, part: Message( - "I", - ), - metadata: {}, - }, - Part { - index: 1, - part: Message( - " ran", - ), - metadata: {}, - }, - Part { - index: 1, - part: Message( - " the", + "Done", ), metadata: {}, }, Part { index: 1, part: Message( - " tool", + " —", ), metadata: {}, }, Part { index: 1, part: Message( - " for", + " I", ), metadata: {}, }, Part { index: 1, part: Message( - " you", + " ran", ), metadata: {}, }, Part { index: 1, part: Message( - ".", + " the", ), metadata: {}, }, Part { index: 1, part: Message( - " Output", + " tool", ), metadata: {}, }, Part { index: 1, part: Message( - " returned", + " with", ), metadata: {}, }, Part { index: 1, part: Message( - ":", + " the", ), metadata: {}, }, Part { index: 1, part: Message( - " \"", + " argument", ), metadata: {}, }, Part { index: 1, part: Message( - "working", + " {\"", ), metadata: {}, }, Part { index: 1, part: Message( - "!\"\n\n", + "bar", ), metadata: {}, }, Part { index: 1, part: Message( - "Arguments", + "\":\"", ), metadata: {}, }, Part { index: 1, part: Message( - " used", + "foo", ), metadata: {}, }, Part { index: 1, part: Message( - " when", + "\"}", ), metadata: {}, }, Part { index: 1, part: Message( - " calling", + " and", ), metadata: {}, }, Part { index: 1, part: Message( - " the", + " it", ), metadata: {}, }, Part { index: 1, part: Message( - " tool", + " returned", ), metadata: {}, }, @@ -298,41 +221,6 @@ expression: v ), metadata: {}, }, - Part { - index: 1, - part: Message( - " {\"", - ), - metadata: {}, - }, - Part { - index: 1, - part: Message( - "foo", - ), - metadata: {}, - }, - Part { - index: 1, - part: Message( - "\":", - ), - metadata: {}, - }, - Part { - index: 1, - part: Message( - " null", - ), - metadata: {}, - }, - Part { - index: 1, - part: Message( - ",", - ), - metadata: {}, - }, Part { index: 1, part: Message( @@ -343,140 +231,140 @@ expression: v Part { index: 1, part: Message( - "bar", + "working", ), metadata: {}, }, Part { index: 1, part: Message( - "\":", + "!\".", ), metadata: {}, }, Part { index: 1, part: Message( - " \"", + " Do", ), metadata: {}, }, Part { index: 1, part: Message( - "foo", + " you", ), metadata: {}, }, Part { index: 1, part: Message( - "\"}\n\n", + " want", ), metadata: {}, }, Part { index: 1, part: Message( - "Do", + " me", ), metadata: {}, }, Part { index: 1, part: Message( - " you", + " to", ), metadata: {}, }, Part { index: 1, part: Message( - " want", + " run", ), metadata: {}, }, Part { index: 1, part: Message( - " me", + " it", ), metadata: {}, }, Part { index: 1, part: Message( - " to", + " again", ), metadata: {}, }, Part { index: 1, part: Message( - " run", + " with", ), metadata: {}, }, Part { index: 1, part: Message( - " it", + " different", ), metadata: {}, }, Part { index: 1, part: Message( - " again", + " arguments", ), metadata: {}, }, Part { index: 1, part: Message( - " with", + " or", ), metadata: {}, }, Part { index: 1, part: Message( - " different", + " perform", ), metadata: {}, }, Part { index: 1, part: Message( - " arguments", + " something", ), metadata: {}, }, Part { index: 1, part: Message( - " or", + " else", ), metadata: {}, }, Part { index: 1, part: Message( - " show", + " with", ), metadata: {}, }, Part { index: 1, part: Message( - " more", + " the", ), metadata: {}, }, Part { index: 1, part: Message( - " details", + " result", ), metadata: {}, },