feat(Message API): MCP tool streaming support - #414
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughThe PR introduces streaming MCP tool-loop support for Anthropic Messages API with a new interception layer that detects tool_use blocks, executes MCP tool calls, and emits synthetic tool events within the SSE stream. Additionally, three handler functions are exposed at crate visibility, and router logic is updated to conditionally route streaming requests through the tool-loop when MCP servers are present. Changes
Sequence DiagramsequenceDiagram
participant Client
participant Router as AnthropicRouter
participant ToolLoop as execute_streaming_tool_loop
participant SSEConsumer as SSE Channel
participant UpstreamAPI as Anthropic API
participant MCPServers as MCP Tool Servers
Client->>Router: POST messages (streaming=true, mcp_servers)
Router->>ToolLoop: execute_streaming_tool_loop(router, req_ctx, mcp_servers)
ToolLoop->>SSEConsumer: Create SSE channel for client response
ToolLoop->>UpstreamAPI: Spawn background task, send upstream request
UpstreamAPI-->>ToolLoop: SSE stream (content_block_start, delta, stop)
ToolLoop->>ToolLoop: parse_sse_frame, detect tool_use blocks
ToolLoop->>ToolLoop: Transform content_block_start to mcp_tool_use, accumulate state
ToolLoop->>SSEConsumer: Forward/emit mcp_tool_use events
ToolLoop->>ToolLoop: Detect StopReason::ToolUse
ToolLoop->>MCPServers: execute_mcp_tool_calls(tool_blocks)
MCPServers-->>ToolLoop: Tool execution results
ToolLoop->>SSEConsumer: emit_mcp_tool_result_events
ToolLoop->>UpstreamAPI: Continue SSE stream consumption
UpstreamAPI-->>ToolLoop: Final message_delta, message_stop
ToolLoop->>SSEConsumer: emit_final_events (usage, stop_reason)
SSEConsumer-->>Client: Complete SSE stream to client
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
Comment |
Summary of ChangesHello @key4ng, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly enhances the Anthropic Messages API by integrating streaming support for MCP tools. The change enables the gateway to dynamically intercept and process tool calls within an ongoing Server-Sent Event (SSE) stream. It executes these tools and injects their results back into the stream, providing a more interactive and integrated experience for clients utilizing streaming and multi-cloud platform tools. This allows for a continuous, real-time interaction where tool usage and results are part of the same coherent stream. Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces streaming support for MCP tool use in the Anthropic Messages API, adding a new module streaming.rs to intercept, process, and generate SSE streams. Critical security concerns regarding Denial of Service (DoS) vulnerabilities due to unbounded resource accumulation from upstream workers have been identified. These cross-cutting security issues, requiring design decisions, should be addressed in dedicated security pull requests. Additionally, there are opportunities to improve code quality by removing unused code, refactoring complex functions for maintainability, and enhancing robustness through better JSON parsing error handling.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Fix all issues with AI agents
In `@model_gateway/src/routers/anthropic/messages/streaming.rs`:
- Around line 692-697: emit_final_events currently ignores the Result returned
by send_sse when sending "message_delta" and "message_stop"; modify
emit_final_events to await and check the Result from send_sse for both calls
(the send_sse invocations that send "message_delta" and "message_stop") and, on
Err (e.g., channel closed), log a warning or error via the existing
logger/tracing (include context like "failed to send final SSE event" and which
event type). Ensure you do not change control flow beyond logging (since stream
is ending), but surface the failure for observability.
- Around line 210-211: The current map_err call discards the original error from
handler::select_worker, losing context; change the closure to capture the
original error (e.g., |e| ...) and include its Display/Debug output in the
returned error message so the error preserves details about why selection
failed; update the call to handler::select_worker(&router.worker_registry,
model_id) to propagate or wrap the original error (referencing select_worker,
worker_registry, and model_id) instead of replacing it with a generic string.
- Around line 106-107: The token accumulators total_input_tokens and
total_output_tokens can overflow as u32 (given DEFAULT_MAX_ITERATIONS and large
per-iteration token counts); change their types to u64 and update every
accumulation site in streaming.rs to use u64 arithmetic (or use saturating_add
if you prefer saturating behavior) so additions are safe — ensure any casts
to/from token counts elsewhere are adjusted (e.g., when calling functions or
returning values) to match the new u64 type.
- Around line 523-524: The code silently converts malformed JSON by using
serde_json::from_str(input_json).unwrap_or(...); change this to explicitly
handle the Result from serde_json::from_str(input_json) (e.g., match or if let
Err(e) => ...) so you log a warning that includes the parsing error and the
offending input_json before falling back to Value::Object(Map::new()); update
the use site where input: Value is created to perform that match and emit the
warning (use the existing logger in scope or log::warn!) so malformed tool input
is visible in logs.
- Around line 57-62: The spawned fire-and-forget task can panic and close the
stream without emitting an error; wrap the call to run_tool_loop in a
panic-capture wrapper (use std::panic::catch_unwind with
std::panic::AssertUnwindSafe around the async body) inside the tokio::spawn so
panics are caught, log the panic and call send_sse_error(&tx, &panic_info).await
(or convert the panic payload to a string) instead of letting the task abort;
keep the existing parameters (tx, router, req_ctx, mcp_servers) and ensure both
normal Err(e) and caught panics produce a logged message and an SSE error to the
client.
|
Hi @key4ng, the branch Please use one of the following formats:
Allowed types:
|
|
Hi @key4ng, the branch Please use one of the following formats:
Allowed types:
|
Description
Problem
The Anthropic router supports non-streaming MCP tool loops but passes streaming requests through without MCP support — streaming.rs was empty. When stream: true and MCP tools are present, there was no mechanism to intercept the upstream worker's SSE stream, detect tool_use blocks, execute MCP tools, and emit mcp_tool_use/mcp_tool_result events within a single coherent SSE stream.
Solution
Implement a streaming MCP tool loop that intercepts upstream SSE events, transforms tool_use → mcp_tool_use, executes MCP tools betweeniterations, emits synthetic mcp_tool_result events, and continues the loop — all within one SSE stream to the client. Uses a tokio::mpsc channel with a spawned task to drive the tool loop while returning an Axum streaming response immediately.
Changes
Key behaviors
Test Plan
stream result
event: message_start data: {"type":"message_start","message":{"model":"claude-3-haiku-20240307","id":"msg_01T5ZFUVHU3BhyDpwg6tv59v","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":691,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":5,"service_tier":"standard","inference_geo":"not_available"}}}event: content_block_start
data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}
event: ping
data: {"type":"ping"}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Okay, let's"}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" look"}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" up"}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" the stock prices"}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" for Google and Oracle"}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"."}}
event: content_block_stop
data: {"type":"content_block_stop","index":0}
event: content_block_start
data: {"type":"content_block_start","index":1,"content_block":{"type":"mcp_tool_use","id":"mcptoolu_019oo5fy6WaRFV5TNH31boiQ","name":"brave_web_search","server_name":"brave","input":{}}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":""}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"{""}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"query":"}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":" "goog"}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"le stoc"}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"k price"}}
event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":" today"}"}}
event: content_block_stop
data: {"type":"content_block_stop","index":1}
event: content_block_start
data: {"type":"content_block_start","index":2,"content_block":{"type":"mcp_tool_result","tool_use_id":"mcptoolu_019oo5fy6WaRFV5TNH31boiQ","is_error":false,"content":[{"type":"text","text":"Title: Alphabet Inc. (GOOG) Stock Price, News, Quote & History - Yahoo Finance\nDescription: (GOOG) is witnessing increased analyst confidence as Scotiabank raised its price target to $400 following strong earnings. The company is also ramping up its capital expenditures to over $500 billion in AI initiatives, aligning with industry trends.\nURL: https://finance.yahoo.com/quote/GOOG/\n\nTitle: Check out Alphabet Class A's stock price (GOOGL) in real time\nDescription: Get Alphabet Class A (GOOGL:NASDAQ) real-time stock quotes, news, price and financial information from CNBC.\nURL: https://www.cnbc.com/quotes/GOOGL\n\nTitle: Alphabet Class C: GOOG Stock Price Quote & News | Robinhood\nDescription: The company's market cap stands at 3.76T, with a P/E ratio of 29.48 and a dividend yield of 26.0%. On 2026-02-12, Alphabet Class C(GOOG) stock traded between a low of $310.13 and a high of $321.11.\nURL: https://robinhood.com/us/en/stocks/GOOG/\n\nTitle: Alphabet Class A: GOOGL Stock Price Quote & News | Robinhood\nDescription: As of 2026-02-12, Alphabet Class A(GOOGL) stock has fluctuated between $309.43 and $316.24. The current price stands at $313.32, placing the stock +1.3% above today's low and -0.9% off the high.\nURL: https://robinhood.com/us/en/stocks/GOOGL/\n\nTitle: Buy Alphabet Stock – GOOG Stock Quote Today & Investment Insights - Public.com\nDescription: The 52-week low for Alphabet stock is $142.66. The current Alphabet stock price $undefined has increased 100.00% from its 52-week low · Yes, the Alphabet stock pays a dividend to its shareholders.\nURL: https://public.com/stocks/goog\n\nTitle: Alphabet Inc (Google) Class C - GOOG Stock Price and Chart\nDescription: Google Short - Target $312Hello Traders, After the recent impulsive move up into the 349–350 area and subsequent displacement lower, price is now retracing back into a prior supply / inefficiency zone between 338–342.\nURL: https://www.tradingview.com/symbols/NASDAQ-GOOG/\n\nTitle: Alphabet Inc. (Google) Stock | GOOGL - Investing.com\nDescription: Alphabet A is listed and trades on the Nasdaq Stock Exchange. ... The Alphabet A dividend yield is 0.27%. As of today, Alphabet A market cap is 3.76T. The Alphabet A EPS (TTM) is 10.80.\nURL: https://www.investing.com/equities/google-inc\n\nTitle: Alphabet (Class C) (GOOG) Stock price today - quote & chart\nDescription: The firm's investments in up-and-coming technologies such as self-driving cars (Waymo), health (Verily), and internet access (Google Fiber) make up the rest. The Alphabet Inc. Class C Capital Stock (GOOG) stock price today is $318.15, reflecting ...\nURL: https://www.kraken.com/stocks/goog\n\nTitle: symbol Stock Quote Price and Forecast | CNN\nDescription: This is a 0.85% drop. Closed at $330.34. The stock has since dropped $0.46 in after-hours trading. ... Alphabet, Inc. is a holding company, which engages in software, health care, transportation, and other technologies.\nURL: https://www.cnn.com/markets/stocks/GOOG\n\nTitle: GOOGL Stock Price Quote | Morningstar\nDescription: Stock XNAS Rating as of Feb 11, 2026 · Download PDF · More Actions · $310.96 −7.62 (2.39%) View Full Chart · As of Feb 11, 2026, 9:00:11 PM Delayed Price Closed · View Archive · Malik Ahmed Khan Feb 5, 2026 · Alphabet reported strong ...\nURL: https://www.morningstar.com/stocks/xnas/googl/quote"}]}}
event: content_block_stop
data: {"type":"content_block_stop","index":2}
event: content_block_start
data: {"type":"content_block_start","index":3,"content_block":{"type":"mcp_tool_use","id":"mcptoolu_018W9SZdhEwUB6ZYERB74fvH","name":"brave_web_search","server_name":"brave","input":{}}}
event: ping
data: {"type":"ping"}
event: content_block_delta
data: {"type":"content_block_delta","index":3,"delta":{"type":"input_json_delta","partial_json":""}}
event: content_block_delta
data: {"type":"content_block_delta","index":3,"delta":{"type":"input_json_delta","partial_json":"{"query": "o"}}
event: content_block_delta
data: {"type":"content_block_delta","index":3,"delta":{"type":"input_json_delta","partial_json":"racle stock"}}
event: content_block_delta
data: {"type":"content_block_delta","index":3,"delta":{"type":"input_json_delta","partial_json":" pri"}}
event: content_block_delta
data: {"type":"content_block_delta","index":3,"delta":{"type":"input_json_delta","partial_json":"ce toda"}}
event: content_block_delta
data: {"type":"content_block_delta","index":3,"delta":{"type":"input_json_delta","partial_json":"y"}"}}
event: content_block_stop
data: {"type":"content_block_stop","index":3}
event: content_block_start
data: {"type":"content_block_start","index":4,"content_block":{"type":"mcp_tool_result","tool_use_id":"mcptoolu_018W9SZdhEwUB6ZYERB74fvH","is_error":false,"content":[{"type":"text","text":"Title: Oracle Corporation (ORCL) Stock Price, News, Quote & History - Yahoo Finance\nDescription: Find the latest Oracle Corporation (ORCL) stock quote, history, news and other vital information to help you with your stock trading and investing.\nURL: https://finance.yahoo.com/quote/ORCL/\n\nTitle: Check out Oracle Corp's stock price (ORCL) in real time\nDescription: Get Oracle Corp (ORCL:NYSE) real-time stock quotes, news, price and financial information from CNBC.\nURL: https://www.cnbc.com/quotes/ORCL\n\nTitle: Oracle - Stock information\nDescription: To opt-in for investor email alerts, please enter your email address in the field below and select at least one alert option. After submitting your request, you will receive an activation email to the requested email address. You must click the activation link in order to complete your subscription.\nURL: https://investor.oracle.com/stock-information/default.aspx\n\nTitle: Oracle: ORCL Stock Price Quote & News | Robinhood\nDescription: With a market cap of 505.49B, Oracle(ORCL) trades at $156.64. The stock has a price-to-earnings ratio of 30.05 and currently yields dividends of 1.3%.\nURL: https://robinhood.com/us/en/stocks/ORCL/\n\nTitle: symbol Stock Quote Price and Forecast | CNN\nDescription: The price of ORCL shares has increased $6.34 since the market last closed. This is a 4.65% rise. Closed at $142.82. The stock has since risen $0.58 in after-hours trading. ... Oracle Corp. engages in the provision of products and services that ...\nURL: https://www.cnn.com/markets/stocks/ORCL\n\nTitle: ORCL Stock Price and Chart — NYSE:ORCL — TradingView\nDescription: View live Oracle Corporation chart to track its stock's price action. Find market predictions, ORCL financials and market news.\nURL: https://www.tradingview.com/symbols/NYSE-ORCL/\n\nTitle: ORCL Stock Price | Analyst Target 275.75 & Consensus\nDescription: A ‘rising’ price indicates ... in weekly price is between -0.5% and 0.5%. The Oracle Corporation share price today is $156.76, reflecting a -0.25% change over the last 24 hours and 17.14% over the past ...\nURL: https://www.etoro.com/markets/orcl\n\nTitle: Oracle (ORCL) Stock Chart - Investing.com\nDescription: The Oracle stock price today is 157.16.\nURL: https://www.investing.com/equities/oracle-corp-chart\n\nTitle: Oracle - 40 Year Stock Price History | ORCL | MacroTrends\nDescription: Historical daily share price chart and data for Oracle since 1986 adjusted for splits and dividends. The latest closing stock price for Oracle as of February 11, 2026 is 156.95. The all-time high Oracle stock closing price was 326.90 on September 10, 2025. The Oracle 52-week high stock price ...\nURL: https://www.macrotrends.net/stocks/charts/ORCL/oracle/stock-price-history\n\nTitle: Oracle (ORCL) Stock price today - quote & chart\nDescription: The Oracle Corp (ORCL) stock pre-market price today is $158.50, reflecting a +0.88% pre-market move since the market last closed. The company’s market capitalization stands at $455.40B, with a daily trading volume of $251.07K shares.\nURL: https://www.kraken.com/stocks/orcl"}]}}
event: content_block_stop
data: {"type":"content_block_stop","index":4}
event: content_block_start
data: {"type":"content_block_start","index":5,"content_block":{"type":"text","text":""}}
event: ping
data: {"type":"ping"}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"Summary"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":":"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"\n\nGoogle"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" ("}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"Alphabet Inc."}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" Class"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" C -"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" GOOG)"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" Stock"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" Price:"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"\n-"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" The"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" current"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" Google"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" stock price is aroun"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"d $318"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":".15"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" as"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" of the"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" most"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" recent trading day"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"."}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"\n- Google stock has"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" ran"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"ged between"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" $310"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"-"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"$321"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" in the past"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" week"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":","}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" with a "}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"52-week low"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" of $142"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":".66"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"."}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"\n- Analysts"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" are"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" generally"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" bullish on Google"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":","}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" with a price"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" target of aroun"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"d $400"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" per share."}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"\n- Google has"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" a market capit"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"alization of around $"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"3"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":".76"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" trillion."}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"\n\nOracle ("}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"ORCL)"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" Stock Price:"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" \n- The"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" current Oracle stock price"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" is around $156"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":".64 as"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" of the most recent"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" trading day."}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"\n- Oracle stock has"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" trade"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"d in"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" the"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" range of $142"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"-"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"$157"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" over"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" the past week."}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"\n- Oracle"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" has"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" a market capitalization"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" of around $505"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" "}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"billion.\n-"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" Oracle stock"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" has a"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" P"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"/E ratio of"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" 30.05"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" "}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"and a"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" dividend yield of "}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"1.3%."}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"\n\nOverall"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":", both Google an"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"d Oracle appear"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" to be trading at"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" relatively strong"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" levels"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" compare"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"d to their recent"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" historical prices"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":". Google in"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" particular is seeing"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" bullish sentiment"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" from analysts"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" base"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"d on its growth"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" prospects, while Oracle"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" remains"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" a steady tech"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" blue"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" chip."}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" The"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" summary"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" highlights the key stock"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" price points an"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"d financial"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" metrics for"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" each"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":" company"}}
event: content_block_delta
data: {"type":"content_block_delta","index":5,"delta":{"type":"text_delta","text":"."}}
event: content_block_stop
data: {"type":"content_block_stop","index":5}
event: message_delta
data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":5396,"output_tokens":408}}
event: message_stop
data: {"type":"message_stop"}
Checklist
cargo +nightly fmtpassescargo clippy --all-targets --all-features -- -D warningspassesSummary by CodeRabbit
Release Notes