Bump rig to 0.41 so reasoning shows on LocalAI (#745) - #751
Merged
Conversation
added 3 commits
August 5, 2026 17:57
rig 0.39 only deserialized `delta.reasoning_content`. Providers that stream reasoning as `delta.reasoning` — LocalAI, Cerebras — had it dropped by serde while text and tool calls carried in the same delta worked fine, which is why the panel stayed empty but everything else looked normal. rig 0.40 added the fallback upstream; this takes us to 0.41. The bump is wide. 0.41 splits the classic runtime into rig-agent behind an `agent` feature, replaces Tool::definition with description/parameters across all 37 tools, drops ToolDyn in favour of a concrete struct, and makes Agent::preamble and Agent::model private. Tools move to the context-free PortableTool contract, which is the honest fit — the loop has driven its own dispatch since 4.5h-6 and never used rig's ToolContext. The erased-tool seam is now dirge's own DynTool rather than rig's; it has broken on two consecutive rig releases and does not need to be theirs. AnyAgentInner holds the completion model directly instead of a rig Agent it only ever read the model back out of. Capturing the reasoning then broke Cerebras, which rejects an echoed reasoning_content on the next turn. The field is renamed to `reasoning` at the wire boundary rather than dropped, so the model keeps its own reasoning in context — the same thing @ai-sdk/cerebras does for opencode. Backends that want reasoning_content are untouched: DeepSeek needs it on tool-call turns, and llama.cpp/LocalAI chat templates read it back out of the assistant turn. rmcp was on three versions at once — ours, one from rig's unused rmcp feature, one from agent-client-protocol. That feature is gone, acp goes to 2.0 and rmcp to 3.1, leaving one copy at latest. rusqlite, sysinfo, sha2, jsonschema, base64, compact_str, http and notify-rust go current too; tree-sitter stays at 0.25 because 0.26 does not resolve against the grammar crates. heal.rs listed a third repair it never implemented. The claim is gone, with a note on why the port was skipped: opencode carries an equivalent for DeepSeek only because its own transform lifts reasoning out of the message content, and dirge replays the block in place.
It said two versions and then listed three.
rig 0.41 made tool_definition sync; this call site kept the block_on wrapper. It is behind experimental-graph-search, so only CI's --all-features and windows-default clippy configs reached it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #745.
rig 0.39 only deserialized
delta.reasoning_content. Providers that stream reasoning asdelta.reasoning— LocalAI, and as it turns out Cerebras — had it dropped by serde, while text and tool calls carried in the same delta worked fine. That's why the reporter saw an empty reasoning panel and normal output otherwise. Parsing the log they attached: 196 chunks, 188 withreasoning, zero withreasoning_content.rig 0.40 added
reasoning_content.or_else(|| reasoning)upstream. Checked against opencode, which the reporter noted does not have the bug:@ai-sdk/openai-compatibledoesdelta.reasoning_content ?? delta.reasoning. Same precedence, so this matches the reference implementation.The bump
0.41 splits the classic runtime into
rig-agentbehind anagentfeature, replacesTool::definitionwithdescription/parametersacross all 37 tools, dropsToolDynfor a concrete struct, and makesAgent::preambleandAgent::modelprivate.PortableToolcontract. The loop has driven its own dispatch since 4.5h-6 and never used rig'sToolContext.DynTool. It has broken on two consecutive rig releases and does not need to be rig's. 0.39's semantics are ported exactly, including thenull->{}fallback for all-optional args and the rule that aStringoutput is not double-quoted.AnyAgentInnerholds the completion model directly instead of a rigAgentit only ever read the model back out of.Cerebras fallout
Capturing the reasoning made Cerebras 400 on the next turn:
property 'messages.N.assistant.reasoning_content' is unsupported. Confirmed a real regression by running the smoke test on 0.39 (passes) and 0.41 (fails), not just assuming a flaky live API.The field is renamed to
reasoningat the wire boundary rather than dropped, so the model keeps its own reasoning in context. That is what@ai-sdk/cerebrasdoes for opencode. Backends that wantreasoning_contentare untouched — DeepSeek needs it on tool-call turns, and llama.cpp/LocalAI chat templates read it back out of the assistant turn. Only the OpenAI Responses API still has the block dropped, since it keys reasoning to encrypted ids we don't retain.Dependencies
rmcpwas on three versions at once: ours, one from rig'srmcpfeature (which nothing here used), and one fromagent-client-protocol. That feature is gone, acp goes to 2.0 and rmcp to 3.1 — one copy, at latest.rusqlite,sysinfo,sha2,jsonschema,base64,compact_str,httpandnotify-rustgo current too.tree-sitterstays at 0.25; 0.26 does not resolve against the grammar crates.Verification
cargo fmt --allcleanRUSTFLAGS="-D warnings" cargo clippy --all-targetsexit 0cargo nextest run --bin dirge --retries 2 --no-fail-fast— 4995 passed, 1 skipped, 0 failed (baseline 4960)The live
h7_cerebras_tool_dispatch_completes_round_trippasses, so the rename is verified against the real API rather than only in unit tests.Two things worth a reviewer's eye:
memory,session_search,spec), silently changing model-visible prompt text. Restored, and every changed file is now checked so no long or multi-line literal value differs from HEAD.reasoning_contentbefore checking whetherreasoningwas already present, which lost the field on a skipped message when a later one triggered the re-serialize. Fixed, with a test that fails against the buggy version.