Skip to content

feat: streaming dep optional, non streaming path, streaming flag, rel… - #65

Open
bobrykov wants to merge 1 commit into
masterfrom
feat/non-streaming-path
Open

feat: streaming dep optional, non streaming path, streaming flag, rel…#65
bobrykov wants to merge 1 commit into
masterfrom
feat/non-streaming-path

Conversation

@bobrykov

@bobrykov bobrykov commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

…ease profile

@bobrykov

bobrykov commented Aug 1, 2026

Copy link
Copy Markdown
Contributor Author

@CodeRabbit review

@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

Turn execution and feature configuration

Layer / File(s) Summary
Feature configuration and gated APIs
Cargo.toml, src/capabilities.rs, src/stream.rs, src/managers.rs, src/provider.rs, src/reflection/llm.rs, src/engine/bare/...
Streaming dependencies and APIs are feature-gated. Provider infrastructure, hook paths, tool-health paths, and schema validation compile only when their features are enabled.
Turn-mode dispatch and cancellation
src/engine/bare.rs
BareLoop now supports TurnMode, non-streaming provider requests, cancellation, shared success and failure bookkeeping, and mode-aware dispatch.
Execution tests and streaming compatibility
src/engine/bare.rs
Mocks assemble non-streaming responses. Tests cover defaults, tool loops, cancellation, observers, and feature-gated streaming behavior.
Example and feature documentation
README.md, CHANGELOG.md, examples/chat.rs, src/observer.rs, src/stream/rate_limit.rs, src/structured.rs
The example selects streaming at runtime. Documentation describes feature dependencies, turn paths, API changes, and corrected references.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant chat
  participant BareLoop
  participant ProviderClient
  User->>chat: Set NO_STREAM=1
  chat->>BareLoop: Set TurnMode::NonStreaming
  BareLoop->>ProviderClient: Send create_message request
  ProviderClient-->>BareLoop: Return assembled response
  BareLoop-->>chat: Return completed turn
  chat-->>User: Print assembled response
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 50.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main changes: optional streaming support, a non-streaming path, and a streaming feature flag.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/non-streaming-path

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (3)
src/engine/bare.rs (2)

2708-2716: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Rename the test to match what it asserts.

turn_mode_default_is_nonstreaming_without_feature asserts both branches: NonStreaming without the feature and Streaming with it. The name describes only one branch.

📝 Proposed rename
-    fn turn_mode_default_is_nonstreaming_without_feature() {
+    fn turn_mode_default_follows_streaming_feature() {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/engine/bare.rs` around lines 2708 - 2716, Rename the test function
turn_mode_default_is_nonstreaming_without_feature to reflect that it verifies
the default turn mode for both streaming and non-streaming feature
configurations. Keep the assertions and test behavior unchanged.

2469-2494: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the shared mock response assembly.

MockClient::create_message here and RecordingClient::create_message at lines 6062-6092 contain the same event-to-response assembly: pop queued events, track the last MessageDelta stop reason, feed each event to StreamAccumulator, then build the NonStreamingResponse. The two copies will drift as the accumulator contract evolves.

Extract one test helper, for example fn assemble_response(events: Vec<StreamEvent>) -> Result<NonStreamingResponse, ApiError>, and call it from both clients.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/engine/bare.rs` around lines 2469 - 2494, Extract the duplicated
event-to-response logic from MockClient::create_message and
RecordingClient::create_message into a shared test helper such as
assemble_response. The helper should accept queued StreamEvent values, track the
latest MessageDelta stop reason, process events through StreamAccumulator, and
return the constructed NonStreamingResponse or ApiError; update both client
methods to call it after popping their events.
src/provider.rs (1)

130-130: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Collapse the repeated provider gate into one named feature.

The predicate any(feature = "openai", feature = "anthropic", feature = "gemini") now appears at lines 58, 62, 64, 130, 198, 213, 326, and 333. Each new provider requires editing every occurrence, and a missed site produces a feature-combination build break rather than a visible error.

Add an internal aggregate feature in Cargo.toml, for example _http_provider = [], have openai, anthropic, and gemini enable it, then gate on #[cfg(feature = "_http_provider")] at each site.

Also applies to: 198-198, 213-213, 326-333

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/provider.rs` at line 130, Replace the repeated provider cfg predicate in
src/provider.rs, including the sites around provider definitions and
HTTP-provider code, with #[cfg(feature = "_http_provider")]. Define the internal
_http_provider aggregate feature in Cargo.toml and update the openai, anthropic,
and gemini features to enable it, preserving their existing feature behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Cargo.toml`:
- Around line 99-104: Remove panic = "abort" from the [profile.release]
configuration so dispatch_tool’s catch_unwind-based tool-panic isolation remains
effective in release builds. Preserve the other release profile settings
unchanged.

In `@examples/chat.rs`:
- Around line 336-353: Update the runtime mode setup around `no_stream` so it is
true whenever the `streaming` feature is unavailable, ensuring the later
result-printing logic displays non-streaming responses. In the feature-enabled
live-streaming branch, explicitly select `TurnMode::Streaming` before
configuring the text streamer, while preserving the existing `NO_STREAM=1`
non-streaming behavior.

In `@README.md`:
- Around line 170-175: Update the README paragraphs describing streaming so they
distinguish feature availability from runtime mode selection: state that the
streaming feature enables TurnMode::Streaming, but turns use it only when
selected, including via set_turn_mode, while TurnMode::NonStreaming remains
available. Apply the same clarification to the referenced paragraph.

In `@src/engine/bare.rs`:
- Around line 122-134: Resolve the conflicting defaults for TurnMode by removing
its derived Default implementation and relying solely on default_turn_mode() for
the feature-dependent constructor default. Update the associated public
documentation to describe this single default contract accurately, while
preserving the enum variants and mode-switching behavior.
- Around line 136-144: Update the documentation for the cfg-gated Streaming
variant to remove the claim that disabling the streaming feature produces a
LoopError::Config at turn time, while retaining only the accurate streaming
feature requirement.

---

Nitpick comments:
In `@src/engine/bare.rs`:
- Around line 2708-2716: Rename the test function
turn_mode_default_is_nonstreaming_without_feature to reflect that it verifies
the default turn mode for both streaming and non-streaming feature
configurations. Keep the assertions and test behavior unchanged.
- Around line 2469-2494: Extract the duplicated event-to-response logic from
MockClient::create_message and RecordingClient::create_message into a shared
test helper such as assemble_response. The helper should accept queued
StreamEvent values, track the latest MessageDelta stop reason, process events
through StreamAccumulator, and return the constructed NonStreamingResponse or
ApiError; update both client methods to call it after popping their events.

In `@src/provider.rs`:
- Line 130: Replace the repeated provider cfg predicate in src/provider.rs,
including the sites around provider definitions and HTTP-provider code, with
#[cfg(feature = "_http_provider")]. Define the internal _http_provider aggregate
feature in Cargo.toml and update the openai, anthropic, and gemini features to
enable it, preserving their existing feature behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6a114cd1-01ed-41f8-943b-b6b87b293fa5

📥 Commits

Reviewing files that changed from the base of the PR and between a7c0ef6 and 212f0dc.

📒 Files selected for processing (17)
  • CHANGELOG.md
  • Cargo.toml
  • README.md
  • examples/chat.rs
  • src/capabilities.rs
  • src/engine/bare.rs
  • src/engine/bare/compact.rs
  • src/engine/bare/dispatch.rs
  • src/engine/bare/emission.rs
  • src/engine/bare/stream.rs
  • src/managers.rs
  • src/observer.rs
  • src/provider.rs
  • src/reflection/llm.rs
  • src/stream.rs
  • src/stream/rate_limit.rs
  • src/structured.rs

Comment thread Cargo.toml
Comment on lines +99 to +104
[profile.release]
lto = "fat"
codegen-units = 1
strip = true
panic = "abort"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

panic = "abort" disables the tool-panic isolation in dispatch_tool.

src/engine/bare/dispatch.rs wraps each tool invocation in AssertUnwindSafe(...).catch_unwind() and converts a panic into a soft error result (lines 552-601). With panic = "abort" a panicking tool terminates the process in release builds instead of returning a recoverable result, so the release binary loses a documented resilience guarantee that debug builds keep.

Consider dropping panic = "abort" from the release profile, or documenting that tool-panic recovery only holds under panic = "unwind".

♻️ Proposed change to keep unwind-based tool isolation
 [profile.release]
 lto = "fat"
 codegen-units = 1
 strip = true
-panic = "abort"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
[profile.release]
lto = "fat"
codegen-units = 1
strip = true
panic = "abort"
[profile.release]
lto = "fat"
codegen-units = 1
strip = true
panic = "abort"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Cargo.toml` around lines 99 - 104, Remove panic = "abort" from the
[profile.release] configuration so dispatch_tool’s catch_unwind-based tool-panic
isolation remains effective in release builds. Preserve the other release
profile settings unchanged.

Comment thread examples/chat.rs
Comment on lines +336 to +353
// Pick the engine turn mode at runtime. `NO_STREAM=1` drives each turn via
// the non-streaming `create_message` path (no per-delta callbacks, the
// assembled response is printed after the turn). Otherwise stream text
// deltas live as they arrive.
let no_stream = std::env::var("NO_STREAM").map_or(false, |v| v == "1");
#[cfg(feature = "streaming")]
if no_stream {
agent.set_turn_mode(loopctl::engine::TurnMode::NonStreaming);
} else {
agent.set_text_streamer(Arc::new(|delta| {
print!("{delta}");
let _ = std::io::stdout().flush();
}));
}
#[cfg(not(feature = "streaming"))]
{
let _ = no_stream;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Keep no_stream aligned with the actual engine mode.

When the streaming feature is disabled and NO_STREAM is unset, no_stream remains false. The engine still uses the non-streaming path, but Lines 393-399 then skip printing a non-empty result.output. The default no-feature example can therefore complete without displaying the assistant response.

Set no_stream to true when streaming is unavailable. Select TurnMode::Streaming explicitly in the live-streaming branch instead of relying on the constructor default.

Suggested fix
-    let no_stream = std::env::var("NO_STREAM").map_or(false, |v| v == "1");
+    let no_stream = cfg!(not(feature = "streaming"))
+        || std::env::var("NO_STREAM").map_or(false, |v| v == "1");

     #[cfg(feature = "streaming")]
     if no_stream {
         agent.set_turn_mode(loopctl::engine::TurnMode::NonStreaming);
     } else {
+        agent.set_turn_mode(loopctl::engine::TurnMode::Streaming);
         agent.set_text_streamer(Arc::new(|delta| {
             print!("{delta}");
             let _ = std::io::stdout().flush();
         }));
     }
-
-    #[cfg(not(feature = "streaming"))]
-    {
-        let _ = no_stream;
-    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Pick the engine turn mode at runtime. `NO_STREAM=1` drives each turn via
// the non-streaming `create_message` path (no per-delta callbacks, the
// assembled response is printed after the turn). Otherwise stream text
// deltas live as they arrive.
let no_stream = std::env::var("NO_STREAM").map_or(false, |v| v == "1");
#[cfg(feature = "streaming")]
if no_stream {
agent.set_turn_mode(loopctl::engine::TurnMode::NonStreaming);
} else {
agent.set_text_streamer(Arc::new(|delta| {
print!("{delta}");
let _ = std::io::stdout().flush();
}));
}
#[cfg(not(feature = "streaming"))]
{
let _ = no_stream;
}
// Pick the engine turn mode at runtime. `NO_STREAM=1` drives each turn via
// the non-streaming `create_message` path (no per-delta callbacks, the
// assembled response is printed after the turn). Otherwise stream text
// deltas live as they arrive.
let no_stream = cfg!(not(feature = "streaming"))
|| std::env::var("NO_STREAM").map_or(false, |v| v == "1");
#[cfg(feature = "streaming")]
if no_stream {
agent.set_turn_mode(loopctl::engine::TurnMode::NonStreaming);
} else {
agent.set_turn_mode(loopctl::engine::TurnMode::Streaming);
agent.set_text_streamer(Arc::new(|delta| {
print!("{delta}");
let _ = std::io::stdout().flush();
}));
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/chat.rs` around lines 336 - 353, Update the runtime mode setup
around `no_stream` so it is true whenever the `streaming` feature is
unavailable, ensuring the later result-printing logic displays non-streaming
responses. In the feature-enabled live-streaming branch, explicitly select
`TurnMode::Streaming` before configuring the text streamer, while preserving the
existing `NO_STREAM=1` non-streaming behavior.

Comment thread README.md
Comment on lines +170 to +175
Enable the `streaming` feature (implied by every HTTP provider) to route turns
through [`StreamHandler`](https://docs.rs/loopctl/latest/loopctl/stream/handler/struct.StreamHandler.html)
with retry, timeout, rate-limit detection, and `on_text_delta` /
`on_thinking_delta` callbacks for real-time token display. Switch a constructed
loop explicitly with
[`set_turn_mode`](https://docs.rs/loopctl/latest/loopctl/engine/struct.BareLoop.html#method.set_turn_mode).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Describe runtime mode selection explicitly.

The streaming feature makes TurnMode::Streaming available. It does not force every turn to use that mode. A loop can select TurnMode::NonStreaming while the feature is enabled, so these paragraphs should refer to TurnMode::Streaming selection rather than feature availability.

Suggested wording
-Enable the `streaming` feature ... to route turns through `StreamHandler`.
+Enable the `streaming` feature to make `TurnMode::Streaming` available.
+When that mode is selected, turns use `StreamHandler`; otherwise they use
+`ApiClient::create_message`.

-Each turn ... uses the streaming path (`StreamHandler`) when `streaming`
-is enabled, or `create_message` otherwise.
+Each turn ... uses `StreamHandler` when `TurnMode::Streaming` is selected,
+or `create_message` otherwise.

Also applies to: 179-184

🧰 Tools
🪛 LanguageTool

[grammar] ~174-~174: Ensure spelling is correct
Context: ...itch a constructed loop explicitly with set_turn_mode. #...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 170 - 175, Update the README paragraphs describing
streaming so they distinguish feature availability from runtime mode selection:
state that the streaming feature enables TurnMode::Streaming, but turns use it
only when selected, including via set_turn_mode, while TurnMode::NonStreaming
remains available. Apply the same clarification to the referenced paragraph.

Comment thread src/engine/bare.rs
Comment on lines +122 to +134
/// The default is `Streaming` when `streaming` is compiled in, otherwise
/// `NonStreaming`. Switch modes on a constructed loop with
/// [`set_turn_mode`](BareLoop::set_turn_mode).
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum TurnMode {
/// Fulfil each turn via [`ApiClient::create_message`].
///
/// No streaming code is exercised; `on_text_delta`,
/// `on_thinking_delta`, and the text streamer never fire. The full
/// assistant text still surfaces through
/// [`on_response`](crate::observer::LoopObserver::on_response).
#[default]
NonStreaming,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

TurnMode::default() and the constructor default disagree.

The derived Default impl marks NonStreaming as the default, so TurnMode::default() returns NonStreaming even when the streaming feature is enabled. The doc on line 122 states the default is Streaming under that feature, and default_turn_mode() implements that. Two different defaults exist on one public type, which will surprise callers who use TurnMode::default().

Pick one contract. Either drop the Default derive and expose only the constructor default, or make the doc state that Default is always NonStreaming while the constructor resolves per feature.

♻️ Option: drop the `Default` derive
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
 pub enum TurnMode {
     /// Fulfil each turn via [`ApiClient::create_message`].
     ///
     /// No streaming code is exercised; `on_text_delta`,
     /// `on_thinking_delta`, and the text streamer never fire. The full
     /// assistant text still surfaces through
     /// [`on_response`](crate::observer::LoopObserver::on_response).
-    #[default]
     NonStreaming,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/// The default is `Streaming` when `streaming` is compiled in, otherwise
/// `NonStreaming`. Switch modes on a constructed loop with
/// [`set_turn_mode`](BareLoop::set_turn_mode).
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum TurnMode {
/// Fulfil each turn via [`ApiClient::create_message`].
///
/// No streaming code is exercised; `on_text_delta`,
/// `on_thinking_delta`, and the text streamer never fire. The full
/// assistant text still surfaces through
/// [`on_response`](crate::observer::LoopObserver::on_response).
#[default]
NonStreaming,
/// The default is `Streaming` when `streaming` is compiled in, otherwise
/// `NonStreaming`. Switch modes on a constructed loop with
/// [`set_turn_mode`](BareLoop::set_turn_mode).
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TurnMode {
/// Fulfil each turn via [`ApiClient::create_message`].
///
/// No streaming code is exercised; `on_text_delta`,
/// `on_thinking_delta`, and the text streamer never fire. The full
/// assistant text still surfaces through
/// [`on_response`](crate::observer::LoopObserver::on_response).
NonStreaming,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/engine/bare.rs` around lines 122 - 134, Resolve the conflicting defaults
for TurnMode by removing its derived Default implementation and relying solely
on default_turn_mode() for the feature-dependent constructor default. Update the
associated public documentation to describe this single default contract
accurately, while preserving the enum variants and mode-switching behavior.

Comment thread src/engine/bare.rs
Comment on lines +136 to +144
/// Fulfil each turn via [`ApiClient::stream_messages`] wrapped in
/// [`StreamHandler`](crate::stream::handler::StreamHandler).
///
/// Requires the `streaming` feature. Constructing or selecting this
/// mode without `streaming` enabled yields a
/// [`LoopError::Config`](crate::error::LoopError::Config) at turn time.
#[cfg(feature = "streaming")]
Streaming,
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove the unreachable LoopError::Config claim.

The Streaming variant is gated by #[cfg(feature = "streaming")], so it does not exist when the feature is off. A caller cannot construct or select it, and do_turn has no Config error arm. The documented "yields a LoopError::Config at turn time" behavior is unreachable.

📝 Proposed doc fix
-    /// Requires the `streaming` feature. Constructing or selecting this
-    /// mode without `streaming` enabled yields a
-    /// [`LoopError::Config`](crate::error::LoopError::Config) at turn time.
+    /// Requires the `streaming` feature. Without that feature this variant
+    /// is not compiled, so selecting it is a compile-time error rather than
+    /// a runtime one.
     #[cfg(feature = "streaming")]
     Streaming,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/// Fulfil each turn via [`ApiClient::stream_messages`] wrapped in
/// [`StreamHandler`](crate::stream::handler::StreamHandler).
///
/// Requires the `streaming` feature. Constructing or selecting this
/// mode without `streaming` enabled yields a
/// [`LoopError::Config`](crate::error::LoopError::Config) at turn time.
#[cfg(feature = "streaming")]
Streaming,
}
/// Fulfil each turn via [`ApiClient::stream_messages`] wrapped in
/// [`StreamHandler`](crate::stream::handler::StreamHandler).
///
/// Requires the `streaming` feature. Without that feature this variant
/// is not compiled, so selecting it is a compile-time error rather than
/// a runtime one.
#[cfg(feature = "streaming")]
Streaming,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/engine/bare.rs` around lines 136 - 144, Update the documentation for the
cfg-gated Streaming variant to remove the claim that disabling the streaming
feature produces a LoopError::Config at turn time, while retaining only the
accurate streaming feature requirement.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant