Commit Graph
7187 Commits
Author SHA1 Message Date
sydney-runkleandgithub-actions[bot] 1ffa5bc740 chore(deps): upgrade dependencies with uv lock --upgrade 2026-10-18 00:50:24 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>John Kennedyopen-swe[bot] <open-swe@users.noreply.github.com>
beb6fe2ffb chore(deps-dev): bump dotenv from 17.4.2 to 18.0.4 in /libs/cli/js-examples in the major group (#9154)
Bumps the major group in /libs/cli/js-examples with 1 update:
[dotenv](https://github.com/motdotla/dotenv).

Updates `dotenv` from 17.4.2 to 18.0.4
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/motdotla/dotenv/blob/master/CHANGELOG.md">dotenv's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/motdotla/dotenv/compare/v18.0.3...v18.0.4">18.0.4</a>
(2026-09-25)</h2>
<h3>Changed</h3>
<ul>
<li><code>import dotenv/config</code> should default quiet: true (<a
href="https://redirect.github.com/motdotla/dotenv/pull/1063">#1063</a>)</li>
</ul>
<h2><a
href="https://github.com/motdotla/dotenv/compare/v18.0.2...v18.0.3">18.0.3</a>
(2026-09-22)</h2>
<h3>Changed</h3>
<ul>
<li>Patch <code>DOTENV_QUIET</code> setting when inside .env file (<a
href="https://redirect.github.com/motdotla/dotenv/pull/1059">#1059</a>)</li>
</ul>
<h2><a
href="https://github.com/motdotla/dotenv/compare/v18.0.1...v18.0.2">18.0.2</a>
(2026-09-21)</h2>
<h3>Changed</h3>
<ul>
<li>Patch additional edge cases for the fast parser (<a
href="https://redirect.github.com/motdotla/dotenv/pull/1056">#1056</a>)</li>
</ul>
<h2><a
href="https://github.com/motdotla/dotenv/compare/v18.0.0...v18.0.1">18.0.1</a>
(2026-09-18)</h2>
<h3>Changed</h3>
<ul>
<li>Handle file urls in config logging (<a
href="https://redirect.github.com/motdotla/dotenv/pull/1054">#1054</a>)</li>
</ul>
<h2><a
href="https://github.com/motdotla/dotenv/compare/v17.4.2...v18.0.0">18.0.0</a>
(2026-09-17)</h2>
<h3>Added</h3>
<ul>
<li>NEW: Dotenv now has a CLI. (<a
href="https://redirect.github.com/motdotla/dotenv/pull/1022">#1022</a>)</li>
</ul>
<pre lang="sh"><code>$ dotenv run -- node index.js
◇ injected env (2) from .env
Hello Dotenv
</code></pre>
<ul>
<li>NEW: Dotenv now has a fast parser thanks to <a
href="https://github.com/homanp"><code>@​homanp</code></a> of <a
href="https://superagent.sh">superagent.sh</a>. Pass <code>config({
fast: true })</code>, flag <code>--fast</code>, or set
<code>DOTENV_FAST=true</code> to opt-in to ~2x faster character-scanner
parser. (<a
href="https://redirect.github.com/motdotla/dotenv/pull/1010">#1010</a>)</li>
</ul>
<pre lang="sh"><code>$ dotenv run --fast -- node index.js
◇ injected env (2) from .env
Hello Dotenv
</code></pre>
<p><a href="https://dotenvx.com/blog/2026/09/28/dotenv-fast.html">faster
than Node native parseEnv!</a></p>
<h3>Changed</h3>
<ul>
<li>Injecting message sent to stderr rather than stdout and tips removed
(<a
href="https://redirect.github.com/motdotla/dotenv/pull/1037">#1037</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/motdotla/dotenv/commit/86804c0507aff98d3a82204759729af3bc2ce1a9"><code>86804c0</code></a>
18.0.4</li>
<li><a
href="https://github.com/motdotla/dotenv/commit/2403db57c3f8b01123d69a8b441a5f8b828fab3c"><code>2403db5</code></a>
changelog</li>
<li><a
href="https://github.com/motdotla/dotenv/commit/75b775eda45af3085fb7a7de6ae2613eb646807e"><code>75b775e</code></a>
npm audit</li>
<li><a
href="https://github.com/motdotla/dotenv/commit/7e1750ce8034b3c9485f1e1722587a40890449e1"><code>7e1750c</code></a>
Merge pull request <a
href="https://redirect.github.com/motdotla/dotenv/issues/1064">#1064</a>
from motdotla/dependabot/npm_and_yarn/ip-address-10.7.2</li>
<li><a
href="https://github.com/motdotla/dotenv/commit/a6ade63b6fa94a78fdc68f815c4e88cfe8781774"><code>a6ade63</code></a>
Merge pull request <a
href="https://redirect.github.com/motdotla/dotenv/issues/1063">#1063</a>
from motdotla/import</li>
<li><a
href="https://github.com/motdotla/dotenv/commit/288b0d7cd85d8deba3f91a995abd033786626a8d"><code>288b0d7</code></a>
patch test</li>
<li><a
href="https://github.com/motdotla/dotenv/commit/00da9125dd7633a121d169a3a55b62a686b64ef8"><code>00da912</code></a>
Bump ip-address from 10.2.0 to 10.7.2</li>
<li><a
href="https://github.com/motdotla/dotenv/commit/e6b58161d2f2b1448c735b1f6555bde7a20443b7"><code>e6b5816</code></a>
import 'dotenv/config' should still be defaulting to quiet</li>
<li><a
href="https://github.com/motdotla/dotenv/commit/3646ac5e5d000f5f68fe83db52399010f9cb781f"><code>3646ac5</code></a>
Merge pull request <a
href="https://redirect.github.com/motdotla/dotenv/issues/1061">#1061</a>
from motdotla/fast</li>
<li><a
href="https://github.com/motdotla/dotenv/commit/83fc961f92f6c330833da4a5f5dc7093d539501e"><code>83fc961</code></a>
report dotenv vs native vs dotenv.fast</li>
<li>Additional commits viewable in <a
href="https://github.com/motdotla/dotenv/compare/v17.4.2...v18.0.4">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dotenv&package-manager=npm_and_yarn&previous-version=17.4.2&new-version=18.0.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: John Kennedy <jkennedyvz@users.noreply.github.com>
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
2026-10-18 00:49:00 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>John Kennedyopen-swe[bot] <open-swe@users.noreply.github.com>
0eb194fe60 chore(deps-dev): bump the minor-and-patch group in /libs/prebuilt with 6 updates (#9150)
Bumps the minor-and-patch group in /libs/prebuilt with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [langchain-core](https://github.com/langchain-ai/langchain) | `1.6.1`
| `1.6.5` |
| [pytest-mock](https://github.com/pytest-dev/pytest-mock) | `3.15.1` |
`3.16.0` |
| [syrupy](https://github.com/syrupy-project/syrupy) | `6.0.0` | `6.1.1`
|
| [psycopg-binary](https://github.com/psycopg/psycopg) | `3.3.4` |
`3.3.6` |
| [ruff](https://github.com/astral-sh/ruff) | `0.16.5` | `0.16.9` |
| [ty](https://github.com/astral-sh/ty) | `0.0.75` | `0.0.84` |

Updates `langchain-core` from 1.6.1 to 1.6.5
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/langchain-ai/langchain/releases">langchain-core's
releases</a>.</em></p>
<blockquote>
<h2>langchain-core==1.6.5</h2>
<p>Changes since langchain-core==1.6.4</p>
<p>release(core): 1.6.5 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40816">#40816</a>)
fix(core): abbreviate long tool IDs in XML buffer strings (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40792">#40792</a>)</p>
<h2>langchain-core==1.6.4</h2>
<p>Changes since langchain-core==1.6.3</p>
<p>release(core): 1.6.4 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40718">#40718</a>)
chore(core): deprecate chat message history (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40711">#40711</a>)
chore(deps): bump anyio from 4.12.0 to 4.14.2 in /libs/core (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40634">#40634</a>)
chore(deps): bump soupsieve from 2.8.4 to 2.9 in /libs/core (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40574">#40574</a>)</p>
<h2>langchain-core==1.6.3</h2>
<p>Changes since langchain-core==1.6.2</p>
<p>release(core): 1.6.3 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40407">#40407</a>)
feat(core): Allow model name and provider tracing metadata override
based on gateway response (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40406">#40406</a>)
test(core): cover the deprecated <code>.text()</code> access path (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40243">#40243</a>)
docs(core): remove stale Args/Raises entries from
FileCallbackHandler._write and ChatGeneration.set_text (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40211">#40211</a>)</p>
<h2>langchain-core==1.6.2</h2>
<p>Changes since langchain-core==1.6.1</p>
<p>release(core): 1.6.2 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40209">#40209</a>)
feat(openai): support async tools (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40208">#40208</a>)
chore(deps): bump mistune from 3.3.0 to 3.3.3 in /libs/core (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40150">#40150</a>)
chore(deps): bump tornado from 6.5.7 to 6.5.8 in /libs/core (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40113">#40113</a>)
fix(core): avoid mutation in google-genai standard content (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40023">#40023</a>)
fix(core): avoid mutation in bedrock converse standard content (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40022">#40022</a>)</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/langchain-ai/langchain/commit/c5ab14d42a3e22865c9def909de0b11d70b0bbf0"><code>c5ab14d</code></a>
release(core): 1.6.5 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40816">#40816</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/5704d9d4813f8c0527f04e2662cf313e1350f96f"><code>5704d9d</code></a>
chore(model-profiles): refresh model profile data (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40804">#40804</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/7622d3dce760ac4be6d9aef4c653277e06064aea"><code>7622d3d</code></a>
release(openai): 1.6.6 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40800">#40800</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/2dd956b8add667dac4f97605ae441d75b8ae228e"><code>2dd956b</code></a>
docs(infra): fix AGENTS.md root setup guidance and package doc accuracy
(<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40794">#40794</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/49f4b4016b82513c3dc1623bf3daa10453861621"><code>49f4b40</code></a>
fix(openai): raise on error events in stream path (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40791">#40791</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/19cadaa1a1e0cac71f3148e2f18b414dcab17426"><code>19cadaa</code></a>
fix(core): abbreviate long tool IDs in XML buffer strings (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40792">#40792</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/798441e8b07e88e79db355db452cd9492f9628f2"><code>798441e</code></a>
chore(anthropic): fix integration test cassette (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40790">#40790</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/a476942bac3fe5e521676d0f53fabafcb7ba71b1"><code>a476942</code></a>
release(openai): 1.6.5 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40787">#40787</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/46c6bdf1b4e23028a5acc060d8b2797dbf200291"><code>46c6bdf</code></a>
release(anthropic): 1.7.4 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40786">#40786</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/290dabaff27ee379920d55d155d5055d2fe29cc8"><code>290daba</code></a>
fix(anthropic): add Opus 5.5 and GPT-6 profile augmentations (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/40785">#40785</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/langchain-ai/langchain/compare/langchain-core==1.6.1...langchain-core==1.6.5">compare
view</a></li>
</ul>
</details>
<br />

Updates `pytest-mock` from 3.15.1 to 3.16.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/pytest-dev/pytest-mock/releases">pytest-mock's
releases</a>.</em></p>
<blockquote>
<h2>v3.16.0</h2>
<p><em>2026-09-27</em></p>
<ul>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/pull/604">#604</a>:
Fixed <code>duplicate_iterators=True</code> for async functions spied
with <code>mocker.spy</code>.</li>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/pull/611">#611</a>:
Fixed async mock assertion introspection to use awaited arguments
instead of the latest call's arguments.</li>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/pull/606">#606</a>:
<code>mocker.resetall(return_value=True, side_effect=True)</code> now
also applies to non-callable mocks, such as those returned by
<code>mocker.create_autospec(SomeClass, instance=True)</code>.
Previously both arguments were silently ignored for them.</li>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/547">#547</a>:
Added <code>SpyType</code> for annotating <code>mocker.spy</code>
results.</li>
<li>Dropped support for EOL Python 3.9.</li>
<li><a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/147">#147</a>:
Removed handling of <code>RuntimeError: stop called on unstarted
patcher</code>, which can no longer occur in the supported Python
versions.</li>
<li>Added support for Python 3.15.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/pytest-dev/pytest-mock/blob/main/CHANGELOG.rst">pytest-mock's
changelog</a>.</em></p>
<blockquote>
<h2>3.16.0</h2>
<p><em>2026-09-27</em></p>
<ul>
<li><code>[#604](https://github.com/pytest-dev/pytest-mock/issues/604)
&lt;https://github.com/pytest-dev/pytest-mock/pull/604&gt;</code>_:
Fixed <code>duplicate_iterators=True</code> for async functions spied
with <code>mocker.spy</code>.</li>
<li><code>[#611](https://github.com/pytest-dev/pytest-mock/issues/611)
&lt;https://github.com/pytest-dev/pytest-mock/pull/611&gt;</code>_:
Fixed async mock assertion introspection to use awaited arguments
instead of the latest call's arguments.</li>
<li><code>[#606](https://github.com/pytest-dev/pytest-mock/issues/606)
&lt;https://github.com/pytest-dev/pytest-mock/pull/606&gt;</code>_:
<code>mocker.resetall(return_value=True, side_effect=True)</code> now
also applies to non-callable mocks, such as those returned by
<code>mocker.create_autospec(SomeClass, instance=True)</code>.
Previously both arguments were silently ignored for them.</li>
<li><code>[#547](https://github.com/pytest-dev/pytest-mock/issues/547)
&lt;https://github.com/pytest-dev/pytest-mock/issues/547&gt;</code>_:
Added <code>SpyType</code> for annotating <code>mocker.spy</code>
results.</li>
<li>Dropped support for EOL Python 3.9.</li>
<li><code>[#147](https://github.com/pytest-dev/pytest-mock/issues/147)
&lt;https://github.com/pytest-dev/pytest-mock/issues/147&gt;</code>_:
Removed handling of <code>RuntimeError: stop called on unstarted
patcher</code>, which can no longer occur in the supported Python
versions.</li>
<li>Added support for Python 3.15.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/f3b531f93c6d9837edc87ea1a6f4324dc9a2cdf3"><code>f3b531f</code></a>
Release 3.16.0</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/71ed67309520be160f3e100368705b58758d237a"><code>71ed673</code></a>
Fix duplicate_iterators for async spies (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/604">#604</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/0797e3d303cc5bbe0a3514b0625f7aeb3fa350b0"><code>0797e3d</code></a>
Fix async assertion argument introspection (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/611">#611</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/e24c334d573cfbf6989a31f4e3346676d9d31598"><code>e24c334</code></a>
docs: import os in the opening usage example (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/612">#612</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/9e7eb7b59cde362c1c8ace2d18ca00fe2d7a1cd1"><code>9e7eb7b</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/613">#613</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/445fd4d3daa8ed4c6d5428a77880da2e03d2f721"><code>445fd4d</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/610">#610</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/a8bd0b147afdf6b4bb1a1a3c3c088f32b0240091"><code>a8bd0b1</code></a>
Honour resetall() arguments for non-callable mocks (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/606">#606</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/6559fdfd5b67f096423e604a3a5a7045db2486a0"><code>6559fdf</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/608">#608</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/466d026254c949a8fbba8626b894308827be81cf"><code>466d026</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/605">#605</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-mock/commit/164defebde25bc31d53a2a64943c5c9aac43b57e"><code>164defe</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/pytest-dev/pytest-mock/issues/603">#603</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/pytest-dev/pytest-mock/compare/v3.15.1...v3.16.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `syrupy` from 6.0.0 to 6.1.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/syrupy-project/syrupy/releases">syrupy's
releases</a>.</em></p>
<blockquote>
<h2>v6.1.1</h2>
<blockquote>
<p><strong>Note:</strong> 6.1.0 was skipped due to a CI issue. Use
<strong>6.1.1</strong>.</p>
</blockquote>
<h3>Experimental <code>--snapshot-file-lock</code> for pytest-xdist</h3>
<p><code>--snapshot-update</code> under pytest-xdist can race when
multiple workers rewrite the same multi-entry amber (<code>.ambr</code>)
file, silently dropping snapshots (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1237">#1237</a>).</p>
<p>This release adds an <strong>experimental</strong> opt-in:</p>
<ul>
<li><code>--snapshot-file-lock</code> — exclusive file lock + atomic
replace around amber writes</li>
<li><code>--snapshot-file-lock-timeout</code> — max wait for the lock
(default <strong>60s</strong>)</li>
</ul>
<p>Same-machine workers only; not reliable across remote workers / NFS.
See <a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1239">#1239</a>.</p>
<blockquote>
<p><strong>Callout for pytest-xdist users:</strong> please try
<code>--snapshot-file-lock</code> with <code>--snapshot-update</code>
and <a href="https://github.com/syrupy-project/syrupy/issues">open an
issue</a> if you hit problems. Locking is expected to become the default
in a future minor release.</p>
</blockquote>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/shipbyaeron"><code>@​shipbyaeron</code></a>
made their first contribution in <a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1236">syrupy-project/syrupy#1236</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/syrupy-project/syrupy/compare/v6.0.0...v6.1.1">https://github.com/syrupy-project/syrupy/compare/v6.0.0...v6.1.1</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/syrupy-project/syrupy/blob/main/CHANGELOG.md">syrupy's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/syrupy-project/syrupy/releases/tag/v6.1.1">v6.1.1</a>
(2026-09-13)</h2>
<h2>What's Changed</h2>
<ul>
<li>chore(deps): update dependency ruff to v0.16.4 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1225">syrupy-project/syrupy#1225</a></li>
<li>chore(deps): update dependency pytest-benchmark to v5.3.0 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1226">syrupy-project/syrupy#1226</a></li>
<li>chore(deps): update dependency ruff to v0.16.5 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1227">syrupy-project/syrupy#1227</a></li>
<li>chore(deps): update dependency pydantic to v2.13.5 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1228">syrupy-project/syrupy#1228</a></li>
<li>chore(deps): update dependency coverage to v7.16.0 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1229">syrupy-project/syrupy#1229</a></li>
<li>chore(deps): update dependency hypothesis to v6.166.0 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1230">syrupy-project/syrupy#1230</a></li>
<li>chore(deps): update dependency hypothesis to v6.167.0 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1231">syrupy-project/syrupy#1231</a></li>
<li>chore(deps): update dependency hypothesis to v6.167.1 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1232">syrupy-project/syrupy#1232</a></li>
<li>chore(deps): update actions/deploy-pages action to v5.0.1 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1234">syrupy-project/syrupy#1234</a></li>
<li>chore(deps): update dependency ruff to v0.16.6 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1235">syrupy-project/syrupy#1235</a></li>
<li>test: add coverage for read_snapshot_data_from_location returning
None by <a
href="https://github.com/shipbyaeron"><code>@​shipbyaeron</code></a> in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1236">syrupy-project/syrupy#1236</a></li>
<li>chore(deps): update dependency hypothesis to v6.168.0 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1238">syrupy-project/syrupy#1238</a></li>
<li>fix: opt-in file lock for concurrent amber writes under xdist by <a
href="https://github.com/noahnu"><code>@​noahnu</code></a> in <a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1239">syrupy-project/syrupy#1239</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/shipbyaeron"><code>@​shipbyaeron</code></a>
made their first contribution in <a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1236">syrupy-project/syrupy#1236</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/syrupy-project/syrupy/compare/v6.0.0...v6.1.1">https://github.com/syrupy-project/syrupy/compare/v6.0.0...v6.1.1</a></p>
<h2><a
href="https://github.com/syrupy-project/syrupy/releases/tag/v6.1.0">v6.1.0</a>
(2026-09-13)</h2>
<h2>What's Changed</h2>
<ul>
<li>chore(deps): update dependency ruff to v0.16.4 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1225">syrupy-project/syrupy#1225</a></li>
<li>chore(deps): update dependency pytest-benchmark to v5.3.0 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1226">syrupy-project/syrupy#1226</a></li>
<li>chore(deps): update dependency ruff to v0.16.5 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1227">syrupy-project/syrupy#1227</a></li>
<li>chore(deps): update dependency pydantic to v2.13.5 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1228">syrupy-project/syrupy#1228</a></li>
<li>chore(deps): update dependency coverage to v7.16.0 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1229">syrupy-project/syrupy#1229</a></li>
<li>chore(deps): update dependency hypothesis to v6.166.0 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1230">syrupy-project/syrupy#1230</a></li>
<li>chore(deps): update dependency hypothesis to v6.167.0 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1231">syrupy-project/syrupy#1231</a></li>
<li>chore(deps): update dependency hypothesis to v6.167.1 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1232">syrupy-project/syrupy#1232</a></li>
<li>chore(deps): update actions/deploy-pages action to v5.0.1 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1234">syrupy-project/syrupy#1234</a></li>
<li>chore(deps): update dependency ruff to v0.16.6 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1235">syrupy-project/syrupy#1235</a></li>
<li>test: add coverage for read_snapshot_data_from_location returning
None by <a
href="https://github.com/shipbyaeron"><code>@​shipbyaeron</code></a> in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1236">syrupy-project/syrupy#1236</a></li>
<li>chore(deps): update dependency hypothesis to v6.168.0 by <a
href="https://github.com/renovate"><code>@​renovate</code></a>[bot] in
<a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1238">syrupy-project/syrupy#1238</a></li>
<li>fix: opt-in file lock for concurrent amber writes under xdist by <a
href="https://github.com/noahnu"><code>@​noahnu</code></a> in <a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1239">syrupy-project/syrupy#1239</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/shipbyaeron"><code>@​shipbyaeron</code></a>
made their first contribution in <a
href="https://redirect.github.com/syrupy-project/syrupy/pull/1236">syrupy-project/syrupy#1236</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/syrupy-project/syrupy/compare/v6.0.0...v6.1.0">https://github.com/syrupy-project/syrupy/compare/v6.0.0...v6.1.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/2d251e73f1ebe47fe83ed71d835d3ae8580e8313"><code>2d251e7</code></a>
chore(release): 6.1.1 [skip ci]</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/9b64ec05752586c45d1097e9d25f9ee1d4e93219"><code>9b64ec0</code></a>
chore(release): 6.1.0 [skip ci]</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/5b4256eac8720075f25b0fa8491f75948001b983"><code>5b4256e</code></a>
fix: opt-in file lock for concurrent amber writes under xdist (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1239">#1239</a>)</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/d4cb1513b5d2b1b18c3b407150db22d2d8604ddd"><code>d4cb151</code></a>
chore(deps): update dependency hypothesis to v6.168.0 (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1238">#1238</a>)</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/16c4cb5b8785d89e49b8076a99f58d810e02fcce"><code>16c4cb5</code></a>
test: add coverage for read_snapshot_data_from_location returning None
(<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1236">#1236</a>)</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/2e1d3ba0d39a1d87735213a32de9dd9cdb929690"><code>2e1d3ba</code></a>
chore(deps): update dependency ruff to v0.16.6 (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1235">#1235</a>)</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/fcc929d4deb2302f2d37e6511015ef43a0841bc2"><code>fcc929d</code></a>
chore(deps): update actions/deploy-pages action to v5.0.1 (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1234">#1234</a>)</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/4f1bad75777ecc9d916a648dd3669b2844d08f7d"><code>4f1bad7</code></a>
chore(deps): update dependency hypothesis to v6.167.1 (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1232">#1232</a>)</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/24eda28579f5761cbc64713ffcee41cc73602010"><code>24eda28</code></a>
chore(deps): update dependency hypothesis to v6.167.0 (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1231">#1231</a>)</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/0d7e46f9431e07810da4ef90dbe861b85fbc8469"><code>0d7e46f</code></a>
chore(deps): update dependency hypothesis to v6.166.0 (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1230">#1230</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/syrupy-project/syrupy/compare/v6.0.0...v6.1.1">compare
view</a></li>
</ul>
</details>
<br />

Updates `psycopg-binary` from 3.3.4 to 3.3.6
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/psycopg/psycopg/blob/master/docs/news.rst">psycopg-binary's
changelog</a>.</em></p>
<blockquote>
<p>.. currentmodule:: psycopg</p>
<p>.. index::
single: Release notes
single: News</p>
<h1><code>psycopg</code> release notes</h1>
<h2>Future releases</h2>
<p>Psycopg 3.3.7 (unreleased)
^^^^^^^^^^^^^^^^^^^^^^^^^^</p>
<ul>
<li>Fix segfault fetching arrays of strings or timestamps after closing
the
connection
(🎫<code>[#1428](https://github.com/psycopg/psycopg/issues/1428)</code>).</li>
</ul>
<h2>Current release</h2>
<p>Psycopg 3.3.6
^^^^^^^^^^^^^</p>
<ul>
<li>Add support for Python 3.15
(🎫<code>[#1245](https://github.com/psycopg/psycopg/issues/1245)</code>).</li>
<li>Improve performance of async queries by reducing the overhead of the
<code>!wait_async()</code> function
(🎫<code>[#1331](https://github.com/psycopg/psycopg/issues/1331)</code>).</li>
<li>Don't wait forever for a query to terminate after interrupting it,
for
instance if the server is unresponsive. The fix requires libpq 17 or
newer

(🎫<code>[#1371](https://github.com/psycopg/psycopg/issues/1371)</code>).</li>
<li>Cancel a running query upon receiving <code>!SystemExit</code>
(🎫<code>[#1384](https://github.com/psycopg/psycopg/issues/1384)</code>).</li>
<li>Report <code>!None</code> instead of <code>65535</code> as the
<code>Column.precision</code> of an
:sql:<code>interval</code> column declared with a fields restriction and
no explicit
precision, such as e.g. :sql:<code>interval day to second</code>
(🎫<code>[#1397](https://github.com/psycopg/psycopg/issues/1397)</code>).</li>
<li>Fix dumping of nested subclasses of lists as arrays
(🎫<code>[#1398](https://github.com/psycopg/psycopg/issues/1398)</code>).</li>
<li>Discard prepared statements upon :sql:<code>DEALLOCATE ALL</code>
(🎫<code>[#1408](https://github.com/psycopg/psycopg/issues/1408)</code>).</li>
<li>Better guards dumping large Python <code>!int</code> to binary
numeric
(🎫<code>[#1414](https://github.com/psycopg/psycopg/issues/1414)</code>).</li>
</ul>
<p>Psycopg 3.3.5
^^^^^^^^^^^^^</p>
<ul>
<li>Discard prepared statements upon :sql:<code>ALTER *</code> or
<code>DISCARD *</code>

(🎫<code>[#1307](https://github.com/psycopg/psycopg/issues/1307)</code>).</li>
<li>Fix <code>!ProgrammingError</code> when dumping
non-<code>!None</code> values with
no <code>!NoneType</code> dumper registered in python implementation
(🎫<code>[#1325](https://github.com/psycopg/psycopg/issues/1325)</code>).</li>
<li>Fix <code>!wait_selector</code> wait function to not raise
<code>!KeyError</code>

(🎫<code>[#1327](https://github.com/psycopg/psycopg/issues/1327)</code>).</li>
<li>Fix <code>!DataError</code> messages leaking the literal
<code>{...}</code> placeholder instead</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/psycopg/psycopg/commit/a67654d1e7afbf9b3a619557838f62de1c790e7c"><code>a67654d</code></a>
chore: bump psycopg package version to 3.3.6</li>
<li><a
href="https://github.com/psycopg/psycopg/commit/443814b3b111ac678a39fd523c1a826266fb69b5"><code>443814b</code></a>
Merge pull request <a
href="https://redirect.github.com/psycopg/psycopg/issues/1416">#1416</a>
from dvarrazzo/wait-async-perf</li>
<li><a
href="https://github.com/psycopg/psycopg/commit/42966e9ebbda3b9c69b15c5588543c15f2aae5dd"><code>42966e9</code></a>
test: add helpful comments to some tests</li>
<li><a
href="https://github.com/psycopg/psycopg/commit/5e8797f0c8003d8cd12a1e5c13f05fbb94c1c1d2"><code>5e8797f</code></a>
test: add reasonable connect_timeout to most tests</li>
<li><a
href="https://github.com/psycopg/psycopg/commit/c81ba62442dfbd69e207d6914e6ae2aa27e56886"><code>c81ba62</code></a>
perf: reduce the overhead of wait_async()</li>
<li><a
href="https://github.com/psycopg/psycopg/commit/d2bbfe4e2b1e36a20e72a18097f35a3db27296e3"><code>d2bbfe4</code></a>
refactor: use get_running_loop() in the async wait functions</li>
<li><a
href="https://github.com/psycopg/psycopg/commit/2b1484a550e01c88fda077099678f0abb9217ecb"><code>2b1484a</code></a>
test: add a script to measure the async wait functions</li>
<li><a
href="https://github.com/psycopg/psycopg/commit/573cf4aa70d8fdefc9d5f3eb69d5419cd6d3cd51"><code>573cf4a</code></a>
test: fix incorrect wait timing test</li>
<li><a
href="https://github.com/psycopg/psycopg/commit/2b68990874175b8d97269218d4963b2d5c8656f3"><code>2b68990</code></a>
refactor: drop leftovers of waiting with inf interval in
wait_conn_async</li>
<li><a
href="https://github.com/psycopg/psycopg/commit/60765dd8fc7d8df03cd75efcff485bfb3c83a0ed"><code>60765dd</code></a>
Merge pull request <a
href="https://redirect.github.com/psycopg/psycopg/issues/1414">#1414</a>
from dvarrazzo/fix-decimal-overflow</li>
<li>Additional commits viewable in <a
href="https://github.com/psycopg/psycopg/compare/3.3.4...3.3.6">compare
view</a></li>
</ul>
</details>
<br />

Updates `ruff` from 0.16.5 to 0.16.9
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ruff/releases">ruff's
releases</a>.</em></p>
<blockquote>
<h2>0.16.9</h2>
<h2>Release Notes</h2>
<p>Released on 2026-09-24.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>ruff</code>] Avoid false positives for overloaded division
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28309">#28309</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>[<code>flake8-bugbear</code>] Avoid false positives for calls with
keyword arguments (<code>B009</code>, <code>B010</code>,
<code>B043</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28776">#28776</a>)</li>
<li>[<code>flake8-tidy-imports</code>] Allow lazy imports to be used in
deferred annotations (<code>TID255</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28767">#28767</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Update LibCST-based fixes for Python 3.15 (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28616">#28616</a>)</li>
<li>[<code>flake8-pyi</code>] Mention stubs in the diagnostic message
(<code>PYI002</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28542">#28542</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Fix horizontal overflow on the rules documentation page (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28699">#28699</a>)</li>
<li>Update rules table with category information (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28651">#28651</a>)</li>
<li>[<code>flake8-annotations</code>] Clarify that <code>ANN401</code>
checks return types in addition to arguments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28334">#28334</a>)</li>
<li>[<code>flake8-bugbear</code>] Document type-checker interaction
(<code>B010</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28509">#28509</a>)</li>
<li>[<code>flake8-comprehensions</code>] Document
<code>map</code>/generator exception behavior (<code>C417</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27794">#27794</a>)</li>
<li>[<code>ruff</code>] Mention related isort settings
(<code>RUF022</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28719">#28719</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/qinpei-dev"><code>@​qinpei-dev</code></a></li>
<li><a
href="https://github.com/sanjayrohith"><code>@​sanjayrohith</code></a></li>
<li><a href="https://github.com/ntBre"><code>@​ntBre</code></a></li>
<li><a
href="https://github.com/webdevsamran"><code>@​webdevsamran</code></a></li>
<li><a
href="https://github.com/zaniebot"><code>@​zaniebot</code></a></li>
<li><a
href="https://github.com/ewdurbin"><code>@​ewdurbin</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
<li><a
href="https://github.com/spaceone"><code>@​spaceone</code></a></li>
<li><a
href="https://github.com/IbrahimKhan12"><code>@​IbrahimKhan12</code></a></li>
<li><a
href="https://github.com/devtechedge"><code>@​devtechedge</code></a></li>
<li><a
href="https://github.com/GruffElixir"><code>@​GruffElixir</code></a></li>
</ul>
<h2>Install ruff 0.16.9</h2>
<h3>Install prebuilt binaries via shell script</h3>
<pre lang="sh"><code>curl --proto '=https' --tlsv1.2 -LsSf
https://releases.astral.sh/github/ruff/releases/download/0.16.9/ruff-installer.sh
| sh
</code></pre>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md">ruff's
changelog</a>.</em></p>
<blockquote>
<h2>0.16.9</h2>
<p>Released on 2026-09-24.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>ruff</code>] Avoid false positives for overloaded division
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28309">#28309</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>[<code>flake8-bugbear</code>] Avoid false positives for calls with
keyword arguments (<code>B009</code>, <code>B010</code>,
<code>B043</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28776">#28776</a>)</li>
<li>[<code>flake8-tidy-imports</code>] Allow lazy imports to be used in
deferred annotations (<code>TID255</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28767">#28767</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Update LibCST-based fixes for Python 3.15 (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28616">#28616</a>)</li>
<li>[<code>flake8-pyi</code>] Mention stubs in the diagnostic message
(<code>PYI002</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28542">#28542</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Fix horizontal overflow on the rules documentation page (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28699">#28699</a>)</li>
<li>Update rules table with category information (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28651">#28651</a>)</li>
<li>[<code>flake8-annotations</code>] Clarify that <code>ANN401</code>
checks return types in addition to arguments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28334">#28334</a>)</li>
<li>[<code>flake8-bugbear</code>] Document type-checker interaction
(<code>B010</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28509">#28509</a>)</li>
<li>[<code>flake8-comprehensions</code>] Document
<code>map</code>/generator exception behavior (<code>C417</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27794">#27794</a>)</li>
<li>[<code>ruff</code>] Mention related isort settings
(<code>RUF022</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28719">#28719</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/qinpei-dev"><code>@​qinpei-dev</code></a></li>
<li><a
href="https://github.com/sanjayrohith"><code>@​sanjayrohith</code></a></li>
<li><a href="https://github.com/ntBre"><code>@​ntBre</code></a></li>
<li><a
href="https://github.com/webdevsamran"><code>@​webdevsamran</code></a></li>
<li><a
href="https://github.com/zaniebot"><code>@​zaniebot</code></a></li>
<li><a
href="https://github.com/ewdurbin"><code>@​ewdurbin</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
<li><a
href="https://github.com/spaceone"><code>@​spaceone</code></a></li>
<li><a
href="https://github.com/IbrahimKhan12"><code>@​IbrahimKhan12</code></a></li>
<li><a
href="https://github.com/devtechedge"><code>@​devtechedge</code></a></li>
<li><a
href="https://github.com/GruffElixir"><code>@​GruffElixir</code></a></li>
</ul>
<h2>0.16.8</h2>
<p>Released on 2026-09-16.</p>
<h3>Bug fixes</h3>
<ul>
<li>Visit functional <code>TypedDict</code> keyword arguments correctly
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28584">#28584</a>)</li>
<li>[<code>flake8-simplify</code>] Detect nested <code>async with</code>
under sync parent (<code>SIM117</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27821">#27821</a>)</li>
<li>[<code>flake8-simplify</code>] Preserve operand order in
<code>SIM109</code> fix (<a
href="https://redirect.github.com/astral-sh/ruff/pull/27824">#27824</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/ruff/commit/0be08a206f9c3180afd3e93bcc792ed5cb1f4db1"><code>0be08a2</code></a>
Bump version to 0.16.9 (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28882">#28882</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/b4920b72b354e7c715ab861ae23458874683bb02"><code>b4920b7</code></a>
Rename <code>ruff_cli</code> to <code>ruff_command_line</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28881">#28881</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/47c751b95908a4d1f95f9ef8723036aae9da0b18"><code>47c751b</code></a>
Update dependency astral-sh/uv to v0.12.18 (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28880">#28880</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/8c244e56a1aeac31c26d2371ef26588e0632235c"><code>8c244e5</code></a>
[<code>flake8-comprehensions</code>] Document <code>map</code>/generator
exception behavior (<code>C417</code>...</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/5edf5a1d0a84663079e46983216059f06acea87d"><code>5edf5a1</code></a>
Use <code>target</code> form in <code>rooster.version_files</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28876">#28876</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/915bb2b4bf9ae7eee47cf55646bbfebae254a23b"><code>915bb2b</code></a>
[ty] Prefer existing @ paths over response files in Ruff and ty (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28877">#28877</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/4710e1aa962b13720cf64aa84eb279c5333896d7"><code>4710e1a</code></a>
ci(github): update version number in placeholder of issue template (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28871">#28871</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/eedfc62a75bf1ba86d48959b00eea75ae87eadca"><code>eedfc62</code></a>
[ty] Propagate outer type context through cast calls (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28855">#28855</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/ceaa6a00830e1e350b8a23977a1a10ac467920a1"><code>ceaa6a0</code></a>
[ty] Contain rendered code within Markdown fences (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28869">#28869</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/dba0f30615424b94f94a174bba6ce6cce4bf11ff"><code>dba0f30</code></a>
authorize ruff-pre-commit dispatch via OIDC (<a
href="https://redirect.github.com/astral-sh/ruff/issues/28867">#28867</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/ruff/compare/0.16.5...0.16.9">compare
view</a></li>
</ul>
</details>
<br />

Updates `ty` from 0.0.75 to 0.0.84
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ty/releases">ty's
releases</a>.</em></p>
<blockquote>
<h2>0.0.84</h2>
<h2>Release Notes</h2>
<p>Released on 2026-09-24.</p>
<p>This release addresses <a
href="https://github.com/astral-sh/ty/security/advisories/GHSA-vxvm-j4xq-q7m4">GHSA-vxvm-j4xq-q7m4</a>,
a use-after-free vulnerability during incremental type checking that can
result in arbitrary code execution when analyzing a specially crafted
Python project. Users who run ty on untrusted code should upgrade to
0.0.84 or newer.</p>
<h3>Bug fixes</h3>
<ul>
<li>Fix stale diagnostics from the LSP server after toggling
<code>showSyntaxErrors</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28759">#28759</a>)</li>
</ul>
<h3>LSP server</h3>
<ul>
<li>Complete string keys from dictionary initializers (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28820">#28820</a>)</li>
<li>Support LSP requests against closed documents (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28595">#28595</a>)</li>
<li>Select projects for external files using import search paths (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28594">#28594</a>)</li>
<li>Use workspace editor settings for external files (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28639">#28639</a>)</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Avoid repeated subtyping checks for materialized recursive protocols
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28774">#28774</a>)</li>
<li>Skip reading notebooks when discovering scripts (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28781">#28781</a>)</li>
</ul>
<h3>Core type checking</h3>
<ul>
<li>Avoid incorrect simplification of <code>TypeIs</code>
materializations (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28817">#28817</a>)</li>
<li>Fix disjointness of generic class types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28787">#28787</a>)</li>
<li>Fix staticmethod shadowing through generic receivers and unions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28766">#28766</a>)</li>
<li>Infer callable signatures from bounded type variables (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28599">#28599</a>)</li>
<li>Infer constant membership in inline list and set literals (e.g.
<code>&quot;foo&quot; in [&quot;foo&quot;]</code> is now inferred as
<code>Literal[True]</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28676">#28676</a>)</li>
<li>Infer through optional generic containers in the legacy solver (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28791">#28791</a>)</li>
<li>Preserve call narrowing during cyclic inference (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28708">#28708</a>)</li>
<li>Preserve intersections of type guard return types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28796">#28796</a>)</li>
<li>Use subtyping for constraint-set implication (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28657">#28657</a>)</li>
</ul>
<h3>Configuration</h3>
<ul>
<li>Disable <code>invalid-legacy-positional-parameter</code> by default
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28834">#28834</a>)</li>
</ul>
<h3>Other changes</h3>
<ul>
<li>Only consider reachable definitions when determining whether a
condition should be exempted from
<code>redundant-condition(-strict)</code> due to the condition being
defined relative to <code>sys.version_info</code>,
<code>sys.platform</code>, <code>os.name</code> or
<code>typing.TYPE_CHECKING</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28788">#28788</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/ibraheemdev"><code>@​ibraheemdev</code></a></li>
<li><a href="https://github.com/zsol"><code>@​zsol</code></a></li>
<li><a
href="https://github.com/charliermarsh"><code>@​charliermarsh</code></a></li>
<li><a
href="https://github.com/lerebear"><code>@​lerebear</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ty/blob/main/CHANGELOG.md">ty's
changelog</a>.</em></p>
<blockquote>
<h2>0.0.84</h2>
<p>Released on 2026-09-24.</p>
<p>This release addresses <a
href="https://github.com/astral-sh/ty/security/advisories/GHSA-vxvm-j4xq-q7m4">GHSA-vxvm-j4xq-q7m4</a>,
a use-after-free vulnerability during incremental type checking that can
result in arbitrary code execution when analyzing a specially crafted
Python project. Users who run ty on untrusted code should upgrade to
0.0.84 or newer.</p>
<h3>Bug fixes</h3>
<ul>
<li>Fix stale diagnostics from the LSP server after toggling
<code>showSyntaxErrors</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28759">#28759</a>)</li>
</ul>
<h3>LSP server</h3>
<ul>
<li>Complete string keys from dictionary initializers (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28820">#28820</a>)</li>
<li>Support LSP requests against closed documents (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28595">#28595</a>)</li>
<li>Select projects for external files using import search paths (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28594">#28594</a>)</li>
<li>Use workspace editor settings for external files (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28639">#28639</a>)</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Avoid repeated subtyping checks for materialized recursive protocols
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28774">#28774</a>)</li>
<li>Skip reading notebooks when discovering scripts (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28781">#28781</a>)</li>
</ul>
<h3>Core type checking</h3>
<ul>
<li>Avoid incorrect simplification of <code>TypeIs</code>
materializations (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28817">#28817</a>)</li>
<li>Fix disjointness of generic class types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28787">#28787</a>)</li>
<li>Fix staticmethod shadowing through generic receivers and unions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28766">#28766</a>)</li>
<li>Infer callable signatures from bounded type variables (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28599">#28599</a>)</li>
<li>Infer constant membership in inline list and set literals (e.g.
<code>&quot;foo&quot; in [&quot;foo&quot;]</code> is now inferred as
<code>Literal[True]</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28676">#28676</a>)</li>
<li>Infer through optional generic containers in the legacy solver (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28791">#28791</a>)</li>
<li>Preserve call narrowing during cyclic inference (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28708">#28708</a>)</li>
<li>Preserve intersections of type guard return types (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28796">#28796</a>)</li>
<li>Use subtyping for constraint-set implication (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28657">#28657</a>)</li>
</ul>
<h3>Configuration</h3>
<ul>
<li>Disable <code>invalid-legacy-positional-parameter</code> by default
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/28834">#28834</a>)</li>
</ul>
<h3>Other changes</h3>
<ul>
<li>Only consider reachable definitions when determining whether a
condition should be exempted from
<code>redundant-condition(-strict)</code> due to the condition being
defined relative to <code>sys.version_info</code>,
<code>sys.platform</code>, <code>os.name</code> or
<code>typing.TYPE_CHECKING</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/28788">#28788</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a
href="https://github.com/ibraheemdev"><code>@​ibraheemdev</code></a></li>
<li><a href="https://github.com/zsol"><code>@​zsol</code></a></li>
<li><a
href="https://github.com/charliermarsh"><code>@​charliermarsh</code></a></li>
<li><a
href="https://github.com/lerebear"><code>@​lerebear</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
<li><a
href="https://github.com/ewdurbin"><code>@​ewdurbin</code></a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/ty/commit/8dd9a7f7fa35a18275d82117e6593ba45507065f"><code>8dd9a7f</code></a>
Bump version to 0.0.84 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4585">#4585</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/d4e4bf90906c7677049bc3a29d1735de7d22052d"><code>d4e4bf9</code></a>
publish to astral-sh/versions via OIDC (<a
href="https://redirect.github.com/astral-sh/ty/issues/4581">#4581</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/94ce7333abb356b2068dc98d37a68c993da6d09b"><code>94ce733</code></a>
use oidc issued token for docs publication (<a
href="https://redirect.github.com/astral-sh/ty/issues/4579">#4579</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/901eeaa9cd9ac06f34e85e4f721f76a0dc36e217"><code>901eeaa</code></a>
Update prek dependencies (<a
href="https://redirect.github.com/astral-sh/ty/issues/4576">#4576</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/09bf0b1b2114a628f3e2296d3d9d28245066c98b"><code>09bf0b1</code></a>
Update docker/setup-buildx-action action to v4.3.0 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4575">#4575</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/89d6ffe529dd44f64adc0d28f80744b7c7ab217f"><code>89d6ffe</code></a>
Update astral-sh/setup-uv action to v10.2.0 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4574">#4574</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/9c214798cfcc59069e986876564638fadf32d774"><code>9c21479</code></a>
Bump version to 0.0.83 (<a
href="https://redirect.github.com/astral-sh/ty/issues/4569">#4569</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/04c69110b391e96310e6892cbed9936c4f31d7aa"><code>04c6911</code></a>
Sync the ty security mirror (<a
href="https://redirect.github.com/astral-sh/ty/issues/4549">#4549</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/3fa57a25767c619dbeba697c2acfbb8eb291519a"><code>3fa57a2</code></a>
Grant the versions workflow repository read access (<a
href="https://redirect.github.com/astral-sh/ty/issues/4550">#4550</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/a15b35389b44db57f718fd4e19e093481747c53e"><code>a15b353</code></a>
use scoped token for release workflow (<a
href="https://redirect.github.com/astral-sh/ty/issues/4506">#4506</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/ty/compare/0.0.75...0.0.84">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: John Kennedy <jkennedyvz@users.noreply.github.com>
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
2026-10-17 16:17:52 +00:00
Elior Nataf LackritzandGitHub 41c9c22fdc release(langgraph): 1.2.16 (#9334)
Bumps langgraph from 1.2.15 to 1.2.16.

Includes:

- Keep a DeltaChannel's value when its field changes to a plain reducer
(#9302)
- Save a resumed exit run's pending writes once (#9314)
- Stop a subgraph from rerunning its finished tasks on resume (#9315)
- Apply a resumed `Command`'s update once (#9322)
- Let other tasks finish when a resume value is invalid (#9265)
1.2.16 sdk==0.4.8
2026-10-16 18:02:08 -04:00
Elior Nataf LackritzandGitHub 51018652a6 release(sdk-py): 0.4.8 (#9335)
Bumps the Python SDK version from 0.4.7 to 0.4.8. Thread streams now
report why they ended: a server's error frame becomes the error
`thread.output` raises, the sync client no longer blocks forever when
the server closes the stream, and a stream the server rejects with a 4xx
ends at once instead of being retried (#9317).
2026-10-16 18:01:53 -04:00
Elior Nataf LackritzandGitHub 9e6fc45c6f fix(sdk-py): surface thread stream errors and stop retrying a rejected stream (#9317)
## Summary

Thread streams in `langgraph_sdk` now report why they ended. An `id:
null` error frame becomes the error `thread.output` raises, the sync
client no longer blocks forever when the server closes the stream, and a
stream the server rejects with a 4xx ends at once instead of being
retried.

## Problem

- A server sends `{"type": "error", "id": null, ...}` just before it
closes a thread stream whose read failed. The SDK dropped the frame, so
`thread.output` raised a generic "lifecycle stream ended before terminal
event" (async) or blocked forever (sync: the lifecycle watcher returned
without settling the run).
- A 403 or 404 on the stream request was retried like a network error,
then reported as `RuntimeError("Lifecycle transport failed: ...")` with
no status. A server that rejects a WebSocket after accepting it closes
with 4000 plus the HTTP status (4403, 4404, 4422), since a browser can't
read a refused upgrade's status. The shared stream counted each such
reconnect as a success and reconnected forever.

## Fix

- The lifecycle watcher fails the run with the frame's error on a clean
close (both clients). The shared stream logs the frame instead of
dropping it: projections still end when the stream closes, as before,
and `thread.output` carries the error.
- A 4xx other than 408 and 429, as a status or as a 4000+status close
code, ends the stream without retries. `thread.output` now raises that
`httpx.HTTPStatusError` or `websockets.exceptions.ConnectionClosedError`
instead of the generic `RuntimeError`.
- For a minted `thread_id`, the lifecycle watcher starts after
`run.start` creates the thread. Without this, the 4xx stop would turn a
stream opened under custom auth for a not-yet-created thread from
retried into failed. The sync client starts it under a lock, since
`run.start` can be called from several threads.
- Drops the first of two `SyncStreamController._reconnect_shared_stream`
definitions. It was shadowed by the second and never ran.

Not in this PR: over WebSocket the server closes with 1011 after an
error frame, which is still retried, while over SSE the close is clean
and fails the stream. Reconnecting after a clean close, as
`langchain-ai/langgraphjs#2812` does for the JS SDK, is a separate
change.

## Test plan

- [x] The 10 new behavior tests (async and sync: error frame, clean
close, 404, 4404 close, reconnect on 404, minted `thread_id`) fail on
`main` and pass here; a race test checks that two concurrent `run.start`
calls start one watcher.
- [x] `make test` in `libs/sdk-py`: 541 passed. `make lint` clean,
`check_sdk_methods.py` passes.
- [x] `RemoteGraph` v3 tests in `libs/langgraph`
(`test_remote_graph_v3.py`,
`test_stream_events_v3_kwarg_forwarding.py`): 94 passed against this
SDK.
- [x] Against a local server with custom auth: a thread the caller can't
read fails at once with 404 (SSE) or 4404 (WebSocket), and a new thread
works with a 1 s pause before `run.start`, which fails on `main`.
2026-10-16 15:29:34 -04:00
Baihao WangandGitHub b0cabd93d0 fix(langgraph): let other tasks finish when a resume value is invalid (#9265)
Found while testing per-call human-in-the-loop
(langchain-ai/langchain#41062). The code depends only on #9232, which is
already on `main`.

When one answer in a multi-answer resume fails `response_schema`
validation, the runner cancelled the other tasks in the step, so in
async runs a task cut off after its side effect kept its saved answer
and ran again on the next resume. Invalid resume values (already tagged
by `is_invalid_resume` from #9232) no longer stop the other tasks: the
error is raised once they finish, so their results are saved.

Hit by per-call human-in-the-loop: approving one tool call while giving
another an invalid edit, in one resume, sent the approved call's email
twice once the second answer was fixed.

## How to verify

- `test_invalid_resume_lets_other_answered_tasks_finish` fails on `main`
(the approved task is still pending after its side effect) and passes
with this change. Like the other async interrupt tests, it is skipped
before Python 3.11, where async nodes can't call `interrupt()`.
- The per-call HITL reproduction against this branch: the approved async
tool runs once (twice on `main` whenever it awaits after its side
effect).
- `make lint` passes. With `NO_DOCKER=true`, the full `libs/langgraph`
suite has the same failures as `main` locally (`test_prebuilt_tool_chat`
and `test_stream_mode_messages_command`, sync and async), and nothing
new.
2026-10-16 11:33:53 -07:00
raghavverma-langchainandGitHub 4ac46ba186 release(cli): 0.4.36 (#9330)
## Summary

<!-- Write the summary yourself -->

## Notes for reviewers
- Includes [push through the active Docker
context](https://github.com/langchain-ai/langgraph/pull/9321) and
[accept serverless and dedicated deployment
aliases](https://github.com/langchain-ai/langgraph/pull/9325), the two
CLI changes merged since 0.4.35.
- Merging doesn't publish by itself: after it merges, run the `release`
workflow with `working-directory: libs/cli`, as was done for 0.4.35.

## Test Plan
- [x] Only `__version__` in `libs/cli/langgraph_cli/__init__.py` changes
(0.4.35 → 0.4.36), like the 0.4.35 release PR
- [ ] After merge, the `release` workflow for `libs/cli` succeeds and
PyPI shows `langgraph-cli` 0.4.36
- [ ] `uvx --from langgraph-cli==0.4.36 langgraph deploy` pushes on
Docker Desktop without `DOCKER_HOST` set

## Demo

<!-- Drag a screen recording or screenshot here -->
cli==0.4.36
2026-10-16 12:29:42 -04:00
Elior Nataf LackritzandGitHub e14f4277dc fix(langgraph): apply a resumed Command's update once (#9322)
`Command(resume=..., update=...)` applied its update twice once the
resumed node called `interrupt()` again, with sync or async durability
(`invoke`'s default). A node that asks three times, resumed with
`Command(resume=str(i), update={"log": [f"u{i}"]})`, ends with `["u1",
"u1", "u2", "u3", "a:123"]`.

## Cause

The null task's writes are saved as one list, and savers key a regular
write by its position in that list. The Command's resume came first, so
its update was stored at index 1. The next Command saved the null task's
earlier writes again without the resume, which put the update at index
0, so it was stored twice and every later resume applied both copies.
`durability="exit"` saves after the resume is consumed, so it wasn't
affected.

## Fix

The null task's special writes (a resume) now go after its regular ones,
so each regular write keeps its index as the list grows.

`test_resume_with_update_applies_the_update_once` fails on `main` for
sync and async durability.

Found by @hntrl, and flagged by @soarez on #9314.
2026-10-16 12:07:59 -04:00
hari-dhanushkodiandGitHub 4e2dfe4a24 fix(cli): accept serverless and dedicated deployment aliases (#9325) 2026-10-16 08:02:43 -04:00
raghavverma-langchainandGitHub e77a5cb08c fix(cli): push through the active Docker context in langgraph deploy (#9321)
## Summary

<!-- Write the summary yourself -->

## Notes for reviewers
- Known gap: `--host` carries only the context's endpoint, not its TLS
settings, so a remote context that uses client certificates still can't
push. That case was broken before this change too, and it's rare for
local builds.
- A context with no Docker endpoint (Docker prints `<no value>`) or a
missing `docker` binary falls back to today's behavior.

## Test Plan
- [x] `make lint` and `make test` pass in `libs/cli` (556 tests)
- [x] New tests: `login` and `push` get the active context's endpoint as
`--host`; with `DOCKER_HOST` set there's no lookup and no `--host`; when
the context lookup fails, or the context has no Docker endpoint, there's
no `--host` and the deploy still succeeds. The first fails without the
change.
- [x] On a Mac running Docker Desktop with no `/var/run/docker.sock`:
`docker --config <temp dir> version` fails with `failed to connect to
the docker API at unix:///var/run/docker.sock`, and adding `--host
<active context endpoint>` reaches the daemon
- [x] Reproduced end to end on LangSmith AWS: `langgraph deploy`
(0.4.35) failed at the push with that error, then passed with
`DOCKER_HOST` set to the context's endpoint, which this change does
automatically
- [ ] After release, `langgraph deploy` pushes on Docker Desktop without
`DOCKER_HOST` set

## Demo

<!-- Drag a screen recording or screenshot here -->
2026-10-15 16:14:01 -04:00
b0482d0627 fix(langgraph): stop a subgraph from rerunning its finished tasks on resume (#9315)
Fixes #9106

When a subgraph pauses in several parallel interrupts and they're answered one at a time, each resume ran the nodes that were already answered again. Their saved answers carried them straight through `interrupt()`, so whatever they do after it (an API write, say) ran once more per later answer, while the final state still looked right. A `@task` that finished before an interrupt in a nested graph reran the same way, which is the rerun reported in #6792.

## Cause

Every task config sets `checkpoint_id` to None, and `PregelLoop` treats a config with that key as a replay, so a nested graph replayed on every resume. A replaying loop doesn't hand saved writes back to the tasks that made them, so finished tasks ran again.

## Fix

`PregelLoop` now notes whether the run points it at a checkpoint (a truthy `checkpoint_id`, its own `checkpoint_map` entry, or a parent that is replaying), the test `__enter__` already uses to pick the checkpoint to load. `_first` then decides once whether finished tasks rerun: only on time travel, or on a resume at a checkpoint the thread has moved past. A plain resume of a subgraph is neither, so it hands finished tasks their writes back the way a top-level resume does.

The same rule fixes the top level, which @hntrl pointed out: a resume sent with the head's `checkpoint_id`, as Studio sends it, or with `checkpoint_id: None` reran finished siblings too. A resume at an older checkpoint still reruns them, as the checkpoint migration tests expect. Telling the two apart costs one more checkpoint read for a run sent with a `checkpoint_id`. `test_addressed_resume_keeps_a_rerun_tasks_write_to_a_new_channel` relied on a resume at the head rerunning a task, so it now resumes a checkpoint the thread has moved past.

Most subgraph time travel forks first, which gives tasks new ids, so saved writes can't match them anyway. `test_subgraph_replay_reasks_answered_parallel_interrupt` replays an update checkpoint, which runs in place: it passes on `main` and fails if subgraphs never replay.

The counters added to `test_parallel_interrupts_double` and the three new tests in `test_interrupt_state.py` fail on `main`.

## Not in this PR

- With `durability="exit"` and three or more parallel interrupts, a subgraph now hits a bug top-level graphs already have: a finished task's output is applied twice. #9314 fixes it.
- #6792 also reports the interrupt of a `@task` inside a nested `@entrypoint` coming back twice. That's a separate bug.

Thanks @connorimes for the report, the root cause and the fix, which this applies as proposed. The same change was opened as #9113 by @AnvitDevadiga, and @morehardy found the root cause for #6792 in #6793.

JS: langchain-ai/langgraphjs#3028

Co-authored-by: Connor Imes <5701850+connorimes@users.noreply.github.com>
2026-10-15 15:51:21 -04:00
Elior Nataf LackritzandGitHub 889a5ff16f fix(langgraph): save a resumed exit run's pending writes once (#9314)
With `durability="exit"`, resuming three or more parallel interrupts one
at a time applied the earlier answers twice. Nodes `a`, `b` and `c` each
return `{"log": [f"{name}:{interrupt(name)}"]}`, and the run ends with
`{"log": ["a:yes", "a:yes", "b:yes", "c:yes"]}`.

## Cause

An exit-mode run saves its pending writes when it ends, and that save
took all of them, including the ones loaded with the checkpoint. Savers
key a task's writes by their position in the list they're given. A task
that finished in an earlier run comes back with its old interrupt next
to its output, so saving its list again put the output under a new
index, and the next load applied both copies.

## Fix

The save at exit keeps only the writes of tasks that wrote during this
run. The rest are already stored on the checkpoint, which is what sync
and async durability do.

`test_finished_task_output_applies_once` fails on `main` in exit mode
for every saver and passes for sync and async.

The #9106 fix needs this too: once a subgraph stops rerunning its
finished tasks, it hits this bug in exit mode.

JS: langchain-ai/langgraphjs#3027
2026-10-15 15:26:01 -04:00
Baihao WangandGitHub 5eb60aef6f release(prebuilt): 1.1.1 (#9316)
Bumps langgraph-prebuilt from 1.1.0 to 1.1.1.

Includes:

- Stop `ToolNode` from swallowing a resume value that fails an
interrupt's `response_schema` (#9232). This needs langgraph 1.2.15 or
later, which marks those errors; with an older langgraph, `ToolNode`
keeps today's behavior.
- Keep tool results out of v3 messages (#7838)

Managed Deep Agents (langchain-ai/managed-deepagents-sdk#710) will raise
its `langgraph-prebuilt` minimum to this release, so an invalid answer
to an interrupt raised inside a tool, such as a subagent, fails the
resume instead of reaching the model.

After merge, run the Release workflow with
`working-directory=libs/prebuilt`.

---

This PR was written with help from an AI coding agent (Claude Code); a
human reviewed and directed the changes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
prebuilt==1.1.1
2026-10-14 18:31:09 -07:00
Elior Nataf LackritzandGitHub d4149cc1f5 release(checkpoint-postgres): 3.2.0 (#9313)
Version bump only. No library code changes in this PR.

Unreleased since `checkpointpostgres==3.1.3`:

- #9290 - add `prune` / `aprune` to `PostgresSaver` and
`AsyncPostgresSaver`

Minor version for the new public API. It needs nothing beyond the
`langgraph-checkpoint>=4.3.0` floor 3.1.3 already set.
checkpointpostgres==3.2.0
2026-10-14 15:41:43 -04:00
Elior Nataf LackritzandGitHub 36bf3887f0 feat(checkpoint-postgres): add prune to PostgresSaver and AsyncPostgresSaver (#9290)
Closes #8531.

`PostgresSaver` and `AsyncPostgresSaver` inherited `prune` / `aprune`
from the base class, which raises `NotImplementedError`, so long-lived
threads had no supported way to drop old checkpoints. This adds both
strategies. Thanks to @wangjiawei-vegetable for proposing this scope in
#8531 and #9247.

- **`delete`** removes every checkpoint, write and blob of the threads,
in one transaction.
- **`keep_latest`** keeps the latest checkpoint of each namespace (the
one `get_tuple` loads), with its pending writes and the blobs it
references, and deletes the rest, including blobs only the deleted
checkpoints used. A kept checkpoint whose parent is deleted is left with
no parent. A subgraph call's namespace goes with the root checkpoint the
call started from; a `checkpointer=True` subgraph keeps its latest
checkpoint, since its state outlives each call.
- **Each thread is pruned on one snapshot.** Its transaction runs at
`REPEATABLE READ` and deletes everything that snapshot sees except the
kept checkpoints, so a run appending to the thread at the same time is
safe, whatever its checkpoint IDs.
- **`keep_latest` refuses threads that use a `DeltaChannel`**
(`NotImplementedError` naming them, nothing pruned). A `DeltaChannel`
rebuilds its latest value from older checkpoints, so deleting them would
empty it. The saver can't see channel types, so it detects one by what
only a `DeltaChannel` leaves: `counters_since_delta_snapshot` in
metadata, a snapshot (an inline `true` with a blob behind it), or
`delta_writes_versioned`, which LangGraph.js sets on threads its
`DeltaChannel` graphs start. The check runs for the whole batch first
and again in each thread's transaction, so a thread that starts using a
`DeltaChannel` mid-batch is refused at its turn.

Unlike the `prune` in #6883, `keep_latest` here deletes the blobs older
checkpoints no longer share with the kept ones (most of the storage on a
long thread), and guards `DeltaChannel` threads.

Measured locally, with or without planner statistics: a 6,000-checkpoint
thread prunes in 100 to 200 ms, and one with 1,500 finished subgraph
calls in about 110 ms.

## Known limitations

- Two prunes of the same thread at once can fail one of them with a
serialization failure or a deadlock; retrying is safe.
- Forking or replaying from a checkpoint while it's being pruned is not
safe.
- Threads written by older releases can escape the `DeltaChannel` check:
before #9142 (Python 1.2.13) and langchain-ai/langgraphjs#2973 (JS
1.5.0), some `update_state` paths saved checkpoints with neither
counters nor a snapshot.
- Postgres reuses the freed space but doesn't shrink the table files;
that takes `VACUUM FULL` or `pg_repack`.
- `DeltaChannel`-aware pruning (keeping ancestors back to the last
snapshot) is a follow-up.

## Test plan

- [x] `libs/checkpoint-postgres/tests/test_prune.py`: 71 tests over the
sync and async savers (single connection, pool, pipeline), including the
conformance `prune` capability. Passes on Postgres 15 and 16.
- [x] `libs/langgraph/tests/test_prune_postgres.py`: 39 graph tests. A
pruned thread loads the same state and keeps running like an unpruned
twin (sync, async and exit durability, interrupts, a failed parallel
step, interrupted and `checkpointer=True` subgraphs), plus deterministic
races: a turn saved mid-prune, and threads switching to a `DeltaChannel`
before and after their own check.
- [x] Each guard (the snapshot, the writes and blob scopes, the subgraph
call rules, the parent reset, the `DeltaChannel` checks, the
single-string check, the pre-v4 pending sends, the pipeline sync) broken
one at a time: every break fails at least one test.
- [x] A thread pruned in a loop while it runs, in each durability mode,
ends identical to its twin; threads written by LangGraph.js 1.5.0 and
pruned from Python behave like their twins.
2026-10-14 15:09:51 -04:00
gethin-langchainandGitHub e5b422455d release(cli): 0.4.35 (#9310)
Bumping the CLI to 0.4.35 to cut a release including #9305
(--image-pull-secret).
cli==0.4.35
2026-10-14 17:07:39 +01:00
gethin-langchainandGitHub 6cd26d0e21 feat(cli): add --image-pull-secret for deploying through a private registry (#9305)
## Summary

Deployments created with `--push-to` or `--image-uri` had no way to tell
the control plane which Kubernetes secret to use for pulling the image,
so deploying through a private registry that requires authentication
(e.g. an ECR repository gated by an imagePullSecret) wasn't possible at
all.

The control plane's `resource_spec` already supports
`image_pull_secrets` (a list of references to
`kubernetes.io/dockerconfigjson` secrets); the CLI just never exposed a
way to set it. This adds a repeatable `--image-pull-secret <name>` flag
that populates it.

```bash
langgraph deploy --push-to 123456789.dkr.ecr.us-east-1.amazonaws.com/agents/my-agent \
  --image-pull-secret regcred
```

Validation follows the same pattern already used for
`--listener-id`/`--k8s-namespace`: only valid when creating a deployment
with `--push-to` or `--image-uri`, and rejected on an existing
`--deployment-id` (the secret list is fixed at creation, same as
listener placement).

## Test plan

- [x] Added unit tests for the new `_resource_spec` helper (empty list
keeps today's default, secrets become the expected `{"name": ...}` list)
- [x] Added CLI-level tests: secret(s) land in
`source_config.resource_spec.image_pull_secrets` on create (for both
`--push-to` and `--image-uri`), rejected without
`--push-to`/`--image-uri`, rejected on an existing `--deployment-id`
- [x] `make format && make lint` clean
- [x] `make test` passes, 539 passed (9 new), no regressions
2026-10-14 16:11:04 +01:00
raghavverma-langchainandGitHub 53cf85bece feat(cli): log in with the registry username the control plane returns (#9301)
## Summary

<!-- Write the summary yourself -->

## Test Plan
- [x] `make format`, `make lint` and `make test` pass in `libs/cli` (534
tests)
- [x] New tests cover the opt-in request body, logging in with the
returned `username`, and pushing to exactly `repository_url`; they fail
without the change
- [x] Backward compatible: without `username` or `repository_url` in the
response, the CLI logs in as `oauth2accesstoken` and pushes to
`registry_url/<name>` as before, and control planes that don't read the
request body ignore it
- [ ] With the LangSmith AWS change (langchain-ai/langchainplus#49248)
live: `langgraph deploy` builds locally, pushes to the deployment's ECR
repository, and deploys

## Demo

<!-- Drag a screen recording or screenshot here -->
2026-10-14 10:31:24 -04:00
Saad FarooqandGitHub 69d98cc0d9 fix(cli): preserve failed deployment build logs (#9308) 2026-10-14 09:05:38 -04:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
ccb851effb chore(deps): bump handlebars from 4.7.9 to 4.7.10 in /libs/cli/js-examples (#9286)
Bumps [handlebars](https://github.com/handlebars-lang/handlebars.js)
from 4.7.9 to 4.7.10.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/handlebars-lang/handlebars.js/releases">handlebars's
releases</a>.</em></p>
<blockquote>
<h2>v4.7.10</h2>
<ul>
<li>security: Sanitize the source map URL when minifying - f37c599</li>
<li>security: Iterate lazily in #each and strip whitespace in linear
time - 812c226</li>
<li>security: Escape <code>&lt;!--</code> and <code>&lt;script</code> in
precompiled output - 609d1b1 GHSA-xw65-4hp5-5hc7</li>
<li>security: Don't trust special properties on context data - ceec388
GHSA-p8wg-vrv2-v86f</li>
<li>security: Only compile partials that are template strings -
c28ee7a</li>
<li>security: Only dispatch known node types in the Compiler and Visitor
- 7d501a5</li>
<li>security: Validate AST values in the compiler instead of the parser
- 703fdcc GHSA-8r5x-fm3f-whwj</li>
<li>Clarify that --root does not restrict filesystem access -
0fcf25c</li>
<li>Bump minimist to ^1.2.8 - ea8ed82</li>
<li>Fix Ruby component publishing documentation - d069c1c</li>
<li>Fix Composer component definition - 6714e07</li>
</ul>
<p>Compatibility notes:</p>
<ul>
<li><code>{{#each}}</code> iterates iterables such as <code>Map</code>,
<code>Set</code> and generators lazily, like <code>for...of</code>,
instead of
copying them into an array first. Values added to the iterable while the
block renders are now visited too.</li>
</ul>
<p><a
href="https://github.com/handlebars-lang/handlebars.js/compare/v4.7.9...v4.7.10">Commits</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/handlebars-lang/handlebars.js/blob/v4.7.10/release-notes.md">handlebars's
changelog</a>.</em></p>
<blockquote>
<h2>v4.7.10 - October 5th, 2026</h2>
<ul>
<li>security: Sanitize the source map URL when minifying - f37c599</li>
<li>security: Iterate lazily in #each and strip whitespace in linear
time - 812c226</li>
<li>security: Escape <code>&lt;!--</code> and <code>&lt;script</code> in
precompiled output - 609d1b1 GHSA-xw65-4hp5-5hc7</li>
<li>security: Don't trust special properties on context data - ceec388
GHSA-p8wg-vrv2-v86f</li>
<li>security: Only compile partials that are template strings -
c28ee7a</li>
<li>security: Only dispatch known node types in the Compiler and Visitor
- 7d501a5</li>
<li>security: Validate AST values in the compiler instead of the parser
- 703fdcc GHSA-8r5x-fm3f-whwj</li>
<li>Clarify that --root does not restrict filesystem access -
0fcf25c</li>
<li>Bump minimist to ^1.2.8 - ea8ed82</li>
<li>Fix Ruby component publishing documentation - d069c1c</li>
<li>Fix Composer component definition - 6714e07</li>
</ul>
<p>Compatibility notes:</p>
<ul>
<li><code>{{#each}}</code> iterates iterables such as <code>Map</code>,
<code>Set</code> and generators lazily, like <code>for...of</code>,
instead of
copying them into an array first. Values added to the iterable while the
block renders are now visited too.</li>
</ul>
<p><a
href="https://github.com/handlebars-lang/handlebars.js/compare/v4.7.9...v4.7.10">Commits</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/handlebars-lang/handlebars.js/commit/45ce15255e0f430ac6d19742b18e316b7539264e"><code>45ce152</code></a>
v4.7.10</li>
<li><a
href="https://github.com/handlebars-lang/handlebars.js/commit/e47b2365d5656ab5689ae226aef90a485a90c5d8"><code>e47b236</code></a>
Update release notes</li>
<li><a
href="https://github.com/handlebars-lang/handlebars.js/commit/f37c599de9187715eb1e9afedcb2d80c175487a0"><code>f37c599</code></a>
Sanitize the source map URL when minifying</li>
<li><a
href="https://github.com/handlebars-lang/handlebars.js/commit/812c2260cb8794ef4ab63a7f1d946431112560ca"><code>812c226</code></a>
Iterate lazily in #each and strip whitespace in linear time</li>
<li><a
href="https://github.com/handlebars-lang/handlebars.js/commit/609d1b11c833c9a3e00f56f2f34d22f425446725"><code>609d1b1</code></a>
Escape <code>&lt;!--</code> and <code>&lt;script</code> in precompiled
output</li>
<li><a
href="https://github.com/handlebars-lang/handlebars.js/commit/ceec388abe1d1aac8f6369860d5f390fa71ef4fa"><code>ceec388</code></a>
Don't trust special properties on context data</li>
<li><a
href="https://github.com/handlebars-lang/handlebars.js/commit/c28ee7adb312308e0fe26f4d435a481be5e1ff98"><code>c28ee7a</code></a>
Only compile partials that are template strings</li>
<li><a
href="https://github.com/handlebars-lang/handlebars.js/commit/7d501a5af2ac3aa9ac788a8889dbe419849e46f1"><code>7d501a5</code></a>
Only dispatch known node types in the Compiler and Visitor</li>
<li><a
href="https://github.com/handlebars-lang/handlebars.js/commit/703fdcc5fd6cc8d1cc0c33cc19de40c467c4b8d2"><code>703fdcc</code></a>
Validate AST values in the compiler instead of the parser</li>
<li><a
href="https://github.com/handlebars-lang/handlebars.js/commit/0fcf25c63038b43e78e17adbf029cf073e80554d"><code>0fcf25c</code></a>
Clarify that --root does not restrict filesystem access</li>
<li>Additional commits viewable in <a
href="https://github.com/handlebars-lang/handlebars.js/compare/v4.7.9...v4.7.10">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=handlebars&package-manager=npm_and_yarn&previous-version=4.7.9&new-version=4.7.10)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/langchain-ai/langgraph/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-14 16:39:24 +09:00
Elior Nataf LackritzandGitHub a6731f4367 fix(langgraph): keep a DeltaChannel's value when its field changes to a plain reducer (#9302)
Changing a field from a `DeltaChannel` to a plain reducer, for example
to `Annotated[list, add_messages]`, made threads written under the
`DeltaChannel` read that field as empty. The next run saved its writes
over the empty value, so continuing an old thread replaced its history.
The writes were still stored: the read only rebuilt fields whose current
annotation is a `DeltaChannel`.

- A `BinaryOperatorAggregate` stores its value at every version, so one
with a version and nothing stored was written as a `DeltaChannel`. It's
now rebuilt from the same history walk, one `update` per write, since a
single call would reject a second `Overwrite` and drop the writes after
one.
- `BinaryOperatorAggregate.from_checkpoint` unwraps a stored
`_DeltaSnapshot`.
- The next run saves the full value, so later reads are plain reads, and
switching back to a `DeltaChannel` keeps everything.

Threads written under a plain reducer never walk. A rebuilt read costs
the walk plus one reducer call per write since the last snapshot: with
`add_messages` on `InMemorySaver`, 25 ms at 2,048 messages with a
snapshot every 50 writes, and 0.3 s at 1,998 or 0.9 s at 4,998 messages
with the default 1000. After one run, reads take 6 to 16 ms.

`test_delta_channel_to_plain.py` covers every saver; all but the
plain-thread test fail on main.

JS: langchain-ai/langgraphjs#3017
2026-10-13 20:47:19 -04:00
gethin-langchainandGitHub 8a77332d0d release(cli): 0.4.34 (#9300)
Bumping the CLI to 0.4.34 to cut a release including #9243 (--json on
deploy listeners list).
cli==0.4.34
2026-10-13 16:32:51 +01:00
gethin-langchainandGitHub a1ce197234 feat(cli): add --json to deploy listeners list (#9243)
## Summary

`deploy listeners list` only prints a human-readable table, which a
deploy automation pipeline can't reliably parse to extract a listener's
id for `--listener-id`.

Adds `--json`, which prints the listeners as a JSON array instead of the
table. An empty workspace prints `[]` rather than the "No listeners
found" sentence, so callers never need to special-case the no-results
path when scripting against it.

## Test plan

- [x] `make format && make lint` clean in `libs/cli`
- [x] `test_deploy_listeners_list_command_json` and
`test_deploy_listeners_list_command_json_no_results` in `test_cli.py`,
mirroring the existing table-output test pair
- [x] Full `libs/cli` suite: 529 passed, no regressions
2026-10-13 15:43:03 +01:00
Elior Nataf LackritzandGitHub afbe7e48b1 release(checkpoint-postgres): 3.1.3 (#9287)
Version bump only. No library code changes in this PR.

Unreleased since `checkpointpostgres==3.1.2`:

- #8617 - widen `Store` `put` value type to `Mapping[str, Any]`
- #8556 - derive the delta walk cursor once the target loads
- #8544 - order delta channel replay by task path
- #9217 - validate namespace labels before store dispatch
- #9248 - start the delta walk at the target
- #9262 - treat an empty `checkpoint_id` as the latest in delta history

Follows `checkpoint==4.3.0`, which is already live on PyPI. #8544 raised
the floor to `langgraph-checkpoint>=4.3.0`, so this release needs it.
checkpointpostgres==3.1.3
2026-10-12 22:57:04 +00:00
Elior Nataf LackritzandGitHub 1074714c26 release(checkpoint-sqlite): 3.1.2 (#9288)
Version bump only. No library code changes in this PR.

Unreleased since `checkpointsqlite==3.1.1`:

- #8617 - widen `Store` `put` value type to `Mapping[str, Any]`
- #8557 - walk delta ancestors by parent pointer
- #8544 - order delta channel replay by task path
- #9217 - validate namespace labels before store dispatch
- #9262 - treat an empty `checkpoint_id` as the latest in delta history

Follows `checkpoint==4.3.0`, which is already live on PyPI. #8544 raised
the floor to `langgraph-checkpoint>=4.3.0`, so this release needs it.
sdk==0.4.7 checkpointsqlite==3.1.2
2026-10-12 22:47:17 +00:00
Elior Nataf LackritzandGitHub 740461ed50 release(sdk-py): 0.4.7 (#9289)
Bumps the Python SDK version from 0.4.6 to 0.4.7. A thread stream's run
now ends only on the root graph's `completed` or `failed` event, not a
subgraph's, so `thread.output` no longer reads the state too early and a
run that fails after a subgraph finishes is reported as failed (#9228).
2026-10-12 22:47:05 +00:00
Igor SoarezandGitHub 08a345637f release(langgraph): 1.2.15 (#9283)
Bumps langgraph from 1.2.14 to 1.2.15. It now requires
langgraph-checkpoint 4.3.0 or later (#8544).

Also includes:

- Order delta channel replay by task path (#8544)
- Replay a resumed exit-mode run's delta writes in live order (#9114)
- Give each `bulk_update_state` update its own task id (#9128)
- Stop `astream_events` dropping control/interrupts on v1/v2 (#9219)
- Never store exit-mode delta writes under the null task id (#9229)
- Mark a resume value that fails an interrupt's `response_schema`, so
`ToolNode` can stop swallowing it once langgraph-prebuilt is released
(#9232)
- Don't save a checkpoint past a failed DeltaChannel write (#9235)
- Keep a fork's DeltaChannel snapshot from starting nodes that never ran
(#9264)
- Snapshot a DeltaChannel that an `update_state` Overwrite resets
(#9263)
- Read a run's DeltaChannel input back only on its own checkpoints
(#9260)
- Store an `update_state` input's writes on the checkpoint it updates
(#9258)
- Keep an exit run from a checkpoint the thread moved past out of its
newer branch (#9269)
- Stop at an `interrupt_before` breakpoint when a drain is requested
before it (#9281)
- Save a cached node's writes like a node that ran (#9259)
- Give every message written to a messages DeltaChannel an id (#9275)
1.2.15
2026-10-12 18:34:01 -04:00
b7d053b256 fix(langgraph): give every message written to a messages DeltaChannel an id (#9275)
A DeltaChannel replays its saved writes on every read, and
`_messages_delta_reducer` doesn't fill in missing ids, so the loop gives
messages their ids before saving them (`ensure_message_ids`). That
missed several cases:

- Strings and `(role, content)` tuples, alone or in a list (`[("user",
"hi")]`), and messages inside an `Overwrite` were saved with no id, so
nothing could target them by id, for example `RemoveMessage`. A regular
messages channel gives them ids.
- A raw `Pregel` graph's input to a DeltaChannel got its ids after it
was applied, and none with exit durability or on a new thread; a dict
given as input read back with an id its nodes never saw. A
`Command(update=...)` sent to an older checkpoint got none either.

Now, in a DeltaChannel whose reducer is `_messages_delta_reducer`, every
message-like the reducer accepts becomes a message with an id before the
writes are saved or applied: in `put_writes`, before input is applied,
for a forked `Command`, and in `update_state`. Anything that can't
become a message is left as it is, so it fails where it always has.
Other DeltaChannels keep the rule they had (message objects, and message
dicts in a list, get ids), since they may hold other data and
deepagents' messages channel, which uses its own copy of the reducer,
relies on it; the dicts in an `Overwrite` there are left as they are.
Lists and dicts the caller passed in are never changed: a write that
changes is replaced. So the id step can recognize the reducer without an
import cycle, `_messages_delta_reducer` now lives in
`langgraph.pregel._messages`; `langgraph.graph.message` re-exports it.

Visible changes: in a messages DeltaChannel, a node's update streams as
messages with ids, and a string is stored as a message (about 170 bytes
more each).

JS twin: langchain-ai/langgraphjs#2992. Thanks to @HarshShroff for
testing every `Overwrite` form and for the tuple fix.

## Tests

`test_delta_channel_id_stability.py` and
`test_delta_channel_update_state.py`: a write of every shape the reducer
accepts gets an id that every read keeps, as input, from a node and
through `update_state` (sync, async and as input); a list written twice
adds its messages twice and stays as it was; a forked `Command` gets an
id; a message dict the reducer rejects in a list still fails the run
before it's saved; a raw `Pregel` input gets an id on a new thread with
every durability, and its nodes see the ids that are saved; another
DeltaChannel keeps the dicts in an `Overwrite`. 36 of the 87 tests in
these files fail on main. The langgraph and prebuilt suites pass, and
lint is clean.

---------

Co-authored-by: Harsh Shroff <29751900+HarshShroff@users.noreply.github.com>
checkpoint==4.3.0
2026-10-12 20:33:45 +00:00
Elior Nataf LackritzandGitHub 395c145c04 fix(langgraph): save a cached node's writes like a node that ran (#9259)
A node served from the node cache had its writes applied but never
saved: the loop only streamed them. Plain channels didn't notice, since
the next checkpoint stores their value, but a `DeltaChannel` is rebuilt
from the saved writes, so its saved state lost the cached node's write
for good, under every durability. With `a -> b -> c` and `b` cached, a
second thread read back `log` as `a, c` next to `plain` as `a, b, c`.

The loop now saves a cache hit with `put_writes`, like a node that ran,
in all six places it matches cached writes. A new `cached` flag keeps
the hit streamed as cached and stops `put_writes` from writing it back
to the cache, which would also restart its TTL. A hit now costs the
saver write the node makes when it runs, and a cached `@task` call's
result is saved the same way.

The sync loop also stops caching a node that failed or was interrupted,
as the async loop already did: a cached error made the next run with the
same input skip the node without raising.

Found in review of langchain-ai/langgraphjs#2969. JS twin:
langchain-ai/langgraphjs#2980

## Tests

- `test_delta_channel_node_cache.py`: `b` runs on the first thread and
is a cache hit on the second, under every durability, with `invoke` and
`ainvoke`. Every checkpoint of the second thread reads the same in the
DeltaChannel and a plain channel, and the cache is written once. All 6
cases fail on main; without the `cached` check in `put_writes`, they
fail on the cache count.
- `test_a_node_that_fails_is_not_cached`, with `invoke` and `ainvoke`: a
cached node that raises raises again on the next thread. The sync case
fails on main.
- The two tests that spy on `PregelLoop.put_writes` pass the new keyword
through.
- `make format`, `make lint_package`, `make lint_tests`, and the
`langgraph`, `prebuilt` and `cli` suites pass (without Redis).
2026-10-12 14:24:38 -04:00
Igor SoarezandGitHub 10f1fabb3b fix(langgraph): stop at an interrupt_before breakpoint when a drain is requested before it (#9281)
When a drain is requested during the step right before an
interrupt_before breakpoint, the run stops with GraphDrained and the
breakpoint is lost: resuming the run skips it unintentionally.

The fix moves the drain check in tick() after the breakpoint check, so
breakpoints win over draining.

JS twin: langchain-ai/langgraphjs#3009
2026-10-12 18:29:56 +03:00
Elior Nataf LackritzandGitHub 799c2f04fd fix(langgraph): keep an exit run from a checkpoint the thread moved past out of its newer branch (#9269)
An exit-durability run that starts from a checkpoint the thread has
moved past, addressed by `checkpoint_id`, stores its DeltaChannel writes
on that checkpoint. The branch that already grew from it reads the
writes stored there, so its checkpoints picked up this run's writes too:

```python
graph.invoke({"log": ["in1"]}, config)  # nodes a and b add "a1", "b1"
turn_1 = graph.get_state(config).config
graph.invoke({"log": ["in2"]}, config)
turn_2 = graph.get_state(config).config
graph.invoke({"log": ["in3"]}, turn_1, durability="exit")
graph.get_state(turn_2).values["log"]
# ["in1", "a1", "b1", "in3", "a3", "b3", "in2", "a2", "b2"], was ["in1", "a1", "b1", "in2", "a2", "b2"]
```

Sync and async durability store each step's writes on the run's own
checkpoints, so they weren't affected. The run now snapshots the
DeltaChannels it wrote instead, as a run's input already does on a
checkpoint a `checkpoint_id` addressed (#9260). That costs one snapshot
of each channel the run wrote, even when the addressed checkpoint is the
latest one. Threads that already hit this keep the wrong values on the
existing branch.

Found by @hntrl in review of langchain-ai/langgraphjs#2974
([repro](https://gist.github.com/hntrl/2185e489abe22147b3f6f77010c18264)).
JS twin: langchain-ai/langgraphjs#2989

## Tests

`test_delta_channel_exit_mode.py`: one and two exit runs from the end of
turn 1, after turn 2, leave every checkpoint's DeltaChannel equal to a
plain reducer channel. Both fail on main on every saver in the fixture.
The `langgraph` suite passes (without Redis), and lint is clean.
2026-10-11 08:51:09 -04:00
Elior Nataf LackritzandGitHub b4991f1ba3 fix(langgraph): store an update_state input's writes on the checkpoint it updates (#9258)
`update_state(..., as_node="__input__")` stored its writes on the
checkpoint it saved. A DeltaChannel reads the writes stored on a
checkpoint's ancestors, not its own, so that checkpoint read back
without the input unless the channel snapshotted there, and once a later
checkpoint snapshotted, the input was gone for good. Only a raw `Pregel`
graph whose input channel is a DeltaChannel hits it, since a
`StateGraph`'s input goes to its start channel.

The input's writes now go on the checkpoint the update builds on, as a
node update's do. An update on a checkpoint the thread has moved past
stores nothing there and snapshots the DeltaChannels it writes on its
own checkpoint instead, the rule a node update already follows (#9165).

Both kinds of update now go through one helper, which also gives a
message an id before saving it, as the loop's `put_writes` does with
`ensure_message_ids`. Before, a message saved through `update_state`
without an id read back with id `None`, on the node path too, while the
same message from a node got one.

JS twin: langchain-ai/langgraphjs#2973, where review found it.

## Tests

`test_delta_channel_update_state.py`, sync and async: an update as input
reads back on its checkpoint and after the next run, with
`snapshot_frequency` 1 and 2, and an update as input to an older
checkpoint stays out of its other branch. The frequency 2 and
older-checkpoint cases fail on main. Five more check that a message
saved through `update_state` gets an id every read keeps, on the node
path (latest and older checkpoint) and the input path, sync and async;
they fail on main. The langgraph suite passes, and `lint_package` and
`lint_tests` are clean.
2026-10-10 11:57:46 +00:00
Elior Nataf LackritzandGitHub 6aa0afba68 fix(checkpoint): default InMemorySaver delta history to the latest checkpoint (#9257)
`InMemorySaver.get_delta_channel_history` looked its target up by
`config["configurable"].get("checkpoint_id", "")`, so a config without a
`checkpoint_id` matched no checkpoint, and every channel came back with
no seed and no writes, which a `DeltaChannel` reads as empty. The base
implementation, `PostgresSaver` and `SqliteSaver` read from the thread's
latest checkpoint instead, as `get_tuple` does.

A missing id now resolves to the namespace's newest checkpoint id, with
the same `max` that `InMemorySaver.get_tuple` uses. Graphs always pass a
checkpoint id here, so only direct callers of the saver API were
affected, and a call with an id does the same work as before.

Thanks @Hotragn, who pinned this down on #8242, where @longquanzheng's
branch had already fixed it.

JS twin: langchain-ai/langgraphjs#2979

## Tests

- `test_get_channel_writes_without_checkpoint_id_reads_the_latest` fails
on main (`{'messages': {'writes': []}}`).
- The `checkpoint`, `checkpoint-conformance`, `checkpoint-sqlite`,
`checkpoint-postgres` (Postgres 16), `prebuilt` and `langgraph` suites
pass, the last two without their Redis cases. The DeltaChannel
conformance suite also passes against `InMemorySaver`; CI skips that run
in `libs/checkpoint`, where the conformance package isn't installed, so
the new test lives in `test_memory.py`.
2026-10-10 00:59:20 +00:00
Elior Nataf LackritzandGitHub 12aeb0fddb fix(langgraph): read a run's DeltaChannel input back only on its own checkpoints (#9260)
A raw `Pregel` graph whose input channel is a DeltaChannel saved a run's
input to it as a `NULL_TASK_ID` write on the checkpoint the run started
from, under `"sync"` and `"async"` durability. Readers apply a
checkpoint's `NULL_TASK_ID` writes as its own state, so:

- on a new thread that checkpoint is never saved, and the first run's
input was lost for good: after `{"log": [0], "plain": [0], ...}`, `log`
read `[2]` next to `plain` `[0, 2]`;
- the last checkpoint of a run read the next run's input;
- a run with input from an older checkpoint (`checkpoint_id`) leaked its
input into the branch that already grew from it, and read that branch's
input when it had one.

The input's writes now go on the checkpoint the run starts from under a
task id of their own, `uuid5(checkpoint_id, INPUT)`, the one
`update_state` uses for an input update. On a new thread, or a
checkpoint a `checkpoint_id` addressed, which may already have children
that would read them, nothing is stored there and the input checkpoint
snapshots the channel instead. A normal run stores the same write as
before, and `durability="exit"`, which already kept the input right, is
unchanged. Threads saved before this keep the input writes already
stored on their checkpoints.

A `StateGraph` routes its input through its start channel, so only raw
`Pregel` graphs hit this.

JS twin: langchain-ai/langgraphjs#2981

## Tests

`test_delta_channel_run_input.py`, under every durability, with `invoke`
and `ainvoke`: two runs on a new thread, and a run with input from an
older checkpoint whose other branch had DeltaChannel input or none.
Every checkpoint reads the same in the DeltaChannel and a plain channel.
The 12 sync and async cases fail on main, and dropping the task id, the
new-thread snapshot or the addressed-checkpoint snapshot each fails its
own cases. The `langgraph` and `prebuilt` suites pass (without Redis),
and `lint_package` and `lint_tests` are clean.
2026-10-09 15:59:10 -04:00
Elior Nataf LackritzandGitHub d05236f805 fix(langgraph): snapshot a DeltaChannel that an update_state Overwrite resets (#9263)
A node that writes an `Overwrite` to a DeltaChannel makes the loop
snapshot the channel on the checkpoint that superstep saves, so no read
replays across the reset. The same write through `update_state`, as a
node or as input, didn't snapshot: the value read back right, but reads
of the update's checkpoint and the ones after it walked back past the
reset to the last snapshot. `update_state` now snapshots a DeltaChannel
an `Overwrite` resets, as the loop does.

Raised in review of langchain-ai/langgraphjs#2973. JS twin:
langchain-ai/langgraphjs#2982

## Tests

`test_delta_channel_update_overwrite.py`, sync and async: an `Overwrite`
through `update_state` as a node, and as input to a raw `Pregel` graph,
snapshots the channel on the checkpoint the update saves, and the value
reads back as the overwrite. All four fail on main. The `langgraph`
suite passes (without Redis), and `lint_package` and `lint_tests` are
clean.
2026-10-09 15:26:16 -04:00
Elior Nataf LackritzandGitHub 9d92f33cca fix(langgraph): keep a fork's DeltaChannel snapshot from starting nodes that never ran (#9264)
A fork from a checkpoint with pending writes to a DeltaChannel snapshots
the channel on the fork's first checkpoint, so the fork doesn't replay
the other branch's writes. If the channel had never been written there,
the snapshot also gives it its first version, and `_mark_bumps_seen`
only marked the bump seen for nodes that already have a `versions_seen`
entry. A node subscribed to the channel that never ran has none, so the
bump started it, and it read the empty value before the node that writes
the channel had run:

```python
graph.invoke("go", config)  # writer writes [1] to d, reader reads [1]
fork = graph.update_state(first_checkpoint, {"a": "go"}, as_node="__input__")
graph.get_state(fork).next  # ("writer", "reader"): resuming runs reader on [] first
```

A replay from that checkpoint saves the same kind of fork from the loop.
A channel bumped from no version was never written, so
`create_checkpoint` now also marks the bump seen for the nodes the
channel triggers, from the graph's `trigger_to_nodes`, at every call
that can bump. Only raw `Pregel` graphs hit this: `StateGraph` nodes
trigger on their `branch:to:*` channels, not on state keys. An
`as_node="__copy__"` fork still starts such a node, with a plain list
channel as well, so that case isn't DeltaChannel-specific and isn't
changed here.

Raised in review of langchain-ai/langgraphjs#2974. JS twin:
langchain-ai/langgraphjs#2983

## Tests

`test_delta_channel_seal_subscribers.py`: an update as input (sync and
async) and a replay from the checkpoint before a DeltaChannel's first
write leave only the writer next, and the reader then reads the written
value once. All three fail on main. The `langgraph` suite passes
(without Redis), and `lint_package` and `lint_tests` are clean.
2026-10-09 14:36:27 -04:00
Elior Nataf LackritzandGitHub 26356227c4 test(checkpoint): run the delta conformance suite against InMemorySaver in CI (#9261)
The conformance self-test in `libs/checkpoint-conformance` ran every
capability against `InMemorySaver` but asserted only the base ones.
`libs/checkpoint/tests/test_conformance_delta.py`, which ran the delta
conformance tests against it, always skips in CI: `libs/checkpoint`
can't depend on the conformance package, which depends on it. So no CI
job checked `InMemorySaver.get_delta_channel_history` against the delta
conformance tests.

The self-test now asserts every capability `InMemorySaver` implements,
and the skipped copy is gone.

## Tests

- With `InMemorySaver.get_delta_channel_history` broken to return no
history, the self-test now fails on 7 of the 10 delta conformance tests;
on main it still passes.
- `make format`, `make lint` and `make test` pass in
`libs/checkpoint-conformance`.
2026-10-09 13:44:55 -04:00
Elior Nataf LackritzandGitHub a5dbacae0d fix(checkpoint-postgres,checkpoint-sqlite): treat an empty checkpoint_id as the latest in delta history (#9262)
`PostgresSaver` and `SqliteSaver`, sync and async, read a DeltaChannel's
history from the latest checkpoint only when the config's
`checkpoint_id` was missing or `None`. An empty one was looked up as an
id, matched nothing, and came back with no seed and no writes, while
their own `get_tuple` treats an empty id as the latest checkpoint, as
the default implementation does. They now check for a missing or empty
id the way `get_tuple` does. The in-memory saver gets the same in #9257.

Graphs always pass the id of a saved checkpoint, so only direct callers
of the saver API hit this.

## Tests

-
`test_{sync,async}_empty_checkpoint_id_reads_from_the_latest_checkpoint`
in `checkpoint-postgres/tests/test_delta_pagination.py` and
`checkpoint-sqlite/tests/test_delta_parent_walk.py`: all four fail on
main.
- The `checkpoint-postgres` (Postgres 16) and `checkpoint-sqlite` suites
pass, and `lint_package` and `lint_tests` are clean in both.
2026-10-09 13:44:51 -04:00
cba111d8d6 fix(langgraph): don't save a checkpoint past a failed DeltaChannel write (#9235)
A DeltaChannel is rebuilt from its writes along the parent chain, so a
checkpoint saved without one of them reads back short for good. If
saving a DeltaChannel write failed (a database blip, say), the next
checkpoints were saved anyway and the channel lost that write, while
plain channels kept it. Three things let that happen:

- the sync loop waited for the delta writes before saving a checkpoint,
but never checked that they succeeded;
- both loops saved a checkpoint even when the previous save had failed,
so it pointed at a parent that was never saved;
- each save took the pending write list only when it started in the
background, and saves can start out of order, so a save could take a
later checkpoint's writes and not wait for its own. Waiting on writes
queued behind it, a save could also hang a sync run with
`durability="async"` (the default) once every worker was such a save: on
a 15-core machine a loop of 100 fast steps hung every time with default
settings, and with `max_concurrency=1` three steps are enough.

Now `_put_checkpoint` hands each save the writes submitted before it,
and a save fails if one of them or the previous save failed. The run
raises the write's error as before, the thread stays at its last
checkpoint that has all its writes, and running it again reruns the
task. For graphs without a DeltaChannel, a failed save now also stops
the later saves of that run, as JS already does, instead of saving
checkpoints whose parent is missing.

Thanks @shivangsharma01 for reproducing this in #8234, and @iroiro147,
whose #8299 had the first two changes before the issue-assignment check
closed it. Thanks also to @HarshShroff for the failed-save test case.

JS twin: langchain-ai/langgraphjs#2969

## Tests

`test_delta_channel_write_failures.py`:

- a saver fails one delta write once; on every durability, with `invoke`
and `ainvoke`, every saved checkpoint matches a plain channel and a
retry gets the write back. The `invoke` cases and `ainvoke` with
`durability="async"` fail on main.
- a saver fails the save of the checkpoint after `a` once; with `invoke`
and `ainvoke`, every saved checkpoint matches a plain channel and a
retry finishes the run. The `durability="async"` cases fail on main,
which saves the later checkpoints on top of the missing one.
- a delta graph run with `max_concurrency=1` finishes. It hangs on main.

Reverting any one of the three changes fails at least one of these.
`make format`, `make lint` and the langgraph suite pass. A 100-step
benchmark (delta and plain channels, every durability, with and without
1 ms of saver latency) makes the same saver calls and runs in the same
time as main, except for the case that hangs on main.

---------

Co-authored-by: iroiro147 <265728356+iroiro147@users.noreply.github.com>
2026-10-09 12:48:24 +00:00
Elior Nataf LackritzandGitHub 93a5a28008 perf(checkpoint-postgres): start the delta walk at the target (#9248)
Reading a DeltaChannel at an older checkpoint (the state at a past
checkpoint, each entry of `get_state_history`, a fork or replay from
one) walked `checkpoints` down from the newest row, so every newer row
was read before the target's chain. A checkpoint's ancestors have
smaller ids, the order `get_tuple` already relies on to find the latest
checkpoint, so the walk now starts at the target: the first page is
`checkpoint_id <= target`, later pages stay `< cursor`.

The cursor is never NULL anymore, so the `(cursor IS NULL OR
checkpoint_id < cursor)` predicate goes too. Once Postgres caches a
generic plan for the prepared statement (`from_conn_string` sets
`prepare_threshold=0`), that predicate is a filter rather than an index
condition, and each later page re-read every newer row.

`get_delta_channel_history` on a 6,000-checkpoint thread with a snapshot
every 200 checkpoints, median of three runs of 60 reads each, same
results before and after:

| target | main | this PR |
|---|---|---|
| newest | 3.1 ms | 2.7 ms |
| 1,000 back | 4.5 ms | 2.9 ms |
| 3,000 back | 8.9 ms | 2.8 ms |
| 5,000 back | 15.7 ms | 2.8 ms |

The target is now always the first row read, so the pagination tests
from #8556 can no longer leave it off the first page; they are renamed
for what they still cover, a walk that continues across pages.

## Test plan
- [x] `test_{sync,async}_walk_reads_nothing_newer_than_the_target`
record the rows the walk reads; both fail on main, which also reads the
three newer checkpoints.
- [x] `checkpoint-postgres` suite on Postgres 16: 281 passed, 3 skipped.
- [x] `langgraph` DeltaChannel tests against this saver (`-k "delta and
not redis"`): 1,154 passed, 1 skipped.
2026-10-09 08:31:15 -04:00
Baihao WangGitHubBaihao Wangopen-swe[bot] <open-swe@users.noreply.github.com>
bfcfea554e fix(checkpoint,checkpoint-postgres,checkpoint-sqlite): validate namespace labels before store dispatch (#9217)
The SQLite and Postgres stores save a namespace as its labels joined
with `.`, so a label containing `.` could resolve to a different
namespace: `("foo.bar",)` and `("foo", "bar")` share the same row. This
rejects those labels at every entry point.

- `BaseStore` and `AsyncBatchedBaseStore`: `get`, `search`, `delete`,
and `list_namespaces` (sync and async) reject labels that are empty, not
strings, or contain `.`. The check runs before an op is queued, so one
caller's bad label can't fail other callers' concurrent requests.
- New `langgraph.store.base.validate_op_namespace(op)` applies the same
label checks to a single op. `SqliteStore`/`AsyncSqliteStore` and
`PostgresStore`/`AsyncPostgresStore` call it from `_group_ops` before
any SQL runs, which covers direct `batch`/`abatch` calls. Other stores
that serialize namespaces as delimited text can call it too.
- Unchanged: hierarchical prefix search, empty-prefix `search(())`, `*`
wildcards in `list_namespaces`, and the existing `put` rules.

## Release note

`get`, `search`, `delete`, and `list_namespaces` now raise
`InvalidNamespaceError` for labels that are empty, not strings, or
contain `.`, where they previously returned `None` or `[]` (or, on the
SQLite and Postgres stores, matched a different namespace). `put`
already rejected these labels, so nothing written through `put` becomes
unreachable.

## Release order

Release `langgraph-checkpoint` first. `langgraph-checkpoint-sqlite` and
`langgraph-checkpoint-postgres` import `validate_op_namespace`, so they
need the `langgraph-checkpoint` release that ships it. `main` already
has `libs/checkpoint` at 4.3.0 and requires
`langgraph-checkpoint>=4.3.0` in both stores (from #8544), so this must
merge before 4.3.0 is released; if 4.3.0 ships first, bump to the next
version and raise both requirements to it. That also guarantees the
pre-queue checks are installed: with an older `langgraph-checkpoint`, an
invalid op would fail inside the shared `abatch` and reject the calls
batched with it.

---------

Co-authored-by: Baihao Wang <byhow@users.noreply.github.com>
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
2026-10-08 16:10:55 -07:00
Elior Nataf LackritzandGitHub 93f5eaff21 fix(checkpoint): keep serialized data when an object can't be rebuilt (#9251)
Fixes #6970

If a checkpointed object can't be rebuilt on load (its module was
removed or renamed, or its constructor now rejects the stored fields),
`JsonPlusSerializer` returned `None` for it, so the value silently
disappeared from restored state. The constructor and method ext codes
now return the serialized payload instead, the same thing the pydantic
and blocked-type paths already do, and log a one-time warning per type.
The warning names the exception type only, since exception messages can
echo the stored value.

Thanks @yangbaechu for the report and repro. This takes the same
direction as #6972 by @pandego and #7152 by @SinzoL.
2026-10-08 16:01:46 -04:00
Baihao WangandGitHub 5965d72ff7 fix(langgraph,prebuilt): stop ToolNode from swallowing invalid resume values (#9232)
**Problem.** `interrupt(response_schema=...)` checks a human's answer
when the graph resumes. If the answer doesn't match the schema, the
resume fails, nothing is saved, and the human can answer again (#8886).
That works when the interrupt runs in a graph node, but not when it runs
inside a tool: either the tool calls `interrupt()` itself, or it starts
a graph that does, such as a subagent called as a tool. There, the
resume returns normally and the interrupt disappears.

**Why.** `interrupt()` raises a `pydantic.ValidationError` for an
invalid answer. When one comes out of a tool, `ToolNode` assumes the
model passed bad arguments, so it hands the error to the model ("Error
invoking tool … Please fix the error and try again") and the run carries
on. The human never sees the error, the model is blamed for it, and the
interrupt is no longer pending.

**Fix.** `interrupt()` still raises the same `ValidationError`, but
marks it so a new helper, `langgraph.errors.is_invalid_resume(error)`,
can recognize it. `ToolNode` re-raises these errors instead of handing
them to the model, whatever `handle_tool_errors` is set to, so a bad
answer fails the resume the same way inside a tool as outside one:
nothing is saved and the interrupt can be answered again. Every other
`ValidationError` from a tool is handled as before.

**Also fixed, in the same error handling.** With `wrap_tool_call` set
and a `handle_tool_errors` other than the default (for example `True`),
`ToolNode` turned any exception from the wrapper into an error
`ToolMessage`, including `GraphInterrupt`. So an interrupt in that setup
never paused: the model got `Error: GraphInterrupt(...)` instead.
Interrupts now propagate there too, as they already do without a
wrapper. `create_agent` uses the default handler, so it was not
affected.

**Compatibility.** Not a breaking change: the error type is unchanged.
Worth a careful look: a wrapped `ToolNode` with a non-default
`handle_tool_errors` now pauses on interrupts instead of returning them
to the model as errors. With an older `langgraph` that doesn't have
`is_invalid_resume`, `ToolNode` keeps today's behavior.
2026-10-08 12:59:25 -07:00
Elior Nataf LackritzandGitHub 40a2e6d845 fix(langgraph): never store exit-mode delta writes under the null task id (#9229)
In exit mode, a run stores its DeltaChannel writes on the checkpoint it
started from, under synthetic task ids that put the superstep first. For
a `Command`'s writes in a run whose first superstep is 0, that id came
out as `NULL_TASK_ID` itself. Readers take writes under `NULL_TASK_ID`
for the checkpoint's own pending writes, so after
`invoke(Command(update=...), durability="exit")`:

- on a new thread, `get_state` on the empty first checkpoint showed the
update in the DeltaChannel but not in a plain channel;
- on a thread whose first checkpoint came from `update_state(...,
as_node="__input__")`, `get_state` on that checkpoint showed the update
the same way, and a replay or fork from it applied the update to the
DeltaChannel only.

`exit_delta_task_id` now never returns `NULL_TASK_ID`. Threads already
saved this way stay as they are.

## Tests

- `test_command_update_on_an_input_checkpoint_matches_a_plain_channel`
compares every checkpoint in the history, and a replay from the input
checkpoint, with a plain channel, on every checkpointer and durability.
The exit cases fail without the fix.
- `test_exit_command_update_on_a_new_thread_matches_a_plain_channel`
compares every checkpoint in a new thread's history with a plain
channel, on every checkpointer, and fails without the fix. It runs in
exit mode only: in sync and async the two channels already differ on
`main`, because of a separate bug that applies a new thread's `Command`
update twice.

`make format`, `make lint` and the langgraph suite pass.
2026-10-07 19:17:02 -04:00
Elior Nataf LackritzandGitHub a0053bb616 fix(sdk-py): end a thread stream's run only on a root lifecycle event (#9228)
The thread stream's lifecycle watcher ended the run on any `completed`
or `failed` lifecycle event, including the one a subgraph sends when it
finishes. So `thread.output` could read the thread state before the
parent stored the step that ran the subgraph, and a run that failed
after a subgraph completed was reported as completed. The async and sync
watchers now end the run only on a root event, with the
`_is_root_terminal_lifecycle` check the fanout already uses. The JS SDK
checks the root namespace here too.

This is the `sdk-py integration` flake where the final `items` comes
back as `['streamed', 'tool', 'asked']` without `'sub'`: the example
graph's last node runs a subgraph.

## Tests

New async and sync tests send a subgraph `completed` and then a root
`failed`. Without the fix the run ends as completed. `make lint` and
`make test` in `libs/sdk-py` pass.
2026-10-07 19:03:46 -04:00
Igor SoarezandGitHub 87f1c8eb9a fix(langgraph): stop astream_events dropping control/interrupts on v1/v2 (#9219)
### Problem

`Pregel.astream_events` declared `interrupt_before`, `interrupt_after`
and
`control` as keyword-only parameters, but forwarded them only on the
`version="v3"` branch. On async `version="v1"`/`"v2"` the values were
bound to
named parameters and never entered `**kwargs`, so they were silently
dropped
on the way to `astream` — no error, no effect:

- `request_drain()` on a caller-supplied `RunControl` did nothing; the
graph
  created its own control and ran to completion.
- Static interrupts passed as `astream_events(...,
interrupt_before=[...])`
  never fired.

This is a regression introduced by #7677 (first released in `1.2.0a3`).
Before that, `Pregel` did not override `astream_events`, and these
keywords
reached `astream` through `**kwargs` — langchain-core's v1 and v2 event
implementations both forward caller kwargs to `astream`
(`tracers/log_stream.py`, `tracers/event_stream.py`).

Downstream impact: langgraph-api passes run-level `interrupt_before` /
`interrupt_after` into `graph.astream_events(..., version="v2",
**kwargs)` for
runs with `stream_mode="events"` (`models/run.py`, `stream.py`), so
server
runs using that stream mode have silently dropped static interrupts
since
langgraph 1.2.0a3.

Sync `stream_events(version="v1"/"v2")` is unaffected: langchain-core
raises
`NotImplementedError` there, so there was no working sync path to break.

### Fix

Remove the three parameters from the public runtime implementations of
`stream_events` / `astream_events` (and from the explicit passing in
their v3
dispatch calls), so the values travel through `**kwargs` again:

- **v1/v2** recover the pre-#7677 passthrough. `astream` receives
exactly what
the caller passed — a supplied value, an explicit `None`, or nothing for
an
  omitted argument.
- **v3** is unchanged. The values bind on `_pregel_stream_v3` /
`_apregel_stream_v3`, which keep their named parameters and
since-inception
(#7519, `1.2.0a1`) explicit-`None` defaults: an omitted argument arrives
at
  `astream` as `None`, exactly as before.

What `astream` receives after this change:

| caller supplies | async v1/v2 | v3 (sync and async) |
|---|---|---|
| nothing | argument absent | explicit `None` |
| explicit `None` | `None` | `None` |
| a value | the value | the value |

The typed `version="v3"` `@overload` stubs are untouched, so v3 call
sites
keep their static types (invalid values still fail `ty` there, same as
on
`main`). `RemoteGraph` and the v3-only `transformers` parameter are
untouched.

Complexity: net −24 lines in `main.py` with no branches, sentinels or
wrappers added. The public capture-and-drop pattern that caused the bug
is
gone; the two private helpers each have a single call path and forward
unconditionally, so they cannot drop anything.

Docstrings now describe the three parameters as honored on every async
version (type-checked only on the v3 overloads), and no longer promise
synchronous v1/v2 event streaming, which langchain-core does not
implement.

### Compatibility notes

- The three parameters were keyword-only, so no caller can break;
keyword
  callers bind through `**kwargs` identically.
- The names leave the runtime signatures (`inspect.signature`), while
the v3
  overloads keep the typing.
- v3 is unchanged: `_pregel_stream_v3`/`_apregel_stream_v3` still
default all
  three to `None` and pass them explicitly, so an override's non-`None`
default never applied on v3 and still doesn't. The only behavior change
beyond restoring the pre-#7677 passthrough is on v1/v2 with an explicit
  `None`: since 1.2.0a3 the named-parameter capture dropped it, so an
  override's non-`None` default was silently applied instead; now the
explicit `None` reaches `astream`, as it did before 1.2.0 and as it does
on
  v3.

### Testing

New tests in `tests/test_stream_events_v3_kwarg_forwarding.py`:

- `interrupt_before` / `interrupt_after` / pre-drained `control`
parametrized
  over v1/v2/v3 (12 of them fail on unpatched `main`).
- Sync v3 static interrupts.
- Mid-run drain: a node calls `request_drain()`; asserts `GraphDrained`
  propagates, the caller's own `RunControl` was used, and the checkpoint
  keeps the pending step.
- Recording tests pin, for all three names and on both the async and
sync v3
paths, exactly what `(a)stream` receives: supplied values (with
`control`
  identity), explicit `None`, and absence for omitted arguments.

Verified by mutation: replacing the implementation with each rejected
alternative (unpatched parent; injecting `None` for omitted kwargs on
v1/v2;
dropping explicit `None` on v1/v2; kwargs-only private helpers) makes
the
corresponding tests fail.

Suites: 246 passed on the four adjacent streaming test files; 906 passed
/
1 skipped across every test file calling `(a)stream_events` plus
`test_runtime.py`. `ruff check` / `format --check` clean; `ty check
langgraph`
clean.

Not verifiable locally (CI please): Python 3.10 (the new tests carry no
version skip), minimum supported langchain-core, and a live
langgraph-api
server run.

### Release note

> Fixed a regression since 1.2.0a3: `Pregel.astream_events` silently
dropped
> `interrupt_before`, `interrupt_after` and `control` for
> `version="v1"`/`"v2"`. Static interrupts and `RunControl` drains now
work on
> every async version. Server runs using `stream_mode="events"` were
affected
> and get their static interrupts back.
2026-10-07 12:26:50 -04:00
gethin-langchainandGitHub 736a18eaab release(cli): 0.4.33 (#9227)
Bumping the CLI to 0.4.33 to cut a release including #9221 (deploy
listeners list) and #9222 (--image-uri).
cli==0.4.33
2026-10-07 09:19:34 -04:00
gethin-langchainandGitHub ec4f8535f8 feat(cli): add --image-uri to deploy an already-pushed image (#9222)
## Summary

`--push-to` always builds (or retags a local `--image`) and pushes, even
when the image already exists at the destination. That breaks CI/CD
pipelines where the build/push step and the deploy step run in separate
jobs: the deploy job has no local copy of the image to retag, and
`--image` requires one (it runs `docker image inspect`, which needs the
image present in the local Docker daemon).

This adds `--image-uri`, which takes a full image reference already in a
registry and deploys it directly via `source_revision_config.image_uri`,
with no local Docker involvement at all: no inspect, no build, no tag,
no push. It gets the same placement behavior as `--push-to`
(`--listener-id`/`--k8s-namespace`, or auto-selecting the sole listener)
and the same update-in-place semantics, since both produce an
`external_docker` deployment and are interchangeable on the same
deployment.

`--image-uri` requires a digest (`repo@sha256:...`) and rejects
empty/blank input. `--push-to` always resolves to a digest after
pushing; `--image-uri` has no push step to resolve one from, so a
mutable tag (or an unvalidated empty string) could let Kubernetes
silently keep running a previously cached image while the CLI reports
success.

Implementation: `CustomerRegistrySource`'s image-acquisition step is
split into two variants, `BuildAndPush` (the existing
`--push-to`/`--image` flow, unchanged behavior) and `PublishedImage`
(the new flag), so create/update/placement logic stays shared. Also
reworded `_ensure_customer_registry_source`'s error, which previously
mentioned only `--push-to` even though it's reachable from `--image-uri`
too.

## Test plan

- [x] `make format && make lint` clean in `libs/cli`
- [x] Unit tests in `test_deploy_helpers.py` for `_select_source`
selecting `PublishedImage` (by digest, trimmed), requiring no local
Docker, carrying placement, and the mutual-exclusivity + validation
errors (`--push-to`, `--image`, `--tag`, `--remote`, empty/blank input,
missing digest)
- [x] CLI-level tests in `test_deploy_command.py`: create and update an
external deployment via `--image-uri` with zero Docker calls, listener
auto-placement, rejecting a non-external existing deployment (now
mentioning both flags), and the conflicting-flag cases end to end
- [x] Full `libs/cli` suite: 524 passed, no regressions
2026-10-07 13:32:46 +01:00
gethin-langchainandGitHub ce14d33687 feat(cli): add 'langgraph deploy listeners list' (#9221)
## Summary

Originally this auto-selected a workspace's sole listener for
self-hosted/hybrid control planes the same way #9056 already does for
Cloud. Per review, that's reverted: in self-hosted environments, leaving
placement blank is the deliberate signal to deploy to the bundled
operator, not an unresolved default. Auto-selecting a sole listener
there would silently take that option away from anyone who has both a
bundled operator and one listener configured, with no way to get it
back.

The actual need behind this was simpler: a way to find a listener's id
without hardcoding it, so it can be passed to `--listener-id`
explicitly. `HostBackendClient.list_listeners()` already existed and is
used internally for placement resolution, but had no CLI surface of its
own.

This adds `langgraph deploy listeners list`, mirroring the existing
`deploy list` / `deploy revisions list` pattern, to look up a
workspace's listeners and their namespaces. No change to default
placement behavior.

## Test plan

- [x] `make format && make lint` clean in `libs/cli`
- [x] `format_listeners_table` unit test in `test_util.py`
- [x] CLI-level tests for `deploy listeners list` (with and without
results) in `test_cli.py`
- [x] Full `libs/cli` suite: 508 passed, no regressions
2026-10-07 13:32:26 +01:00