feat(core/cli): expose model thinking events in --output-format stream-json#22089
feat(core/cli): expose model thinking events in --output-format stream-json#22089KobiAms wants to merge 3 commits intogoogle-gemini:mainfrom
Conversation
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
Summary of ChangesHello, 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 enhances the 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 support for 'thinking' events in the stream-json output format. However, a critical security vulnerability has been identified where these new events fail to apply necessary ANSI escape sequence sanitization, potentially allowing malicious model output to bypass security controls and lead to terminal-based attacks like phishing or command injection. This issue is addressed by applying stripAnsi to relevant fields, aligning with best practices for sanitizing display output. Additionally, there's an opportunity to improve the structure of the new ThinkingEvent for better machine-readability by separating data from presentation, suggesting a rename of content to description for clearer intent.
packages/core/src/output/types.ts
Outdated
|
|
||
| export interface ThinkingEvent extends BaseJsonStreamEvent { | ||
| type: JsonStreamEventType.THINKING; | ||
| content: string; |
There was a problem hiding this comment.
The ThinkingEvent interface is part of a machine-readable stream-json API. Using content and pre-formatting it with markdown in nonInteractiveCli.ts mixes data with presentation. A cleaner API would be to provide the raw data components. I suggest renaming content to description to make the intent clearer and to align with the ThoughtSummary type from which this event is generated. This will allow consumers of the stream to handle formatting themselves.
| content: string; | |
| description: string; |
b07a4da to
07e9dc6
Compare
Add THINKING event type to JsonStreamEventType enum and ThinkingEvent interface in types.ts. Handle GeminiEventType.Thought in the non-interactive stream loop to emit structured thinking events when using --output-format stream-json. Previously, thinking tokens from models like Gemini 2.5 Pro were silently dropped in non-interactive mode. The interactive UI already handled these via useGeminiStream, but the stream-json path had no corresponding support. Developers building integrations can now observe model reasoning in real time. Fixes google-gemini#22083
…oughtSummary - Rename ThinkingEvent.content to description to match the ThoughtSummary type and avoid mixing presentation into the machine-readable API - Apply stripAnsi to subject and description fields in thinking events, consistent with how Content events are handled, to prevent ANSI injection from model output - Respect getRawOutput/getAcceptRawOutputRisk flags for thinking events
07e9dc6 to
31345a7
Compare
|
Hi there! Thank you for your interest in contributing to Gemini CLI. To ensure we maintain high code quality and focus on our prioritized roadmap, we have updated our contribution policy (see Discussion #17383). We only guarantee review and consideration of pull requests for issues that are explicitly labeled as 'help wanted'. All other community pull requests are subject to closure after 14 days if they do not align with our current focus areas. For this reason, we strongly recommend that contributors only submit pull requests against issues explicitly labeled as 'help-wanted'. This pull request is being closed as it has been open for 14 days without a 'help wanted' designation. We encourage you to find and contribute to existing 'help wanted' issues in our backlog! Thank you for your understanding and for being part of our community! |
Summary
Fixes #22083
When using
--output-format stream-jsonwith a thinking-capable model (e.g. Gemini 2.5 Pro), modelThoughtevents were silently dropped. The interactive UI already handles thinking viauseGeminiStream, but the non-interactive stream-json path had no corresponding support.THINKING = 'thinking'toJsonStreamEventTypeenum inpackages/core/src/output/types.tsThinkingEventinterface (content: string,subject?: string) to theJsonStreamEventunionGeminiEventType.ThoughtinnonInteractiveCli.tsto emit structuredthinkingevents in stream-json modedocs/reference/configuration.mdto document all stream-json event types includingthinkingExample stream-json output with thinking:
{"type":"thinking","timestamp":"2025-...","content":"**Analysis** Let me think through this...","subject":"Analysis"}Test plan
gemini -p "solve step by step: what is 15% of 240" --output-format stream-jsonwith a thinking-capable model and verifythinkingevents appear in the outputnpm run preflight— all checks pass (2 pre-existing flaky UI integration test timeouts unrelated to this change)thinkingevents emitted when none are produced)