## 0xPlaygrounds/rig — v0.39.0…v0.40.0

_91 commits._

### Features
- **feat(core): expand rig::prelude to cover the everyday API surface (#2057)** (12515a8)
- **feat(tool)!: structured tool-execution results (#2015)** (9fc7dc3)
- **feat(agent)!: hook system v2 — composable middleware (#2012)** (e43089a)
- **Add Groq agent tool cassette regressions (#2011)** (ea014f3)
- **Add Mistral agent tool cassette regressions (#2010)** (95b37c6)
- **Add DeepSeek agent tool cassette regressions (#2009)** (e80a486)
- **Add xAI agent tool cassette regressions (#2008)** (a39c9ac)
- **Add OpenRouter agent tool cassette regressions (#2006)** (afbd426)
- **feat(ollama): Extend `think` options with `max` (#1982)** (854d9d5)
- **feat(examples): human-in-the-loop tool-call approval — examples + tests (#1967)** (00573a9)
- **feat(rig-core): steer the model request per turn from a hook via Flow::OverrideRequest (#1966)** (f764884)
- **feat(rig-core): rewrite tool results from a hook via Flow::RewriteResult (#1965)** (67a896b)
- **feat(rig-core): rewrite tool-call arguments from a hook via Flow::RewriteArgs (#1963)** (bcfb699)
- **feat(neo4j): implement InsertDocuments for Neo4jVectorIndex (#1960)** (003e6b7)
- **feat(rig-core): concurrent tool execution in the streaming driver (parity with blocking tool_concurrency) (#1957)** (e0bd386)
- **feat(rig-core): ToolCallExtensions — per-call tool context through the agent loop, MCP & sub-agents (supersedes #1537, #1953) (#1954)** (1bee2a1)
- **feat(openai): preserve responses prompt cache parameters (#1830)** (e777c1d)
- **feat(streaming)!: surface unmodeled provider output items through the stream (#1951)** (b59e013)
- **feat(openai-responses)!: preserve unknown Output payloads (#1950)** (684e247)
- **feat(rig-core)!: integrate hooks into AgentRun via a composable AgentRunner (#1945)** (81c1414)
- **feat(rig-core)!: broaden provider error-response inspection workspace-wide (#1944)** (6918058)
- **feat(message): add video helper constructors + OpenRouter audio/video conversion tests (#1942)** (f3048e2)
- **feat(rig-core): expose provider error response inspection (#1859)** (3d33796)
- **feat(agent): add OutputMode to compose structured output with tools (#1928) (#1929)** (f4a0d60)

### Fixes
- **fix(agent)!: enforce exact max turns budget (#2093)** (18f7547)
- **fix(vertexai): map generation config and preserve image history (#2086)** (56e15e1)
- **fix(telemetry): keep GenAI message span fields empty (#2066)** (d03689a)
- **fix(chatgpt): preserve non-success response errors (#2053)** (9d74cc5)
- **fix(vertexai): preserve signed thought text parts (#2052)** (c9788df)
- **Add ChatGPT Codex cassette regression suite (#2005)** (0737bf9)
- **fix(chatgpt): fallback on empty SSE output (#2001)** (7059c59)
- **fix(openai): preserve reasoning text content (#1999)** (e62e2ae)
- **Fix provider ClientBuilder API key aliases (#1996)** (24a4176)
- **fix: preserve OpenAI Responses instructions (#1995)** (0972c5f)
- **fix(openai): accept null Responses metadata (#1993)** (af0a97f)
- **fix(postgres): update sqlx and pgvector (#1992)** (417c931)
- **fix(gemini): tolerate omitted proto defaults (#1984)** (520b3a2)
- **fix(openai): make Responses API strict tools opt-in (#1991)** (70f0204)
- **fix(ollama): omit `think` when unset so the model default applies (#1990)** (d1151af)
- **fix(agent): stream concurrent tool results as they complete (#1981)** (747b95a)
- **fix(anthropic): deserialize explicit null citations as empty vec (#1972)** (cb5018c)
- **fix(anthropic): coerce tool_use.input to an object at the send boundary (#1964)** (6b1991b)
- **fix(openai-compat): normalize evicted tool-call string arguments to an object (#1958)** (fbfa8a0)
- **fix(rig-core): fix epub loader tests + prevent CWD-relative fixture-path regressions (#1940)** (dc252ae)
- **fix(gemini): default totalTokenCount to avoid deser crash on empty generations (#1936)** (de90692)
- **fix(ollama): preserve assistant reasoning from non-streaming responses (#1926) (#1927)** (57de200)

### Backend
- **Remove unused derive and core APIs (#2087)** (21be6f1)
- **Remove unused stream completion stdout helper (#2085)** (aebf757)
- **Remove unused generation wrapper traits (#2083)** (d799996)
- **Remove unused Anthropic decoders (#2082)** (129391c)
- **Flatten Tool metadata API (#2029)** (4c25682)
- **Gate Gemini image cassette tests on image feature (#2007)** (4419316)
- **Release-N cleanup: correctness fixes + dead-code removal (#1987)** (eda2e17)

### Tests
- **test: add Bedrock cassette coverage (#2084)** (562d81e)
- **test(anthropic): cover ANTHROPIC_BASE_URL from_env (#2051)** (0421e50)
- **test(auth): add non-interactive oauth cassette coverage (#2050)** (9ab30a8)
- **test(perplexity): add cassette coverage (#2049)** (ec20bee)
- **test(gemini): live cassette hook-system stress suite (#2013)** (562353a)
- **test(gemini): production-grade generateContent cassette suite (#2004)** (ace3e72)
- **test(anthropic): production-grade Messages API cassette suite (#2003)** (e7f486e)
- **test(openai): production-grade Responses API cassette suite + tool_choice and replay-ID fixes (#2002)** (f18f73c)
- **test(anthropic): add null citation streaming cassette (#1978)** (47f20d7)
- **test(openai-compat): genuinely exercise the #1958 tool-call eviction string-leak (+ live cassette) (#1962)** (2b6f763)

### Docs
- **docs(examples): demonstrate scratchpad failure policy (#2092)** (c233d35)
- **docs(examples): add force_tool_first_turn hook example (#2014)** (cc4808c)
- **docs(providers): add provider implementation checklist (#1997)** (ecec2b7)
- **docs(examples): refresh Gemini Deep Research example (#1976)** (3f9c66d)
- **docs: update agent and contribution guidance (#1974)** (45f1840)
- **docs: add Archestra to "Who is using Rig?" section (#1925)** (5bfe20b)

### Chore
- **chore: release v0.40.0 (#1923)** (2f37dfc)
- **chore(deps): bump prost from 0.14.3 to 0.14.4 (#2017)** (7a86fc7)
- **chore(deps): bump log from 0.4.29 to 0.4.33 (#2018)** (8c03640)
- **chore(deps): bump tonic-prost from 0.14.5 to 0.14.6 (#2016)** (cf3d25a)
- **refactor(agent)!: unify PromptResponse and FinalResponse into one type (#2056)** (a26409c)
- **chore(core)!: API paper cuts — duplicate names, hand-copied setters, dead types (#2055)** (0a328b4)
- **refactor(openrouter): use generic completion model (#2054)** (2fc78dd)
- **refactor(providers)!: remove galadriel provider (#2041)** (695490d)
- **refactor(providers)!: collapse remaining providers onto GenericCompletionModel<Ext> (#2035 phases 2–4) (#2040)** (e8cc0ca)
- **refactor(providers)!: migrate llamafile onto GenericCompletionModel<Ext> (#2035 phase 1) (#2038)** (49532e0)
- **refactor(core)!: delete unused evals module and experimental feature flag (#2036)** (8693f13)
- **chore(deps): bump assert_fs from 1.1.3 to 1.1.4 (#1933)** (70627a0)
- **chore(deps): bump trybuild from 1.0.116 to 1.0.117 (#1935)** (807b9c0)
- **chore(deps): bump chrono from 0.4.44 to 0.4.45 (#1934)** (155a491)
- **chore(deps): bump uuid from 1.23.3 to 1.23.4 (#1975)** (38382b8)
- **chore(deps): bump scylla from 1.6.0 to 1.7.0 (#1932)** (07a70ed)
- **refactor(agent): unify streaming/non-streaming seams; fix Anthropic streaming output_schema drop (#1986)** (13602eb)
- **refactor(agent): unify the streaming and non-streaming drivers over one engine (#1985)** (50dc5d5)
- **refactor(rig-core)!: remove the experimental pipeline module (#1941)** (b17a0a0)
- **ci: run doctests and stop rig-sqlite opting out of them (#1939)** (2cafc88)
- **refactor(rig-core): replace nanoid with fastrand for internal IDs (#1938)** (1d41118)
- **refactor(examples): migrate to a package-per-example layout (#1937)** (4346a50)

_Recap by [Repo Wrapped](https://repowrapped.com/gh/0xPlaygrounds/rig?utm_source=github-action)._