1313 * See the License for the specific language governing permissions and
1414 * limitations under the License.
1515 */
16+
1617package io .agentscope .core .agent ;
1718
1819import java .util .Arrays ;
2425 *
2526 * <p>Controls which event types to receive and how streaming content is delivered.
2627 *
28+ * <p><b>Reasoning filtering (Issue #265):</b>
29+ * Some streaming backends emit both:
30+ * <ul>
31+ * <li><b>Reasoning chunks</b>: incremental deltas during the reasoning process</li>
32+ * <li><b>Reasoning result</b>: the final consolidated reasoning output</li>
33+ * </ul>
34+ *
35+ * <p>Use {@link #isIncludeReasoningChunk()} and {@link #isIncludeReasoningResult()} to filter
36+ * these reasoning-related emissions when {@link EventType#REASONING} is enabled.
37+ *
2738 * <p><b>Example usage:</b>
2839 *
2940 * <pre>{@code
3344 * .incremental(true)
3445 * .build();
3546 *
36- * // All events including final result, cumulative mode
47+ * // Reasoning events, but hide intermediate deltas and only keep the final reasoning result
3748 * StreamOptions options = StreamOptions.builder()
38- * .eventTypes(EventType.ALL)
39- * .includeAgentResult(true)
40- * .incremental(false)
49+ * .eventTypes(EventType.REASONING)
50+ * .includeReasoningChunk(false)
51+ * .includeReasoningResult(true)
52+ * .incremental(true)
4153 * .build();
4254 *
4355 * // Multiple specific types
@@ -52,6 +64,22 @@ public class StreamOptions {
5264 private final Set <EventType > eventTypes ;
5365 private final boolean incremental ;
5466
67+ /**
68+ * Whether to include the incremental delta of the reasoning process during streaming.
69+ * <p>
70+ * If false, intermediate reasoning chunk emissions should be filtered out by the stream
71+ * implementation.
72+ */
73+ private final boolean includeReasoningChunk ;
74+
75+ /**
76+ * Whether to include the final consolidated reasoning output in the response.
77+ * <p>
78+ * If false, final reasoning result emissions should be filtered out by the stream
79+ * implementation.
80+ */
81+ private final boolean includeReasoningResult ;
82+
5583 /**
5684 * Private constructor called by the builder.
5785 *
@@ -60,10 +88,12 @@ public class StreamOptions {
6088 private StreamOptions (Builder builder ) {
6189 this .eventTypes = builder .eventTypes ;
6290 this .incremental = builder .incremental ;
91+ this .includeReasoningChunk = builder .includeReasoningChunk ;
92+ this .includeReasoningResult = builder .includeReasoningResult ;
6393 }
6494
6595 /**
66- * Default options: All event types (except AGENT_RESULT) , incremental mode.
96+ * Default options: All event types, incremental mode, include both reasoning chunk and reasoning result .
6797 *
6898 * @return StreamOptions with default configuration
6999 */
@@ -83,8 +113,7 @@ public static Builder builder() {
83113 /**
84114 * Get the set of event types that should be streamed.
85115 *
86- * <p>If the set contains {@link EventType#ALL}, all event types (except AGENT_RESULT unless
87- * explicitly opted-in) will be streamed.
116+ * <p>If the set contains {@link EventType#ALL}, all event types will be streamed.
88117 *
89118 * @return The set of event types to stream
90119 */
@@ -104,6 +133,28 @@ public boolean isIncremental() {
104133 return incremental ;
105134 }
106135
136+ /**
137+ * Whether reasoning "chunk" emissions should be included.
138+ *
139+ * <p>Reasoning chunks are the incremental delta of the reasoning process during streaming.</p>
140+ *
141+ * @return true if reasoning chunks should be included
142+ */
143+ public boolean isIncludeReasoningChunk () {
144+ return includeReasoningChunk ;
145+ }
146+
147+ /**
148+ * Whether the final reasoning result should be included.
149+ *
150+ * <p>The reasoning result is the final consolidated reasoning output in the response.</p>
151+ *
152+ * @return true if the final reasoning result should be included
153+ */
154+ public boolean isIncludeReasoningResult () {
155+ return includeReasoningResult ;
156+ }
157+
107158 /**
108159 * Check if a specific event type should be streamed.
109160 *
@@ -114,11 +165,28 @@ public boolean shouldStream(EventType type) {
114165 return eventTypes .contains (EventType .ALL ) || eventTypes .contains (type );
115166 }
116167
168+ /**
169+ * Convenience method for stream implementations to decide whether to emit a reasoning subtype.
170+ *
171+ * <p><b>TODO (Issue #265):</b> Thread these flags through the stream event mapping layer where
172+ * reasoning events are converted into Flux emissions (e.g., when distinguishing chunk vs result).
173+ *
174+ * @param isChunk true if the reasoning emission is an incremental chunk, false if it is the final result
175+ * @return true if this reasoning emission should be included
176+ */
177+ public boolean shouldIncludeReasoningEmission (boolean isChunk ) {
178+ return isChunk ? includeReasoningChunk : includeReasoningResult ;
179+ }
180+
117181 /** Builder for {@link StreamOptions}. */
118182 public static class Builder {
119183 private Set <EventType > eventTypes = EnumSet .of (EventType .ALL );
120184 private boolean incremental = true ;
121185
186+ // Defaults are "true" to preserve existing behavior.
187+ private boolean includeReasoningChunk = true ;
188+ private boolean includeReasoningResult = true ;
189+
122190 /**
123191 * Set which event types to stream.
124192 *
@@ -150,6 +218,34 @@ public Builder incremental(boolean incremental) {
150218 return this ;
151219 }
152220
221+ /**
222+ * Include or exclude incremental reasoning chunk emissions.
223+ *
224+ * <p>When {@link EventType#REASONING} is enabled, some providers emit reasoning deltas (chunks)
225+ * as the model thinks. Set to false to hide these.</p>
226+ *
227+ * @param includeReasoningChunk true to include chunk emissions, false to filter them out
228+ * @return this builder
229+ */
230+ public Builder includeReasoningChunk (boolean includeReasoningChunk ) {
231+ this .includeReasoningChunk = includeReasoningChunk ;
232+ return this ;
233+ }
234+
235+ /**
236+ * Include or exclude the final consolidated reasoning result emission.
237+ *
238+ * <p>When {@link EventType#REASONING} is enabled, some providers emit a final reasoning result.
239+ * Set to false to hide it.</p>
240+ *
241+ * @param includeReasoningResult true to include the final reasoning result, false to filter it out
242+ * @return this builder
243+ */
244+ public Builder includeReasoningResult (boolean includeReasoningResult ) {
245+ this .includeReasoningResult = includeReasoningResult ;
246+ return this ;
247+ }
248+
153249 public StreamOptions build () {
154250 return new StreamOptions (this );
155251 }
0 commit comments