Compare commits

..
Author SHA1 Message Date
Sydney RunkleandGitHub 73cebea3c2 release: langgraph + prebuilt (#6875) 2026-02-19 13:12:01 -05:00
b73b2d19eb fix: inject ToolRuntime for dynamically registered tools (#6874)
Fixes https://github.com/langchain-ai/langchain/issues/35305

Co-authored-by: Shivangi Sharma <shivangi.sharma7004@gmail.com>
2026-02-19 17:39:57 +00:00
ca26805b5f fix: sequential interrupt handling w/ functional API (#6863)
In the original proposed fix
https://github.com/langchain-ai/langgraph/pull/6863, we were guarding
this specific case by only checking for null resume in the scratchpad.

But I noticed the tests passed on main for the sync case, indicating an
inconsistency between the two paths.

Seems like we were making a redundant put_writes call when replaying the
async tasks

---------

Co-authored-by: William FH <13333726+hinthornw@users.noreply.github.com>
2026-02-19 07:24:18 -08:00
5ac837d7cd feat(sdk-py): improve store auth type safety and docstrings (#6867)
## Summary
- Add `_StoreActionOn` class with action-specific decorator properties
(`.put`, `.get`, `.search`, `.delete`, `.list_namespaces`) to
`_StoreOn`, enabling `@auth.on.store.put` etc. which was documented but
not implemented
- Update docstring examples to show namespace-rewriting pattern as the
canonical store auth approach
- Fix `AuthContext.action` docstring: add missing `search` and `delete`
store actions
- Fix typo in `StoreSearch.query` docstring
- Add auth-handler-aware docstrings to all store TypedDicts

## Test plan
- [x] `make format && make lint` passes in `libs/sdk-py`
- [] Verify `@auth.on.store.put` decorator works at runtime

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 07:16:26 -08:00
Lauren Hirata SinghandGitHub c4f5861166 chore(docs): Add new redirects file(s) so we can update/add (#6778)
Adds redirects for all old LangGraph docs URLs to docs.langchain.com
using meta refresh and GitHub Pages
2026-02-18 14:35:38 -05:00
Parker J. RuleandGitHub 172238b2d5 fix(sdk-py): allow reset of config/context in assistants update (#6862)
This distinguishes an empty `config`/`context` (`{}`) from a null
`config`/`context`, and therefore allows resetting these fields.

(Easiest to test this E2E on the server side; will create a separate PR
for that.)
2026-02-18 18:48:07 +00:00
William FHandGitHub 095da17833 chore: state_updated_at sort by (#6857) 2026-02-18 10:41:23 -08:00
John KennedyandGitHub e931c68669 fix: actual fix for workflow (#6854)
Another attempt at fixing `_integration_test.yml`
2026-02-17 11:31:08 -08:00
John KennedyandGitHub 666c224c2d chore: bump orjson (#6852)
The orjson.dumps function in orjson thru 3.11.4 does not limit recursion
for deeply nested JSON documents.
2026-02-17 10:30:58 -08:00
William FHandGitHub 21a6f41e0a chore: add testpypi index (#6853) 2026-02-17 10:24:39 -08:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>John Kennedy
acdf85aba6 chore(deps): bump langgraph-sdk from 0.3.5 to 0.3.6 in /libs/cli in the all-dependencies group (#6851)
Bumps the all-dependencies group in /libs/cli with 1 update:
[langgraph-sdk](https://github.com/langchain-ai/langgraph).

Updates `langgraph-sdk` from 0.3.5 to 0.3.6
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/langchain-ai/langgraph/releases">langgraph-sdk's
releases</a>.</em></p>
<blockquote>
<h2>cli==0.3.6</h2>
<p>Changes since cli==0.3.5</p>
<ul>
<li>add api-version option</li>
<li>chore(langgraph): bump api version and prep for v0.6 alpha (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/5559">#5559</a>)</li>
<li>feat(langgraph): new context api (replacing
<code>config['configurable']</code> and <code>config_schema</code>) (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/5243">#5243</a>)</li>
<li>langgraph[change]: solidify public/private differentiations (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/5252">#5252</a>)</li>
</ul>
<h2>langgraph-sdk==0.3.6</h2>
<p>Changes since sdk==0.3.5</p>
<ul>
<li>release(sdk-py): 0.3.6 (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/6805">#6805</a>)</li>
<li>chore: update to add prune method (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/6804">#6804</a>)</li>
<li>chore: Re-organize client files. (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/6787">#6787</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/ca8d92421a9832620c071435807ca6dd14449fad"><code>ca8d924</code></a>
langgraph: release 0.3.6 (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/3775">#3775</a>)</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/7aa9d3fd003545c1df9b9d2690cf4863ec6adefb"><code>7aa9d3f</code></a>
langgraph: use input schema from conditional edge (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/2516">#2516</a>)</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/3a4af1e5737eeac1d292cefb5325d1114c9e0787"><code>3a4af1e</code></a>
chore(deps): bump axios from 1.7.7 to 1.8.2 in /libs/sdk-js (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/3740">#3740</a>)</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/37344124e17453c712207624c045c646f8827eb3"><code>3734412</code></a>
Fix updated_at timestamp loading (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/3767">#3767</a>)</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/d0f4db6ddd624c4a8be0164fc2af319c56836820"><code>d0f4db6</code></a>
feat(sdk-js): use fetchClient from <code>client</code> in gen ui (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/3761">#3761</a>)</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/a9800aab876f78017fd633ffcbb50236d04d54bd"><code>a9800aa</code></a>
checkpoint-sqlite: release 2.0.6 (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/3763">#3763</a>)</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/9bf3fc2d0fa9c67e1a2725fa9f8012cd31146c11"><code>9bf3fc2</code></a>
checkpoint-sqlite: commit transactions in AsyncSqliteSaver.aput_writes
(<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/3762">#3762</a>)</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/a6e4bd93ff930ce60e5103c121ec9440db7954a3"><code>a6e4bd9</code></a>
Bump to 0.0.52</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/0e9c41f48059aa37e98f342720982ec8bfd5ae41"><code>0e9c41f</code></a>
feat(sdk-js): use fetchClient from <code>client</code> in gen ui</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/3808302309f1ccc6951148367f597df5fabf5764"><code>3808302</code></a>
Bump to 0.0.51</li>
<li>Additional commits viewable in <a
href="https://github.com/langchain-ai/langgraph/compare/0.3.5...0.3.6">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=langgraph-sdk&package-manager=uv&previous-version=0.3.5&new-version=0.3.6)](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 <65985482+jkennedyvz@users.noreply.github.com>
2026-02-17 10:14:06 -08:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>John Kennedy
9b18243fa6 chore(deps): bump the all-dependencies group in /libs/checkpoint with 2 updates (#6850)
Bumps the all-dependencies group in /libs/checkpoint with 2 updates:
[langchain-core](https://github.com/langchain-ai/langchain) and
[redis](https://github.com/redis/redis-py).

Updates `langchain-core` from 1.2.12 to 1.2.13
<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.2.13</h2>
<p>Changes since langchain-core==1.2.12</p>
<p>release(core): 1.2.13 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35230">#35230</a>)
docs(core): expanded <code>get_lc_namespace</code> docstring (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35229">#35229</a>)
feat(openrouter): add <code>langchain-openrouter</code> provider package
(<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35211">#35211</a>)
style: bump ruff version to 0.15 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35042">#35042</a>)</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/langchain-ai/langchain/commit/b026fd605b0cc150f943e6ea8a8aed45e23373e5"><code>b026fd6</code></a>
release(core): 1.2.13 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35230">#35230</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/1573757b3bf53bab48b7ff3804707adf3a173e96"><code>1573757</code></a>
docs(core): expanded <code>get_lc_namespace</code> docstring (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35229">#35229</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/f9fd7be695c70f33cb6cbeb4cca1547ee225c5b1"><code>f9fd7be</code></a>
feat(openrouter): add <code>langchain-openrouter</code> provider package
(<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35211">#35211</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/b97c629f9ade098236aa56d861a21706a9830f54"><code>b97c629</code></a>
style: bump ruff version to 0.15 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35042">#35042</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/1493b4c5eed3b6c08358a5ce5d890bc8b52b4874"><code>1493b4c</code></a>
fix: Server-Side Request Forgery (SSRF) in
HTMLHeaderTextSplitter.split_text_...</li>
<li>See full diff in <a
href="https://github.com/langchain-ai/langchain/compare/langchain-core==1.2.12...langchain-core==1.2.13">compare
view</a></li>
</ul>
</details>
<br />

Updates `redis` from 7.1.1 to 7.2.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/redis/redis-py/releases">redis's
releases</a>.</em></p>
<blockquote>
<h2>7.2.0</h2>
<h1>Changes</h1>
<p><strong>Redis 8.6 Support</strong>
Added support for Redis 8.6, including new commands and features for
streams idempotent production and HOTKEYS.</p>
<p><strong>Smart Client Handoff (Maintenance Notifications) for Cluster
note: Pending a Redis Enterprise version release</strong></p>
<p>This release introduces comprehensive support for Redis Enterprise
Cluster maintenance notifications via SMIGRATING/SMIGRATED push
notifications. The client now automatically handles slot migrations
by:</p>
<p>Relaxing timeouts during migration (SMIGRATING) to prevent false
failures
Triggering cluster state reloads upon completion (SMIGRATED)
Enabling seamless operations during Redis Enterprise maintenance
windows</p>
<p><strong>OpenTelemetry Native Metrics Support</strong>
Added comprehensive OpenTelemetry metrics support following the <a
href="https://opentelemetry.io/docs/specs/semconv/database/database-metrics/">OpenTelemetry
Database Client Semantic Conventions</a>.
Metric groups include:</p>
<ul>
<li>Command metrics: Operation duration with retry tracking</li>
<li>Connection basic: Connection count and creation time</li>
<li>Resiliency: Errors, handoffs, timeout relaxation</li>
<li>Connection advanced: Wait time and use time</li>
<li>Pubsub metrics: Published and received messages</li>
<li>Stream metrics: Processing duration and maintenance
notifications</li>
</ul>
<h2>🚀 New Features</h2>
<ul>
<li>Added OTel instrumentation and metrics export for sync client (<a
href="https://redirect.github.com/redis/redis-py/issues/3954">#3954</a>)</li>
<li>Add maintenance notifications support for OSS API cluster clients
(<a
href="https://redirect.github.com/redis/redis-py/issues/3946">#3946</a>)</li>
<li>Adding hotkeys commands support. (<a
href="https://redirect.github.com/redis/redis-py/issues/3924">#3924</a>)</li>
<li>Adds support for the new Idempotent Producers feature in Redis 8.6
(<a
href="https://redirect.github.com/redis/redis-py/issues/3926">#3926</a>)</li>
<li>Adding support for vrange command. (<a
href="https://redirect.github.com/redis/redis-py/issues/3927">#3927</a>)</li>
<li>Added a local digest command to the client to execute the XXH3
locally… (<a
href="https://redirect.github.com/redis/redis-py/issues/3884">#3884</a>)</li>
<li>Add DriverInfo class for upstream driver tracking (<a
href="https://redirect.github.com/redis/redis-py/issues/3880">#3880</a>)</li>
<li>Add ssl_password support to async Redis client (<a
href="https://redirect.github.com/redis/redis-py/issues/3878">#3878</a>)</li>
<li>Add ssl_ca_path support to async Redis client (<a
href="https://redirect.github.com/redis/redis-py/issues/3879">#3879</a>)</li>
</ul>
<h2>⚠️ Deprecations</h2>
<ul>
<li>Adding special handling of client_tracking_on and
client_tracking_off for cluster clients. Marking those two functions as
deprecated for cluster - embedded client-side caching feature should be
used instead. (<a
href="https://redirect.github.com/redis/redis-py/issues/3858">#3858</a>)</li>
</ul>
<h2>🐛 Bug Fixes</h2>
<ul>
<li>Fix handling of circular MOVED redirects in cluster slot mapping (<a
href="https://redirect.github.com/redis/redis-py/issues/3899">#3899</a>)</li>
<li>fix(asyncio): prevent deadlock when Lock.release() is cancelled (<a
href="https://redirect.github.com/redis/redis-py/issues/3900">#3900</a>)</li>
<li>Fix unrecoverable connection state (<a
href="https://redirect.github.com/redis/redis-py/issues/3905">#3905</a>)</li>
<li>Fixed potential race condition between call_later() and
run_forever() (<a
href="https://redirect.github.com/redis/redis-py/issues/3897">#3897</a>)</li>
<li>Fix RuntimeError in ClusterPubSub sharded message generator (<a
href="https://redirect.github.com/redis/redis-py/issues/3889">#3889</a>)</li>
<li>Fix async connection pool lock contention during connection
establishment (<a
href="https://redirect.github.com/redis/redis-py/issues/3885">#3885</a>)</li>
<li>Fix PubSub client health check handling for sync client
implementation (<a
href="https://redirect.github.com/redis/redis-py/issues/3870">#3870</a>)</li>
<li>Adding retries for the overall connect - socket connect + handshake.
Fix for pubsub reconnect issues. (<a
href="https://redirect.github.com/redis/redis-py/issues/3863">#3863</a>)</li>
<li>Adding special handling of client_tracking_on and
client_tracking_off for cluster clients. Marking those two functions as
deprecated for cluster - embedded client-side caching feature should be
used instead. (<a
href="https://redirect.github.com/redis/redis-py/issues/3858">#3858</a>)</li>
<li><a
href="https://redirect.github.com/redis/redis-py/issues/3618">#3618</a>
Fix client-side cache invalidation for mixed str and bytes Redis keys
(<a
href="https://redirect.github.com/redis/redis-py/issues/3766">#3766</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/redis/redis-py/commit/915e8b41d2bd3cb053f82dd4faa72a0ca55f2ce2"><code>915e8b4</code></a>
Updating server version to 7.2.0</li>
<li><a
href="https://github.com/redis/redis-py/commit/b41e47d76911563232e09a95c05ccc09c010def6"><code>b41e47d</code></a>
Added OTel instrumentation and metrics export for sync client (<a
href="https://redirect.github.com/redis/redis-py/issues/3954">#3954</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/9c8ad166a83929656fd00d52f65072890f7b7f1e"><code>9c8ad16</code></a>
Fix type hints for spop and srandmember methods (<a
href="https://redirect.github.com/redis/redis-py/issues/3943">#3943</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/34c73c783ec2e8ade103ad2d324630cff6a26d58"><code>34c73c7</code></a>
Add maintenance notifications support for OSS API cluster clients (<a
href="https://redirect.github.com/redis/redis-py/issues/3946">#3946</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/24974feafdcd1a03bc2254fbdfd028316106ab0e"><code>24974fe</code></a>
Renamed initial health check policies and unhealthy database argument
(<a
href="https://redirect.github.com/redis/redis-py/issues/3949">#3949</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/3d6b571e3df69c1ab0060e7a53fea7ac0c50a725"><code>3d6b571</code></a>
Reorganize pipeline actions (<a
href="https://redirect.github.com/redis/redis-py/issues/3951">#3951</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/877d7a2987ca388489fbe221df806e5cc9cc51a9"><code>877d7a2</code></a>
Disabled SCH in MultiDBClient underlying clients (<a
href="https://redirect.github.com/redis/redis-py/issues/3938">#3938</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/9ac9ee6ce13f4b292b1d2d3db81ef0f30afe29b4"><code>9ac9ee6</code></a>
Adding hotkeys commands support. (<a
href="https://redirect.github.com/redis/redis-py/issues/3924">#3924</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/65623b7fad9833b5281d6ce7f44f62f942621234"><code>65623b7</code></a>
Extending the tests to validate more supported scorers for hybrid
search. Add...</li>
<li><a
href="https://github.com/redis/redis-py/commit/2b2f2cf5416862d15399f422c3658c0e1d671a10"><code>2b2f2cf</code></a>
Adds support for the new Idempotent Producers feature in Redis 8.6 (<a
href="https://redirect.github.com/redis/redis-py/issues/3926">#3926</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/redis/redis-py/compare/v7.1.1...v7.2.0">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 <65985482+jkennedyvz@users.noreply.github.com>
2026-02-17 10:13:43 -08:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>John Kennedy
0225b998af chore(deps): bump the all-dependencies group in /libs/cli/js-examples with 2 updates (#6848)
Bumps the all-dependencies group in /libs/cli/js-examples with 2
updates:
[@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin)
and
[@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser).

Updates `@typescript-eslint/eslint-plugin` from 8.55.0 to 8.56.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/typescript-eslint/typescript-eslint/releases"><code>@​typescript-eslint/eslint-plugin</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v8.56.0</h2>
<h2>8.56.0 (2026-02-16)</h2>
<h3>🚀 Features</h3>
<ul>
<li>support ESLint v10 (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12057">#12057</a>)</li>
</ul>
<h3>🩹 Fixes</h3>
<ul>
<li>use parser options from context.languageOptions (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12043">#12043</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Brad Zacher <a
href="https://github.com/bradzacher"><code>@​bradzacher</code></a></li>
<li>fnx <a
href="https://github.com/DMartens"><code>@​DMartens</code></a></li>
<li>Joshua Chen</li>
</ul>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.56.0">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md"><code>@​typescript-eslint/eslint-plugin</code>'s
changelog</a>.</em></p>
<blockquote>
<h2>8.56.0 (2026-02-16)</h2>
<h3>🚀 Features</h3>
<ul>
<li>support ESLint v10 (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12057">#12057</a>)</li>
</ul>
<h3>🩹 Fixes</h3>
<ul>
<li>use parser options from context.languageOptions (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12043">#12043</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Brad Zacher <a
href="https://github.com/bradzacher"><code>@​bradzacher</code></a></li>
<li>fnx <a
href="https://github.com/DMartens"><code>@​DMartens</code></a></li>
<li>Joshua Chen</li>
</ul>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.56.0">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/8b8b68f200a48ee9d6f7be8670e964629375196c"><code>8b8b68f</code></a>
chore(release): publish 8.56.0</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/68a074fb61a10c3627f09678859fb4d42a3b88f5"><code>68a074f</code></a>
feat: support ESLint v10 (<a
href="https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin/issues/12057">#12057</a>)</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/c0a359df266e2ff4903eff2fdfa6c8ea30b84bca"><code>c0a359d</code></a>
fix: use parser options from context.languageOptions (<a
href="https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin/issues/12043">#12043</a>)</li>
<li>See full diff in <a
href="https://github.com/typescript-eslint/typescript-eslint/commits/v8.56.0/packages/eslint-plugin">compare
view</a></li>
</ul>
</details>
<br />

Updates `@typescript-eslint/parser` from 8.55.0 to 8.56.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/typescript-eslint/typescript-eslint/releases"><code>@​typescript-eslint/parser</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v8.56.0</h2>
<h2>8.56.0 (2026-02-16)</h2>
<h3>🚀 Features</h3>
<ul>
<li>support ESLint v10 (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12057">#12057</a>)</li>
</ul>
<h3>🩹 Fixes</h3>
<ul>
<li>use parser options from context.languageOptions (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12043">#12043</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Brad Zacher <a
href="https://github.com/bradzacher"><code>@​bradzacher</code></a></li>
<li>fnx <a
href="https://github.com/DMartens"><code>@​DMartens</code></a></li>
<li>Joshua Chen</li>
</ul>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.56.0">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md"><code>@​typescript-eslint/parser</code>'s
changelog</a>.</em></p>
<blockquote>
<h2>8.56.0 (2026-02-16)</h2>
<h3>🚀 Features</h3>
<ul>
<li>support ESLint v10 (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12057">#12057</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Brad Zacher <a
href="https://github.com/bradzacher"><code>@​bradzacher</code></a></li>
<li>Joshua Chen</li>
</ul>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.56.0">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/8b8b68f200a48ee9d6f7be8670e964629375196c"><code>8b8b68f</code></a>
chore(release): publish 8.56.0</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/68a074fb61a10c3627f09678859fb4d42a3b88f5"><code>68a074f</code></a>
feat: support ESLint v10 (<a
href="https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser/issues/12057">#12057</a>)</li>
<li>See full diff in <a
href="https://github.com/typescript-eslint/typescript-eslint/commits/v8.56.0/packages/parser">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 <65985482+jkennedyvz@users.noreply.github.com>
2026-02-17 10:12:44 -08:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>John Kennedy
bec122d4a2 chore(deps): bump langchain-core from 1.2.12 to 1.2.13 in /libs/prebuilt in the all-dependencies group (#6849)
Bumps the all-dependencies group in /libs/prebuilt with 1 update:
[langchain-core](https://github.com/langchain-ai/langchain).

Updates `langchain-core` from 1.2.12 to 1.2.13
<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.2.13</h2>
<p>Changes since langchain-core==1.2.12</p>
<p>release(core): 1.2.13 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35230">#35230</a>)
docs(core): expanded <code>get_lc_namespace</code> docstring (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35229">#35229</a>)
feat(openrouter): add <code>langchain-openrouter</code> provider package
(<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35211">#35211</a>)
style: bump ruff version to 0.15 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35042">#35042</a>)</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/langchain-ai/langchain/commit/b026fd605b0cc150f943e6ea8a8aed45e23373e5"><code>b026fd6</code></a>
release(core): 1.2.13 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35230">#35230</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/1573757b3bf53bab48b7ff3804707adf3a173e96"><code>1573757</code></a>
docs(core): expanded <code>get_lc_namespace</code> docstring (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35229">#35229</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/f9fd7be695c70f33cb6cbeb4cca1547ee225c5b1"><code>f9fd7be</code></a>
feat(openrouter): add <code>langchain-openrouter</code> provider package
(<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35211">#35211</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/b97c629f9ade098236aa56d861a21706a9830f54"><code>b97c629</code></a>
style: bump ruff version to 0.15 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35042">#35042</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/1493b4c5eed3b6c08358a5ce5d890bc8b52b4874"><code>1493b4c</code></a>
fix: Server-Side Request Forgery (SSRF) in
HTMLHeaderTextSplitter.split_text_...</li>
<li>See full diff in <a
href="https://github.com/langchain-ai/langchain/compare/langchain-core==1.2.12...langchain-core==1.2.13">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=langchain-core&package-manager=uv&previous-version=1.2.12&new-version=1.2.13)](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 <65985482+jkennedyvz@users.noreply.github.com>
2026-02-17 10:11:53 -08:00
John KennedyandGitHub 2b416f6f47 fix: secret ref (#6847) 2026-02-17 09:50:23 -08:00
William FHandGitHub 9b9de5bd16 chore: conformance testing (#6842)
Add some conformance tests for checkpointer implementations. Includes
additona methods that will be useful if you want to integarte in the
agent server.
2026-02-17 09:49:22 -08:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
3b04ee4677 chore(deps): bump langchain-core from 1.2.7 to 1.2.11 in /libs/checkpoint-postgres (#6831)
Bumps [langchain-core](https://github.com/langchain-ai/langchain) from
1.2.7 to 1.2.11.
<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.2.11</h2>
<p>Changes since langchain-core==1.2.10</p>
<p>release(core): 1.2.11 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35144">#35144</a>)
fix(openai): sanitize urls when counting tokens in images (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35143">#35143</a>)
chore(core): clean up docstring mismatch and redundant logic in
langchain-core (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35064">#35064</a>)
fix(core): replace bare except with Exception in tracer (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35138">#35138</a>)</p>
<h2>langchain-core==1.2.10</h2>
<p>Changes since langchain-core==1.2.9</p>
<p>release(core): 1.2.10 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35136">#35136</a>)
chore(deps): bump the langchain-deps group across 3 directories with 40
updates (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35129">#35129</a>)
chore(deps): bump the langchain-deps group across 3 directories with 11
updates (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35121">#35121</a>)
feat(core): add ContextOverflowError, raise in anthropic and openai (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35099">#35099</a>)
feat(model-profiles): add <code>text_inputs</code> and
<code>text_outputs</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35084">#35084</a>)
feat(core): count tokens from tool schemas in
<code>count_tokens_approximately</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35098">#35098</a>)
docs(core): add missing <code>name</code> docstring for
<code>RunnableSerializable</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35088">#35088</a>)</p>
<h2>langchain-core==1.2.9</h2>
<p>Changes since langchain-core==1.2.8</p>
<p>release(core): 1.2.9 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35025">#35025</a>)
fix(core): adjust cap when scaling approximate token counts (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35017">#35017</a>)
revert: precompile hex color regex pattern at module level (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35016">#35016</a>)
chore: add <code>make type</code> target (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35015">#35015</a>)
revert: &quot;chore: add typing target in <code>Makefile</code>&quot;
(<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35013">#35013</a>)
chore: add typing target in <code>Makefile</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35012">#35012</a>)
fix(core): apply cap when scaling approximate token counts (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35005">#35005</a>)
feat(core): allow scaling by reported usage when counting tokens
approximately (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34996">#34996</a>)
test(core): increase <code>delta_time</code> for flaky test (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34982">#34982</a>)
chore: enrich <code>pyproject.toml</code> files (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34980">#34980</a>)</p>
<h2>langchain-core==1.2.8</h2>
<p>Changes since langchain-core==1.2.7</p>
<p>release(core): 1.2.8 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34975">#34975</a>)
docs(core): add examples for <code>pretty_repr</code>,
<code>pretty_print</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34968">#34968</a>)
docs(core): use proper admonition for <code>get_buffer_string</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34967">#34967</a>)
docs: add usage examples to core classes (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34841">#34841</a>)
chore(core): fix docstring format (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34966">#34966</a>)
chore(deps): bump the uv group across 20 directories with 3 updates (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34941">#34941</a>)
docs: add example to create_message function docstring (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34851">#34851</a>)
docs(core): clarify <a
href="https://github.com/tool"><code>@​tool</code></a> decorator
argument and return type requirements (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34860">#34860</a>)
fix(core): fix nested mustache variable extraction and update docs (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34872">#34872</a>)
fix(core): allow base model annotations for empty model (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34932">#34932</a>)
chore: upgrade urllib3 to 2.6.3 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34940">#34940</a>)
fix(core): prevent crash in ParrotFakeChatModel when messages list is
empty (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34943">#34943</a>)
fix(core): google docstring parsing with no arguments/reserved arguments
(<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34861">#34861</a>)
test(core): add tests for approximate token counting with multimodal
messages (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34898">#34898</a>)</p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/langchain-ai/langchain/commit/524e1dab5e7c8229bd78be3c13ab38ac93a6216b"><code>524e1da</code></a>
release(core): 1.2.11 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35144">#35144</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/2b4b1dc29a833d4053deba4c2b77a3848c834565"><code>2b4b1dc</code></a>
fix(openai): sanitize urls when counting tokens in images (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35143">#35143</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/0493b276e0be31d4f48d9d0ba5fcbce7fdded38f"><code>0493b27</code></a>
fix(anthropic): support effort=&quot;max&quot; and remove beta headers
(<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35141">#35141</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/a5f22e7cb18a05ed057028797a7d0d79cd509b0d"><code>a5f22e7</code></a>
chore(core): clean up docstring mismatch and redundant logic in
langchain-cor...</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/97ee14c179f703473a6ec6ee24179ea756a5698f"><code>97ee14c</code></a>
fix(core): replace bare except with Exception in tracer (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35138">#35138</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/990e8076e1d61a0c8ced4d83607685bd71e23687"><code>990e807</code></a>
release(standard-tests): release 1.1.5 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35139">#35139</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/74dffca3d89effdb62da567d1ff6d160c9ad5354"><code>74dffca</code></a>
release(langchain): 1.2.10 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35137">#35137</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/f41e0493336698e9a3e25e6e238786dfc8af91ba"><code>f41e049</code></a>
release(core): 1.2.10 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35136">#35136</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/de05838fca46eb6c2f67064da3a59f5e84818e9a"><code>de05838</code></a>
chore(deps): bump the langchain-deps group across 3 directories with 40
updat...</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/d6e86aa748ae173857732ee1f7114a06ff8f4231"><code>d6e86aa</code></a>
chore(deps): bump the other-deps group across 3 directories with 12
updates (...</li>
<li>Additional commits viewable in <a
href="https://github.com/langchain-ai/langchain/compare/langchain-core==1.2.7...langchain-core==1.2.11">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=langchain-core&package-manager=uv&previous-version=1.2.7&new-version=1.2.11)](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-02-17 09:37:04 -08:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>John Kennedy
e80b3136ad chore(deps): bump langchain-core from 1.2.7 to 1.2.11 in /libs/cli (#6836)
Bumps [langchain-core](https://github.com/langchain-ai/langchain) from
1.2.7 to 1.2.11.
<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.2.11</h2>
<p>Changes since langchain-core==1.2.10</p>
<p>release(core): 1.2.11 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35144">#35144</a>)
fix(openai): sanitize urls when counting tokens in images (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35143">#35143</a>)
chore(core): clean up docstring mismatch and redundant logic in
langchain-core (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35064">#35064</a>)
fix(core): replace bare except with Exception in tracer (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35138">#35138</a>)</p>
<h2>langchain-core==1.2.10</h2>
<p>Changes since langchain-core==1.2.9</p>
<p>release(core): 1.2.10 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35136">#35136</a>)
chore(deps): bump the langchain-deps group across 3 directories with 40
updates (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35129">#35129</a>)
chore(deps): bump the langchain-deps group across 3 directories with 11
updates (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35121">#35121</a>)
feat(core): add ContextOverflowError, raise in anthropic and openai (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35099">#35099</a>)
feat(model-profiles): add <code>text_inputs</code> and
<code>text_outputs</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35084">#35084</a>)
feat(core): count tokens from tool schemas in
<code>count_tokens_approximately</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35098">#35098</a>)
docs(core): add missing <code>name</code> docstring for
<code>RunnableSerializable</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35088">#35088</a>)</p>
<h2>langchain-core==1.2.9</h2>
<p>Changes since langchain-core==1.2.8</p>
<p>release(core): 1.2.9 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35025">#35025</a>)
fix(core): adjust cap when scaling approximate token counts (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35017">#35017</a>)
revert: precompile hex color regex pattern at module level (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35016">#35016</a>)
chore: add <code>make type</code> target (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35015">#35015</a>)
revert: &quot;chore: add typing target in <code>Makefile</code>&quot;
(<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35013">#35013</a>)
chore: add typing target in <code>Makefile</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35012">#35012</a>)
fix(core): apply cap when scaling approximate token counts (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35005">#35005</a>)
feat(core): allow scaling by reported usage when counting tokens
approximately (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34996">#34996</a>)
test(core): increase <code>delta_time</code> for flaky test (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34982">#34982</a>)
chore: enrich <code>pyproject.toml</code> files (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34980">#34980</a>)</p>
<h2>langchain-core==1.2.8</h2>
<p>Changes since langchain-core==1.2.7</p>
<p>release(core): 1.2.8 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34975">#34975</a>)
docs(core): add examples for <code>pretty_repr</code>,
<code>pretty_print</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34968">#34968</a>)
docs(core): use proper admonition for <code>get_buffer_string</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34967">#34967</a>)
docs: add usage examples to core classes (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34841">#34841</a>)
chore(core): fix docstring format (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34966">#34966</a>)
chore(deps): bump the uv group across 20 directories with 3 updates (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34941">#34941</a>)
docs: add example to create_message function docstring (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34851">#34851</a>)
docs(core): clarify <a
href="https://github.com/tool"><code>@​tool</code></a> decorator
argument and return type requirements (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34860">#34860</a>)
fix(core): fix nested mustache variable extraction and update docs (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34872">#34872</a>)
fix(core): allow base model annotations for empty model (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34932">#34932</a>)
chore: upgrade urllib3 to 2.6.3 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34940">#34940</a>)
fix(core): prevent crash in ParrotFakeChatModel when messages list is
empty (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34943">#34943</a>)
fix(core): google docstring parsing with no arguments/reserved arguments
(<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34861">#34861</a>)
test(core): add tests for approximate token counting with multimodal
messages (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34898">#34898</a>)</p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/langchain-ai/langchain/commit/524e1dab5e7c8229bd78be3c13ab38ac93a6216b"><code>524e1da</code></a>
release(core): 1.2.11 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35144">#35144</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/2b4b1dc29a833d4053deba4c2b77a3848c834565"><code>2b4b1dc</code></a>
fix(openai): sanitize urls when counting tokens in images (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35143">#35143</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/0493b276e0be31d4f48d9d0ba5fcbce7fdded38f"><code>0493b27</code></a>
fix(anthropic): support effort=&quot;max&quot; and remove beta headers
(<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35141">#35141</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/a5f22e7cb18a05ed057028797a7d0d79cd509b0d"><code>a5f22e7</code></a>
chore(core): clean up docstring mismatch and redundant logic in
langchain-cor...</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/97ee14c179f703473a6ec6ee24179ea756a5698f"><code>97ee14c</code></a>
fix(core): replace bare except with Exception in tracer (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35138">#35138</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/990e8076e1d61a0c8ced4d83607685bd71e23687"><code>990e807</code></a>
release(standard-tests): release 1.1.5 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35139">#35139</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/74dffca3d89effdb62da567d1ff6d160c9ad5354"><code>74dffca</code></a>
release(langchain): 1.2.10 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35137">#35137</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/f41e0493336698e9a3e25e6e238786dfc8af91ba"><code>f41e049</code></a>
release(core): 1.2.10 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35136">#35136</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/de05838fca46eb6c2f67064da3a59f5e84818e9a"><code>de05838</code></a>
chore(deps): bump the langchain-deps group across 3 directories with 40
updat...</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/d6e86aa748ae173857732ee1f7114a06ff8f4231"><code>d6e86aa</code></a>
chore(deps): bump the other-deps group across 3 directories with 12
updates (...</li>
<li>Additional commits viewable in <a
href="https://github.com/langchain-ai/langchain/compare/langchain-core==1.2.7...langchain-core==1.2.11">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=langchain-core&package-manager=uv&previous-version=1.2.7&new-version=1.2.11)](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>
Co-authored-by: John Kennedy <65985482+jkennedyvz@users.noreply.github.com>
2026-02-17 09:29:50 -08:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>John Kennedy
4eb1766b58 chore(deps): bump the all-dependencies group in /libs/langgraph with 6 updates (#6815)
Bumps the all-dependencies group in /libs/langgraph with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [langchain-core](https://github.com/langchain-ai/langchain) | `1.2.7`
| `1.2.12` |
| [syrupy](https://github.com/syrupy-project/syrupy) | `5.0.0` | `5.1.0`
|
| [uvloop](https://github.com/MagicStack/uvloop) | `0.21.0beta1` |
`0.22.1` |
| [pyperf](https://github.com/psf/pyperf) | `2.9.0` | `2.10.0` |
| [redis](https://github.com/redis/redis-py) | `7.1.0` | `7.1.1` |
| [ruff](https://github.com/astral-sh/ruff) | `0.14.13` | `0.15.1` |

Updates `langchain-core` from 1.2.7 to 1.2.12
<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.2.12</h2>
<p>Changes since langchain-core==1.2.11</p>
<p>release(core): 1.2.12 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35192">#35192</a>)
fix(core): fix setting <code>ChatGeneration.text</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35191">#35191</a>)</p>
<h2>langchain-core==1.2.11</h2>
<p>Changes since langchain-core==1.2.10</p>
<p>release(core): 1.2.11 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35144">#35144</a>)
fix(openai): sanitize urls when counting tokens in images (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35143">#35143</a>)
chore(core): clean up docstring mismatch and redundant logic in
langchain-core (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35064">#35064</a>)
fix(core): replace bare except with Exception in tracer (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35138">#35138</a>)</p>
<h2>langchain-core==1.2.10</h2>
<p>Changes since langchain-core==1.2.9</p>
<p>release(core): 1.2.10 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35136">#35136</a>)
chore(deps): bump the langchain-deps group across 3 directories with 40
updates (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35129">#35129</a>)
chore(deps): bump the langchain-deps group across 3 directories with 11
updates (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35121">#35121</a>)
feat(core): add ContextOverflowError, raise in anthropic and openai (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35099">#35099</a>)
feat(model-profiles): add <code>text_inputs</code> and
<code>text_outputs</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35084">#35084</a>)
feat(core): count tokens from tool schemas in
<code>count_tokens_approximately</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35098">#35098</a>)
docs(core): add missing <code>name</code> docstring for
<code>RunnableSerializable</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35088">#35088</a>)</p>
<h2>langchain-core==1.2.9</h2>
<p>Changes since langchain-core==1.2.8</p>
<p>release(core): 1.2.9 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35025">#35025</a>)
fix(core): adjust cap when scaling approximate token counts (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35017">#35017</a>)
revert: precompile hex color regex pattern at module level (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35016">#35016</a>)
chore: add <code>make type</code> target (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35015">#35015</a>)
revert: &quot;chore: add typing target in <code>Makefile</code>&quot;
(<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35013">#35013</a>)
chore: add typing target in <code>Makefile</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35012">#35012</a>)
fix(core): apply cap when scaling approximate token counts (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35005">#35005</a>)
feat(core): allow scaling by reported usage when counting tokens
approximately (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34996">#34996</a>)
test(core): increase <code>delta_time</code> for flaky test (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34982">#34982</a>)
chore: enrich <code>pyproject.toml</code> files (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34980">#34980</a>)</p>
<h2>langchain-core==1.2.8</h2>
<p>Changes since langchain-core==1.2.7</p>
<p>release(core): 1.2.8 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34975">#34975</a>)
docs(core): add examples for <code>pretty_repr</code>,
<code>pretty_print</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34968">#34968</a>)
docs(core): use proper admonition for <code>get_buffer_string</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34967">#34967</a>)
docs: add usage examples to core classes (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34841">#34841</a>)
chore(core): fix docstring format (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34966">#34966</a>)
chore(deps): bump the uv group across 20 directories with 3 updates (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34941">#34941</a>)
docs: add example to create_message function docstring (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34851">#34851</a>)
docs(core): clarify <a
href="https://github.com/tool"><code>@​tool</code></a> decorator
argument and return type requirements (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34860">#34860</a>)</p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/langchain-ai/langchain/commit/b06716fb879f0d656ce4d1dad4a9710a61e8ec1e"><code>b06716f</code></a>
release(core): 1.2.12 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35192">#35192</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/16cabfa212782d03b00e08658fb3e74160a1dd45"><code>16cabfa</code></a>
fix(core): fix setting <code>ChatGeneration.text</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35191">#35191</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/8f859bd91f122b532689db199f69a6464a1bf7ef"><code>8f859bd</code></a>
release(huggingface): 1.2.1 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35182">#35182</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/19ddd42891514aba6d2c92cd32a915e7bb4b7b31"><code>19ddd42</code></a>
fix(ollama): raise error when clients are not initialized (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35185">#35185</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/a50d86c353bdf611bd0b908d5fc3d737086dba98"><code>a50d86c</code></a>
docs(langchain-classic): clarify MultiVectorRetriever usage (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35053">#35053</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/f89e30eb131d48c5354dd98c068a229b4c585f2d"><code>f89e30e</code></a>
chore(huggingface): version bump for huggingface-hub and transformers
deps (#...</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/6ac12b330a5c4912c37aa3bd888bc086d5d387f7"><code>6ac12b3</code></a>
chore: bump pillow from 11.3.0 to 12.1.1 in /libs/partners/openai (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35177">#35177</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/d41dedae978dfd4e4ee82d57fc1f0c530d827b90"><code>d41deda</code></a>
fix(langchain-classic): validate ensemble retriever weights (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35078">#35078</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/9d0bd8376cdd19dc19ac34d15a34dabe94361d8b"><code>9d0bd83</code></a>
chore: bump pillow from 11.3.0 to 12.1.1 in /libs/partners/perplexity
(<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35176">#35176</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/f22f5d5d673d2db5dc8a68991cdc063664c6f96b"><code>f22f5d5</code></a>
chore(deps): bump pillow from 11.3.0 to 12.1.1 in /libs/langchain (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35175">#35175</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/langchain-ai/langchain/compare/langchain-core==1.2.7...langchain-core==1.2.12">compare
view</a></li>
</ul>
</details>
<br />

Updates `syrupy` from 5.0.0 to 5.1.0
<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>v5.1.0</h2>
<h1><a
href="https://github.com/syrupy-project/syrupy/compare/v5.0.0...v5.1.0">5.1.0</a>
(2026-01-25)</h1>
<h3>Features</h3>
<ul>
<li>add serializer plugin system; plugins for data models (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1062">#1062</a>)
(<a
href="https://github.com/syrupy-project/syrupy/commit/df9bc8f6b3a222dde82167e10a2e6bb57456305a">df9bc8f</a>)</li>
</ul>
</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>
<h1><a
href="https://github.com/syrupy-project/syrupy/compare/v5.0.0...v5.1.0">5.1.0</a>
(2026-01-25)</h1>
<h3>Features</h3>
<ul>
<li>add serializer plugin system; plugins for data models (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1062">#1062</a>)
(<a
href="https://github.com/syrupy-project/syrupy/commit/df9bc8f6b3a222dde82167e10a2e6bb57456305a">df9bc8f</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/7096efdee61a8e1bc47492bdd0bc860766df40e9"><code>7096efd</code></a>
chore(release): 5.1.0 [skip ci]</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/07aa00dd48d65e74814cec863b5f236e09afb464"><code>07aa00d</code></a>
chore(deps): update dependency attrs to v25 (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1063">#1063</a>)</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/1f29ae061e9557e205e50fb2f9971ee95c4bd08e"><code>1f29ae0</code></a>
docs: add bwrob as a contributor for code (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1064">#1064</a>)</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/df9bc8f6b3a222dde82167e10a2e6bb57456305a"><code>df9bc8f</code></a>
feat: add serializer plugin system; plugins for data models (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1062">#1062</a>)</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/841257deaf598df7c3d154b8e2d694f8bb7e5055"><code>841257d</code></a>
chore(deps): update dependency coverage to v7.13.1 (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1061">#1061</a>)</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/2d8dfa7f7bb2a5f7c0210107dbb65b62a615d434"><code>2d8dfa7</code></a>
chore(deps): update codecov/codecov-action action to v5.5.2 (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1056">#1056</a>)</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/f5f9ef77027983d3b62d8cc5bfc3a9ef058fe509"><code>f5f9ef7</code></a>
chore(deps): update dependency debugpy to v1.8.18 (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1057">#1057</a>)</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/eaeb6ae11f57aa3e595d4c45e7be4a3ed2d66dfc"><code>eaeb6ae</code></a>
chore(deps): update dependency pytest to v9.0.2 (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1055">#1055</a>)</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/263b23b768ef761c3f7e1faa0671b0709c1887b1"><code>263b23b</code></a>
chore(deps): update python docker tag to v3.14.1 (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1054">#1054</a>)</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/a0dd77b023fee34ff0968a822e0d0740c9c7fb93"><code>a0dd77b</code></a>
chore(deps): update actions/checkout action to v6.0.1 (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1053">#1053</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/syrupy-project/syrupy/compare/v5.0.0...v5.1.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `uvloop` from 0.21.0beta1 to 0.22.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/MagicStack/uvloop/releases">uvloop's
releases</a>.</em></p>
<blockquote>
<h2>v0.22.1</h2>
<p>This is identical to 0.22.0, re-ran with CI fixes</p>
<h2>v0.22.0</h2>
<h1>Changes</h1>
<ul>
<li>
<p>Fixes for Python 3.14 (<a
href="https://redirect.github.com/MagicStack/uvloop/issues/638">#638</a>)
(by <a href="https://github.com/graingert"><code>@​graingert</code></a>
<a href="https://github.com/hroncok"><code>@​hroncok</code></a> <a
href="https://github.com/paulocheque"><code>@​paulocheque</code></a> <a
href="https://github.com/fantix"><code>@​fantix</code></a> in 46456b6a
for <a
href="https://redirect.github.com/MagicStack/uvloop/issues/637">#637</a>)</p>
</li>
<li>
<p>Add free-threading support (<a
href="https://redirect.github.com/MagicStack/uvloop/issues/693">#693</a>)
(by <a
href="https://github.com/kumaraditya303"><code>@​kumaraditya303</code></a>
in 286b3707 for <a
href="https://redirect.github.com/MagicStack/uvloop/issues/642">#642</a>)</p>
</li>
</ul>
<h1>Fixes</h1>
<ul>
<li>
<p>Use Cython <code>enum</code> for <code>__PREALLOCED_BUFS</code> (<a
href="https://redirect.github.com/MagicStack/uvloop/issues/634">#634</a>)
(by <a href="https://github.com/jakirkham"><code>@​jakirkham</code></a>
in 7bb12a17 for <a
href="https://redirect.github.com/MagicStack/uvloop/issues/634">#634</a>)</p>
</li>
<li>
<p>test: fix getaddrinfo test (<a
href="https://redirect.github.com/MagicStack/uvloop/issues/663">#663</a>)
(by <a href="https://github.com/fantix"><code>@​fantix</code></a> in
56807922 for <a
href="https://redirect.github.com/MagicStack/uvloop/issues/663">#663</a>)</p>
</li>
<li>
<p>test: fix task name for Python 3.13.3/3.14 (<a
href="https://redirect.github.com/MagicStack/uvloop/issues/662">#662</a>)
(by <a href="https://github.com/cjwatson"><code>@​cjwatson</code></a> in
96b7ed31 for <a
href="https://redirect.github.com/MagicStack/uvloop/issues/662">#662</a>)</p>
</li>
</ul>
<h2>v0.21.0</h2>
<h1>Changes</h1>
<ul>
<li>Add cleanup_socket param on create_unix_server()
(<a
href="https://redirect.github.com/MagicStack/uvloop/issues/623">#623</a>)
(by <a href="https://github.com/fantix"><code>@​fantix</code></a> in
d6114d2)</li>
</ul>
<h1>Fixes</h1>
<ul>
<li>
<p>Use cythonized SO_REUSEPORT rather than the unwrapped native one. (<a
href="https://redirect.github.com/MagicStack/uvloop/issues/609">#609</a>)
(by <a href="https://github.com/ptribble"><code>@​ptribble</code></a> in
4083a94e for <a
href="https://redirect.github.com/MagicStack/uvloop/issues/550">#550</a>)</p>
</li>
<li>
<p>UDP errors should result in protocol.error_received (<a
href="https://redirect.github.com/MagicStack/uvloop/issues/601">#601</a>)
(by <a
href="https://github.com/jensbjorgensen"><code>@​jensbjorgensen</code></a>
in 3c3bbeff)</p>
</li>
<li>
<p>Updates for Cython3 (<a
href="https://redirect.github.com/MagicStack/uvloop/issues/587">#587</a>)
(by <a
href="https://github.com/alan-brooks"><code>@​alan-brooks</code></a> in
3fba9fab for <a
href="https://redirect.github.com/MagicStack/uvloop/issues/587">#587</a>)</p>
</li>
<li>
<p>Test with Python 3.13 (<a
href="https://redirect.github.com/MagicStack/uvloop/issues/610">#610</a>)
(by <a
href="https://github.com/edgarrmondragon"><code>@​edgarrmondragon</code></a>
in fb5a139)</p>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/MagicStack/uvloop/commit/74f4c96d3fc5281b1820491d2568de771ea7851b"><code>74f4c96</code></a>
uvloop 0.22.1</li>
<li><a
href="https://github.com/MagicStack/uvloop/commit/321d345bdadd4d9f244a22ab9778a66d6cdd7f4f"><code>321d345</code></a>
ci: bump pypa/gh-action-pypi-publish</li>
<li><a
href="https://github.com/MagicStack/uvloop/commit/3cf6b44fb39e0a865c812b8070fc8af640750476"><code>3cf6b44</code></a>
uvloop 0.22.0</li>
<li><a
href="https://github.com/MagicStack/uvloop/commit/e4d569e244ba1c44305254a89e1abb7484759f73"><code>e4d569e</code></a>
ci: use native ubuntu-24.04-arm</li>
<li><a
href="https://github.com/MagicStack/uvloop/commit/d9fa054cf882615f7810081ed2bbb7820544371d"><code>d9fa054</code></a>
ci: fix test and release workflow</li>
<li><a
href="https://github.com/MagicStack/uvloop/commit/7effa903f6f4e6d66a6f330afac63079135826ec"><code>7effa90</code></a>
ci: fix artifact handling</li>
<li><a
href="https://github.com/MagicStack/uvloop/commit/286b370702109f84f60cfe80deae9abf8da2a2e4"><code>286b370</code></a>
add free-threading support (<a
href="https://redirect.github.com/MagicStack/uvloop/issues/693">#693</a>)</li>
<li><a
href="https://github.com/MagicStack/uvloop/commit/46456b6abd7e98b70e1dd38252272a98533cc75b"><code>46456b6</code></a>
Fixes for Python 3.14 (<a
href="https://redirect.github.com/MagicStack/uvloop/issues/638">#638</a>)</li>
<li><a
href="https://github.com/MagicStack/uvloop/commit/96b7ed31afaf02800d779a395591da6a2c8c50e1"><code>96b7ed3</code></a>
test: fix task name for Python 3.13.3/3.14 (<a
href="https://redirect.github.com/MagicStack/uvloop/issues/662">#662</a>)</li>
<li><a
href="https://github.com/MagicStack/uvloop/commit/56807922f847ddac231a53d5b03eef70092b987c"><code>5680792</code></a>
test: fix getaddrinfo test (<a
href="https://redirect.github.com/MagicStack/uvloop/issues/663">#663</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/MagicStack/uvloop/compare/v0.21.0beta1...v0.22.1">compare
view</a></li>
</ul>
</details>
<br />

Updates `pyperf` from 2.9.0 to 2.10.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/psf/pyperf/releases">pyperf's
releases</a>.</em></p>
<blockquote>
<h2>2.10.0</h2>
<h2>What's Changed</h2>
<ul>
<li>ReadTheDocs: use latest Ubuntu and Python by <a
href="https://github.com/vstinner"><code>@​vstinner</code></a> in <a
href="https://redirect.github.com/psf/pyperf/pull/218">psf/pyperf#218</a></li>
<li>Add BSD support for track-memory by <a
href="https://github.com/lcheylus"><code>@​lcheylus</code></a> in <a
href="https://redirect.github.com/psf/pyperf/pull/220">psf/pyperf#220</a></li>
<li>Docs: Update minimum Python version. Add matching badge by <a
href="https://github.com/moreati"><code>@​moreati</code></a> in <a
href="https://redirect.github.com/psf/pyperf/pull/226">psf/pyperf#226</a></li>
<li>Remove fallbacks for unsupported Python versions (&lt; 3.9) by <a
href="https://github.com/moreati"><code>@​moreati</code></a> in <a
href="https://redirect.github.com/psf/pyperf/pull/228">psf/pyperf#228</a></li>
<li>Setup Dependabot for Github actions, bump checkout and setup-python
actions by <a
href="https://github.com/maurycy"><code>@​maurycy</code></a> in <a
href="https://redirect.github.com/psf/pyperf/pull/229">psf/pyperf#229</a></li>
<li>Recognise CPython as a JIT implementation by <a
href="https://github.com/Fidget-Spinner"><code>@​Fidget-Spinner</code></a>
in <a
href="https://redirect.github.com/psf/pyperf/pull/231">psf/pyperf#231</a></li>
<li>Prepare 2.10.0 release by <a
href="https://github.com/Fidget-Spinner"><code>@​Fidget-Spinner</code></a>
in <a
href="https://redirect.github.com/psf/pyperf/pull/232">psf/pyperf#232</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/lcheylus"><code>@​lcheylus</code></a>
made their first contribution in <a
href="https://redirect.github.com/psf/pyperf/pull/220">psf/pyperf#220</a></li>
<li><a href="https://github.com/maurycy"><code>@​maurycy</code></a> made
their first contribution in <a
href="https://redirect.github.com/psf/pyperf/pull/229">psf/pyperf#229</a></li>
<li><a
href="https://github.com/Fidget-Spinner"><code>@​Fidget-Spinner</code></a>
made their first contribution in <a
href="https://redirect.github.com/psf/pyperf/pull/231">psf/pyperf#231</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/psf/pyperf/compare/2.9.0...2.10.0">https://github.com/psf/pyperf/compare/2.9.0...2.10.0</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/psf/pyperf/blob/main/doc/changelog.rst">pyperf's
changelog</a>.</em></p>
<blockquote>
<h2>Version 2.10.0 (2026-02-07)</h2>
<ul>
<li>Feature: JIT builds of CPython are now recognized as a JIT
implementation by :func:<code>perf.python_has_jit</code>.
Patch by Ken Jin.</li>
<li>Feature: Memory tracker now supports BSD.
Patch by Laurent Cheylus and Victor Stinner.</li>
<li>Maintenance: <code>pyperf</code> now requires Python 3.9 or higher.
Patch by Alex Willmer.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/psf/pyperf/commit/ddb748a44d766dac28b2b1fa570c64503bbec82c"><code>ddb748a</code></a>
Prepare 2.10.0 release (<a
href="https://redirect.github.com/psf/pyperf/issues/232">#232</a>)</li>
<li><a
href="https://github.com/psf/pyperf/commit/8f6e7d037a890dc26c01713a279d06ae5694123e"><code>8f6e7d0</code></a>
Recognise CPython as a JIT implementation (<a
href="https://redirect.github.com/psf/pyperf/issues/231">#231</a>)</li>
<li><a
href="https://github.com/psf/pyperf/commit/ff3ba746161edae3d514635e6a722ce0fb3efbd3"><code>ff3ba74</code></a>
Setup Dependabot for Github actions, bump checkout and setup-python
actions (...</li>
<li><a
href="https://github.com/psf/pyperf/commit/188810f42e79755ea43c5f85a55d7757c31f5ce9"><code>188810f</code></a>
Remove fallbacks for unsupported Python versions (&lt; 3.9) (<a
href="https://redirect.github.com/psf/pyperf/issues/228">#228</a>)</li>
<li><a
href="https://github.com/psf/pyperf/commit/e6675c6208b15c7409745dfd19d206e7f03844f1"><code>e6675c6</code></a>
Docs: Update minimum Python version. Add matching badge (<a
href="https://redirect.github.com/psf/pyperf/issues/226">#226</a>)</li>
<li><a
href="https://github.com/psf/pyperf/commit/d2cc8031ef2ab8e398ff01ffa545d07cf6adfdf1"><code>d2cc803</code></a>
Add BSD support for track-memory (<a
href="https://redirect.github.com/psf/pyperf/issues/220">#220</a>)</li>
<li><a
href="https://github.com/psf/pyperf/commit/2fcee6089886e15fdc23cbde820ae1cc582610ea"><code>2fcee60</code></a>
ReadTheDocs: use latest Ubuntu and Python (<a
href="https://redirect.github.com/psf/pyperf/issues/218">#218</a>)</li>
<li>See full diff in <a
href="https://github.com/psf/pyperf/compare/2.9.0...2.10.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `redis` from 7.1.0 to 7.1.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/redis/redis-py/releases">redis's
releases</a>.</em></p>
<blockquote>
<h2>7.1.1</h2>
<h1>Changes</h1>
<h2>🧪 Experimental Features</h2>
<ul>
<li>Added initial health check policies, refactored add_database method
(<a
href="https://redirect.github.com/redis/redis-py/issues/3906">#3906</a>)</li>
</ul>
<h2>🧰 Maintenance</h2>
<ul>
<li>Disabled SCH in MultiDBClient underlying clients by default (<a
href="https://redirect.github.com/redis/redis-py/issues/3938">#3938</a>)</li>
<li>Added logging for MultiDBClients (<a
href="https://redirect.github.com/redis/redis-py/issues/3865">#3865</a>
<a
href="https://redirect.github.com/redis/redis-py/issues/3896">#3896</a>)</li>
</ul>
<p>We'd like to thank all the contributors who worked on this release!
<a
href="https://github.com/vladvildanov"><code>@​vladvildanov</code></a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/redis/redis-py/commit/7351a1e2d68f386ce6079e274df6bf2ae1406188"><code>7351a1e</code></a>
Updating lib version to 7.1.1</li>
<li><a
href="https://github.com/redis/redis-py/commit/b81c856c6b9f965cc5e4bb5fdcb2d3f323687357"><code>b81c856</code></a>
Disabled SCH in MultiDBClient underlying clients (<a
href="https://redirect.github.com/redis/redis-py/issues/3938">#3938</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/0438784ff41c0f14c6dd78682b9a8d9149a7b33b"><code>0438784</code></a>
Added initial health check policies, refactored add_database method (<a
href="https://redirect.github.com/redis/redis-py/issues/3906">#3906</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/76befb443c583815cc99100a58ef943096f27b50"><code>76befb4</code></a>
Added logging for MultiDBClients (<a
href="https://redirect.github.com/redis/redis-py/issues/3896">#3896</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/faee0fbbafd1ab4ad7f5402385f71660c5601948"><code>faee0fb</code></a>
Remove high-severity exception logging (<a
href="https://redirect.github.com/redis/redis-py/issues/3865">#3865</a>)</li>
<li>See full diff in <a
href="https://github.com/redis/redis-py/compare/v7.1.0...v7.1.1">compare
view</a></li>
</ul>
</details>
<br />

Updates `ruff` from 0.14.13 to 0.15.1
<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.15.1</h2>
<h2>Release Notes</h2>
<p>Released on 2026-02-12.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>airflow</code>] Add ruff rules to catch deprecated Airflow
imports for Airflow 3.1 (<code>AIR321</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22376">#22376</a>)</li>
<li>[<code>airflow</code>] Third positional parameter not named
<code>ti_key</code> should be flagged for
<code>BaseOperatorLink.get_link</code> (<code>AIR303</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22828">#22828</a>)</li>
<li>[<code>flake8-gettext</code>] Fix false negatives for plural
argument of <code>ngettext</code> (<code>INT001</code>,
<code>INT002</code>, <code>INT003</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/21078">#21078</a>)</li>
<li>[<code>pyflakes</code>] Fix infinite loop in preview fix for
<code>unused-import</code> (<code>F401</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23038">#23038</a>)</li>
<li>[<code>pygrep-hooks</code>] Detect non-existent mock methods in
standalone expressions (<code>PGH005</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22830">#22830</a>)</li>
<li>[<code>pylint</code>] Allow dunder submodules and improve diagnostic
range (<code>PLC2701</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22804">#22804</a>)</li>
<li>[<code>pyupgrade</code>] Improve diagnostic range for tuples
(<code>UP024</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23013">#23013</a>)</li>
<li>[<code>refurb</code>] Check subscripts in tuple do not use lambda
parameters in <code>reimplemented-operator</code> (<code>FURB118</code>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23079">#23079</a>)</li>
<li>[<code>ruff</code>] Detect mutable defaults in <code>field</code>
calls (<code>RUF008</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23046">#23046</a>)</li>
<li>[<code>ruff</code>] Ignore std <code>cmath.inf</code>
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23120">#23120</a>)</li>
<li>[<code>ruff</code>] New rule <code>float-equality-comparison</code>
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/20585">#20585</a>)</li>
<li>Don't format unlabeled Markdown code blocks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23106">#23106</a>)</li>
<li>Markdown formatting support in LSP (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23063">#23063</a>)</li>
<li>Support Quarto Markdown language markers (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22947">#22947</a>)</li>
<li>Support formatting <code>pycon</code> Markdown code blocks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23112">#23112</a>)</li>
<li>Use extension mapping to select Markdown code block language (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22934">#22934</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>Avoid false positive for undefined variables in <code>FAST001</code>
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23224">#23224</a>)</li>
<li>Avoid introducing syntax errors for <code>FAST003</code> autofix (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23227">#23227</a>)</li>
<li>Avoid suggesting <code>InitVar</code> for <code>__post_init__</code>
that references PEP 695 type parameters (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23226">#23226</a>)</li>
<li>Deduplicate type variables in generic functions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23225">#23225</a>)</li>
<li>Fix exception handler parenthesis removal for Python 3.14+ (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23126">#23126</a>)</li>
<li>Fix f-string middle panic when parsing t-strings (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23232">#23232</a>)</li>
<li>Wrap <code>RUF020</code> target for multiline fixes (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23210">#23210</a>)</li>
<li>Wrap <code>UP007</code> target for multiline fixes (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23208">#23208</a>)</li>
<li>Fix missing diagnostics for last range suppression in file (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23242">#23242</a>)</li>
<li>[<code>pyupgrade</code>] Fix syntax error on string with newline
escape and comment (<code>UP037</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22968">#22968</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Use <code>ruff</code> instead of <code>Ruff</code> as the program
name in GitHub output format (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23240">#23240</a>)</li>
<li>[<code>PT006</code>] Fix syntax error when unpacking nested tuples
in <code>parametrize</code> fixes (<a
href="https://redirect.github.com/astral-sh/ruff/issues/22441">#22441</a>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/22464">#22464</a>)</li>
<li>[<code>airflow</code>] Catch deprecated attribute access from
context key for Airflow 3.0 (<code>AIR301</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22850">#22850</a>)</li>
<li>[<code>airflow</code>] Capture deprecated arguments and a decorator
(<code>AIR301</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23170">#23170</a>)</li>
<li>[<code>flake8-boolean-trap</code>] Add
<code>multiprocessing.Value</code> to excluded functions for
<code>FBT003</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23010">#23010</a>)</li>
<li>[<code>flake8-bugbear</code>] Add a secondary annotation showing the
previous occurrence (<code>B033</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22634">#22634</a>)</li>
<li>[<code>flake8-type-checking</code>] Add sub-diagnostic showing the
runtime use of an annotation (<code>TC004</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23091">#23091</a>)</li>
<li>[<code>isort</code>] Support configurable import section heading
comments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23151">#23151</a>)</li>
<li>[<code>ruff</code>] Improve the diagnostic for <code>RUF012</code>
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23202">#23202</a>)</li>
</ul>
<h3>Formatter</h3>
<!-- 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.15.1</h2>
<p>Released on 2026-02-12.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>airflow</code>] Add ruff rules to catch deprecated Airflow
imports for Airflow 3.1 (<code>AIR321</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22376">#22376</a>)</li>
<li>[<code>airflow</code>] Third positional parameter not named
<code>ti_key</code> should be flagged for
<code>BaseOperatorLink.get_link</code> (<code>AIR303</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22828">#22828</a>)</li>
<li>[<code>flake8-gettext</code>] Fix false negatives for plural
argument of <code>ngettext</code> (<code>INT001</code>,
<code>INT002</code>, <code>INT003</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/21078">#21078</a>)</li>
<li>[<code>pyflakes</code>] Fix infinite loop in preview fix for
<code>unused-import</code> (<code>F401</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23038">#23038</a>)</li>
<li>[<code>pygrep-hooks</code>] Detect non-existent mock methods in
standalone expressions (<code>PGH005</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22830">#22830</a>)</li>
<li>[<code>pylint</code>] Allow dunder submodules and improve diagnostic
range (<code>PLC2701</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22804">#22804</a>)</li>
<li>[<code>pyupgrade</code>] Improve diagnostic range for tuples
(<code>UP024</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23013">#23013</a>)</li>
<li>[<code>refurb</code>] Check subscripts in tuple do not use lambda
parameters in <code>reimplemented-operator</code> (<code>FURB118</code>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23079">#23079</a>)</li>
<li>[<code>ruff</code>] Detect mutable defaults in <code>field</code>
calls (<code>RUF008</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23046">#23046</a>)</li>
<li>[<code>ruff</code>] Ignore std <code>cmath.inf</code>
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23120">#23120</a>)</li>
<li>[<code>ruff</code>] New rule <code>float-equality-comparison</code>
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/20585">#20585</a>)</li>
<li>Don't format unlabeled Markdown code blocks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23106">#23106</a>)</li>
<li>Markdown formatting support in LSP (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23063">#23063</a>)</li>
<li>Support Quarto Markdown language markers (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22947">#22947</a>)</li>
<li>Support formatting <code>pycon</code> Markdown code blocks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23112">#23112</a>)</li>
<li>Use extension mapping to select Markdown code block language (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22934">#22934</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>Avoid false positive for undefined variables in <code>FAST001</code>
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23224">#23224</a>)</li>
<li>Avoid introducing syntax errors for <code>FAST003</code> autofix (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23227">#23227</a>)</li>
<li>Avoid suggesting <code>InitVar</code> for <code>__post_init__</code>
that references PEP 695 type parameters (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23226">#23226</a>)</li>
<li>Deduplicate type variables in generic functions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23225">#23225</a>)</li>
<li>Fix exception handler parenthesis removal for Python 3.14+ (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23126">#23126</a>)</li>
<li>Fix f-string middle panic when parsing t-strings (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23232">#23232</a>)</li>
<li>Wrap <code>RUF020</code> target for multiline fixes (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23210">#23210</a>)</li>
<li>Wrap <code>UP007</code> target for multiline fixes (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23208">#23208</a>)</li>
<li>Fix missing diagnostics for last range suppression in file (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23242">#23242</a>)</li>
<li>[<code>pyupgrade</code>] Fix syntax error on string with newline
escape and comment (<code>UP037</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22968">#22968</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Use <code>ruff</code> instead of <code>Ruff</code> as the program
name in GitHub output format (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23240">#23240</a>)</li>
<li>[<code>PT006</code>] Fix syntax error when unpacking nested tuples
in <code>parametrize</code> fixes (<a
href="https://redirect.github.com/astral-sh/ruff/issues/22441">#22441</a>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/22464">#22464</a>)</li>
<li>[<code>airflow</code>] Catch deprecated attribute access from
context key for Airflow 3.0 (<code>AIR301</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22850">#22850</a>)</li>
<li>[<code>airflow</code>] Capture deprecated arguments and a decorator
(<code>AIR301</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23170">#23170</a>)</li>
<li>[<code>flake8-boolean-trap</code>] Add
<code>multiprocessing.Value</code> to excluded functions for
<code>FBT003</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23010">#23010</a>)</li>
<li>[<code>flake8-bugbear</code>] Add a secondary annotation showing the
previous occurrence (<code>B033</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22634">#22634</a>)</li>
<li>[<code>flake8-type-checking</code>] Add sub-diagnostic showing the
runtime use of an annotation (<code>TC004</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23091">#23091</a>)</li>
<li>[<code>isort</code>] Support configurable import section heading
comments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23151">#23151</a>)</li>
<li>[<code>ruff</code>] Improve the diagnostic for <code>RUF012</code>
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23202">#23202</a>)</li>
</ul>
<h3>Formatter</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/ruff/commit/a2f11d239f91cf8daedb0764ec15fcfe29c5ae6d"><code>a2f11d2</code></a>
Prepare for 0.15.1 (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23253">#23253</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/d29628e9665baa17272aad489398eb72b70e60ff"><code>d29628e</code></a>
Remove docker-run-action (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23254">#23254</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/8a042667651d7b1cdfc1742478d2b29b04d91be0"><code>8a04266</code></a>
[ty] Allow discovering dependencies in system Python environments (<a
href="https://redirect.github.com/astral-sh/ruff/issues/22994">#22994</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/55d06c8879761c5500e9558502abc84cefcb7163"><code>55d06c8</code></a>
Ensure pending suppression diagnostics are reported (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23242">#23242</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/d056a9fa6dfb842f2c0d439bf7b1a8099e5734ea"><code>d056a9f</code></a>
[<code>isort</code>] support for configurable import section heading
comments (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23151">#23151</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/e22fa4f14d8fae550249e452d11bc53756df5c7a"><code>e22fa4f</code></a>
[ty] Fix method calls on subclasses of <code>Any</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23248">#23248</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/fa56c1550d723e458b91dc2405d5537d40401d5c"><code>fa56c15</code></a>
[ty] Fix bound method access on <code>None</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23246">#23246</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/4fd07d0e1cbbb4e4c3f5b4c1f04f2d8b3f4a2bf2"><code>4fd07d0</code></a>
Make range suppression test snapshot actually useful (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23251">#23251</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/8c63bced13b21d1952a56e6a096d9c2ec4af442f"><code>8c63bce</code></a>
[ty] Include conditional symbols (like <code>datetime.UTC</code>) in
auto-import in more...</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/46be94361b3b4c54be911eb88bfbd9666eb06a6d"><code>46be943</code></a>
Exclude WASM artifacts from GitHub releases (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23221">#23221</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/ruff/compare/0.14.13...0.15.1">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 <65985482+jkennedyvz@users.noreply.github.com>
2026-02-17 09:28:01 -08:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
a76cf88232 chore(deps): bump ruff from 0.14.13 to 0.15.1 in /libs/checkpoint-sqlite in the all-dependencies group (#6807)
Bumps the all-dependencies group in /libs/checkpoint-sqlite with 1
update: [ruff](https://github.com/astral-sh/ruff).

Updates `ruff` from 0.14.13 to 0.15.1
<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.15.1</h2>
<h2>Release Notes</h2>
<p>Released on 2026-02-12.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>airflow</code>] Add ruff rules to catch deprecated Airflow
imports for Airflow 3.1 (<code>AIR321</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22376">#22376</a>)</li>
<li>[<code>airflow</code>] Third positional parameter not named
<code>ti_key</code> should be flagged for
<code>BaseOperatorLink.get_link</code> (<code>AIR303</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22828">#22828</a>)</li>
<li>[<code>flake8-gettext</code>] Fix false negatives for plural
argument of <code>ngettext</code> (<code>INT001</code>,
<code>INT002</code>, <code>INT003</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/21078">#21078</a>)</li>
<li>[<code>pyflakes</code>] Fix infinite loop in preview fix for
<code>unused-import</code> (<code>F401</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23038">#23038</a>)</li>
<li>[<code>pygrep-hooks</code>] Detect non-existent mock methods in
standalone expressions (<code>PGH005</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22830">#22830</a>)</li>
<li>[<code>pylint</code>] Allow dunder submodules and improve diagnostic
range (<code>PLC2701</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22804">#22804</a>)</li>
<li>[<code>pyupgrade</code>] Improve diagnostic range for tuples
(<code>UP024</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23013">#23013</a>)</li>
<li>[<code>refurb</code>] Check subscripts in tuple do not use lambda
parameters in <code>reimplemented-operator</code> (<code>FURB118</code>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23079">#23079</a>)</li>
<li>[<code>ruff</code>] Detect mutable defaults in <code>field</code>
calls (<code>RUF008</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23046">#23046</a>)</li>
<li>[<code>ruff</code>] Ignore std <code>cmath.inf</code>
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23120">#23120</a>)</li>
<li>[<code>ruff</code>] New rule <code>float-equality-comparison</code>
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/20585">#20585</a>)</li>
<li>Don't format unlabeled Markdown code blocks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23106">#23106</a>)</li>
<li>Markdown formatting support in LSP (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23063">#23063</a>)</li>
<li>Support Quarto Markdown language markers (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22947">#22947</a>)</li>
<li>Support formatting <code>pycon</code> Markdown code blocks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23112">#23112</a>)</li>
<li>Use extension mapping to select Markdown code block language (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22934">#22934</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>Avoid false positive for undefined variables in <code>FAST001</code>
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23224">#23224</a>)</li>
<li>Avoid introducing syntax errors for <code>FAST003</code> autofix (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23227">#23227</a>)</li>
<li>Avoid suggesting <code>InitVar</code> for <code>__post_init__</code>
that references PEP 695 type parameters (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23226">#23226</a>)</li>
<li>Deduplicate type variables in generic functions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23225">#23225</a>)</li>
<li>Fix exception handler parenthesis removal for Python 3.14+ (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23126">#23126</a>)</li>
<li>Fix f-string middle panic when parsing t-strings (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23232">#23232</a>)</li>
<li>Wrap <code>RUF020</code> target for multiline fixes (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23210">#23210</a>)</li>
<li>Wrap <code>UP007</code> target for multiline fixes (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23208">#23208</a>)</li>
<li>Fix missing diagnostics for last range suppression in file (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23242">#23242</a>)</li>
<li>[<code>pyupgrade</code>] Fix syntax error on string with newline
escape and comment (<code>UP037</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22968">#22968</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Use <code>ruff</code> instead of <code>Ruff</code> as the program
name in GitHub output format (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23240">#23240</a>)</li>
<li>[<code>PT006</code>] Fix syntax error when unpacking nested tuples
in <code>parametrize</code> fixes (<a
href="https://redirect.github.com/astral-sh/ruff/issues/22441">#22441</a>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/22464">#22464</a>)</li>
<li>[<code>airflow</code>] Catch deprecated attribute access from
context key for Airflow 3.0 (<code>AIR301</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22850">#22850</a>)</li>
<li>[<code>airflow</code>] Capture deprecated arguments and a decorator
(<code>AIR301</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23170">#23170</a>)</li>
<li>[<code>flake8-boolean-trap</code>] Add
<code>multiprocessing.Value</code> to excluded functions for
<code>FBT003</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23010">#23010</a>)</li>
<li>[<code>flake8-bugbear</code>] Add a secondary annotation showing the
previous occurrence (<code>B033</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22634">#22634</a>)</li>
<li>[<code>flake8-type-checking</code>] Add sub-diagnostic showing the
runtime use of an annotation (<code>TC004</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23091">#23091</a>)</li>
<li>[<code>isort</code>] Support configurable import section heading
comments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23151">#23151</a>)</li>
<li>[<code>ruff</code>] Improve the diagnostic for <code>RUF012</code>
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23202">#23202</a>)</li>
</ul>
<h3>Formatter</h3>
<!-- 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.15.1</h2>
<p>Released on 2026-02-12.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>airflow</code>] Add ruff rules to catch deprecated Airflow
imports for Airflow 3.1 (<code>AIR321</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22376">#22376</a>)</li>
<li>[<code>airflow</code>] Third positional parameter not named
<code>ti_key</code> should be flagged for
<code>BaseOperatorLink.get_link</code> (<code>AIR303</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22828">#22828</a>)</li>
<li>[<code>flake8-gettext</code>] Fix false negatives for plural
argument of <code>ngettext</code> (<code>INT001</code>,
<code>INT002</code>, <code>INT003</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/21078">#21078</a>)</li>
<li>[<code>pyflakes</code>] Fix infinite loop in preview fix for
<code>unused-import</code> (<code>F401</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23038">#23038</a>)</li>
<li>[<code>pygrep-hooks</code>] Detect non-existent mock methods in
standalone expressions (<code>PGH005</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22830">#22830</a>)</li>
<li>[<code>pylint</code>] Allow dunder submodules and improve diagnostic
range (<code>PLC2701</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22804">#22804</a>)</li>
<li>[<code>pyupgrade</code>] Improve diagnostic range for tuples
(<code>UP024</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23013">#23013</a>)</li>
<li>[<code>refurb</code>] Check subscripts in tuple do not use lambda
parameters in <code>reimplemented-operator</code> (<code>FURB118</code>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23079">#23079</a>)</li>
<li>[<code>ruff</code>] Detect mutable defaults in <code>field</code>
calls (<code>RUF008</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23046">#23046</a>)</li>
<li>[<code>ruff</code>] Ignore std <code>cmath.inf</code>
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23120">#23120</a>)</li>
<li>[<code>ruff</code>] New rule <code>float-equality-comparison</code>
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/20585">#20585</a>)</li>
<li>Don't format unlabeled Markdown code blocks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23106">#23106</a>)</li>
<li>Markdown formatting support in LSP (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23063">#23063</a>)</li>
<li>Support Quarto Markdown language markers (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22947">#22947</a>)</li>
<li>Support formatting <code>pycon</code> Markdown code blocks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23112">#23112</a>)</li>
<li>Use extension mapping to select Markdown code block language (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22934">#22934</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>Avoid false positive for undefined variables in <code>FAST001</code>
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23224">#23224</a>)</li>
<li>Avoid introducing syntax errors for <code>FAST003</code> autofix (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23227">#23227</a>)</li>
<li>Avoid suggesting <code>InitVar</code> for <code>__post_init__</code>
that references PEP 695 type parameters (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23226">#23226</a>)</li>
<li>Deduplicate type variables in generic functions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23225">#23225</a>)</li>
<li>Fix exception handler parenthesis removal for Python 3.14+ (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23126">#23126</a>)</li>
<li>Fix f-string middle panic when parsing t-strings (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23232">#23232</a>)</li>
<li>Wrap <code>RUF020</code> target for multiline fixes (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23210">#23210</a>)</li>
<li>Wrap <code>UP007</code> target for multiline fixes (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23208">#23208</a>)</li>
<li>Fix missing diagnostics for last range suppression in file (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23242">#23242</a>)</li>
<li>[<code>pyupgrade</code>] Fix syntax error on string with newline
escape and comment (<code>UP037</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22968">#22968</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Use <code>ruff</code> instead of <code>Ruff</code> as the program
name in GitHub output format (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23240">#23240</a>)</li>
<li>[<code>PT006</code>] Fix syntax error when unpacking nested tuples
in <code>parametrize</code> fixes (<a
href="https://redirect.github.com/astral-sh/ruff/issues/22441">#22441</a>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/22464">#22464</a>)</li>
<li>[<code>airflow</code>] Catch deprecated attribute access from
context key for Airflow 3.0 (<code>AIR301</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22850">#22850</a>)</li>
<li>[<code>airflow</code>] Capture deprecated arguments and a decorator
(<code>AIR301</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23170">#23170</a>)</li>
<li>[<code>flake8-boolean-trap</code>] Add
<code>multiprocessing.Value</code> to excluded functions for
<code>FBT003</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23010">#23010</a>)</li>
<li>[<code>flake8-bugbear</code>] Add a secondary annotation showing the
previous occurrence (<code>B033</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22634">#22634</a>)</li>
<li>[<code>flake8-type-checking</code>] Add sub-diagnostic showing the
runtime use of an annotation (<code>TC004</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23091">#23091</a>)</li>
<li>[<code>isort</code>] Support configurable import section heading
comments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23151">#23151</a>)</li>
<li>[<code>ruff</code>] Improve the diagnostic for <code>RUF012</code>
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23202">#23202</a>)</li>
</ul>
<h3>Formatter</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/ruff/commit/a2f11d239f91cf8daedb0764ec15fcfe29c5ae6d"><code>a2f11d2</code></a>
Prepare for 0.15.1 (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23253">#23253</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/d29628e9665baa17272aad489398eb72b70e60ff"><code>d29628e</code></a>
Remove docker-run-action (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23254">#23254</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/8a042667651d7b1cdfc1742478d2b29b04d91be0"><code>8a04266</code></a>
[ty] Allow discovering dependencies in system Python environments (<a
href="https://redirect.github.com/astral-sh/ruff/issues/22994">#22994</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/55d06c8879761c5500e9558502abc84cefcb7163"><code>55d06c8</code></a>
Ensure pending suppression diagnostics are reported (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23242">#23242</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/d056a9fa6dfb842f2c0d439bf7b1a8099e5734ea"><code>d056a9f</code></a>
[<code>isort</code>] support for configurable import section heading
comments (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23151">#23151</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/e22fa4f14d8fae550249e452d11bc53756df5c7a"><code>e22fa4f</code></a>
[ty] Fix method calls on subclasses of <code>Any</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23248">#23248</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/fa56c1550d723e458b91dc2405d5537d40401d5c"><code>fa56c15</code></a>
[ty] Fix bound method access on <code>None</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23246">#23246</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/4fd07d0e1cbbb4e4c3f5b4c1f04f2d8b3f4a2bf2"><code>4fd07d0</code></a>
Make range suppression test snapshot actually useful (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23251">#23251</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/8c63bced13b21d1952a56e6a096d9c2ec4af442f"><code>8c63bce</code></a>
[ty] Include conditional symbols (like <code>datetime.UTC</code>) in
auto-import in more...</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/46be94361b3b4c54be911eb88bfbd9666eb06a6d"><code>46be943</code></a>
Exclude WASM artifacts from GitHub releases (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23221">#23221</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/ruff/compare/0.14.13...0.15.1">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=ruff&package-manager=uv&previous-version=0.14.13&new-version=0.15.1)](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>
2026-02-17 09:27:08 -08:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>John Kennedy
bd6da75a85 chore(deps): bump protobuf from 6.33.4 to 6.33.5 in /libs/cli (#6830)
Bumps [protobuf](https://github.com/protocolbuffers/protobuf) from
6.33.4 to 6.33.5.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/protocolbuffers/protobuf/releases">protobuf's
releases</a>.</em></p>
<blockquote>
<h2>Protocol Buffers v34.0-rc1</h2>
<h1>Announcements</h1>
<ul>
<li><strong>This version includes breaking changes to: C++, Objective-C,
PHP, Python.</strong></li>
<li>[Bazel] Remove deprecated ProtoInfo.transitive_imports. Use
equivalent transitive_sources instead (<a
href="https://github.com/protocolbuffers/protobuf/commit/0a5c2f6b633c1e5259f566cb42d30fe347b8aadb">https://github.com/protocolbuffers/protobuf/commit/0a5c2f6b633c1e5259f566cb42d30fe347b8aadb</a>)</li>
<li>[C++] Make generator headers private (<a
href="https://github.com/protocolbuffers/protobuf/commit/3a2af3510f0d454dbe3e4dc281674b61c4d20b9e">https://github.com/protocolbuffers/protobuf/commit/3a2af3510f0d454dbe3e4dc281674b61c4d20b9e</a>)</li>
<li>[C++] Add a debug check that the target of CopyFrom is not a
descendant of the source. (<a
href="https://github.com/protocolbuffers/protobuf/commit/7a7589823d2cfaaf7994b050e98d5d553bc9b1c1">https://github.com/protocolbuffers/protobuf/commit/7a7589823d2cfaaf7994b050e98d5d553bc9b1c1</a>)</li>
<li>[C++] Add [[nodiscard]] to many APIs. (<a
href="https://github.com/protocolbuffers/protobuf/commit/a70115f33f9af2c4b2202c800b84837e7fe0d738">https://github.com/protocolbuffers/protobuf/commit/a70115f33f9af2c4b2202c800b84837e7fe0d738</a>)</li>
<li>[C++] Make the arena-enabled constructors of
<code>RepeatedField</code>, <code>RepeatedPtrField</code>, and
<code>Map</code> private. (<a
href="https://github.com/protocolbuffers/protobuf/commit/ef890c3d0c79398c70e047fe5dd893f460ba2336">https://github.com/protocolbuffers/protobuf/commit/ef890c3d0c79398c70e047fe5dd893f460ba2336</a>)</li>
<li>[C++] Remove deprecated FieldDescriptor::label() in OSS. Use
is_repeated() or is_required() instead (<a
href="https://github.com/protocolbuffers/protobuf/commit/b76faa921fdd244f374c7be0bddd4050fc42c292">https://github.com/protocolbuffers/protobuf/commit/b76faa921fdd244f374c7be0bddd4050fc42c292</a>)</li>
<li>[C++] Removes proto2::util::MessageDifferencer::AddIgnoreCriteria
that takes a raw pointer as an argument in favor of the overload that
takes a unique_ptr. Remove macro
PROTOBUF_FUTURE_REMOVE_ADD_IGNORE_CRITERIA (<a
href="https://github.com/protocolbuffers/protobuf/commit/b115358c64127896fed88b8b5ef5d91d86d8cbae">https://github.com/protocolbuffers/protobuf/commit/b115358c64127896fed88b8b5ef5d91d86d8cbae</a>)</li>
<li>[C++] Remove deprecated FieldDescriptor::has_optional_keyword() in
OSS. Use is_repeated() or has_presence() instead (<a
href="https://github.com/protocolbuffers/protobuf/commit/68346ec9348e932664e58c3ecdcd1478f95233a8">https://github.com/protocolbuffers/protobuf/commit/68346ec9348e932664e58c3ecdcd1478f95233a8</a>)</li>
<li>[C++] Remove AddUnusedImportTrackFile() and
ClearUnusedImportTrackFiles(). Remove
PROTOBUF_FUTURE_RENAME_ADD_UNUSED_IMPORT (<a
href="https://github.com/protocolbuffers/protobuf/commit/837a2cd1d6c75402b2503ffe7cd8aeaf25868536">https://github.com/protocolbuffers/protobuf/commit/837a2cd1d6c75402b2503ffe7cd8aeaf25868536</a>)</li>
<li>[C++] Remove deprecated FieldDescriptor::is_optional() in OSS. Use
(!is_required() &amp;&amp; !is_repeated()) instead (<a
href="https://github.com/protocolbuffers/protobuf/commit/9dbc5d479a8e453921485d8d3de47fb3c005f1af">https://github.com/protocolbuffers/protobuf/commit/9dbc5d479a8e453921485d8d3de47fb3c005f1af</a>)</li>
<li>[C++] Remove deprecated UseDeprecatedLegacyJsonFieldConflicts() (<a
href="https://github.com/protocolbuffers/protobuf/commit/c301c2ca286327a21c50c0c4cd877afc9c655b00">https://github.com/protocolbuffers/protobuf/commit/c301c2ca286327a21c50c0c4cd877afc9c655b00</a>)</li>
<li>[C++] All entity names have length limit (2afb0dc)</li>
<li>[ObjC] Remove <code>generate_minimal_imports</code> generation
option warning (<a
href="https://github.com/protocolbuffers/protobuf/commit/45b1297fdaad5a9436d0e207422168c38dc45ac4">https://github.com/protocolbuffers/protobuf/commit/45b1297fdaad5a9436d0e207422168c38dc45ac4</a>)</li>
<li>[ObjC] Fix nullability annotations on some
<code>GPB*Dictionary</code> types. (<a
href="https://github.com/protocolbuffers/protobuf/commit/ea67d6d26a48478a567c404679e3bb99cf230d50">https://github.com/protocolbuffers/protobuf/commit/ea67d6d26a48478a567c404679e3bb99cf230d50</a>)</li>
<li>[ObjC] Remove <code>-[GPBFieldDescriptor optional]</code> (<a
href="https://github.com/protocolbuffers/protobuf/commit/3414dc151eb4dcbdb2ca952e2589993bf7af75c4">https://github.com/protocolbuffers/protobuf/commit/3414dc151eb4dcbdb2ca952e2589993bf7af75c4</a>)</li>
<li>[Other] Remove deprecated flag for enabling MSVC support (<a
href="https://github.com/protocolbuffers/protobuf/commit/97c979be6e0907e1051bee62584dac4594e73fa7">https://github.com/protocolbuffers/protobuf/commit/97c979be6e0907e1051bee62584dac4594e73fa7</a>)</li>
<li>[PHP] Remove deprecated PHP APIs (<a
href="https://github.com/protocolbuffers/protobuf/commit/9c45014099a4f7004fab6dd1278de2f4f2a393c5">https://github.com/protocolbuffers/protobuf/commit/9c45014099a4f7004fab6dd1278de2f4f2a393c5</a>)</li>
<li>[PHP] Remove deprecated PHP APIs FieldDescriptor getLabel, use
IsRepeated or isRequired instead. (<a
href="https://github.com/protocolbuffers/protobuf/commit/42081219920c6fad17ba6ddd1e28d111bcfb3345">https://github.com/protocolbuffers/protobuf/commit/42081219920c6fad17ba6ddd1e28d111bcfb3345</a>,
<a
href="https://github.com/protocolbuffers/protobuf/commit/cd76e675b14d00dda5623b30835d2bc7105fccc6">https://github.com/protocolbuffers/protobuf/commit/cd76e675b14d00dda5623b30835d2bc7105fccc6</a>,
<a
href="https://github.com/protocolbuffers/protobuf/commit/42081219920c6fad17ba6ddd1e28d111bcfb3345">https://github.com/protocolbuffers/protobuf/commit/42081219920c6fad17ba6ddd1e28d111bcfb3345</a>)</li>
<li>[PHP] Add PHP typehints for setters and remove redundant GPBUtil
checks (<a
href="https://redirect.github.com/protocolbuffers/protobuf/pull/25296">protocolbuffers/protobuf#25296</a>)
(<a
href="https://github.com/protocolbuffers/protobuf/commit/aee03b78929c02461a5f9d8e136a2a016359b0cd">https://github.com/protocolbuffers/protobuf/commit/aee03b78929c02461a5f9d8e136a2a016359b0cd</a>)</li>
<li>[PHP] support default values for editions/proto2 (<a
href="https://redirect.github.com/protocolbuffers/protobuf/pull/25161">protocolbuffers/protobuf#25161</a>)
(<a
href="https://github.com/protocolbuffers/protobuf/commit/b01099d56350551bae3da88b97bf3027274c9f17">https://github.com/protocolbuffers/protobuf/commit/b01099d56350551bae3da88b97bf3027274c9f17</a>)</li>
<li>[Python] Raise errors in OSS when assign bool to int/enum field in
Python Proto. (<a
href="https://github.com/protocolbuffers/protobuf/commit/5b116fe2f14f49dd0cc3b76089983717f211025c">https://github.com/protocolbuffers/protobuf/commit/5b116fe2f14f49dd0cc3b76089983717f211025c</a>)</li>
<li>[Python] Remove float_format/double_format from python proto
text_format (<a
href="https://github.com/protocolbuffers/protobuf/commit/e4854a186e0bfa867d5bfa5cd850608a948fd488">https://github.com/protocolbuffers/protobuf/commit/e4854a186e0bfa867d5bfa5cd850608a948fd488</a>)</li>
<li>[Python] Raise TypeError when convert non-timedelta to Duration, or
convert non-datetime to Timestamp in python proto. (Original code may
raise ArributeError) (<a
href="https://github.com/protocolbuffers/protobuf/commit/00aaca1b4d98954bc2933d7c8a5379ba6088124c">https://github.com/protocolbuffers/protobuf/commit/00aaca1b4d98954bc2933d7c8a5379ba6088124c</a>)</li>
<li>[Python] Remove float_precision from python proto json_format (<a
href="https://github.com/protocolbuffers/protobuf/commit/f027f1fcd52b9d080b7ee79f4024f53cf54e0dc5">https://github.com/protocolbuffers/protobuf/commit/f027f1fcd52b9d080b7ee79f4024f53cf54e0dc5</a>)</li>
<li>[Python] Remove deprecated FieldDescriptor::label() in OSS. Use
is_repeated() or is_required() instead (<a
href="https://github.com/protocolbuffers/protobuf/commit/b76faa921fdd244f374c7be0bddd4050fc42c292">https://github.com/protocolbuffers/protobuf/commit/b76faa921fdd244f374c7be0bddd4050fc42c292</a>)</li>
<li>[Python] Remove deprecated FieldDescriptor.label (<a
href="https://github.com/protocolbuffers/protobuf/commit/0a8ff55518ea5874478ad5b26515b31d186045a9">https://github.com/protocolbuffers/protobuf/commit/0a8ff55518ea5874478ad5b26515b31d186045a9</a>)</li>
<li>[Python] Remove deprecated UseDeprecatedLegacyJsonFieldConflicts()
(<a
href="https://github.com/protocolbuffers/protobuf/commit/c301c2ca286327a21c50c0c4cd877afc9c655b00">https://github.com/protocolbuffers/protobuf/commit/c301c2ca286327a21c50c0c4cd877afc9c655b00</a>)</li>
<li><a href="https://protobuf.dev/news/">Protobuf News</a> may include
additional announcements or pre-announcements for upcoming changes.</li>
<li><a href="https://protobuf.dev/support/migration/">Migration
Guide</a> may include additional guidance for breaking changes.</li>
</ul>
<h1>Bazel</h1>
<ul>
<li>Fix: cc_toolchain should prefer protoc when prebuilt flag is
flipped. (<a
href="https://redirect.github.com/protocolbuffers/protobuf/issues/25168">#25168</a>)
(<a
href="https://github.com/protocolbuffers/protobuf/commit/8c857c3a1c6a106b0a096f1c9fa504bfaca035a9">https://github.com/protocolbuffers/protobuf/commit/8c857c3a1c6a106b0a096f1c9fa504bfaca035a9</a>)</li>
<li>Breaking change: Remove deprecated ProtoInfo.transitive_imports. Use
equivalent transitive_sources instead (<a
href="https://github.com/protocolbuffers/protobuf/commit/0a5c2f6b633c1e5259f566cb42d30fe347b8aadb">https://github.com/protocolbuffers/protobuf/commit/0a5c2f6b633c1e5259f566cb42d30fe347b8aadb</a>)</li>
<li>Feat(bazel): wire up prebuilt protoc toolchain (<a
href="https://redirect.github.com/protocolbuffers/protobuf/issues/24115">#24115</a>)
(<a
href="https://github.com/protocolbuffers/protobuf/commit/cc23698b486e690ea2eb873cc7596a87c74a3ba6">https://github.com/protocolbuffers/protobuf/commit/cc23698b486e690ea2eb873cc7596a87c74a3ba6</a>)</li>
<li>Migrate <code>proto_descriptor_set</code> (<a
href="https://redirect.github.com/protocolbuffers/protobuf/issues/23369">#23369</a>)
(<a
href="https://github.com/protocolbuffers/protobuf/commit/8d4dfdd39a7a242a9ed631a6ab2192c57dd9b9c8">https://github.com/protocolbuffers/protobuf/commit/8d4dfdd39a7a242a9ed631a6ab2192c57dd9b9c8</a>)</li>
</ul>
<h1>Compiler</h1>
<ul>
<li>Ruby codegen: support generation of rbs files (<a
href="https://redirect.github.com/protocolbuffers/protobuf/issues/15633">#15633</a>)
(<a
href="https://github.com/protocolbuffers/protobuf/commit/6ebdf851ba78728f0aa145d38454ed9a316fb08d">https://github.com/protocolbuffers/protobuf/commit/6ebdf851ba78728f0aa145d38454ed9a316fb08d</a>)</li>
<li>Avoid collision name problems between a message named
<code>Xyz</code> and a direct sibling enum named <code>XyzView</code>
(<a
href="https://github.com/protocolbuffers/protobuf/commit/eba53e8f172b273d679759a72ce4250131ee3df1">https://github.com/protocolbuffers/protobuf/commit/eba53e8f172b273d679759a72ce4250131ee3df1</a>)</li>
<li>Generalizing and implementing ValidateFeatureSupport for both
Options and Features during proto parsing (<a
href="https://github.com/protocolbuffers/protobuf/commit/ed3c57114d8e2b47cca7697ddaa50c1b3762a6b0">https://github.com/protocolbuffers/protobuf/commit/ed3c57114d8e2b47cca7697ddaa50c1b3762a6b0</a>)</li>
<li>Fix a bug with custom features outside of the <code>pb</code>
package. (<a
href="https://github.com/protocolbuffers/protobuf/commit/872d3ce7a4da00d7dcec33ced20cfe45235935e8">https://github.com/protocolbuffers/protobuf/commit/872d3ce7a4da00d7dcec33ced20cfe45235935e8</a>)</li>
<li>Fix import option handling when include_imports isn't set. (<a
href="https://github.com/protocolbuffers/protobuf/commit/9ef9e80afd9bc8379d578fe67e5ab0738728c04e">https://github.com/protocolbuffers/protobuf/commit/9ef9e80afd9bc8379d578fe67e5ab0738728c04e</a>)</li>
<li>Fix a bug in STRICT check of namespaced enums to properly check for
'reserved 1 to max' (<a
href="https://github.com/protocolbuffers/protobuf/commit/1229d4adba24c0952ab85ce96bc7b7f8a1fe6d0f">https://github.com/protocolbuffers/protobuf/commit/1229d4adba24c0952ab85ce96bc7b7f8a1fe6d0f</a>)</li>
<li>Prevent accidental stripping of <code>debug_redact</code> options
via import option. (<a
href="https://github.com/protocolbuffers/protobuf/commit/f58b098bffa7ca4045ef7773b09151a6af5d0c28">https://github.com/protocolbuffers/protobuf/commit/f58b098bffa7ca4045ef7773b09151a6af5d0c28</a>)</li>
</ul>
<h1>C++</h1>
<ul>
<li>Add EnumerateEnumValues function. (<a
href="https://github.com/protocolbuffers/protobuf/commit/397d5d99db274b379d1384814074bf7df39d32f7">https://github.com/protocolbuffers/protobuf/commit/397d5d99db274b379d1384814074bf7df39d32f7</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/protocolbuffers/protobuf/commits">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=protobuf&package-manager=uv&previous-version=6.33.4&new-version=6.33.5)](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>
Co-authored-by: John Kennedy <65985482+jkennedyvz@users.noreply.github.com>
2026-02-17 09:26:14 -08:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>John Kennedy
7889a907e5 chore(deps): bump the all-dependencies group in /libs/cli with 2 updates (#6811)
Bumps the all-dependencies group in /libs/cli with 2 updates:
[langgraph-sdk](https://github.com/langchain-ai/langgraph) and
[ruff](https://github.com/astral-sh/ruff).

Updates `langgraph-sdk` from 0.3.3 to 0.3.5
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/langchain-ai/langgraph/releases">langgraph-sdk's
releases</a>.</em></p>
<blockquote>
<h2>langgraph-sdk==0.3.5</h2>
<p>Changes since sdk==0.3.4</p>
<ul>
<li>chore: server runtime type (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/6774">#6774</a>)</li>
</ul>
<h2>langgraph-sdk==0.3.4</h2>
<p>Changes since sdk==0.3.3</p>
<ul>
<li>chore: release python sdk (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/6754">#6754</a>)</li>
<li>feat(sdk-py): add update method for crons client (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/6742">#6742</a>)</li>
<li>feat(sdk-py): add support for enabling/disabling crons (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/6740">#6740</a>)</li>
<li>chore(deps-dev): bump ruff from 0.14.7 to 0.14.11 in /libs/sdk-py
(<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/6673">#6673</a>)</li>
<li>chore(deps): upgrade dependencies with <code>uv lock
--upgrade</code> (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/6671">#6671</a>)</li>
<li>docs: clarify cron job schedule interpretation in UTC (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/6692">#6692</a>)</li>
<li>chore: update twitter URLs (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/6683">#6683</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/ff60ee8c9a81c2a1519f557d2695ae9a2ce911af"><code>ff60ee8</code></a>
langgraph: release 0.3.5 (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/3690">#3690</a>)</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/8761721fb95d21da8c08ef75a523153e972d4363"><code>8761721</code></a>
langgraph: do not pass subgraph state on Command.parent updates (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/3686">#3686</a>)</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/de85e7c2464d23c76e13bc26873398b58095dea3"><code>de85e7c</code></a>
Add json schema to CLI (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/3684">#3684</a>)</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/e466c2c90caabbd2e0ab958aefbdb19e3afe7b3b"><code>e466c2c</code></a>
fix(sdk-js): handle threadId: undefined as controlled</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/815a67ef5589c62b7669181fc2cb7c6676476602"><code>815a67e</code></a>
0.3.4</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/38f1b415a00b899fd02c2e557dc0eea7e69042f7"><code>38f1b41</code></a>
When rehydrating a pydantic module, fallback to returning the kwargs
dict (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/3">#3</a>...</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/ed78174adf0896d2073dbdcc677de5feb3d05913"><code>ed78174</code></a>
Lint</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/5da6971a95480f1f92cacbcc2ed34ec066fe60bf"><code>5da6971</code></a>
When rehydrating a pydantic module, fallback to returning the kwargs
dict</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/256e92bfb339c3a5ae6c7b53805a83c3486879a7"><code>256e92b</code></a>
Pregel.config_schema should use config_type directly when present (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/3641">#3641</a>)</li>
<li><a
href="https://github.com/langchain-ai/langgraph/commit/3d4e5c0471cfdc276abfb2d3eece239f523cfa9a"><code>3d4e5c0</code></a>
sdk-py: fix decode_json in sdk (<a
href="https://redirect.github.com/langchain-ai/langgraph/issues/3681">#3681</a>)</li>
<li>See full diff in <a
href="https://github.com/langchain-ai/langgraph/compare/0.3.3...0.3.5">compare
view</a></li>
</ul>
</details>
<br />

Updates `ruff` from 0.14.14 to 0.15.1
<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.15.1</h2>
<h2>Release Notes</h2>
<p>Released on 2026-02-12.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>airflow</code>] Add ruff rules to catch deprecated Airflow
imports for Airflow 3.1 (<code>AIR321</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22376">#22376</a>)</li>
<li>[<code>airflow</code>] Third positional parameter not named
<code>ti_key</code> should be flagged for
<code>BaseOperatorLink.get_link</code> (<code>AIR303</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22828">#22828</a>)</li>
<li>[<code>flake8-gettext</code>] Fix false negatives for plural
argument of <code>ngettext</code> (<code>INT001</code>,
<code>INT002</code>, <code>INT003</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/21078">#21078</a>)</li>
<li>[<code>pyflakes</code>] Fix infinite loop in preview fix for
<code>unused-import</code> (<code>F401</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23038">#23038</a>)</li>
<li>[<code>pygrep-hooks</code>] Detect non-existent mock methods in
standalone expressions (<code>PGH005</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22830">#22830</a>)</li>
<li>[<code>pylint</code>] Allow dunder submodules and improve diagnostic
range (<code>PLC2701</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22804">#22804</a>)</li>
<li>[<code>pyupgrade</code>] Improve diagnostic range for tuples
(<code>UP024</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23013">#23013</a>)</li>
<li>[<code>refurb</code>] Check subscripts in tuple do not use lambda
parameters in <code>reimplemented-operator</code> (<code>FURB118</code>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23079">#23079</a>)</li>
<li>[<code>ruff</code>] Detect mutable defaults in <code>field</code>
calls (<code>RUF008</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23046">#23046</a>)</li>
<li>[<code>ruff</code>] Ignore std <code>cmath.inf</code>
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23120">#23120</a>)</li>
<li>[<code>ruff</code>] New rule <code>float-equality-comparison</code>
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/20585">#20585</a>)</li>
<li>Don't format unlabeled Markdown code blocks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23106">#23106</a>)</li>
<li>Markdown formatting support in LSP (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23063">#23063</a>)</li>
<li>Support Quarto Markdown language markers (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22947">#22947</a>)</li>
<li>Support formatting <code>pycon</code> Markdown code blocks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23112">#23112</a>)</li>
<li>Use extension mapping to select Markdown code block language (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22934">#22934</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>Avoid false positive for undefined variables in <code>FAST001</code>
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23224">#23224</a>)</li>
<li>Avoid introducing syntax errors for <code>FAST003</code> autofix (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23227">#23227</a>)</li>
<li>Avoid suggesting <code>InitVar</code> for <code>__post_init__</code>
that references PEP 695 type parameters (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23226">#23226</a>)</li>
<li>Deduplicate type variables in generic functions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23225">#23225</a>)</li>
<li>Fix exception handler parenthesis removal for Python 3.14+ (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23126">#23126</a>)</li>
<li>Fix f-string middle panic when parsing t-strings (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23232">#23232</a>)</li>
<li>Wrap <code>RUF020</code> target for multiline fixes (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23210">#23210</a>)</li>
<li>Wrap <code>UP007</code> target for multiline fixes (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23208">#23208</a>)</li>
<li>Fix missing diagnostics for last range suppression in file (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23242">#23242</a>)</li>
<li>[<code>pyupgrade</code>] Fix syntax error on string with newline
escape and comment (<code>UP037</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22968">#22968</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Use <code>ruff</code> instead of <code>Ruff</code> as the program
name in GitHub output format (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23240">#23240</a>)</li>
<li>[<code>PT006</code>] Fix syntax error when unpacking nested tuples
in <code>parametrize</code> fixes (<a
href="https://redirect.github.com/astral-sh/ruff/issues/22441">#22441</a>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/22464">#22464</a>)</li>
<li>[<code>airflow</code>] Catch deprecated attribute access from
context key for Airflow 3.0 (<code>AIR301</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22850">#22850</a>)</li>
<li>[<code>airflow</code>] Capture deprecated arguments and a decorator
(<code>AIR301</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23170">#23170</a>)</li>
<li>[<code>flake8-boolean-trap</code>] Add
<code>multiprocessing.Value</code> to excluded functions for
<code>FBT003</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23010">#23010</a>)</li>
<li>[<code>flake8-bugbear</code>] Add a secondary annotation showing the
previous occurrence (<code>B033</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22634">#22634</a>)</li>
<li>[<code>flake8-type-checking</code>] Add sub-diagnostic showing the
runtime use of an annotation (<code>TC004</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23091">#23091</a>)</li>
<li>[<code>isort</code>] Support configurable import section heading
comments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23151">#23151</a>)</li>
<li>[<code>ruff</code>] Improve the diagnostic for <code>RUF012</code>
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23202">#23202</a>)</li>
</ul>
<h3>Formatter</h3>
<!-- 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.15.1</h2>
<p>Released on 2026-02-12.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>airflow</code>] Add ruff rules to catch deprecated Airflow
imports for Airflow 3.1 (<code>AIR321</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22376">#22376</a>)</li>
<li>[<code>airflow</code>] Third positional parameter not named
<code>ti_key</code> should be flagged for
<code>BaseOperatorLink.get_link</code> (<code>AIR303</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22828">#22828</a>)</li>
<li>[<code>flake8-gettext</code>] Fix false negatives for plural
argument of <code>ngettext</code> (<code>INT001</code>,
<code>INT002</code>, <code>INT003</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/21078">#21078</a>)</li>
<li>[<code>pyflakes</code>] Fix infinite loop in preview fix for
<code>unused-import</code> (<code>F401</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23038">#23038</a>)</li>
<li>[<code>pygrep-hooks</code>] Detect non-existent mock methods in
standalone expressions (<code>PGH005</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22830">#22830</a>)</li>
<li>[<code>pylint</code>] Allow dunder submodules and improve diagnostic
range (<code>PLC2701</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22804">#22804</a>)</li>
<li>[<code>pyupgrade</code>] Improve diagnostic range for tuples
(<code>UP024</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23013">#23013</a>)</li>
<li>[<code>refurb</code>] Check subscripts in tuple do not use lambda
parameters in <code>reimplemented-operator</code> (<code>FURB118</code>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23079">#23079</a>)</li>
<li>[<code>ruff</code>] Detect mutable defaults in <code>field</code>
calls (<code>RUF008</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23046">#23046</a>)</li>
<li>[<code>ruff</code>] Ignore std <code>cmath.inf</code>
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23120">#23120</a>)</li>
<li>[<code>ruff</code>] New rule <code>float-equality-comparison</code>
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/20585">#20585</a>)</li>
<li>Don't format unlabeled Markdown code blocks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23106">#23106</a>)</li>
<li>Markdown formatting support in LSP (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23063">#23063</a>)</li>
<li>Support Quarto Markdown language markers (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22947">#22947</a>)</li>
<li>Support formatting <code>pycon</code> Markdown code blocks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23112">#23112</a>)</li>
<li>Use extension mapping to select Markdown code block language (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22934">#22934</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>Avoid false positive for undefined variables in <code>FAST001</code>
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23224">#23224</a>)</li>
<li>Avoid introducing syntax errors for <code>FAST003</code> autofix (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23227">#23227</a>)</li>
<li>Avoid suggesting <code>InitVar</code> for <code>__post_init__</code>
that references PEP 695 type parameters (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23226">#23226</a>)</li>
<li>Deduplicate type variables in generic functions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23225">#23225</a>)</li>
<li>Fix exception handler parenthesis removal for Python 3.14+ (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23126">#23126</a>)</li>
<li>Fix f-string middle panic when parsing t-strings (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23232">#23232</a>)</li>
<li>Wrap <code>RUF020</code> target for multiline fixes (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23210">#23210</a>)</li>
<li>Wrap <code>UP007</code> target for multiline fixes (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23208">#23208</a>)</li>
<li>Fix missing diagnostics for last range suppression in file (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23242">#23242</a>)</li>
<li>[<code>pyupgrade</code>] Fix syntax error on string with newline
escape and comment (<code>UP037</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22968">#22968</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Use <code>ruff</code> instead of <code>Ruff</code> as the program
name in GitHub output format (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23240">#23240</a>)</li>
<li>[<code>PT006</code>] Fix syntax error when unpacking nested tuples
in <code>parametrize</code> fixes (<a
href="https://redirect.github.com/astral-sh/ruff/issues/22441">#22441</a>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/22464">#22464</a>)</li>
<li>[<code>airflow</code>] Catch deprecated attribute access from
context key for Airflow 3.0 (<code>AIR301</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22850">#22850</a>)</li>
<li>[<code>airflow</code>] Capture deprecated arguments and a decorator
(<code>AIR301</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23170">#23170</a>)</li>
<li>[<code>flake8-boolean-trap</code>] Add
<code>multiprocessing.Value</code> to excluded functions for
<code>FBT003</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23010">#23010</a>)</li>
<li>[<code>flake8-bugbear</code>] Add a secondary annotation showing the
previous occurrence (<code>B033</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22634">#22634</a>)</li>
<li>[<code>flake8-type-checking</code>] Add sub-diagnostic showing the
runtime use of an annotation (<code>TC004</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23091">#23091</a>)</li>
<li>[<code>isort</code>] Support configurable import section heading
comments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23151">#23151</a>)</li>
<li>[<code>ruff</code>] Improve the diagnostic for <code>RUF012</code>
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23202">#23202</a>)</li>
</ul>
<h3>Formatter</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/ruff/commit/a2f11d239f91cf8daedb0764ec15fcfe29c5ae6d"><code>a2f11d2</code></a>
Prepare for 0.15.1 (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23253">#23253</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/d29628e9665baa17272aad489398eb72b70e60ff"><code>d29628e</code></a>
Remove docker-run-action (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23254">#23254</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/8a042667651d7b1cdfc1742478d2b29b04d91be0"><code>8a04266</code></a>
[ty] Allow discovering dependencies in system Python environments (<a
href="https://redirect.github.com/astral-sh/ruff/issues/22994">#22994</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/55d06c8879761c5500e9558502abc84cefcb7163"><code>55d06c8</code></a>
Ensure pending suppression diagnostics are reported (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23242">#23242</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/d056a9fa6dfb842f2c0d439bf7b1a8099e5734ea"><code>d056a9f</code></a>
[<code>isort</code>] support for configurable import section heading
comments (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23151">#23151</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/e22fa4f14d8fae550249e452d11bc53756df5c7a"><code>e22fa4f</code></a>
[ty] Fix method calls on subclasses of <code>Any</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23248">#23248</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/fa56c1550d723e458b91dc2405d5537d40401d5c"><code>fa56c15</code></a>
[ty] Fix bound method access on <code>None</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23246">#23246</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/4fd07d0e1cbbb4e4c3f5b4c1f04f2d8b3f4a2bf2"><code>4fd07d0</code></a>
Make range suppression test snapshot actually useful (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23251">#23251</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/8c63bced13b21d1952a56e6a096d9c2ec4af442f"><code>8c63bce</code></a>
[ty] Include conditional symbols (like <code>datetime.UTC</code>) in
auto-import in more...</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/46be94361b3b4c54be911eb88bfbd9666eb06a6d"><code>46be943</code></a>
Exclude WASM artifacts from GitHub releases (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23221">#23221</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/ruff/compare/0.14.14...0.15.1">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 <65985482+jkennedyvz@users.noreply.github.com>
2026-02-17 09:25:39 -08:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>John Kennedy
762b8f8579 chore(deps): bump the all-dependencies group in /libs/cli/js-examples with 17 updates (#6814)
Bumps the all-dependencies group in /libs/cli/js-examples with 17
updates:

| Package | From | To |
| --- | --- | --- |
| [@langchain/core](https://github.com/langchain-ai/langchainjs) |
`0.3.2` | `1.1.24` |
|
[@langchain/langgraph](https://github.com/langchain-ai/langgraphjs/tree/HEAD/libs/langgraph-core)
| `0.2.67` | `1.1.4` |
| [@eslint/eslintrc](https://github.com/eslint/eslintrc) | `3.1.0` |
`3.3.3` |
| [@eslint/js](https://github.com/eslint/eslint/tree/HEAD/packages/js) |
`9.9.1` | `10.0.1` |
|
[@tsconfig/recommended](https://github.com/tsconfig/bases/tree/HEAD/bases)
| `1.0.7` | `1.0.13` |
|
[@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin)
| `5.62.0` | `8.55.0` |
|
[@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser)
| `5.62.0` | `8.55.0` |
| [dotenv](https://github.com/motdotla/dotenv) | `16.4.5` | `17.3.1` |
| [eslint](https://github.com/eslint/eslint) | `8.57.0` | `10.0.0` |
|
[eslint-config-prettier](https://github.com/prettier/eslint-config-prettier)
| `8.10.0` | `10.1.8` |
|
[eslint-plugin-import](https://github.com/import-js/eslint-plugin-import)
| `2.29.1` | `2.32.0` |
|
[eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier)
| `4.2.1` | `5.5.5` |
| [jest](https://github.com/jestjs/jest/tree/HEAD/packages/jest) |
`29.7.0` | `30.2.0` |
|
[@types/jest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jest)
| `29.5.12` | `30.0.0` |
| [prettier](https://github.com/prettier/prettier) | `3.3.3` | `3.8.1` |
| [ts-jest](https://github.com/kulshekhar/ts-jest) | `29.2.4` | `29.4.6`
|
| [typescript](https://github.com/microsoft/TypeScript) | `5.5.4` |
`5.9.3` |

Updates `@langchain/core` from 0.3.2 to 1.1.24
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/langchain-ai/langchainjs/releases"><code>@​langchain/core</code>'s
releases</a>.</em></p>
<blockquote>
<h2><code>@​langchain/core</code><a
href="https://github.com/1"><code>@​1</code></a>.1.24</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/langchain-ai/langchainjs/pull/9978">#9978</a>
<a
href="https://github.com/langchain-ai/langchainjs/commit/70a440085b4bc2d036726ed12d9dc7841e914061"><code>70a4400</code></a>
Thanks <a
href="https://github.com/christian-bromann"><code>@​christian-bromann</code></a>!
- fix(core): fix web_search_call and file_search_call contentBlocks for
OpenAI Responses API</li>
</ul>
<h2><code>@​langchain/core</code><a
href="https://github.com/1"><code>@​1</code></a>.1.22</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/langchain-ai/langchainjs/pull/9995">#9995</a>
<a
href="https://github.com/langchain-ai/langchainjs/commit/8f166b159343ae6fd0d6d44c0835ab56c0b153f4"><code>8f166b1</code></a>
Thanks <a
href="https://github.com/kaigritun"><code>@​kaigritun</code></a>! -
fix(core): skip empty text blocks in ChatOpenAI contentBlocks</li>
</ul>
<h2><code>@​langchain/core</code><a
href="https://github.com/1"><code>@​1</code></a>.1.21</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/langchain-ai/langchainjs/pull/9990">#9990</a>
<a
href="https://github.com/langchain-ai/langchainjs/commit/d5e3db0d01ab321ec70a875805b2f74aefdadf9d"><code>d5e3db0</code></a>
Thanks <a href="https://github.com/hntrl"><code>@​hntrl</code></a>! -
feat(core): Add SSRF protection module
(<code>@langchain/core/utils/ssrf</code>) with utilities for validating
URLs against private IPs, cloud metadata endpoints, and localhost.</p>
<p>fix(community): Harden <code>RecursiveUrlLoader</code> against SSRF
attacks by integrating <code>validateSafeUrl</code> and replacing
string-based URL comparison with origin-based <code>isSameOrigin</code>
from the shared SSRF module.</p>
</li>
</ul>
<h2><code>@​langchain/core</code><a
href="https://github.com/1"><code>@​1</code></a>.1.19</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/langchain-ai/langchainjs/pull/9905">#9905</a>
<a
href="https://github.com/langchain-ai/langchainjs/commit/41bfea51cf119573a3b956ee782d2731fe71c681"><code>41bfea5</code></a>
Thanks <a
href="https://github.com/christian-bromann"><code>@​christian-bromann</code></a>!
- fix(classic/community/core): avoid long lived abort signals</li>
</ul>
<h2><code>@​langchain/core</code><a
href="https://github.com/1"><code>@​1</code></a>.1.18</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/langchain-ai/langchainjs/pull/9900">#9900</a>
<a
href="https://github.com/langchain-ai/langchainjs/commit/a9b50597186002221aaa4585246e569fa44c27c8"><code>a9b5059</code></a>
Thanks <a href="https://github.com/hntrl"><code>@​hntrl</code></a>! -
fix(core): update method signatures to use
<code>Partial&lt;CallOptions&gt;</code> for options parameters</p>
<p>Updated <code>invoke</code>, <code>stream</code>,
<code>generate</code>, and <code>generatePrompt</code> method signatures
across <code>Runnable</code>, <code>BaseChatModel</code>, and
<code>BaseLLM</code> to correctly accept
<code>Partial&lt;CallOptions&gt;</code> instead of full
<code>CallOptions</code>. This aligns the implementation with the
<code>RunnableInterface</code> specification and allows users to pass
partial options (e.g., <code>{ signal: abortedSignal }</code>) without
TypeScript errors.</p>
</li>
<li>
<p><a
href="https://redirect.github.com/langchain-ai/langchainjs/pull/9900">#9900</a>
<a
href="https://github.com/langchain-ai/langchainjs/commit/a9b50597186002221aaa4585246e569fa44c27c8"><code>a9b5059</code></a>
Thanks <a href="https://github.com/hntrl"><code>@​hntrl</code></a>! -
Improved abort signal handling for chat models:</p>
<ul>
<li>Added <code>ModelAbortError</code> class in
<code>@langchain/core/errors</code> that contains partial output when a
model invocation is aborted mid-stream</li>
<li><code>invoke()</code> now throws <code>ModelAbortError</code> with
accumulated <code>partialOutput</code> when aborted during streaming
(when using streaming callback handlers)</li>
<li><code>stream()</code> throws a regular <code>AbortError</code> when
aborted (since chunks are already yielded to the caller)</li>
<li>All provider implementations now properly check and propagate abort
signals in both <code>_generate()</code> and
<code>_streamResponseChunks()</code> methods</li>
<li>Added standard tests for abort signal behavior</li>
</ul>
</li>
</ul>
<h2><code>@​langchain/core</code><a
href="https://github.com/1"><code>@​1</code></a>.1.16</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/langchain-ai/langchainjs/pull/9830">#9830</a>
<a
href="https://github.com/langchain-ai/langchainjs/commit/70387a144464539d65a546c8130cf51dfad025a1"><code>70387a1</code></a>
Thanks <a
href="https://github.com/bracesproul"><code>@​bracesproul</code></a>! -
fix: More undefined null errors and tests</p>
</li>
<li>
<p><a
href="https://redirect.github.com/langchain-ai/langchainjs/pull/9679">#9679</a>
<a
href="https://github.com/langchain-ai/langchainjs/commit/a7c6ec51ab9baa186ab5ebf815599c08f5c7e8ab"><code>a7c6ec5</code></a>
Thanks <a
href="https://github.com/christian-bromann"><code>@​christian-bromann</code></a>!
- feat(openai): elevate OpenAI image generation outputs to proper image
content blocks</p>
</li>
<li>
<p><a
href="https://redirect.github.com/langchain-ai/langchainjs/pull/9817">#9817</a>
<a
href="https://github.com/langchain-ai/langchainjs/commit/5e045435a783fdae44bc9a43e01a8e5eb7100db2"><code>5e04543</code></a>
Thanks <a href="https://github.com/Ashx098"><code>@​Ashx098</code></a>!
- read error.status when response.status is absent to avoid retrying
OpenAI SDK 4xx</p>
</li>
<li>
<p><a
href="https://redirect.github.com/langchain-ai/langchainjs/pull/9819">#9819</a>
<a
href="https://github.com/langchain-ai/langchainjs/commit/40b446762445575844610ee528abc77c247b2c43"><code>40b4467</code></a>
Thanks <a
href="https://github.com/MrDockal"><code>@​MrDockal</code></a>! - Tool
call content returns compacted json</p>
</li>
<li>
<p><a
href="https://redirect.github.com/langchain-ai/langchainjs/pull/9815">#9815</a>
<a
href="https://github.com/langchain-ai/langchainjs/commit/17e30bd7f4c7bdf87c9c30304b3b9e121cc1fbbc"><code>17e30bd</code></a>
Thanks <a href="https://github.com/hntrl"><code>@​hntrl</code></a>! -
fix(core): respect tracingEnabled=false from RunTree when env tracing is
enabled</p>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/langchain-ai/langchainjs/commit/0eed408d8b005564197809e1e8366ee336364371"><code>0eed408</code></a>
chore: version packages (<a
href="https://redirect.github.com/langchain-ai/langchainjs/issues/10012">#10012</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchainjs/commit/70a440085b4bc2d036726ed12d9dc7841e914061"><code>70a4400</code></a>
fix(core): fix web_search_call and file_search_call contentBlocks for
OpenAI ...</li>
<li><a
href="https://github.com/langchain-ai/langchainjs/commit/bf6eac40179f87da18fd122b4efc2ee48cd44b6c"><code>bf6eac4</code></a>
fix(langchain): fix structured output on opus (<a
href="https://redirect.github.com/langchain-ai/langchainjs/issues/10010">#10010</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchainjs/commit/2d05e3af944e4c325d912b0eb404cb9db6d696a6"><code>2d05e3a</code></a>
fix(google): use tsdown (<a
href="https://redirect.github.com/langchain-ai/langchainjs/issues/10011">#10011</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchainjs/commit/d686aec0fa044df65fd4a4ee8cf24c2d931f67fc"><code>d686aec</code></a>
chore: version packages (<a
href="https://redirect.github.com/langchain-ai/langchainjs/issues/9999">#9999</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchainjs/commit/295687448772af89b35d9f2a446344f9e1de0e18"><code>2956874</code></a>
feat(google): add model profiles (<a
href="https://redirect.github.com/langchain-ai/langchainjs/issues/10009">#10009</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchainjs/commit/5283513740ff93063f9c1eaa583365f590ec5994"><code>5283513</code></a>
fix(langchain): re-export missing interface (<a
href="https://redirect.github.com/langchain-ai/langchainjs/issues/10008">#10008</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchainjs/commit/d1365a125fc9d0d17120d923957841a33ba160cf"><code>d1365a1</code></a>
fix: map mcp resource link content blocks to langchain url content block
(<a
href="https://redirect.github.com/langchain-ai/langchainjs/issues/10">#10</a>...</li>
<li><a
href="https://github.com/langchain-ai/langchainjs/commit/35d54fb1a7cee8f22c1bac7f03cf63e4b19b4333"><code>35d54fb</code></a>
chore(google): use core caret resolution (<a
href="https://redirect.github.com/langchain-ai/langchainjs/issues/10007">#10007</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchainjs/commit/885771766f256eb66638c74d3c8925cc34c58e77"><code>8857717</code></a>
chore(deps): bump langsmith from 0.5.0 to 0.5.1 (<a
href="https://redirect.github.com/langchain-ai/langchainjs/issues/10006">#10006</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/langchain-ai/langchainjs/compare/0.3.2...@langchain/core@1.1.24">compare
view</a></li>
</ul>
</details>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by [GitHub Actions](<a
href="https://www.npmjs.com/~GitHub">https://www.npmjs.com/~GitHub</a>
Actions), a new releaser for <code>@​langchain/core</code> since your
current version.</p>
</details>
<br />

Updates `@langchain/langgraph` from 0.2.67 to 1.1.4
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/langchain-ai/langgraphjs/releases"><code>@​langchain/langgraph</code>'s
releases</a>.</em></p>
<blockquote>
<h2><code>@​langchain/langgraph-checkpoint-mongodb</code><a
href="https://github.com/1"><code>@​1</code></a>.1.4</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/langchain-ai/langgraphjs/pull/1853">#1853</a>
<a
href="https://github.com/langchain-ai/langgraphjs/commit/a84c1ff18289653ff4715bd0db4ac3d06600556e"><code>a84c1ff</code></a>
Thanks <a
href="https://github.com/christian-bromann"><code>@​christian-bromann</code></a>!
- retry release: Updates the checkpoint-mongodb to append client
metadata</li>
</ul>
<h2><code>@​langchain/langgraph</code><a
href="https://github.com/1"><code>@​1</code></a>.1.4</h2>
<h3>Patch Changes</h3>
<ul>
<li>Updated dependencies [<a
href="https://github.com/langchain-ai/langgraphjs/commit/8d5c2d688d330012638d8f34ce20a454600ebc1b"><code>8d5c2d6</code></a>]:
<ul>
<li><code>@​langchain/langgraph-sdk</code><a
href="https://github.com/1"><code>@​1</code></a>.6.0</li>
</ul>
</li>
</ul>
<h2><code>@​langchain/langgraph</code><a
href="https://github.com/1"><code>@​1</code></a>.1.3</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/langchain-ai/langgraphjs/pull/1932">#1932</a>
<a
href="https://github.com/langchain-ai/langgraphjs/commit/0cda1f3b78a86e7809b7db15a7ff0ea00ee1ecd8"><code>0cda1f3</code></a>
Thanks <a
href="https://github.com/samecrowder"><code>@​samecrowder</code></a>! -
fix: preserve <code>langgraph_type</code> metadata for LangSmith Studio
tab detection</p>
<ul>
<li><strong>Zod v4 <code>.register()</code> fix</strong>: The metadata
registry now properly stores and retrieves <code>langgraph_type</code>
metadata when using Zod v4's <code>.register()</code> method with
<code>MessagesZodMeta</code></li>
<li><strong>StateSchema fix</strong>:
<code>StateSchema.getJsonSchema()</code> now correctly includes
<code>jsonSchemaExtra</code> (like <code>langgraph_type:
&quot;messages&quot;</code>) even when the underlying schema (e.g.,
<code>z.custom()</code>) doesn't produce a JSON schema</li>
</ul>
</li>
</ul>
<h2><code>@​langchain/langgraph</code><a
href="https://github.com/1"><code>@​1</code></a>.1.2</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/langchain-ai/langgraphjs/pull/1914">#1914</a>
<a
href="https://github.com/langchain-ai/langgraphjs/commit/e60ec1be6efc3b7fd1bde907de3d1d08fa2a0262"><code>e60ec1b</code></a>
Thanks <a href="https://github.com/hntrl"><code>@​hntrl</code></a>! -
fix ConditionalEdgeRouter type rejection</p>
</li>
<li>
<p><a
href="https://redirect.github.com/langchain-ai/langgraphjs/pull/1916">#1916</a>
<a
href="https://github.com/langchain-ai/langgraphjs/commit/9f34c8ce420f44c604f12468806be807f7b372c1"><code>9f34c8c</code></a>
Thanks <a href="https://github.com/hntrl"><code>@​hntrl</code></a>! -
Add unified schema support for <code>StateGraph</code> constructor</p>
<ul>
<li>Support mixing <code>AnnotationRoot</code>, Zod schemas, and
<code>StateSchema</code> for state, input, and output definitions</li>
<li>Add <code>{ input, output }</code> only pattern where state is
inferred from input schema</li>
<li>Add per-node input schema support via <code>addNode</code>
options</li>
<li>Deprecate <code>stateSchema</code> property in favor of
<code>state</code></li>
<li>Simplify constructor overloads with unified
<code>StateGraphInit</code> type</li>
</ul>
</li>
<li>
<p><a
href="https://redirect.github.com/langchain-ai/langgraphjs/pull/1918">#1918</a>
<a
href="https://github.com/langchain-ai/langgraphjs/commit/cc12263ad26804ef53760cabf1bd2fda0be575d6"><code>cc12263</code></a>
Thanks <a href="https://github.com/hntrl"><code>@​hntrl</code></a>! -
Add type bag pattern for <code>GraphNode</code> and
<code>ConditionalEdgeRouter</code> type utilities.</p>
<p><strong>New types:</strong></p>
<ul>
<li><code>GraphNodeTypes&lt;InputSchema, OutputSchema, ContextSchema,
Nodes&gt;</code> - Type bag interface for GraphNode</li>
<li><code>GraphNodeReturnValue&lt;Update, Nodes&gt;</code> - Return type
helper for node functions</li>
<li><code>ConditionalEdgeRouterTypes&lt;InputSchema, ContextSchema,
Nodes&gt;</code> - Type bag interface for ConditionalEdgeRouter</li>
</ul>
<p><strong>Usage:</strong></p>
<p>Both <code>GraphNode</code> and <code>ConditionalEdgeRouter</code>
now support two patterns:</p>
<ol>
<li>
<p><strong>Single schema</strong> (backward compatible):</p>
<pre lang="typescript"><code>const node: GraphNode&lt;typeof AgentState,
MyContext, &quot;agent&quot; | &quot;tool&quot;&gt; = ...
</code></pre>
</li>
</ol>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/langchain-ai/langgraphjs/blob/main/libs/langgraph-core/CHANGELOG.md"><code>@​langchain/langgraph</code>'s
changelog</a>.</em></p>
<blockquote>
<h2>1.1.4</h2>
<h3>Patch Changes</h3>
<ul>
<li>Updated dependencies [<a
href="https://github.com/langchain-ai/langgraphjs/commit/8d5c2d688d330012638d8f34ce20a454600ebc1b"><code>8d5c2d6</code></a>]:
<ul>
<li><code>@​langchain/langgraph-sdk</code><a
href="https://github.com/1"><code>@​1</code></a>.6.0</li>
</ul>
</li>
</ul>
<h2>1.1.3</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/langchain-ai/langgraphjs/pull/1932">#1932</a>
<a
href="https://github.com/langchain-ai/langgraphjs/commit/0cda1f3b78a86e7809b7db15a7ff0ea00ee1ecd8"><code>0cda1f3</code></a>
Thanks <a
href="https://github.com/samecrowder"><code>@​samecrowder</code></a>! -
fix: preserve <code>langgraph_type</code> metadata for LangSmith Studio
tab detection</p>
<ul>
<li><strong>Zod v4 <code>.register()</code> fix</strong>: The metadata
registry now properly stores and retrieves <code>langgraph_type</code>
metadata when using Zod v4's <code>.register()</code> method with
<code>MessagesZodMeta</code></li>
<li><strong>StateSchema fix</strong>:
<code>StateSchema.getJsonSchema()</code> now correctly includes
<code>jsonSchemaExtra</code> (like <code>langgraph_type:
&quot;messages&quot;</code>) even when the underlying schema (e.g.,
<code>z.custom()</code>) doesn't produce a JSON schema</li>
</ul>
</li>
</ul>
<h2>1.1.2</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/langchain-ai/langgraphjs/pull/1914">#1914</a>
<a
href="https://github.com/langchain-ai/langgraphjs/commit/e60ec1be6efc3b7fd1bde907de3d1d08fa2a0262"><code>e60ec1b</code></a>
Thanks <a href="https://github.com/hntrl"><code>@​hntrl</code></a>! -
fix ConditionalEdgeRouter type rejection</p>
</li>
<li>
<p><a
href="https://redirect.github.com/langchain-ai/langgraphjs/pull/1916">#1916</a>
<a
href="https://github.com/langchain-ai/langgraphjs/commit/9f34c8ce420f44c604f12468806be807f7b372c1"><code>9f34c8c</code></a>
Thanks <a href="https://github.com/hntrl"><code>@​hntrl</code></a>! -
Add unified schema support for <code>StateGraph</code> constructor</p>
<ul>
<li>Support mixing <code>AnnotationRoot</code>, Zod schemas, and
<code>StateSchema</code> for state, input, and output definitions</li>
<li>Add <code>{ input, output }</code> only pattern where state is
inferred from input schema</li>
<li>Add per-node input schema support via <code>addNode</code>
options</li>
<li>Deprecate <code>stateSchema</code> property in favor of
<code>state</code></li>
<li>Simplify constructor overloads with unified
<code>StateGraphInit</code> type</li>
</ul>
</li>
<li>
<p><a
href="https://redirect.github.com/langchain-ai/langgraphjs/pull/1918">#1918</a>
<a
href="https://github.com/langchain-ai/langgraphjs/commit/cc12263ad26804ef53760cabf1bd2fda0be575d6"><code>cc12263</code></a>
Thanks <a href="https://github.com/hntrl"><code>@​hntrl</code></a>! -
Add type bag pattern for <code>GraphNode</code> and
<code>ConditionalEdgeRouter</code> type utilities.</p>
<p><strong>New types:</strong></p>
<ul>
<li><code>GraphNodeTypes&lt;InputSchema, OutputSchema, ContextSchema,
Nodes&gt;</code> - Type bag interface for GraphNode</li>
<li><code>GraphNodeReturnValue&lt;Update, Nodes&gt;</code> - Return type
helper for node functions</li>
<li><code>ConditionalEdgeRouterTypes&lt;InputSchema, ContextSchema,
Nodes&gt;</code> - Type bag interface for ConditionalEdgeRouter</li>
</ul>
<p><strong>Usage:</strong></p>
<p>Both <code>GraphNode</code> and <code>ConditionalEdgeRouter</code>
now support two patterns:</p>
<ol>
<li>
<p><strong>Single schema</strong> (backward compatible):</p>
<pre lang="typescript"><code>const node: GraphNode&lt;typeof AgentState,
MyContext, &quot;agent&quot; | &quot;tool&quot;&gt; = ...
</code></pre>
</li>
<li>
<p><strong>Type bag pattern</strong> (new):</p>
<pre lang="typescript"><code></code></pre>
</li>
</ol>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/langchain-ai/langgraphjs/commit/f38f82ffd0c4df2349b16a94713fa63a1014eec0"><code>f38f82f</code></a>
chore: version packages (<a
href="https://github.com/langchain-ai/langgraphjs/tree/HEAD/libs/langgraph-core/issues/1945">#1945</a>)</li>
<li><a
href="https://github.com/langchain-ai/langgraphjs/commit/8d5c2d688d330012638d8f34ce20a454600ebc1b"><code>8d5c2d6</code></a>
feat(sdk): add multi-subagent tracking to useStream (<a
href="https://github.com/langchain-ai/langgraphjs/tree/HEAD/libs/langgraph-core/issues/1903">#1903</a>)</li>
<li><a
href="https://github.com/langchain-ai/langgraphjs/commit/a0964fbd16979cbb4401640504e464b368bce168"><code>a0964fb</code></a>
chore: version packages (<a
href="https://github.com/langchain-ai/langgraphjs/tree/HEAD/libs/langgraph-core/issues/1936">#1936</a>)</li>
<li><a
href="https://github.com/langchain-ai/langgraphjs/commit/0cda1f3b78a86e7809b7db15a7ff0ea00ee1ecd8"><code>0cda1f3</code></a>
fix: studio zod issue (<a
href="https://github.com/langchain-ai/langgraphjs/tree/HEAD/libs/langgraph-core/issues/1932">#1932</a>)</li>
<li><a
href="https://github.com/langchain-ai/langgraphjs/commit/990040da221198e9e5c982949f28e24a61a4605d"><code>990040d</code></a>
chore: version packages (<a
href="https://github.com/langchain-ai/langgraphjs/tree/HEAD/libs/langgraph-core/issues/1921">#1921</a>)</li>
<li><a
href="https://github.com/langchain-ai/langgraphjs/commit/160f2e0dc5cafe252f44c5bb256105b685f42c83"><code>160f2e0</code></a>
chore: version packages (<a
href="https://github.com/langchain-ai/langgraphjs/tree/HEAD/libs/langgraph-core/issues/1915">#1915</a>)</li>
<li><a
href="https://github.com/langchain-ai/langgraphjs/commit/cc12263ad26804ef53760cabf1bd2fda0be575d6"><code>cc12263</code></a>
feat(langgraph): add type bag pattern for GraphNode and
ConditionalEdgeRouter...</li>
<li><a
href="https://github.com/langchain-ai/langgraphjs/commit/9f34c8ce420f44c604f12468806be807f7b372c1"><code>9f34c8c</code></a>
feat(langgraph): add mixed schema support for StateGraph input/output
(<a
href="https://github.com/langchain-ai/langgraphjs/tree/HEAD/libs/langgraph-core/issues/1916">#1916</a>)</li>
<li><a
href="https://github.com/langchain-ai/langgraphjs/commit/e60ec1be6efc3b7fd1bde907de3d1d08fa2a0262"><code>e60ec1b</code></a>
fix(langgraph): fix ConditionalEdgeRouter type rejection (<a
href="https://github.com/langchain-ai/langgraphjs/tree/HEAD/libs/langgraph-core/issues/1914">#1914</a>)</li>
<li><a
href="https://github.com/langchain-ai/langgraphjs/commit/0812242b86c08360cf76564fe53e573d9991f75e"><code>0812242</code></a>
chore: version packages (<a
href="https://github.com/langchain-ai/langgraphjs/tree/HEAD/libs/langgraph-core/issues/1905">#1905</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/langchain-ai/langgraphjs/commits/@langchain/langgraph@1.1.4/libs/langgraph-core">compare
view</a></li>
</ul>
</details>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by [GitHub Actions](<a
href="https://www.npmjs.com/~GitHub">https://www.npmjs.com/~GitHub</a>
Actions), a new releaser for <code>@​langchain/langgraph</code> since
your current version.</p>
</details>
<details>
<summary>Install script changes</summary>
<p>This version adds <code>prepublish</code> script that runs during
installation. Review the package contents before updating.</p>
</details>
<br />

Updates `@eslint/eslintrc` from 3.1.0 to 3.3.3
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/eslint/eslintrc/releases"><code>@​eslint/eslintrc</code>'s
releases</a>.</em></p>
<blockquote>
<h2>eslintrc: v3.3.3</h2>
<h2><a
href="https://github.com/eslint/eslintrc/compare/eslintrc-v3.3.2...eslintrc-v3.3.3">3.3.3</a>
(2025-11-28)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>release v3.3.3 because publishing v3.3.2 failed (<a
href="https://redirect.github.com/eslint/eslintrc/issues/211">#211</a>)
(<a
href="https://github.com/eslint/eslintrc/commit/8aa555a3f5fcfb7d99249fb57e819a7b6f635496">8aa555a</a>)</li>
</ul>
<h2>eslintrc: v3.3.2</h2>
<h2><a
href="https://github.com/eslint/eslintrc/compare/eslintrc-v3.3.1...eslintrc-v3.3.2">3.3.2</a>
(2025-11-25)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>Remove name property from all and recommended configs (<a
href="https://redirect.github.com/eslint/eslintrc/issues/200">#200</a>)
(<a
href="https://github.com/eslint/eslintrc/commit/344da491898a2a3595943d4528ba78fe2f238217">344da49</a>)</li>
</ul>
<h2>v3.3.1</h2>
<h2><a
href="https://github.com/eslint/eslintrc/compare/v3.3.0...v3.3.1">3.3.1</a>
(2025-03-11)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>correct <code>types</code> field in package.json (<a
href="https://redirect.github.com/eslint/eslintrc/issues/184">#184</a>)
(<a
href="https://github.com/eslint/eslintrc/commit/2f4cf3fe36ee0df93c1c53f32c030c58db1816a2">2f4cf3f</a>)</li>
</ul>
<h2>v3.3.0</h2>
<h2><a
href="https://github.com/eslint/eslintrc/compare/v3.2.0...v3.3.0">3.3.0</a>
(2025-02-21)</h2>
<h3>Features</h3>
<ul>
<li>Add types to package (<a
href="https://redirect.github.com/eslint/eslintrc/issues/179">#179</a>)
(<a
href="https://github.com/eslint/eslintrc/commit/cb546be8ba53abcb4c64ed2fdd3a729dd1337f61">cb546be</a>)</li>
</ul>
<h2>v3.2.0</h2>
<h2><a
href="https://github.com/eslint/eslintrc/compare/v3.1.0...v3.2.0">3.2.0</a>
(2024-11-14)</h2>
<h3>Features</h3>
<ul>
<li>merge rule.meta.defaultOptions before validation (<a
href="https://redirect.github.com/eslint/eslintrc/issues/166">#166</a>)
(<a
href="https://github.com/eslint/eslintrc/commit/d02f91452b81caff971f7895237cc4fb002e31da">d02f914</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/eslint/eslintrc/blob/main/CHANGELOG.md"><code>@​eslint/eslintrc</code>'s
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/eslint/eslintrc/compare/eslintrc-v3.3.2...eslintrc-v3.3.3">3.3.3</a>
(2025-11-28)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>release v3.3.3 because publishing v3.3.2 failed (<a
href="https://redirect.github.com/eslint/eslintrc/issues/211">#211</a>)
(<a
href="https://github.com/eslint/eslintrc/commit/8aa555a3f5fcfb7d99249fb57e819a7b6f635496">8aa555a</a>)</li>
</ul>
<h2><a
href="https://github.com/eslint/eslintrc/compare/eslintrc-v3.3.1...eslintrc-v3.3.2">3.3.2</a>
(2025-11-25)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>Remove name property from all and recommended configs (<a
href="https://redirect.github.com/eslint/eslintrc/issues/200">#200</a>)
(<a
href="https://github.com/eslint/eslintrc/commit/344da491898a2a3595943d4528ba78fe2f238217">344da49</a>)</li>
</ul>
<h2><a
href="https://github.com/eslint/eslintrc/compare/v3.3.0...v3.3.1">3.3.1</a>
(2025-03-11)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>correct <code>types</code> field in package.json (<a
href="https://redirect.github.com/eslint/eslintrc/issues/184">#184</a>)
(<a
href="https://github.com/eslint/eslintrc/commit/2f4cf3fe36ee0df93c1c53f32c030c58db1816a2">2f4cf3f</a>)</li>
</ul>
<h2><a
href="https://github.com/eslint/eslintrc/compare/v3.2.0...v3.3.0">3.3.0</a>
(2025-02-21)</h2>
<h3>Features</h3>
<ul>
<li>Add types to package (<a
href="https://redirect.github.com/eslint/eslintrc/issues/179">#179</a>)
(<a
href="https://github.com/eslint/eslintrc/commit/cb546be8ba53abcb4c64ed2fdd3a729dd1337f61">cb546be</a>)</li>
</ul>
<h2><a
href="https://github.com/eslint/eslintrc/compare/v3.1.0...v3.2.0">3.2.0</a>
(2024-11-14)</h2>
<h3>Features</h3>
<ul>
<li>merge rule.meta.defaultOptions before validation (<a
href="https://redirect.github.com/eslint/eslintrc/issues/166">#166</a>)
(<a
href="https://github.com/eslint/eslintrc/commit/d02f91452b81caff971f7895237cc4fb002e31da">d02f914</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/eslint/eslintrc/commit/fdb529826fd769f2bdcd1281d711412253561231"><code>fdb5298</code></a>
chore: release 3.3.3 🚀 (<a
href="https://redirect.github.com/eslint/eslintrc/issues/212">#212</a>)</li>
<li><a
href="https://github.com/eslint/eslintrc/commit/8aa555a3f5fcfb7d99249fb57e819a7b6f635496"><code>8aa555a</code></a>
fix: release v3.3.3 because publishing v3.3.2 failed (<a
href="https://redirect.github.com/eslint/eslintrc/issues/211">#211</a>)</li>
<li><a
href="https://github.com/eslint/eslintrc/commit/a8b773d0cfecbd987e4301ad40be271a2c800c40"><code>a8b773d</code></a>
chore: release 3.3.2 🚀 (<a
href="https://redirect.github.com/eslint/eslintrc/issues/204">#204</a>)</li>
<li><a
href="https://github.com/eslint/eslintrc/commit/85244bb33023f25eb8ac443d08b769be7bafec2e"><code>85244bb</code></a>
chore: switch to <code>googleapis/release-please-action</code> (<a
href="https://redirect.github.com/eslint/eslintrc/issues/208">#208</a>)</li>
<li><a
href="https://github.com/eslint/eslintrc/commit/d356360dfee5173b3ace73cc1f3ecb922eb4310d"><code>d356360</code></a>
docs: Update README sponsors</li>
<li><a
href="https://github.com/eslint/eslintrc/commit/116bf0332e3ce6dd848704b3782c8c77067c635b"><code>116bf03</code></a>
chore: update js-yaml to version 4.1.1 (<a
href="https://redirect.github.com/eslint/eslintrc/issues/207">#207</a>)</li>
<li><a
href="https://github.com/eslint/eslintrc/commit/16e8d207557fcac8512bd5d9ffd475ec777db0df"><code>16e8d20</code></a>
docs: Update README sponsors</li>
<li><a
href="https://github.com/eslint/eslintrc/commit/3b089acfeba445f3fef84662c43143a5d0eb8a15"><code>3b089ac</code></a>
chore: update <code>.gitignore</code> to exclude shared workflows (<a
href="https://redirect.github.com/eslint/eslintrc/issues/206">#206</a>)</li>
<li><a
href="https://github.com/eslint/eslintrc/commit/1f6e2d19b2f9617c10597fbe97ac99076a716a0c"><code>1f6e2d1</code></a>
docs: Update README sponsors</li>
<li><a
href="https://github.com/eslint/eslintrc/commit/785c00b8cce58c2b4962996699e0f3dbdc6d2d13"><code>785c00b</code></a>
docs: Update README sponsors</li>
<li>Additional commits viewable in <a
href="https://github.com/eslint/eslintrc/compare/v3.1.0...eslintrc-v3.3.3">compare
view</a></li>
</ul>
</details>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by [GitHub Actions](<a
href="https://www.npmjs.com/~GitHub">https://www.npmjs.com/~GitHub</a>
Actions), a new releaser for <code>@​eslint/eslintrc</code> since your
current version.</p>
</details>
<br />

Updates `@eslint/js` from 9.9.1 to 10.0.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/eslint/eslint/releases"><code>@​eslint/js</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v10.0.0</h2>
<h2>Breaking Changes</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/f9e54f43a5e497cdfa179338b431093245cb787b"><code>f9e54f4</code></a>
feat!: estimate rule-tester failure location (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20420">#20420</a>)
(ST-DDT)</li>
<li><a
href="https://github.com/eslint/eslint/commit/a176319d8ade1a7d9b2d7fb8f038f55a2662325f"><code>a176319</code></a>
feat!: replace <code>chalk</code> with <code>styleText</code> and add
<code>color</code> to <code>ResultsMeta</code> (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20227">#20227</a>)
(루밀LuMir)</li>
<li><a
href="https://github.com/eslint/eslint/commit/c7046e6c1e03c4ca0eee4888a1f2eba4c6454f84"><code>c7046e6</code></a>
feat!: enable JSX reference tracking (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20152">#20152</a>)
(Pixel998)</li>
<li><a
href="https://github.com/eslint/eslint/commit/fa31a608901684fbcd9906d1907e66561d16e5aa"><code>fa31a60</code></a>
feat!: add <code>name</code> to configs (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20015">#20015</a>)
(Kirk Waiblinger)</li>
<li><a
href="https://github.com/eslint/eslint/commit/3383e7ec9028166cafc8ea7986c2f7498d0049f0"><code>3383e7e</code></a>
fix!: remove deprecated <code>SourceCode</code> methods (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20137">#20137</a>)
(Pixel998)</li>
<li><a
href="https://github.com/eslint/eslint/commit/501abd0e916a35554c58b7c0365537f1fa3880ce"><code>501abd0</code></a>
feat!: update dependency minimatch to v10 (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20246">#20246</a>)
(renovate[bot])</li>
<li><a
href="https://github.com/eslint/eslint/commit/ca4d3b40085de47561f89656a2207d09946ed45e"><code>ca4d3b4</code></a>
fix!: stricter rule tester assertions for valid test cases (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20125">#20125</a>)
(唯然)</li>
<li><a
href="https://github.com/eslint/eslint/commit/96512a66c86402fb0538cdcb6cd30b9073f6bf3b"><code>96512a6</code></a>
fix!: Remove deprecated rule context methods (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20086">#20086</a>)
(Nicholas C. Zakas)</li>
<li><a
href="https://github.com/eslint/eslint/commit/c69fdacdb2e886b9d965568a397aa8220db3fe90"><code>c69fdac</code></a>
feat!: remove eslintrc support (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20037">#20037</a>)
(Francesco Trotta)</li>
<li><a
href="https://github.com/eslint/eslint/commit/208b5cc34a8374ff81412b5bec2e0800eebfbd04"><code>208b5cc</code></a>
feat!: Use <code>ScopeManager#addGlobals()</code> (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20132">#20132</a>)
(Milos Djermanovic)</li>
<li><a
href="https://github.com/eslint/eslint/commit/a2ee188ea7a38a0c6155f3d39e2b00e1d0f36e14"><code>a2ee188</code></a>
fix!: add <code>uniqueItems: true</code> in
<code>no-invalid-regexp</code> option (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20155">#20155</a>)
(Tanuj Kanti)</li>
<li><a
href="https://github.com/eslint/eslint/commit/a89059dbf2832d417dd493ee81483227ec44e4ab"><code>a89059d</code></a>
feat!: Program range span entire source text (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20133">#20133</a>)
(Pixel998)</li>
<li><a
href="https://github.com/eslint/eslint/commit/39a6424373d915fa9de0d7b0caba9a4dc3da9b53"><code>39a6424</code></a>
fix!: assert 'text' is a string across all RuleFixer methods (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20082">#20082</a>)
(Pixel998)</li>
<li><a
href="https://github.com/eslint/eslint/commit/f28fbf846244e043c92b355b224d121b06140b44"><code>f28fbf8</code></a>
fix!: Deprecate <code>&quot;always&quot;</code> and
<code>&quot;as-needed&quot;</code> options of the <code>radix</code>
rule (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20223">#20223</a>)
(Milos Djermanovic)</li>
<li><a
href="https://github.com/eslint/eslint/commit/aa3fb2b233e929b37220be940575f42c280e0b98"><code>aa3fb2b</code></a>
fix!: tighten <code>func-names</code> schema (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20119">#20119</a>)
(Pixel998)</li>
<li><a
href="https://github.com/eslint/eslint/commit/f6c0ed0311dcfee853367d5068c765d066e6b756"><code>f6c0ed0</code></a>
feat!: report <code>eslint-env</code> comments as errors (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20128">#20128</a>)
(Francesco Trotta)</li>
<li><a
href="https://github.com/eslint/eslint/commit/4bf739fb533e59f7f0a66b65f7bc80be0f37d8db"><code>4bf739f</code></a>
fix!: remove deprecated <code>LintMessage#nodeType</code> and
<code>TestCaseError#type</code> (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20096">#20096</a>)
(Pixel998)</li>
<li><a
href="https://github.com/eslint/eslint/commit/523c076866400670fb2192a3f55dbf7ad3469247"><code>523c076</code></a>
feat!: drop support for jiti &lt; 2.2.0 (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20016">#20016</a>)
(michael faith)</li>
<li><a
href="https://github.com/eslint/eslint/commit/454a292c95f34dad232411ddac06408e6383bb64"><code>454a292</code></a>
feat!: update <code>eslint:recommended</code> configuration (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20210">#20210</a>)
(Pixel998)</li>
<li><a
href="https://github.com/eslint/eslint/commit/4f880ee02992e1bf0e96ebaba679985e2d1295f1"><code>4f880ee</code></a>
feat!: remove <code>v10_*</code> and inactive <code>unstable_*</code>
flags (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20225">#20225</a>)
(sethamus)</li>
<li><a
href="https://github.com/eslint/eslint/commit/f18115c363a4ac7671a4c7f30ee13d57ebba330f"><code>f18115c</code></a>
feat!: <code>no-shadow-restricted-names</code> report
<code>globalThis</code> by default (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20027">#20027</a>)
(sethamus)</li>
<li><a
href="https://github.com/eslint/eslint/commit/c6358c31fbd3937b92d89be2618ffdf5a774604e"><code>c6358c3</code></a>
feat!: Require Node.js <code>^20.19.0 || ^22.13.0 || &gt;=24</code> (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20160">#20160</a>)
(Milos Djermanovic)</li>
</ul>
<h2>Features</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/bff9091927811497dbf066b0e3b85ecb37d43822"><code>bff9091</code></a>
feat: handle <code>Array.fromAsync</code> in
<code>array-callback-return</code> (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20457">#20457</a>)
(Francesco Trotta)</li>
<li><a
href="https://github.com/eslint/eslint/commit/290c594bb50c439fb71bc75521ee5360daa8c222"><code>290c594</code></a>
feat: add <code>self</code> to <code>no-implied-eval</code> rule (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20468">#20468</a>)
(sethamus)</li>
<li><a
href="https://github.com/eslint/eslint/commit/43677de07ebd6e14bfac40a46ad749ba783c45f2"><code>43677de</code></a>
feat: fix handling of function and class expression names in
<code>no-shadow</code> (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20432">#20432</a>)
(Milos Djermanovic)</li>
<li><a
href="https://github.com/eslint/eslint/commit/f0cafe5f37e7765e9d8c2751b5f5d33107687009"><code>f0cafe5</code></a>
feat: rule tester add assertion option <code>requireData</code> (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20409">#20409</a>)
(fnx)</li>
<li><a
href="https://github.com/eslint/eslint/commit/f7ab6937e63bc618d326710858f5861a68f80616"><code>f7ab693</code></a>
feat: output RuleTester test case failure index (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/19976">#19976</a>)
(ST-DDT)</li>
<li><a
href="https://github.com/eslint/eslint/commit/7cbcbf9c3c2008deee7d143ae35e668e8ffbccb3"><code>7cbcbf9</code></a>
feat: add <code>countThis</code> option to <code>max-params</code> (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20236">#20236</a>)
(Gerkin)</li>
<li><a
href="https://github.com/eslint/eslint/commit/f148a5eaa1e89dd80ade62f0a690186b00b9f6e1"><code>f148a5e</code></a>
feat: add error assertion options (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20247">#20247</a>)
(ST-DDT)</li>
<li><a
href="https://github.com/eslint/eslint/commit/09e66549ecada6dcb8c567a60faf044fce049188"><code>09e6654</code></a>
feat: update error loc of <code>require-yield</code> and
<code>no-useless-constructor</code> (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20267">#20267</a>)
(Tanuj Kanti)</li>
</ul>
<h2>Bug Fixes</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/436b82f3c0a8cfa2fdc17d173e95ea11d5d3ee03"><code>436b82f</code></a>
fix: update eslint (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20473">#20473</a>)
(renovate[bot])</li>
<li><a
href="https://github.com/eslint/eslint/commit/1d29d22fe302443cec2a11da0816397f94af97ec"><code>1d29d22</code></a>
fix: detect default <code>this</code> binding in
<code>Array.fromAsync</code> callbacks (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20456">#20456</a>)
(Francesco Trotta)</li>
<li><a
href="https://github.com/eslint/eslint/commit/727451eff55b35d853e0e443d0de58f4550762bf"><code>727451e</code></a>
fix: fix regression of global mode report range in <code>strict</code>
rule (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20462">#20462</a>)
(ntnyq)</li>
<li><a
href="https://github.com/eslint/eslint/commit/e80485fcd27196fa0b6f6b5c7ac8cf49ad4b079d"><code>e80485f</code></a>
fix: remove fake <code>FlatESLint</code> and <code>LegacyESLint</code>
exports (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20460">#20460</a>)
(Francesco Trotta)</li>
<li><a
href="https://github.com/eslint/eslint/commit/9eeff3bc13813a786b8a4c3815def97c0fb646ef"><code>9eeff3b</code></a>
fix: update esquery (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20423">#20423</a>)
(cryptnix)</li>
<li><a
href="https://github.com/eslint/eslint/commit/b34b93852d014ebbcf3538d892b55e0216cdf681"><code>b34b938</code></a>
fix: use <code>Error.prepareStackTrace</code> to estimate failing test
location (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20436">#20436</a>)
(Francesco Trotta)</li>
<li><a
href="https://github.com/eslint/eslint/commit/51aab5393b058f7cbed69041a9069b2bd106aabd"><code>51aab53</code></a>
fix: update eslint (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20443">#20443</a>)
(renovate[bot])</li>
<li><a
href="https://github.com/eslint/eslint/commit/23490b266276792896a0b7b43c49a1ce87bf8568"><code>23490b2</code></a>
fix: handle space before colon in <code>RuleTester</code> location
estimation (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20433">#20433</a>)
(Francesco Trotta)</li>
<li><a
href="https://github.com/eslint/eslint/commit/f244dbf2191267a4cafd08645243624baf3e8c83"><code>f244dbf</code></a>
fix: use <code>MessagePlaceholderData</code> type from
<code>@eslint/core</code> (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20348">#20348</a>)
(루밀LuMir)</li>
<li><a
href="https://github.com/eslint/eslint/commit/d186f8c0747f14890e86a5a39708b052b391ddaf"><code>d186f8c</code></a>
fix: update eslint (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20427">#20427</a>)
(renovate[bot])</li>
<li><a
href="https://github.com/eslint/eslint/commit/2332262deb4ef3188b210595896bb0ff552a7e66"><code>2332262</code></a>
fix: error location should not modify error message in RuleTester (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20421">#20421</a>)
(Milos Djermanovic)</li>
<li><a
href="https://github.com/eslint/eslint/commit/ab99b21a6715dee1035d8f4e6d6841853eb5563f"><code>ab99b21</code></a>
fix: ensure <code>filename</code> is passed as third argument to
<code>verifyAndFix()</code> (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20405">#20405</a>)
(루밀LuMir)</li>
<li><a
href="https://github.com/eslint/eslint/commit/8a60f3bc80ad96c65feeb29886342623c630199c"><code>8a60f3b</code></a>
fix: remove <code>ecmaVersion</code> and <code>sourceType</code> from
<code>ParserOptions</code> type (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20415">#20415</a>)
(Pixel998)</li>
<li><a
href="https://github.com/eslint/eslint/commit/eafd727a060131f7fc79b2eb5698d8d27683c3a2"><code>eafd727</code></a>
fix: remove <code>TDZ</code> scope type (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20231">#20231</a>)
(jaymarvelz)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/eslint/eslint/commits/HEAD/packages/js">compare
view</a></li>
</ul>
</details>
<br />

Updates `@tsconfig/recommended` from 1.0.7 to 1.0.13
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/tsconfig/bases/commits/HEAD/bases">compare
view</a></li>
</ul>
</details>
<br />

Updates `@typescript-eslint/eslint-plugin` from 5.62.0 to 8.55.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/typescript-eslint/typescript-eslint/releases"><code>@​typescript-eslint/eslint-plugin</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v8.55.0</h2>
<h2>8.55.0 (2026-02-09)</h2>
<h3>🚀 Features</h3>
<ul>
<li><strong>utils:</strong> deprecate defaultOptions in favor of
meta.defaultOptions (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11992">#11992</a>)</li>
</ul>
<h3>🩹 Fixes</h3>
<ul>
<li><strong>eslint-plugin:</strong> [no-unused-vars] remove trailing
newline when removing entire import (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11990">#11990</a>)</li>
<li><strong>eslint-plugin:</strong> [no-useless-default-assignment]
require strictNullChecks (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11966">#11966</a>,
<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12000">#12000</a>)</li>
<li><strong>eslint-plugin:</strong> [no-useless-default-assignment]
report unnecessary defaults in ternary expressions (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11984">#11984</a>)</li>
<li><strong>eslint-plugin:</strong> [no-useless-default-assignment]
reduce param index to ts this handling (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11949">#11949</a>)</li>
<li><strong>typescript-estree:</strong> forbid invalid modifier in
object expression (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11931">#11931</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Christian Rose <a
href="https://github.com/chrros95"><code>@​chrros95</code></a></li>
<li>fisker Cheung <a
href="https://github.com/fisker"><code>@​fisker</code></a></li>
<li>Josh Goldberg</li>
<li>Maria Solano <a
href="https://github.com/MariaSolOs"><code>@​MariaSolOs</code></a></li>
<li>Minyeong Kim <a
href="https://github.com/minyeong981"><code>@​minyeong981</code></a></li>
<li>SungHyun627 <a
href="https://github.com/SungHyun627"><code>@​SungHyun627</code></a></li>
<li>Yukihiro Hasegawa <a
href="https://github.com/y-hsgw"><code>@​y-hsgw</code></a></li>
</ul>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.55.0">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>v8.54.0</h2>
<h2>8.54.0 (2026-01-26)</h2>
<h3>🚀 Features</h3>
<ul>
<li><strong>eslint-plugin-internal:</strong> add prefer-tsutils-methods
rule (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11974">#11974</a>,
<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/issues/11625">#11625</a>)</li>
<li><strong>scope-manager:</strong> support ScopeManager#addGlobals (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11914">#11914</a>)</li>
<li><strong>typescript-estree:</strong> add shortcut methods to
ParserServicesWithTypeInformation (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11965">#11965</a>,
<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/issues/11955">#11955</a>)</li>
</ul>
<h3>🩹 Fixes</h3>
<ul>
<li><strong>eslint-plugin:</strong> [no-unused-private-class-members]
private destructured class member is defined but used (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11785">#11785</a>)</li>
<li><strong>eslint-plugin:</strong> [no-unnecessary-type-assertion]
check both base constraint and actual type for non-null assertions (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11967">#11967</a>,
<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/issues/11559">#11559</a>)</li>
<li><strong>scope-manager:</strong> fix catch clause scopes
<code>def.name</code> (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11982">#11982</a>)</li>
<li><strong>scope-manager:</strong> prevent misidentification of
<code>&quot;use strict&quot;</code> directives (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11995">#11995</a>)</li>
<li><strong>utils:</strong> handle missing <code>FlatESLint</code> and
<code>LegacyESLint</code> (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11958">#11958</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Brad Zacher <a
href="https://github.com/bradzacher"><code>@​bradzacher</code></a></li>
<li>fnx <a
href="https://github.com/DMartens"><code>@​DMartens</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/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md"><code>@​typescript-eslint/eslint-plugin</code>'s
changelog</a>.</em></p>
<blockquote>
<h2>8.55.0 (2026-02-09)</h2>
<h3>🚀 Features</h3>
<ul>
<li><strong>utils:</strong> deprecate defaultOptions in favor of
meta.defaultOptions (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11992">#11992</a>)</li>
</ul>
<h3>🩹 Fixes</h3>
<ul>
<li><strong>eslint-plugin:</strong> [no-useless-default-assignment]
reduce param index to ts this handling (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11949">#11949</a>)</li>
<li><strong>eslint-plugin:</strong> [no-useless-default-assignment]
report unnecessary defaults in ternary expressions (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11984">#11984</a>)</li>
<li><strong>eslint-plugin:</strong> [no-useless-default-assignment]
require strictNullChecks (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11966">#11966</a>,
<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12000">#12000</a>)</li>
<li><strong>eslint-plugin:</strong> [no-unused-vars] remove trailing
newline when removing entire import (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11990">#11990</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Christian Rose <a
href="https://github.com/chrros95"><code>@​chrros95</code></a></li>
<li>Josh Goldberg</li>
<li>Maria Solano <a
href="https://github.com/MariaSolOs"><code>@​MariaSolOs</code></a></li>
<li>Minyeong Kim <a
href="https://github.com/minyeong981"><code>@​minyeong981</code></a></li>
<li>SungHyun627 <a
href="https://github.com/SungHyun627"><code>@​SungHyun627</code></a></li>
<li>Yukihiro Hasegawa <a
href="https://github.com/y-hsgw"><code>@​y-hsgw</code></a></li>
</ul>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.55.0">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>8.54.0 (2026-01-26)</h2>
<h3>🚀 Features</h3>
<ul>
<li><strong>eslint-plugin-internal:</strong> add prefer-tsutils-methods
rule (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11974">#11974</a>,
<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/issues/11625">#11625</a>)</li>
<li><strong>typescript-estree:</strong> add shortcut methods to
ParserServicesWithTypeInformation (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11965">#11965</a>,
<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/issues/11955">#11955</a>)</li>
</ul>
<h3>🩹 Fixes</h3>
<ul>
<li><strong>eslint-plugin:</strong> [no-unnecessary-type-assertion]
check both base constraint and actual type for non-null assertions (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11967">#11967</a>,
<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/issues/11559">#11559</a>)</li>
<li><strong>deps:</strong> update dependency prettier to v3.8.0 (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11991">#11991</a>)</li>
<li><strong>scope-manager:</strong> fix catch clause scopes
<code>def.name</code> (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11982">#11982</a>)</li>
<li><strong>eslint-plugin:</strong> [no-unused-private-class-members]
private destructured class member is defined but used (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11785">#11785</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Brad Zacher <a
href="https://github.com/bradzacher"><code>@​bradzacher</code></a></li>
<li>Josh Goldberg</li>
<li>MinJae <a
href="https://github.com/Ju-MINJAE"><code>@​Ju-MINJAE</code></a></li>
<li>Minyeong Kim <a
href="https://github.com/minyeong981"><code>@​minyeong981</code></a></li>
<li>overlookmotel</li>
<li>Yuya Yoshioka <a
href="https://github.com/YuyaYoshioka"><code>@​YuyaYoshioka</code></a></li>
<li>김현수 <a
href="https://github.com/Kimsoo0119"><code>@​Kimsoo0119</code></a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/fedfe8665afbabd5c7d3ee09d14f450d5ba0b10a"><code>fedfe86</code></a>
chore(release): publish 8.55.0</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/8a95834bb5fd818cc049390e4cb57196717a011f"><code>8a95834</code></a>
fix(eslint-plugin): [no-useless-default-assignment] reduce param index
to ts ...</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/4ba1e72cd76f357044dca209978d87137c31e6c0"><code>4ba1e72</code></a>
fix(eslint-plugin): [no-useless-default-assignment] report unnecessary
defaul...</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/a1f86179074a143fdb06445a28b1144427d33ec9"><code>a1f8617</code></a>
feat(utils): deprecate defaultOptions in favor of meta.defaultOptions
(<a
href="https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin/issues/11992">#11992</a>)</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/3f0ce54da520cdc58f1dd2e2c45073c92617e2c2"><code>3f0ce54</code></a>
fix(eslint-plugin): [no-useless-default-assignment] require
strictNullChecks ...</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/3df0002e8663f170749cc4a9a054af377cf0c554"><code>3df0002</code></a>
fix(eslint-plugin): [no-unused-vars] remove trailing newline when
removing en...</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/b931f8c706beafc289462824814dca158694cb48"><code>b931f8c</code></a>
chore: use workspace refs for workspace deps (<a
href="https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin/issues/12018">#12018</a>)</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/1f17a7918cd507b11fd04ce75fe44a9c62bf9542"><code>1f17a79</code></a>
chore: migrate to pnpm (<a
href="https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin/issues/11248">#11248</a>)</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/d423e57622e1c8e789a1b84109d1ab2c15497507"><code>d423e57</code></a>
chore(release): publish 8.54.0</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/80e33ff2fd81f88100cda942db5232851adab90e"><code>80e33ff</code></a>
feat(eslint-plugin-internal): add prefer-tsutils-methods rule (<a
href="https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin/issues/11974">#11974</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/typescript-eslint/typescript-eslint/commits/v8.55.0/packages/eslint-plugin">compare
view</a></li>
</ul>
</details>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by [GitHub Actions](<a
href="https://www.npmjs.com/~GitHub">https://www.npmjs.com/~GitHub</a>
Actions), a new releaser for
<code>@​typescript-eslint/eslint-plugin</code> since your current
version.</p>
</details>
<br />

Updates `@typescript-eslint/parser` from 5.62.0 to 8.55.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/typescript-eslint/typescript-eslint/releases"><code>@​typescript-eslint/parser</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v8.55.0</h2>
<h2>8.55.0 (2026-02-09)</h2>
<h3>🚀 Features</h3>
<ul>
<li><strong>utils:</strong> deprecate defaultOptions in favor of
meta.defaultOptions (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11992">#11992</a>)</li>
</ul>
<h3>🩹 Fixes</h3>
<ul>
<li><strong>eslint-plugin:</strong> [no-unused-vars] remove trailing
newline when removing entire import (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11990">#11990</a>)</li>
<li><strong>eslint-plugin:</strong> [no-useless-default-assignment]
require strictNullChecks (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11966">#11966</a>,
<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12000">#12000</a>)</li>
<li><strong>eslint-plugin:</strong> [no-useless-default-assignment]
report unnecessary defaults in ternary expressions (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11984">#11984</a>)</li>
<li><strong>eslint-plugin:</strong> [no-useless-default-assignment]
reduce param index to ts this handling (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11949">#11949</a>)</li>
<li><strong>typescript-estree:</strong> forbid invalid modifier in
object expression (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11931">#11931</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Christian Rose <a
href="https://github.com/chrros95"><code>@​chrros95</code></a></li>
<li>fisker Cheung <a
href="https://github.com/fisker"><code>@​fisker</code></a></li>
<li>Josh Goldberg</li>
<li>Maria Solano <a
href="https://github.com/MariaSolOs"><code>@​MariaSolOs</code></a></li>
<li>Minyeong Kim <a
href="https://github.com/minyeong981"><code>@​minyeong981</code></a></li>
<li>SungHyun627 <a
href="https://github.com/SungHyun627"><code>@​SungHyun627</code></a></li>
<li>Yukihiro Hasegawa <a
href="https://github.com/y-hsgw"><code>@​y-hsgw</code></a></li>
</ul>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.55.0">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>v8.54.0</h2>
<h2>8.54.0 (2026-01-26)</h2>
<h3>🚀 Features</h3>
<ul>
<li><strong>eslint-plugin-internal:</strong> add prefer-tsutils-methods
rule (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11974">#11974</a>,
<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/issues/11625">#11625</a>)</li>
<li><strong>scope-manager:</strong> support ScopeManager#addGlobals (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11914">#11914</a>)</li>
<li><strong>typescript-estree:</strong> add shortcut methods to
ParserServicesWithTypeInformation (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11965">#11965</a>,
<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/issues/11955">#11955</a>)</li>
</ul>
<h3>🩹 Fixes</h3>
<ul>
<li><strong>eslint-plugin:</strong> [no-unused-private-class-members]
private destructured class member is defined but used (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11785">#11785</a>)</li>
<li><strong>eslint-plugin:</strong> [no-unnecessary-type-assertion]
check both base constraint and actual type for non-null assertions (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11967">#11967</a>,
<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/issues/11559">#11559</a>)</li>
<li><strong>scope-manager:</strong> fix catch clause scopes
<code>def.name</code> (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11982">#11982</a>)</li>
<li><strong>scope-manager:</strong> prevent misidentification of
<code>&quot;use strict&quot;</code> directives (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11995">#11995</a>)</li>
<li><strong>utils:</strong> handle missing <code>FlatESLint</code> and
<code>LegacyESLint</code> (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11958">#11958</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Brad Zacher <a
href="https://github.com/bradzacher"><code>@​bradzacher</code></a></li>
<li>fnx <a
href="https://github.com/DMartens"><code>@​DMartens</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/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md"><code>@​typescript-eslint/parser</code>'s
changelog</a>.</em></p>
<blockquote>
<h2>8.55.0 (2026-02-09)</h2>
<p>This was a version bump only for parser to align it with other
projects, there were no code changes.</p>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.55.0">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>8.54.0 (2026-01-26)</h2>
<p>This was a version bump only for parser to align it with other
projects, there were no code changes.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>8.53.1 (2026-01-19)</h2>
<p>This was a version bump only for parser to align it with other
projects, there were no code changes.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>8.53.0 (2026-01-12)</h2>
<p>This was a version bump only for parser to align it with other
projects, there were no code changes.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>8.52.0 (2026-01-05)</h2>
<p>This was a version bump only for parser to align it with other
projects, there were no code changes.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>8.51.0 (2025-12-29)</h2>
<p>This was a version bump only for parser to align it with other
projects, there were no code changes.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>8.50.1 (2025-12-22)</h2>
<p>This was a version bump only for parser to align it with other
projects, there were no code changes.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>8.50.0 (2025-12-15)</h2>
<p>This was a version bump only for parser to align it with other
projects, there were no code changes.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/fedfe8665afbabd5c7d3ee09d14f450d5ba0b10a"><code>fedfe86</code></a>
chore(release): publish 8.55.0</li>
<li><a
href="https://github.com/typescript-eslint/typescript-eslint/commit/b931f8c706beafc289462824814dca158694cb48...

_Description has been truncated_

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 <65985482+jkennedyvz@users.noreply.github.com>
2026-02-17 09:23:45 -08:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>John Kennedy
83fcca8687 chore(deps): bump cryptography from 46.0.3 to 46.0.5 in /libs/cli (#6834)
Bumps [cryptography](https://github.com/pyca/cryptography) from 46.0.3
to 46.0.5.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst">cryptography's
changelog</a>.</em></p>
<blockquote>
<p>46.0.5 - 2026-02-10</p>
<pre><code>
* An attacker could create a malicious public key that reveals portions
of your
private key when using certain uncommon elliptic curves (binary curves).
This version now includes additional security checks to prevent this
attack.
This issue only affects binary elliptic curves, which are rarely used in
real-world applications. Credit to **XlabAI Team of Tencent Xuanwu Lab
and
Atuin Automated Vulnerability Discovery Engine** for reporting the
issue.
  **CVE-2026-26007**
* Support for ``SECT*`` binary elliptic curves is deprecated and will be
  removed in the next release.
<p>.. v46-0-4:</p>
<p>46.0.4 - 2026-01-27<br />
</code></pre></p>
<ul>
<li><code>Dropped support for win_arm64 wheels</code>_.</li>
<li>Updated Windows, macOS, and Linux wheels to be compiled with OpenSSL
3.5.5.</li>
</ul>
<p>.. _v46-0-3:</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/pyca/cryptography/commit/06e120e682cb200e3f7050c02f0bcdac90c4c6ad"><code>06e120e</code></a>
bump version for 46.0.5 release (<a
href="https://redirect.github.com/pyca/cryptography/issues/14289">#14289</a>)</li>
<li><a
href="https://github.com/pyca/cryptography/commit/0eebb9dbb6343d9bc1d91e5a2482ed4e054a6d8c"><code>0eebb9d</code></a>
EC check key on cofactor &gt; 1 (<a
href="https://redirect.github.com/pyca/cryptography/issues/14287">#14287</a>)</li>
<li><a
href="https://github.com/pyca/cryptography/commit/bedf6e186b814f69a3f54f51252c23a71d44ed2e"><code>bedf6e1</code></a>
fix openssl version on 46 branch (<a
href="https://redirect.github.com/pyca/cryptography/issues/14220">#14220</a>)</li>
<li><a
href="https://github.com/pyca/cryptography/commit/e6f44fc8e6391f05d719fb9d369692325b87a471"><code>e6f44fc</code></a>
bump for 46.0.4 and drop win arm64 due to CI issues (<a
href="https://redirect.github.com/pyca/cryptography/issues/14217">#14217</a>)</li>
<li>See full diff in <a
href="https://github.com/pyca/cryptography/compare/46.0.3...46.0.5">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=cryptography&package-manager=uv&previous-version=46.0.3&new-version=46.0.5)](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>
Co-authored-by: John Kennedy <65985482+jkennedyvz@users.noreply.github.com>
2026-02-17 09:23:09 -08:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
5da9a1d844 chore(deps): bump the all-dependencies group in /libs/cli/js-monorepo-example with 13 updates (#6813)
Bumps the all-dependencies group in /libs/cli/js-monorepo-example with
13 updates:

| Package | From | To |
| --- | --- | --- |
| [turbo](https://github.com/vercel/turborepo) | `2.5.6` | `2.8.8` |
| [typescript](https://github.com/microsoft/TypeScript) | `5.9.2` |
`5.9.3` |
|
[@tsconfig/recommended](https://github.com/tsconfig/bases/tree/HEAD/bases)
| `1.0.10` | `1.0.13` |
| [@eslint/eslintrc](https://github.com/eslint/eslintrc) | `3.3.1` |
`3.3.3` |
| [@eslint/js](https://github.com/eslint/eslint/tree/HEAD/packages/js) |
`9.34.0` | `10.0.1` |
| [eslint](https://github.com/eslint/eslint) | `8.57.1` | `10.0.0` |
|
[eslint-config-prettier](https://github.com/prettier/eslint-config-prettier)
| `8.10.2` | `10.1.8` |
|
[eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier)
| `4.2.5` | `5.5.5` |
|
[@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin)
| `5.62.0` | `8.55.0` |
|
[@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser)
| `5.62.0` | `8.55.0` |
| [prettier](https://github.com/prettier/prettier) | `3.6.2` | `3.8.1` |
| [@langchain/core](https://github.com/langchain-ai/langchainjs) |
`0.3.72` | `1.1.24` |
|
[@langchain/langgraph](https://github.com/langchain-ai/langgraphjs/tree/HEAD/libs/langgraph-core)
| `0.2.74` | `1.1.4` |

Updates `turbo` from 2.5.6 to 2.8.8
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/vercel/turborepo/releases">turbo's
releases</a>.</em></p>
<blockquote>
<h2>Turborepo v2.8.8-canary.7</h2>
<!-- raw HTML omitted -->
<h2>What's Changed</h2>
<h3>Changelog</h3>
<ul>
<li>fix: Sync lockfile with <code>@​turbo/gen</code>
optionalDependencies by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/11845">vercel/turborepo#11845</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/vercel/turborepo/compare/v2.8.8-canary.6...v2.8.8-canary.7">https://github.com/vercel/turborepo/compare/v2.8.8-canary.6...v2.8.8-canary.7</a></p>
<h2>Turborepo v2.8.8-canary.6</h2>
<!-- raw HTML omitted -->
<p><strong>Full Changelog</strong>: <a
href="https://github.com/vercel/turborepo/compare/v2.8.8-canary.5...v2.8.8-canary.6">https://github.com/vercel/turborepo/compare/v2.8.8-canary.5...v2.8.8-canary.6</a></p>
<h2>Turborepo v2.8.8-canary.5</h2>
<!-- raw HTML omitted -->
<h2>What's Changed</h2>
<h3>Changelog</h3>
<ul>
<li>chore: Update lockfile for release by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/11840">vercel/turborepo#11840</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/vercel/turborepo/compare/v2.8.8-canary.4...v2.8.8-canary.5">https://github.com/vercel/turborepo/compare/v2.8.8-canary.4...v2.8.8-canary.5</a></p>
<h2>Turborepo v2.8.8-canary.4</h2>
<!-- raw HTML omitted -->
<h2>What's Changed</h2>
<h3>Examples</h3>
<ul>
<li>docs: Replace mysql refs with postgres by <a
href="https://github.com/kyedavey"><code>@​kyedavey</code></a> in <a
href="https://redirect.github.com/vercel/turborepo/pull/11827">vercel/turborepo#11827</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/kyedavey"><code>@​kyedavey</code></a>
made their first contribution in <a
href="https://redirect.github.com/vercel/turborepo/pull/11827">vercel/turborepo#11827</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/vercel/turborepo/compare/v2.8.8-canary.3...v2.8.8-canary.4">https://github.com/vercel/turborepo/compare/v2.8.8-canary.3...v2.8.8-canary.4</a></p>
<h2>Turborepo v2.8.8-canary.3</h2>
<!-- raw HTML omitted -->
<h2>What's Changed</h2>
<h3>Changelog</h3>
<ul>
<li>fix: Harden token protection with <code>secrecy</code> crate and
close exposure gaps by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/11831">vercel/turborepo#11831</a></li>
<li>fix: Clean up orphaned Windows child processes on shutdown by <a
href="https://github.com/anthonyshew"><code>@​anthonyshew</code></a> in
<a
href="https://redirect.github.com/vercel/turborepo/pull/11829">vercel/turborepo#11829</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/vercel/turborepo/compare/v2.8.8-canary.2...v2.8.8-canary.3">https://github.com/vercel/turborepo/compare/v2.8.8-canary.2...v2.8.8-canary.3</a></p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/vercel/turborepo/commits">compare view</a></li>
</ul>
</details>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by [GitHub Actions](<a
href="https://www.npmjs.com/~GitHub">https://www.npmjs.com/~GitHub</a>
Actions), a new releaser for turbo since your current version.</p>
</details>
<br />

Updates `typescript` from 5.9.2 to 5.9.3
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/microsoft/TypeScript/releases">typescript's
releases</a>.</em></p>
<blockquote>
<h2>TypeScript 5.9.3</h2>
<p>Note: this tag was recreated to point at the correct commit. The npm
package contained the correct content.</p>
<p>For release notes, check out the <a
href="https://devblogs.microsoft.com/typescript/announcing-typescript-5-9/">release
announcement</a></p>
<ul>
<li><a
href="https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&amp;q=milestone%3A%22TypeScript+5.9.0%22+is%3Aclosed+">fixed
issues query for Typescript 5.9.0 (Beta)</a>.</li>
<li><a
href="https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&amp;q=milestone%3A%22TypeScript+5.9.1%22+is%3Aclosed+">fixed
issues query for Typescript 5.9.1 (RC)</a>.</li>
<li><em>No specific changes for TypeScript 5.9.2 (Stable)</em></li>
<li><a
href="https://github.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93&amp;q=milestone%3A%22TypeScript+5.9.3%22+is%3Aclosed+">fixed
issues query for Typescript 5.9.3 (Stable)</a>.</li>
</ul>
<p>Downloads are available on:</p>
<ul>
<li><a href="https://www.npmjs.com/package/typescript">npm</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/microsoft/TypeScript/commit/c63de15a992d37f0d6cec03ac7631872838602cb"><code>c63de15</code></a>
Bump version to 5.9.3 and LKG</li>
<li><a
href="https://github.com/microsoft/TypeScript/commit/8428ca4cc8a7ecc9ac18dd0258016228814f5eaf"><code>8428ca4</code></a>
🤖 Pick PR <a
href="https://redirect.github.com/microsoft/TypeScript/issues/62438">#62438</a>
(Fix incorrectly ignored dts file fr...) into release-5.9 (#...</li>
<li><a
href="https://github.com/microsoft/TypeScript/commit/a131cac6831aa6532ea963d0cb3131b957cad980"><code>a131cac</code></a>
🤖 Pick PR <a
href="https://redirect.github.com/microsoft/TypeScript/issues/62351">#62351</a>
(Add missing Float16Array constructo...) into release-5.9 (#...</li>
<li><a
href="https://github.com/microsoft/TypeScript/commit/04243333584a5bfaeb3434c0982c6280fe87b8d5"><code>0424333</code></a>
🤖 Pick PR <a
href="https://redirect.github.com/microsoft/TypeScript/issues/62423">#62423</a>
(Revert PR 61928) into release-5.9 (<a
href="https://redirect.github.com/microsoft/TypeScript/issues/62425">#62425</a>)</li>
<li><a
href="https://github.com/microsoft/TypeScript/commit/bdb641a4347af822916fb8cdb9894c9c2d2421dd"><code>bdb641a</code></a>
🤖 Pick PR <a
href="https://redirect.github.com/microsoft/TypeScript/issues/62311">#62311</a>
(Fix parenthesizer rules for manuall...) into release-5.9 (#...</li>
<li><a
href="https://github.com/microsoft/TypeScript/commit/0d9b9b92e2aca2f75c979a801abbc21bff473748"><code>0d9b9b9</code></a>
🤖 Pick PR <a
href="https://redirect.github.com/microsoft/TypeScript/issues/61978">#61978</a>
(Restructure CI to prepare for requi...) into release-5.9 (#...</li>
<li><a
href="https://github.com/microsoft/TypeScript/commit/2dce0c58af51cf9a9068365dc2f756c61b82b597"><code>2dce0c5</code></a>
Intentionally regress one buggy declaration output to an older version
(<a
href="https://redirect.github.com/microsoft/TypeScript/issues/62163">#62163</a>)</li>
<li>See full diff in <a
href="https://github.com/microsoft/TypeScript/compare/v5.9.2...v5.9.3">compare
view</a></li>
</ul>
</details>
<br />

Updates `@tsconfig/recommended` from 1.0.10 to 1.0.13
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/tsconfig/bases/commits/HEAD/bases">compare
view</a></li>
</ul>
</details>
<br />

Updates `@eslint/eslintrc` from 3.3.1 to 3.3.3
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/eslint/eslintrc/releases"><code>@​eslint/eslintrc</code>'s
releases</a>.</em></p>
<blockquote>
<h2>eslintrc: v3.3.3</h2>
<h2><a
href="https://github.com/eslint/eslintrc/compare/eslintrc-v3.3.2...eslintrc-v3.3.3">3.3.3</a>
(2025-11-28)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>release v3.3.3 because publishing v3.3.2 failed (<a
href="https://redirect.github.com/eslint/eslintrc/issues/211">#211</a>)
(<a
href="https://github.com/eslint/eslintrc/commit/8aa555a3f5fcfb7d99249fb57e819a7b6f635496">8aa555a</a>)</li>
</ul>
<h2>eslintrc: v3.3.2</h2>
<h2><a
href="https://github.com/eslint/eslintrc/compare/eslintrc-v3.3.1...eslintrc-v3.3.2">3.3.2</a>
(2025-11-25)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>Remove name property from all and recommended configs (<a
href="https://redirect.github.com/eslint/eslintrc/issues/200">#200</a>)
(<a
href="https://github.com/eslint/eslintrc/commit/344da491898a2a3595943d4528ba78fe2f238217">344da49</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/eslint/eslintrc/blob/main/CHANGELOG.md"><code>@​eslint/eslintrc</code>'s
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/eslint/eslintrc/compare/eslintrc-v3.3.2...eslintrc-v3.3.3">3.3.3</a>
(2025-11-28)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>release v3.3.3 because publishing v3.3.2 failed (<a
href="https://redirect.github.com/eslint/eslintrc/issues/211">#211</a>)
(<a
href="https://github.com/eslint/eslintrc/commit/8aa555a3f5fcfb7d99249fb57e819a7b6f635496">8aa555a</a>)</li>
</ul>
<h2><a
href="https://github.com/eslint/eslintrc/compare/eslintrc-v3.3.1...eslintrc-v3.3.2">3.3.2</a>
(2025-11-25)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>Remove name property from all and recommended configs (<a
href="https://redirect.github.com/eslint/eslintrc/issues/200">#200</a>)
(<a
href="https://github.com/eslint/eslintrc/commit/344da491898a2a3595943d4528ba78fe2f238217">344da49</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/eslint/eslintrc/commit/fdb529826fd769f2bdcd1281d711412253561231"><code>fdb5298</code></a>
chore: release 3.3.3 🚀 (<a
href="https://redirect.github.com/eslint/eslintrc/issues/212">#212</a>)</li>
<li><a
href="https://github.com/eslint/eslintrc/commit/8aa555a3f5fcfb7d99249fb57e819a7b6f635496"><code>8aa555a</code></a>
fix: release v3.3.3 because publishing v3.3.2 failed (<a
href="https://redirect.github.com/eslint/eslintrc/issues/211">#211</a>)</li>
<li><a
href="https://github.com/eslint/eslintrc/commit/a8b773d0cfecbd987e4301ad40be271a2c800c40"><code>a8b773d</code></a>
chore: release 3.3.2 🚀 (<a
href="https://redirect.github.com/eslint/eslintrc/issues/204">#204</a>)</li>
<li><a
href="https://github.com/eslint/eslintrc/commit/85244bb33023f25eb8ac443d08b769be7bafec2e"><code>85244bb</code></a>
chore: switch to <code>googleapis/release-please-action</code> (<a
href="https://redirect.github.com/eslint/eslintrc/issues/208">#208</a>)</li>
<li><a
href="https://github.com/eslint/eslintrc/commit/d356360dfee5173b3ace73cc1f3ecb922eb4310d"><code>d356360</code></a>
docs: Update README sponsors</li>
<li><a
href="https://github.com/eslint/eslintrc/commit/116bf0332e3ce6dd848704b3782c8c77067c635b"><code>116bf03</code></a>
chore: update js-yaml to version 4.1.1 (<a
href="https://redirect.github.com/eslint/eslintrc/issues/207">#207</a>)</li>
<li><a
href="https://github.com/eslint/eslintrc/commit/16e8d207557fcac8512bd5d9ffd475ec777db0df"><code>16e8d20</code></a>
docs: Update README sponsors</li>
<li><a
href="https://github.com/eslint/eslintrc/commit/3b089acfeba445f3fef84662c43143a5d0eb8a15"><code>3b089ac</code></a>
chore: update <code>.gitignore</code> to exclude shared workflows (<a
href="https://redirect.github.com/eslint/eslintrc/issues/206">#206</a>)</li>
<li><a
href="https://github.com/eslint/eslintrc/commit/1f6e2d19b2f9617c10597fbe97ac99076a716a0c"><code>1f6e2d1</code></a>
docs: Update README sponsors</li>
<li><a
href="https://github.com/eslint/eslintrc/commit/785c00b8cce58c2b4962996699e0f3dbdc6d2d13"><code>785c00b</code></a>
docs: Update README sponsors</li>
<li>Additional commits viewable in <a
href="https://github.com/eslint/eslintrc/compare/v3.3.1...eslintrc-v3.3.3">compare
view</a></li>
</ul>
</details>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by [GitHub Actions](<a
href="https://www.npmjs.com/~GitHub">https://www.npmjs.com/~GitHub</a>
Actions), a new releaser for <code>@​eslint/eslintrc</code> since your
current version.</p>
</details>
<br />

Updates `@eslint/js` from 9.34.0 to 10.0.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/eslint/eslint/releases"><code>@​eslint/js</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v10.0.0</h2>
<h2>Breaking Changes</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/f9e54f43a5e497cdfa179338b431093245cb787b"><code>f9e54f4</code></a>
feat!: estimate rule-tester failure location (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20420">#20420</a>)
(ST-DDT)</li>
<li><a
href="https://github.com/eslint/eslint/commit/a176319d8ade1a7d9b2d7fb8f038f55a2662325f"><code>a176319</code></a>
feat!: replace <code>chalk</code> with <code>styleText</code> and add
<code>color</code> to <code>ResultsMeta</code> (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20227">#20227</a>)
(루밀LuMir)</li>
<li><a
href="https://github.com/eslint/eslint/commit/c7046e6c1e03c4ca0eee4888a1f2eba4c6454f84"><code>c7046e6</code></a>
feat!: enable JSX reference tracking (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20152">#20152</a>)
(Pixel998)</li>
<li><a
href="https://github.com/eslint/eslint/commit/fa31a608901684fbcd9906d1907e66561d16e5aa"><code>fa31a60</code></a>
feat!: add <code>name</code> to configs (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20015">#20015</a>)
(Kirk Waiblinger)</li>
<li><a
href="https://github.com/eslint/eslint/commit/3383e7ec9028166cafc8ea7986c2f7498d0049f0"><code>3383e7e</code></a>
fix!: remove deprecated <code>SourceCode</code> methods (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20137">#20137</a>)
(Pixel998)</li>
<li><a
href="https://github.com/eslint/eslint/commit/501abd0e916a35554c58b7c0365537f1fa3880ce"><code>501abd0</code></a>
feat!: update dependency minimatch to v10 (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20246">#20246</a>)
(renovate[bot])</li>
<li><a
href="https://github.com/eslint/eslint/commit/ca4d3b40085de47561f89656a2207d09946ed45e"><code>ca4d3b4</code></a>
fix!: stricter rule tester assertions for valid test cases (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20125">#20125</a>)
(唯然)</li>
<li><a
href="https://github.com/eslint/eslint/commit/96512a66c86402fb0538cdcb6cd30b9073f6bf3b"><code>96512a6</code></a>
fix!: Remove deprecated rule context methods (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20086">#20086</a>)
(Nicholas C. Zakas)</li>
<li><a
href="https://github.com/eslint/eslint/commit/c69fdacdb2e886b9d965568a397aa8220db3fe90"><code>c69fdac</code></a>
feat!: remove eslintrc support (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20037">#20037</a>)
(Francesco Trotta)</li>
<li><a
href="https://github.com/eslint/eslint/commit/208b5cc34a8374ff81412b5bec2e0800eebfbd04"><code>208b5cc</code></a>
feat!: Use <code>ScopeManager#addGlobals()</code> (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20132">#20132</a>)
(Milos Djermanovic)</li>
<li><a
href="https://github.com/eslint/eslint/commit/a2ee188ea7a38a0c6155f3d39e2b00e1d0f36e14"><code>a2ee188</code></a>
fix!: add <code>uniqueItems: true</code> in
<code>no-invalid-regexp</code> option (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20155">#20155</a>)
(Tanuj Kanti)</li>
<li><a
href="https://github.com/eslint/eslint/commit/a89059dbf2832d417dd493ee81483227ec44e4ab"><code>a89059d</code></a>
feat!: Program range span entire source text (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20133">#20133</a>)
(Pixel998)</li>
<li><a
href="https://github.com/eslint/eslint/commit/39a6424373d915fa9de0d7b0caba9a4dc3da9b53"><code>39a6424</code></a>
fix!: assert 'text' is a string across all RuleFixer methods (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20082">#20082</a>)
(Pixel998)</li>
<li><a
href="https://github.com/eslint/eslint/commit/f28fbf846244e043c92b355b224d121b06140b44"><code>f28fbf8</code></a>
fix!: Deprecate <code>&quot;always&quot;</code> and
<code>&quot;as-needed&quot;</code> options of the <code>radix</code>
rule (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20223">#20223</a>)
(Milos Djermanovic)</li>
<li><a
href="https://github.com/eslint/eslint/commit/aa3fb2b233e929b37220be940575f42c280e0b98"><code>aa3fb2b</code></a>
fix!: tighten <code>func-names</code> schema (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20119">#20119</a>)
(Pixel998)</li>
<li><a
href="https://github.com/eslint/eslint/commit/f6c0ed0311dcfee853367d5068c765d066e6b756"><code>f6c0ed0</code></a>
feat!: report <code>eslint-env</code> comments as errors (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20128">#20128</a>)
(Francesco Trotta)</li>
<li><a
href="https://github.com/eslint/eslint/commit/4bf739fb533e59f7f0a66b65f7bc80be0f37d8db"><code>4bf739f</code></a>
fix!: remove deprecated <code>LintMessage#nodeType</code> and
<code>TestCaseError#type</code> (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20096">#20096</a>)
(Pixel998)</li>
<li><a
href="https://github.com/eslint/eslint/commit/523c076866400670fb2192a3f55dbf7ad3469247"><code>523c076</code></a>
feat!: drop support for jiti &lt; 2.2.0 (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20016">#20016</a>)
(michael faith)</li>
<li><a
href="https://github.com/eslint/eslint/commit/454a292c95f34dad232411ddac06408e6383bb64"><code>454a292</code></a>
feat!: update <code>eslint:recommended</code> configuration (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20210">#20210</a>)
(Pixel998)</li>
<li><a
href="https://github.com/eslint/eslint/commit/4f880ee02992e1bf0e96ebaba679985e2d1295f1"><code>4f880ee</code></a>
feat!: remove <code>v10_*</code> and inactive <code>unstable_*</code>
flags (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20225">#20225</a>)
(sethamus)</li>
<li><a
href="https://github.com/eslint/eslint/commit/f18115c363a4ac7671a4c7f30ee13d57ebba330f"><code>f18115c</code></a>
feat!: <code>no-shadow-restricted-names</code> report
<code>globalThis</code> by default (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20027">#20027</a>)
(sethamus)</li>
<li><a
href="https://github.com/eslint/eslint/commit/c6358c31fbd3937b92d89be2618ffdf5a774604e"><code>c6358c3</code></a>
feat!: Require Node.js <code>^20.19.0 || ^22.13.0 || &gt;=24</code> (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20160">#20160</a>)
(Milos Djermanovic)</li>
</ul>
<h2>Features</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/bff9091927811497dbf066b0e3b85ecb37d43822"><code>bff9091</code></a>
feat: handle <code>Array.fromAsync</code> in
<code>array-callback-return</code> (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20457">#20457</a>)
(Francesco Trotta)</li>
<li><a
href="https://github.com/eslint/eslint/commit/290c594bb50c439fb71bc75521ee5360daa8c222"><code>290c594</code></a>
feat: add <code>self</code> to <code>no-implied-eval</code> rule (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20468">#20468</a>)
(sethamus)</li>
<li><a
href="https://github.com/eslint/eslint/commit/43677de07ebd6e14bfac40a46ad749ba783c45f2"><code>43677de</code></a>
feat: fix handling of function and class expression names in
<code>no-shadow</code> (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20432">#20432</a>)
(Milos Djermanovic)</li>
<li><a
href="https://github.com/eslint/eslint/commit/f0cafe5f37e7765e9d8c2751b5f5d33107687009"><code>f0cafe5</code></a>
feat: rule tester add assertion option <code>requireData</code> (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20409">#20409</a>)
(fnx)</li>
<li><a
href="https://github.com/eslint/eslint/commit/f7ab6937e63bc618d326710858f5861a68f80616"><code>f7ab693</code></a>
feat: output RuleTester test case failure index (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/19976">#19976</a>)
(ST-DDT)</li>
<li><a
href="https://github.com/eslint/eslint/commit/7cbcbf9c3c2008deee7d143ae35e668e8ffbccb3"><code>7cbcbf9</code></a>
feat: add <code>countThis</code> option to <code>max-params</code> (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20236">#20236</a>)
(Gerkin)</li>
<li><a
href="https://github.com/eslint/eslint/commit/f148a5eaa1e89dd80ade62f0a690186b00b9f6e1"><code>f148a5e</code></a>
feat: add error assertion options (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20247">#20247</a>)
(ST-DDT)</li>
<li><a
href="https://github.com/eslint/eslint/commit/09e66549ecada6dcb8c567a60faf044fce049188"><code>09e6654</code></a>
feat: update error loc of <code>require-yield</code> and
<code>no-useless-constructor</code> (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20267">#20267</a>)
(Tanuj Kanti)</li>
</ul>
<h2>Bug Fixes</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/436b82f3c0a8cfa2fdc17d173e95ea11d5d3ee03"><code>436b82f</code></a>
fix: update eslint (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20473">#20473</a>)
(renovate[bot])</li>
<li><a
href="https://github.com/eslint/eslint/commit/1d29d22fe302443cec2a11da0816397f94af97ec"><code>1d29d22</code></a>
fix: detect default <code>this</code> binding in
<code>Array.fromAsync</code> callbacks (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20456">#20456</a>)
(Francesco Trotta)</li>
<li><a
href="https://github.com/eslint/eslint/commit/727451eff55b35d853e0e443d0de58f4550762bf"><code>727451e</code></a>
fix: fix regression of global mode report range in <code>strict</code>
rule (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20462">#20462</a>)
(ntnyq)</li>
<li><a
href="https://github.com/eslint/eslint/commit/e80485fcd27196fa0b6f6b5c7ac8cf49ad4b079d"><code>e80485f</code></a>
fix: remove fake <code>FlatESLint</code> and <code>LegacyESLint</code>
exports (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20460">#20460</a>)
(Francesco Trotta)</li>
<li><a
href="https://github.com/eslint/eslint/commit/9eeff3bc13813a786b8a4c3815def97c0fb646ef"><code>9eeff3b</code></a>
fix: update esquery (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20423">#20423</a>)
(cryptnix)</li>
<li><a
href="https://github.com/eslint/eslint/commit/b34b93852d014ebbcf3538d892b55e0216cdf681"><code>b34b938</code></a>
fix: use <code>Error.prepareStackTrace</code> to estimate failing test
location (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20436">#20436</a>)
(Francesco Trotta)</li>
<li><a
href="https://github.com/eslint/eslint/commit/51aab5393b058f7cbed69041a9069b2bd106aabd"><code>51aab53</code></a>
fix: update eslint (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20443">#20443</a>)
(renovate[bot])</li>
<li><a
href="https://github.com/eslint/eslint/commit/23490b266276792896a0b7b43c49a1ce87bf8568"><code>23490b2</code></a>
fix: handle space before colon in <code>RuleTester</code> location
estimation (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20433">#20433</a>)
(Francesco Trotta)</li>
<li><a
href="https://github.com/eslint/eslint/commit/f244dbf2191267a4cafd08645243624baf3e8c83"><code>f244dbf</code></a>
fix: use <code>MessagePlaceholderData</code> type from
<code>@eslint/core</code> (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20348">#20348</a>)
(루밀LuMir)</li>
<li><a
href="https://github.com/eslint/eslint/commit/d186f8c0747f14890e86a5a39708b052b391ddaf"><code>d186f8c</code></a>
fix: update eslint (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20427">#20427</a>)
(renovate[bot])</li>
<li><a
href="https://github.com/eslint/eslint/commit/2332262deb4ef3188b210595896bb0ff552a7e66"><code>2332262</code></a>
fix: error location should not modify error message in RuleTester (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20421">#20421</a>)
(Milos Djermanovic)</li>
<li><a
href="https://github.com/eslint/eslint/commit/ab99b21a6715dee1035d8f4e6d6841853eb5563f"><code>ab99b21</code></a>
fix: ensure <code>filename</code> is passed as third argument to
<code>verifyAndFix()</code> (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20405">#20405</a>)
(루밀LuMir)</li>
<li><a
href="https://github.com/eslint/eslint/commit/8a60f3bc80ad96c65feeb29886342623c630199c"><code>8a60f3b</code></a>
fix: remove <code>ecmaVersion</code> and <code>sourceType</code> from
<code>ParserOptions</code> type (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20415">#20415</a>)
(Pixel998)</li>
<li><a
href="https://github.com/eslint/eslint/commit/eafd727a060131f7fc79b2eb5698d8d27683c3a2"><code>eafd727</code></a>
fix: remove <code>TDZ</code> scope type (<a
href="https://github.com/eslint/eslint/tree/HEAD/packages/js/issues/20231">#20231</a>)
(jaymarvelz)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/eslint/eslint/commits/HEAD/packages/js">compare
view</a></li>
</ul>
</details>
<br />

Updates `eslint` from 8.57.1 to 10.0.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/eslint/eslint/releases">eslint's
releases</a>.</em></p>
<blockquote>
<h2>v10.0.0</h2>
<h2>Breaking Changes</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/f9e54f43a5e497cdfa179338b431093245cb787b"><code>f9e54f4</code></a>
feat!: estimate rule-tester failure location (<a
href="https://redirect.github.com/eslint/eslint/issues/20420">#20420</a>)
(ST-DDT)</li>
<li><a
href="https://github.com/eslint/eslint/commit/a176319d8ade1a7d9b2d7fb8f038f55a2662325f"><code>a176319</code></a>
feat!: replace <code>chalk</code> with <code>styleText</code> and add
<code>color</code> to <code>ResultsMeta</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/20227">#20227</a>)
(루밀LuMir)</li>
<li><a
href="https://github.com/eslint/eslint/commit/c7046e6c1e03c4ca0eee4888a1f2eba4c6454f84"><code>c7046e6</code></a>
feat!: enable JSX reference tracking (<a
href="https://redirect.github.com/eslint/eslint/issues/20152">#20152</a>)
(Pixel998)</li>
<li><a
href="https://github.com/eslint/eslint/commit/fa31a608901684fbcd9906d1907e66561d16e5aa"><code>fa31a60</code></a>
feat!: add <code>name</code> to configs (<a
href="https://redirect.github.com/eslint/eslint/issues/20015">#20015</a>)
(Kirk Waiblinger)</li>
<li><a
href="https://github.com/eslint/eslint/commit/3383e7ec9028166cafc8ea7986c2f7498d0049f0"><code>3383e7e</code></a>
fix!: remove deprecated <code>SourceCode</code> methods (<a
href="https://redirect.github.com/eslint/eslint/issues/20137">#20137</a>)
(Pixel998)</li>
<li><a
href="https://github.com/eslint/eslint/commit/501abd0e916a35554c58b7c0365537f1fa3880ce"><code>501abd0</code></a>
feat!: update dependency minimatch to v10 (<a
href="https://redirect.github.com/eslint/eslint/issues/20246">#20246</a>)
(renovate[bot])</li>
<li><a
href="https://github.com/eslint/eslint/commit/ca4d3b40085de47561f89656a2207d09946ed45e"><code>ca4d3b4</code></a>
fix!: stricter rule tester assertions for valid test cases (<a
href="https://redirect.github.com/eslint/eslint/issues/20125">#20125</a>)
(唯然)</li>
<li><a
href="https://github.com/eslint/eslint/commit/96512a66c86402fb0538cdcb6cd30b9073f6bf3b"><code>96512a6</code></a>
fix!: Remove deprecated rule context methods (<a
href="https://redirect.github.com/eslint/eslint/issues/20086">#20086</a>)
(Nicholas C. Zakas)</li>
<li><a
href="https://github.com/eslint/eslint/commit/c69fdacdb2e886b9d965568a397aa8220db3fe90"><code>c69fdac</code></a>
feat!: remove eslintrc support (<a
href="https://redirect.github.com/eslint/eslint/issues/20037">#20037</a>)
(Francesco Trotta)</li>
<li><a
href="https://github.com/eslint/eslint/commit/208b5cc34a8374ff81412b5bec2e0800eebfbd04"><code>208b5cc</code></a>
feat!: Use <code>ScopeManager#addGlobals()</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/20132">#20132</a>)
(Milos Djermanovic)</li>
<li><a
href="https://github.com/eslint/eslint/commit/a2ee188ea7a38a0c6155f3d39e2b00e1d0f36e14"><code>a2ee188</code></a>
fix!: add <code>uniqueItems: true</code> in
<code>no-invalid-regexp</code> option (<a
href="https://redirect.github.com/eslint/eslint/issues/20155">#20155</a>)
(Tanuj Kanti)</li>
<li><a
href="https://github.com/eslint/eslint/commit/a89059dbf2832d417dd493ee81483227ec44e4ab"><code>a89059d</code></a>
feat!: Program range span entire source text (<a
href="https://redirect.github.com/eslint/eslint/issues/20133">#20133</a>)
(Pixel998)</li>
<li><a
href="https://github.com/eslint/eslint/commit/39a6424373d915fa9de0d7b0caba9a4dc3da9b53"><code>39a6424</code></a>
fix!: assert 'text' is a string across all RuleFixer methods (<a
href="https://redirect.github.com/eslint/eslint/issues/20082">#20082</a>)
(Pixel998)</li>
<li><a
href="https://github.com/eslint/eslint/commit/f28fbf846244e043c92b355b224d121b06140b44"><code>f28fbf8</code></a>
fix!: Deprecate <code>&quot;always&quot;</code> and
<code>&quot;as-needed&quot;</code> options of the <code>radix</code>
rule (<a
href="https://redirect.github.com/eslint/eslint/issues/20223">#20223</a>)
(Milos Djermanovic)</li>
<li><a
href="https://github.com/eslint/eslint/commit/aa3fb2b233e929b37220be940575f42c280e0b98"><code>aa3fb2b</code></a>
fix!: tighten <code>func-names</code> schema (<a
href="https://redirect.github.com/eslint/eslint/issues/20119">#20119</a>)
(Pixel998)</li>
<li><a
href="https://github.com/eslint/eslint/commit/f6c0ed0311dcfee853367d5068c765d066e6b756"><code>f6c0ed0</code></a>
feat!: report <code>eslint-env</code> comments as errors (<a
href="https://redirect.github.com/eslint/eslint/issues/20128">#20128</a>)
(Francesco Trotta)</li>
<li><a
href="https://github.com/eslint/eslint/commit/4bf739fb533e59f7f0a66b65f7bc80be0f37d8db"><code>4bf739f</code></a>
fix!: remove deprecated <code>LintMessage#nodeType</code> and
<code>TestCaseError#type</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/20096">#20096</a>)
(Pixel998)</li>
<li><a
href="https://github.com/eslint/eslint/commit/523c076866400670fb2192a3f55dbf7ad3469247"><code>523c076</code></a>
feat!: drop support for jiti &lt; 2.2.0 (<a
href="https://redirect.github.com/eslint/eslint/issues/20016">#20016</a>)
(michael faith)</li>
<li><a
href="https://github.com/eslint/eslint/commit/454a292c95f34dad232411ddac06408e6383bb64"><code>454a292</code></a>
feat!: update <code>eslint:recommended</code> configuration (<a
href="https://redirect.github.com/eslint/eslint/issues/20210">#20210</a>)
(Pixel998)</li>
<li><a
href="https://github.com/eslint/eslint/commit/4f880ee02992e1bf0e96ebaba679985e2d1295f1"><code>4f880ee</code></a>
feat!: remove <code>v10_*</code> and inactive <code>unstable_*</code>
flags (<a
href="https://redirect.github.com/eslint/eslint/issues/20225">#20225</a>)
(sethamus)</li>
<li><a
href="https://github.com/eslint/eslint/commit/f18115c363a4ac7671a4c7f30ee13d57ebba330f"><code>f18115c</code></a>
feat!: <code>no-shadow-restricted-names</code> report
<code>globalThis</code> by default (<a
href="https://redirect.github.com/eslint/eslint/issues/20027">#20027</a>)
(sethamus)</li>
<li><a
href="https://github.com/eslint/eslint/commit/c6358c31fbd3937b92d89be2618ffdf5a774604e"><code>c6358c3</code></a>
feat!: Require Node.js <code>^20.19.0 || ^22.13.0 || &gt;=24</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/20160">#20160</a>)
(Milos Djermanovic)</li>
</ul>
<h2>Features</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/bff9091927811497dbf066b0e3b85ecb37d43822"><code>bff9091</code></a>
feat: handle <code>Array.fromAsync</code> in
<code>array-callback-return</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/20457">#20457</a>)
(Francesco Trotta)</li>
<li><a
href="https://github.com/eslint/eslint/commit/290c594bb50c439fb71bc75521ee5360daa8c222"><code>290c594</code></a>
feat: add <code>self</code> to <code>no-implied-eval</code> rule (<a
href="https://redirect.github.com/eslint/eslint/issues/20468">#20468</a>)
(sethamus)</li>
<li><a
href="https://github.com/eslint/eslint/commit/43677de07ebd6e14bfac40a46ad749ba783c45f2"><code>43677de</code></a>
feat: fix handling of function and class expression names in
<code>no-shadow</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/20432">#20432</a>)
(Milos Djermanovic)</li>
<li><a
href="https://github.com/eslint/eslint/commit/f0cafe5f37e7765e9d8c2751b5f5d33107687009"><code>f0cafe5</code></a>
feat: rule tester add assertion option <code>requireData</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/20409">#20409</a>)
(fnx)</li>
<li><a
href="https://github.com/eslint/eslint/commit/f7ab6937e63bc618d326710858f5861a68f80616"><code>f7ab693</code></a>
feat: output RuleTester test case failure index (<a
href="https://redirect.github.com/eslint/eslint/issues/19976">#19976</a>)
(ST-DDT)</li>
<li><a
href="https://github.com/eslint/eslint/commit/7cbcbf9c3c2008deee7d143ae35e668e8ffbccb3"><code>7cbcbf9</code></a>
feat: add <code>countThis</code> option to <code>max-params</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/20236">#20236</a>)
(Gerkin)</li>
<li><a
href="https://github.com/eslint/eslint/commit/f148a5eaa1e89dd80ade62f0a690186b00b9f6e1"><code>f148a5e</code></a>
feat: add error assertion options (<a
href="https://redirect.github.com/eslint/eslint/issues/20247">#20247</a>)
(ST-DDT)</li>
<li><a
href="https://github.com/eslint/eslint/commit/09e66549ecada6dcb8c567a60faf044fce049188"><code>09e6654</code></a>
feat: update error loc of <code>require-yield</code> and
<code>no-useless-constructor</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/20267">#20267</a>)
(Tanuj Kanti)</li>
</ul>
<h2>Bug Fixes</h2>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/436b82f3c0a8cfa2fdc17d173e95ea11d5d3ee03"><code>436b82f</code></a>
fix: update eslint (<a
href="https://redirect.github.com/eslint/eslint/issues/20473">#20473</a>)
(renovate[bot])</li>
<li><a
href="https://github.com/eslint/eslint/commit/1d29d22fe302443cec2a11da0816397f94af97ec"><code>1d29d22</code></a>
fix: detect default <code>this</code> binding in
<code>Array.fromAsync</code> callbacks (<a
href="https://redirect.github.com/eslint/eslint/issues/20456">#20456</a>)
(Francesco Trotta)</li>
<li><a
href="https://github.com/eslint/eslint/commit/727451eff55b35d853e0e443d0de58f4550762bf"><code>727451e</code></a>
fix: fix regression of global mode report range in <code>strict</code>
rule (<a
href="https://redirect.github.com/eslint/eslint/issues/20462">#20462</a>)
(ntnyq)</li>
<li><a
href="https://github.com/eslint/eslint/commit/e80485fcd27196fa0b6f6b5c7ac8cf49ad4b079d"><code>e80485f</code></a>
fix: remove fake <code>FlatESLint</code> and <code>LegacyESLint</code>
exports (<a
href="https://redirect.github.com/eslint/eslint/issues/20460">#20460</a>)
(Francesco Trotta)</li>
<li><a
href="https://github.com/eslint/eslint/commit/9eeff3bc13813a786b8a4c3815def97c0fb646ef"><code>9eeff3b</code></a>
fix: update esquery (<a
href="https://redirect.github.com/eslint/eslint/issues/20423">#20423</a>)
(cryptnix)</li>
<li><a
href="https://github.com/eslint/eslint/commit/b34b93852d014ebbcf3538d892b55e0216cdf681"><code>b34b938</code></a>
fix: use <code>Error.prepareStackTrace</code> to estimate failing test
location (<a
href="https://redirect.github.com/eslint/eslint/issues/20436">#20436</a>)
(Francesco Trotta)</li>
<li><a
href="https://github.com/eslint/eslint/commit/51aab5393b058f7cbed69041a9069b2bd106aabd"><code>51aab53</code></a>
fix: update eslint (<a
href="https://redirect.github.com/eslint/eslint/issues/20443">#20443</a>)
(renovate[bot])</li>
<li><a
href="https://github.com/eslint/eslint/commit/23490b266276792896a0b7b43c49a1ce87bf8568"><code>23490b2</code></a>
fix: handle space before colon in <code>RuleTester</code> location
estimation (<a
href="https://redirect.github.com/eslint/eslint/issues/20433">#20433</a>)
(Francesco Trotta)</li>
<li><a
href="https://github.com/eslint/eslint/commit/f244dbf2191267a4cafd08645243624baf3e8c83"><code>f244dbf</code></a>
fix: use <code>MessagePlaceholderData</code> type from
<code>@eslint/core</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/20348">#20348</a>)
(루밀LuMir)</li>
<li><a
href="https://github.com/eslint/eslint/commit/d186f8c0747f14890e86a5a39708b052b391ddaf"><code>d186f8c</code></a>
fix: update eslint (<a
href="https://redirect.github.com/eslint/eslint/issues/20427">#20427</a>)
(renovate[bot])</li>
<li><a
href="https://github.com/eslint/eslint/commit/2332262deb4ef3188b210595896bb0ff552a7e66"><code>2332262</code></a>
fix: error location should not modify error message in RuleTester (<a
href="https://redirect.github.com/eslint/eslint/issues/20421">#20421</a>)
(Milos Djermanovic)</li>
<li><a
href="https://github.com/eslint/eslint/commit/ab99b21a6715dee1035d8f4e6d6841853eb5563f"><code>ab99b21</code></a>
fix: ensure <code>filename</code> is passed as third argument to
<code>verifyAndFix()</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/20405">#20405</a>)
(루밀LuMir)</li>
<li><a
href="https://github.com/eslint/eslint/commit/8a60f3bc80ad96c65feeb29886342623c630199c"><code>8a60f3b</code></a>
fix: remove <code>ecmaVersion</code> and <code>sourceType</code> from
<code>ParserOptions</code> type (<a
href="https://redirect.github.com/eslint/eslint/issues/20415">#20415</a>)
(Pixel998)</li>
<li><a
href="https://github.com/eslint/eslint/commit/eafd727a060131f7fc79b2eb5698d8d27683c3a2"><code>eafd727</code></a>
fix: remove <code>TDZ</code> scope type (<a
href="https://redirect.github.com/eslint/eslint/issues/20231">#20231</a>)
(jaymarvelz)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/eslint/eslint/commit/4e6c4ac042e321da8fc29ce53ed03c86dcaa44a7"><code>4e6c4ac</code></a>
10.0.0</li>
<li><a
href="https://github.com/eslint/eslint/commit/ddd8a223000ac6a2182cc8eae35254806a3b0289"><code>ddd8a22</code></a>
Build: changelog update for 10.0.0</li>
<li><a
href="https://github.com/eslint/eslint/commit/bff9091927811497dbf066b0e3b85ecb37d43822"><code>bff9091</code></a>
feat: handle <code>Array.fromAsync</code> in
<code>array-callback-return</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/20457">#20457</a>)</li>
<li><a
href="https://github.com/eslint/eslint/commit/1ece282c2286b5dc187ece2a793dbd8798f20bd7"><code>1ece282</code></a>
chore: ignore <code>/docs/v9.x</code> in link checker (<a
href="https://redirect.github.com/eslint/eslint/issues/20452">#20452</a>)</li>
<li><a
href="https://github.com/eslint/eslint/commit/034e1397446205e83eb341354605380195c88633"><code>034e139</code></a>
ci: add type integration test for
<code>@html-eslint/eslint-plugin</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/20345">#20345</a>)</li>
<li><a
href="https://github.com/eslint/eslint/commit/f3fbc2f60cbe2c718364feb8c3fc0452c0df3c56"><code>f3fbc2f</code></a>
chore: set <code>@eslint/js</code> version to 10.0.0 to skip releasing
it (<a
href="https://redirect.github.com/eslint/eslint/issues/20466">#20466</a>)</li>
<li><a
href="https://github.com/eslint/eslint/commit/e978ddaab7e6a3c38b4a2afa721148a6ef38f29a"><code>e978dda</code></a>
docs: Update README</li>
<li><a
href="https://github.com/eslint/eslint/commit/4cecf8393ae9af18c4cfd50621115eb23b3d0cb6"><code>4cecf83</code></a>
docs: Update README</li>
<li><a
href="https://github.com/eslint/eslint/commit/c79f0ab2e2d242a93b08ff2f6a0712e2ef60b7b8"><code>c79f0ab</code></a>
docs: Update README</li>
<li><a
href="https://github.com/eslint/eslint/commit/afc06817bbd0625c7b0a46bdc81c38dab0c99441"><code>afc0681</code></a>
chore: remove scopeManager.addGlobals patch for typescript-eslint parser
(<a
href="https://redirect.github.com/eslint/eslint/issues/20">#20</a>...</li>
<li>Additional commits viewable in <a
href="https://github.com/eslint/eslint/compare/v8.57.1...v10.0.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `eslint-config-prettier` from 8.10.2 to 10.1.8
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/prettier/eslint-config-prettier/releases">eslint-config-prettier's
releases</a>.</em></p>
<blockquote>
<h2>v10.1.8</h2>
<p>republish latest version</p>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/prettier/eslint-config-prettier/compare/v10.1.5...v10.1.8">https://github.com/prettier/eslint-config-prettier/compare/v10.1.5...v10.1.8</a></p>
<h2>v10.1.5</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/prettier/eslint-config-prettier/pull/332">#332</a>
<a
href="https://github.com/prettier/eslint-config-prettier/commit/60fef02574467d31d10ff47ecb567d378483c9d4"><code>60fef02</code></a>
Thanks <a href="https://github.com/JounQin"><code>@​JounQin</code></a>!
- chore: add <code>funding</code> field into
<code>package.json</code></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/prettier/eslint-config-prettier/compare/v10.1.4...v10.1.5">https://github.com/prettier/eslint-config-prettier/compare/v10.1.4...v10.1.5</a></p>
<h2>v10.1.4</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/prettier/eslint-config-prettier/pull/328">#328</a>
<a
href="https://github.com/prettier/eslint-config-prettier/commit/94b47999e7eb13b703835729331376cef598b850"><code>94b4799</code></a>
Thanks <a
href="https://github.com/silvenon"><code>@​silvenon</code></a>! -
fix(cli): do not crash on no rules configured</li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/prettier/eslint-config-prettier/compare/v10.1.3...v10.1.4">https://github.com/prettier/eslint-config-prettier/compare/v10.1.3...v10.1.4</a></p>
<h2>v10.1.3</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/prettier/eslint-config-prettier/pull/325">#325</a>
<a
href="https://github.com/prettier/eslint-config-prettier/commit/4e95a1d50073f1a24f004239ad6e1a4ffa8476df"><code>4e95a1d</code></a>
Thanks <a href="https://github.com/pilikan"><code>@​pilikan</code></a>!
- fix: this package is <code>commonjs</code>, align its types
correctly</li>
</ul>
<h3>New Contributors</h3>
<ul>
<li><a href="https://github.com/pilikan"><code>@​pilikan</code></a> made
their first contribution in <a
href="https://redirect.github.com/prettier/eslint-config-prettier/pull/325">prettier/eslint-config-prettier#325</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/prettier/eslint-config-prettier/compare/v10.1.2...v10.1.3">https://github.com/prettier/eslint-config-prettier/compare/v10.1.2...v10.1.3</a></p>
<h2>v10.1.2</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/prettier/eslint-config-prettier/pull/321">#321</a>
<a
href="https://github.com/prettier/eslint-config-prettier/commit/a8768bfe54a91d08f0cef8705f91de2883436bb0"><code>a8768bf</code></a>
Thanks <a href="https://github.com/Fdawgs"><code>@​Fdawgs</code></a>! -
chore(package): add homepage for some 3rd-party registry - see <a
href="https://redirect.github.com/prettier/eslint-config-prettier/pull/321">#321</a>
for more details</li>
</ul>
<h2>v10.1.1</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/prettier/eslint-config-prettier/pull/309">#309</a>
<a
href="https://github.com/prettier/eslint-config-prettier/commit/eb56a5e09964e49045bccde3c616275eb0a0902d"><code>eb56a5e</code></a>
Thanks <a href="https://github.com/JounQin"><code>@​JounQin</code></a>!
- fix: separate the <code>/flat</code> entry for compatibility</p>
<p>For flat config users, the previous
<code>&quot;eslint-config-prettier&quot;</code> entry still works, but
<code>&quot;eslint-config-prettier/flat&quot;</code> adds a new
<code>name</code> property for <a
href="https://eslint.org/blog/2024/04/eslint-config-inspector/">config-inspector</a>,
we just can't add it for the default entry for compatibility.</p>
<p>See also <a
href="https://redirect.github.com/prettier/eslint-config-prettier/issues/308">prettier/eslint-config-prettier#308</a></p>
<pre lang="ts"><code>// before
import eslintConfigPrettier from &quot;eslint-config-prettier&quot;;
<p>// after<br />
import eslintConfigPrettier from
&quot;eslint-config-prettier/flat&quot;;<br />
</code></pre></p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/prettier/eslint-config-prettier/blob/main/CHANGELOG.md">eslint-config-prettier's
changelog</a>.</em></p>
<blockquote>
<h1>eslint-config-prettier</h1>
<h2>10.1.5</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/prettier/eslint-config-prettier/pull/332">#332</a>
<a
href="https://github.com/prettier/eslint-config-prettier/commit/60fef02574467d31d10ff47ecb567d378483c9d4"><code>60fef02</code></a>
Thanks <a href="https://github.com/JounQin"><code>@​JounQin</code></a>!
- chore: add <code>funding</code> field into
<code>package.json</code></li>
</ul>
<h2>10.1.4</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/prettier/eslint-config-prettier/pull/328">#328</a>
<a
href="https://github.com/prettier/eslint-config-prettier/commit/94b47999e7eb13b703835729331376cef598b850"><code>94b4799</code></a>
Thanks <a
href="https://github.com/silvenon"><code>@​silvenon</code></a>! -
fix(cli): do not crash on no rules configured</li>
</ul>
<h2>10.1.3</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/prettier/eslint-config-prettier/pull/325">#325</a>
<a
href="https://github.com/prettier/eslint-config-prettier/commit/4e95a1d50073f1a24f004239ad6e1a4ffa8476df"><code>4e95a1d</code></a>
Thanks <a href="https://github.com/pilikan"><code>@​pilikan</code></a>!
- fix: this package is <code>commonjs</code>, align its types
correctly</li>
</ul>
<h2>10.1.2</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/prettier/eslint-config-prettier/pull/321">#321</a>
<a
href="https://github.com/prettier/eslint-config-prettier/commit/a8768bfe54a91d08f0cef8705f91de2883436bb0"><code>a8768bf</code></a>
Thanks <a href="https://github.com/Fdawgs"><code>@​Fdawgs</code></a>! -
chore(package): add homepage for some 3rd-party registry - see <a
href="https://redirect.github.com/prettier/eslint-config-prettier/pull/321">#321</a>
for more details</li>
</ul>
<h2>10.1.1</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/prettier/eslint-config-prettier/pull/309">#309</a>
<a
href="https://github.com/prettier/eslint-config-prettier/commit/eb56a5e09964e49045bccde3c616275eb0a0902d"><code>eb56a5e</code></a>
Thanks <a href="https://github.com/JounQin"><code>@​JounQin</code></a>!
- fix: separate the <code>/flat</code> entry for compatibility</p>
<p>For flat config users, the previous
<code>&quot;eslint-config-prettier&quot;</code> entry still works, but
<code>&quot;eslint-config-prettier/flat&quot;</code> adds a new
<code>name</code> property for <a
href="https://eslint.org/blog/2024/04/eslint-config-inspector/">config-inspector</a>,
we just can't add it for the default entry for compatibility.</p>
<p>See also <a
href="https://redirect.github.com/prettier/eslint-config-prettier/issues/308">prettier/eslint-config-prettier#308</a></p>
<pre lang="ts"><code>// before
import eslintConfigPrettier from &quot;eslint-config-prettier&quot;;
<p>// after<br />
import eslintConfigPrettier from
&quot;eslint-config-prettier/flat&quot;;<br />
</code></pre></p>
</li>
</ul>
<h2>10.1.0</h2>
<h3>Minor Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/prettier/eslint-config-prettier/pull/306">#306</a>
<a
href="https://github.com/prettier/eslint-config-prettier/commit/56e2e3466391d0fdfc200e42130309c687aaab53"><code>56e2e34</code></a>
Thanks <a href="https://github.com/JounQin"><code>@​JounQin</code></a>!
- feat: migrate to exports field</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/prettier/eslint-config-prettier/commits/v10.1.8">compare
view</a></li>
</ul>
</details>
<br />

Updates `eslint-plugin-prettier` from 4.2.5 to 5.5.5
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/prettier/eslint-plugin-prettier/releases">eslint-plugin-prettier's
releases</a>.</em></p>
<blockquote>
<h2>v5.5.5</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/prettier/eslint-plugin-prettier/pull/772">#772</a>
<a
href="https://github.com/prettier/eslint-plugin-prettier/commit/7264ed0a6cf47fc36befed32f459e7d875f5992c"><code>7264ed0</code></a>
Thanks <a href="https://github.com/BPScott"><code>@​BPScott</code></a>!
- Bump prettier-linter-helpers dependency to v1.0.1</p>
</li>
<li>
<p><a
href="https://redirect.github.com/prettier/eslint-plugin-prettier/pull/776">#776</a>
<a
href="https://github.com/prettier/eslint-plugin-prettier/commit/77651a33cd16fd4c50b7346971990b900a42408b"><code>77651a3</code></a>
Thanks <a href="https://github.com/aswils"><code>@​aswils</code></a>! -
fix: bump synckit for yarn PnP ESM issue</p>
</li>
</ul>
<h2>v5.5.4</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/prettier/eslint-plugin-prettier/pull/755">#755</a>
<a
href="https://github.com/prettier/eslint-plugin-prettier/commit/723f7a803f014746f2146e5be021c9071fa52d7e"><code>723f7a8</code></a>
Thanks <a href="https://github.com/kbrilla"><code>@​kbrilla</code></a>!
- fix: add 'oxc', 'oxc-ts' and 'hermes' parsers to
<code>parserBlocklist</code></p>
</li>
<li>
<p><a
href="https://redirect.github.com/prettier/eslint-plugin-prettier/pull/751">#751</a>
<a
href="https://github.com/prettier/eslint-plugin-prettier/commit/cf52b306a533b971bf40bbbf0d2033a1ed4f3c5d"><code>cf52b30</code></a>
Thanks <a
href="https://github.com/andreww2012"><code>@​andreww2012</code></a>! -
fix: disallow extra properties in rule options</p>
</li>
</ul>
<h2>v5.5.3</h2>
<p>republish the latest version</p>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/prettier/eslint-plugin-prettier/compare/v5.5.2...v5.5.3">https://github.com/prettier/eslint-plugin-prettier/compare/v5.5.2...v5.5.3</a></p>
<h2>v5.5.2</h2>
<p>republish the latest version</p>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/prettier/eslint-plugin-prettier/compare/v5.5.1...v5.5.2">https://github.com/prettier/eslint-plugin-prettier/compare/v5.5.1...v5.5.2</a></p>
<h2>v5.5.1</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/prettier/eslint-plugin-prettier/pull/748">#748</a>
<a
href="https://github.com/prettier/eslint-plugin-prettier/commit/bfd1e9547de9afaaf30318735f2f441c0250b77e"><code>bfd1e95</code></a>
Thanks <a href="https://github.com/JounQin"><code>@​JounQin</code></a>!
- fix: use <code>prettierRcOptions</code> directly for prettier
3.6+</li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/prettier/eslint-plugin-prettier/compare/v5.5.0...v5.5.1">https://github.com/prettier/eslint-plugin-prettier/compare/v5.5.0...v5.5.1</a></p>
<h2>v5.5.0</h2>
<h3>Minor Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/prettier/eslint-plugin-prettier/pull/743">#743</a>
<a
href="https://github.com/prettier/eslint-plugin-prettier/commit/92f2c9c8f0b083a0208b4236cf5c8e4af5612a8b"><code>92f2c9c</code></a>
Thanks <a
href="https://github.com/dotcarmen"><code>@​dotcarmen</code></a>! -
feat: support non-js languages like <code>css</code> for
<code>@eslint/css</code> and <code>json</code> for
<code>@eslint/json</code></li>
</ul>
<h3>New Contributors</h3>
<ul>
<li><a href="https://github.com/dotcarmen"><code>@​dotcarmen</code></a>
made their first contribution in <a
href="https://redirect.github.com/prettier/eslint-plugin-prettier/pull/743">prettier/eslint-plugin-prettier#743</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/prettier/eslint-plugin-prettier/compare/v5.4.1...v5.5.0">https://github.com/prettier/eslint-plugin-prettier/compare/v5.4.1...v5.5.0</a></p>
<h2>v5.4.1</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/prettier/eslint-plugin-prettier/pull/740">#740</a>
<a
href="https://github.com/prettier/eslint-plugin-prettier/commit/c21521ffbe7bfb60bdca8cbf6349fba4de774d21"><code>c21521f</code></a>
Thanks <a href="https://github.com/JounQin"><code>@​JounQin</code></a>!
- fix(deps): bump <code>synckit</code> to v0.11.7 to fix potential
<code>TypeError: Cannot read properties of undefined (reading
'message')</code> error</li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/prettier/eslint-plugin-prettier/compare/v5.4.0...v5.4.1">https://github.com/prettier/eslint-plugin-prettier/compare/v5.4.0...v5.4.1</a></p>
<h2>v5.4.0</h2>
<h3>Minor Changes</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/prettier/eslint-plugin-prettier/blob/main/CHANGELOG.md">eslint-plugin-prettier's
changelog</a>.</em></p>
<blockquote>
<h2>5.5.5</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/prettier/eslint-plugin-prettier/pull/772">#772</a>
<a
href="https://github.com/prettier/eslint-plugin-prettier/commit/7264ed0a6cf47fc36befed32f459e7d875f5992c"><code>7264ed0</code></a>
Thanks <a href="https://github.com/BPScott"><code>@​BPScott</code></a>!
- Bump prettier-linter-helpers dependency to v1.0.1</p>
</li>
<li>
<p><a
href="https://redirect.github.com/prettier/eslint-plugin-prettier/pull/776">#776</a>
<a
href="https://github.com/prettier/eslint-plugin-prettier/commit/77651a33cd16fd4c50b7346971990b900a42408b"><code>77651a3</code></a>
Thanks <a href="https://github.com/aswils"><code>@​aswils</code></a>! -
fix: bump synckit for yarn PnP ESM issue</p>
</li>
</ul>
<h2>5.5.4</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p><a
href="https://redirect.github.com/prettier/eslint-plugin-prettier/pull/755">#755</a>
<a
href="https://github.com/prettier/eslint-plugin-prettier/commit/723f7a803f014746f2146e5be021c9071fa52d7e"><code>723f7a8</code></a>
Thanks <a href="https://github.com/kbrilla"><code>@​kbrilla</code></a>!
- fix: add 'oxc', 'oxc-ts' and 'hermes' parsers to
<code>parserBlocklist</code></p>
</li>
<li>
<p><a
href="https://redirect.github.com/prettier/eslint-plugin-prettier/pull/751">#751</a>
<a
href="https://github.com/prettier/eslint-plugin-prettier/commit/cf52b306a533b971bf40bbbf0d2033a1ed4f3c5d"><code>cf52b30</code></a>
Thanks <a
href="https://github.com/andreww2012"><code>@​andreww2012</code></a>! -
fix: disallow extra properties in rule options</p>
</li>
</ul>
<h2>5.5.1</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/prettier/eslint-plugin-prettier/pull/748">#748</a>
<a
href="https://github.com/prettier/eslint-plugin-prettier/commit/bfd1e9547de9afaaf30318735f2f441c0250b77e"><code>bfd1e95</code></a>
Thanks <a href="https://github.com/JounQin"><code>@​JounQin</code></a>!
- fix: use <code>prettierRcOptions</code> directly for prettier
3.6+</li>
</ul>
<h2>5.5.0</h2>
<h3>Minor Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/prettier/eslint-plugin-prettier/pull/743">#743</a>
<a
href="https://github.com/prettier/eslint-plugin-prettier/commit/92f2c9c8f0b083a0208b4236cf5c8e4af5612a8b"><code>92f2c9c</code></a>
Thanks <a
href="https://github.com/dotcarmen"><code>@​dotcarmen</code></a>! -
feat: support non-js languages like <code>css</code> for
<code>@eslint/css</code> and <code>json</code> for
<code>@eslint/json</code></li>
</ul>
<h2>5.4.1</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/prettier/eslint-plugin-prettier/pull/740">#740</a>
<a
href="https://github.com/prettier/eslint-plugin-prettier/commit/c21521ffbe7bfb60bdca8cbf6349fba4de774d21"><code>c21521f</code></a>
Thanks <a href="https://github.com/JounQin"><code>@​JounQin</code></a>!
- fix(deps): bump <code>synckit</code> to v0.11.7 to fix potential
<code>TypeError: Cannot read properties of undefined (reading
'message')</code> error</li>
</ul>
<h2>5.4.0</h2>
<h3>Minor Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/prettier/eslint-plugin-prettier/pull/736">#736</a>
<a
href="https://github.com/prettier/eslint-plugin-prettier/commit/59a0cae5f27801d7e00f257c6be059a848b32fbe"><code>59a0cae</code></a>
Thanks <a
href="https://github.com/yashtech00"><code>@​yashtech00</code></a>! -
refactor: migrate <code>worker.js</code> to <code>worker.mjs</code></li>
</ul>
<h2>5.3.1</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/prettier/eslint-plugin-prettier/pull/734">#734</a>
<a
href="https://github.com/prettier/eslint-plugin-prettier/commit/dcf2c8083e0f7146b7b7d641224ee2db8b318189"><code>dcf2c80</code></a>
Thanks <a href="https://github.com/JounQin"><code>@​JounQin</code></a>!
- ci: enable <code>NPM_CONFIG_PROVENANCE</code> env</li>
</ul>
<h2>5.3.0</h2>
<h3>Minor Changes</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/prettier/eslint-plugin-prettier/commit/e2c154a7214d4548dad225a56ee1e333d6389b66"><code>e2c154a</code></a>
chore: release eslint-plugin-prettier (<a
href="https://redirect.github.com/prettier/eslint-plugin-prettier/issues/773">#773</a>)</li>
<li><a
href="https://github.com/prettier/eslint-plugin-prettier/commit/6795c1abf6dc9949da8681b05ec31d323794d00c"><code>6795c1a</code></a>
build(deps): Bump the actions group across 1 directory with 2 updates
(<a
href="https://redirect.github.com/prettier/eslint-plugin-prettier/issues/774">#774</a>)</li>
<li><a
href="https://github.com/prettier/eslint-plugin-prettier/commit/77651a33cd16fd4c50b7346971990b900a42408b"><code>77651a3</code></a>
fix: bump synckit for yarn PnP ESM issue (<a
href="https://redirect.github.com/prettier/eslint-plugin-prettier/issues/776">#776</a>)</li>
<li><a
href="https://github.com/prettier/eslint-plugin-prettier/commit/7264ed0a6cf47fc36befed32f459e7d875f5992c"><code>7264ed0</code></a>
chore: bump prettier-linter-helpers to v1.0.1 (<a
href="https://redirect.github.com/prettier/eslint-plugin-prettier/issues/772">#772</a>)</li>
<li><a
href="https://github.com/prettier/eslint-plugin-prettier/commit/e11a5b7e71f41b3238da944ba1ee84f7f518a4f4"><code>e11a5b7</code></a>
build(deps): Bump the actions group across 1 directory with 3 updates
(<a
href="https://redirect.github.com/prettier/eslint-plugin-prettier/issues/769">#769</a>)</li>
<li><a
href="https://github.com/prettier/eslint-plugin-prettier/commit/befda88381335cd5491d2aaa16b67350ba3cc602"><code>befda88</code></a>
ci: enable trusted publishing (<a
href="https://redirect.github.com/prettier/eslint-plugin-prettier/issues/757">#757</a>)</li>
<li><a
href="https://github.com/prettier/eslint-plugin-prettier/commit/e2c31d20f326133157a12d0989097ebd52860c5b"><code>e2c31d2</code></a>
chore: release eslint-plugin-prettier (<a
href="https://redirect.github.com/prettier/eslint-plugin-prettier/issues/756">#756</a>)</li>
<li><a
href="https://github.com/prettier/eslint-plugin-prettier/commit/98a8bfd269f0f2ead6750ec88eb81f6d59b6c005"><code>98a8bfd</code></a>
chore(deps): update all dependencies (<a
href="https://redirect.github.com/prettier/eslint-plugin-prettier/issues/750">#750</a>)</li>
<li><a
href="https://github.com/prettier/eslint-plugin-prettier/commit/cf52b306a533b971bf40bbbf0d2033a1ed4f3c5d"><code>cf52b30</code></a>
fix: disallow extra properties in rule options (<a
href="https://redirect.github.com/prettier/eslint-plugin-prettier/issues/751">#751</a>)</li>
<li><a
href="https://github.com/prettier/eslint-plugin-prettier/commit/723f7a803f014746f2146e5be021c9071fa52d7e"><code>723f7a8</code></a>
fix: add 'oxc', 'oxc-ts' and 'hermes' parsers to
<code>parserBlocklist</code> (<a
href="https://redirect.github.com/prettier/eslint-plugin-prettier/issues/755">#755</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/prettier/eslint-plugin-prettier/compare/v4.2.5...v5.5.5">compare
view</a></li>
</ul>
</details>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by [GitHub Actions](<a
href="https://www.npmjs.com/~GitHub">https://www.npmjs.com/~GitHub</a>
Actions), a new releaser for eslint-plugin-prettier since your current
version.</p>
</details>
<br />

Updates `@typescript-eslint/eslint-plugin` from 5.62.0 to 8.55.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/typescript-eslint/typescript-eslint/releases"><code>@​typescript-eslint/eslint-plugin</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v8.55.0</h2>
<h2>8.55.0 (2026-02-09)</h2>
<h3>🚀 Features</h3>
<ul>
<li><strong>utils:</strong> deprecate defaultOptions in favor of
meta.defaultOptions (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11992">#11992</a>)</li>
</ul>
<h3>🩹 Fixes</h3>
<ul>
<li><strong>eslint-plugin:</strong> [no-unused-vars] remove trailing
newline when removing entire import (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11990">#11990</a>)</li>
<li><strong>eslint-plugin:</strong> [no-useless-default-assignment]
require strictNullChecks (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11966">#11966</a>,
<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/12000">#12000</a>)</li>
<li><strong>eslint-plugin:</strong> [no-useless-default-assignment]
report unnecessary defaults in ternary expressions (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11984">#11984</a>)</li>
<li><strong>eslint-plugin:</strong> [no-useless-default-assignment]
reduce param index to ts this handling (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11949">#11949</a>)</li>
<li><strong>typescript-estree:</strong> forbid invalid modifier in
object expression (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11931">#11931</a>)</li>
</ul>
<h3>❤️ Thank You</h3>
<ul>
<li>Christian Rose <a
href="https://github.com/chrros95"><code>@​chrros95</code></a></li>
<li>fisker Cheung <a
href="https://github.com/fisker"><code>@​fisker</code></a></li>
<li>Josh Goldberg</li>
<li>Maria Solano <a
href="https://github.com/MariaSolOs"><code>@​MariaSolOs</code></a></li>
<li>Minyeong Kim <a
href="https://github.com/minyeong981"><code>@​minyeong981</code></a></li>
<li>SungHyun627 <a
href="https://github.com/SungHyun627"><code>@​SungHyun627</code></a></li>
<li>Yukihiro Hasegawa <a
href="https://github.com/y-hsgw"><code>@​y-hsgw</code></a></li>
</ul>
<p>See <a
href="https://github.com/typescript-eslint/typescript-eslint/releases/tag/v8.55.0">GitHub
Releases</a> for more information.</p>
<p>You can read about our <a
href="https://typescript-eslint.io/users/versioning">versioning
strategy</a> and <a
href="https://typescript-eslint.io/users/releases">releases</a> on our
website.</p>
<h2>v8.54.0</h2>
<h2>8.54.0 (2026-01-26)</h2>
<h3>🚀 Features</h3>
<ul>
<li><strong>eslint-plugin-internal:</strong> add prefer-tsutils-methods
rule (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11974">#11974</a>,
<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/issues/11625">#11625</a>)</li>
<li><strong>scope-manager:</strong> support ScopeManager#addGlobals (<a
href="https://redirect.github.com/typescript-eslint/typescript-eslint/pull/11914">#11914</a>)</li>
<li><strong>typescript-estree:</strong> add shortcut methods to
ParserServicesWithTypeInformation (<a href="http...

_Description has been truncated_

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-17 09:21:54 -08:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>John Kennedy
17b3285907 chore(deps): bump the all-dependencies group in /libs/sdk-py with 4 updates (#6809)
Bumps the all-dependencies group in /libs/sdk-py with 4 updates:
[orjson](https://github.com/ijl/orjson),
[ruff](https://github.com/astral-sh/ruff),
[mypy](https://github.com/python/mypy) and
[ty](https://github.com/astral-sh/ty).

Updates `orjson` from 3.11.5 to 3.11.7
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/ijl/orjson/releases">orjson's
releases</a>.</em></p>
<blockquote>
<h2>3.11.7</h2>
<h3>Changed</h3>
<ul>
<li>Use a faster library to serialize <code>float</code>. Users with
byte-exact regression
tests should note positive exponents are now written using a
<code>+</code>, e.g.,
<code>1.2e+30</code> instead of <code>1.2e30</code>. Both formats are
spec-compliant.</li>
<li>ABI compatibility with CPython 3.15 alpha 5 free-threading.</li>
</ul>
<h2>3.11.6</h2>
<h3>Changed</h3>
<ul>
<li>orjson now includes code licensed under the Mozilla Public License
2.0 (MPL-2.0).</li>
<li>Drop support for Python 3.9.</li>
<li>ABI compatibility with CPython 3.15 alpha 5.</li>
<li>Build now depends on Rust 1.89 or later instead of 1.85.</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>Fix sporadic crash serializing deeply nested <code>list</code> of
<code>dict</code>.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/ijl/orjson/blob/master/CHANGELOG.md">orjson's
changelog</a>.</em></p>
<blockquote>
<h2>3.11.7 - 2026-02-02</h2>
<h3>Changed</h3>
<ul>
<li>Use a faster library to serialize <code>float</code>. Users with
byte-exact regression
tests should note positive exponents are now written using a
<code>+</code>, e.g.,
<code>1.2e+30</code> instead of <code>1.2e30</code>. Both formats are
spec-compliant.</li>
<li>ABI compatibility with CPython 3.15 alpha 5 free-threading.</li>
</ul>
<h2>3.11.6 - 2026-01-29</h2>
<h3>Changed</h3>
<ul>
<li>orjson now includes code licensed under the Mozilla Public License
2.0 (MPL-2.0).</li>
<li>Drop support for Python 3.9.</li>
<li>ABI compatibility with CPython 3.15 alpha 5.</li>
<li>Build now depends on Rust 1.89 or later instead of 1.85.</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>Fix sporadic crash serializing deeply nested <code>list</code> of
<code>dict</code>.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/ijl/orjson/commit/ec2b066cae79ae4a90ed126ac5723335dd99e408"><code>ec2b066</code></a>
3.11.7</li>
<li><a
href="https://github.com/ijl/orjson/commit/1ca01f78cf4198ec37407d83713afa6e5c53dbf9"><code>1ca01f7</code></a>
zmij</li>
<li><a
href="https://github.com/ijl/orjson/commit/1716a226bd1f38db01503f30cd37b0efec48d88e"><code>1716a22</code></a>
cargo update</li>
<li><a
href="https://github.com/ijl/orjson/commit/ec02024c3837255064f248c0d2d331319b75e9ad"><code>ec02024</code></a>
3.11.6</li>
<li><a
href="https://github.com/ijl/orjson/commit/d58168733189f82b3fd0c058dff73e05d09202e6"><code>d581687</code></a>
build, clippy misc</li>
<li><a
href="https://github.com/ijl/orjson/commit/4105b29b2275f200f6fae01349bef02ccf1bc2e2"><code>4105b29</code></a>
writer::num</li>
<li><a
href="https://github.com/ijl/orjson/commit/62bb185b70785ded49c79c26f8c9781f1e6fe370"><code>62bb185</code></a>
Fix sporadic crash on serializing object close</li>
<li><a
href="https://github.com/ijl/orjson/commit/d860078a973f44401265c5c4ad12a7dbe4f839ad"><code>d860078</code></a>
PyRef idiom refactors</li>
<li><a
href="https://github.com/ijl/orjson/commit/343ae2f148197918aba9f8562db42c364620e4b8"><code>343ae2f</code></a>
Deserializer, Utf8Buffer</li>
<li><a
href="https://github.com/ijl/orjson/commit/7835f58d1c56947d1cf7a18acdfc07a2bca9b0f2"><code>7835f58</code></a>
PyBytesRef and other input refactor</li>
<li>Additional commits viewable in <a
href="https://github.com/ijl/orjson/compare/3.11.5...3.11.7">compare
view</a></li>
</ul>
</details>
<br />

Updates `ruff` from 0.14.11 to 0.15.1
<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.15.1</h2>
<h2>Release Notes</h2>
<p>Released on 2026-02-12.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>airflow</code>] Add ruff rules to catch deprecated Airflow
imports for Airflow 3.1 (<code>AIR321</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22376">#22376</a>)</li>
<li>[<code>airflow</code>] Third positional parameter not named
<code>ti_key</code> should be flagged for
<code>BaseOperatorLink.get_link</code> (<code>AIR303</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22828">#22828</a>)</li>
<li>[<code>flake8-gettext</code>] Fix false negatives for plural
argument of <code>ngettext</code> (<code>INT001</code>,
<code>INT002</code>, <code>INT003</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/21078">#21078</a>)</li>
<li>[<code>pyflakes</code>] Fix infinite loop in preview fix for
<code>unused-import</code> (<code>F401</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23038">#23038</a>)</li>
<li>[<code>pygrep-hooks</code>] Detect non-existent mock methods in
standalone expressions (<code>PGH005</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22830">#22830</a>)</li>
<li>[<code>pylint</code>] Allow dunder submodules and improve diagnostic
range (<code>PLC2701</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22804">#22804</a>)</li>
<li>[<code>pyupgrade</code>] Improve diagnostic range for tuples
(<code>UP024</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23013">#23013</a>)</li>
<li>[<code>refurb</code>] Check subscripts in tuple do not use lambda
parameters in <code>reimplemented-operator</code> (<code>FURB118</code>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23079">#23079</a>)</li>
<li>[<code>ruff</code>] Detect mutable defaults in <code>field</code>
calls (<code>RUF008</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23046">#23046</a>)</li>
<li>[<code>ruff</code>] Ignore std <code>cmath.inf</code>
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23120">#23120</a>)</li>
<li>[<code>ruff</code>] New rule <code>float-equality-comparison</code>
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/20585">#20585</a>)</li>
<li>Don't format unlabeled Markdown code blocks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23106">#23106</a>)</li>
<li>Markdown formatting support in LSP (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23063">#23063</a>)</li>
<li>Support Quarto Markdown language markers (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22947">#22947</a>)</li>
<li>Support formatting <code>pycon</code> Markdown code blocks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23112">#23112</a>)</li>
<li>Use extension mapping to select Markdown code block language (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22934">#22934</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>Avoid false positive for undefined variables in <code>FAST001</code>
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23224">#23224</a>)</li>
<li>Avoid introducing syntax errors for <code>FAST003</code> autofix (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23227">#23227</a>)</li>
<li>Avoid suggesting <code>InitVar</code> for <code>__post_init__</code>
that references PEP 695 type parameters (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23226">#23226</a>)</li>
<li>Deduplicate type variables in generic functions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23225">#23225</a>)</li>
<li>Fix exception handler parenthesis removal for Python 3.14+ (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23126">#23126</a>)</li>
<li>Fix f-string middle panic when parsing t-strings (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23232">#23232</a>)</li>
<li>Wrap <code>RUF020</code> target for multiline fixes (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23210">#23210</a>)</li>
<li>Wrap <code>UP007</code> target for multiline fixes (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23208">#23208</a>)</li>
<li>Fix missing diagnostics for last range suppression in file (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23242">#23242</a>)</li>
<li>[<code>pyupgrade</code>] Fix syntax error on string with newline
escape and comment (<code>UP037</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22968">#22968</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Use <code>ruff</code> instead of <code>Ruff</code> as the program
name in GitHub output format (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23240">#23240</a>)</li>
<li>[<code>PT006</code>] Fix syntax error when unpacking nested tuples
in <code>parametrize</code> fixes (<a
href="https://redirect.github.com/astral-sh/ruff/issues/22441">#22441</a>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/22464">#22464</a>)</li>
<li>[<code>airflow</code>] Catch deprecated attribute access from
context key for Airflow 3.0 (<code>AIR301</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22850">#22850</a>)</li>
<li>[<code>airflow</code>] Capture deprecated arguments and a decorator
(<code>AIR301</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23170">#23170</a>)</li>
<li>[<code>flake8-boolean-trap</code>] Add
<code>multiprocessing.Value</code> to excluded functions for
<code>FBT003</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23010">#23010</a>)</li>
<li>[<code>flake8-bugbear</code>] Add a secondary annotation showing the
previous occurrence (<code>B033</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22634">#22634</a>)</li>
<li>[<code>flake8-type-checking</code>] Add sub-diagnostic showing the
runtime use of an annotation (<code>TC004</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23091">#23091</a>)</li>
<li>[<code>isort</code>] Support configurable import section heading
comments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23151">#23151</a>)</li>
<li>[<code>ruff</code>] Improve the diagnostic for <code>RUF012</code>
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23202">#23202</a>)</li>
</ul>
<h3>Formatter</h3>
<!-- 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.15.1</h2>
<p>Released on 2026-02-12.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>airflow</code>] Add ruff rules to catch deprecated Airflow
imports for Airflow 3.1 (<code>AIR321</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22376">#22376</a>)</li>
<li>[<code>airflow</code>] Third positional parameter not named
<code>ti_key</code> should be flagged for
<code>BaseOperatorLink.get_link</code> (<code>AIR303</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22828">#22828</a>)</li>
<li>[<code>flake8-gettext</code>] Fix false negatives for plural
argument of <code>ngettext</code> (<code>INT001</code>,
<code>INT002</code>, <code>INT003</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/21078">#21078</a>)</li>
<li>[<code>pyflakes</code>] Fix infinite loop in preview fix for
<code>unused-import</code> (<code>F401</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23038">#23038</a>)</li>
<li>[<code>pygrep-hooks</code>] Detect non-existent mock methods in
standalone expressions (<code>PGH005</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22830">#22830</a>)</li>
<li>[<code>pylint</code>] Allow dunder submodules and improve diagnostic
range (<code>PLC2701</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22804">#22804</a>)</li>
<li>[<code>pyupgrade</code>] Improve diagnostic range for tuples
(<code>UP024</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23013">#23013</a>)</li>
<li>[<code>refurb</code>] Check subscripts in tuple do not use lambda
parameters in <code>reimplemented-operator</code> (<code>FURB118</code>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23079">#23079</a>)</li>
<li>[<code>ruff</code>] Detect mutable defaults in <code>field</code>
calls (<code>RUF008</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23046">#23046</a>)</li>
<li>[<code>ruff</code>] Ignore std <code>cmath.inf</code>
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23120">#23120</a>)</li>
<li>[<code>ruff</code>] New rule <code>float-equality-comparison</code>
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/20585">#20585</a>)</li>
<li>Don't format unlabeled Markdown code blocks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23106">#23106</a>)</li>
<li>Markdown formatting support in LSP (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23063">#23063</a>)</li>
<li>Support Quarto Markdown language markers (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22947">#22947</a>)</li>
<li>Support formatting <code>pycon</code> Markdown code blocks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23112">#23112</a>)</li>
<li>Use extension mapping to select Markdown code block language (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22934">#22934</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>Avoid false positive for undefined variables in <code>FAST001</code>
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23224">#23224</a>)</li>
<li>Avoid introducing syntax errors for <code>FAST003</code> autofix (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23227">#23227</a>)</li>
<li>Avoid suggesting <code>InitVar</code> for <code>__post_init__</code>
that references PEP 695 type parameters (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23226">#23226</a>)</li>
<li>Deduplicate type variables in generic functions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23225">#23225</a>)</li>
<li>Fix exception handler parenthesis removal for Python 3.14+ (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23126">#23126</a>)</li>
<li>Fix f-string middle panic when parsing t-strings (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23232">#23232</a>)</li>
<li>Wrap <code>RUF020</code> target for multiline fixes (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23210">#23210</a>)</li>
<li>Wrap <code>UP007</code> target for multiline fixes (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23208">#23208</a>)</li>
<li>Fix missing diagnostics for last range suppression in file (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23242">#23242</a>)</li>
<li>[<code>pyupgrade</code>] Fix syntax error on string with newline
escape and comment (<code>UP037</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22968">#22968</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Use <code>ruff</code> instead of <code>Ruff</code> as the program
name in GitHub output format (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23240">#23240</a>)</li>
<li>[<code>PT006</code>] Fix syntax error when unpacking nested tuples
in <code>parametrize</code> fixes (<a
href="https://redirect.github.com/astral-sh/ruff/issues/22441">#22441</a>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/22464">#22464</a>)</li>
<li>[<code>airflow</code>] Catch deprecated attribute access from
context key for Airflow 3.0 (<code>AIR301</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22850">#22850</a>)</li>
<li>[<code>airflow</code>] Capture deprecated arguments and a decorator
(<code>AIR301</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23170">#23170</a>)</li>
<li>[<code>flake8-boolean-trap</code>] Add
<code>multiprocessing.Value</code> to excluded functions for
<code>FBT003</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23010">#23010</a>)</li>
<li>[<code>flake8-bugbear</code>] Add a secondary annotation showing the
previous occurrence (<code>B033</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22634">#22634</a>)</li>
<li>[<code>flake8-type-checking</code>] Add sub-diagnostic showing the
runtime use of an annotation (<code>TC004</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23091">#23091</a>)</li>
<li>[<code>isort</code>] Support configurable import section heading
comments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23151">#23151</a>)</li>
<li>[<code>ruff</code>] Improve the diagnostic for <code>RUF012</code>
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23202">#23202</a>)</li>
</ul>
<h3>Formatter</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/ruff/commit/a2f11d239f91cf8daedb0764ec15fcfe29c5ae6d"><code>a2f11d2</code></a>
Prepare for 0.15.1 (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23253">#23253</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/d29628e9665baa17272aad489398eb72b70e60ff"><code>d29628e</code></a>
Remove docker-run-action (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23254">#23254</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/8a042667651d7b1cdfc1742478d2b29b04d91be0"><code>8a04266</code></a>
[ty] Allow discovering dependencies in system Python environments (<a
href="https://redirect.github.com/astral-sh/ruff/issues/22994">#22994</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/55d06c8879761c5500e9558502abc84cefcb7163"><code>55d06c8</code></a>
Ensure pending suppression diagnostics are reported (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23242">#23242</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/d056a9fa6dfb842f2c0d439bf7b1a8099e5734ea"><code>d056a9f</code></a>
[<code>isort</code>] support for configurable import section heading
comments (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23151">#23151</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/e22fa4f14d8fae550249e452d11bc53756df5c7a"><code>e22fa4f</code></a>
[ty] Fix method calls on subclasses of <code>Any</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23248">#23248</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/fa56c1550d723e458b91dc2405d5537d40401d5c"><code>fa56c15</code></a>
[ty] Fix bound method access on <code>None</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23246">#23246</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/4fd07d0e1cbbb4e4c3f5b4c1f04f2d8b3f4a2bf2"><code>4fd07d0</code></a>
Make range suppression test snapshot actually useful (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23251">#23251</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/8c63bced13b21d1952a56e6a096d9c2ec4af442f"><code>8c63bce</code></a>
[ty] Include conditional symbols (like <code>datetime.UTC</code>) in
auto-import in more...</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/46be94361b3b4c54be911eb88bfbd9666eb06a6d"><code>46be943</code></a>
Exclude WASM artifacts from GitHub releases (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23221">#23221</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/ruff/compare/0.14.11...0.15.1">compare
view</a></li>
</ul>
</details>
<br />

Updates `mypy` from 1.19.0 to 1.19.1
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/python/mypy/blob/master/CHANGELOG.md">mypy's
changelog</a>.</em></p>
<blockquote>
<h3>Mypy 1.19.1</h3>
<ul>
<li>Fix noncommutative joins with bounded TypeVars (Shantanu, PR <a
href="https://redirect.github.com/python/mypy/pull/20345">20345</a>)</li>
<li>Respect output format for cached runs by serializing raw errors in
cache metas (Ivan Levkivskyi, PR <a
href="https://redirect.github.com/python/mypy/pull/20372">20372</a>)</li>
<li>Allow <code>types.NoneType</code> in match cases (A5rocks, PR <a
href="https://redirect.github.com/python/mypy/pull/20383">20383</a>)</li>
<li>Fix mypyc generator regression with empty tuple (BobTheBuidler, PR
<a
href="https://redirect.github.com/python/mypy/pull/20371">20371</a>)</li>
<li>Fix crash involving Unpack-ed TypeVarTuple (Shantanu, PR <a
href="https://redirect.github.com/python/mypy/pull/20323">20323</a>)</li>
<li>Fix crash on star import of redefinition (Ivan Levkivskyi, PR <a
href="https://redirect.github.com/python/mypy/pull/20333">20333</a>)</li>
<li>Fix crash on typevar with forward ref used in other module (Ivan
Levkivskyi, PR <a
href="https://redirect.github.com/python/mypy/pull/20334">20334</a>)</li>
<li>Fail with an explicit error on PyPy (Ivan Levkivskyi, PR <a
href="https://redirect.github.com/python/mypy/pull/20389">20389</a>)</li>
</ul>
<h3>Acknowledgements</h3>
<p>Thanks to all mypy contributors who contributed to this release:</p>
<ul>
<li>A5rocks</li>
<li>BobTheBuidler</li>
<li>bzoracler</li>
<li>Chainfire</li>
<li>Christoph Tyralla</li>
<li>David Foster</li>
<li>Frank Dana</li>
<li>Guo Ci</li>
<li>iap</li>
<li>Ivan Levkivskyi</li>
<li>James Hilton-Balfe</li>
<li>jhance</li>
<li>Joren Hammudoglu</li>
<li>Jukka Lehtosalo</li>
<li>KarelKenens</li>
<li>Kevin Kannammalil</li>
<li>Marc Mueller</li>
<li>Michael Carlstrom</li>
<li>Michael J. Sullivan</li>
<li>Piotr Sawicki</li>
<li>Randolf Scholz</li>
<li>Shantanu</li>
<li>Sigve Sebastian Farstad</li>
<li>sobolevn</li>
<li>Stanislav Terliakov</li>
<li>Stephen Morton</li>
<li>Theodore Ando</li>
<li>Thiago J. Barbalho</li>
<li>wyattscarpenter</li>
</ul>
<p>I’d also like to thank my employer, Dropbox, for supporting mypy
development.</p>
<h2>Mypy 1.18</h2>
<p>We’ve just uploaded mypy 1.18.1 to the Python Package Index (<a
href="https://pypi.org/project/mypy/">PyPI</a>).
Mypy is a static type checker for Python. This release includes new
features, performance</p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/python/mypy/commit/412c19a6bde31e7afa7f41afdf8356664689ae80"><code>412c19a</code></a>
Bump version to 1.19.1</li>
<li><a
href="https://github.com/python/mypy/commit/20aea0a6ca0710f5427239bdd2fd8e8bf1caf634"><code>20aea0a</code></a>
Update changelog for 1.19.1 (<a
href="https://redirect.github.com/python/mypy/issues/20414">#20414</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/2b23b507524bf1bd7513eea6f2a16fb91e072cb6"><code>2b23b50</code></a>
Serialize raw errors in cache metas (<a
href="https://redirect.github.com/python/mypy/issues/20372">#20372</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/f60f90fb8872bf722e32aefd548daaf6d8560e05"><code>f60f90f</code></a>
Fail on PyPy in main instead of setup.py (<a
href="https://redirect.github.com/python/mypy/issues/20389">#20389</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/58d485b4ea4776e0b9d4045b306cb0818ecc2aa6"><code>58d485b</code></a>
Fail with an explicit error on PyPy (<a
href="https://redirect.github.com/python/mypy/issues/20384">#20384</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/a4b31a26788b70c4a2a19adbafa2bbda43dc2e8b"><code>a4b31a2</code></a>
Allow <code>types.NoneType</code> in match cases (<a
href="https://redirect.github.com/python/mypy/issues/20383">#20383</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/8a6eff478416cd3ed3931a6ed77ce61c88ab69e9"><code>8a6eff4</code></a>
[mypyc] fix generator regression with empty tuple (<a
href="https://redirect.github.com/python/mypy/issues/20371">#20371</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/70eceea682c041c0d8e8462dffef9c7bb252e014"><code>70eceea</code></a>
Fix noncommutative joins with bounded TypeVars (<a
href="https://redirect.github.com/python/mypy/issues/20345">#20345</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/3890fc49bf7cc02db04b1e63eb2540aaacdeecc0"><code>3890fc4</code></a>
Fix crash involving Unpack-ed TypeVarTuple (<a
href="https://redirect.github.com/python/mypy/issues/20323">#20323</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/c93d917a86993e06dcc88e508f28f4f5199ce1c8"><code>c93d917</code></a>
Fix crash on star import of redefinition (<a
href="https://redirect.github.com/python/mypy/issues/20333">#20333</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/python/mypy/compare/v1.19.0...v1.19.1">compare
view</a></li>
</ul>
</details>
<br />

Updates `ty` from 0.0.1a27 to 0.0.17
<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.17</h2>
<h2>Release Notes</h2>
<p>Released on 2026-02-13.</p>
<h3>Bug fixes</h3>
<ul>
<li>Avoid <code>Literal</code> promotion for constrained
<code>TypeVar</code>s with <code>Literal</code> bounds (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23209">#23209</a>)</li>
<li>Fix false positives in <code>TypeVar</code> shadowing checks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23222">#23222</a>)</li>
</ul>
<h3>Core type checking</h3>
<ul>
<li>Support generic protocols (<a
href="https://redirect.github.com/astral-sh/ruff/pull/21902">#21902</a>)</li>
<li>Perform control-flow analysis in loops (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22794">#22794</a>)</li>
<li>Support <code>typing.Self</code> in attribute annotations (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23108">#23108</a>)</li>
<li>Support type narrowing in situations with calls to
<code>NoReturn</code> functions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23109">#23109</a>)</li>
<li>Support type narrowing and reachability analysis based on
<code>os.name</code> checks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23230">#23230</a>)</li>
<li>Detect overrides of <code>Final</code> class variables in subclasses
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23180">#23180</a>)</li>
<li>Fix bound method access on <code>None</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23246">#23246</a>)</li>
<li>Fix method calls on subclasses of <code>Any</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23248">#23248</a>)</li>
<li>Disallow type variables within PEP-695 type variable bounds and
constraints (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22982">#22982</a>)</li>
<li>Emit error for attribute access on union where some elements lack
the attribute (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23042">#23042</a>)</li>
<li>Emit error for invalid typevar defaults (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23194">#23194</a>)</li>
<li>Improve display of <code>ParamSpec</code>s in some situations (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23211">#23211</a>)</li>
</ul>
<h3>LSP server</h3>
<ul>
<li>Add hover and go-to-declaration support for subscript literals (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22837">#22837</a>)</li>
<li>Assign lower completion ranking to deprecated names in auto import
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23188">#23188</a>)</li>
<li>Improve spans of references to submodules imported in an
<code>__init__.py</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/21795">#21795</a>)</li>
<li>Include conditional symbols (like <code>datetime.UTC</code>) in
auto-import in more cases (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23249">#23249</a>)</li>
<li>Support auto-import for symbols in inlay hints (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22111">#22111</a>)</li>
<li>Include overload declarations in find-references (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23215">#23215</a>)</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Avoid <code>UnionBuilder</code> overhead when creating a new union
from the filtered elements of an existing union (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22352">#22352</a>)</li>
</ul>
<h3>Other changes</h3>
<ul>
<li>Allow discovering dependencies in system Python environments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22994">#22994</a>)</li>
<li>Apply workspace settings to virtual files (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23228">#23228</a>)</li>
<li>Add support for <code>--output-format=junit</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22125">#22125</a>)</li>
<li>Use a smaller diagnostic range for <code>inconsistent-mro</code>
diagnostics (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23213">#23213</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a href="https://github.com/carljm"><code>@​carljm</code></a></li>
<li><a
href="https://github.com/BurntSushi"><code>@​BurntSushi</code></a></li>
<li><a
href="https://github.com/charliermarsh"><code>@​charliermarsh</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.17</h2>
<p>Released on 2026-02-13.</p>
<h3>Bug fixes</h3>
<ul>
<li>Avoid <code>Literal</code> promotion for constrained
<code>TypeVar</code>s with <code>Literal</code> bounds (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23209">#23209</a>)</li>
<li>Fix false positives in <code>TypeVar</code> shadowing checks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23222">#23222</a>)</li>
</ul>
<h3>Core type checking</h3>
<ul>
<li>Support generic protocols (<a
href="https://redirect.github.com/astral-sh/ruff/pull/21902">#21902</a>)</li>
<li>Perform control-flow analysis in loops (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22794">#22794</a>)</li>
<li>Support <code>typing.Self</code> in attribute annotations (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23108">#23108</a>)</li>
<li>Support type narrowing in situations with calls to
<code>NoReturn</code> functions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23109">#23109</a>)</li>
<li>Support type narrowing and reachability analysis based on
<code>os.name</code> checks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23230">#23230</a>)</li>
<li>Detect overrides of <code>Final</code> class variables in subclasses
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23180">#23180</a>)</li>
<li>Fix bound method access on <code>None</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23246">#23246</a>)</li>
<li>Fix method calls on subclasses of <code>Any</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23248">#23248</a>)</li>
<li>Disallow type variables within PEP-695 type variable bounds and
constraints (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22982">#22982</a>)</li>
<li>Emit error for attribute access on union where some elements lack
the attribute (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23042">#23042</a>)</li>
<li>Emit error for invalid typevar defaults (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23194">#23194</a>)</li>
<li>Improve display of <code>ParamSpec</code>s in some situations (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23211">#23211</a>)</li>
</ul>
<h3>LSP server</h3>
<ul>
<li>Add hover and go-to-declaration support for subscript literals (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22837">#22837</a>)</li>
<li>Assign lower completion ranking to deprecated names in auto import
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23188">#23188</a>)</li>
<li>Improve spans of references to submodules imported in an
<code>__init__.py</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/21795">#21795</a>)</li>
<li>Include conditional symbols (like <code>datetime.UTC</code>) in
auto-import in more cases (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23249">#23249</a>)</li>
<li>Support auto-import for symbols in inlay hints (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22111">#22111</a>)</li>
<li>Include overload declarations in find-references (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23215">#23215</a>)</li>
</ul>
<h3>Performance</h3>
<ul>
<li>Avoid <code>UnionBuilder</code> overhead when creating a new union
from the filtered elements of an existing union (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22352">#22352</a>)</li>
</ul>
<h3>Other changes</h3>
<ul>
<li>Allow discovering dependencies in system Python environments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22994">#22994</a>)</li>
<li>Apply workspace settings to virtual files (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23228">#23228</a>)</li>
<li>Add support for <code>--output-format=junit</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22125">#22125</a>)</li>
<li>Use a smaller diagnostic range for <code>inconsistent-mro</code>
diagnostics (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23213">#23213</a>)</li>
</ul>
<h3>Contributors</h3>
<ul>
<li><a href="https://github.com/carljm"><code>@​carljm</code></a></li>
<li><a
href="https://github.com/BurntSushi"><code>@​BurntSushi</code></a></li>
<li><a
href="https://github.com/charliermarsh"><code>@​charliermarsh</code></a></li>
<li><a
href="https://github.com/Glyphack"><code>@​Glyphack</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/8cec857182f4bc28bd8e103940341643162777f8"><code>8cec857</code></a>
[ty] Bump version to 0.0.17 (<a
href="https://redirect.github.com/astral-sh/ty/issues/2806">#2806</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/3650f58ffd1ce30b6ba92deed8bfc77322447aef"><code>3650f58</code></a>
docs: Clarify that nvim-lspconfig is the recommended way of using ty in
all v...</li>
<li><a
href="https://github.com/astral-sh/ty/commit/55b8ff2055aeb212d3412fb18df3ccc44553d074"><code>55b8ff2</code></a>
Add note about fallback behavior to <code>python</code> in
<code>PATH</code> (<a
href="https://redirect.github.com/astral-sh/ty/issues/2787">#2787</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/e96ea4cd97534cb43bee6111f36bdff109c181b5"><code>e96ea4c</code></a>
Bump version to 0.0.16 (<a
href="https://redirect.github.com/astral-sh/ty/issues/2779">#2779</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/b393d32aa6e07e2c9100cb86b4383e78372edc40"><code>b393d32</code></a>
Update docker/login-action action to v3.7.0 (<a
href="https://redirect.github.com/astral-sh/ty/issues/2754">#2754</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/532b111c6a6787fb135e6491e47a9d41fe29d4a0"><code>532b111</code></a>
Update actions/cache action to v5.0.3 (<a
href="https://redirect.github.com/astral-sh/ty/issues/2751">#2751</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/61b037612f91b1683cab04bf68bdce4dca7857cf"><code>61b0376</code></a>
Update astral-sh/setup-uv action to v7.3.0 (<a
href="https://redirect.github.com/astral-sh/ty/issues/2753">#2753</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/216f8dc41a6222aac93feebda4828aa3b8535b4d"><code>216f8dc</code></a>
Update prek dependencies (<a
href="https://redirect.github.com/astral-sh/ty/issues/2752">#2752</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/044af7fda21189c69a489362f451ebd600ef460a"><code>044af7f</code></a>
FAQ: Why doesn't ty warn about missing type annotations? (<a
href="https://redirect.github.com/astral-sh/ty/issues/2721">#2721</a>)</li>
<li><a
href="https://github.com/astral-sh/ty/commit/eb43dff062024361be79449ebb1cff9ab61366a9"><code>eb43dff</code></a>
Bump version to 0.0.15 (<a
href="https://redirect.github.com/astral-sh/ty/issues/2717">#2717</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/ty/compare/0.0.1-alpha.27...0.0.17">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 <65985482+jkennedyvz@users.noreply.github.com>
2026-02-17 09:21:26 -08:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
20570cf700 chore(deps): bump langsmith from 0.3.66 to 0.3.87 in /libs/cli/js-monorepo-example (#6840)
Bumps [langsmith](https://github.com/langchain-ai/langsmith-sdk) from
0.3.66 to 0.3.87.
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/langchain-ai/langsmith-sdk/commits">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=langsmith&package-manager=npm_and_yarn&previous-version=0.3.66&new-version=0.3.87)](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-02-17 08:58:20 -08:00
df94475d3a fix(ci): skip server startup tests when LANGSMITH_API_KEY unavailable (#6844)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 06:12:35 -08:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
270621db66 chore(deps): bump the all-dependencies group in /libs/prebuilt with 3 updates (#6810)
Bumps the all-dependencies group in /libs/prebuilt with 3 updates:
[langchain-core](https://github.com/langchain-ai/langchain),
[syrupy](https://github.com/syrupy-project/syrupy) and
[ruff](https://github.com/astral-sh/ruff).

Updates `langchain-core` from 1.2.7 to 1.2.12
<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.2.12</h2>
<p>Changes since langchain-core==1.2.11</p>
<p>release(core): 1.2.12 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35192">#35192</a>)
fix(core): fix setting <code>ChatGeneration.text</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35191">#35191</a>)</p>
<h2>langchain-core==1.2.11</h2>
<p>Changes since langchain-core==1.2.10</p>
<p>release(core): 1.2.11 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35144">#35144</a>)
fix(openai): sanitize urls when counting tokens in images (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35143">#35143</a>)
chore(core): clean up docstring mismatch and redundant logic in
langchain-core (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35064">#35064</a>)
fix(core): replace bare except with Exception in tracer (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35138">#35138</a>)</p>
<h2>langchain-core==1.2.10</h2>
<p>Changes since langchain-core==1.2.9</p>
<p>release(core): 1.2.10 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35136">#35136</a>)
chore(deps): bump the langchain-deps group across 3 directories with 40
updates (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35129">#35129</a>)
chore(deps): bump the langchain-deps group across 3 directories with 11
updates (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35121">#35121</a>)
feat(core): add ContextOverflowError, raise in anthropic and openai (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35099">#35099</a>)
feat(model-profiles): add <code>text_inputs</code> and
<code>text_outputs</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35084">#35084</a>)
feat(core): count tokens from tool schemas in
<code>count_tokens_approximately</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35098">#35098</a>)
docs(core): add missing <code>name</code> docstring for
<code>RunnableSerializable</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35088">#35088</a>)</p>
<h2>langchain-core==1.2.9</h2>
<p>Changes since langchain-core==1.2.8</p>
<p>release(core): 1.2.9 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35025">#35025</a>)
fix(core): adjust cap when scaling approximate token counts (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35017">#35017</a>)
revert: precompile hex color regex pattern at module level (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35016">#35016</a>)
chore: add <code>make type</code> target (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35015">#35015</a>)
revert: &quot;chore: add typing target in <code>Makefile</code>&quot;
(<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35013">#35013</a>)
chore: add typing target in <code>Makefile</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35012">#35012</a>)
fix(core): apply cap when scaling approximate token counts (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35005">#35005</a>)
feat(core): allow scaling by reported usage when counting tokens
approximately (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34996">#34996</a>)
test(core): increase <code>delta_time</code> for flaky test (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34982">#34982</a>)
chore: enrich <code>pyproject.toml</code> files (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34980">#34980</a>)</p>
<h2>langchain-core==1.2.8</h2>
<p>Changes since langchain-core==1.2.7</p>
<p>release(core): 1.2.8 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34975">#34975</a>)
docs(core): add examples for <code>pretty_repr</code>,
<code>pretty_print</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34968">#34968</a>)
docs(core): use proper admonition for <code>get_buffer_string</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34967">#34967</a>)
docs: add usage examples to core classes (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34841">#34841</a>)
chore(core): fix docstring format (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34966">#34966</a>)
chore(deps): bump the uv group across 20 directories with 3 updates (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34941">#34941</a>)
docs: add example to create_message function docstring (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34851">#34851</a>)
docs(core): clarify <a
href="https://github.com/tool"><code>@​tool</code></a> decorator
argument and return type requirements (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34860">#34860</a>)</p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/langchain-ai/langchain/commit/b06716fb879f0d656ce4d1dad4a9710a61e8ec1e"><code>b06716f</code></a>
release(core): 1.2.12 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35192">#35192</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/16cabfa212782d03b00e08658fb3e74160a1dd45"><code>16cabfa</code></a>
fix(core): fix setting <code>ChatGeneration.text</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35191">#35191</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/8f859bd91f122b532689db199f69a6464a1bf7ef"><code>8f859bd</code></a>
release(huggingface): 1.2.1 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35182">#35182</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/19ddd42891514aba6d2c92cd32a915e7bb4b7b31"><code>19ddd42</code></a>
fix(ollama): raise error when clients are not initialized (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35185">#35185</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/a50d86c353bdf611bd0b908d5fc3d737086dba98"><code>a50d86c</code></a>
docs(langchain-classic): clarify MultiVectorRetriever usage (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35053">#35053</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/f89e30eb131d48c5354dd98c068a229b4c585f2d"><code>f89e30e</code></a>
chore(huggingface): version bump for huggingface-hub and transformers
deps (#...</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/6ac12b330a5c4912c37aa3bd888bc086d5d387f7"><code>6ac12b3</code></a>
chore: bump pillow from 11.3.0 to 12.1.1 in /libs/partners/openai (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35177">#35177</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/d41dedae978dfd4e4ee82d57fc1f0c530d827b90"><code>d41deda</code></a>
fix(langchain-classic): validate ensemble retriever weights (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35078">#35078</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/9d0bd8376cdd19dc19ac34d15a34dabe94361d8b"><code>9d0bd83</code></a>
chore: bump pillow from 11.3.0 to 12.1.1 in /libs/partners/perplexity
(<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35176">#35176</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/f22f5d5d673d2db5dc8a68991cdc063664c6f96b"><code>f22f5d5</code></a>
chore(deps): bump pillow from 11.3.0 to 12.1.1 in /libs/langchain (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35175">#35175</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/langchain-ai/langchain/compare/langchain-core==1.2.7...langchain-core==1.2.12">compare
view</a></li>
</ul>
</details>
<br />

Updates `syrupy` from 5.0.0 to 5.1.0
<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>v5.1.0</h2>
<h1><a
href="https://github.com/syrupy-project/syrupy/compare/v5.0.0...v5.1.0">5.1.0</a>
(2026-01-25)</h1>
<h3>Features</h3>
<ul>
<li>add serializer plugin system; plugins for data models (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1062">#1062</a>)
(<a
href="https://github.com/syrupy-project/syrupy/commit/df9bc8f6b3a222dde82167e10a2e6bb57456305a">df9bc8f</a>)</li>
</ul>
</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>
<h1><a
href="https://github.com/syrupy-project/syrupy/compare/v5.0.0...v5.1.0">5.1.0</a>
(2026-01-25)</h1>
<h3>Features</h3>
<ul>
<li>add serializer plugin system; plugins for data models (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1062">#1062</a>)
(<a
href="https://github.com/syrupy-project/syrupy/commit/df9bc8f6b3a222dde82167e10a2e6bb57456305a">df9bc8f</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/7096efdee61a8e1bc47492bdd0bc860766df40e9"><code>7096efd</code></a>
chore(release): 5.1.0 [skip ci]</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/07aa00dd48d65e74814cec863b5f236e09afb464"><code>07aa00d</code></a>
chore(deps): update dependency attrs to v25 (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1063">#1063</a>)</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/1f29ae061e9557e205e50fb2f9971ee95c4bd08e"><code>1f29ae0</code></a>
docs: add bwrob as a contributor for code (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1064">#1064</a>)</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/df9bc8f6b3a222dde82167e10a2e6bb57456305a"><code>df9bc8f</code></a>
feat: add serializer plugin system; plugins for data models (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1062">#1062</a>)</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/841257deaf598df7c3d154b8e2d694f8bb7e5055"><code>841257d</code></a>
chore(deps): update dependency coverage to v7.13.1 (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1061">#1061</a>)</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/2d8dfa7f7bb2a5f7c0210107dbb65b62a615d434"><code>2d8dfa7</code></a>
chore(deps): update codecov/codecov-action action to v5.5.2 (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1056">#1056</a>)</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/f5f9ef77027983d3b62d8cc5bfc3a9ef058fe509"><code>f5f9ef7</code></a>
chore(deps): update dependency debugpy to v1.8.18 (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1057">#1057</a>)</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/eaeb6ae11f57aa3e595d4c45e7be4a3ed2d66dfc"><code>eaeb6ae</code></a>
chore(deps): update dependency pytest to v9.0.2 (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1055">#1055</a>)</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/263b23b768ef761c3f7e1faa0671b0709c1887b1"><code>263b23b</code></a>
chore(deps): update python docker tag to v3.14.1 (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1054">#1054</a>)</li>
<li><a
href="https://github.com/syrupy-project/syrupy/commit/a0dd77b023fee34ff0968a822e0d0740c9c7fb93"><code>a0dd77b</code></a>
chore(deps): update actions/checkout action to v6.0.1 (<a
href="https://redirect.github.com/syrupy-project/syrupy/issues/1053">#1053</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/syrupy-project/syrupy/compare/v5.0.0...v5.1.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `ruff` from 0.14.13 to 0.15.1
<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.15.1</h2>
<h2>Release Notes</h2>
<p>Released on 2026-02-12.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>airflow</code>] Add ruff rules to catch deprecated Airflow
imports for Airflow 3.1 (<code>AIR321</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22376">#22376</a>)</li>
<li>[<code>airflow</code>] Third positional parameter not named
<code>ti_key</code> should be flagged for
<code>BaseOperatorLink.get_link</code> (<code>AIR303</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22828">#22828</a>)</li>
<li>[<code>flake8-gettext</code>] Fix false negatives for plural
argument of <code>ngettext</code> (<code>INT001</code>,
<code>INT002</code>, <code>INT003</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/21078">#21078</a>)</li>
<li>[<code>pyflakes</code>] Fix infinite loop in preview fix for
<code>unused-import</code> (<code>F401</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23038">#23038</a>)</li>
<li>[<code>pygrep-hooks</code>] Detect non-existent mock methods in
standalone expressions (<code>PGH005</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22830">#22830</a>)</li>
<li>[<code>pylint</code>] Allow dunder submodules and improve diagnostic
range (<code>PLC2701</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22804">#22804</a>)</li>
<li>[<code>pyupgrade</code>] Improve diagnostic range for tuples
(<code>UP024</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23013">#23013</a>)</li>
<li>[<code>refurb</code>] Check subscripts in tuple do not use lambda
parameters in <code>reimplemented-operator</code> (<code>FURB118</code>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23079">#23079</a>)</li>
<li>[<code>ruff</code>] Detect mutable defaults in <code>field</code>
calls (<code>RUF008</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23046">#23046</a>)</li>
<li>[<code>ruff</code>] Ignore std <code>cmath.inf</code>
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23120">#23120</a>)</li>
<li>[<code>ruff</code>] New rule <code>float-equality-comparison</code>
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/20585">#20585</a>)</li>
<li>Don't format unlabeled Markdown code blocks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23106">#23106</a>)</li>
<li>Markdown formatting support in LSP (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23063">#23063</a>)</li>
<li>Support Quarto Markdown language markers (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22947">#22947</a>)</li>
<li>Support formatting <code>pycon</code> Markdown code blocks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23112">#23112</a>)</li>
<li>Use extension mapping to select Markdown code block language (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22934">#22934</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>Avoid false positive for undefined variables in <code>FAST001</code>
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23224">#23224</a>)</li>
<li>Avoid introducing syntax errors for <code>FAST003</code> autofix (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23227">#23227</a>)</li>
<li>Avoid suggesting <code>InitVar</code> for <code>__post_init__</code>
that references PEP 695 type parameters (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23226">#23226</a>)</li>
<li>Deduplicate type variables in generic functions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23225">#23225</a>)</li>
<li>Fix exception handler parenthesis removal for Python 3.14+ (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23126">#23126</a>)</li>
<li>Fix f-string middle panic when parsing t-strings (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23232">#23232</a>)</li>
<li>Wrap <code>RUF020</code> target for multiline fixes (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23210">#23210</a>)</li>
<li>Wrap <code>UP007</code> target for multiline fixes (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23208">#23208</a>)</li>
<li>Fix missing diagnostics for last range suppression in file (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23242">#23242</a>)</li>
<li>[<code>pyupgrade</code>] Fix syntax error on string with newline
escape and comment (<code>UP037</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22968">#22968</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Use <code>ruff</code> instead of <code>Ruff</code> as the program
name in GitHub output format (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23240">#23240</a>)</li>
<li>[<code>PT006</code>] Fix syntax error when unpacking nested tuples
in <code>parametrize</code> fixes (<a
href="https://redirect.github.com/astral-sh/ruff/issues/22441">#22441</a>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/22464">#22464</a>)</li>
<li>[<code>airflow</code>] Catch deprecated attribute access from
context key for Airflow 3.0 (<code>AIR301</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22850">#22850</a>)</li>
<li>[<code>airflow</code>] Capture deprecated arguments and a decorator
(<code>AIR301</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23170">#23170</a>)</li>
<li>[<code>flake8-boolean-trap</code>] Add
<code>multiprocessing.Value</code> to excluded functions for
<code>FBT003</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23010">#23010</a>)</li>
<li>[<code>flake8-bugbear</code>] Add a secondary annotation showing the
previous occurrence (<code>B033</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22634">#22634</a>)</li>
<li>[<code>flake8-type-checking</code>] Add sub-diagnostic showing the
runtime use of an annotation (<code>TC004</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23091">#23091</a>)</li>
<li>[<code>isort</code>] Support configurable import section heading
comments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23151">#23151</a>)</li>
<li>[<code>ruff</code>] Improve the diagnostic for <code>RUF012</code>
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23202">#23202</a>)</li>
</ul>
<h3>Formatter</h3>
<!-- 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.15.1</h2>
<p>Released on 2026-02-12.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>airflow</code>] Add ruff rules to catch deprecated Airflow
imports for Airflow 3.1 (<code>AIR321</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22376">#22376</a>)</li>
<li>[<code>airflow</code>] Third positional parameter not named
<code>ti_key</code> should be flagged for
<code>BaseOperatorLink.get_link</code> (<code>AIR303</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22828">#22828</a>)</li>
<li>[<code>flake8-gettext</code>] Fix false negatives for plural
argument of <code>ngettext</code> (<code>INT001</code>,
<code>INT002</code>, <code>INT003</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/21078">#21078</a>)</li>
<li>[<code>pyflakes</code>] Fix infinite loop in preview fix for
<code>unused-import</code> (<code>F401</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23038">#23038</a>)</li>
<li>[<code>pygrep-hooks</code>] Detect non-existent mock methods in
standalone expressions (<code>PGH005</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22830">#22830</a>)</li>
<li>[<code>pylint</code>] Allow dunder submodules and improve diagnostic
range (<code>PLC2701</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22804">#22804</a>)</li>
<li>[<code>pyupgrade</code>] Improve diagnostic range for tuples
(<code>UP024</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23013">#23013</a>)</li>
<li>[<code>refurb</code>] Check subscripts in tuple do not use lambda
parameters in <code>reimplemented-operator</code> (<code>FURB118</code>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23079">#23079</a>)</li>
<li>[<code>ruff</code>] Detect mutable defaults in <code>field</code>
calls (<code>RUF008</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23046">#23046</a>)</li>
<li>[<code>ruff</code>] Ignore std <code>cmath.inf</code>
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23120">#23120</a>)</li>
<li>[<code>ruff</code>] New rule <code>float-equality-comparison</code>
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/20585">#20585</a>)</li>
<li>Don't format unlabeled Markdown code blocks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23106">#23106</a>)</li>
<li>Markdown formatting support in LSP (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23063">#23063</a>)</li>
<li>Support Quarto Markdown language markers (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22947">#22947</a>)</li>
<li>Support formatting <code>pycon</code> Markdown code blocks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23112">#23112</a>)</li>
<li>Use extension mapping to select Markdown code block language (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22934">#22934</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>Avoid false positive for undefined variables in <code>FAST001</code>
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23224">#23224</a>)</li>
<li>Avoid introducing syntax errors for <code>FAST003</code> autofix (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23227">#23227</a>)</li>
<li>Avoid suggesting <code>InitVar</code> for <code>__post_init__</code>
that references PEP 695 type parameters (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23226">#23226</a>)</li>
<li>Deduplicate type variables in generic functions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23225">#23225</a>)</li>
<li>Fix exception handler parenthesis removal for Python 3.14+ (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23126">#23126</a>)</li>
<li>Fix f-string middle panic when parsing t-strings (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23232">#23232</a>)</li>
<li>Wrap <code>RUF020</code> target for multiline fixes (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23210">#23210</a>)</li>
<li>Wrap <code>UP007</code> target for multiline fixes (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23208">#23208</a>)</li>
<li>Fix missing diagnostics for last range suppression in file (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23242">#23242</a>)</li>
<li>[<code>pyupgrade</code>] Fix syntax error on string with newline
escape and comment (<code>UP037</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22968">#22968</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Use <code>ruff</code> instead of <code>Ruff</code> as the program
name in GitHub output format (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23240">#23240</a>)</li>
<li>[<code>PT006</code>] Fix syntax error when unpacking nested tuples
in <code>parametrize</code> fixes (<a
href="https://redirect.github.com/astral-sh/ruff/issues/22441">#22441</a>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/22464">#22464</a>)</li>
<li>[<code>airflow</code>] Catch deprecated attribute access from
context key for Airflow 3.0 (<code>AIR301</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22850">#22850</a>)</li>
<li>[<code>airflow</code>] Capture deprecated arguments and a decorator
(<code>AIR301</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23170">#23170</a>)</li>
<li>[<code>flake8-boolean-trap</code>] Add
<code>multiprocessing.Value</code> to excluded functions for
<code>FBT003</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23010">#23010</a>)</li>
<li>[<code>flake8-bugbear</code>] Add a secondary annotation showing the
previous occurrence (<code>B033</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22634">#22634</a>)</li>
<li>[<code>flake8-type-checking</code>] Add sub-diagnostic showing the
runtime use of an annotation (<code>TC004</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23091">#23091</a>)</li>
<li>[<code>isort</code>] Support configurable import section heading
comments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23151">#23151</a>)</li>
<li>[<code>ruff</code>] Improve the diagnostic for <code>RUF012</code>
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23202">#23202</a>)</li>
</ul>
<h3>Formatter</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/ruff/commit/a2f11d239f91cf8daedb0764ec15fcfe29c5ae6d"><code>a2f11d2</code></a>
Prepare for 0.15.1 (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23253">#23253</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/d29628e9665baa17272aad489398eb72b70e60ff"><code>d29628e</code></a>
Remove docker-run-action (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23254">#23254</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/8a042667651d7b1cdfc1742478d2b29b04d91be0"><code>8a04266</code></a>
[ty] Allow discovering dependencies in system Python environments (<a
href="https://redirect.github.com/astral-sh/ruff/issues/22994">#22994</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/55d06c8879761c5500e9558502abc84cefcb7163"><code>55d06c8</code></a>
Ensure pending suppression diagnostics are reported (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23242">#23242</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/d056a9fa6dfb842f2c0d439bf7b1a8099e5734ea"><code>d056a9f</code></a>
[<code>isort</code>] support for configurable import section heading
comments (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23151">#23151</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/e22fa4f14d8fae550249e452d11bc53756df5c7a"><code>e22fa4f</code></a>
[ty] Fix method calls on subclasses of <code>Any</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23248">#23248</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/fa56c1550d723e458b91dc2405d5537d40401d5c"><code>fa56c15</code></a>
[ty] Fix bound method access on <code>None</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23246">#23246</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/4fd07d0e1cbbb4e4c3f5b4c1f04f2d8b3f4a2bf2"><code>4fd07d0</code></a>
Make range suppression test snapshot actually useful (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23251">#23251</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/8c63bced13b21d1952a56e6a096d9c2ec4af442f"><code>8c63bce</code></a>
[ty] Include conditional symbols (like <code>datetime.UTC</code>) in
auto-import in more...</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/46be94361b3b4c54be911eb88bfbd9666eb06a6d"><code>46be943</code></a>
Exclude WASM artifacts from GitHub releases (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23221">#23221</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/ruff/compare/0.14.13...0.15.1">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>
2026-02-17 01:30:58 -08:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
a181e0bb91 chore(deps): bump langchain-core from 1.2.7 to 1.2.11 in /libs/checkpoint-sqlite (#6828)
Bumps [langchain-core](https://github.com/langchain-ai/langchain) from
1.2.7 to 1.2.11.
<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.2.11</h2>
<p>Changes since langchain-core==1.2.10</p>
<p>release(core): 1.2.11 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35144">#35144</a>)
fix(openai): sanitize urls when counting tokens in images (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35143">#35143</a>)
chore(core): clean up docstring mismatch and redundant logic in
langchain-core (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35064">#35064</a>)
fix(core): replace bare except with Exception in tracer (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35138">#35138</a>)</p>
<h2>langchain-core==1.2.10</h2>
<p>Changes since langchain-core==1.2.9</p>
<p>release(core): 1.2.10 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35136">#35136</a>)
chore(deps): bump the langchain-deps group across 3 directories with 40
updates (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35129">#35129</a>)
chore(deps): bump the langchain-deps group across 3 directories with 11
updates (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35121">#35121</a>)
feat(core): add ContextOverflowError, raise in anthropic and openai (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35099">#35099</a>)
feat(model-profiles): add <code>text_inputs</code> and
<code>text_outputs</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35084">#35084</a>)
feat(core): count tokens from tool schemas in
<code>count_tokens_approximately</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35098">#35098</a>)
docs(core): add missing <code>name</code> docstring for
<code>RunnableSerializable</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35088">#35088</a>)</p>
<h2>langchain-core==1.2.9</h2>
<p>Changes since langchain-core==1.2.8</p>
<p>release(core): 1.2.9 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35025">#35025</a>)
fix(core): adjust cap when scaling approximate token counts (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35017">#35017</a>)
revert: precompile hex color regex pattern at module level (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35016">#35016</a>)
chore: add <code>make type</code> target (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35015">#35015</a>)
revert: &quot;chore: add typing target in <code>Makefile</code>&quot;
(<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35013">#35013</a>)
chore: add typing target in <code>Makefile</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35012">#35012</a>)
fix(core): apply cap when scaling approximate token counts (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35005">#35005</a>)
feat(core): allow scaling by reported usage when counting tokens
approximately (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34996">#34996</a>)
test(core): increase <code>delta_time</code> for flaky test (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34982">#34982</a>)
chore: enrich <code>pyproject.toml</code> files (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34980">#34980</a>)</p>
<h2>langchain-core==1.2.8</h2>
<p>Changes since langchain-core==1.2.7</p>
<p>release(core): 1.2.8 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34975">#34975</a>)
docs(core): add examples for <code>pretty_repr</code>,
<code>pretty_print</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34968">#34968</a>)
docs(core): use proper admonition for <code>get_buffer_string</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34967">#34967</a>)
docs: add usage examples to core classes (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34841">#34841</a>)
chore(core): fix docstring format (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34966">#34966</a>)
chore(deps): bump the uv group across 20 directories with 3 updates (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34941">#34941</a>)
docs: add example to create_message function docstring (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34851">#34851</a>)
docs(core): clarify <a
href="https://github.com/tool"><code>@​tool</code></a> decorator
argument and return type requirements (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34860">#34860</a>)
fix(core): fix nested mustache variable extraction and update docs (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34872">#34872</a>)
fix(core): allow base model annotations for empty model (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34932">#34932</a>)
chore: upgrade urllib3 to 2.6.3 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34940">#34940</a>)
fix(core): prevent crash in ParrotFakeChatModel when messages list is
empty (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34943">#34943</a>)
fix(core): google docstring parsing with no arguments/reserved arguments
(<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34861">#34861</a>)
test(core): add tests for approximate token counting with multimodal
messages (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34898">#34898</a>)</p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/langchain-ai/langchain/commit/524e1dab5e7c8229bd78be3c13ab38ac93a6216b"><code>524e1da</code></a>
release(core): 1.2.11 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35144">#35144</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/2b4b1dc29a833d4053deba4c2b77a3848c834565"><code>2b4b1dc</code></a>
fix(openai): sanitize urls when counting tokens in images (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35143">#35143</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/0493b276e0be31d4f48d9d0ba5fcbce7fdded38f"><code>0493b27</code></a>
fix(anthropic): support effort=&quot;max&quot; and remove beta headers
(<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35141">#35141</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/a5f22e7cb18a05ed057028797a7d0d79cd509b0d"><code>a5f22e7</code></a>
chore(core): clean up docstring mismatch and redundant logic in
langchain-cor...</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/97ee14c179f703473a6ec6ee24179ea756a5698f"><code>97ee14c</code></a>
fix(core): replace bare except with Exception in tracer (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35138">#35138</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/990e8076e1d61a0c8ced4d83607685bd71e23687"><code>990e807</code></a>
release(standard-tests): release 1.1.5 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35139">#35139</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/74dffca3d89effdb62da567d1ff6d160c9ad5354"><code>74dffca</code></a>
release(langchain): 1.2.10 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35137">#35137</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/f41e0493336698e9a3e25e6e238786dfc8af91ba"><code>f41e049</code></a>
release(core): 1.2.10 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35136">#35136</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/de05838fca46eb6c2f67064da3a59f5e84818e9a"><code>de05838</code></a>
chore(deps): bump the langchain-deps group across 3 directories with 40
updat...</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/d6e86aa748ae173857732ee1f7114a06ff8f4231"><code>d6e86aa</code></a>
chore(deps): bump the other-deps group across 3 directories with 12
updates (...</li>
<li>Additional commits viewable in <a
href="https://github.com/langchain-ai/langchain/compare/langchain-core==1.2.7...langchain-core==1.2.11">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=langchain-core&package-manager=uv&previous-version=1.2.7&new-version=1.2.11)](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-02-17 01:28:08 -08:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
b233201308 chore(deps): bump protobuf from 6.33.4 to 6.33.5 in /libs/langgraph (#6833)
Bumps [protobuf](https://github.com/protocolbuffers/protobuf) from
6.33.4 to 6.33.5.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/protocolbuffers/protobuf/releases">protobuf's
releases</a>.</em></p>
<blockquote>
<h2>Protocol Buffers v34.0-rc1</h2>
<h1>Announcements</h1>
<ul>
<li><strong>This version includes breaking changes to: C++, Objective-C,
PHP, Python.</strong></li>
<li>[Bazel] Remove deprecated ProtoInfo.transitive_imports. Use
equivalent transitive_sources instead (<a
href="https://github.com/protocolbuffers/protobuf/commit/0a5c2f6b633c1e5259f566cb42d30fe347b8aadb">https://github.com/protocolbuffers/protobuf/commit/0a5c2f6b633c1e5259f566cb42d30fe347b8aadb</a>)</li>
<li>[C++] Make generator headers private (<a
href="https://github.com/protocolbuffers/protobuf/commit/3a2af3510f0d454dbe3e4dc281674b61c4d20b9e">https://github.com/protocolbuffers/protobuf/commit/3a2af3510f0d454dbe3e4dc281674b61c4d20b9e</a>)</li>
<li>[C++] Add a debug check that the target of CopyFrom is not a
descendant of the source. (<a
href="https://github.com/protocolbuffers/protobuf/commit/7a7589823d2cfaaf7994b050e98d5d553bc9b1c1">https://github.com/protocolbuffers/protobuf/commit/7a7589823d2cfaaf7994b050e98d5d553bc9b1c1</a>)</li>
<li>[C++] Add [[nodiscard]] to many APIs. (<a
href="https://github.com/protocolbuffers/protobuf/commit/a70115f33f9af2c4b2202c800b84837e7fe0d738">https://github.com/protocolbuffers/protobuf/commit/a70115f33f9af2c4b2202c800b84837e7fe0d738</a>)</li>
<li>[C++] Make the arena-enabled constructors of
<code>RepeatedField</code>, <code>RepeatedPtrField</code>, and
<code>Map</code> private. (<a
href="https://github.com/protocolbuffers/protobuf/commit/ef890c3d0c79398c70e047fe5dd893f460ba2336">https://github.com/protocolbuffers/protobuf/commit/ef890c3d0c79398c70e047fe5dd893f460ba2336</a>)</li>
<li>[C++] Remove deprecated FieldDescriptor::label() in OSS. Use
is_repeated() or is_required() instead (<a
href="https://github.com/protocolbuffers/protobuf/commit/b76faa921fdd244f374c7be0bddd4050fc42c292">https://github.com/protocolbuffers/protobuf/commit/b76faa921fdd244f374c7be0bddd4050fc42c292</a>)</li>
<li>[C++] Removes proto2::util::MessageDifferencer::AddIgnoreCriteria
that takes a raw pointer as an argument in favor of the overload that
takes a unique_ptr. Remove macro
PROTOBUF_FUTURE_REMOVE_ADD_IGNORE_CRITERIA (<a
href="https://github.com/protocolbuffers/protobuf/commit/b115358c64127896fed88b8b5ef5d91d86d8cbae">https://github.com/protocolbuffers/protobuf/commit/b115358c64127896fed88b8b5ef5d91d86d8cbae</a>)</li>
<li>[C++] Remove deprecated FieldDescriptor::has_optional_keyword() in
OSS. Use is_repeated() or has_presence() instead (<a
href="https://github.com/protocolbuffers/protobuf/commit/68346ec9348e932664e58c3ecdcd1478f95233a8">https://github.com/protocolbuffers/protobuf/commit/68346ec9348e932664e58c3ecdcd1478f95233a8</a>)</li>
<li>[C++] Remove AddUnusedImportTrackFile() and
ClearUnusedImportTrackFiles(). Remove
PROTOBUF_FUTURE_RENAME_ADD_UNUSED_IMPORT (<a
href="https://github.com/protocolbuffers/protobuf/commit/837a2cd1d6c75402b2503ffe7cd8aeaf25868536">https://github.com/protocolbuffers/protobuf/commit/837a2cd1d6c75402b2503ffe7cd8aeaf25868536</a>)</li>
<li>[C++] Remove deprecated FieldDescriptor::is_optional() in OSS. Use
(!is_required() &amp;&amp; !is_repeated()) instead (<a
href="https://github.com/protocolbuffers/protobuf/commit/9dbc5d479a8e453921485d8d3de47fb3c005f1af">https://github.com/protocolbuffers/protobuf/commit/9dbc5d479a8e453921485d8d3de47fb3c005f1af</a>)</li>
<li>[C++] Remove deprecated UseDeprecatedLegacyJsonFieldConflicts() (<a
href="https://github.com/protocolbuffers/protobuf/commit/c301c2ca286327a21c50c0c4cd877afc9c655b00">https://github.com/protocolbuffers/protobuf/commit/c301c2ca286327a21c50c0c4cd877afc9c655b00</a>)</li>
<li>[C++] All entity names have length limit (2afb0dc)</li>
<li>[ObjC] Remove <code>generate_minimal_imports</code> generation
option warning (<a
href="https://github.com/protocolbuffers/protobuf/commit/45b1297fdaad5a9436d0e207422168c38dc45ac4">https://github.com/protocolbuffers/protobuf/commit/45b1297fdaad5a9436d0e207422168c38dc45ac4</a>)</li>
<li>[ObjC] Fix nullability annotations on some
<code>GPB*Dictionary</code> types. (<a
href="https://github.com/protocolbuffers/protobuf/commit/ea67d6d26a48478a567c404679e3bb99cf230d50">https://github.com/protocolbuffers/protobuf/commit/ea67d6d26a48478a567c404679e3bb99cf230d50</a>)</li>
<li>[ObjC] Remove <code>-[GPBFieldDescriptor optional]</code> (<a
href="https://github.com/protocolbuffers/protobuf/commit/3414dc151eb4dcbdb2ca952e2589993bf7af75c4">https://github.com/protocolbuffers/protobuf/commit/3414dc151eb4dcbdb2ca952e2589993bf7af75c4</a>)</li>
<li>[Other] Remove deprecated flag for enabling MSVC support (<a
href="https://github.com/protocolbuffers/protobuf/commit/97c979be6e0907e1051bee62584dac4594e73fa7">https://github.com/protocolbuffers/protobuf/commit/97c979be6e0907e1051bee62584dac4594e73fa7</a>)</li>
<li>[PHP] Remove deprecated PHP APIs (<a
href="https://github.com/protocolbuffers/protobuf/commit/9c45014099a4f7004fab6dd1278de2f4f2a393c5">https://github.com/protocolbuffers/protobuf/commit/9c45014099a4f7004fab6dd1278de2f4f2a393c5</a>)</li>
<li>[PHP] Remove deprecated PHP APIs FieldDescriptor getLabel, use
IsRepeated or isRequired instead. (<a
href="https://github.com/protocolbuffers/protobuf/commit/42081219920c6fad17ba6ddd1e28d111bcfb3345">https://github.com/protocolbuffers/protobuf/commit/42081219920c6fad17ba6ddd1e28d111bcfb3345</a>,
<a
href="https://github.com/protocolbuffers/protobuf/commit/cd76e675b14d00dda5623b30835d2bc7105fccc6">https://github.com/protocolbuffers/protobuf/commit/cd76e675b14d00dda5623b30835d2bc7105fccc6</a>,
<a
href="https://github.com/protocolbuffers/protobuf/commit/42081219920c6fad17ba6ddd1e28d111bcfb3345">https://github.com/protocolbuffers/protobuf/commit/42081219920c6fad17ba6ddd1e28d111bcfb3345</a>)</li>
<li>[PHP] Add PHP typehints for setters and remove redundant GPBUtil
checks (<a
href="https://redirect.github.com/protocolbuffers/protobuf/pull/25296">protocolbuffers/protobuf#25296</a>)
(<a
href="https://github.com/protocolbuffers/protobuf/commit/aee03b78929c02461a5f9d8e136a2a016359b0cd">https://github.com/protocolbuffers/protobuf/commit/aee03b78929c02461a5f9d8e136a2a016359b0cd</a>)</li>
<li>[PHP] support default values for editions/proto2 (<a
href="https://redirect.github.com/protocolbuffers/protobuf/pull/25161">protocolbuffers/protobuf#25161</a>)
(<a
href="https://github.com/protocolbuffers/protobuf/commit/b01099d56350551bae3da88b97bf3027274c9f17">https://github.com/protocolbuffers/protobuf/commit/b01099d56350551bae3da88b97bf3027274c9f17</a>)</li>
<li>[Python] Raise errors in OSS when assign bool to int/enum field in
Python Proto. (<a
href="https://github.com/protocolbuffers/protobuf/commit/5b116fe2f14f49dd0cc3b76089983717f211025c">https://github.com/protocolbuffers/protobuf/commit/5b116fe2f14f49dd0cc3b76089983717f211025c</a>)</li>
<li>[Python] Remove float_format/double_format from python proto
text_format (<a
href="https://github.com/protocolbuffers/protobuf/commit/e4854a186e0bfa867d5bfa5cd850608a948fd488">https://github.com/protocolbuffers/protobuf/commit/e4854a186e0bfa867d5bfa5cd850608a948fd488</a>)</li>
<li>[Python] Raise TypeError when convert non-timedelta to Duration, or
convert non-datetime to Timestamp in python proto. (Original code may
raise ArributeError) (<a
href="https://github.com/protocolbuffers/protobuf/commit/00aaca1b4d98954bc2933d7c8a5379ba6088124c">https://github.com/protocolbuffers/protobuf/commit/00aaca1b4d98954bc2933d7c8a5379ba6088124c</a>)</li>
<li>[Python] Remove float_precision from python proto json_format (<a
href="https://github.com/protocolbuffers/protobuf/commit/f027f1fcd52b9d080b7ee79f4024f53cf54e0dc5">https://github.com/protocolbuffers/protobuf/commit/f027f1fcd52b9d080b7ee79f4024f53cf54e0dc5</a>)</li>
<li>[Python] Remove deprecated FieldDescriptor::label() in OSS. Use
is_repeated() or is_required() instead (<a
href="https://github.com/protocolbuffers/protobuf/commit/b76faa921fdd244f374c7be0bddd4050fc42c292">https://github.com/protocolbuffers/protobuf/commit/b76faa921fdd244f374c7be0bddd4050fc42c292</a>)</li>
<li>[Python] Remove deprecated FieldDescriptor.label (<a
href="https://github.com/protocolbuffers/protobuf/commit/0a8ff55518ea5874478ad5b26515b31d186045a9">https://github.com/protocolbuffers/protobuf/commit/0a8ff55518ea5874478ad5b26515b31d186045a9</a>)</li>
<li>[Python] Remove deprecated UseDeprecatedLegacyJsonFieldConflicts()
(<a
href="https://github.com/protocolbuffers/protobuf/commit/c301c2ca286327a21c50c0c4cd877afc9c655b00">https://github.com/protocolbuffers/protobuf/commit/c301c2ca286327a21c50c0c4cd877afc9c655b00</a>)</li>
<li><a href="https://protobuf.dev/news/">Protobuf News</a> may include
additional announcements or pre-announcements for upcoming changes.</li>
<li><a href="https://protobuf.dev/support/migration/">Migration
Guide</a> may include additional guidance for breaking changes.</li>
</ul>
<h1>Bazel</h1>
<ul>
<li>Fix: cc_toolchain should prefer protoc when prebuilt flag is
flipped. (<a
href="https://redirect.github.com/protocolbuffers/protobuf/issues/25168">#25168</a>)
(<a
href="https://github.com/protocolbuffers/protobuf/commit/8c857c3a1c6a106b0a096f1c9fa504bfaca035a9">https://github.com/protocolbuffers/protobuf/commit/8c857c3a1c6a106b0a096f1c9fa504bfaca035a9</a>)</li>
<li>Breaking change: Remove deprecated ProtoInfo.transitive_imports. Use
equivalent transitive_sources instead (<a
href="https://github.com/protocolbuffers/protobuf/commit/0a5c2f6b633c1e5259f566cb42d30fe347b8aadb">https://github.com/protocolbuffers/protobuf/commit/0a5c2f6b633c1e5259f566cb42d30fe347b8aadb</a>)</li>
<li>Feat(bazel): wire up prebuilt protoc toolchain (<a
href="https://redirect.github.com/protocolbuffers/protobuf/issues/24115">#24115</a>)
(<a
href="https://github.com/protocolbuffers/protobuf/commit/cc23698b486e690ea2eb873cc7596a87c74a3ba6">https://github.com/protocolbuffers/protobuf/commit/cc23698b486e690ea2eb873cc7596a87c74a3ba6</a>)</li>
<li>Migrate <code>proto_descriptor_set</code> (<a
href="https://redirect.github.com/protocolbuffers/protobuf/issues/23369">#23369</a>)
(<a
href="https://github.com/protocolbuffers/protobuf/commit/8d4dfdd39a7a242a9ed631a6ab2192c57dd9b9c8">https://github.com/protocolbuffers/protobuf/commit/8d4dfdd39a7a242a9ed631a6ab2192c57dd9b9c8</a>)</li>
</ul>
<h1>Compiler</h1>
<ul>
<li>Ruby codegen: support generation of rbs files (<a
href="https://redirect.github.com/protocolbuffers/protobuf/issues/15633">#15633</a>)
(<a
href="https://github.com/protocolbuffers/protobuf/commit/6ebdf851ba78728f0aa145d38454ed9a316fb08d">https://github.com/protocolbuffers/protobuf/commit/6ebdf851ba78728f0aa145d38454ed9a316fb08d</a>)</li>
<li>Avoid collision name problems between a message named
<code>Xyz</code> and a direct sibling enum named <code>XyzView</code>
(<a
href="https://github.com/protocolbuffers/protobuf/commit/eba53e8f172b273d679759a72ce4250131ee3df1">https://github.com/protocolbuffers/protobuf/commit/eba53e8f172b273d679759a72ce4250131ee3df1</a>)</li>
<li>Generalizing and implementing ValidateFeatureSupport for both
Options and Features during proto parsing (<a
href="https://github.com/protocolbuffers/protobuf/commit/ed3c57114d8e2b47cca7697ddaa50c1b3762a6b0">https://github.com/protocolbuffers/protobuf/commit/ed3c57114d8e2b47cca7697ddaa50c1b3762a6b0</a>)</li>
<li>Fix a bug with custom features outside of the <code>pb</code>
package. (<a
href="https://github.com/protocolbuffers/protobuf/commit/872d3ce7a4da00d7dcec33ced20cfe45235935e8">https://github.com/protocolbuffers/protobuf/commit/872d3ce7a4da00d7dcec33ced20cfe45235935e8</a>)</li>
<li>Fix import option handling when include_imports isn't set. (<a
href="https://github.com/protocolbuffers/protobuf/commit/9ef9e80afd9bc8379d578fe67e5ab0738728c04e">https://github.com/protocolbuffers/protobuf/commit/9ef9e80afd9bc8379d578fe67e5ab0738728c04e</a>)</li>
<li>Fix a bug in STRICT check of namespaced enums to properly check for
'reserved 1 to max' (<a
href="https://github.com/protocolbuffers/protobuf/commit/1229d4adba24c0952ab85ce96bc7b7f8a1fe6d0f">https://github.com/protocolbuffers/protobuf/commit/1229d4adba24c0952ab85ce96bc7b7f8a1fe6d0f</a>)</li>
<li>Prevent accidental stripping of <code>debug_redact</code> options
via import option. (<a
href="https://github.com/protocolbuffers/protobuf/commit/f58b098bffa7ca4045ef7773b09151a6af5d0c28">https://github.com/protocolbuffers/protobuf/commit/f58b098bffa7ca4045ef7773b09151a6af5d0c28</a>)</li>
</ul>
<h1>C++</h1>
<ul>
<li>Add EnumerateEnumValues function. (<a
href="https://github.com/protocolbuffers/protobuf/commit/397d5d99db274b379d1384814074bf7df39d32f7">https://github.com/protocolbuffers/protobuf/commit/397d5d99db274b379d1384814074bf7df39d32f7</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/protocolbuffers/protobuf/commits">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=protobuf&package-manager=uv&previous-version=6.33.4&new-version=6.33.5)](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-02-17 01:27:42 -08:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
443cee2fb3 chore(deps): bump cryptography from 46.0.3 to 46.0.5 in /libs/langgraph (#6837)
Bumps [cryptography](https://github.com/pyca/cryptography) from 46.0.3
to 46.0.5.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst">cryptography's
changelog</a>.</em></p>
<blockquote>
<p>46.0.5 - 2026-02-10</p>
<pre><code>
* An attacker could create a malicious public key that reveals portions
of your
private key when using certain uncommon elliptic curves (binary curves).
This version now includes additional security checks to prevent this
attack.
This issue only affects binary elliptic curves, which are rarely used in
real-world applications. Credit to **XlabAI Team of Tencent Xuanwu Lab
and
Atuin Automated Vulnerability Discovery Engine** for reporting the
issue.
  **CVE-2026-26007**
* Support for ``SECT*`` binary elliptic curves is deprecated and will be
  removed in the next release.
<p>.. v46-0-4:</p>
<p>46.0.4 - 2026-01-27<br />
</code></pre></p>
<ul>
<li><code>Dropped support for win_arm64 wheels</code>_.</li>
<li>Updated Windows, macOS, and Linux wheels to be compiled with OpenSSL
3.5.5.</li>
</ul>
<p>.. _v46-0-3:</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/pyca/cryptography/commit/06e120e682cb200e3f7050c02f0bcdac90c4c6ad"><code>06e120e</code></a>
bump version for 46.0.5 release (<a
href="https://redirect.github.com/pyca/cryptography/issues/14289">#14289</a>)</li>
<li><a
href="https://github.com/pyca/cryptography/commit/0eebb9dbb6343d9bc1d91e5a2482ed4e054a6d8c"><code>0eebb9d</code></a>
EC check key on cofactor &gt; 1 (<a
href="https://redirect.github.com/pyca/cryptography/issues/14287">#14287</a>)</li>
<li><a
href="https://github.com/pyca/cryptography/commit/bedf6e186b814f69a3f54f51252c23a71d44ed2e"><code>bedf6e1</code></a>
fix openssl version on 46 branch (<a
href="https://redirect.github.com/pyca/cryptography/issues/14220">#14220</a>)</li>
<li><a
href="https://github.com/pyca/cryptography/commit/e6f44fc8e6391f05d719fb9d369692325b87a471"><code>e6f44fc</code></a>
bump for 46.0.4 and drop win arm64 due to CI issues (<a
href="https://redirect.github.com/pyca/cryptography/issues/14217">#14217</a>)</li>
<li>See full diff in <a
href="https://github.com/pyca/cryptography/compare/46.0.3...46.0.5">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=cryptography&package-manager=uv&previous-version=46.0.3&new-version=46.0.5)](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-02-17 01:27:17 -08:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
d280bca8da chore(deps): bump langchain-core from 1.2.10 to 1.2.11 in /libs/sdk-py (#6829)
Bumps [langchain-core](https://github.com/langchain-ai/langchain) from
1.2.10 to 1.2.11.
<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.2.11</h2>
<p>Changes since langchain-core==1.2.10</p>
<p>release(core): 1.2.11 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35144">#35144</a>)
fix(openai): sanitize urls when counting tokens in images (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35143">#35143</a>)
chore(core): clean up docstring mismatch and redundant logic in
langchain-core (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35064">#35064</a>)
fix(core): replace bare except with Exception in tracer (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35138">#35138</a>)</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/langchain-ai/langchain/commit/524e1dab5e7c8229bd78be3c13ab38ac93a6216b"><code>524e1da</code></a>
release(core): 1.2.11 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35144">#35144</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/2b4b1dc29a833d4053deba4c2b77a3848c834565"><code>2b4b1dc</code></a>
fix(openai): sanitize urls when counting tokens in images (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35143">#35143</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/0493b276e0be31d4f48d9d0ba5fcbce7fdded38f"><code>0493b27</code></a>
fix(anthropic): support effort=&quot;max&quot; and remove beta headers
(<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35141">#35141</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/a5f22e7cb18a05ed057028797a7d0d79cd509b0d"><code>a5f22e7</code></a>
chore(core): clean up docstring mismatch and redundant logic in
langchain-cor...</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/97ee14c179f703473a6ec6ee24179ea756a5698f"><code>97ee14c</code></a>
fix(core): replace bare except with Exception in tracer (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35138">#35138</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/990e8076e1d61a0c8ced4d83607685bd71e23687"><code>990e807</code></a>
release(standard-tests): release 1.1.5 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35139">#35139</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/74dffca3d89effdb62da567d1ff6d160c9ad5354"><code>74dffca</code></a>
release(langchain): 1.2.10 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35137">#35137</a>)</li>
<li>See full diff in <a
href="https://github.com/langchain-ai/langchain/compare/langchain-core==1.2.10...langchain-core==1.2.11">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=langchain-core&package-manager=uv&previous-version=1.2.10&new-version=1.2.11)](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-02-17 01:24:06 -08:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
3701fa4806 chore(deps): bump nbconvert from 7.16.6 to 7.17.0 in /libs/langgraph (#6832)
Bumps [nbconvert](https://github.com/jupyter/nbconvert) from 7.16.6 to
7.17.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/jupyter/nbconvert/releases">nbconvert's
releases</a>.</em></p>
<blockquote>
<h2>v7.17.0</h2>
<h2>7.17.0</h2>
<p>(<a
href="https://github.com/jupyter/nbconvert/compare/v7.16.6...c9ac1d1040459ed1ff9eb34e9918ce5a87cf9d71">Full
Changelog</a>)</p>
<h3>Enhancements made</h3>
<ul>
<li>Add support for arbitrary browser arguments <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2227">#2227</a>
(<a href="https://github.com/shreve"><code>@​shreve</code></a>, <a
href="https://github.com/Carreau"><code>@​Carreau</code></a>, <a
href="https://github.com/krassowski"><code>@​krassowski</code></a>)</li>
</ul>
<h3>Bugs fixed</h3>
<ul>
<li>Fix QtPNGExporter returning empty bytes on macOS <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2264">#2264</a>
(<a href="https://github.com/h3pdesign"><code>@​h3pdesign</code></a>, <a
href="https://github.com/Carreau"><code>@​Carreau</code></a>, <a
href="https://github.com/QuLogic"><code>@​QuLogic</code></a>)</li>
<li>Fix CVE-2025-53000: Secure Inkscape Windows path (registry first +
block CWD) <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2261">#2261</a>
(<a href="https://github.com/h3pdesign"><code>@​h3pdesign</code></a>, <a
href="https://github.com/krassowski"><code>@​krassowski</code></a>, <a
href="https://github.com/mberlanda"><code>@​mberlanda</code></a>, <a
href="https://github.com/minrk"><code>@​minrk</code></a>, <a
href="https://github.com/salmankadaya"><code>@​salmankadaya</code></a>,
<a
href="https://github.com/th3gowtham"><code>@​th3gowtham</code></a>)</li>
<li>Fix get_export_names and get_exporter default args <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2228">#2228</a>
(<a href="https://github.com/shreve"><code>@​shreve</code></a>, <a
href="https://github.com/krassowski"><code>@​krassowski</code></a>)</li>
<li>PyPA-Compliant Summary <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2226">#2226</a>
(<a
href="https://github.com/hackowitz-af"><code>@​hackowitz-af</code></a>,
<a href="https://github.com/Carreau"><code>@​Carreau</code></a>)</li>
</ul>
<h3>Maintenance and upkeep improvements</h3>
<ul>
<li>avoid cov environment on free-threaded Pythons <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2267">#2267</a>
(<a href="https://github.com/minrk"><code>@​minrk</code></a>)</li>
<li>update pre-commit, and fix all issues. <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2238">#2238</a>
(<a href="https://github.com/Carreau"><code>@​Carreau</code></a>)</li>
<li>Drop test on 3.9, test on 3.13, 3.14, 3.14t <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2237">#2237</a>
(<a href="https://github.com/Carreau"><code>@​Carreau</code></a>)</li>
<li>Bump the actions group across 1 directory with 2 updates <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2231">#2231</a>
(<a href="https://github.com/Carreau"><code>@​Carreau</code></a>, <a
href="https://github.com/krassowski"><code>@​krassowski</code></a>)</li>
<li>Replace <code>@flaky.flaky</code> decorate with pytest marker <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2229">#2229</a>
(<a href="https://github.com/mgorny"><code>@​mgorny</code></a>, <a
href="https://github.com/Carreau"><code>@​Carreau</code></a>)</li>
<li>update to mermaid 11.10.0 <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2224">#2224</a>
(<a href="https://github.com/bollwyvl"><code>@​bollwyvl</code></a>, <a
href="https://github.com/krassowski"><code>@​krassowski</code></a>)</li>
<li>Drop support for Python 3.8, fix the CI tests <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2221">#2221</a>
(<a href="https://github.com/shreve"><code>@​shreve</code></a>, <a
href="https://github.com/minrk"><code>@​minrk</code></a>)</li>
</ul>
<h3>Documentation improvements</h3>
<ul>
<li>Use <code>intersphinx_registry</code> <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2232">#2232</a>
(<a href="https://github.com/Carreau"><code>@​Carreau</code></a>, <a
href="https://github.com/krassowski"><code>@​krassowski</code></a>)</li>
</ul>
<h3>Contributors to this release</h3>
<p>The following people contributed discussions, new ideas, code and
documentation contributions, and review.
See <a
href="https://github-activity.readthedocs.io/en/latest/use/#how-does-this-tool-define-contributions-in-the-reports">our
definition of contributors</a>.</p>
<p>(<a
href="https://github.com/jupyter/nbconvert/graphs/contributors?from=2025-01-28&amp;to=2026-01-29&amp;type=c">GitHub
contributors page for this release</a>)</p>
<p><a href="https://github.com/bollwyvl"><code>@​bollwyvl</code></a> (<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Abollwyvl+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/Carreau"><code>@​Carreau</code></a> (<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3ACarreau+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/h3pdesign"><code>@​h3pdesign</code></a>
(<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Ah3pdesign+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a
href="https://github.com/hackowitz-af"><code>@​hackowitz-af</code></a>
(<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Ahackowitz-af+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/krassowski"><code>@​krassowski</code></a>
(<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Akrassowski+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/mberlanda"><code>@​mberlanda</code></a>
(<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Amberlanda+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/mgorny"><code>@​mgorny</code></a> (<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Amgorny+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/minrk"><code>@​minrk</code></a> (<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Aminrk+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/MSeal"><code>@​MSeal</code></a> (<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3AMSeal+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/QuLogic"><code>@​QuLogic</code></a> (<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3AQuLogic+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a
href="https://github.com/salmankadaya"><code>@​salmankadaya</code></a>
(<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Asalmankadaya+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/shreve"><code>@​shreve</code></a> (<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Ashreve+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/th3gowtham"><code>@​th3gowtham</code></a>
(<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Ath3gowtham+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)</p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/jupyter/nbconvert/blob/main/CHANGELOG.md">nbconvert's
changelog</a>.</em></p>
<blockquote>
<h2>7.17.0</h2>
<p>(<a
href="https://github.com/jupyter/nbconvert/compare/v7.16.6...c9ac1d1040459ed1ff9eb34e9918ce5a87cf9d71">Full
Changelog</a>)</p>
<h3>Enhancements made</h3>
<ul>
<li>Add support for arbitrary browser arguments <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2227">#2227</a>
(<a href="https://github.com/shreve"><code>@​shreve</code></a>, <a
href="https://github.com/Carreau"><code>@​Carreau</code></a>, <a
href="https://github.com/krassowski"><code>@​krassowski</code></a>)</li>
</ul>
<h3>Bugs fixed</h3>
<ul>
<li>Fix QtPNGExporter returning empty bytes on macOS <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2264">#2264</a>
(<a href="https://github.com/h3pdesign"><code>@​h3pdesign</code></a>, <a
href="https://github.com/Carreau"><code>@​Carreau</code></a>, <a
href="https://github.com/QuLogic"><code>@​QuLogic</code></a>)</li>
<li>Fix CVE-2025-53000: Secure Inkscape Windows path (registry first +
block CWD) <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2261">#2261</a>
(<a href="https://github.com/h3pdesign"><code>@​h3pdesign</code></a>, <a
href="https://github.com/krassowski"><code>@​krassowski</code></a>, <a
href="https://github.com/mberlanda"><code>@​mberlanda</code></a>, <a
href="https://github.com/minrk"><code>@​minrk</code></a>, <a
href="https://github.com/salmankadaya"><code>@​salmankadaya</code></a>,
<a
href="https://github.com/th3gowtham"><code>@​th3gowtham</code></a>)</li>
<li>Fix get_export_names and get_exporter default args <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2228">#2228</a>
(<a href="https://github.com/shreve"><code>@​shreve</code></a>, <a
href="https://github.com/krassowski"><code>@​krassowski</code></a>)</li>
<li>PyPA-Compliant Summary <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2226">#2226</a>
(<a
href="https://github.com/hackowitz-af"><code>@​hackowitz-af</code></a>,
<a href="https://github.com/Carreau"><code>@​Carreau</code></a>)</li>
</ul>
<h3>Maintenance and upkeep improvements</h3>
<ul>
<li>avoid cov environment on free-threaded Pythons <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2267">#2267</a>
(<a href="https://github.com/minrk"><code>@​minrk</code></a>)</li>
<li>update pre-commit, and fix all issues. <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2238">#2238</a>
(<a href="https://github.com/Carreau"><code>@​Carreau</code></a>)</li>
<li>Drop test on 3.9, test on 3.13, 3.14, 3.14t <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2237">#2237</a>
(<a href="https://github.com/Carreau"><code>@​Carreau</code></a>)</li>
<li>Bump the actions group across 1 directory with 2 updates <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2231">#2231</a>
(<a href="https://github.com/Carreau"><code>@​Carreau</code></a>, <a
href="https://github.com/krassowski"><code>@​krassowski</code></a>)</li>
<li>Replace <code>@flaky.flaky</code> decorate with pytest marker <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2229">#2229</a>
(<a href="https://github.com/mgorny"><code>@​mgorny</code></a>, <a
href="https://github.com/Carreau"><code>@​Carreau</code></a>)</li>
<li>update to mermaid 11.10.0 <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2224">#2224</a>
(<a href="https://github.com/bollwyvl"><code>@​bollwyvl</code></a>, <a
href="https://github.com/krassowski"><code>@​krassowski</code></a>)</li>
<li>Drop support for Python 3.8, fix the CI tests <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2221">#2221</a>
(<a href="https://github.com/shreve"><code>@​shreve</code></a>, <a
href="https://github.com/minrk"><code>@​minrk</code></a>)</li>
</ul>
<h3>Documentation improvements</h3>
<ul>
<li>Use <code>intersphinx_registry</code> <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2232">#2232</a>
(<a href="https://github.com/Carreau"><code>@​Carreau</code></a>, <a
href="https://github.com/krassowski"><code>@​krassowski</code></a>)</li>
</ul>
<h3>Contributors to this release</h3>
<p>The following people contributed discussions, new ideas, code and
documentation contributions, and review.
See <a
href="https://github-activity.readthedocs.io/en/latest/use/#how-does-this-tool-define-contributions-in-the-reports">our
definition of contributors</a>.</p>
<p>(<a
href="https://github.com/jupyter/nbconvert/graphs/contributors?from=2025-01-28&amp;to=2026-01-29&amp;type=c">GitHub
contributors page for this release</a>)</p>
<p><a href="https://github.com/bollwyvl"><code>@​bollwyvl</code></a> (<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Abollwyvl+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/Carreau"><code>@​Carreau</code></a> (<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3ACarreau+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/h3pdesign"><code>@​h3pdesign</code></a>
(<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Ah3pdesign+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a
href="https://github.com/hackowitz-af"><code>@​hackowitz-af</code></a>
(<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Ahackowitz-af+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/krassowski"><code>@​krassowski</code></a>
(<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Akrassowski+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/mberlanda"><code>@​mberlanda</code></a>
(<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Amberlanda+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/mgorny"><code>@​mgorny</code></a> (<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Amgorny+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/minrk"><code>@​minrk</code></a> (<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Aminrk+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/MSeal"><code>@​MSeal</code></a> (<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3AMSeal+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/QuLogic"><code>@​QuLogic</code></a> (<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3AQuLogic+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a
href="https://github.com/salmankadaya"><code>@​salmankadaya</code></a>
(<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Asalmankadaya+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/shreve"><code>@​shreve</code></a> (<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Ashreve+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/th3gowtham"><code>@​th3gowtham</code></a>
(<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Ath3gowtham+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)</p>
<!-- raw HTML omitted -->
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/jupyter/nbconvert/commit/21b35d85b46f5ff0956d3d088a52b9bef00e8196"><code>21b35d8</code></a>
Publish 7.17.0</li>
<li><a
href="https://github.com/jupyter/nbconvert/commit/c9ac1d1040459ed1ff9eb34e9918ce5a87cf9d71"><code>c9ac1d1</code></a>
Fix CVE-2025-53000: Secure Inkscape Windows path (registry first + block
CWD)...</li>
<li><a
href="https://github.com/jupyter/nbconvert/commit/b13276d80ae6fadbfda981304810e26f421c4ced"><code>b13276d</code></a>
avoid cov environment on free-threaded Pythons (<a
href="https://redirect.github.com/jupyter/nbconvert/issues/2267">#2267</a>)</li>
<li><a
href="https://github.com/jupyter/nbconvert/commit/7c7055fe833fe9832e6f9a64fa5f67d66692c8d6"><code>7c7055f</code></a>
[pre-commit.ci] auto fixes from pre-commit.com hooks</li>
<li><a
href="https://github.com/jupyter/nbconvert/commit/74f3ddd37ef4b7ffb5eee9acbf52062217c15852"><code>74f3ddd</code></a>
Fix QtPNGExporter returning empty bytes on macOS</li>
<li><a
href="https://github.com/jupyter/nbconvert/commit/216550b2aae4c329f4dab597a96ae7cac30de79a"><code>216550b</code></a>
fix links</li>
<li><a
href="https://github.com/jupyter/nbconvert/commit/39777ac5716350e994171d025a7369c58b0afc8c"><code>39777ac</code></a>
try to comment fialing test</li>
<li><a
href="https://github.com/jupyter/nbconvert/commit/7b591ca526f2598dbae3256a53765659c3edcf14"><code>7b591ca</code></a>
ruff-check</li>
<li><a
href="https://github.com/jupyter/nbconvert/commit/6ec7638a3dc7a0bc2c533c116202d7f9b07ce9d9"><code>6ec7638</code></a>
parent</li>
<li><a
href="https://github.com/jupyter/nbconvert/commit/59414b36f94e318d4207e8af863167047d936c19"><code>59414b3</code></a>
fix mypy</li>
<li>Additional commits viewable in <a
href="https://github.com/jupyter/nbconvert/compare/v7.16.6...v7.17.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=nbconvert&package-manager=uv&previous-version=7.16.6&new-version=7.17.0)](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-02-17 01:23:26 -08:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
72be9b23ee chore(deps): bump the all-dependencies group in /libs/checkpoint with 4 updates (#6812)
Bumps the all-dependencies group in /libs/checkpoint with 4 updates:
[langchain-core](https://github.com/langchain-ai/langchain),
[ormsgpack](https://github.com/ormsgpack/ormsgpack),
[redis](https://github.com/redis/redis-py) and
[ruff](https://github.com/astral-sh/ruff).

Updates `langchain-core` from 1.2.7 to 1.2.12
<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.2.12</h2>
<p>Changes since langchain-core==1.2.11</p>
<p>release(core): 1.2.12 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35192">#35192</a>)
fix(core): fix setting <code>ChatGeneration.text</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35191">#35191</a>)</p>
<h2>langchain-core==1.2.11</h2>
<p>Changes since langchain-core==1.2.10</p>
<p>release(core): 1.2.11 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35144">#35144</a>)
fix(openai): sanitize urls when counting tokens in images (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35143">#35143</a>)
chore(core): clean up docstring mismatch and redundant logic in
langchain-core (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35064">#35064</a>)
fix(core): replace bare except with Exception in tracer (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35138">#35138</a>)</p>
<h2>langchain-core==1.2.10</h2>
<p>Changes since langchain-core==1.2.9</p>
<p>release(core): 1.2.10 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35136">#35136</a>)
chore(deps): bump the langchain-deps group across 3 directories with 40
updates (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35129">#35129</a>)
chore(deps): bump the langchain-deps group across 3 directories with 11
updates (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35121">#35121</a>)
feat(core): add ContextOverflowError, raise in anthropic and openai (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35099">#35099</a>)
feat(model-profiles): add <code>text_inputs</code> and
<code>text_outputs</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35084">#35084</a>)
feat(core): count tokens from tool schemas in
<code>count_tokens_approximately</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35098">#35098</a>)
docs(core): add missing <code>name</code> docstring for
<code>RunnableSerializable</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35088">#35088</a>)</p>
<h2>langchain-core==1.2.9</h2>
<p>Changes since langchain-core==1.2.8</p>
<p>release(core): 1.2.9 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35025">#35025</a>)
fix(core): adjust cap when scaling approximate token counts (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35017">#35017</a>)
revert: precompile hex color regex pattern at module level (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35016">#35016</a>)
chore: add <code>make type</code> target (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35015">#35015</a>)
revert: &quot;chore: add typing target in <code>Makefile</code>&quot;
(<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35013">#35013</a>)
chore: add typing target in <code>Makefile</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35012">#35012</a>)
fix(core): apply cap when scaling approximate token counts (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35005">#35005</a>)
feat(core): allow scaling by reported usage when counting tokens
approximately (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34996">#34996</a>)
test(core): increase <code>delta_time</code> for flaky test (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34982">#34982</a>)
chore: enrich <code>pyproject.toml</code> files (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34980">#34980</a>)</p>
<h2>langchain-core==1.2.8</h2>
<p>Changes since langchain-core==1.2.7</p>
<p>release(core): 1.2.8 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34975">#34975</a>)
docs(core): add examples for <code>pretty_repr</code>,
<code>pretty_print</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34968">#34968</a>)
docs(core): use proper admonition for <code>get_buffer_string</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34967">#34967</a>)
docs: add usage examples to core classes (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34841">#34841</a>)
chore(core): fix docstring format (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34966">#34966</a>)
chore(deps): bump the uv group across 20 directories with 3 updates (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34941">#34941</a>)
docs: add example to create_message function docstring (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34851">#34851</a>)
docs(core): clarify <a
href="https://github.com/tool"><code>@​tool</code></a> decorator
argument and return type requirements (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/34860">#34860</a>)</p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/langchain-ai/langchain/commit/b06716fb879f0d656ce4d1dad4a9710a61e8ec1e"><code>b06716f</code></a>
release(core): 1.2.12 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35192">#35192</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/16cabfa212782d03b00e08658fb3e74160a1dd45"><code>16cabfa</code></a>
fix(core): fix setting <code>ChatGeneration.text</code> (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35191">#35191</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/8f859bd91f122b532689db199f69a6464a1bf7ef"><code>8f859bd</code></a>
release(huggingface): 1.2.1 (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35182">#35182</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/19ddd42891514aba6d2c92cd32a915e7bb4b7b31"><code>19ddd42</code></a>
fix(ollama): raise error when clients are not initialized (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35185">#35185</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/a50d86c353bdf611bd0b908d5fc3d737086dba98"><code>a50d86c</code></a>
docs(langchain-classic): clarify MultiVectorRetriever usage (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35053">#35053</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/f89e30eb131d48c5354dd98c068a229b4c585f2d"><code>f89e30e</code></a>
chore(huggingface): version bump for huggingface-hub and transformers
deps (#...</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/6ac12b330a5c4912c37aa3bd888bc086d5d387f7"><code>6ac12b3</code></a>
chore: bump pillow from 11.3.0 to 12.1.1 in /libs/partners/openai (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35177">#35177</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/d41dedae978dfd4e4ee82d57fc1f0c530d827b90"><code>d41deda</code></a>
fix(langchain-classic): validate ensemble retriever weights (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35078">#35078</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/9d0bd8376cdd19dc19ac34d15a34dabe94361d8b"><code>9d0bd83</code></a>
chore: bump pillow from 11.3.0 to 12.1.1 in /libs/partners/perplexity
(<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35176">#35176</a>)</li>
<li><a
href="https://github.com/langchain-ai/langchain/commit/f22f5d5d673d2db5dc8a68991cdc063664c6f96b"><code>f22f5d5</code></a>
chore(deps): bump pillow from 11.3.0 to 12.1.1 in /libs/langchain (<a
href="https://redirect.github.com/langchain-ai/langchain/issues/35175">#35175</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/langchain-ai/langchain/compare/langchain-core==1.2.7...langchain-core==1.2.12">compare
view</a></li>
</ul>
</details>
<br />

Updates `ormsgpack` from 1.12.1 to 1.12.2
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/ormsgpack/ormsgpack/releases">ormsgpack's
releases</a>.</em></p>
<blockquote>
<h2>1.12.2</h2>
<p>Changed</p>
<ul>
<li>Add Python 3.14 free-threaded Windows x86_64 wheel</li>
<li>Improve serialization performance</li>
<li>Update dependencies</li>
</ul>
<p>Fixed</p>
<ul>
<li>Fix <code>unpackb</code> crash on Windows with Python 3.14
free-threaded and
on Linux s390x (<a
href="https://redirect.github.com/ormsgpack/ormsgpack/issues/499">#499</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/ormsgpack/ormsgpack/blob/master/docs/changelog.rst">ormsgpack's
changelog</a>.</em></p>
<blockquote>
<h2>1.12.2 - 2026-01-18</h2>
<p>Changed</p>
<pre><code>
- Add Python 3.14 free-threaded Windows x86_64 wheel
- Improve serialization performance
- Update dependencies
<p>Fixed</p>
<pre><code>
- Fix ``unpackb`` crash on Windows with Python 3.14 free-threaded and
  on Linux s390x (:issue:`499`)
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;/details&gt;
&lt;details&gt;
&lt;summary&gt;Commits&lt;/summary&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/ormsgpack/ormsgpack/commit/9645772ab1e19420fa509197a95fb40fcc92fe9f&quot;&gt;&lt;code&gt;9645772&lt;/code&gt;&lt;/a&gt;
1.12.2&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/ormsgpack/ormsgpack/commit/cfc189fe17ea41cce9baffff0c55da105fce0d2e&quot;&gt;&lt;code&gt;cfc189f&lt;/code&gt;&lt;/a&gt;
Update Changelog&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/ormsgpack/ormsgpack/commit/cf8c3bb3988e063f628e62e3ead0de24c3a95381&quot;&gt;&lt;code&gt;cf8c3bb&lt;/code&gt;&lt;/a&gt;
Lint docs&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/ormsgpack/ormsgpack/commit/cc6e45a07d5cb13098da5752cc552deed525c8f6&quot;&gt;&lt;code&gt;cc6e45a&lt;/code&gt;&lt;/a&gt;
Update development dependencies&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/ormsgpack/ormsgpack/commit/42f501fc0fdbb86601bcecafd77e0096e41b266f&quot;&gt;&lt;code&gt;42f501f&lt;/code&gt;&lt;/a&gt;
Update dependencies&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/ormsgpack/ormsgpack/commit/6e621b8abcfa48cd9b4248bb5889baf3fdca06d3&quot;&gt;&lt;code&gt;6e621b8&lt;/code&gt;&lt;/a&gt;
Update repository url&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/ormsgpack/ormsgpack/commit/079c7fcf9b96d5c869af106c61d156f06bd5f6cd&quot;&gt;&lt;code&gt;079c7fc&lt;/code&gt;&lt;/a&gt;
Bump urllib3 from 2.6.0 to 2.6.3&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/ormsgpack/ormsgpack/commit/4bb944cf066fca788024ebd3614164627daeac33&quot;&gt;&lt;code&gt;4bb944c&lt;/code&gt;&lt;/a&gt;
Bump ruff from 0.14.11 to 0.14.12 in the uv group&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/ormsgpack/ormsgpack/commit/2f447c2475c60f0e966428825229f456734a35dc&quot;&gt;&lt;code&gt;2f447c2&lt;/code&gt;&lt;/a&gt;
Trigger workflows on merge group events&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/ormsgpack/ormsgpack/commit/2acc85d4437bcf6baa3a4f16fe333e46c97d7a66&quot;&gt;&lt;code&gt;2acc85d&lt;/code&gt;&lt;/a&gt;
Bump chrono from 0.4.42 to 0.4.43&lt;/li&gt;
&lt;li&gt;Additional commits viewable in &lt;a
href=&quot;https://github.com/ormsgpack/ormsgpack/compare/1.12.1...1.12.2&quot;&gt;compare
view&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;

&lt;br /&gt;
</code></pre>

Updates `redis` from 7.1.0 to 7.1.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/redis/redis-py/releases">redis's
releases</a>.</em></p>
<blockquote>
<h2>7.1.1</h2>
<h1>Changes</h1>
<h2>🧪 Experimental Features</h2>
<ul>
<li>Added initial health check policies, refactored add_database method
(<a
href="https://redirect.github.com/redis/redis-py/issues/3906">#3906</a>)</li>
</ul>
<h2>🧰 Maintenance</h2>
<ul>
<li>Disabled SCH in MultiDBClient underlying clients by default (<a
href="https://redirect.github.com/redis/redis-py/issues/3938">#3938</a>)</li>
<li>Added logging for MultiDBClients (<a
href="https://redirect.github.com/redis/redis-py/issues/3865">#3865</a>
<a
href="https://redirect.github.com/redis/redis-py/issues/3896">#3896</a>)</li>
</ul>
<p>We'd like to thank all the contributors who worked on this release!
<a
href="https://github.com/vladvildanov"><code>@​vladvildanov</code></a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/redis/redis-py/commit/7351a1e2d68f386ce6079e274df6bf2ae1406188"><code>7351a1e</code></a>
Updating lib version to 7.1.1</li>
<li><a
href="https://github.com/redis/redis-py/commit/b81c856c6b9f965cc5e4bb5fdcb2d3f323687357"><code>b81c856</code></a>
Disabled SCH in MultiDBClient underlying clients (<a
href="https://redirect.github.com/redis/redis-py/issues/3938">#3938</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/0438784ff41c0f14c6dd78682b9a8d9149a7b33b"><code>0438784</code></a>
Added initial health check policies, refactored add_database method (<a
href="https://redirect.github.com/redis/redis-py/issues/3906">#3906</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/76befb443c583815cc99100a58ef943096f27b50"><code>76befb4</code></a>
Added logging for MultiDBClients (<a
href="https://redirect.github.com/redis/redis-py/issues/3896">#3896</a>)</li>
<li><a
href="https://github.com/redis/redis-py/commit/faee0fbbafd1ab4ad7f5402385f71660c5601948"><code>faee0fb</code></a>
Remove high-severity exception logging (<a
href="https://redirect.github.com/redis/redis-py/issues/3865">#3865</a>)</li>
<li>See full diff in <a
href="https://github.com/redis/redis-py/compare/v7.1.0...v7.1.1">compare
view</a></li>
</ul>
</details>
<br />

Updates `ruff` from 0.14.13 to 0.15.1
<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.15.1</h2>
<h2>Release Notes</h2>
<p>Released on 2026-02-12.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>airflow</code>] Add ruff rules to catch deprecated Airflow
imports for Airflow 3.1 (<code>AIR321</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22376">#22376</a>)</li>
<li>[<code>airflow</code>] Third positional parameter not named
<code>ti_key</code> should be flagged for
<code>BaseOperatorLink.get_link</code> (<code>AIR303</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22828">#22828</a>)</li>
<li>[<code>flake8-gettext</code>] Fix false negatives for plural
argument of <code>ngettext</code> (<code>INT001</code>,
<code>INT002</code>, <code>INT003</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/21078">#21078</a>)</li>
<li>[<code>pyflakes</code>] Fix infinite loop in preview fix for
<code>unused-import</code> (<code>F401</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23038">#23038</a>)</li>
<li>[<code>pygrep-hooks</code>] Detect non-existent mock methods in
standalone expressions (<code>PGH005</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22830">#22830</a>)</li>
<li>[<code>pylint</code>] Allow dunder submodules and improve diagnostic
range (<code>PLC2701</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22804">#22804</a>)</li>
<li>[<code>pyupgrade</code>] Improve diagnostic range for tuples
(<code>UP024</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23013">#23013</a>)</li>
<li>[<code>refurb</code>] Check subscripts in tuple do not use lambda
parameters in <code>reimplemented-operator</code> (<code>FURB118</code>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23079">#23079</a>)</li>
<li>[<code>ruff</code>] Detect mutable defaults in <code>field</code>
calls (<code>RUF008</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23046">#23046</a>)</li>
<li>[<code>ruff</code>] Ignore std <code>cmath.inf</code>
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23120">#23120</a>)</li>
<li>[<code>ruff</code>] New rule <code>float-equality-comparison</code>
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/20585">#20585</a>)</li>
<li>Don't format unlabeled Markdown code blocks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23106">#23106</a>)</li>
<li>Markdown formatting support in LSP (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23063">#23063</a>)</li>
<li>Support Quarto Markdown language markers (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22947">#22947</a>)</li>
<li>Support formatting <code>pycon</code> Markdown code blocks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23112">#23112</a>)</li>
<li>Use extension mapping to select Markdown code block language (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22934">#22934</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>Avoid false positive for undefined variables in <code>FAST001</code>
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23224">#23224</a>)</li>
<li>Avoid introducing syntax errors for <code>FAST003</code> autofix (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23227">#23227</a>)</li>
<li>Avoid suggesting <code>InitVar</code> for <code>__post_init__</code>
that references PEP 695 type parameters (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23226">#23226</a>)</li>
<li>Deduplicate type variables in generic functions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23225">#23225</a>)</li>
<li>Fix exception handler parenthesis removal for Python 3.14+ (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23126">#23126</a>)</li>
<li>Fix f-string middle panic when parsing t-strings (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23232">#23232</a>)</li>
<li>Wrap <code>RUF020</code> target for multiline fixes (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23210">#23210</a>)</li>
<li>Wrap <code>UP007</code> target for multiline fixes (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23208">#23208</a>)</li>
<li>Fix missing diagnostics for last range suppression in file (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23242">#23242</a>)</li>
<li>[<code>pyupgrade</code>] Fix syntax error on string with newline
escape and comment (<code>UP037</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22968">#22968</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Use <code>ruff</code> instead of <code>Ruff</code> as the program
name in GitHub output format (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23240">#23240</a>)</li>
<li>[<code>PT006</code>] Fix syntax error when unpacking nested tuples
in <code>parametrize</code> fixes (<a
href="https://redirect.github.com/astral-sh/ruff/issues/22441">#22441</a>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/22464">#22464</a>)</li>
<li>[<code>airflow</code>] Catch deprecated attribute access from
context key for Airflow 3.0 (<code>AIR301</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22850">#22850</a>)</li>
<li>[<code>airflow</code>] Capture deprecated arguments and a decorator
(<code>AIR301</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23170">#23170</a>)</li>
<li>[<code>flake8-boolean-trap</code>] Add
<code>multiprocessing.Value</code> to excluded functions for
<code>FBT003</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23010">#23010</a>)</li>
<li>[<code>flake8-bugbear</code>] Add a secondary annotation showing the
previous occurrence (<code>B033</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22634">#22634</a>)</li>
<li>[<code>flake8-type-checking</code>] Add sub-diagnostic showing the
runtime use of an annotation (<code>TC004</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23091">#23091</a>)</li>
<li>[<code>isort</code>] Support configurable import section heading
comments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23151">#23151</a>)</li>
<li>[<code>ruff</code>] Improve the diagnostic for <code>RUF012</code>
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23202">#23202</a>)</li>
</ul>
<h3>Formatter</h3>
<!-- 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.15.1</h2>
<p>Released on 2026-02-12.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>airflow</code>] Add ruff rules to catch deprecated Airflow
imports for Airflow 3.1 (<code>AIR321</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22376">#22376</a>)</li>
<li>[<code>airflow</code>] Third positional parameter not named
<code>ti_key</code> should be flagged for
<code>BaseOperatorLink.get_link</code> (<code>AIR303</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22828">#22828</a>)</li>
<li>[<code>flake8-gettext</code>] Fix false negatives for plural
argument of <code>ngettext</code> (<code>INT001</code>,
<code>INT002</code>, <code>INT003</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/21078">#21078</a>)</li>
<li>[<code>pyflakes</code>] Fix infinite loop in preview fix for
<code>unused-import</code> (<code>F401</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23038">#23038</a>)</li>
<li>[<code>pygrep-hooks</code>] Detect non-existent mock methods in
standalone expressions (<code>PGH005</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22830">#22830</a>)</li>
<li>[<code>pylint</code>] Allow dunder submodules and improve diagnostic
range (<code>PLC2701</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22804">#22804</a>)</li>
<li>[<code>pyupgrade</code>] Improve diagnostic range for tuples
(<code>UP024</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23013">#23013</a>)</li>
<li>[<code>refurb</code>] Check subscripts in tuple do not use lambda
parameters in <code>reimplemented-operator</code> (<code>FURB118</code>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23079">#23079</a>)</li>
<li>[<code>ruff</code>] Detect mutable defaults in <code>field</code>
calls (<code>RUF008</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23046">#23046</a>)</li>
<li>[<code>ruff</code>] Ignore std <code>cmath.inf</code>
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23120">#23120</a>)</li>
<li>[<code>ruff</code>] New rule <code>float-equality-comparison</code>
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/20585">#20585</a>)</li>
<li>Don't format unlabeled Markdown code blocks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23106">#23106</a>)</li>
<li>Markdown formatting support in LSP (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23063">#23063</a>)</li>
<li>Support Quarto Markdown language markers (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22947">#22947</a>)</li>
<li>Support formatting <code>pycon</code> Markdown code blocks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23112">#23112</a>)</li>
<li>Use extension mapping to select Markdown code block language (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22934">#22934</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>Avoid false positive for undefined variables in <code>FAST001</code>
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23224">#23224</a>)</li>
<li>Avoid introducing syntax errors for <code>FAST003</code> autofix (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23227">#23227</a>)</li>
<li>Avoid suggesting <code>InitVar</code> for <code>__post_init__</code>
that references PEP 695 type parameters (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23226">#23226</a>)</li>
<li>Deduplicate type variables in generic functions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23225">#23225</a>)</li>
<li>Fix exception handler parenthesis removal for Python 3.14+ (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23126">#23126</a>)</li>
<li>Fix f-string middle panic when parsing t-strings (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23232">#23232</a>)</li>
<li>Wrap <code>RUF020</code> target for multiline fixes (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23210">#23210</a>)</li>
<li>Wrap <code>UP007</code> target for multiline fixes (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23208">#23208</a>)</li>
<li>Fix missing diagnostics for last range suppression in file (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23242">#23242</a>)</li>
<li>[<code>pyupgrade</code>] Fix syntax error on string with newline
escape and comment (<code>UP037</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22968">#22968</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Use <code>ruff</code> instead of <code>Ruff</code> as the program
name in GitHub output format (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23240">#23240</a>)</li>
<li>[<code>PT006</code>] Fix syntax error when unpacking nested tuples
in <code>parametrize</code> fixes (<a
href="https://redirect.github.com/astral-sh/ruff/issues/22441">#22441</a>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/22464">#22464</a>)</li>
<li>[<code>airflow</code>] Catch deprecated attribute access from
context key for Airflow 3.0 (<code>AIR301</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22850">#22850</a>)</li>
<li>[<code>airflow</code>] Capture deprecated arguments and a decorator
(<code>AIR301</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23170">#23170</a>)</li>
<li>[<code>flake8-boolean-trap</code>] Add
<code>multiprocessing.Value</code> to excluded functions for
<code>FBT003</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23010">#23010</a>)</li>
<li>[<code>flake8-bugbear</code>] Add a secondary annotation showing the
previous occurrence (<code>B033</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22634">#22634</a>)</li>
<li>[<code>flake8-type-checking</code>] Add sub-diagnostic showing the
runtime use of an annotation (<code>TC004</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23091">#23091</a>)</li>
<li>[<code>isort</code>] Support configurable import section heading
comments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23151">#23151</a>)</li>
<li>[<code>ruff</code>] Improve the diagnostic for <code>RUF012</code>
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23202">#23202</a>)</li>
</ul>
<h3>Formatter</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/ruff/commit/a2f11d239f91cf8daedb0764ec15fcfe29c5ae6d"><code>a2f11d2</code></a>
Prepare for 0.15.1 (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23253">#23253</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/d29628e9665baa17272aad489398eb72b70e60ff"><code>d29628e</code></a>
Remove docker-run-action (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23254">#23254</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/8a042667651d7b1cdfc1742478d2b29b04d91be0"><code>8a04266</code></a>
[ty] Allow discovering dependencies in system Python environments (<a
href="https://redirect.github.com/astral-sh/ruff/issues/22994">#22994</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/55d06c8879761c5500e9558502abc84cefcb7163"><code>55d06c8</code></a>
Ensure pending suppression diagnostics are reported (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23242">#23242</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/d056a9fa6dfb842f2c0d439bf7b1a8099e5734ea"><code>d056a9f</code></a>
[<code>isort</code>] support for configurable import section heading
comments (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23151">#23151</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/e22fa4f14d8fae550249e452d11bc53756df5c7a"><code>e22fa4f</code></a>
[ty] Fix method calls on subclasses of <code>Any</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23248">#23248</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/fa56c1550d723e458b91dc2405d5537d40401d5c"><code>fa56c15</code></a>
[ty] Fix bound method access on <code>None</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23246">#23246</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/4fd07d0e1cbbb4e4c3f5b4c1f04f2d8b3f4a2bf2"><code>4fd07d0</code></a>
Make range suppression test snapshot actually useful (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23251">#23251</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/8c63bced13b21d1952a56e6a096d9c2ec4af442f"><code>8c63bce</code></a>
[ty] Include conditional symbols (like <code>datetime.UTC</code>) in
auto-import in more...</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/46be94361b3b4c54be911eb88bfbd9666eb06a6d"><code>46be943</code></a>
Exclude WASM artifacts from GitHub releases (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23221">#23221</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/ruff/compare/0.14.13...0.15.1">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>
2026-02-17 01:02:33 -08:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
52bbd34673 chore(deps): bump the all-dependencies group in /libs/checkpoint-postgres with 2 updates (#6808)
Bumps the all-dependencies group in /libs/checkpoint-postgres with 2
updates: [orjson](https://github.com/ijl/orjson) and
[ruff](https://github.com/astral-sh/ruff).

Updates `orjson` from 3.11.5 to 3.11.7
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/ijl/orjson/releases">orjson's
releases</a>.</em></p>
<blockquote>
<h2>3.11.7</h2>
<h3>Changed</h3>
<ul>
<li>Use a faster library to serialize <code>float</code>. Users with
byte-exact regression
tests should note positive exponents are now written using a
<code>+</code>, e.g.,
<code>1.2e+30</code> instead of <code>1.2e30</code>. Both formats are
spec-compliant.</li>
<li>ABI compatibility with CPython 3.15 alpha 5 free-threading.</li>
</ul>
<h2>3.11.6</h2>
<h3>Changed</h3>
<ul>
<li>orjson now includes code licensed under the Mozilla Public License
2.0 (MPL-2.0).</li>
<li>Drop support for Python 3.9.</li>
<li>ABI compatibility with CPython 3.15 alpha 5.</li>
<li>Build now depends on Rust 1.89 or later instead of 1.85.</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>Fix sporadic crash serializing deeply nested <code>list</code> of
<code>dict</code>.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/ijl/orjson/blob/master/CHANGELOG.md">orjson's
changelog</a>.</em></p>
<blockquote>
<h2>3.11.7 - 2026-02-02</h2>
<h3>Changed</h3>
<ul>
<li>Use a faster library to serialize <code>float</code>. Users with
byte-exact regression
tests should note positive exponents are now written using a
<code>+</code>, e.g.,
<code>1.2e+30</code> instead of <code>1.2e30</code>. Both formats are
spec-compliant.</li>
<li>ABI compatibility with CPython 3.15 alpha 5 free-threading.</li>
</ul>
<h2>3.11.6 - 2026-01-29</h2>
<h3>Changed</h3>
<ul>
<li>orjson now includes code licensed under the Mozilla Public License
2.0 (MPL-2.0).</li>
<li>Drop support for Python 3.9.</li>
<li>ABI compatibility with CPython 3.15 alpha 5.</li>
<li>Build now depends on Rust 1.89 or later instead of 1.85.</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>Fix sporadic crash serializing deeply nested <code>list</code> of
<code>dict</code>.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/ijl/orjson/commit/ec2b066cae79ae4a90ed126ac5723335dd99e408"><code>ec2b066</code></a>
3.11.7</li>
<li><a
href="https://github.com/ijl/orjson/commit/1ca01f78cf4198ec37407d83713afa6e5c53dbf9"><code>1ca01f7</code></a>
zmij</li>
<li><a
href="https://github.com/ijl/orjson/commit/1716a226bd1f38db01503f30cd37b0efec48d88e"><code>1716a22</code></a>
cargo update</li>
<li><a
href="https://github.com/ijl/orjson/commit/ec02024c3837255064f248c0d2d331319b75e9ad"><code>ec02024</code></a>
3.11.6</li>
<li><a
href="https://github.com/ijl/orjson/commit/d58168733189f82b3fd0c058dff73e05d09202e6"><code>d581687</code></a>
build, clippy misc</li>
<li><a
href="https://github.com/ijl/orjson/commit/4105b29b2275f200f6fae01349bef02ccf1bc2e2"><code>4105b29</code></a>
writer::num</li>
<li><a
href="https://github.com/ijl/orjson/commit/62bb185b70785ded49c79c26f8c9781f1e6fe370"><code>62bb185</code></a>
Fix sporadic crash on serializing object close</li>
<li><a
href="https://github.com/ijl/orjson/commit/d860078a973f44401265c5c4ad12a7dbe4f839ad"><code>d860078</code></a>
PyRef idiom refactors</li>
<li><a
href="https://github.com/ijl/orjson/commit/343ae2f148197918aba9f8562db42c364620e4b8"><code>343ae2f</code></a>
Deserializer, Utf8Buffer</li>
<li><a
href="https://github.com/ijl/orjson/commit/7835f58d1c56947d1cf7a18acdfc07a2bca9b0f2"><code>7835f58</code></a>
PyBytesRef and other input refactor</li>
<li>Additional commits viewable in <a
href="https://github.com/ijl/orjson/compare/3.11.5...3.11.7">compare
view</a></li>
</ul>
</details>
<br />

Updates `ruff` from 0.14.13 to 0.15.1
<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.15.1</h2>
<h2>Release Notes</h2>
<p>Released on 2026-02-12.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>airflow</code>] Add ruff rules to catch deprecated Airflow
imports for Airflow 3.1 (<code>AIR321</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22376">#22376</a>)</li>
<li>[<code>airflow</code>] Third positional parameter not named
<code>ti_key</code> should be flagged for
<code>BaseOperatorLink.get_link</code> (<code>AIR303</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22828">#22828</a>)</li>
<li>[<code>flake8-gettext</code>] Fix false negatives for plural
argument of <code>ngettext</code> (<code>INT001</code>,
<code>INT002</code>, <code>INT003</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/21078">#21078</a>)</li>
<li>[<code>pyflakes</code>] Fix infinite loop in preview fix for
<code>unused-import</code> (<code>F401</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23038">#23038</a>)</li>
<li>[<code>pygrep-hooks</code>] Detect non-existent mock methods in
standalone expressions (<code>PGH005</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22830">#22830</a>)</li>
<li>[<code>pylint</code>] Allow dunder submodules and improve diagnostic
range (<code>PLC2701</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22804">#22804</a>)</li>
<li>[<code>pyupgrade</code>] Improve diagnostic range for tuples
(<code>UP024</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23013">#23013</a>)</li>
<li>[<code>refurb</code>] Check subscripts in tuple do not use lambda
parameters in <code>reimplemented-operator</code> (<code>FURB118</code>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23079">#23079</a>)</li>
<li>[<code>ruff</code>] Detect mutable defaults in <code>field</code>
calls (<code>RUF008</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23046">#23046</a>)</li>
<li>[<code>ruff</code>] Ignore std <code>cmath.inf</code>
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23120">#23120</a>)</li>
<li>[<code>ruff</code>] New rule <code>float-equality-comparison</code>
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/20585">#20585</a>)</li>
<li>Don't format unlabeled Markdown code blocks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23106">#23106</a>)</li>
<li>Markdown formatting support in LSP (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23063">#23063</a>)</li>
<li>Support Quarto Markdown language markers (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22947">#22947</a>)</li>
<li>Support formatting <code>pycon</code> Markdown code blocks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23112">#23112</a>)</li>
<li>Use extension mapping to select Markdown code block language (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22934">#22934</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>Avoid false positive for undefined variables in <code>FAST001</code>
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23224">#23224</a>)</li>
<li>Avoid introducing syntax errors for <code>FAST003</code> autofix (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23227">#23227</a>)</li>
<li>Avoid suggesting <code>InitVar</code> for <code>__post_init__</code>
that references PEP 695 type parameters (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23226">#23226</a>)</li>
<li>Deduplicate type variables in generic functions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23225">#23225</a>)</li>
<li>Fix exception handler parenthesis removal for Python 3.14+ (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23126">#23126</a>)</li>
<li>Fix f-string middle panic when parsing t-strings (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23232">#23232</a>)</li>
<li>Wrap <code>RUF020</code> target for multiline fixes (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23210">#23210</a>)</li>
<li>Wrap <code>UP007</code> target for multiline fixes (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23208">#23208</a>)</li>
<li>Fix missing diagnostics for last range suppression in file (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23242">#23242</a>)</li>
<li>[<code>pyupgrade</code>] Fix syntax error on string with newline
escape and comment (<code>UP037</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22968">#22968</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Use <code>ruff</code> instead of <code>Ruff</code> as the program
name in GitHub output format (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23240">#23240</a>)</li>
<li>[<code>PT006</code>] Fix syntax error when unpacking nested tuples
in <code>parametrize</code> fixes (<a
href="https://redirect.github.com/astral-sh/ruff/issues/22441">#22441</a>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/22464">#22464</a>)</li>
<li>[<code>airflow</code>] Catch deprecated attribute access from
context key for Airflow 3.0 (<code>AIR301</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22850">#22850</a>)</li>
<li>[<code>airflow</code>] Capture deprecated arguments and a decorator
(<code>AIR301</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23170">#23170</a>)</li>
<li>[<code>flake8-boolean-trap</code>] Add
<code>multiprocessing.Value</code> to excluded functions for
<code>FBT003</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23010">#23010</a>)</li>
<li>[<code>flake8-bugbear</code>] Add a secondary annotation showing the
previous occurrence (<code>B033</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22634">#22634</a>)</li>
<li>[<code>flake8-type-checking</code>] Add sub-diagnostic showing the
runtime use of an annotation (<code>TC004</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23091">#23091</a>)</li>
<li>[<code>isort</code>] Support configurable import section heading
comments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23151">#23151</a>)</li>
<li>[<code>ruff</code>] Improve the diagnostic for <code>RUF012</code>
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23202">#23202</a>)</li>
</ul>
<h3>Formatter</h3>
<!-- 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.15.1</h2>
<p>Released on 2026-02-12.</p>
<h3>Preview features</h3>
<ul>
<li>[<code>airflow</code>] Add ruff rules to catch deprecated Airflow
imports for Airflow 3.1 (<code>AIR321</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22376">#22376</a>)</li>
<li>[<code>airflow</code>] Third positional parameter not named
<code>ti_key</code> should be flagged for
<code>BaseOperatorLink.get_link</code> (<code>AIR303</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22828">#22828</a>)</li>
<li>[<code>flake8-gettext</code>] Fix false negatives for plural
argument of <code>ngettext</code> (<code>INT001</code>,
<code>INT002</code>, <code>INT003</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/21078">#21078</a>)</li>
<li>[<code>pyflakes</code>] Fix infinite loop in preview fix for
<code>unused-import</code> (<code>F401</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23038">#23038</a>)</li>
<li>[<code>pygrep-hooks</code>] Detect non-existent mock methods in
standalone expressions (<code>PGH005</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22830">#22830</a>)</li>
<li>[<code>pylint</code>] Allow dunder submodules and improve diagnostic
range (<code>PLC2701</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22804">#22804</a>)</li>
<li>[<code>pyupgrade</code>] Improve diagnostic range for tuples
(<code>UP024</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23013">#23013</a>)</li>
<li>[<code>refurb</code>] Check subscripts in tuple do not use lambda
parameters in <code>reimplemented-operator</code> (<code>FURB118</code>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23079">#23079</a>)</li>
<li>[<code>ruff</code>] Detect mutable defaults in <code>field</code>
calls (<code>RUF008</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23046">#23046</a>)</li>
<li>[<code>ruff</code>] Ignore std <code>cmath.inf</code>
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23120">#23120</a>)</li>
<li>[<code>ruff</code>] New rule <code>float-equality-comparison</code>
(<code>RUF069</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/20585">#20585</a>)</li>
<li>Don't format unlabeled Markdown code blocks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23106">#23106</a>)</li>
<li>Markdown formatting support in LSP (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23063">#23063</a>)</li>
<li>Support Quarto Markdown language markers (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22947">#22947</a>)</li>
<li>Support formatting <code>pycon</code> Markdown code blocks (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23112">#23112</a>)</li>
<li>Use extension mapping to select Markdown code block language (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22934">#22934</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>Avoid false positive for undefined variables in <code>FAST001</code>
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23224">#23224</a>)</li>
<li>Avoid introducing syntax errors for <code>FAST003</code> autofix (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23227">#23227</a>)</li>
<li>Avoid suggesting <code>InitVar</code> for <code>__post_init__</code>
that references PEP 695 type parameters (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23226">#23226</a>)</li>
<li>Deduplicate type variables in generic functions (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23225">#23225</a>)</li>
<li>Fix exception handler parenthesis removal for Python 3.14+ (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23126">#23126</a>)</li>
<li>Fix f-string middle panic when parsing t-strings (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23232">#23232</a>)</li>
<li>Wrap <code>RUF020</code> target for multiline fixes (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23210">#23210</a>)</li>
<li>Wrap <code>UP007</code> target for multiline fixes (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23208">#23208</a>)</li>
<li>Fix missing diagnostics for last range suppression in file (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23242">#23242</a>)</li>
<li>[<code>pyupgrade</code>] Fix syntax error on string with newline
escape and comment (<code>UP037</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22968">#22968</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>Use <code>ruff</code> instead of <code>Ruff</code> as the program
name in GitHub output format (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23240">#23240</a>)</li>
<li>[<code>PT006</code>] Fix syntax error when unpacking nested tuples
in <code>parametrize</code> fixes (<a
href="https://redirect.github.com/astral-sh/ruff/issues/22441">#22441</a>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/22464">#22464</a>)</li>
<li>[<code>airflow</code>] Catch deprecated attribute access from
context key for Airflow 3.0 (<code>AIR301</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22850">#22850</a>)</li>
<li>[<code>airflow</code>] Capture deprecated arguments and a decorator
(<code>AIR301</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23170">#23170</a>)</li>
<li>[<code>flake8-boolean-trap</code>] Add
<code>multiprocessing.Value</code> to excluded functions for
<code>FBT003</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23010">#23010</a>)</li>
<li>[<code>flake8-bugbear</code>] Add a secondary annotation showing the
previous occurrence (<code>B033</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/22634">#22634</a>)</li>
<li>[<code>flake8-type-checking</code>] Add sub-diagnostic showing the
runtime use of an annotation (<code>TC004</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23091">#23091</a>)</li>
<li>[<code>isort</code>] Support configurable import section heading
comments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/23151">#23151</a>)</li>
<li>[<code>ruff</code>] Improve the diagnostic for <code>RUF012</code>
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/23202">#23202</a>)</li>
</ul>
<h3>Formatter</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/ruff/commit/a2f11d239f91cf8daedb0764ec15fcfe29c5ae6d"><code>a2f11d2</code></a>
Prepare for 0.15.1 (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23253">#23253</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/d29628e9665baa17272aad489398eb72b70e60ff"><code>d29628e</code></a>
Remove docker-run-action (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23254">#23254</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/8a042667651d7b1cdfc1742478d2b29b04d91be0"><code>8a04266</code></a>
[ty] Allow discovering dependencies in system Python environments (<a
href="https://redirect.github.com/astral-sh/ruff/issues/22994">#22994</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/55d06c8879761c5500e9558502abc84cefcb7163"><code>55d06c8</code></a>
Ensure pending suppression diagnostics are reported (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23242">#23242</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/d056a9fa6dfb842f2c0d439bf7b1a8099e5734ea"><code>d056a9f</code></a>
[<code>isort</code>] support for configurable import section heading
comments (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23151">#23151</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/e22fa4f14d8fae550249e452d11bc53756df5c7a"><code>e22fa4f</code></a>
[ty] Fix method calls on subclasses of <code>Any</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23248">#23248</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/fa56c1550d723e458b91dc2405d5537d40401d5c"><code>fa56c15</code></a>
[ty] Fix bound method access on <code>None</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23246">#23246</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/4fd07d0e1cbbb4e4c3f5b4c1f04f2d8b3f4a2bf2"><code>4fd07d0</code></a>
Make range suppression test snapshot actually useful (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23251">#23251</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/8c63bced13b21d1952a56e6a096d9c2ec4af442f"><code>8c63bce</code></a>
[ty] Include conditional symbols (like <code>datetime.UTC</code>) in
auto-import in more...</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/46be94361b3b4c54be911eb88bfbd9666eb06a6d"><code>46be943</code></a>
Exclude WASM artifacts from GitHub releases (<a
href="https://redirect.github.com/astral-sh/ruff/issues/23221">#23221</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/ruff/compare/0.14.13...0.15.1">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>
2026-02-17 01:01:50 -08:00
William FHandGitHub 7216504ce2 fix: dependabot (#6806) 2026-02-14 11:44:02 -08:00
William FHandGitHub fe4daa1c7c release(sdk-py): 0.3.6 (#6805) 2026-02-14 11:41:27 -08:00
John KennedyandGitHub 34769f31bc chore: update dependabot.yml to comply with posture checks (#6780)
- Add schedule.day: monday to all entries
- Add groups configuration to prevent noisy per-dependency PRs
- Split pip directories into individual entries per Dependabot v2 spec
- Add npm ecosystem entries for js-examples and js-monorepo-example
subdirectories
- Specify package-manager: uv for all Python entries (repo uses uv.lock)

Thank you for contributing to LangGraph! Follow these steps to mark your
pull request as ready for review. **If any of these steps are not
completed, your PR will not be considered for review.**

- [x] **PR title**: Follows the format: {TYPE}({SCOPE}): {DESCRIPTION}
  - Examples:
    - feat(core): add multi-tenant support
    - fix(cli): resolve flag parsing error
    - docs(openai): update API usage examples
  - Allowed `{TYPE}` values:
- feat, fix, docs, style, refactor, perf, test, build, ci, chore,
revert, release
  - Allowed `{SCOPE}` values (optional):
- langgraph, docs, cli, checkpoint, checkpoint-postgres,
checkpoint-sqlite, prebuilt, scheduler-kafka, sdk-py
- Once you've written the title, please delete this checklist item; do
not include it in the PR.

- [x] **PR message**: ***Delete this entire checklist*** and replace
with
- **Description:** a description of the change. Include a [closing
keyword](https://docs.github.com/en/issues/tracking-your-work-with-issues/using-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword)
if applicable.
  - **Issue:** the issue # it fixes, if applicable
  - **Dependencies:** any dependencies required for this change
- **Twitter handle:** if your PR gets announced, and you'd like a
mention, we'll gladly shout you out!

- [x] **Add tests and docs**: If you're adding a new integration, you
must include:
1. A test for the integration, preferably unit tests that do not rely on
network access,
2. An example notebook showing its use. It lives in
`docs/docs/integrations` directory.

- [x] **Lint and test**: Run `make format`, `make lint` and `make test`
from the root of the package(s) you've modified. We will not consider a
PR unless these three are passing in CI. See [contribution
guidelines](https://docs.langchain.com/oss/python/contributing/overview)
for more.

Additional guidelines:

- Make sure optional dependencies are imported within a function.
- Please do not add dependencies to `pyproject.toml` files (even
optional ones) unless they are **required** for unit tests.
- Most PRs should not touch more than one package.
- Changes should be backwards compatible.
2026-02-14 11:36:12 -08:00
William FHandGitHub eac6abb8ee chore: update to add prune method (#6804) 2026-02-14 10:02:07 -08:00
9f0ae94f27 chore: Re-organize client files. (#6787)
Additional guidelines:

- Make sure optional dependencies are imported within a function.
- Please do not add dependencies to `pyproject.toml` files (even
optional ones) unless they are **required** for unit tests.
- Most PRs should not touch more than one package.
- Changes should be backwards compatible.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 17:22:59 -05:00
f5e56e200d feat(cli): add keep_latest prune strategy to ThreadTTLConfig (#6784)
## Summary
- Add `"keep_latest"` to `ThreadTTLConfig.strategy` to match
langgraph-api support for pruning old checkpoints while retaining the
thread and its latest state
- Add `sweep_limit` to `ThreadTTLConfig` where the API actually reads it
(was previously a no-op on `CheckpointerConfig`)
- Regenerate `schema.json` / `schema.v0.json`

## Test plan
- [x] `make format && make lint` passes
- [x] `make test` passes (85/85)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 19:00:48 -08:00
William FHandGitHub f9870bc9ae chore: Drop support for bullseye builds (#6779)
It's EOL for debian.
2026-02-10 15:11:24 -08:00
William FHandGitHub a734f5e6ce chore: server runtime type (#6774)
Main jtbd here:
a) clarify who/how a graph is being accessed and make the factory aware
of the `context` where relevant (and make it obvious when it is
available)
b) make it more clear when you can bypass / defer resources with
expensive lifespans (like MCp connections)
c) make auth access more type-safe.

Gives us room to add other information, like:
- langsmith distributed tracing information



---- old
Can start doing things like this:

```
def my_graph(runtime: ServerRuntime):
     if runtime.ensure_user().permissions not in ("foo"):
         raise ValueError("bar")
```
etc.

Points of expected confusion:
- You won't have a stream_writer in this context.
- This won't be an accessible object within the graph, only the graph
factory.


For maintainers, related draft PR int he server
https://github.com/langchain-ai/langgraph/pull/6774
2026-02-10 08:53:52 -08:00
Luka AladashviliandGitHub 84446f5ad8 refactor: replace bare except with BaseException in AsyncQueue (#6765)
## Description
Replaced a bare `except:` with `except BaseException:` in
`libs/langgraph/langgraph/_internal/_queue.py`.

## Motivation
Using a bare `except:` violates PEP 8 (E722). While functionally
equivalent to `except BaseException:`, making it explicit improves code
readability and satisfies static analysis tools.

This ensures that `asyncio.CancelledError` (which inherits from
`BaseException`) is still caught and handled correctly by the
cancellation logic in the `wait()` method, but without the ambiguity of
a bare except.
2026-02-10 05:08:39 -08:00
Mason DaughertyandGitHub f6d95abbe3 docs(prebuilt): update warning for create_react_agent (#6760) 2026-02-06 15:08:08 -05:00
William FHandGitHub a7a27dd43a release(langgraph): 1.0.8 (#6757) 2026-02-06 07:27:08 -05:00
William FHandGitHub 50238be239 chore: shallow copy futures (#6755) 2026-02-05 19:14:42 -08:00
Sydney RunkleandGitHub 114978b612 fix: pydantic messages double streaming (#6753)
Problem: `StreamMessagesHandler.on_chain_start` only populated the seen
set for dict inputs, so Pydantic/dataclass state, objects were skipped —
causing duplicate messages after interrupt/resume

Solution: Extract a shared `_state_values()` helper that handles dict,
BaseModel, and dataclass inputs uniformly, and use it in both
on_chain_start and on_chain_end
 
Also replaces the fragile dir()/getattr fallback in on_chain_end with
the same helper

Tests: Added test_stream_messages_dedupe_pydantic_subgraph_interrupt —
confirms no duplicate message IDs across interrupt/resume with Pydantic
subgraph state (fails on main, passes with fix)
2026-02-05 17:07:33 -08:00
92 changed files with 18357 additions and 9705 deletions
+102 -9
View File
@@ -4,15 +4,108 @@ updates:
directory: "/"
schedule:
interval: "weekly"
day: "monday"
groups:
all-dependencies:
patterns:
- "*"
- package-ecosystem: "pip"
directories:
- "libs/checkpoint"
- "libs/checkpoint-postgres"
- "libs/checkpoint-sqlite"
- "libs/cli"
- "libs/langgraph"
- "libs/prebuilt"
- "libs/sdk-py"
- package-ecosystem: "uv"
directory: "/libs/checkpoint"
schedule:
interval: "weekly"
day: "monday"
groups:
all-dependencies:
patterns:
- "*"
- package-ecosystem: "uv"
directory: "/libs/checkpoint-conformance"
schedule:
interval: "weekly"
day: "monday"
groups:
all-dependencies:
patterns:
- "*"
- package-ecosystem: "uv"
directory: "/libs/checkpoint-postgres"
schedule:
interval: "weekly"
day: "monday"
groups:
all-dependencies:
patterns:
- "*"
- package-ecosystem: "uv"
directory: "/libs/checkpoint-sqlite"
schedule:
interval: "weekly"
day: "monday"
groups:
all-dependencies:
patterns:
- "*"
- package-ecosystem: "uv"
directory: "/libs/cli"
schedule:
interval: "weekly"
day: "monday"
groups:
all-dependencies:
patterns:
- "*"
- package-ecosystem: "uv"
directory: "/libs/langgraph"
schedule:
interval: "weekly"
day: "monday"
groups:
all-dependencies:
patterns:
- "*"
- package-ecosystem: "uv"
directory: "/libs/prebuilt"
schedule:
interval: "weekly"
day: "monday"
groups:
all-dependencies:
patterns:
- "*"
- package-ecosystem: "uv"
directory: "/libs/sdk-py"
schedule:
interval: "weekly"
day: "monday"
groups:
all-dependencies:
patterns:
- "*"
- package-ecosystem: "npm"
directory: "/libs/cli/js-examples"
schedule:
interval: "weekly"
day: "monday"
groups:
all-dependencies:
patterns:
- "*"
- package-ecosystem: "npm"
directory: "/libs/cli/js-monorepo-example"
schedule:
interval: "weekly"
day: "monday"
groups:
all-dependencies:
patterns:
- "*"
+2 -2
View File
@@ -63,7 +63,7 @@ def test(config: pathlib.Path, port: int, tag: str, verbose: bool):
try:
sys.stderr.write("\n== docker compose ps ==\n")
runner.run(
subp_exec(*compose_cmd, *args, "ps", input=stdin, verbose=False)
subp_exec(*compose_cmd, *args, "ps", input=stdin, verbose=True)
)
except Exception:
pass
@@ -76,7 +76,7 @@ def test(config: pathlib.Path, port: int, tag: str, verbose: bool):
"logs",
"langgraph-api",
input=stdin,
verbose=False,
verbose=True,
)
)
except Exception:
+30 -10
View File
@@ -2,6 +2,9 @@ name: CLI integration test
on:
workflow_call:
secrets:
LANGSMITH_API_KEY:
required: false
permissions:
contents: read
@@ -28,6 +31,8 @@ jobs:
workdir: libs/cli/examples/graphs_reqs_b
tag: langgraph-test-d
name: "CLI integration test"
env:
HAS_LANGSMITH_API_KEY: ${{ secrets.LANGSMITH_API_KEY != '' }}
defaults:
run:
working-directory: libs/cli
@@ -49,19 +54,22 @@ jobs:
- name: Install cli globally
if: steps.changed-files.outputs.all
run: pip install -e .
- name: Build and test service ${{ matrix.example.name }}
- name: Build service ${{ matrix.example.name }}
if: steps.changed-files.outputs.all
working-directory: ${{ matrix.example.workdir }}
run: |
langgraph build -t ${{ matrix.example.tag }}
- name: Test service ${{ matrix.example.name }}
if: ${{ steps.changed-files.outputs.all && env.HAS_LANGSMITH_API_KEY == 'true' }}
working-directory: ${{ matrix.example.workdir }}
env:
LANGSMITH_API_KEY: ${{ secrets.LANGSMITH_API_KEY }}
run: |
# Build the image for this example
langgraph build -t ${{ matrix.example.tag }}
# Prepare environment file from local or parent example directory
if [ -f .env.example ]; then cp .env.example .env; elif [ -f ../.env.example ]; then cp ../.env.example .env && cp ../.env.example ../.env; fi
if [ -n "${{ secrets.LANGSMITH_API_KEY }}" ]; then echo "LANGSMITH_API_KEY=${{ secrets.LANGSMITH_API_KEY }}" >> .env; if [ -f ../.env ]; then echo "LANGSMITH_API_KEY=${{ secrets.LANGSMITH_API_KEY }}" >> ../.env; fi; fi
echo "LANGSMITH_API_KEY=${{ secrets.LANGSMITH_API_KEY }}" >> .env
if [ -f ../.env ]; then echo "LANGSMITH_API_KEY=${{ secrets.LANGSMITH_API_KEY }}" >> ../.env; fi
# Run the integration test using the built tag
# Compute repo root to reference the shared script robustly
REPO_ROOT=$(git rev-parse --show-toplevel)
timeout 60 python "$REPO_ROOT/.github/scripts/run_langgraph_cli_test.py" -t ${{ matrix.example.tag }}
@@ -82,22 +90,34 @@ jobs:
working-directory: libs/cli/python-monorepo-example
run: |
langgraph build -t langgraph-test-g -c apps/agent/langgraph.json
- name: Test Python monorepo service
if: ${{ steps.changed-files.outputs.all && matrix.example.name == 'A' && env.HAS_LANGSMITH_API_KEY == 'true' }}
working-directory: libs/cli/python-monorepo-example
env:
LANGSMITH_API_KEY: ${{ secrets.LANGSMITH_API_KEY }}
run: |
cp apps/agent/.env.example apps/agent/.env
if [ -n "${{ secrets.LANGSMITH_API_KEY }}" ]; then echo "LANGSMITH_API_KEY=${{ secrets.LANGSMITH_API_KEY }}" >> apps/agent/.env; fi
echo "LANGSMITH_API_KEY=${{ secrets.LANGSMITH_API_KEY }}" >> apps/agent/.env
timeout 60 python ../../../.github/scripts/run_langgraph_cli_test.py -t langgraph-test-g -c apps/agent/langgraph.json
- name: Build and test prerelease reqs service
- name: Build prerelease reqs service
if: ${{ steps.changed-files.outputs.all && matrix.example.name == 'A' }}
working-directory: libs/cli/examples/graph_prerelease_reqs
run: |
langgraph build -t langgraph-test-h
- name: Test prerelease reqs service
if: ${{ steps.changed-files.outputs.all && matrix.example.name == 'A' && env.HAS_LANGSMITH_API_KEY == 'true' }}
working-directory: libs/cli/examples/graph_prerelease_reqs
env:
LANGSMITH_API_KEY: ${{ secrets.LANGSMITH_API_KEY }}
run: |
cp ../.env.example .env
if [ -n "${{ secrets.LANGSMITH_API_KEY }}" ]; then echo "LANGSMITH_API_KEY=${{ secrets.LANGSMITH_API_KEY }}" >> .env; fi
echo "LANGSMITH_API_KEY=${{ secrets.LANGSMITH_API_KEY }}" >> .env
timeout 60 python ../../../../.github/scripts/run_langgraph_cli_test.py -t langgraph-test-h
echo "Finished starting up langgraph-test-h"
LANGGRAPH_VERSION=$(docker run --rm --entrypoint "" langgraph-test-h python -c "import sys; from importlib.metadata import version; v = version('langgraph'); print(v);")
if [ "$LANGGRAPH_VERSION" != "1.0.2" ]; then
echo "LANGGRAPH_VERSION != 1.0.2; $LANGGRAPH_VERSION"
if [ "$LANGGRAPH_VERSION" != "1.0.8" ]; then
echo "LANGGRAPH_VERSION != 1.0.8; $LANGGRAPH_VERSION"
exit 1
fi
LANGCHAIN_OPENAI_VERSION=$(docker run --rm --entrypoint "" langgraph-test-h python -c "import sys; from importlib.metadata import version; v = version('langchain-openai'); print(v);")
+3 -1
View File
@@ -39,6 +39,7 @@ jobs:
- 'libs/checkpoint/**'
- 'libs/checkpoint-sqlite/**'
- 'libs/checkpoint-postgres/**'
- 'libs/checkpoint-conformance/**'
- 'libs/prebuilt/**'
deps:
- '**/pyproject.toml'
@@ -57,7 +58,7 @@ jobs:
"libs/checkpoint",
"libs/checkpoint-sqlite",
"libs/checkpoint-postgres",
"libs/checkpoint-conformance",
"libs/prebuilt",
]
if: needs.changes.outputs.python == 'true' || needs.changes.outputs.deps == 'true'
@@ -77,6 +78,7 @@ jobs:
"libs/checkpoint",
"libs/checkpoint-sqlite",
"libs/checkpoint-postgres",
"libs/checkpoint-conformance",
"libs/prebuilt",
"libs/sdk-py",
]
+49
View File
@@ -0,0 +1,49 @@
name: Deploy Redirects to GitHub Pages
on:
push:
branches:
- main
paths:
- 'docs/**'
- '.github/workflows/deploy-redirects.yml'
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Generate redirect files
run: python docs/generate_redirects.py
- name: Setup Pages
uses: actions/configure-pages@v4
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: 'docs/_site'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
+1
View File
@@ -0,0 +1 @@
_site/
+142
View File
@@ -0,0 +1,142 @@
#!/usr/bin/env python3
"""
Generate HTML redirect files from redirects.json.
Usage:
python generate_redirects.py
This script reads redirects.json and generates individual HTML files
for each redirect path. Each HTML file uses meta refresh (0 delay)
which is SEO-friendly and treated similarly to 301 redirects by Google.
To add new redirects, simply edit redirects.json and re-run this script.
"""
import json
import os
from pathlib import Path
# Default fallback URL for any path not in the redirect map
DEFAULT_REDIRECT = "https://docs.langchain.com/oss/python/langgraph/overview"
HTML_TEMPLATE = """<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Redirecting...</title>
<link rel="canonical" href="{url}">
<meta name="robots" content="noindex">
<script>var anchor=window.location.hash.substr(1);location.href="{url}"+(anchor?"#"+anchor:"")</script>
<meta http-equiv="refresh" content="0; url={url}">
</head>
<body>
Redirecting...
</body>
</html>
"""
ROOT_HTML_TEMPLATE = """<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Redirecting to LangGraph Documentation</title>
<link rel="canonical" href="{url}">
<meta name="robots" content="noindex">
<script>var anchor=window.location.hash.substr(1);location.href="{url}"+(anchor?"#"+anchor:"")</script>
<meta http-equiv="refresh" content="0; url={url}">
</head>
<body>
<h1>Documentation has moved</h1>
<p>The LangGraph documentation has moved to <a href="{url}">docs.langchain.com</a>.</p>
<p>Redirecting you now...</p>
</body>
</html>
"""
CATCHALL_404_TEMPLATE = """<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Redirecting to LangGraph Documentation</title>
<link rel="canonical" href="{default_url}">
<meta name="robots" content="noindex">
<script>
// Catchall redirect for any unmapped paths
window.location.replace("{default_url}");
</script>
<meta http-equiv="refresh" content="0; url={default_url}">
</head>
<body>
<h1>Documentation has moved</h1>
<p>The LangGraph documentation has moved to <a href="{default_url}">docs.langchain.com</a>.</p>
<p>Redirecting you now...</p>
</body>
</html>
"""
def generate_redirects():
script_dir = Path(__file__).parent
output_dir = script_dir / "_site"
# Load redirects
with open(script_dir / "redirects.json") as f:
redirects = json.load(f)
# Clean output directory
if output_dir.exists():
import shutil
shutil.rmtree(output_dir)
output_dir.mkdir(parents=True)
# Generate individual HTML files for each redirect
for old_path, new_url in redirects.items():
# Remove leading slash and create directory structure
path = old_path.lstrip("/")
# Check if path has a file extension (e.g., .txt, .xml)
# If so, create the file directly instead of a directory with index.html
path_obj = Path(path)
has_extension = path_obj.suffix and len(path_obj.suffix) <= 5
if not path:
html_path = output_dir / "index.html"
elif has_extension:
# For files with extensions, create the file directly
html_path = output_dir / path
else:
# For directory-style URLs, create index.html inside
html_path = output_dir / path / "index.html"
# Create parent directories
html_path.parent.mkdir(parents=True, exist_ok=True)
# Write the redirect HTML
html_path.write_text(HTML_TEMPLATE.format(url=new_url))
print(f"Created: {html_path}")
# Create root index.html
root_index = output_dir / "index.html"
if not root_index.exists():
root_index.write_text(ROOT_HTML_TEMPLATE.format(url=DEFAULT_REDIRECT))
print(f"Created: {root_index}")
# Create 404.html for catchall
catchall_404 = output_dir / "404.html"
catchall_404.write_text(CATCHALL_404_TEMPLATE.format(default_url=DEFAULT_REDIRECT))
print(f"Created: {catchall_404}")
# Copy static files (like llms.txt) that can't be redirected via HTML
static_files = ["llms.txt"]
for static_file in static_files:
src = script_dir / static_file
if src.exists():
dst = output_dir / static_file
dst.write_text(src.read_text())
print(f"Copied: {dst}")
print(f"\nGenerated {len(redirects)} redirect files in {output_dir}")
if __name__ == "__main__":
generate_redirects()
+35
View File
@@ -0,0 +1,35 @@
# LangGraph
LangGraph documentation has moved to docs.langchain.com.
## Overview
- [LangGraph Overview](https://docs.langchain.com/oss/python/langgraph/overview): Introduction to LangGraph, a library for building stateful, multi-actor applications with LLMs.
- [Why LangGraph?](https://docs.langchain.com/oss/python/langgraph/why-langgraph): Motivation for LangGraph and its key features.
## Core Concepts
- [Graph API](https://docs.langchain.com/oss/python/langgraph/graph-api): Learn how to define state, create nodes, and connect them with edges.
- [Streaming](https://docs.langchain.com/oss/python/langgraph/streaming): Stream outputs from your graph for better UX.
- [Persistence](https://docs.langchain.com/oss/python/langgraph/persistence): Add memory and checkpointing to your graphs.
- [Add Memory](https://docs.langchain.com/oss/python/langgraph/add-memory): Implement short-term and long-term memory.
- [Workflows & Agents](https://docs.langchain.com/oss/python/langgraph/workflows-agents): Build agents and workflows with LangGraph.
## How-To Guides
- [Use Subgraphs](https://docs.langchain.com/oss/python/langgraph/use-subgraphs): Compose graphs using subgraphs.
- [Observability](https://docs.langchain.com/oss/python/langgraph/observability): Add tracing and debugging to your graphs.
- [Common Errors](https://docs.langchain.com/oss/python/langgraph/common-errors): Troubleshoot common LangGraph errors.
## Tutorials
- [Agentic RAG](https://docs.langchain.com/oss/python/langgraph/agentic-rag): Build an agentic RAG system with LangGraph.
- [SQL Agent](https://docs.langchain.com/oss/python/langgraph/sql-agent): Create a SQL agent with LangGraph.
## Reference
- [API Reference](https://reference.langchain.com/python/langgraph/): Complete API documentation for LangGraph.
## LangGraph Platform
For deploying LangGraph applications in production, see the [LangSmith documentation](https://docs.langchain.com/langsmith/agent-server).
+296
View File
@@ -0,0 +1,296 @@
{
"/how-tos/stream-values": "https://docs.langchain.com/oss/python/langgraph/streaming",
"/how-tos/stream-updates": "https://docs.langchain.com/oss/python/langgraph/streaming",
"/how-tos/streaming-content": "https://docs.langchain.com/oss/python/langgraph/streaming",
"/how-tos/stream-multiple": "https://docs.langchain.com/oss/python/langgraph/streaming",
"/how-tos/streaming-tokens-without-langchain": "https://docs.langchain.com/oss/python/langgraph/streaming",
"/how-tos/streaming-from-final-node": "https://docs.langchain.com/oss/python/langgraph/streaming",
"/how-tos/streaming-events-from-within-tools-without-langchain": "https://docs.langchain.com/oss/python/langgraph/streaming",
"/how-tos/state-reducers": "https://docs.langchain.com/oss/python/langgraph/graph-api#define-and-update-state",
"/how-tos/sequence": "https://docs.langchain.com/oss/python/langgraph/graph-api#create-a-sequence-of-steps",
"/how-tos/branching": "https://docs.langchain.com/oss/python/langgraph/graph-api#create-branches",
"/how-tos/recursion-limit": "https://docs.langchain.com/oss/python/langgraph/graph-api#create-and-control-loops",
"/how-tos/visualization": "https://docs.langchain.com/oss/python/langgraph/graph-api#visualize-your-graph",
"/how-tos/input_output_schema": "https://docs.langchain.com/oss/python/langgraph/graph-api#define-input-and-output-schemas",
"/how-tos/pass_private_state": "https://docs.langchain.com/oss/python/langgraph/graph-api#pass-private-state-between-nodes",
"/how-tos/state-model": "https://docs.langchain.com/oss/python/langgraph/graph-api#use-pydantic-models-for-graph-state",
"/how-tos/map-reduce": "https://docs.langchain.com/oss/python/langgraph/graph-api#map-reduce-and-the-send-api",
"/how-tos/command": "https://docs.langchain.com/oss/python/langgraph/graph-api#combine-control-flow-and-state-updates-with-command",
"/how-tos/configuration": "https://docs.langchain.com/oss/python/langgraph/graph-api#add-runtime-configuration",
"/how-tos/node-retries": "https://docs.langchain.com/oss/python/langgraph/graph-api#add-retry-policies",
"/how-tos/return-when-recursion-limit-hits": "https://docs.langchain.com/oss/python/langgraph/graph-api#impose-a-recursion-limit",
"/how-tos/async": "https://docs.langchain.com/oss/python/langgraph/graph-api#async",
"/how-tos/memory/manage-conversation-history": "https://docs.langchain.com/oss/python/langgraph/add-memory",
"/how-tos/memory/delete-messages": "https://docs.langchain.com/oss/python/langgraph/add-memory#delete-messages",
"/how-tos/memory/add-summary-conversation-history": "https://docs.langchain.com/oss/python/langgraph/add-memory#summarize-messages",
"/how-tos/memory": "https://docs.langchain.com/oss/python/langgraph/add-memory",
"/agents/memory": "https://docs.langchain.com/oss/python/langgraph/add-memory",
"/how-tos/subgraph-transform-state": "https://docs.langchain.com/oss/python/langgraph/use-subgraphs#different-state-schemas",
"/how-tos/subgraphs-manage-state": "https://docs.langchain.com/oss/python/langgraph/use-subgraphs#add-persistence",
"/how-tos/persistence_postgres": "https://docs.langchain.com/oss/python/langgraph/add-memory#use-in-production",
"/how-tos/persistence_mongodb": "https://docs.langchain.com/oss/python/langgraph/add-memory#use-in-production",
"/how-tos/persistence_redis": "https://docs.langchain.com/oss/python/langgraph/add-memory#use-in-production",
"/how-tos/subgraph-persistence": "https://docs.langchain.com/oss/python/langgraph/add-memory#use-with-subgraphs",
"/how-tos/cross-thread-persistence": "https://docs.langchain.com/oss/python/langgraph/add-memory#add-long-term-memory",
"/cloud/how-tos/copy_threads": "https://docs.langchain.com/langsmith/use-threads",
"/cloud/how-tos/check-thread-status": "https://docs.langchain.com/langsmith/use-threads",
"/cloud/concepts/threads": "https://docs.langchain.com/oss/python/langgraph/persistence#threads",
"/how-tos/persistence": "https://docs.langchain.com/oss/python/langgraph/add-memory",
"/how-tos/tool-calling-errors": "https://docs.langchain.com/oss/python/langgraph/workflows-agents",
"/how-tos/pass-config-to-tools": "https://docs.langchain.com/oss/python/langgraph/workflows-agents",
"/how-tos/pass-run-time-values-to-tools": "https://docs.langchain.com/oss/python/langgraph/workflows-agents",
"/how-tos/update-state-from-tools": "https://docs.langchain.com/oss/python/langgraph/workflows-agents",
"/agents/tools": "https://docs.langchain.com/oss/python/langgraph/workflows-agents",
"/how-tos/agent-handoffs": "https://docs.langchain.com/oss/python/langgraph/graph-api",
"/how-tos/multi-agent-network": "https://docs.langchain.com/oss/python/langgraph/graph-api",
"/how-tos/multi-agent-multi-turn-convo": "https://docs.langchain.com/oss/python/langgraph/graph-api",
"/cloud/index": "https://docs.langchain.com/oss/python/langgraph/overview",
"/cloud/how-tos/index": "https://docs.langchain.com/langsmith/home",
"/cloud/concepts/api": "https://docs.langchain.com/langsmith/agent-server",
"/cloud/concepts/cloud": "https://docs.langchain.com/langsmith/cloud",
"/cloud/faq/studio": "https://docs.langchain.com/langsmith/studio",
"/cloud/how-tos/human_in_the_loop_edit_state": "https://docs.langchain.com/langsmith/add-human-in-the-loop",
"/cloud/how-tos/human_in_the_loop_user_input": "https://docs.langchain.com/langsmith/add-human-in-the-loop",
"/concepts/platform_architecture": "https://docs.langchain.com/langsmith/cloud#architecture",
"/cloud/how-tos/stream_values": "https://docs.langchain.com/langsmith/streaming",
"/cloud/how-tos/stream_updates": "https://docs.langchain.com/langsmith/streaming",
"/cloud/how-tos/stream_messages": "https://docs.langchain.com/langsmith/streaming",
"/cloud/how-tos/stream_events": "https://docs.langchain.com/langsmith/streaming",
"/cloud/how-tos/stream_debug": "https://docs.langchain.com/langsmith/streaming",
"/cloud/how-tos/stream_multiple": "https://docs.langchain.com/langsmith/streaming",
"/cloud/concepts/streaming": "https://docs.langchain.com/oss/python/langgraph/streaming",
"/agents/streaming": "https://docs.langchain.com/oss/python/langgraph/streaming",
"/how-tos/create-react-agent": "https://docs.langchain.com/oss/python/langchain/agents#basic-configuration",
"/how-tos/create-react-agent-memory": "https://docs.langchain.com/oss/python/langgraph/add-memory",
"/how-tos/create-react-agent-system-prompt": "https://docs.langchain.com/oss/python/langgraph/add-memory",
"/how-tos/create-react-agent-structured-output": "https://docs.langchain.com/oss/python/langchain/agents#structured-output",
"/prebuilt": "https://docs.langchain.com/oss/python/langchain/agents",
"/reference/prebuilt": "https://reference.langchain.com/python/langgraph/agents/",
"/concepts/high_level": "https://docs.langchain.com/oss/python/langgraph/overview",
"/concepts/index": "https://docs.langchain.com/oss/python/langgraph/overview",
"/concepts/v0-human-in-the-loop": "https://docs.langchain.com/oss/python/langgraph/interrupts",
"/how-tos/index": "https://docs.langchain.com/oss/python/langgraph/overview",
"/tutorials/introduction": "https://docs.langchain.com/oss/python/langgraph/overview",
"/agents/deployment": "https://docs.langchain.com/oss/python/langgraph/local-server",
"/how-tos/deploy-self-hosted": "https://docs.langchain.com/langsmith/platform-setup",
"/concepts/self_hosted": "https://docs.langchain.com/langsmith/platform-setup",
"/tutorials/deployment": "https://docs.langchain.com/langsmith/deployments",
"/cloud/how-tos/assistant_versioning": "https://docs.langchain.com/langsmith/configuration-cloud",
"/cloud/concepts/runs": "https://docs.langchain.com/langsmith/assistants#execution",
"/how-tos/wait-user-input-functional": "https://docs.langchain.com/oss/python/langgraph/functional-api",
"/how-tos/review-tool-calls-functional": "https://docs.langchain.com/oss/python/langgraph/functional-api",
"/how-tos/create-react-agent-hitl": "https://docs.langchain.com/oss/python/langgraph/interrupts",
"/agents/human-in-the-loop": "https://docs.langchain.com/oss/python/langgraph/interrupts",
"/how-tos/human_in_the_loop/dynamic_breakpoints": "https://docs.langchain.com/oss/python/langgraph/interrupts",
"/concepts/breakpoints": "https://docs.langchain.com/oss/python/langgraph/interrupts",
"/how-tos/human_in_the_loop/breakpoints": "https://docs.langchain.com/oss/python/langgraph/interrupts",
"/cloud/how-tos/human_in_the_loop_breakpoint": "https://docs.langchain.com/langsmith/add-human-in-the-loop",
"/how-tos/human_in_the_loop/edit-graph-state": "https://docs.langchain.com/oss/python/langgraph/use-time-travel",
"/examples/index": "https://docs.langchain.com/oss/python/langgraph/case-studies",
"/guides/index": "https://docs.langchain.com/oss/python/langchain/overview",
"/tutorials/index": "https://docs.langchain.com/oss/python/learn",
"/llms-txt-overview": "https://docs.langchain.com/llms.txt",
"/tutorials/rag/langgraph_adaptive_rag": "https://docs.langchain.com/oss/python/langgraph/agentic-rag",
"/tutorials/multi_agent/multi-agent-collaboration": "https://docs.langchain.com/oss/python/langchain/multi-agent",
"/how-tos/create-react-agent-manage-message-history": "https://docs.langchain.com/oss/python/langgraph/add-memory",
"/how-tos/many-tools": "https://docs.langchain.com/oss/python/langchain/tools",
"/tutorials/customer-support/customer-support": "https://docs.langchain.com/oss/python/langgraph/agentic-rag",
"/how-tos/react-agent-structured-output": "https://docs.langchain.com/oss/python/langchain/agents#structured-output",
"/tutorials/code_assistant/langgraph_code_assistant": "https://docs.langchain.com/oss/python/langgraph/agentic-rag",
"/tutorials/multi_agent/hierarchical_agent_teams": "https://docs.langchain.com/oss/python/langchain/supervisor",
"/tutorials/auth/getting_started": "https://docs.langchain.com/langsmith/auth",
"/tutorials/auth/resource_auth": "https://docs.langchain.com/langsmith/resource-auth",
"/tutorials/auth/add_auth_server": "https://docs.langchain.com/langsmith/add-auth-server",
"/how-tos/use-remote-graph": "https://docs.langchain.com/langsmith/use-remote-graph",
"/how-tos/autogen-integration": "https://docs.langchain.com/langsmith/autogen-integration",
"/how-tos/human_in_the_loop/wait-user-input": "https://docs.langchain.com/oss/python/langgraph/interrupts",
"/cloud/how-tos/use_stream_react": "https://docs.langchain.com/langsmith/use-stream-react",
"/cloud/how-tos/generative_ui_react": "https://docs.langchain.com/langsmith/generative-ui-react",
"/concepts/langgraph_platform": "https://docs.langchain.com/langsmith/home",
"/concepts/langgraph_components": "https://docs.langchain.com/langsmith/components",
"/concepts/langgraph_server": "https://docs.langchain.com/langsmith/agent-server",
"/concepts/langgraph_data_plane": "https://docs.langchain.com/langsmith/data-plane",
"/concepts/langgraph_control_plane": "https://docs.langchain.com/langsmith/control-plane",
"/concepts/langgraph_cli": "https://docs.langchain.com/langsmith/cli",
"/concepts/langgraph_studio": "https://docs.langchain.com/langsmith/studio",
"/cloud/how-tos/studio/quick_start": "https://docs.langchain.com/langsmith/quick-start-studio",
"/cloud/how-tos/invoke_studio": "https://docs.langchain.com/langsmith/use-studio",
"/cloud/how-tos/studio/manage_assistants": "https://docs.langchain.com/langsmith/use-studio",
"/cloud/how-tos/threads_studio": "https://docs.langchain.com/langsmith/use-threads",
"/cloud/how-tos/iterate_graph_studio": "https://docs.langchain.com/langsmith/use-studio",
"/cloud/how-tos/studio/run_evals": "https://docs.langchain.com/langsmith/observability",
"/cloud/how-tos/clone_traces_studio": "https://docs.langchain.com/langsmith/observability",
"/cloud/how-tos/datasets_studio": "https://docs.langchain.com/langsmith/use-studio",
"/concepts/sdk": "https://docs.langchain.com/langsmith/sdk",
"/concepts/plans": "https://docs.langchain.com/langsmith/home",
"/concepts/application_structure": "https://docs.langchain.com/langsmith/application-structure",
"/concepts/scalability_and_resilience": "https://docs.langchain.com/langsmith/scalability-and-resilience",
"/concepts/auth": "https://docs.langchain.com/langsmith/auth",
"/how-tos/auth/custom_auth": "https://docs.langchain.com/langsmith/custom-auth",
"/how-tos/auth/openapi_security": "https://docs.langchain.com/langsmith/openapi-security",
"/concepts/assistants": "https://docs.langchain.com/langsmith/assistants",
"/cloud/how-tos/configuration_cloud": "https://docs.langchain.com/langsmith/configuration-cloud",
"/cloud/how-tos/use_threads": "https://docs.langchain.com/langsmith/use-threads",
"/cloud/how-tos/background_run": "https://docs.langchain.com/langsmith/background-run",
"/cloud/how-tos/same-thread": "https://docs.langchain.com/langsmith/same-thread",
"/cloud/how-tos/stateless_runs": "https://docs.langchain.com/langsmith/stateless-runs",
"/cloud/how-tos/configurable_headers": "https://docs.langchain.com/langsmith/configurable-headers",
"/concepts/double_texting": "https://docs.langchain.com/langsmith/double-texting",
"/cloud/how-tos/interrupt_concurrent": "https://docs.langchain.com/langsmith/interrupt-concurrent",
"/cloud/how-tos/rollback_concurrent": "https://docs.langchain.com/langsmith/rollback-concurrent",
"/cloud/how-tos/reject_concurrent": "https://docs.langchain.com/langsmith/reject-concurrent",
"/cloud/how-tos/enqueue_concurrent": "https://docs.langchain.com/langsmith/enqueue-concurrent",
"/cloud/concepts/webhooks": "https://docs.langchain.com/langsmith/use-webhooks",
"/cloud/how-tos/webhooks": "https://docs.langchain.com/langsmith/use-webhooks",
"/cloud/concepts/cron_jobs": "https://docs.langchain.com/langsmith/cron-jobs",
"/cloud/how-tos/cron_jobs": "https://docs.langchain.com/langsmith/cron-jobs",
"/how-tos/http/custom_lifespan": "https://docs.langchain.com/langsmith/custom-lifespan",
"/how-tos/http/custom_middleware": "https://docs.langchain.com/langsmith/custom-middleware",
"/how-tos/http/custom_routes": "https://docs.langchain.com/langsmith/custom-routes",
"/cloud/concepts/data_storage_and_privacy": "https://docs.langchain.com/langsmith/data-storage-and-privacy",
"/cloud/deployment/semantic_search": "https://docs.langchain.com/langsmith/semantic-search",
"/how-tos/ttl/configure_ttl": "https://docs.langchain.com/langsmith/configure-ttl",
"/concepts/deployment_options": "https://docs.langchain.com/langsmith/deployments",
"/cloud/quick_start": "https://docs.langchain.com/langsmith/deployment-quickstart",
"/cloud/deployment/setup": "https://docs.langchain.com/langsmith/setup-app-requirements-txt",
"/cloud/deployment/setup_pyproject": "https://docs.langchain.com/langsmith/setup-pyproject",
"/cloud/deployment/setup_javascript": "https://docs.langchain.com/langsmith/setup-javascript",
"/cloud/deployment/custom_docker": "https://docs.langchain.com/langsmith/custom-docker",
"/cloud/deployment/graph_rebuild": "https://docs.langchain.com/langsmith/graph-rebuild",
"/concepts/langgraph_cloud": "https://docs.langchain.com/langsmith/cloud",
"/concepts/langgraph_self_hosted_data_plane": "https://docs.langchain.com/langsmith/platform-setup",
"/concepts/langgraph_self_hosted_control_plane": "https://docs.langchain.com/langsmith/platform-setup",
"/concepts/langgraph_standalone_container": "https://docs.langchain.com/langsmith/docker",
"/cloud/deployment/cloud": "https://docs.langchain.com/langsmith/cloud",
"/cloud/deployment/self_hosted_data_plane": "https://docs.langchain.com/langsmith/platform-setup",
"/cloud/deployment/self_hosted_control_plane": "https://docs.langchain.com/langsmith/platform-setup",
"/cloud/deployment/standalone_container": "https://docs.langchain.com/langsmith/docker",
"/concepts/server-mcp": "https://docs.langchain.com/langsmith/server-mcp",
"/cloud/how-tos/human_in_the_loop_time_travel": "https://docs.langchain.com/langsmith/human-in-the-loop-time-travel",
"/cloud/how-tos/add-human-in-the-loop": "https://docs.langchain.com/langsmith/add-human-in-the-loop",
"/cloud/deployment/egress": "https://docs.langchain.com/langsmith/env-var",
"/cloud/how-tos/streaming": "https://docs.langchain.com/langsmith/streaming",
"/cloud/reference/api/api_ref": "https://docs.langchain.com/langsmith/server-api-ref",
"/cloud/reference/langgraph_server_changelog": "https://docs.langchain.com/langsmith/agent-server-changelog",
"/cloud/reference/api/api_ref_control_plane": "https://docs.langchain.com/langsmith/api-ref-control-plane",
"/cloud/reference/cli": "https://docs.langchain.com/langsmith/cli",
"/cloud/reference/env_var": "https://docs.langchain.com/langsmith/env-var",
"/troubleshooting/studio": "https://docs.langchain.com/langsmith/troubleshooting-studio",
"/index": "https://docs.langchain.com/oss/python/langgraph/overview",
"/agents/agents": "https://docs.langchain.com/oss/python/langchain/agents",
"/concepts/why-langgraph": "https://docs.langchain.com/oss/python/langgraph/overview",
"/tutorials/get-started/1-build-basic-chatbot": "https://docs.langchain.com/oss/python/langgraph/quickstart",
"/tutorials/get-started/2-add-tools": "https://docs.langchain.com/oss/python/langgraph/quickstart",
"/tutorials/get-started/3-add-memory": "https://docs.langchain.com/oss/python/langgraph/quickstart",
"/tutorials/get-started/4-human-in-the-loop": "https://docs.langchain.com/oss/python/langgraph/quickstart",
"/tutorials/get-started/5-customize-state": "https://docs.langchain.com/oss/python/langgraph/quickstart",
"/tutorials/get-started/6-time-travel": "https://docs.langchain.com/oss/python/langgraph/quickstart",
"/tutorials/langsmith/local-server": "https://docs.langchain.com/oss/python/langgraph/local-server",
"/tutorials/workflows": "https://docs.langchain.com/oss/python/langgraph/workflows-agents",
"/tutorials/plan-and-execute/plan-and-execute": "https://docs.langchain.com/oss/python/langchain/middleware/built-in#to-do-list",
"/tutorials/langgraph-platform/local-server/local-server": "https://docs.langchain.com/langsmith/local-server",
"/concepts/agentic_concepts": "https://docs.langchain.com/oss/python/langgraph/workflows-agents",
"/agents/overview": "https://docs.langchain.com/oss/python/langchain/agents",
"/agents/run_agents": "https://docs.langchain.com/oss/python/langgraph/quickstart",
"/concepts/low_level": "https://docs.langchain.com/oss/python/langgraph/graph-api",
"/how-tos/graph-api": "https://docs.langchain.com/oss/python/langgraph/graph-api",
"/how-tos/react-agent-from-scratch": "https://docs.langchain.com/oss/python/langchain/quickstart",
"/concepts/functional_api": "https://docs.langchain.com/oss/python/langgraph/functional-api",
"/how-tos/use-functional-api": "https://docs.langchain.com/oss/python/langgraph/functional-api",
"/concepts/pregel": "https://docs.langchain.com/oss/python/langgraph/pregel",
"/concepts/streaming": "https://docs.langchain.com/oss/python/langgraph/streaming",
"/how-tos/streaming": "https://docs.langchain.com/oss/python/langgraph/streaming",
"/concepts/persistence": "https://docs.langchain.com/oss/python/langgraph/persistence",
"/concepts/durable_execution": "https://docs.langchain.com/oss/python/langgraph/durable-execution",
"/concepts/memory": "https://docs.langchain.com/oss/python/langgraph/memory",
"/how-tos/memory/add-memory": "https://docs.langchain.com/oss/python/langgraph/add-memory",
"/agents/context": "https://docs.langchain.com/oss/python/langgraph/add-memory",
"/agents/models": "https://docs.langchain.com/oss/python/langgraph/overview",
"/concepts/tools": "https://docs.langchain.com/oss/python/langgraph/workflows-agents",
"/how-tos/tool-calling": "https://docs.langchain.com/oss/python/langgraph/workflows-agents",
"/concepts/human_in_the_loop": "https://docs.langchain.com/oss/python/langgraph/interrupts",
"/how-tos/human_in_the_loop/add-human-in-the-loop": "https://docs.langchain.com/oss/python/langgraph/interrupts",
"/concepts/time-travel": "https://docs.langchain.com/oss/python/langgraph/persistence",
"/how-tos/human_in_the_loop/time-travel": "https://docs.langchain.com/oss/python/langgraph/use-time-travel",
"/concepts/subgraphs": "https://docs.langchain.com/oss/python/langgraph/use-subgraphs",
"/how-tos/subgraph": "https://docs.langchain.com/oss/python/langgraph/use-subgraphs",
"/concepts/multi_agent": "https://docs.langchain.com/oss/python/langgraph/graph-api",
"/agents/multi-agent": "https://docs.langchain.com/oss/python/langchain/multi-agent",
"/how-tos/multi_agent": "https://docs.langchain.com/oss/python/langgraph/graph-api",
"/concepts/mcp": "https://docs.langchain.com/oss/python/langgraph/overview",
"/agents/mcp": "https://docs.langchain.com/oss/python/langgraph/overview",
"/concepts/tracing": "https://docs.langchain.com/oss/python/langgraph/observability",
"/how-tos/enable-tracing": "https://docs.langchain.com/oss/python/langgraph/observability",
"/agents/evals": "https://docs.langchain.com/oss/python/langgraph/overview",
"/concepts/template_applications": "https://docs.langchain.com/oss/python/langgraph/overview",
"/tutorials/rag/langgraph_agentic_rag": "https://docs.langchain.com/oss/python/langgraph/agentic-rag",
"/tutorials/multi_agent/agent_supervisor": "https://docs.langchain.com/oss/python/langgraph/workflows-agents",
"/tutorials/sql/sql-agent": "https://docs.langchain.com/oss/python/langgraph/sql-agent",
"/agents/ui": "https://docs.langchain.com/oss/python/langgraph/ui",
"/how-tos/run-id-langsmith": "https://docs.langchain.com/oss/python/langgraph/observability",
"/troubleshooting/errors/index": "https://docs.langchain.com/oss/python/langgraph/common-errors",
"/troubleshooting/errors/INVALID_CHAT_HISTORY": "https://docs.langchain.com/oss/python/langgraph/INVALID_CHAT_HISTORY",
"/troubleshooting/errors/INVALID_LICENSE": "https://docs.langchain.com/oss/python/langgraph/common-errors",
"/adopters": "https://docs.langchain.com/oss/python/langgraph/case-studies",
"/concepts/faq": "https://docs.langchain.com/oss/python/langgraph/overview",
"/agents/prebuilt": "https://docs.langchain.com/oss/python/langchain/agents",
"/reference/index": "https://reference.langchain.com/python/langgraph/",
"/reference/graphs": "https://reference.langchain.com/python/langgraph/graphs/",
"/reference/func": "https://reference.langchain.com/python/langgraph/func/",
"/reference/pregel": "https://reference.langchain.com/python/langgraph/pregel/",
"/reference/checkpoints": "https://reference.langchain.com/python/langgraph/checkpoints/",
"/reference/store": "https://reference.langchain.com/python/langgraph/store/",
"/reference/cache": "https://reference.langchain.com/python/langgraph/cache/",
"/reference/types": "https://reference.langchain.com/python/langgraph/types/",
"/reference/runtime": "https://reference.langchain.com/python/langgraph/runtime/",
"/reference/config": "https://reference.langchain.com/python/langgraph/config/",
"/reference/errors": "https://reference.langchain.com/python/langgraph/errors/",
"/reference/constants": "https://reference.langchain.com/python/langgraph/constants/",
"/reference/channels": "https://reference.langchain.com/python/langgraph/channels/",
"/reference/agents": "https://reference.langchain.com/python/langgraph/agents/",
"/reference/supervisor": "https://reference.langchain.com/python/langgraph/supervisor/",
"/reference/swarm": "https://reference.langchain.com/python/langgraph/swarm/",
"/reference/mcp": "https://reference.langchain.com/python/langgraph/mcp/",
"/cloud/reference/sdk/python_sdk_ref": "https://reference.langchain.com/python/langsmith/deployment/sdk/",
"/reference/remote_graph": "https://reference.langchain.com/python/langsmith/deployment/remote_graph/",
"/additional-resources/index": "https://docs.langchain.com/oss/python/langchain/overview",
"/cloud/reference/sdk/js_ts_sdk_ref": "https://reference.langchain.com/javascript/modules/langsmith.html",
"/snippets/chat_model_tabs": "https://docs.langchain.com/oss/python/langchain/overview",
"/troubleshooting/errors/GRAPH_RECURSION_LIMIT": "https://docs.langchain.com/oss/python/langgraph/GRAPH_RECURSION_LIMIT",
"/troubleshooting/errors/INVALID_CONCURRENT_GRAPH_UPDATE": "https://docs.langchain.com/oss/python/langgraph/INVALID_CONCURRENT_GRAPH_UPDATE",
"/troubleshooting/errors/INVALID_GRAPH_NODE_RETURN_VALUE": "https://docs.langchain.com/oss/python/langgraph/INVALID_GRAPH_NODE_RETURN_VALUE",
"/troubleshooting/errors/MULTIPLE_SUBGRAPHS": "https://docs.langchain.com/oss/python/langgraph/MULTIPLE_SUBGRAPHS",
"/tutorials/rag/langgraph_self_rag": "https://docs.langchain.com/oss/python/langgraph/agentic-rag",
"/additional-resources": "https://docs.langchain.com/oss/python/langgraph/overview",
"/examples": "https://docs.langchain.com/oss/python/langgraph/overview",
"/guides": "https://docs.langchain.com/oss/python/langgraph/overview",
"/how-tos/autogen-integration-functional": "https://docs.langchain.com/oss/python/langgraph/overview",
"/how-tos/cross-thread-persistence-functional": "https://docs.langchain.com/oss/python/langgraph/add-memory#add-long-term-memory",
"/how-tos/disable-streaming": "https://docs.langchain.com/oss/python/langgraph/streaming",
"/how-tos/memory/semantic-search": "https://docs.langchain.com/oss/python/langgraph/add-memory",
"/how-tos/multi-agent-multi-turn-convo-functional": "https://docs.langchain.com/oss/python/langgraph/graph-api",
"/how-tos/multi-agent-network-functional": "https://docs.langchain.com/oss/python/langgraph/graph-api",
"/how-tos/persistence-functional": "https://docs.langchain.com/oss/python/langgraph/add-memory",
"/how-tos/react-agent-from-scratch-functional": "https://docs.langchain.com/oss/python/langgraph/workflows-agents",
"/reference": "https://reference.langchain.com/python/langgraph/",
"/troubleshooting/errors": "https://docs.langchain.com/oss/python/langgraph/common-errors",
"/tutorials/chatbot-simulation-evaluation/agent-simulation-evaluation": "https://docs.langchain.com/oss/python/langgraph/overview",
"/tutorials/chatbot-simulation-evaluation/langsmith-agent-simulation-evaluation": "https://docs.langchain.com/oss/python/langgraph/overview",
"/tutorials/chatbots/information-gather-prompting": "https://docs.langchain.com/oss/python/langgraph/overview",
"/tutorials/extraction/retries": "https://docs.langchain.com/oss/python/langgraph/overview",
"/tutorials/langgraph-platform/local-server": "https://docs.langchain.com/langsmith/agent-server",
"/tutorials/lats/lats": "https://docs.langchain.com/oss/python/langgraph/overview",
"/tutorials/llm-compiler/LLMCompiler": "https://docs.langchain.com/oss/python/langgraph/overview",
"/tutorials/rag/langgraph_adaptive_rag_local": "https://docs.langchain.com/oss/python/langgraph/agentic-rag",
"/tutorials/rag/langgraph_crag": "https://docs.langchain.com/oss/python/langgraph/agentic-rag",
"/tutorials/rag/langgraph_crag_local": "https://docs.langchain.com/oss/python/langgraph/agentic-rag",
"/tutorials/rag/langgraph_self_rag_local": "https://docs.langchain.com/oss/python/langgraph/agentic-rag",
"/tutorials/reflection/reflection": "https://docs.langchain.com/oss/python/langgraph/overview",
"/tutorials/reflexion/reflexion": "https://docs.langchain.com/oss/python/langgraph/overview",
"/tutorials/rewoo/rewoo": "https://docs.langchain.com/oss/python/langgraph/overview",
"/tutorials/self-discover/self-discover": "https://docs.langchain.com/oss/python/langgraph/overview",
"/tutorials/tnt-llm/tnt-llm": "https://docs.langchain.com/oss/python/langgraph/overview",
"/tutorials/tot/tot": "https://docs.langchain.com/oss/python/langgraph/overview",
"/tutorials/usaco/usaco": "https://docs.langchain.com/oss/python/langgraph/overview",
"/tutorials/web-navigation/web_voyager": "https://docs.langchain.com/oss/python/langgraph/overview"
}
+12
View File
@@ -0,0 +1,12 @@
.PHONY: format lint test
format:
uv run ruff format .
uv run ruff check --fix .
lint:
uv run ruff check .
uv run ty check
test:
uv run pytest $(TEST)
+111
View File
@@ -0,0 +1,111 @@
# langgraph-checkpoint-conformance
Conformance test suite for [LangGraph](https://github.com/langchain-ai/langgraph) checkpointer implementations.
Validates that a `BaseCheckpointSaver` subclass correctly implements the checkpoint storage contract — blob round-trips, metadata preservation, namespace isolation, incremental channel updates, and more.
## Installation
```bash
pip install langgraph-checkpoint-conformance
```
## Quick start
Register your checkpointer with `@checkpointer_test` and run `validate()`:
```python
import asyncio
from langgraph.checkpoint.conformance import checkpointer_test, validate
@checkpointer_test(name="MyCheckpointer")
async def my_checkpointer():
saver = MyCheckpointer(...)
yield saver
# cleanup runs after yield
async def main():
report = await validate(my_checkpointer)
report.print_report()
assert report.passed_all_base()
asyncio.run(main())
```
Or in a pytest test:
```python
import pytest
from langgraph.checkpoint.conformance import checkpointer_test, validate
@checkpointer_test(name="MyCheckpointer")
async def my_checkpointer():
yield MyCheckpointer(...)
@pytest.mark.asyncio
async def test_conformance():
report = await validate(my_checkpointer)
report.print_report()
assert report.passed_all_base()
```
## Capabilities
The suite tests **base** capabilities (required) and **extended** capabilities (optional, auto-detected):
| Capability | Required | Method |
|---|---|---|
| `put` | yes | `aput` |
| `put_writes` | yes | `aput_writes` |
| `get_tuple` | yes | `aget_tuple` |
| `list` | yes | `alist` |
| `delete_thread` | yes | `adelete_thread` |
| `delete_for_runs` | no | `adelete_for_runs` |
| `copy_thread` | no | `acopy_thread` |
| `prune` | no | `aprune` |
Extended capabilities are detected by checking whether the method is overridden from `BaseCheckpointSaver`. If not overridden, those tests are skipped.
## Options
### Progress output
```python
from langgraph.checkpoint.conformance.report import ProgressCallbacks
# Dot-style progress (. per pass, F per fail)
report = await validate(my_checkpointer, progress=ProgressCallbacks.default())
# Verbose (per-test names + stacktraces on failure)
report = await validate(my_checkpointer, progress=ProgressCallbacks.verbose())
```
### Skip capabilities
```python
@checkpointer_test(name="MyCheckpointer", skip_capabilities={"prune"})
async def my_checkpointer():
yield MyCheckpointer(...)
```
### Run specific capabilities
```python
report = await validate(my_checkpointer, capabilities={"put", "list"})
```
### Lifespan (one-time setup/teardown)
For expensive setup like database creation:
```python
async def db_lifespan():
await create_database()
yield
await drop_database()
@checkpointer_test(name="PostgresSaver", lifespan=db_lifespan)
async def pg_checkpointer():
async with PostgresSaver.from_conn_string(CONN_STRING) as saver:
yield saver
```
@@ -0,0 +1,9 @@
"""langgraph-checkpoint-conformance: conformance test suite for checkpointer implementations."""
from langgraph.checkpoint.conformance.initializer import checkpointer_test
from langgraph.checkpoint.conformance.validate import validate
__all__ = [
"checkpointer_test",
"validate",
]
@@ -0,0 +1,93 @@
"""Capability detection for checkpointer implementations."""
from __future__ import annotations
from dataclasses import dataclass
from enum import Enum
from typing import TYPE_CHECKING
from langgraph.checkpoint.base import BaseCheckpointSaver
if TYPE_CHECKING:
pass
class Capability(str, Enum):
"""Capabilities that a checkpointer may support."""
PUT = "put"
PUT_WRITES = "put_writes"
GET_TUPLE = "get_tuple"
LIST = "list"
DELETE_THREAD = "delete_thread"
DELETE_FOR_RUNS = "delete_for_runs"
COPY_THREAD = "copy_thread"
PRUNE = "prune"
# Capabilities that every checkpointer must support.
BASE_CAPABILITIES = frozenset(
{
Capability.PUT,
Capability.PUT_WRITES,
Capability.GET_TUPLE,
Capability.LIST,
Capability.DELETE_THREAD,
}
)
# Capabilities that are optional extensions.
EXTENDED_CAPABILITIES = frozenset(
{
Capability.DELETE_FOR_RUNS,
Capability.COPY_THREAD,
Capability.PRUNE,
}
)
ALL_CAPABILITIES = BASE_CAPABILITIES | EXTENDED_CAPABILITIES
# Maps capability to the async method name on BaseCheckpointSaver (or subclass).
_CAPABILITY_METHOD_MAP: dict[Capability, str] = {
Capability.PUT: "aput",
Capability.PUT_WRITES: "aput_writes",
Capability.GET_TUPLE: "aget_tuple",
Capability.LIST: "alist",
Capability.DELETE_THREAD: "adelete_thread",
Capability.DELETE_FOR_RUNS: "adelete_for_runs",
Capability.COPY_THREAD: "acopy_thread",
Capability.PRUNE: "aprune",
}
@dataclass(frozen=True)
class DetectedCapabilities:
"""Result of capability detection for a checkpointer type."""
detected: frozenset[Capability]
missing: frozenset[Capability]
@classmethod
def from_instance(cls, saver: BaseCheckpointSaver) -> DetectedCapabilities:
"""Detect capabilities from a checkpointer instance."""
inner_type = type(saver)
detected: set[Capability] = set()
for cap, method_name in _CAPABILITY_METHOD_MAP.items():
if _is_overridden(inner_type, method_name):
detected.add(cap)
detected_fs = frozenset(detected)
return cls(
detected=detected_fs,
missing=ALL_CAPABILITIES - detected_fs,
)
def _is_overridden(inner_type: type, method: str) -> bool:
"""Check if *method* on *inner_type* differs from the base class default."""
base = getattr(BaseCheckpointSaver, method, None)
impl = getattr(inner_type, method, None)
if base is None or impl is None:
return impl is not None
return impl is not base
@@ -0,0 +1,100 @@
"""Checkpointer test registration and factory management."""
from __future__ import annotations
from collections.abc import AsyncGenerator, Callable
from contextlib import asynccontextmanager
from dataclasses import dataclass, field
from typing import Any
from langgraph.checkpoint.base import BaseCheckpointSaver
# Type for the lifespan async context manager factory.
LifespanFactory = Callable[[], AsyncGenerator[None, None]]
# Module-level registry of decorated checkpointer factories.
_REGISTRY: dict[str, RegisteredCheckpointer] = {}
async def _noop_lifespan() -> AsyncGenerator[None, None]:
yield
@dataclass
class RegisteredCheckpointer:
"""A registered checkpointer test factory."""
name: str
factory: Callable[[], AsyncGenerator[BaseCheckpointSaver, None]]
skip_capabilities: set[str] = field(default_factory=set)
lifespan: LifespanFactory = _noop_lifespan
@asynccontextmanager
async def create(self) -> AsyncGenerator[BaseCheckpointSaver, None]:
"""Create a fresh checkpointer instance via the async generator."""
gen = self.factory()
try:
saver = await gen.__anext__()
yield saver
finally:
try:
await gen.__anext__()
except StopAsyncIteration:
pass
@asynccontextmanager
async def enter_lifespan(self) -> AsyncGenerator[None, None]:
"""Enter the lifespan context (once per validation run)."""
gen = self.lifespan()
try:
await gen.__anext__()
yield
finally:
try:
await gen.__anext__()
except StopAsyncIteration:
pass
def checkpointer_test(
name: str,
*,
skip_capabilities: set[str] | None = None,
lifespan: LifespanFactory | None = None,
) -> Callable[[Any], RegisteredCheckpointer]:
"""Register an async generator as a checkpointer test factory.
The factory is called once per capability suite to create a fresh
checkpointer. The optional `lifespan` is an async generator that
runs once for the entire validation run (e.g. to create/destroy a
database).
Example::
@checkpointer_test(name="InMemorySaver")
async def memory_checkpointer():
yield InMemorySaver()
With lifespan::
async def pg_lifespan():
await create_database()
yield
await drop_database()
@checkpointer_test(name="PostgresSaver", lifespan=pg_lifespan)
async def pg_checkpointer():
yield PostgresSaver(conn_string="...")
"""
def decorator(fn: Any) -> RegisteredCheckpointer:
registered = RegisteredCheckpointer(
name=name,
factory=fn,
skip_capabilities=skip_capabilities or set(),
lifespan=lifespan or _noop_lifespan,
)
_REGISTRY[name] = registered
return registered
return decorator
@@ -0,0 +1,198 @@
"""Capability report: results, progress callbacks, and pretty-printing."""
from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass, field
from typing import Any
from langgraph.checkpoint.conformance.capabilities import (
BASE_CAPABILITIES,
EXTENDED_CAPABILITIES,
Capability,
)
# Callback type for per-test progress reporting.
# (capability_name, test_name, passed, error_msg_or_None) -> None
OnTestResult = Callable[[str, str, bool, str | None], None]
# Callback type for capability-level events.
# (capability_name, detected) -> None
OnCapabilityStart = Callable[[str, bool], None]
class ProgressCallbacks:
"""Grouped callbacks for progress reporting during validation."""
def __init__(
self,
*,
on_capability_start: Callable[[str, bool], None] | None = None,
on_test_result: OnTestResult | None = None,
on_capability_end: Callable[[str], None] | None = None,
) -> None:
self.on_capability_start = on_capability_start
self.on_test_result = on_test_result
self.on_capability_end = on_capability_end
@classmethod
def default(cls) -> ProgressCallbacks:
"""Dot-style progress: ``.`` per pass, ``F`` per fail."""
def _cap_start(capability: str, detected: bool) -> None:
if detected:
print(f" {capability}: ", end="", flush=True)
else:
print(f"{capability} (not implemented)")
def _test_result(
capability: str, test_name: str, passed: bool, error: str | None
) -> None:
print("." if passed else "F", end="", flush=True)
def _cap_end(capability: str) -> None:
print() # newline after dots
return cls(
on_capability_start=_cap_start,
on_test_result=_test_result,
on_capability_end=_cap_end,
)
@classmethod
def verbose(cls) -> ProgressCallbacks:
"""Per-test output with names and errors."""
def _cap_start(capability: str, detected: bool) -> None:
if detected:
print(f" {capability}:")
else:
print(f"{capability} (not implemented)")
def _test_result(
capability: str, test_name: str, passed: bool, error: str | None
) -> None:
icon = "" if passed else ""
print(f" {icon} {test_name}")
if error:
for line in error.rstrip().splitlines():
print(f" {line}")
return cls(
on_capability_start=_cap_start,
on_test_result=_test_result,
)
@classmethod
def quiet(cls) -> ProgressCallbacks:
"""No progress output."""
return cls()
@dataclass
class CapabilityResult:
"""Result of running a single capability's test suite."""
detected: bool = False
passed: bool | None = None # None = skipped
tests_passed: int = 0
tests_failed: int = 0
tests_skipped: int = 0
failures: list[str] = field(default_factory=list)
@dataclass
class CapabilityReport:
"""Aggregate report across all capabilities."""
checkpointer_name: str
results: dict[str, CapabilityResult] = field(default_factory=dict)
def passed_all_base(self) -> bool:
"""Whether all base capability tests passed."""
for cap in BASE_CAPABILITIES:
result = self.results.get(cap.value)
if result is None or result.passed is not True:
return False
return True
def passed_all(self) -> bool:
"""Whether every detected capability's tests passed."""
for result in self.results.values():
if result.detected and result.passed is not True:
return False
return True
def conformance_level(self) -> str:
"""Return a human-readable conformance level string."""
if self.passed_all():
return "FULL"
if self.passed_all_base():
return "BASE+PARTIAL"
return "BASE" if self._any_base_passed() else "NONE"
def _any_base_passed(self) -> bool:
for cap in BASE_CAPABILITIES:
result = self.results.get(cap.value)
if result and result.passed is True:
return True
return False
def print_report(self) -> None:
"""Pretty-print the report to stdout."""
width = 52
border = "=" * width
print(f"\n{'':>2}{border}")
print(f"{'':>2} Checkpointer Validation: {self.checkpointer_name}")
print(f"{'':>2}{border}")
def _section(title: str, caps: frozenset[Capability]) -> None:
print(f"{'':>2} {title}")
for cap in sorted(caps, key=lambda c: c.value):
result = self.results.get(cap.value)
if result is None:
icon = " "
suffix = "(no tests)"
elif not result.detected:
icon = ""
suffix = "(not implemented)"
elif result.passed is True:
icon = ""
suffix = ""
elif result.passed is False:
icon = ""
suffix = f"({result.tests_failed} failed)"
else:
icon = ""
suffix = "(skipped)"
print(f"{'':>2} {icon} {cap.value:20s} {suffix}")
print()
_section("BASE CAPABILITIES", BASE_CAPABILITIES)
_section("EXTENDED CAPABILITIES", EXTENDED_CAPABILITIES)
total = sum(1 for r in self.results.values() if r.detected)
passed = sum(
1 for r in self.results.values() if r.detected and r.passed is True
)
level = self.conformance_level()
print(f"{'':>2} Result: {level} ({passed}/{total})")
print(f"{'':>2}{border}\n")
def to_dict(self) -> dict[str, Any]:
"""Return a JSON-serializable dict."""
return {
"checkpointer_name": self.checkpointer_name,
"conformance_level": self.conformance_level(),
"results": {
name: {
"detected": r.detected,
"passed": r.passed,
"tests_passed": r.tests_passed,
"tests_failed": r.tests_failed,
"tests_skipped": r.tests_skipped,
"failures": r.failures,
}
for name, r in self.results.items()
},
}
@@ -0,0 +1,27 @@
"""Test spec modules for each checkpointer capability."""
from langgraph.checkpoint.conformance.spec.test_copy_thread import (
run_copy_thread_tests,
)
from langgraph.checkpoint.conformance.spec.test_delete_for_runs import (
run_delete_for_runs_tests,
)
from langgraph.checkpoint.conformance.spec.test_delete_thread import (
run_delete_thread_tests,
)
from langgraph.checkpoint.conformance.spec.test_get_tuple import run_get_tuple_tests
from langgraph.checkpoint.conformance.spec.test_list import run_list_tests
from langgraph.checkpoint.conformance.spec.test_prune import run_prune_tests
from langgraph.checkpoint.conformance.spec.test_put import run_put_tests
from langgraph.checkpoint.conformance.spec.test_put_writes import run_put_writes_tests
__all__ = [
"run_put_tests",
"run_put_writes_tests",
"run_get_tuple_tests",
"run_list_tests",
"run_delete_thread_tests",
"run_delete_for_runs_tests",
"run_copy_thread_tests",
"run_prune_tests",
]
@@ -0,0 +1,250 @@
"""COPY_THREAD capability tests — acopy_thread."""
from __future__ import annotations
import traceback
from collections.abc import Callable
from uuid import uuid4
from langgraph.checkpoint.base import BaseCheckpointSaver
from langgraph.checkpoint.conformance.test_utils import (
generate_checkpoint,
generate_config,
generate_metadata,
)
async def _setup_source_thread(
saver: BaseCheckpointSaver,
tid: str,
*,
n: int = 3,
namespaces: list[str] | None = None,
) -> list[dict]:
"""Create n checkpoints on tid (optionally across namespaces). Returns stored configs."""
nss = namespaces or [""]
stored = []
for ns in nss:
parent_cfg = None
for i in range(n):
config = generate_config(tid, checkpoint_ns=ns)
if parent_cfg:
config["configurable"]["checkpoint_id"] = parent_cfg["configurable"][
"checkpoint_id"
]
cp = generate_checkpoint(channel_values={"step": i})
cp["channel_versions"] = {"step": 1}
parent_cfg = await saver.aput(
config, cp, generate_metadata(step=i), {"step": 1}
)
stored.append(parent_cfg)
return stored
async def test_copy_thread_basic(saver: BaseCheckpointSaver) -> None:
"""Checkpoints appear on target thread."""
src = str(uuid4())
dst = str(uuid4())
await _setup_source_thread(saver, src)
await saver.acopy_thread(src, dst)
results = []
async for tup in saver.alist(generate_config(dst)):
results.append(tup)
assert len(results) == 3, f"Expected 3 copied checkpoints, got {len(results)}"
async def test_copy_thread_all_checkpoints(saver: BaseCheckpointSaver) -> None:
"""All checkpoints copied, not just latest."""
src = str(uuid4())
dst = str(uuid4())
await _setup_source_thread(saver, src, n=3)
await saver.acopy_thread(src, dst)
src_results = []
async for tup in saver.alist(generate_config(src)):
src_results.append(tup)
dst_results = []
async for tup in saver.alist(generate_config(dst)):
dst_results.append(tup)
assert len(dst_results) == len(src_results)
# Verify content matches
for s, d in zip(
sorted(src_results, key=lambda t: t.checkpoint["id"]),
sorted(dst_results, key=lambda t: t.checkpoint["id"]),
strict=True,
):
assert s.checkpoint["channel_values"] == d.checkpoint["channel_values"], (
f"channel_values mismatch for checkpoint {s.checkpoint['id']}"
)
async def test_copy_thread_preserves_metadata(
saver: BaseCheckpointSaver,
) -> None:
"""Metadata intact on copied checkpoints."""
src = str(uuid4())
dst = str(uuid4())
await _setup_source_thread(saver, src, n=2)
await saver.acopy_thread(src, dst)
src_tuples = []
async for tup in saver.alist(generate_config(src)):
src_tuples.append(tup)
dst_tuples = []
async for tup in saver.alist(generate_config(dst)):
dst_tuples.append(tup)
for s, d in zip(
sorted(src_tuples, key=lambda t: t.metadata.get("step", 0)),
sorted(dst_tuples, key=lambda t: t.metadata.get("step", 0)),
strict=True,
):
for key in s.metadata:
assert s.metadata.get(key) == d.metadata.get(key), (
f"metadata[{key!r}] mismatch: {s.metadata.get(key)!r} != {d.metadata.get(key)!r}"
)
async def test_copy_thread_preserves_namespaces(
saver: BaseCheckpointSaver,
) -> None:
"""Root + child namespaces copied."""
src = str(uuid4())
dst = str(uuid4())
await _setup_source_thread(saver, src, n=1, namespaces=["", "child:1"])
await saver.acopy_thread(src, dst)
for ns in ["", "child:1"]:
results = []
async for tup in saver.alist(generate_config(dst, checkpoint_ns=ns)):
results.append(tup)
assert len(results) == 1, (
f"Expected 1 checkpoint in namespace '{ns}', got {len(results)}"
)
async def test_copy_thread_preserves_writes(saver: BaseCheckpointSaver) -> None:
"""Pending writes copied."""
src = str(uuid4())
dst = str(uuid4())
configs = await _setup_source_thread(saver, src, n=1)
# Add a write to the source
await saver.aput_writes(configs[-1], [("ch", "write_val")], str(uuid4()))
await saver.acopy_thread(src, dst)
tup = await saver.aget_tuple(generate_config(dst))
assert tup is not None
assert tup.pending_writes is not None
assert len(tup.pending_writes) == 1, (
f"Expected 1 write, got {len(tup.pending_writes)}"
)
assert tup.pending_writes[0][1] == "ch", (
f"channel mismatch: {tup.pending_writes[0][1]!r}"
)
assert tup.pending_writes[0][2] == "write_val", (
f"value mismatch: {tup.pending_writes[0][2]!r}"
)
async def test_copy_thread_preserves_ordering(
saver: BaseCheckpointSaver,
) -> None:
"""Checkpoint order maintained."""
src = str(uuid4())
dst = str(uuid4())
await _setup_source_thread(saver, src, n=4)
await saver.acopy_thread(src, dst)
src_ids = []
async for tup in saver.alist(generate_config(src)):
src_ids.append(tup.checkpoint["id"])
dst_ids = []
async for tup in saver.alist(generate_config(dst)):
dst_ids.append(tup.checkpoint["id"])
# Order should match (both newest-first)
assert src_ids == dst_ids
async def test_copy_thread_source_unchanged(saver: BaseCheckpointSaver) -> None:
"""Source thread still intact after copy."""
src = str(uuid4())
dst = str(uuid4())
await _setup_source_thread(saver, src, n=2)
# Snapshot source before copy
src_before = []
async for tup in saver.alist(generate_config(src)):
src_before.append(tup.checkpoint["id"])
await saver.acopy_thread(src, dst)
# Source should be unchanged
src_after = []
async for tup in saver.alist(generate_config(src)):
src_after.append(tup.checkpoint["id"])
assert src_before == src_after
async def test_copy_thread_nonexistent_source(
saver: BaseCheckpointSaver,
) -> None:
"""Graceful handling of non-existent source thread."""
src = str(uuid4())
dst = str(uuid4())
# Should not raise (or raise a known error)
try:
await saver.acopy_thread(src, dst)
except Exception:
pass # Some implementations may raise; that's acceptable
# Destination should be empty
results = []
async for tup in saver.alist(generate_config(dst)):
results.append(tup)
assert len(results) == 0
ALL_COPY_THREAD_TESTS = [
test_copy_thread_basic,
test_copy_thread_all_checkpoints,
test_copy_thread_preserves_metadata,
test_copy_thread_preserves_namespaces,
test_copy_thread_preserves_writes,
test_copy_thread_preserves_ordering,
test_copy_thread_source_unchanged,
test_copy_thread_nonexistent_source,
]
async def run_copy_thread_tests(
saver: BaseCheckpointSaver,
on_test_result: Callable[[str, str, bool, str | None], None] | None = None,
) -> tuple[int, int, list[str]]:
"""Run all copy_thread tests. Returns (passed, failed, failure_names)."""
passed = 0
failed = 0
failures: list[str] = []
for test_fn in ALL_COPY_THREAD_TESTS:
try:
await test_fn(saver)
passed += 1
if on_test_result:
on_test_result("copy_thread", test_fn.__name__, True, None)
except Exception as e:
failed += 1
msg = f"{test_fn.__name__}: {e}"
failures.append(msg)
if on_test_result:
on_test_result(
"copy_thread", test_fn.__name__, False, traceback.format_exc()
)
return passed, failed, failures
@@ -0,0 +1,218 @@
"""DELETE_FOR_RUNS capability tests — adelete_for_runs."""
from __future__ import annotations
import traceback
from collections.abc import Callable
from uuid import uuid4
from langgraph.checkpoint.base import BaseCheckpointSaver
from langgraph.checkpoint.conformance.test_utils import (
generate_checkpoint,
generate_config,
generate_metadata,
)
async def _put_with_run_id(
saver: BaseCheckpointSaver,
tid: str,
run_id: str,
*,
checkpoint_ns: str = "",
parent_config: dict | None = None,
) -> dict:
"""Put a checkpoint with a run_id in metadata, return stored config."""
config = generate_config(tid, checkpoint_ns=checkpoint_ns)
if parent_config:
config["configurable"]["checkpoint_id"] = parent_config["configurable"][
"checkpoint_id"
]
cp = generate_checkpoint()
md = generate_metadata(run_id=run_id)
return await saver.aput(config, cp, md, {})
async def test_delete_for_runs_single(saver: BaseCheckpointSaver) -> None:
"""One run_id removed."""
tid = str(uuid4())
run1, run2 = str(uuid4()), str(uuid4())
stored1 = await _put_with_run_id(saver, tid, run1)
await _put_with_run_id(saver, tid, run2, parent_config=stored1)
# Pre-delete: verify both runs exist
pre_results = []
async for tup in saver.alist(generate_config(tid)):
pre_results.append(tup)
pre_run_ids = {t.metadata.get("run_id") for t in pre_results}
assert run1 in pre_run_ids, "Pre-delete: run1 should exist"
assert run2 in pre_run_ids, "Pre-delete: run2 should exist"
await saver.adelete_for_runs([run1])
# run1's checkpoint should be gone; run2 should remain
results = []
async for tup in saver.alist(generate_config(tid)):
results.append(tup)
run_ids = {t.metadata.get("run_id") for t in results}
assert run1 not in run_ids
assert run2 in run_ids
async def test_delete_for_runs_multiple(saver: BaseCheckpointSaver) -> None:
"""List of run_ids removed."""
tid = str(uuid4())
run1, run2, run3 = str(uuid4()), str(uuid4()), str(uuid4())
s1 = await _put_with_run_id(saver, tid, run1)
s2 = await _put_with_run_id(saver, tid, run2, parent_config=s1)
await _put_with_run_id(saver, tid, run3, parent_config=s2)
# Pre-delete: verify all 3 runs exist
pre_results = []
async for tup in saver.alist(generate_config(tid)):
pre_results.append(tup)
pre_run_ids = {t.metadata.get("run_id") for t in pre_results}
assert run1 in pre_run_ids, "Pre-delete: run1 should exist"
assert run2 in pre_run_ids, "Pre-delete: run2 should exist"
assert run3 in pre_run_ids, "Pre-delete: run3 should exist"
await saver.adelete_for_runs([run1, run2])
results = []
async for tup in saver.alist(generate_config(tid)):
results.append(tup)
run_ids = {t.metadata.get("run_id") for t in results}
assert run1 not in run_ids
assert run2 not in run_ids
assert run3 in run_ids
async def test_delete_for_runs_preserves_other_runs(
saver: BaseCheckpointSaver,
) -> None:
"""Unrelated runs untouched."""
tid = str(uuid4())
run_keep = str(uuid4())
run_delete = str(uuid4())
await _put_with_run_id(saver, tid, run_keep)
await _put_with_run_id(saver, tid, run_delete)
# Pre-delete: verify both runs exist
pre_results = []
async for tup in saver.alist(generate_config(tid)):
pre_results.append(tup)
pre_run_ids = {t.metadata.get("run_id") for t in pre_results}
assert run_keep in pre_run_ids, "Pre-delete: run_keep should exist"
assert run_delete in pre_run_ids, "Pre-delete: run_delete should exist"
await saver.adelete_for_runs([run_delete])
results = []
async for tup in saver.alist(generate_config(tid)):
results.append(tup)
run_ids = {t.metadata.get("run_id") for t in results}
assert run_keep in run_ids
async def test_delete_for_runs_removes_writes(
saver: BaseCheckpointSaver,
) -> None:
"""Associated writes cleaned up."""
tid = str(uuid4())
run1 = str(uuid4())
stored = await _put_with_run_id(saver, tid, run1)
await saver.aput_writes(stored, [("ch", "val")], str(uuid4()))
# Pre-delete: verify writes exist
pre_tup = await saver.aget_tuple(stored)
assert pre_tup is not None, "Pre-delete: checkpoint should exist"
assert pre_tup.pending_writes is not None and len(pre_tup.pending_writes) == 1, (
f"Pre-delete: expected 1 write, got {len(pre_tup.pending_writes) if pre_tup.pending_writes else 0}"
)
await saver.adelete_for_runs([run1])
# The checkpoint (and its writes) should be gone
tup = await saver.aget_tuple(stored)
assert tup is None
async def test_delete_for_runs_empty_list_noop(
saver: BaseCheckpointSaver,
) -> None:
"""Empty list no error."""
await saver.adelete_for_runs([])
async def test_delete_for_runs_nonexistent_noop(
saver: BaseCheckpointSaver,
) -> None:
"""Missing run_ids no error."""
await saver.adelete_for_runs([str(uuid4())])
async def test_delete_for_runs_across_namespaces(
saver: BaseCheckpointSaver,
) -> None:
"""All namespaces cleaned."""
tid = str(uuid4())
run1 = str(uuid4())
await _put_with_run_id(saver, tid, run1, checkpoint_ns="")
await _put_with_run_id(saver, tid, run1, checkpoint_ns="child:1")
# Pre-delete: verify run1 present in both namespaces
for ns in ["", "child:1"]:
pre_results = []
async for tup in saver.alist(generate_config(tid, checkpoint_ns=ns)):
pre_results.append(tup)
pre_run_ids = {t.metadata.get("run_id") for t in pre_results}
assert run1 in pre_run_ids, f"Pre-delete: run1 should exist in ns='{ns}'"
await saver.adelete_for_runs([run1])
for ns in ["", "child:1"]:
results = []
async for tup in saver.alist(generate_config(tid, checkpoint_ns=ns)):
results.append(tup)
run_ids = {t.metadata.get("run_id") for t in results}
assert run1 not in run_ids
ALL_DELETE_FOR_RUNS_TESTS = [
test_delete_for_runs_single,
test_delete_for_runs_multiple,
test_delete_for_runs_preserves_other_runs,
test_delete_for_runs_removes_writes,
test_delete_for_runs_empty_list_noop,
test_delete_for_runs_nonexistent_noop,
test_delete_for_runs_across_namespaces,
]
async def run_delete_for_runs_tests(
saver: BaseCheckpointSaver,
on_test_result: Callable[[str, str, bool, str | None], None] | None = None,
) -> tuple[int, int, list[str]]:
"""Run all delete_for_runs tests. Returns (passed, failed, failure_names)."""
passed = 0
failed = 0
failures: list[str] = []
for test_fn in ALL_DELETE_FOR_RUNS_TESTS:
try:
await test_fn(saver)
passed += 1
if on_test_result:
on_test_result("delete_for_runs", test_fn.__name__, True, None)
except Exception as e:
failed += 1
msg = f"{test_fn.__name__}: {e}"
failures.append(msg)
if on_test_result:
on_test_result(
"delete_for_runs", test_fn.__name__, False, traceback.format_exc()
)
return passed, failed, failures
@@ -0,0 +1,149 @@
"""DELETE_THREAD capability tests — adelete_thread."""
from __future__ import annotations
import traceback
from collections.abc import Callable
from uuid import uuid4
from langgraph.checkpoint.base import BaseCheckpointSaver
from langgraph.checkpoint.conformance.test_utils import (
generate_checkpoint,
generate_config,
generate_metadata,
)
async def test_delete_thread_removes_checkpoints(
saver: BaseCheckpointSaver,
) -> None:
"""All checkpoints gone after delete."""
tid = str(uuid4())
parent_cfg = None
for i in range(3):
config = generate_config(tid)
if parent_cfg:
config["configurable"]["checkpoint_id"] = parent_cfg["configurable"][
"checkpoint_id"
]
cp = generate_checkpoint()
parent_cfg = await saver.aput(config, cp, generate_metadata(step=i), {})
# Pre-delete: verify data exists
assert await saver.aget_tuple(generate_config(tid)) is not None, (
"Pre-delete: checkpoint should exist"
)
await saver.adelete_thread(tid)
tup = await saver.aget_tuple(generate_config(tid))
assert tup is None
results = []
async for t in saver.alist(generate_config(tid)):
results.append(t)
assert len(results) == 0
async def test_delete_thread_removes_writes(saver: BaseCheckpointSaver) -> None:
"""Pending writes gone after delete."""
tid = str(uuid4())
config = generate_config(tid)
cp = generate_checkpoint()
stored = await saver.aput(config, cp, generate_metadata(), {})
await saver.aput_writes(stored, [("ch", "val")], str(uuid4()))
# Pre-delete: verify writes exist
pre_tup = await saver.aget_tuple(generate_config(tid))
assert pre_tup is not None, "Pre-delete: checkpoint should exist"
assert pre_tup.pending_writes is not None and len(pre_tup.pending_writes) == 1, (
f"Pre-delete: expected 1 write, got {len(pre_tup.pending_writes) if pre_tup.pending_writes else 0}"
)
await saver.adelete_thread(tid)
tup = await saver.aget_tuple(generate_config(tid))
assert tup is None
async def test_delete_thread_removes_all_namespaces(
saver: BaseCheckpointSaver,
) -> None:
"""Root + child namespaces both removed."""
tid = str(uuid4())
for ns in ["", "child:1"]:
cfg = generate_config(tid, checkpoint_ns=ns)
cp = generate_checkpoint()
await saver.aput(cfg, cp, generate_metadata(), {})
# Pre-delete: verify each namespace has data
for ns in ["", "child:1"]:
pre = await saver.aget_tuple(generate_config(tid, checkpoint_ns=ns))
assert pre is not None, f"Pre-delete: namespace '{ns}' should have data"
await saver.adelete_thread(tid)
for ns in ["", "child:1"]:
tup = await saver.aget_tuple(generate_config(tid, checkpoint_ns=ns))
assert tup is None
async def test_delete_thread_preserves_other_threads(
saver: BaseCheckpointSaver,
) -> None:
"""Other threads untouched."""
tid1, tid2 = str(uuid4()), str(uuid4())
for tid in (tid1, tid2):
cfg = generate_config(tid)
cp = generate_checkpoint()
await saver.aput(cfg, cp, generate_metadata(), {})
await saver.adelete_thread(tid1)
assert await saver.aget_tuple(generate_config(tid1)) is None
assert await saver.aget_tuple(generate_config(tid2)) is not None
async def test_delete_thread_nonexistent_noop(
saver: BaseCheckpointSaver,
) -> None:
"""No error for missing thread."""
# Should not raise
await saver.adelete_thread(str(uuid4()))
ALL_DELETE_THREAD_TESTS = [
test_delete_thread_removes_checkpoints,
test_delete_thread_removes_writes,
test_delete_thread_removes_all_namespaces,
test_delete_thread_preserves_other_threads,
test_delete_thread_nonexistent_noop,
]
async def run_delete_thread_tests(
saver: BaseCheckpointSaver,
on_test_result: Callable[[str, str, bool, str | None], None] | None = None,
) -> tuple[int, int, list[str]]:
"""Run all delete_thread tests. Returns (passed, failed, failure_names)."""
passed = 0
failed = 0
failures: list[str] = []
for test_fn in ALL_DELETE_THREAD_TESTS:
try:
await test_fn(saver)
passed += 1
if on_test_result:
on_test_result("delete_thread", test_fn.__name__, True, None)
except Exception as e:
failed += 1
msg = f"{test_fn.__name__}: {e}"
failures.append(msg)
if on_test_result:
on_test_result(
"delete_thread", test_fn.__name__, False, traceback.format_exc()
)
return passed, failed, failures
@@ -0,0 +1,253 @@
"""GET_TUPLE capability tests — aget_tuple retrieval."""
from __future__ import annotations
import traceback
from collections.abc import Callable
from uuid import uuid4
from langgraph.checkpoint.base import BaseCheckpointSaver
from langgraph.checkpoint.conformance.test_utils import (
generate_checkpoint,
generate_config,
generate_metadata,
)
async def test_get_tuple_nonexistent_returns_none(
saver: BaseCheckpointSaver,
) -> None:
"""Missing thread returns None."""
config = generate_config(str(uuid4()))
tup = await saver.aget_tuple(config)
assert tup is None
async def test_get_tuple_latest_when_no_checkpoint_id(
saver: BaseCheckpointSaver,
) -> None:
"""Returns newest checkpoint when no checkpoint_id in config."""
tid = str(uuid4())
ids = []
parent_cfg = None
for i in range(3):
config = generate_config(tid)
if parent_cfg:
config["configurable"]["checkpoint_id"] = parent_cfg["configurable"][
"checkpoint_id"
]
cp = generate_checkpoint()
parent_cfg = await saver.aput(config, cp, generate_metadata(step=i), {})
ids.append(cp["id"])
# Get without checkpoint_id — should return the latest
tup = await saver.aget_tuple(generate_config(tid))
assert tup is not None
assert tup.checkpoint["id"] == ids[-1]
assert tup.metadata["step"] == 2, (
f"Expected latest step=2, got {tup.metadata['step']}"
)
async def test_get_tuple_specific_checkpoint_id(
saver: BaseCheckpointSaver,
) -> None:
"""Returns exact match when checkpoint_id specified."""
tid = str(uuid4())
config1 = generate_config(tid)
cp1 = generate_checkpoint()
stored1 = await saver.aput(config1, cp1, generate_metadata(step=0), {})
config2 = generate_config(tid)
config2["configurable"]["checkpoint_id"] = stored1["configurable"]["checkpoint_id"]
cp2 = generate_checkpoint()
await saver.aput(config2, cp2, generate_metadata(step=1), {})
# Fetch the first one specifically
tup = await saver.aget_tuple(stored1)
assert tup is not None
assert tup.checkpoint["id"] == cp1["id"]
async def test_get_tuple_config_structure(saver: BaseCheckpointSaver) -> None:
"""tuple.config has thread_id, checkpoint_ns, checkpoint_id."""
tid = str(uuid4())
config = generate_config(tid)
cp = generate_checkpoint()
stored = await saver.aput(config, cp, generate_metadata(), {})
tup = await saver.aget_tuple(stored)
assert tup is not None
conf = tup.config["configurable"]
assert conf["thread_id"] == tid
assert conf.get("checkpoint_ns", "") == "", (
f"Expected checkpoint_ns='', got {conf.get('checkpoint_ns')!r}"
)
assert conf["checkpoint_id"] == cp["id"]
async def test_get_tuple_checkpoint_fields(saver: BaseCheckpointSaver) -> None:
"""All Checkpoint fields present."""
tid = str(uuid4())
config = generate_config(tid)
cp = generate_checkpoint(channel_values={"k": "v"})
cp["channel_versions"] = {"k": 1}
stored = await saver.aput(config, cp, generate_metadata(), {"k": 1})
tup = await saver.aget_tuple(stored)
assert tup is not None
c = tup.checkpoint
assert c["id"] == cp["id"], f"id mismatch: {c['id']!r} != {cp['id']!r}"
assert c["v"] == 1, f"Expected v=1, got {c['v']!r}"
assert "ts" in c and c["ts"], "ts should be non-empty"
assert c["channel_values"] == {"k": "v"}, f"channel_values: {c['channel_values']!r}"
assert "channel_versions" in c
assert "versions_seen" in c
async def test_get_tuple_metadata(saver: BaseCheckpointSaver) -> None:
"""metadata populated correctly."""
tid = str(uuid4())
config = generate_config(tid)
cp = generate_checkpoint()
md = generate_metadata(source="input", step=-1)
stored = await saver.aput(config, cp, md, {})
tup = await saver.aget_tuple(stored)
assert tup is not None
assert tup.metadata["source"] == "input"
assert tup.metadata["step"] == -1
async def test_get_tuple_parent_config(saver: BaseCheckpointSaver) -> None:
"""parent_config when parent exists, None otherwise."""
tid = str(uuid4())
# First checkpoint — no parent
config1 = generate_config(tid)
cp1 = generate_checkpoint()
stored1 = await saver.aput(config1, cp1, generate_metadata(step=0), {})
tup1 = await saver.aget_tuple(stored1)
assert tup1 is not None
assert tup1.parent_config is None
# Second checkpoint — has parent
config2 = generate_config(tid)
config2["configurable"]["checkpoint_id"] = stored1["configurable"]["checkpoint_id"]
cp2 = generate_checkpoint()
stored2 = await saver.aput(config2, cp2, generate_metadata(step=1), {})
tup2 = await saver.aget_tuple(stored2)
assert tup2 is not None
assert tup2.parent_config is not None
assert (
tup2.parent_config["configurable"]["checkpoint_id"]
== stored1["configurable"]["checkpoint_id"]
)
async def test_get_tuple_pending_writes(saver: BaseCheckpointSaver) -> None:
"""pending_writes from put_writes visible."""
tid = str(uuid4())
config = generate_config(tid)
cp = generate_checkpoint()
stored = await saver.aput(config, cp, generate_metadata(), {})
task_id = str(uuid4())
await saver.aput_writes(stored, [("ch", "val")], task_id)
tup = await saver.aget_tuple(stored)
assert tup is not None
assert tup.pending_writes is not None
assert len(tup.pending_writes) == 1, (
f"Expected 1 write, got {len(tup.pending_writes)}"
)
assert tup.pending_writes[0][0] == task_id, (
f"task_id mismatch: {tup.pending_writes[0][0]!r}"
)
assert tup.pending_writes[0][1] == "ch", (
f"channel mismatch: {tup.pending_writes[0][1]!r}"
)
assert tup.pending_writes[0][2] == "val", (
f"value mismatch: {tup.pending_writes[0][2]!r}"
)
async def test_get_tuple_respects_namespace(saver: BaseCheckpointSaver) -> None:
"""checkpoint_ns filtering."""
tid = str(uuid4())
cfg_root = generate_config(tid, checkpoint_ns="")
cp_root = generate_checkpoint()
stored_root = await saver.aput(cfg_root, cp_root, generate_metadata(), {})
cfg_child = generate_config(tid, checkpoint_ns="child:1")
cp_child = generate_checkpoint()
stored_child = await saver.aput(cfg_child, cp_child, generate_metadata(), {})
tup_root = await saver.aget_tuple(stored_root)
assert tup_root is not None
assert tup_root.checkpoint["id"] == cp_root["id"]
tup_child = await saver.aget_tuple(stored_child)
assert tup_child is not None
assert tup_child.checkpoint["id"] == cp_child["id"]
async def test_get_tuple_nonexistent_checkpoint_id(
saver: BaseCheckpointSaver,
) -> None:
"""Specific but missing checkpoint_id returns None."""
tid = str(uuid4())
nonexistent_id = str(uuid4())
# Put one checkpoint so the thread exists
config = generate_config(tid)
cp = generate_checkpoint()
await saver.aput(config, cp, generate_metadata(), {})
# Ask for a non-existent checkpoint_id
bad_cfg = generate_config(tid, checkpoint_id=nonexistent_id)
tup = await saver.aget_tuple(bad_cfg)
assert tup is None
ALL_GET_TUPLE_TESTS = [
test_get_tuple_nonexistent_returns_none,
test_get_tuple_latest_when_no_checkpoint_id,
test_get_tuple_specific_checkpoint_id,
test_get_tuple_config_structure,
test_get_tuple_checkpoint_fields,
test_get_tuple_metadata,
test_get_tuple_parent_config,
test_get_tuple_pending_writes,
test_get_tuple_respects_namespace,
test_get_tuple_nonexistent_checkpoint_id,
]
async def run_get_tuple_tests(
saver: BaseCheckpointSaver,
on_test_result: Callable[[str, str, bool, str | None], None] | None = None,
) -> tuple[int, int, list[str]]:
"""Run all get_tuple tests. Returns (passed, failed, failure_names)."""
passed = 0
failed = 0
failures: list[str] = []
for test_fn in ALL_GET_TUPLE_TESTS:
try:
await test_fn(saver)
passed += 1
if on_test_result:
on_test_result("get_tuple", test_fn.__name__, True, None)
except Exception as e:
failed += 1
msg = f"{test_fn.__name__}: {e}"
failures.append(msg)
if on_test_result:
on_test_result(
"get_tuple", test_fn.__name__, False, traceback.format_exc()
)
return passed, failed, failures
@@ -0,0 +1,414 @@
"""LIST capability tests — alist with various filters."""
from __future__ import annotations
import traceback
from collections.abc import Callable
from uuid import uuid4
from langgraph.checkpoint.base import BaseCheckpointSaver
from langgraph.checkpoint.conformance.test_utils import (
generate_checkpoint,
generate_config,
generate_metadata,
)
async def _setup_list_data(saver: BaseCheckpointSaver) -> dict:
"""Populate saver with test data for list tests. Returns lookup info."""
tid = str(uuid4())
ids = []
parent_cfg = None
for i in range(4):
config = generate_config(tid)
if parent_cfg:
config["configurable"]["checkpoint_id"] = parent_cfg["configurable"][
"checkpoint_id"
]
cp = generate_checkpoint()
source = "input" if i % 2 == 0 else "loop"
md = generate_metadata(source=source, step=i)
parent_cfg = await saver.aput(config, cp, md, {})
ids.append(cp["id"])
return {
"thread_id": tid,
"checkpoint_ids": ids,
"latest_config": parent_cfg,
}
async def test_list_all(saver: BaseCheckpointSaver) -> None:
"""No filters returns all checkpoints for the thread."""
data = await _setup_list_data(saver)
tid = data["thread_id"]
results = []
async for tup in saver.alist(generate_config(tid)):
results.append(tup)
assert len(results) == 4
async def test_list_by_thread(saver: BaseCheckpointSaver) -> None:
"""Filter by thread_id — other threads not returned."""
data = await _setup_list_data(saver)
# List for a non-existent thread
results = []
async for tup in saver.alist(generate_config(str(uuid4()))):
results.append(tup)
assert len(results) == 0
# List for actual thread
results = []
async for tup in saver.alist(generate_config(data["thread_id"])):
results.append(tup)
assert len(results) == 4
async def test_list_by_namespace(saver: BaseCheckpointSaver) -> None:
"""Filter by checkpoint_ns."""
tid = str(uuid4())
# Root namespace
cfg1 = generate_config(tid, checkpoint_ns="")
cp1 = generate_checkpoint()
await saver.aput(cfg1, cp1, generate_metadata(), {})
# Child namespace
cfg2 = generate_config(tid, checkpoint_ns="child:1")
cp2 = generate_checkpoint()
await saver.aput(cfg2, cp2, generate_metadata(), {})
root_results = []
async for tup in saver.alist(generate_config(tid, checkpoint_ns="")):
root_results.append(tup)
assert len(root_results) == 1
child_results = []
async for tup in saver.alist(generate_config(tid, checkpoint_ns="child:1")):
child_results.append(tup)
assert len(child_results) == 1
async def test_list_ordering(saver: BaseCheckpointSaver) -> None:
"""Newest first (descending checkpoint_id)."""
data = await _setup_list_data(saver)
ids = data["checkpoint_ids"]
results = []
async for tup in saver.alist(generate_config(data["thread_id"])):
results.append(tup.checkpoint["id"])
# Should be in reverse order (newest first)
assert results == list(reversed(ids))
async def test_list_metadata_filter_single_key(
saver: BaseCheckpointSaver,
) -> None:
"""filter={'source': 'input'} returns only input checkpoints."""
data = await _setup_list_data(saver)
results = []
async for tup in saver.alist(
generate_config(data["thread_id"]),
filter={"source": "input"},
):
results.append(tup)
assert len(results) == 2, (
f"Expected 2 'input' checkpoints (steps 0,2), got {len(results)}"
)
for tup in results:
assert tup.metadata["source"] == "input"
async def test_list_metadata_filter_step(saver: BaseCheckpointSaver) -> None:
"""filter={'step': 1} returns matching checkpoints."""
data = await _setup_list_data(saver)
results = []
async for tup in saver.alist(
generate_config(data["thread_id"]),
filter={"step": 1},
):
results.append(tup)
assert len(results) == 1
assert results[0].metadata["step"] == 1
async def test_list_before(saver: BaseCheckpointSaver) -> None:
"""Pagination cursor — only checkpoints before the given one."""
data = await _setup_list_data(saver)
ids = data["checkpoint_ids"]
# Use the 3rd checkpoint as the 'before' cursor (index 2)
before_cfg = generate_config(data["thread_id"], checkpoint_id=ids[2])
results = []
async for tup in saver.alist(
generate_config(data["thread_id"]),
before=before_cfg,
):
results.append(tup)
# Should only include checkpoints before ids[2]
result_ids = [t.checkpoint["id"] for t in results]
assert ids[2] not in result_ids
assert ids[3] not in result_ids
assert set(result_ids) == {ids[0], ids[1]}, (
f"Expected {{ids[0], ids[1]}}, got {set(result_ids)}"
)
async def test_list_limit(saver: BaseCheckpointSaver) -> None:
"""limit=1, limit=N."""
data = await _setup_list_data(saver)
results = []
async for tup in saver.alist(generate_config(data["thread_id"]), limit=1):
results.append(tup)
assert len(results) == 1
results = []
async for tup in saver.alist(generate_config(data["thread_id"]), limit=2):
results.append(tup)
assert len(results) == 2
async def test_list_limit_plus_before(saver: BaseCheckpointSaver) -> None:
"""Pagination with limit."""
data = await _setup_list_data(saver)
ids = data["checkpoint_ids"]
before_cfg = generate_config(data["thread_id"], checkpoint_id=ids[3])
results = []
async for tup in saver.alist(
generate_config(data["thread_id"]),
before=before_cfg,
limit=1,
):
results.append(tup)
assert len(results) == 1
assert results[0].checkpoint["id"] == ids[2]
async def test_list_combined_thread_and_filter(
saver: BaseCheckpointSaver,
) -> None:
"""thread_id + metadata filter combined."""
data = await _setup_list_data(saver)
results = []
async for tup in saver.alist(
generate_config(data["thread_id"]),
filter={"source": "loop"},
):
results.append(tup)
assert len(results) == 2, (
f"Expected 2 'loop' checkpoints (steps 1,3), got {len(results)}"
)
for tup in results:
assert tup.metadata["source"] == "loop"
async def test_list_empty_result(saver: BaseCheckpointSaver) -> None:
"""No matches returns empty."""
results = []
async for tup in saver.alist(
generate_config(str(uuid4())),
filter={"source": "nonexistent"},
):
results.append(tup)
assert len(results) == 0
async def test_list_includes_pending_writes(saver: BaseCheckpointSaver) -> None:
"""pending_writes in listed tuples."""
tid = str(uuid4())
config = generate_config(tid)
cp = generate_checkpoint()
stored = await saver.aput(config, cp, generate_metadata(), {})
await saver.aput_writes(stored, [("ch", "val")], str(uuid4()))
results = []
async for tup in saver.alist(generate_config(tid)):
results.append(tup)
assert len(results) == 1
assert results[0].pending_writes is not None
assert len(results[0].pending_writes) == 1, (
f"Expected 1 write, got {len(results[0].pending_writes)}"
)
assert results[0].pending_writes[0][1] == "ch", (
f"channel mismatch: {results[0].pending_writes[0][1]!r}"
)
assert results[0].pending_writes[0][2] == "val", (
f"value mismatch: {results[0].pending_writes[0][2]!r}"
)
async def test_list_multiple_namespaces(saver: BaseCheckpointSaver) -> None:
"""Root namespace checkpoint listed correctly."""
tid = str(uuid4())
for ns in ["", "child:1", "child:2"]:
cfg = generate_config(tid, checkpoint_ns=ns)
cp = generate_checkpoint()
await saver.aput(cfg, cp, generate_metadata(), {})
# List with root namespace filter — should return exactly the root checkpoint
results = []
async for tup in saver.alist(generate_config(tid, checkpoint_ns="")):
results.append(tup)
assert len(results) == 1, f"Expected 1 root checkpoint, got {len(results)}"
async def test_list_metadata_filter_multiple_keys(
saver: BaseCheckpointSaver,
) -> None:
"""filter with multiple keys — all must match."""
tid = str(uuid4())
# Create checkpoints with different metadata combos
for source, step in [("input", 1), ("loop", 1), ("input", 2)]:
cfg = generate_config(tid)
cp = generate_checkpoint()
await saver.aput(cfg, cp, generate_metadata(source=source, step=step), {})
results = []
async for tup in saver.alist(
generate_config(tid),
filter={"source": "input", "step": 2},
):
results.append(tup)
assert len(results) == 1, (
f"Expected 1 match for source=input+step=2, got {len(results)}"
)
assert results[0].metadata["source"] == "input"
assert results[0].metadata["step"] == 2
async def test_list_metadata_filter_no_match(
saver: BaseCheckpointSaver,
) -> None:
"""Multi-key filter that matches nothing returns empty."""
data = await _setup_list_data(saver)
results = []
async for tup in saver.alist(
generate_config(data["thread_id"]),
filter={"source": "update", "step": 99},
):
results.append(tup)
assert len(results) == 0
async def test_list_metadata_custom_keys(
saver: BaseCheckpointSaver,
) -> None:
"""Custom (non-standard) metadata keys are filterable."""
tid = str(uuid4())
cfg = generate_config(tid)
cp = generate_checkpoint()
await saver.aput(cfg, cp, generate_metadata(score=42, run_id="run-abc"), {})
cfg2 = generate_config(tid)
cp2 = generate_checkpoint()
await saver.aput(cfg2, cp2, generate_metadata(score=99, run_id="run-xyz"), {})
# Filter by custom key
results = []
async for tup in saver.alist(
generate_config(tid),
filter={"score": 42},
):
results.append(tup)
assert len(results) == 1
assert results[0].metadata["score"] == 42
assert results[0].metadata["run_id"] == "run-abc"
async def test_list_global_search(
saver: BaseCheckpointSaver,
) -> None:
"""alist(None, filter=...) searches across all threads."""
tid1, tid2 = str(uuid4()), str(uuid4())
# Use a unique marker so we don't collide with other tests' data
marker = str(uuid4())
cfg1 = generate_config(tid1)
cp1 = generate_checkpoint()
await saver.aput(cfg1, cp1, generate_metadata(source="input", marker=marker), {})
cfg2 = generate_config(tid2)
cp2 = generate_checkpoint()
await saver.aput(cfg2, cp2, generate_metadata(source="loop", marker=marker), {})
# Search across all threads with filter
results = []
async for tup in saver.alist(None, filter={"source": "input", "marker": marker}):
results.append(tup)
assert len(results) == 1
assert results[0].config["configurable"]["thread_id"] == tid1
# Search with marker only — should find both
results = []
async for tup in saver.alist(None, filter={"marker": marker}):
results.append(tup)
assert len(results) == 2
ALL_LIST_TESTS = [
test_list_all,
test_list_by_thread,
test_list_by_namespace,
test_list_ordering,
test_list_metadata_filter_single_key,
test_list_metadata_filter_step,
test_list_metadata_filter_multiple_keys,
test_list_metadata_filter_no_match,
test_list_metadata_custom_keys,
test_list_global_search,
test_list_before,
test_list_limit,
test_list_limit_plus_before,
test_list_combined_thread_and_filter,
test_list_empty_result,
test_list_includes_pending_writes,
test_list_multiple_namespaces,
]
async def run_list_tests(
saver: BaseCheckpointSaver,
on_test_result: Callable[[str, str, bool, str | None], None] | None = None,
) -> tuple[int, int, list[str]]:
"""Run all list tests. Returns (passed, failed, failure_names)."""
passed = 0
failed = 0
failures: list[str] = []
for test_fn in ALL_LIST_TESTS:
try:
await test_fn(saver)
passed += 1
if on_test_result:
on_test_result("list", test_fn.__name__, True, None)
except Exception as e:
failed += 1
msg = f"{test_fn.__name__}: {e}"
failures.append(msg)
if on_test_result:
on_test_result("list", test_fn.__name__, False, traceback.format_exc())
return passed, failed, failures
@@ -0,0 +1,217 @@
"""PRUNE capability tests — aprune(strategy)."""
from __future__ import annotations
import traceback
from collections.abc import Callable
from uuid import uuid4
from langgraph.checkpoint.base import BaseCheckpointSaver
from langgraph.checkpoint.conformance.test_utils import (
generate_checkpoint,
generate_config,
generate_metadata,
)
async def _setup_thread(saver: BaseCheckpointSaver, tid: str, n: int = 3) -> list[dict]:
"""Create n checkpoints on tid. Returns stored configs."""
stored = []
parent_cfg = None
for i in range(n):
config = generate_config(tid)
if parent_cfg:
config["configurable"]["checkpoint_id"] = parent_cfg["configurable"][
"checkpoint_id"
]
cp = generate_checkpoint()
parent_cfg = await saver.aput(config, cp, generate_metadata(step=i), {})
stored.append(parent_cfg)
return stored
async def test_prune_keep_latest_single_thread(
saver: BaseCheckpointSaver,
) -> None:
"""Only latest checkpoint survives."""
tid = str(uuid4())
configs = await _setup_thread(saver, tid, n=4)
await saver.aprune([tid], strategy="keep_latest")
results = []
async for tup in saver.alist(generate_config(tid)):
results.append(tup)
assert len(results) == 1
assert (
results[0].config["configurable"]["checkpoint_id"]
== configs[-1]["configurable"]["checkpoint_id"]
)
async def test_prune_keep_latest_multiple_threads(
saver: BaseCheckpointSaver,
) -> None:
"""Each thread keeps its latest."""
tid1, tid2 = str(uuid4()), str(uuid4())
c1 = await _setup_thread(saver, tid1, n=3)
c2 = await _setup_thread(saver, tid2, n=2)
await saver.aprune([tid1, tid2], strategy="keep_latest")
for tid, expected_last in [(tid1, c1[-1]), (tid2, c2[-1])]:
results = []
async for tup in saver.alist(generate_config(tid)):
results.append(tup)
assert len(results) == 1
assert (
results[0].config["configurable"]["checkpoint_id"]
== expected_last["configurable"]["checkpoint_id"]
)
async def test_prune_keep_latest_across_namespaces(
saver: BaseCheckpointSaver,
) -> None:
"""Latest per namespace kept."""
tid = str(uuid4())
# Root namespace: 3 checkpoints
parent = None
for i in range(3):
cfg = generate_config(tid, checkpoint_ns="")
if parent:
cfg["configurable"]["checkpoint_id"] = parent["configurable"][
"checkpoint_id"
]
cp = generate_checkpoint()
parent = await saver.aput(cfg, cp, generate_metadata(step=i), {})
root_latest = parent
# Child namespace: 2 checkpoints
parent = None
for i in range(2):
cfg = generate_config(tid, checkpoint_ns="child:1")
if parent:
cfg["configurable"]["checkpoint_id"] = parent["configurable"][
"checkpoint_id"
]
cp = generate_checkpoint()
parent = await saver.aput(cfg, cp, generate_metadata(step=i), {})
child_latest = parent
assert root_latest is not None
assert child_latest is not None
await saver.aprune([tid], strategy="keep_latest")
for ns, expected in [("", root_latest), ("child:1", child_latest)]:
results = []
async for tup in saver.alist(generate_config(tid, checkpoint_ns=ns)):
results.append(tup)
assert len(results) == 1
assert (
results[0].config["configurable"]["checkpoint_id"]
== expected["configurable"]["checkpoint_id"]
)
async def test_prune_keep_latest_preserves_writes(
saver: BaseCheckpointSaver,
) -> None:
"""Latest checkpoint's writes kept."""
tid = str(uuid4())
configs = await _setup_thread(saver, tid, n=3)
# Add writes to the latest
await saver.aput_writes(configs[-1], [("ch", "val")], str(uuid4()))
await saver.aprune([tid], strategy="keep_latest")
tup = await saver.aget_tuple(generate_config(tid))
assert tup is not None
assert tup.pending_writes is not None
assert len(tup.pending_writes) == 1, (
f"Expected 1 write, got {len(tup.pending_writes)}"
)
assert tup.pending_writes[0][1] == "ch", (
f"channel mismatch: {tup.pending_writes[0][1]!r}"
)
assert tup.pending_writes[0][2] == "val", (
f"value mismatch: {tup.pending_writes[0][2]!r}"
)
async def test_prune_delete_all(saver: BaseCheckpointSaver) -> None:
"""delete_all strategy removes everything."""
tid = str(uuid4())
await _setup_thread(saver, tid, n=3)
await saver.aprune([tid], strategy="delete")
results = []
async for tup in saver.alist(generate_config(tid)):
results.append(tup)
assert len(results) == 0
async def test_prune_preserves_other_threads(
saver: BaseCheckpointSaver,
) -> None:
"""Unlisted threads untouched."""
tid1, tid2 = str(uuid4()), str(uuid4())
await _setup_thread(saver, tid1, n=3)
await _setup_thread(saver, tid2, n=2)
# Snapshot tid2 before prune
pre_ids = []
async for tup in saver.alist(generate_config(tid2)):
pre_ids.append(tup.checkpoint["id"])
await saver.aprune([tid1], strategy="keep_latest")
# tid2 should be fully intact — same checkpoint IDs
post_ids = []
async for tup in saver.alist(generate_config(tid2)):
post_ids.append(tup.checkpoint["id"])
assert post_ids == pre_ids, f"tid2 changed: {pre_ids} -> {post_ids}"
async def test_prune_empty_list_noop(saver: BaseCheckpointSaver) -> None:
"""Empty thread_ids no error."""
await saver.aprune([], strategy="keep_latest")
async def test_prune_nonexistent_noop(saver: BaseCheckpointSaver) -> None:
"""Missing threads no error."""
await saver.aprune([str(uuid4())], strategy="keep_latest")
ALL_PRUNE_TESTS = [
test_prune_keep_latest_single_thread,
test_prune_keep_latest_multiple_threads,
test_prune_keep_latest_across_namespaces,
test_prune_keep_latest_preserves_writes,
test_prune_delete_all,
test_prune_preserves_other_threads,
test_prune_empty_list_noop,
test_prune_nonexistent_noop,
]
async def run_prune_tests(
saver: BaseCheckpointSaver,
on_test_result: Callable[[str, str, bool, str | None], None] | None = None,
) -> tuple[int, int, list[str]]:
"""Run all prune tests. Returns (passed, failed, failure_names)."""
passed = 0
failed = 0
failures: list[str] = []
for test_fn in ALL_PRUNE_TESTS:
try:
await test_fn(saver)
passed += 1
if on_test_result:
on_test_result("prune", test_fn.__name__, True, None)
except Exception as e:
failed += 1
msg = f"{test_fn.__name__}: {e}"
failures.append(msg)
if on_test_result:
on_test_result("prune", test_fn.__name__, False, traceback.format_exc())
return passed, failed, failures
@@ -0,0 +1,411 @@
"""PUT capability tests — aput + aget_tuple round-trip."""
from __future__ import annotations
import traceback
from collections.abc import Callable
from typing import Any
from uuid import uuid4
from langgraph.checkpoint.base import (
BaseCheckpointSaver,
ChannelVersions,
)
from langgraph.checkpoint.conformance.test_utils import (
generate_checkpoint,
generate_config,
generate_metadata,
)
async def test_put_returns_config(saver: BaseCheckpointSaver) -> None:
"""aput returns a RunnableConfig with thread_id, checkpoint_ns, checkpoint_id."""
config = generate_config()
cp = generate_checkpoint(channel_values={"k": "v"})
cp["channel_versions"] = {"k": 1}
md = generate_metadata()
result = await saver.aput(config, cp, md, {"k": 1})
assert "configurable" in result
conf = result["configurable"]
assert "thread_id" in conf
assert "checkpoint_ns" in conf
assert "checkpoint_id" in conf
assert conf["checkpoint_id"] == cp["id"]
async def test_put_roundtrip(saver: BaseCheckpointSaver) -> None:
"""put then get_tuple returns identical checkpoint."""
config = generate_config()
cp = generate_checkpoint(channel_values={"msg": "hello"})
cp["channel_versions"] = {"msg": 1}
md = generate_metadata(source="input", step=-1)
stored_config = await saver.aput(config, cp, md, {"msg": 1})
tup = await saver.aget_tuple(stored_config)
assert tup is not None
assert tup.checkpoint["id"] == cp["id"]
assert tup.checkpoint["channel_values"] == {"msg": "hello"}
async def test_put_preserves_channel_values(saver: BaseCheckpointSaver) -> None:
"""Various types (str, int, list, dict, bytes, None) round-trip correctly."""
values: dict[str, Any] = {
"str_val": "hello",
"int_val": 42,
"list_val": [1, 2, 3],
"dict_val": {"nested": True},
}
config = generate_config()
cp = generate_checkpoint(channel_values=values)
versions: ChannelVersions = {k: 1 for k in values}
cp["channel_versions"] = versions
md = generate_metadata()
stored = await saver.aput(config, cp, md, versions)
tup = await saver.aget_tuple(stored)
assert tup is not None
for k, v in values.items():
assert tup.checkpoint["channel_values"].get(k) == v, (
f"channel_values[{k}]: expected {v!r}, got {tup.checkpoint['channel_values'].get(k)!r}"
)
async def test_put_preserves_channel_versions(saver: BaseCheckpointSaver) -> None:
"""ChannelVersions round-trip correctly."""
versions: ChannelVersions = {"a": 1, "b": 2}
config = generate_config()
cp = generate_checkpoint(
channel_values={"a": "x", "b": "y"}, channel_versions=versions
)
md = generate_metadata()
stored = await saver.aput(config, cp, md, versions)
tup = await saver.aget_tuple(stored)
assert tup is not None
# Compare version values — checkpointers may convert int to str
for k, expected in versions.items():
actual = tup.checkpoint["channel_versions"].get(k)
assert actual is not None, f"channel_versions[{k}] missing"
assert str(actual).split(".")[0] == str(expected).split(".")[0], (
f"channel_versions[{k}]: expected {expected!r}, got {actual!r}"
)
async def test_put_preserves_versions_seen(saver: BaseCheckpointSaver) -> None:
"""versions_seen dict round-trips."""
vs: dict[str, ChannelVersions] = {"node1": {"ch": 1}, "node2": {"ch": 2}}
config = generate_config()
cp = generate_checkpoint(versions_seen=vs)
md = generate_metadata()
stored = await saver.aput(config, cp, md, {})
tup = await saver.aget_tuple(stored)
assert tup is not None
for node in vs:
assert node in tup.checkpoint["versions_seen"], f"versions_seen[{node}] missing"
async def test_put_preserves_metadata(saver: BaseCheckpointSaver) -> None:
"""Metadata source, step, parents, and custom keys round-trip."""
md = generate_metadata(source="loop", step=3, custom_key="custom_value")
config = generate_config()
cp = generate_checkpoint()
stored = await saver.aput(config, cp, md, {})
tup = await saver.aget_tuple(stored)
assert tup is not None
assert tup.metadata["source"] == "loop"
assert tup.metadata["step"] == 3
assert tup.metadata.get("custom_key") == "custom_value"
async def test_put_root_namespace(saver: BaseCheckpointSaver) -> None:
"""checkpoint_ns='' works."""
config = generate_config(checkpoint_ns="")
cp = generate_checkpoint()
md = generate_metadata()
stored = await saver.aput(config, cp, md, {})
tup = await saver.aget_tuple(stored)
assert tup is not None
assert tup.config["configurable"].get("checkpoint_ns", "") == ""
async def test_put_child_namespace(saver: BaseCheckpointSaver) -> None:
"""checkpoint_ns='child:abc' works."""
config = generate_config(checkpoint_ns="child:abc")
cp = generate_checkpoint()
md = generate_metadata()
stored = await saver.aput(config, cp, md, {})
tup = await saver.aget_tuple(stored)
assert tup is not None
assert tup.config["configurable"]["checkpoint_ns"] == "child:abc"
async def test_put_default_namespace(saver: BaseCheckpointSaver) -> None:
"""Config without checkpoint_ns defaults to ''."""
tid = str(uuid4())
config = {"configurable": {"thread_id": tid, "checkpoint_ns": ""}}
cp = generate_checkpoint()
md = generate_metadata()
stored = await saver.aput(config, cp, md, {})
tup = await saver.aget_tuple(stored)
assert tup is not None
async def test_put_multiple_checkpoints_same_thread(
saver: BaseCheckpointSaver,
) -> None:
"""Sequential puts on same thread, all retrievable."""
tid = str(uuid4())
ids = []
parent_cfg = None
for i in range(3):
config = generate_config(tid)
if parent_cfg is not None:
config["configurable"]["checkpoint_id"] = parent_cfg["configurable"][
"checkpoint_id"
]
cp = generate_checkpoint()
md = generate_metadata(step=i)
parent_cfg = await saver.aput(config, cp, md, {})
ids.append(cp["id"])
# All three should be retrievable
for cid in ids:
cfg = generate_config(tid, checkpoint_id=cid)
tup = await saver.aget_tuple(cfg)
assert tup is not None, f"checkpoint {cid} not found"
assert tup.checkpoint["id"] == cid
async def test_put_multiple_threads_isolated(saver: BaseCheckpointSaver) -> None:
"""Different thread_ids don't interfere."""
tid1, tid2 = str(uuid4()), str(uuid4())
config1 = generate_config(tid1)
cp1 = generate_checkpoint(channel_values={"x": "thread1"})
cp1["channel_versions"] = {"x": 1}
await saver.aput(config1, cp1, generate_metadata(), {"x": 1})
config2 = generate_config(tid2)
cp2 = generate_checkpoint(channel_values={"x": "thread2"})
cp2["channel_versions"] = {"x": 1}
await saver.aput(config2, cp2, generate_metadata(), {"x": 1})
tup1 = await saver.aget_tuple(generate_config(tid1))
tup2 = await saver.aget_tuple(generate_config(tid2))
assert tup1 is not None and tup2 is not None
assert tup1.checkpoint["channel_values"]["x"] == "thread1"
assert tup2.checkpoint["channel_values"]["x"] == "thread2"
async def test_put_parent_config(saver: BaseCheckpointSaver) -> None:
"""parent checkpoint_id tracked correctly."""
tid = str(uuid4())
config1 = generate_config(tid)
cp1 = generate_checkpoint()
stored1 = await saver.aput(config1, cp1, generate_metadata(step=0), {})
# Second checkpoint — its config carries the parent checkpoint_id
config2 = generate_config(tid)
config2["configurable"]["checkpoint_id"] = stored1["configurable"]["checkpoint_id"]
cp2 = generate_checkpoint()
stored2 = await saver.aput(config2, cp2, generate_metadata(step=1), {})
tup = await saver.aget_tuple(stored2)
assert tup is not None
assert tup.parent_config is not None
assert (
tup.parent_config["configurable"]["checkpoint_id"]
== stored1["configurable"]["checkpoint_id"]
)
async def test_put_incremental_channel_update(saver: BaseCheckpointSaver) -> None:
"""Only updated channels need new blobs; unchanged channels loaded from prior versions."""
tid = str(uuid4())
# Checkpoint 1: both channels are new
config1 = generate_config(tid)
cp1 = generate_checkpoint(
channel_values={"a": "v1", "b": "v2"},
channel_versions={"a": 1, "b": 1},
)
stored1 = await saver.aput(
config1, cp1, generate_metadata(step=0), {"a": 1, "b": 1}
)
# Checkpoint 2: only 'a' is updated
config2 = generate_config(tid)
config2["configurable"]["checkpoint_id"] = stored1["configurable"]["checkpoint_id"]
cp2 = generate_checkpoint(
channel_values={"a": "v1_updated", "b": "v2"},
channel_versions={"a": 2, "b": 1},
)
stored2 = await saver.aput(config2, cp2, generate_metadata(step=1), {"a": 2})
# cp2 should reconstruct full channel_values from blobs at mixed versions
tup2 = await saver.aget_tuple(stored2)
assert tup2 is not None
assert tup2.checkpoint["channel_values"].get("a") == "v1_updated", (
f"a: expected 'v1_updated', got {tup2.checkpoint['channel_values'].get('a')!r}"
)
assert tup2.checkpoint["channel_values"].get("b") == "v2", (
f"b: expected 'v2', got {tup2.checkpoint['channel_values'].get('b')!r}"
)
# cp1 should still return original values
tup1 = await saver.aget_tuple(stored1)
assert tup1 is not None
assert tup1.checkpoint["channel_values"].get("a") == "v1"
assert tup1.checkpoint["channel_values"].get("b") == "v2"
async def test_put_new_channel_added(saver: BaseCheckpointSaver) -> None:
"""A channel that appears for the first time in a later checkpoint."""
tid = str(uuid4())
config1 = generate_config(tid)
cp1 = generate_checkpoint(
channel_values={"a": "v1"},
channel_versions={"a": 1},
)
stored1 = await saver.aput(config1, cp1, generate_metadata(step=0), {"a": 1})
# Checkpoint 2: 'b' is brand new, 'a' is unchanged
config2 = generate_config(tid)
config2["configurable"]["checkpoint_id"] = stored1["configurable"]["checkpoint_id"]
cp2 = generate_checkpoint(
channel_values={"a": "v1", "b": "new_channel"},
channel_versions={"a": 1, "b": 1},
)
stored2 = await saver.aput(config2, cp2, generate_metadata(step=1), {"b": 1})
tup2 = await saver.aget_tuple(stored2)
assert tup2 is not None
assert tup2.checkpoint["channel_values"].get("a") == "v1", (
f"a: expected 'v1', got {tup2.checkpoint['channel_values'].get('a')!r}"
)
assert tup2.checkpoint["channel_values"].get("b") == "new_channel", (
f"b: expected 'new_channel', got {tup2.checkpoint['channel_values'].get('b')!r}"
)
async def test_put_channel_removed(saver: BaseCheckpointSaver) -> None:
"""Channel no longer in channel_versions should not appear in loaded values."""
tid = str(uuid4())
config1 = generate_config(tid)
cp1 = generate_checkpoint(
channel_values={"a": "v1", "b": "v2"},
channel_versions={"a": 1, "b": 1},
)
stored1 = await saver.aput(
config1, cp1, generate_metadata(step=0), {"a": 1, "b": 1}
)
# Checkpoint 2: 'b' dropped from channel_versions
config2 = generate_config(tid)
config2["configurable"]["checkpoint_id"] = stored1["configurable"]["checkpoint_id"]
cp2 = generate_checkpoint(
channel_values={"a": "v1_updated"},
channel_versions={"a": 2},
)
stored2 = await saver.aput(config2, cp2, generate_metadata(step=1), {"a": 2})
tup2 = await saver.aget_tuple(stored2)
assert tup2 is not None
assert tup2.checkpoint["channel_values"].get("a") == "v1_updated"
assert "b" not in tup2.checkpoint["channel_values"], (
f"'b' should not be present, got {tup2.checkpoint['channel_values']}"
)
async def test_put_preserves_run_id(saver: BaseCheckpointSaver) -> None:
"""run_id in metadata round-trips correctly."""
run_id = str(uuid4())
config = generate_config()
cp = generate_checkpoint()
md = generate_metadata(source="loop", step=0, run_id=run_id)
stored = await saver.aput(config, cp, md, {})
tup = await saver.aget_tuple(stored)
assert tup is not None
assert tup.metadata.get("run_id") == run_id, (
f"run_id: expected {run_id!r}, got {tup.metadata.get('run_id')!r}"
)
async def test_put_preserves_versions_seen_values(saver: BaseCheckpointSaver) -> None:
"""versions_seen values (not just keys) round-trip correctly."""
vs: dict[str, ChannelVersions] = {
"node1": {"ch_a": 1, "ch_b": 2},
"node2": {"ch_a": 3},
}
config = generate_config()
cp = generate_checkpoint(versions_seen=vs)
md = generate_metadata()
stored = await saver.aput(config, cp, md, {})
tup = await saver.aget_tuple(stored)
assert tup is not None
for node, expected_versions in vs.items():
assert node in tup.checkpoint["versions_seen"], f"versions_seen[{node}] missing"
actual_versions = tup.checkpoint["versions_seen"][node]
for ch, expected_v in expected_versions.items():
actual_v = actual_versions.get(ch)
assert actual_v is not None, f"versions_seen[{node}][{ch}] missing"
assert str(actual_v).split(".")[0] == str(expected_v).split(".")[0], (
f"versions_seen[{node}][{ch}]: expected {expected_v!r}, got {actual_v!r}"
)
ALL_PUT_TESTS = [
test_put_returns_config,
test_put_roundtrip,
test_put_preserves_channel_values,
test_put_preserves_channel_versions,
test_put_preserves_versions_seen,
test_put_preserves_metadata,
test_put_root_namespace,
test_put_child_namespace,
test_put_default_namespace,
test_put_multiple_checkpoints_same_thread,
test_put_multiple_threads_isolated,
test_put_parent_config,
test_put_incremental_channel_update,
test_put_new_channel_added,
test_put_channel_removed,
test_put_preserves_run_id,
test_put_preserves_versions_seen_values,
]
async def run_put_tests(
saver: BaseCheckpointSaver,
on_test_result: Callable[[str, str, bool, str | None], None] | None = None,
) -> tuple[int, int, list[str]]:
"""Run all put tests. Returns (passed, failed, failure_names)."""
passed = 0
failed = 0
failures: list[str] = []
for test_fn in ALL_PUT_TESTS:
try:
await test_fn(saver)
passed += 1
if on_test_result:
on_test_result("put", test_fn.__name__, True, None)
except Exception as e:
failed += 1
msg = f"{test_fn.__name__}: {e}"
failures.append(msg)
if on_test_result:
on_test_result("put", test_fn.__name__, False, traceback.format_exc())
return passed, failed, failures
@@ -0,0 +1,302 @@
"""PUT_WRITES capability tests — aput_writes + pending_writes retrieval."""
from __future__ import annotations
import traceback
from collections.abc import Callable
from uuid import uuid4
from langgraph.checkpoint.base import BaseCheckpointSaver
from langgraph.checkpoint.conformance.test_utils import (
generate_checkpoint,
generate_config,
generate_metadata,
)
async def test_put_writes_basic(saver: BaseCheckpointSaver) -> None:
"""Write stored, visible in aget_tuple pending_writes."""
tid = str(uuid4())
config = generate_config(tid)
cp = generate_checkpoint()
stored = await saver.aput(config, cp, generate_metadata(), {})
task_id = str(uuid4())
await saver.aput_writes(stored, [("channel1", "value1")], task_id)
tup = await saver.aget_tuple(stored)
assert tup is not None
assert tup.pending_writes is not None
# Verify exact write tuple: (task_id, channel, value)
matching = [w for w in tup.pending_writes if w[0] == task_id and w[1] == "channel1"]
assert len(matching) == 1, f"Expected 1 write, got {len(matching)}"
assert matching[0][2] == "value1", f"Value mismatch: {matching[0][2]!r}"
async def test_put_writes_multiple_writes_same_task(
saver: BaseCheckpointSaver,
) -> None:
"""Multiple (channel, value) pairs in a single call."""
tid = str(uuid4())
config = generate_config(tid)
cp = generate_checkpoint()
stored = await saver.aput(config, cp, generate_metadata(), {})
task_id = str(uuid4())
writes = [("ch1", "v1"), ("ch2", "v2"), ("ch3", "v3")]
await saver.aput_writes(stored, writes, task_id)
tup = await saver.aget_tuple(stored)
assert tup is not None
assert tup.pending_writes is not None
assert len(tup.pending_writes) == 3, (
f"Expected 3 writes, got {len(tup.pending_writes)}"
)
channels = {w[1] for w in tup.pending_writes}
assert channels == {"ch1", "ch2", "ch3"}, f"Expected exact channels, got {channels}"
# Verify values per channel
for expected_ch, expected_val in writes:
match = [
w for w in tup.pending_writes if w[0] == task_id and w[1] == expected_ch
]
assert len(match) == 1, f"Expected 1 write for {expected_ch}, got {len(match)}"
assert match[0][2] == expected_val, (
f"Value mismatch for {expected_ch}: {match[0][2]!r}"
)
async def test_put_writes_multiple_tasks(saver: BaseCheckpointSaver) -> None:
"""Different task_ids produce separate writes."""
tid = str(uuid4())
config = generate_config(tid)
cp = generate_checkpoint()
stored = await saver.aput(config, cp, generate_metadata(), {})
t1, t2 = str(uuid4()), str(uuid4())
await saver.aput_writes(stored, [("ch", "from_t1")], t1)
await saver.aput_writes(stored, [("ch", "from_t2")], t2)
tup = await saver.aget_tuple(stored)
assert tup is not None
assert tup.pending_writes is not None
assert len(tup.pending_writes) == 2, (
f"Expected 2 writes, got {len(tup.pending_writes)}"
)
# Verify values per task
t1_writes = [w for w in tup.pending_writes if w[0] == t1 and w[1] == "ch"]
t2_writes = [w for w in tup.pending_writes if w[0] == t2 and w[1] == "ch"]
assert len(t1_writes) == 1, f"Expected 1 write from t1, got {len(t1_writes)}"
assert len(t2_writes) == 1, f"Expected 1 write from t2, got {len(t2_writes)}"
assert t1_writes[0][2] == "from_t1", f"t1 value: {t1_writes[0][2]!r}"
assert t2_writes[0][2] == "from_t2", f"t2 value: {t2_writes[0][2]!r}"
async def test_put_writes_preserves_task_id(saver: BaseCheckpointSaver) -> None:
"""task_id in pending_writes matches what was passed to aput_writes."""
tid = str(uuid4())
config = generate_config(tid)
cp = generate_checkpoint()
stored = await saver.aput(config, cp, generate_metadata(), {})
task_id = str(uuid4())
await saver.aput_writes(stored, [("ch", "val")], task_id)
tup = await saver.aget_tuple(stored)
assert tup is not None
assert tup.pending_writes is not None
assert any(w[0] == task_id for w in tup.pending_writes)
async def test_put_writes_preserves_channel_and_value(
saver: BaseCheckpointSaver,
) -> None:
"""Channel name + value round-trip."""
tid = str(uuid4())
config = generate_config(tid)
cp = generate_checkpoint()
stored = await saver.aput(config, cp, generate_metadata(), {})
task_id = str(uuid4())
await saver.aput_writes(stored, [("my_channel", {"data": 123})], task_id)
tup = await saver.aget_tuple(stored)
assert tup is not None
assert tup.pending_writes is not None
match = [w for w in tup.pending_writes if w[0] == task_id and w[1] == "my_channel"]
assert len(match) == 1, f"Expected 1 write, got {len(match)}"
assert match[0][2] == {"data": 123}, f"Value mismatch: {match[0][2]!r}"
async def test_put_writes_task_path(saver: BaseCheckpointSaver) -> None:
"""task_path parameter accepted without error."""
tid = str(uuid4())
config = generate_config(tid)
cp = generate_checkpoint()
stored = await saver.aput(config, cp, generate_metadata(), {})
task_id = str(uuid4())
# Should not raise
await saver.aput_writes(stored, [("ch", "v")], task_id, task_path="a:b:c")
tup = await saver.aget_tuple(stored)
assert tup is not None
assert tup.pending_writes is not None
assert len(tup.pending_writes) == 1
async def test_put_writes_idempotent(saver: BaseCheckpointSaver) -> None:
"""Duplicate (task_id, idx) doesn't duplicate writes."""
tid = str(uuid4())
config = generate_config(tid)
cp = generate_checkpoint()
stored = await saver.aput(config, cp, generate_metadata(), {})
task_id = str(uuid4())
await saver.aput_writes(stored, [("ch", "val")], task_id)
await saver.aput_writes(stored, [("ch", "val")], task_id)
tup = await saver.aget_tuple(stored)
assert tup is not None
assert tup.pending_writes is not None
assert len(tup.pending_writes) == 1, (
f"Expected exactly 1 write total, got {len(tup.pending_writes)}"
)
# Should not have duplicated
matching = [w for w in tup.pending_writes if w[0] == task_id and w[1] == "ch"]
assert len(matching) == 1
async def test_put_writes_special_channels(saver: BaseCheckpointSaver) -> None:
"""ERROR and INTERRUPT channels handled correctly."""
from langgraph.checkpoint.serde.types import ERROR, INTERRUPT
tid = str(uuid4())
config = generate_config(tid)
cp = generate_checkpoint()
stored = await saver.aput(config, cp, generate_metadata(), {})
task_id = str(uuid4())
await saver.aput_writes(
stored,
[(ERROR, "something went wrong"), (INTERRUPT, {"reason": "human_input"})],
task_id,
)
tup = await saver.aget_tuple(stored)
assert tup is not None
assert tup.pending_writes is not None
channels = {w[1] for w in tup.pending_writes}
assert ERROR in channels
assert INTERRUPT in channels
# Verify values
err_writes = [w for w in tup.pending_writes if w[0] == task_id and w[1] == ERROR]
assert len(err_writes) == 1, f"Expected 1 ERROR write, got {len(err_writes)}"
assert err_writes[0][2] == "something went wrong", (
f"ERROR value: {err_writes[0][2]!r}"
)
int_writes = [
w for w in tup.pending_writes if w[0] == task_id and w[1] == INTERRUPT
]
assert len(int_writes) == 1, f"Expected 1 INTERRUPT write, got {len(int_writes)}"
assert int_writes[0][2] == {"reason": "human_input"}, (
f"INTERRUPT value: {int_writes[0][2]!r}"
)
async def test_put_writes_across_namespaces(saver: BaseCheckpointSaver) -> None:
"""Writes isolated by checkpoint_ns."""
tid = str(uuid4())
# Root namespace checkpoint + write
cfg_root = generate_config(tid, checkpoint_ns="")
cp_root = generate_checkpoint()
stored_root = await saver.aput(cfg_root, cp_root, generate_metadata(), {})
root_task = str(uuid4())
await saver.aput_writes(stored_root, [("ch", "root_val")], root_task)
# Child namespace checkpoint + write
cfg_child = generate_config(tid, checkpoint_ns="child:1")
cp_child = generate_checkpoint()
stored_child = await saver.aput(cfg_child, cp_child, generate_metadata(), {})
child_task = str(uuid4())
await saver.aput_writes(stored_child, [("ch", "child_val")], child_task)
# Verify isolation — root should have exactly 1 write with root_val
tup_root = await saver.aget_tuple(stored_root)
assert tup_root is not None
assert tup_root.pending_writes is not None
root_ch = [w for w in tup_root.pending_writes if w[1] == "ch"]
assert len(root_ch) == 1, f"Expected 1 root write, got {len(root_ch)}"
assert root_ch[0][2] == "root_val", f"Root value: {root_ch[0][2]!r}"
# Child should have exactly 1 write with child_val
tup_child = await saver.aget_tuple(stored_child)
assert tup_child is not None
assert tup_child.pending_writes is not None
child_ch = [w for w in tup_child.pending_writes if w[1] == "ch"]
assert len(child_ch) == 1, f"Expected 1 child write, got {len(child_ch)}"
assert child_ch[0][2] == "child_val", f"Child value: {child_ch[0][2]!r}"
async def test_put_writes_cleared_on_next_checkpoint(
saver: BaseCheckpointSaver,
) -> None:
"""New checkpoint starts with fresh pending_writes."""
tid = str(uuid4())
config = generate_config(tid)
cp1 = generate_checkpoint()
stored1 = await saver.aput(config, cp1, generate_metadata(step=0), {})
await saver.aput_writes(stored1, [("ch", "old_write")], str(uuid4()))
# New checkpoint
config2 = generate_config(tid)
config2["configurable"]["checkpoint_id"] = stored1["configurable"]["checkpoint_id"]
cp2 = generate_checkpoint()
stored2 = await saver.aput(config2, cp2, generate_metadata(step=1), {})
tup = await saver.aget_tuple(stored2)
assert tup is not None
# New checkpoint should have no pending writes
writes = tup.pending_writes or []
assert len(writes) == 0
ALL_PUT_WRITES_TESTS = [
test_put_writes_basic,
test_put_writes_multiple_writes_same_task,
test_put_writes_multiple_tasks,
test_put_writes_preserves_task_id,
test_put_writes_preserves_channel_and_value,
test_put_writes_task_path,
test_put_writes_idempotent,
test_put_writes_special_channels,
test_put_writes_across_namespaces,
test_put_writes_cleared_on_next_checkpoint,
]
async def run_put_writes_tests(
saver: BaseCheckpointSaver,
on_test_result: Callable[[str, str, bool, str | None], None] | None = None,
) -> tuple[int, int, list[str]]:
"""Run all put_writes tests. Returns (passed, failed, failure_names)."""
passed = 0
failed = 0
failures: list[str] = []
for test_fn in ALL_PUT_WRITES_TESTS:
try:
await test_fn(saver)
passed += 1
if on_test_result:
on_test_result("put_writes", test_fn.__name__, True, None)
except Exception as e:
failed += 1
msg = f"{test_fn.__name__}: {e}"
failures.append(msg)
if on_test_result:
on_test_result(
"put_writes", test_fn.__name__, False, traceback.format_exc()
)
return passed, failed, failures
@@ -0,0 +1,212 @@
"""Test utilities: checkpoint generators, assertion helpers, bulk operations."""
from __future__ import annotations
from datetime import datetime, timezone
from typing import Any
from uuid import uuid4
from langchain_core.runnables import RunnableConfig
from langgraph.checkpoint.base import (
ChannelVersions,
Checkpoint,
CheckpointMetadata,
CheckpointTuple,
)
from langgraph.checkpoint.base.id import uuid6
def generate_checkpoint(
*,
checkpoint_id: str | None = None,
channel_values: dict[str, Any] | None = None,
channel_versions: ChannelVersions | None = None,
versions_seen: dict[str, ChannelVersions] | None = None,
) -> Checkpoint:
"""Create a well-formed Checkpoint with sensible defaults."""
return Checkpoint(
v=1,
id=checkpoint_id or str(uuid6(clock_seq=-1)),
ts=datetime.now(timezone.utc).isoformat(),
channel_values=channel_values if channel_values is not None else {},
channel_versions=channel_versions if channel_versions is not None else {},
versions_seen=versions_seen if versions_seen is not None else {},
pending_sends=[], # ty: ignore[invalid-key]
updated_channels=None,
)
def generate_config(
thread_id: str | None = None,
*,
checkpoint_ns: str = "",
checkpoint_id: str | None = None,
) -> RunnableConfig:
"""Create a RunnableConfig targeting a specific thread / namespace / checkpoint."""
configurable: dict[str, Any] = {
"thread_id": thread_id or str(uuid4()),
"checkpoint_ns": checkpoint_ns,
}
if checkpoint_id is not None:
configurable["checkpoint_id"] = checkpoint_id
return {"configurable": configurable}
def generate_metadata(
source: str = "loop",
step: int = 0,
**extra: Any,
) -> CheckpointMetadata:
"""Create CheckpointMetadata with defaults."""
md: dict[str, Any] = {"source": source, "step": step, "parents": {}}
md.update(extra)
return md
async def put_test_checkpoint(
saver: Any,
*,
thread_id: str | None = None,
checkpoint_ns: str = "",
parent_config: RunnableConfig | None = None,
channel_values: dict[str, Any] | None = None,
channel_versions: ChannelVersions | None = None,
metadata: CheckpointMetadata | None = None,
new_versions: ChannelVersions | None = None,
) -> RunnableConfig:
"""Put a single test checkpoint and return the stored config.
Handles wiring up parent_config, channel_values -> new_versions, etc.
"""
tid = thread_id or str(uuid4())
cp = generate_checkpoint(
channel_values=channel_values,
channel_versions=channel_versions,
)
# When channel_values are provided, ensure channel_versions + new_versions
# are consistent so the checkpointer stores the blobs correctly.
vals = channel_values or {}
cv = channel_versions
if cv is None and vals:
cv = {k: 1 for k in vals}
cp["channel_versions"] = cv
nv = new_versions
if nv is None:
nv = cv or {}
md = metadata or generate_metadata()
config = generate_config(tid, checkpoint_ns=checkpoint_ns)
if parent_config is not None:
config["configurable"]["checkpoint_id"] = parent_config["configurable"][
"checkpoint_id"
]
return await saver.aput(config, cp, md, nv)
async def put_test_checkpoints(
saver: Any,
*,
n_threads: int = 1,
n_checkpoints: int = 1,
namespaces: list[str] | None = None,
channel_values: dict[str, Any] | None = None,
) -> list[RunnableConfig]:
"""Convenience: put multiple checkpoints across threads/namespaces.
Returns the stored configs in insertion order.
"""
nss = namespaces or [""]
stored: list[RunnableConfig] = []
for t in range(n_threads):
tid = f"thread-{t}"
for ns in nss:
parent: RunnableConfig | None = None
for _c in range(n_checkpoints):
cfg = await put_test_checkpoint(
saver,
thread_id=tid,
checkpoint_ns=ns,
parent_config=parent,
channel_values=channel_values,
)
parent = cfg
stored.append(cfg)
return stored
def assert_checkpoint_equal(
actual: Checkpoint,
expected: Checkpoint,
*,
check_channel_values: bool = True,
) -> None:
"""Assert two checkpoints are semantically equal."""
assert actual["v"] == expected["v"], f"v mismatch: {actual['v']} != {expected['v']}"
assert actual["id"] == expected["id"], (
f"id mismatch: {actual['id']} != {expected['id']}"
)
assert actual["channel_versions"] == expected["channel_versions"], (
"channel_versions mismatch"
)
assert actual["versions_seen"] == expected["versions_seen"], (
"versions_seen mismatch"
)
if check_channel_values:
assert actual["channel_values"] == expected["channel_values"], (
"channel_values mismatch"
)
def assert_tuple_equal(
actual: CheckpointTuple,
expected: CheckpointTuple,
*,
check_writes: bool = True,
check_channel_values: bool = True,
) -> None:
"""Assert two CheckpointTuples are semantically equal."""
# Config
a_conf = actual.config["configurable"]
e_conf = expected.config["configurable"]
assert a_conf["thread_id"] == e_conf["thread_id"], (
f"thread_id mismatch: {a_conf['thread_id']} != {e_conf['thread_id']}"
)
assert a_conf.get("checkpoint_ns", "") == e_conf.get("checkpoint_ns", ""), (
"checkpoint_ns mismatch"
)
assert a_conf["checkpoint_id"] == e_conf["checkpoint_id"], "checkpoint_id mismatch"
# Checkpoint
assert_checkpoint_equal(
actual.checkpoint,
expected.checkpoint,
check_channel_values=check_channel_values,
)
# Metadata
for k, v in expected.metadata.items():
assert actual.metadata.get(k) == v, (
f"metadata[{k}] mismatch: {actual.metadata.get(k)} != {v}"
)
# Parent config
if expected.parent_config is not None:
assert actual.parent_config is not None, "expected parent_config, got None"
assert (
actual.parent_config["configurable"]["checkpoint_id"]
== expected.parent_config["configurable"]["checkpoint_id"]
), "parent checkpoint_id mismatch"
else:
assert actual.parent_config is None, (
f"expected no parent_config, got {actual.parent_config}"
)
# Pending writes
if check_writes and expected.pending_writes is not None:
assert actual.pending_writes is not None
assert len(actual.pending_writes) == len(expected.pending_writes), (
f"pending_writes length mismatch: {len(actual.pending_writes)} != {len(expected.pending_writes)}"
)
@@ -0,0 +1,124 @@
"""Core conformance runner — detects capabilities, runs test suites, builds report."""
from __future__ import annotations
from langgraph.checkpoint.conformance.capabilities import (
Capability,
DetectedCapabilities,
)
from langgraph.checkpoint.conformance.initializer import RegisteredCheckpointer
from langgraph.checkpoint.conformance.report import (
CapabilityReport,
CapabilityResult,
ProgressCallbacks,
)
from langgraph.checkpoint.conformance.spec.test_copy_thread import run_copy_thread_tests
from langgraph.checkpoint.conformance.spec.test_delete_for_runs import (
run_delete_for_runs_tests,
)
from langgraph.checkpoint.conformance.spec.test_delete_thread import (
run_delete_thread_tests,
)
from langgraph.checkpoint.conformance.spec.test_get_tuple import run_get_tuple_tests
from langgraph.checkpoint.conformance.spec.test_list import run_list_tests
from langgraph.checkpoint.conformance.spec.test_prune import run_prune_tests
from langgraph.checkpoint.conformance.spec.test_put import run_put_tests
from langgraph.checkpoint.conformance.spec.test_put_writes import run_put_writes_tests
# Maps capability to its runner function.
_RUNNERS = {
Capability.PUT: run_put_tests,
Capability.PUT_WRITES: run_put_writes_tests,
Capability.GET_TUPLE: run_get_tuple_tests,
Capability.LIST: run_list_tests,
Capability.DELETE_THREAD: run_delete_thread_tests,
Capability.DELETE_FOR_RUNS: run_delete_for_runs_tests,
Capability.COPY_THREAD: run_copy_thread_tests,
Capability.PRUNE: run_prune_tests,
}
async def validate(
registered: RegisteredCheckpointer,
*,
capabilities: set[str] | None = None,
progress: ProgressCallbacks | None = None,
) -> CapabilityReport:
"""Run the validation suite against a registered checkpointer.
Args:
registered: A RegisteredCheckpointer (from @checkpointer_test decorator).
capabilities: If given, only run tests for these capability names.
Otherwise, auto-detect and run all applicable tests.
progress: Optional progress callbacks for incremental output.
Use ``ProgressCallbacks.default()`` for dot-style,
``ProgressCallbacks.verbose()`` for per-test output, or
``None`` / ``ProgressCallbacks.quiet()`` for silent mode.
Returns:
A CapabilityReport with per-capability results.
"""
report = CapabilityReport(checkpointer_name=registered.name)
# Determine which capabilities to test.
caps_to_test: set[Capability]
if capabilities is not None:
caps_to_test = {Capability(c) for c in capabilities}
else:
caps_to_test = set(Capability)
async with registered.enter_lifespan():
for cap in Capability:
if cap in caps_to_test and cap.value not in registered.skip_capabilities:
# Create a fresh checkpointer for each capability suite.
async with registered.create() as saver:
detected = DetectedCapabilities.from_instance(saver)
is_detected = cap in detected.detected
if not is_detected:
if progress and progress.on_capability_start:
progress.on_capability_start(cap.value, False)
report.results[cap.value] = CapabilityResult(
detected=False,
passed=None,
tests_skipped=1,
)
continue
runner = _RUNNERS.get(cap)
if runner is None:
report.results[cap.value] = CapabilityResult(
detected=True,
passed=None,
tests_skipped=1,
)
continue
if progress and progress.on_capability_start:
progress.on_capability_start(cap.value, True)
passed, failed, failures = await runner(
saver,
on_test_result=progress.on_test_result if progress else None,
)
if progress and progress.on_capability_end:
progress.on_capability_end(cap.value)
report.results[cap.value] = CapabilityResult(
detected=True,
passed=failed == 0,
tests_passed=passed,
tests_failed=failed,
failures=failures,
)
else:
if progress and progress.on_capability_start:
progress.on_capability_start(cap.value, False)
report.results[cap.value] = CapabilityResult(
detected=False,
passed=None,
tests_skipped=1,
)
return report
@@ -0,0 +1,65 @@
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "langgraph-checkpoint-conformance"
version = "0.0.1"
description = "Conformance test suite for LangGraph checkpointer implementations."
authors = [{name = "William FH", email = "13333726+hinthornw@users.noreply.github.com"}]
requires-python = ">=3.10"
readme = "README.md"
license = "MIT"
dependencies = [
"langgraph-checkpoint>=2.0.0",
]
[project.urls]
Source = "https://github.com/langchain-ai/langgraph/tree/main/libs/checkpoint-conformance"
[dependency-groups]
test = [
"pytest",
"pytest-asyncio",
]
lint = [
"ruff",
"ty",
]
dev = [
{include-group = "test"},
{include-group = "lint"},
]
[tool.hatch.build.targets.wheel]
include = ["langgraph"]
[tool.pytest.ini_options]
addopts = "--strict-markers --strict-config --durations=5 -vv"
testpaths = ["tests"]
asyncio_mode = "auto"
[tool.ty.rules]
# The extended methods (acopy_thread, adelete_for_runs, aprune) are checked
# at runtime via capability detection and may not exist on the installed
# base class. Dict literal inference is also overly strict for RunnableConfig.
unresolved-attribute = "ignore"
invalid-argument-type = "ignore"
invalid-return-type = "ignore"
[tool.ruff]
lint.select = [
"E", # pycodestyle
"F", # Pyflakes
"UP", # pyupgrade
"B", # flake8-bugbear
"I", # isort
]
lint.ignore = ["E501", "B008"]
target-version = "py310"
[[tool.uv.index]]
name = "testpypi"
url = "https://test.pypi.org/simple/"
publish-url = "https://test.pypi.org/legacy/"
explicit = true
@@ -0,0 +1,21 @@
"""Self-tests: run the conformance suite against InMemorySaver."""
from __future__ import annotations
import pytest
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.checkpoint.conformance import checkpointer_test, validate
@checkpointer_test(name="InMemorySaver")
async def memory_checkpointer():
yield InMemorySaver()
@pytest.mark.asyncio
async def test_validate_memory_base():
"""InMemorySaver passes all base capability tests."""
report = await validate(memory_checkpointer)
report.print_report()
assert report.passed_all_base(), f"Base tests failed: {report.to_dict()}"
+1124
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -13,7 +13,7 @@ license = "MIT"
license-files = ['LICENSE']
dependencies = [
"langgraph-checkpoint>=2.1.2,<5.0.0",
"orjson>=3.10.1",
"orjson>=3.11.5",
"psycopg>=3.2.0",
"psycopg-pool>=3.2.0",
]
+98 -99
View File
@@ -240,7 +240,7 @@ wheels = [
[[package]]
name = "langchain-core"
version = "1.2.7"
version = "1.2.11"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "jsonpatch" },
@@ -252,9 +252,9 @@ dependencies = [
{ name = "typing-extensions" },
{ name = "uuid-utils" },
]
sdist = { url = "https://files.pythonhosted.org/packages/a2/0e/664d8d81b3493e09cbab72448d2f9d693d1fa5aa2bcc488602203a9b6da0/langchain_core-1.2.7.tar.gz", hash = "sha256:e1460639f96c352b4a41c375f25aeb8d16ffc1769499fb1c20503aad59305ced", size = 837039, upload-time = "2026-01-09T17:44:25.505Z" }
sdist = { url = "https://files.pythonhosted.org/packages/12/17/1943cedfc118e04b8128e4c3e1dbf0fa0ea58eefddbb6198cfd699d19f01/langchain_core-1.2.11.tar.gz", hash = "sha256:f164bb36602dd74a3a50c1334fca75309ad5ed95767acdfdbb9fa95ce28a1e01", size = 831211, upload-time = "2026-02-10T20:35:28.35Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/6e/6f/34a9fba14d191a67f7e2ee3dbce3e9b86d2fa7310e2c7f2c713583481bd2/langchain_core-1.2.7-py3-none-any.whl", hash = "sha256:452f4fef7a3d883357b22600788d37e3d8854ef29da345b7ac7099f33c31828b", size = 490232, upload-time = "2026-01-09T17:44:24.236Z" },
{ url = "https://files.pythonhosted.org/packages/10/30/1f80e3fc674353cad975ed5294353d42512535d2094ef032c06454c2c873/langchain_core-1.2.11-py3-none-any.whl", hash = "sha256:ae11ceb8dda60d0b9d09e763116e592f1683327c17be5b715f350fd29aee65d3", size = 500062, upload-time = "2026-02-10T20:35:26.698Z" },
]
[[package]]
@@ -346,7 +346,7 @@ test = [
[package.metadata]
requires-dist = [
{ name = "langgraph-checkpoint", editable = "../checkpoint" },
{ name = "orjson", specifier = ">=3.10.1" },
{ name = "orjson", specifier = ">=3.11.5" },
{ name = "psycopg", specifier = ">=3.2.0" },
{ name = "psycopg-pool", specifier = ">=3.2.0" },
]
@@ -528,83 +528,83 @@ wheels = [
[[package]]
name = "orjson"
version = "3.11.5"
version = "3.11.7"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/04/b8/333fdb27840f3bf04022d21b654a35f58e15407183aeb16f3b41aa053446/orjson-3.11.5.tar.gz", hash = "sha256:82393ab47b4fe44ffd0a7659fa9cfaacc717eb617c93cde83795f14af5c2e9d5", size = 5972347, upload-time = "2025-12-06T15:55:39.458Z" }
sdist = { url = "https://files.pythonhosted.org/packages/53/45/b268004f745ede84e5798b48ee12b05129d19235d0e15267aa57dcdb400b/orjson-3.11.7.tar.gz", hash = "sha256:9b1a67243945819ce55d24a30b59d6a168e86220452d2c96f4d1f093e71c0c49", size = 6144992, upload-time = "2026-02-02T15:38:49.29Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/79/19/b22cf9dad4db20c8737041046054cbd4f38bb5a2d0e4bb60487832ce3d76/orjson-3.11.5-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:df9eadb2a6386d5ea2bfd81309c505e125cfc9ba2b1b99a97e60985b0b3665d1", size = 245719, upload-time = "2025-12-06T15:53:43.877Z" },
{ url = "https://files.pythonhosted.org/packages/03/2e/b136dd6bf30ef5143fbe76a4c142828b55ccc618be490201e9073ad954a1/orjson-3.11.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ccc70da619744467d8f1f49a8cadae5ec7bbe054e5232d95f92ed8737f8c5870", size = 132467, upload-time = "2025-12-06T15:53:45.379Z" },
{ url = "https://files.pythonhosted.org/packages/ae/fc/ae99bfc1e1887d20a0268f0e2686eb5b13d0ea7bbe01de2b566febcd2130/orjson-3.11.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:073aab025294c2f6fc0807201c76fdaed86f8fc4be52c440fb78fbb759a1ac09", size = 130702, upload-time = "2025-12-06T15:53:46.659Z" },
{ url = "https://files.pythonhosted.org/packages/6e/43/ef7912144097765997170aca59249725c3ab8ef6079f93f9d708dd058df5/orjson-3.11.5-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:835f26fa24ba0bb8c53ae2a9328d1706135b74ec653ed933869b74b6909e63fd", size = 135907, upload-time = "2025-12-06T15:53:48.487Z" },
{ url = "https://files.pythonhosted.org/packages/3f/da/24d50e2d7f4092ddd4d784e37a3fa41f22ce8ed97abc9edd222901a96e74/orjson-3.11.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:667c132f1f3651c14522a119e4dd631fad98761fa960c55e8e7430bb2a1ba4ac", size = 139935, upload-time = "2025-12-06T15:53:49.88Z" },
{ url = "https://files.pythonhosted.org/packages/02/4a/b4cb6fcbfff5b95a3a019a8648255a0fac9b221fbf6b6e72be8df2361feb/orjson-3.11.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:42e8961196af655bb5e63ce6c60d25e8798cd4dfbc04f4203457fa3869322c2e", size = 137541, upload-time = "2025-12-06T15:53:51.226Z" },
{ url = "https://files.pythonhosted.org/packages/a5/99/a11bd129f18c2377c27b2846a9d9be04acec981f770d711ba0aaea563984/orjson-3.11.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75412ca06e20904c19170f8a24486c4e6c7887dea591ba18a1ab572f1300ee9f", size = 139031, upload-time = "2025-12-06T15:53:52.309Z" },
{ url = "https://files.pythonhosted.org/packages/64/29/d7b77d7911574733a036bb3e8ad7053ceb2b7d6ea42208b9dbc55b23b9ed/orjson-3.11.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6af8680328c69e15324b5af3ae38abbfcf9cbec37b5346ebfd52339c3d7e8a18", size = 141622, upload-time = "2025-12-06T15:53:53.606Z" },
{ url = "https://files.pythonhosted.org/packages/93/41/332db96c1de76b2feda4f453e91c27202cd092835936ce2b70828212f726/orjson-3.11.5-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:a86fe4ff4ea523eac8f4b57fdac319faf037d3c1be12405e6a7e86b3fbc4756a", size = 413800, upload-time = "2025-12-06T15:53:54.866Z" },
{ url = "https://files.pythonhosted.org/packages/76/e1/5a0d148dd1f89ad2f9651df67835b209ab7fcb1118658cf353425d7563e9/orjson-3.11.5-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e607b49b1a106ee2086633167033afbd63f76f2999e9236f638b06b112b24ea7", size = 151198, upload-time = "2025-12-06T15:53:56.383Z" },
{ url = "https://files.pythonhosted.org/packages/0d/96/8db67430d317a01ae5cf7971914f6775affdcfe99f5bff9ef3da32492ecc/orjson-3.11.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7339f41c244d0eea251637727f016b3d20050636695bc78345cce9029b189401", size = 141984, upload-time = "2025-12-06T15:53:57.746Z" },
{ url = "https://files.pythonhosted.org/packages/71/49/40d21e1aa1ac569e521069228bb29c9b5a350344ccf922a0227d93c2ed44/orjson-3.11.5-cp310-cp310-win32.whl", hash = "sha256:8be318da8413cdbbce77b8c5fac8d13f6eb0f0db41b30bb598631412619572e8", size = 135272, upload-time = "2025-12-06T15:53:59.769Z" },
{ url = "https://files.pythonhosted.org/packages/c4/7e/d0e31e78be0c100e08be64f48d2850b23bcb4d4c70d114f4e43b39f6895a/orjson-3.11.5-cp310-cp310-win_amd64.whl", hash = "sha256:b9f86d69ae822cabc2a0f6c099b43e8733dda788405cba2665595b7e8dd8d167", size = 133360, upload-time = "2025-12-06T15:54:01.25Z" },
{ url = "https://files.pythonhosted.org/packages/fd/68/6b3659daec3a81aed5ab47700adb1a577c76a5452d35b91c88efee89987f/orjson-3.11.5-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9c8494625ad60a923af6b2b0bd74107146efe9b55099e20d7740d995f338fcd8", size = 245318, upload-time = "2025-12-06T15:54:02.355Z" },
{ url = "https://files.pythonhosted.org/packages/e9/00/92db122261425f61803ccf0830699ea5567439d966cbc35856fe711bfe6b/orjson-3.11.5-cp311-cp311-macosx_15_0_arm64.whl", hash = "sha256:7bb2ce0b82bc9fd1168a513ddae7a857994b780b2945a8c51db4ab1c4b751ebc", size = 129491, upload-time = "2025-12-06T15:54:03.877Z" },
{ url = "https://files.pythonhosted.org/packages/94/4f/ffdcb18356518809d944e1e1f77589845c278a1ebbb5a8297dfefcc4b4cb/orjson-3.11.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67394d3becd50b954c4ecd24ac90b5051ee7c903d167459f93e77fc6f5b4c968", size = 132167, upload-time = "2025-12-06T15:54:04.944Z" },
{ url = "https://files.pythonhosted.org/packages/97/c6/0a8caff96f4503f4f7dd44e40e90f4d14acf80d3b7a97cb88747bb712d3e/orjson-3.11.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:298d2451f375e5f17b897794bcc3e7b821c0f32b4788b9bcae47ada24d7f3cf7", size = 130516, upload-time = "2025-12-06T15:54:06.274Z" },
{ url = "https://files.pythonhosted.org/packages/4d/63/43d4dc9bd9954bff7052f700fdb501067f6fb134a003ddcea2a0bb3854ed/orjson-3.11.5-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa5e4244063db8e1d87e0f54c3f7522f14b2dc937e65d5241ef0076a096409fd", size = 135695, upload-time = "2025-12-06T15:54:07.702Z" },
{ url = "https://files.pythonhosted.org/packages/87/6f/27e2e76d110919cb7fcb72b26166ee676480a701bcf8fc53ac5d0edce32f/orjson-3.11.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1db2088b490761976c1b2e956d5d4e6409f3732e9d79cfa69f876c5248d1baf9", size = 139664, upload-time = "2025-12-06T15:54:08.828Z" },
{ url = "https://files.pythonhosted.org/packages/d4/f8/5966153a5f1be49b5fbb8ca619a529fde7bc71aa0a376f2bb83fed248bcd/orjson-3.11.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c2ed66358f32c24e10ceea518e16eb3549e34f33a9d51f99ce23b0251776a1ef", size = 137289, upload-time = "2025-12-06T15:54:09.898Z" },
{ url = "https://files.pythonhosted.org/packages/a7/34/8acb12ff0299385c8bbcbb19fbe40030f23f15a6de57a9c587ebf71483fb/orjson-3.11.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2021afda46c1ed64d74b555065dbd4c2558d510d8cec5ea6a53001b3e5e82a9", size = 138784, upload-time = "2025-12-06T15:54:11.022Z" },
{ url = "https://files.pythonhosted.org/packages/ee/27/910421ea6e34a527f73d8f4ee7bdffa48357ff79c7b8d6eb6f7b82dd1176/orjson-3.11.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b42ffbed9128e547a1647a3e50bc88ab28ae9daa61713962e0d3dd35e820c125", size = 141322, upload-time = "2025-12-06T15:54:12.427Z" },
{ url = "https://files.pythonhosted.org/packages/87/a3/4b703edd1a05555d4bb1753d6ce44e1a05b7a6d7c164d5b332c795c63d70/orjson-3.11.5-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:8d5f16195bb671a5dd3d1dbea758918bada8f6cc27de72bd64adfbd748770814", size = 413612, upload-time = "2025-12-06T15:54:13.858Z" },
{ url = "https://files.pythonhosted.org/packages/1b/36/034177f11d7eeea16d3d2c42a1883b0373978e08bc9dad387f5074c786d8/orjson-3.11.5-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:c0e5d9f7a0227df2927d343a6e3859bebf9208b427c79bd31949abcc2fa32fa5", size = 150993, upload-time = "2025-12-06T15:54:15.189Z" },
{ url = "https://files.pythonhosted.org/packages/44/2f/ea8b24ee046a50a7d141c0227c4496b1180b215e728e3b640684f0ea448d/orjson-3.11.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:23d04c4543e78f724c4dfe656b3791b5f98e4c9253e13b2636f1af5d90e4a880", size = 141774, upload-time = "2025-12-06T15:54:16.451Z" },
{ url = "https://files.pythonhosted.org/packages/8a/12/cc440554bf8200eb23348a5744a575a342497b65261cd65ef3b28332510a/orjson-3.11.5-cp311-cp311-win32.whl", hash = "sha256:c404603df4865f8e0afe981aa3c4b62b406e6d06049564d58934860b62b7f91d", size = 135109, upload-time = "2025-12-06T15:54:17.73Z" },
{ url = "https://files.pythonhosted.org/packages/a3/83/e0c5aa06ba73a6760134b169f11fb970caa1525fa4461f94d76e692299d9/orjson-3.11.5-cp311-cp311-win_amd64.whl", hash = "sha256:9645ef655735a74da4990c24ffbd6894828fbfa117bc97c1edd98c282ecb52e1", size = 133193, upload-time = "2025-12-06T15:54:19.426Z" },
{ url = "https://files.pythonhosted.org/packages/cb/35/5b77eaebc60d735e832c5b1a20b155667645d123f09d471db0a78280fb49/orjson-3.11.5-cp311-cp311-win_arm64.whl", hash = "sha256:1cbf2735722623fcdee8e712cbaaab9e372bbcb0c7924ad711b261c2eccf4a5c", size = 126830, upload-time = "2025-12-06T15:54:20.836Z" },
{ url = "https://files.pythonhosted.org/packages/ef/a4/8052a029029b096a78955eadd68ab594ce2197e24ec50e6b6d2ab3f4e33b/orjson-3.11.5-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:334e5b4bff9ad101237c2d799d9fd45737752929753bf4faf4b207335a416b7d", size = 245347, upload-time = "2025-12-06T15:54:22.061Z" },
{ url = "https://files.pythonhosted.org/packages/64/67/574a7732bd9d9d79ac620c8790b4cfe0717a3d5a6eb2b539e6e8995e24a0/orjson-3.11.5-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:ff770589960a86eae279f5d8aa536196ebda8273a2a07db2a54e82b93bc86626", size = 129435, upload-time = "2025-12-06T15:54:23.615Z" },
{ url = "https://files.pythonhosted.org/packages/52/8d/544e77d7a29d90cf4d9eecd0ae801c688e7f3d1adfa2ebae5e1e94d38ab9/orjson-3.11.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed24250e55efbcb0b35bed7caaec8cedf858ab2f9f2201f17b8938c618c8ca6f", size = 132074, upload-time = "2025-12-06T15:54:24.694Z" },
{ url = "https://files.pythonhosted.org/packages/6e/57/b9f5b5b6fbff9c26f77e785baf56ae8460ef74acdb3eae4931c25b8f5ba9/orjson-3.11.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a66d7769e98a08a12a139049aac2f0ca3adae989817f8c43337455fbc7669b85", size = 130520, upload-time = "2025-12-06T15:54:26.185Z" },
{ url = "https://files.pythonhosted.org/packages/f6/6d/d34970bf9eb33f9ec7c979a262cad86076814859e54eb9a059a52f6dc13d/orjson-3.11.5-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:86cfc555bfd5794d24c6a1903e558b50644e5e68e6471d66502ce5cb5fdef3f9", size = 136209, upload-time = "2025-12-06T15:54:27.264Z" },
{ url = "https://files.pythonhosted.org/packages/e7/39/bc373b63cc0e117a105ea12e57280f83ae52fdee426890d57412432d63b3/orjson-3.11.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a230065027bc2a025e944f9d4714976a81e7ecfa940923283bca7bbc1f10f626", size = 139837, upload-time = "2025-12-06T15:54:28.75Z" },
{ url = "https://files.pythonhosted.org/packages/cb/aa/7c4818c8d7d324da220f4f1af55c343956003aa4d1ce1857bdc1d396ba69/orjson-3.11.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b29d36b60e606df01959c4b982729c8845c69d1963f88686608be9ced96dbfaa", size = 137307, upload-time = "2025-12-06T15:54:29.856Z" },
{ url = "https://files.pythonhosted.org/packages/46/bf/0993b5a056759ba65145effe3a79dd5a939d4a070eaa5da2ee3180fbb13f/orjson-3.11.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c74099c6b230d4261fdc3169d50efc09abf38ace1a42ea2f9994b1d79153d477", size = 139020, upload-time = "2025-12-06T15:54:31.024Z" },
{ url = "https://files.pythonhosted.org/packages/65/e8/83a6c95db3039e504eda60fc388f9faedbb4f6472f5aba7084e06552d9aa/orjson-3.11.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e697d06ad57dd0c7a737771d470eedc18e68dfdefcdd3b7de7f33dfda5b6212e", size = 141099, upload-time = "2025-12-06T15:54:32.196Z" },
{ url = "https://files.pythonhosted.org/packages/b9/b4/24fdc024abfce31c2f6812973b0a693688037ece5dc64b7a60c1ce69e2f2/orjson-3.11.5-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:e08ca8a6c851e95aaecc32bc44a5aa75d0ad26af8cdac7c77e4ed93acf3d5b69", size = 413540, upload-time = "2025-12-06T15:54:33.361Z" },
{ url = "https://files.pythonhosted.org/packages/d9/37/01c0ec95d55ed0c11e4cae3e10427e479bba40c77312b63e1f9665e0737d/orjson-3.11.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e8b5f96c05fce7d0218df3fdfeb962d6b8cfff7e3e20264306b46dd8b217c0f3", size = 151530, upload-time = "2025-12-06T15:54:34.6Z" },
{ url = "https://files.pythonhosted.org/packages/f9/d4/f9ebc57182705bb4bbe63f5bbe14af43722a2533135e1d2fb7affa0c355d/orjson-3.11.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ddbfdb5099b3e6ba6d6ea818f61997bb66de14b411357d24c4612cf1ebad08ca", size = 141863, upload-time = "2025-12-06T15:54:35.801Z" },
{ url = "https://files.pythonhosted.org/packages/0d/04/02102b8d19fdcb009d72d622bb5781e8f3fae1646bf3e18c53d1bc8115b5/orjson-3.11.5-cp312-cp312-win32.whl", hash = "sha256:9172578c4eb09dbfcf1657d43198de59b6cef4054de385365060ed50c458ac98", size = 135255, upload-time = "2025-12-06T15:54:37.209Z" },
{ url = "https://files.pythonhosted.org/packages/d4/fb/f05646c43d5450492cb387de5549f6de90a71001682c17882d9f66476af5/orjson-3.11.5-cp312-cp312-win_amd64.whl", hash = "sha256:2b91126e7b470ff2e75746f6f6ee32b9ab67b7a93c8ba1d15d3a0caaf16ec875", size = 133252, upload-time = "2025-12-06T15:54:38.401Z" },
{ url = "https://files.pythonhosted.org/packages/dc/a6/7b8c0b26ba18c793533ac1cd145e131e46fcf43952aa94c109b5b913c1f0/orjson-3.11.5-cp312-cp312-win_arm64.whl", hash = "sha256:acbc5fac7e06777555b0722b8ad5f574739e99ffe99467ed63da98f97f9ca0fe", size = 126777, upload-time = "2025-12-06T15:54:39.515Z" },
{ url = "https://files.pythonhosted.org/packages/10/43/61a77040ce59f1569edf38f0b9faadc90c8cf7e9bec2e0df51d0132c6bb7/orjson-3.11.5-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:3b01799262081a4c47c035dd77c1301d40f568f77cc7ec1bb7db5d63b0a01629", size = 245271, upload-time = "2025-12-06T15:54:40.878Z" },
{ url = "https://files.pythonhosted.org/packages/55/f9/0f79be617388227866d50edd2fd320cb8fb94dc1501184bb1620981a0aba/orjson-3.11.5-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:61de247948108484779f57a9f406e4c84d636fa5a59e411e6352484985e8a7c3", size = 129422, upload-time = "2025-12-06T15:54:42.403Z" },
{ url = "https://files.pythonhosted.org/packages/77/42/f1bf1549b432d4a78bfa95735b79b5dac75b65b5bb815bba86ad406ead0a/orjson-3.11.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:894aea2e63d4f24a7f04a1908307c738d0dce992e9249e744b8f4e8dd9197f39", size = 132060, upload-time = "2025-12-06T15:54:43.531Z" },
{ url = "https://files.pythonhosted.org/packages/25/49/825aa6b929f1a6ed244c78acd7b22c1481fd7e5fda047dc8bf4c1a807eb6/orjson-3.11.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ddc21521598dbe369d83d4d40338e23d4101dad21dae0e79fa20465dbace019f", size = 130391, upload-time = "2025-12-06T15:54:45.059Z" },
{ url = "https://files.pythonhosted.org/packages/42/ec/de55391858b49e16e1aa8f0bbbb7e5997b7345d8e984a2dec3746d13065b/orjson-3.11.5-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7cce16ae2f5fb2c53c3eafdd1706cb7b6530a67cc1c17abe8ec747f5cd7c0c51", size = 135964, upload-time = "2025-12-06T15:54:46.576Z" },
{ url = "https://files.pythonhosted.org/packages/1c/40/820bc63121d2d28818556a2d0a09384a9f0262407cf9fa305e091a8048df/orjson-3.11.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e46c762d9f0e1cfb4ccc8515de7f349abbc95b59cb5a2bd68df5973fdef913f8", size = 139817, upload-time = "2025-12-06T15:54:48.084Z" },
{ url = "https://files.pythonhosted.org/packages/09/c7/3a445ca9a84a0d59d26365fd8898ff52bdfcdcb825bcc6519830371d2364/orjson-3.11.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d7345c759276b798ccd6d77a87136029e71e66a8bbf2d2755cbdde1d82e78706", size = 137336, upload-time = "2025-12-06T15:54:49.426Z" },
{ url = "https://files.pythonhosted.org/packages/9a/b3/dc0d3771f2e5d1f13368f56b339c6782f955c6a20b50465a91acb79fe961/orjson-3.11.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75bc2e59e6a2ac1dd28901d07115abdebc4563b5b07dd612bf64260a201b1c7f", size = 138993, upload-time = "2025-12-06T15:54:50.939Z" },
{ url = "https://files.pythonhosted.org/packages/d1/a2/65267e959de6abe23444659b6e19c888f242bf7725ff927e2292776f6b89/orjson-3.11.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:54aae9b654554c3b4edd61896b978568c6daa16af96fa4681c9b5babd469f863", size = 141070, upload-time = "2025-12-06T15:54:52.414Z" },
{ url = "https://files.pythonhosted.org/packages/63/c9/da44a321b288727a322c6ab17e1754195708786a04f4f9d2220a5076a649/orjson-3.11.5-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:4bdd8d164a871c4ec773f9de0f6fe8769c2d6727879c37a9666ba4183b7f8228", size = 413505, upload-time = "2025-12-06T15:54:53.67Z" },
{ url = "https://files.pythonhosted.org/packages/7f/17/68dc14fa7000eefb3d4d6d7326a190c99bb65e319f02747ef3ebf2452f12/orjson-3.11.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:a261fef929bcf98a60713bf5e95ad067cea16ae345d9a35034e73c3990e927d2", size = 151342, upload-time = "2025-12-06T15:54:55.113Z" },
{ url = "https://files.pythonhosted.org/packages/c4/c5/ccee774b67225bed630a57478529fc026eda33d94fe4c0eac8fe58d4aa52/orjson-3.11.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c028a394c766693c5c9909dec76b24f37e6a1b91999e8d0c0d5feecbe93c3e05", size = 141823, upload-time = "2025-12-06T15:54:56.331Z" },
{ url = "https://files.pythonhosted.org/packages/67/80/5d00e4155d0cd7390ae2087130637671da713959bb558db9bac5e6f6b042/orjson-3.11.5-cp313-cp313-win32.whl", hash = "sha256:2cc79aaad1dfabe1bd2d50ee09814a1253164b3da4c00a78c458d82d04b3bdef", size = 135236, upload-time = "2025-12-06T15:54:57.507Z" },
{ url = "https://files.pythonhosted.org/packages/95/fe/792cc06a84808dbdc20ac6eab6811c53091b42f8e51ecebf14b540e9cfe4/orjson-3.11.5-cp313-cp313-win_amd64.whl", hash = "sha256:ff7877d376add4e16b274e35a3f58b7f37b362abf4aa31863dadacdd20e3a583", size = 133167, upload-time = "2025-12-06T15:54:58.71Z" },
{ url = "https://files.pythonhosted.org/packages/46/2c/d158bd8b50e3b1cfdcf406a7e463f6ffe3f0d167b99634717acdaf5e299f/orjson-3.11.5-cp313-cp313-win_arm64.whl", hash = "sha256:59ac72ea775c88b163ba8d21b0177628bd015c5dd060647bbab6e22da3aad287", size = 126712, upload-time = "2025-12-06T15:54:59.892Z" },
{ url = "https://files.pythonhosted.org/packages/c2/60/77d7b839e317ead7bb225d55bb50f7ea75f47afc489c81199befc5435b50/orjson-3.11.5-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:e446a8ea0a4c366ceafc7d97067bfd55292969143b57e3c846d87fc701e797a0", size = 245252, upload-time = "2025-12-06T15:55:01.127Z" },
{ url = "https://files.pythonhosted.org/packages/f1/aa/d4639163b400f8044cef0fb9aa51b0337be0da3a27187a20d1166e742370/orjson-3.11.5-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:53deb5addae9c22bbe3739298f5f2196afa881ea75944e7720681c7080909a81", size = 129419, upload-time = "2025-12-06T15:55:02.723Z" },
{ url = "https://files.pythonhosted.org/packages/30/94/9eabf94f2e11c671111139edf5ec410d2f21e6feee717804f7e8872d883f/orjson-3.11.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82cd00d49d6063d2b8791da5d4f9d20539c5951f965e45ccf4e96d33505ce68f", size = 132050, upload-time = "2025-12-06T15:55:03.918Z" },
{ url = "https://files.pythonhosted.org/packages/3d/c8/ca10f5c5322f341ea9a9f1097e140be17a88f88d1cfdd29df522970d9744/orjson-3.11.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3fd15f9fc8c203aeceff4fda211157fad114dde66e92e24097b3647a08f4ee9e", size = 130370, upload-time = "2025-12-06T15:55:05.173Z" },
{ url = "https://files.pythonhosted.org/packages/25/d4/e96824476d361ee2edd5c6290ceb8d7edf88d81148a6ce172fc00278ca7f/orjson-3.11.5-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9df95000fbe6777bf9820ae82ab7578e8662051bb5f83d71a28992f539d2cda7", size = 136012, upload-time = "2025-12-06T15:55:06.402Z" },
{ url = "https://files.pythonhosted.org/packages/85/8e/9bc3423308c425c588903f2d103cfcfe2539e07a25d6522900645a6f257f/orjson-3.11.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:92a8d676748fca47ade5bc3da7430ed7767afe51b2f8100e3cd65e151c0eaceb", size = 139809, upload-time = "2025-12-06T15:55:07.656Z" },
{ url = "https://files.pythonhosted.org/packages/e9/3c/b404e94e0b02a232b957c54643ce68d0268dacb67ac33ffdee24008c8b27/orjson-3.11.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aa0f513be38b40234c77975e68805506cad5d57b3dfd8fe3baa7f4f4051e15b4", size = 137332, upload-time = "2025-12-06T15:55:08.961Z" },
{ url = "https://files.pythonhosted.org/packages/51/30/cc2d69d5ce0ad9b84811cdf4a0cd5362ac27205a921da524ff42f26d65e0/orjson-3.11.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa1863e75b92891f553b7922ce4ee10ed06db061e104f2b7815de80cdcb135ad", size = 138983, upload-time = "2025-12-06T15:55:10.595Z" },
{ url = "https://files.pythonhosted.org/packages/0e/87/de3223944a3e297d4707d2fe3b1ffb71437550e165eaf0ca8bbe43ccbcb1/orjson-3.11.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d4be86b58e9ea262617b8ca6251a2f0d63cc132a6da4b5fcc8e0a4128782c829", size = 141069, upload-time = "2025-12-06T15:55:11.832Z" },
{ url = "https://files.pythonhosted.org/packages/65/30/81d5087ae74be33bcae3ff2d80f5ccaa4a8fedc6d39bf65a427a95b8977f/orjson-3.11.5-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:b923c1c13fa02084eb38c9c065afd860a5cff58026813319a06949c3af5732ac", size = 413491, upload-time = "2025-12-06T15:55:13.314Z" },
{ url = "https://files.pythonhosted.org/packages/d0/6f/f6058c21e2fc1efaf918986dbc2da5cd38044f1a2d4b7b91ad17c4acf786/orjson-3.11.5-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:1b6bd351202b2cd987f35a13b5e16471cf4d952b42a73c391cc537974c43ef6d", size = 151375, upload-time = "2025-12-06T15:55:14.715Z" },
{ url = "https://files.pythonhosted.org/packages/54/92/c6921f17d45e110892899a7a563a925b2273d929959ce2ad89e2525b885b/orjson-3.11.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:bb150d529637d541e6af06bbe3d02f5498d628b7f98267ff87647584293ab439", size = 141850, upload-time = "2025-12-06T15:55:15.94Z" },
{ url = "https://files.pythonhosted.org/packages/88/86/cdecb0140a05e1a477b81f24739da93b25070ee01ce7f7242f44a6437594/orjson-3.11.5-cp314-cp314-win32.whl", hash = "sha256:9cc1e55c884921434a84a0c3dd2699eb9f92e7b441d7f53f3941079ec6ce7499", size = 135278, upload-time = "2025-12-06T15:55:17.202Z" },
{ url = "https://files.pythonhosted.org/packages/e4/97/b638d69b1e947d24f6109216997e38922d54dcdcdb1b11c18d7efd2d3c59/orjson-3.11.5-cp314-cp314-win_amd64.whl", hash = "sha256:a4f3cb2d874e03bc7767c8f88adaa1a9a05cecea3712649c3b58589ec7317310", size = 133170, upload-time = "2025-12-06T15:55:18.468Z" },
{ url = "https://files.pythonhosted.org/packages/8f/dd/f4fff4a6fe601b4f8f3ba3aa6da8ac33d17d124491a3b804c662a70e1636/orjson-3.11.5-cp314-cp314-win_arm64.whl", hash = "sha256:38b22f476c351f9a1c43e5b07d8b5a02eb24a6ab8e75f700f7d479d4568346a5", size = 126713, upload-time = "2025-12-06T15:55:19.738Z" },
{ url = "https://files.pythonhosted.org/packages/de/1a/a373746fa6d0e116dd9e54371a7b54622c44d12296d5d0f3ad5e3ff33490/orjson-3.11.7-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a02c833f38f36546ba65a452127633afce4cf0dd7296b753d3bb54e55e5c0174", size = 229140, upload-time = "2026-02-02T15:37:06.082Z" },
{ url = "https://files.pythonhosted.org/packages/52/a2/fa129e749d500f9b183e8a3446a193818a25f60261e9ce143ad61e975208/orjson-3.11.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b63c6e6738d7c3470ad01601e23376aa511e50e1f3931395b9f9c722406d1a67", size = 128670, upload-time = "2026-02-02T15:37:08.002Z" },
{ url = "https://files.pythonhosted.org/packages/08/93/1e82011cd1e0bd051ef9d35bed1aa7fb4ea1f0a055dc2c841b46b43a9ebd/orjson-3.11.7-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:043d3006b7d32c7e233b8cfb1f01c651013ea079e08dcef7189a29abd8befe11", size = 123832, upload-time = "2026-02-02T15:37:09.191Z" },
{ url = "https://files.pythonhosted.org/packages/fe/d8/a26b431ef962c7d55736674dddade876822f3e33223c1f47a36879350d04/orjson-3.11.7-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57036b27ac8a25d81112eb0cc9835cd4833c5b16e1467816adc0015f59e870dc", size = 129171, upload-time = "2026-02-02T15:37:11.112Z" },
{ url = "https://files.pythonhosted.org/packages/a7/19/f47819b84a580f490da260c3ee9ade214cf4cf78ac9ce8c1c758f80fdfc9/orjson-3.11.7-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:733ae23ada68b804b222c44affed76b39e30806d38660bf1eb200520d259cc16", size = 141967, upload-time = "2026-02-02T15:37:12.282Z" },
{ url = "https://files.pythonhosted.org/packages/5b/cd/37ece39a0777ba077fdcdbe4cccae3be8ed00290c14bf8afdc548befc260/orjson-3.11.7-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5fdfad2093bdd08245f2e204d977facd5f871c88c4a71230d5bcbd0e43bf6222", size = 130991, upload-time = "2026-02-02T15:37:13.465Z" },
{ url = "https://files.pythonhosted.org/packages/8f/ed/f2b5d66aa9b6b5c02ff5f120efc7b38c7c4962b21e6be0f00fd99a5c348e/orjson-3.11.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cededd6738e1c153530793998e31c05086582b08315db48ab66649768f326baa", size = 133674, upload-time = "2026-02-02T15:37:14.694Z" },
{ url = "https://files.pythonhosted.org/packages/c4/6e/baa83e68d1aa09fa8c3e5b2c087d01d0a0bd45256de719ed7bc22c07052d/orjson-3.11.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:14f440c7268c8f8633d1b3d443a434bd70cb15686117ea6beff8fdc8f5917a1e", size = 138722, upload-time = "2026-02-02T15:37:16.501Z" },
{ url = "https://files.pythonhosted.org/packages/0c/47/7f8ef4963b772cd56999b535e553f7eb5cd27e9dd6c049baee6f18bfa05d/orjson-3.11.7-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:3a2479753bbb95b0ebcf7969f562cdb9668e6d12416a35b0dda79febf89cdea2", size = 409056, upload-time = "2026-02-02T15:37:17.895Z" },
{ url = "https://files.pythonhosted.org/packages/38/eb/2df104dd2244b3618f25325a656f85cc3277f74bbd91224752410a78f3c7/orjson-3.11.7-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:71924496986275a737f38e3f22b4e0878882b3f7a310d2ff4dc96e812789120c", size = 144196, upload-time = "2026-02-02T15:37:19.349Z" },
{ url = "https://files.pythonhosted.org/packages/b6/2a/ee41de0aa3a6686598661eae2b4ebdff1340c65bfb17fcff8b87138aab21/orjson-3.11.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b4a9eefdc70bf8bf9857f0290f973dec534ac84c35cd6a7f4083be43e7170a8f", size = 134979, upload-time = "2026-02-02T15:37:20.906Z" },
{ url = "https://files.pythonhosted.org/packages/4c/fa/92fc5d3d402b87a8b28277a9ed35386218a6a5287c7fe5ee9b9f02c53fb2/orjson-3.11.7-cp310-cp310-win32.whl", hash = "sha256:ae9e0b37a834cef7ce8f99de6498f8fad4a2c0bf6bfc3d02abd8ed56aa15b2de", size = 127968, upload-time = "2026-02-02T15:37:23.178Z" },
{ url = "https://files.pythonhosted.org/packages/07/29/a576bf36d73d60df06904d3844a9df08e25d59eba64363aaf8ec2f9bff41/orjson-3.11.7-cp310-cp310-win_amd64.whl", hash = "sha256:d772afdb22555f0c58cfc741bdae44180122b3616faa1ecadb595cd526e4c993", size = 125128, upload-time = "2026-02-02T15:37:24.329Z" },
{ url = "https://files.pythonhosted.org/packages/37/02/da6cb01fc6087048d7f61522c327edf4250f1683a58a839fdcc435746dd5/orjson-3.11.7-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9487abc2c2086e7c8eb9a211d2ce8855bae0e92586279d0d27b341d5ad76c85c", size = 228664, upload-time = "2026-02-02T15:37:25.542Z" },
{ url = "https://files.pythonhosted.org/packages/c1/c2/5885e7a5881dba9a9af51bc564e8967225a642b3e03d089289a35054e749/orjson-3.11.7-cp311-cp311-macosx_15_0_arm64.whl", hash = "sha256:79cacb0b52f6004caf92405a7e1f11e6e2de8bdf9019e4f76b44ba045125cd6b", size = 125344, upload-time = "2026-02-02T15:37:26.92Z" },
{ url = "https://files.pythonhosted.org/packages/a4/1d/4e7688de0a92d1caf600dfd5fb70b4c5bfff51dfa61ac555072ef2d0d32a/orjson-3.11.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2e85fe4698b6a56d5e2ebf7ae87544d668eb6bde1ad1226c13f44663f20ec9e", size = 128404, upload-time = "2026-02-02T15:37:28.108Z" },
{ url = "https://files.pythonhosted.org/packages/2f/b2/ec04b74ae03a125db7bd69cffd014b227b7f341e3261bf75b5eb88a1aa92/orjson-3.11.7-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b8d14b71c0b12963fe8a62aac87119f1afdf4cb88a400f61ca5ae581449efcb5", size = 123677, upload-time = "2026-02-02T15:37:30.287Z" },
{ url = "https://files.pythonhosted.org/packages/4c/69/f95bdf960605f08f827f6e3291fe243d8aa9c5c9ff017a8d7232209184c3/orjson-3.11.7-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:91c81ef070c8f3220054115e1ef468b1c9ce8497b4e526cb9f68ab4dc0a7ac62", size = 128950, upload-time = "2026-02-02T15:37:31.595Z" },
{ url = "https://files.pythonhosted.org/packages/a4/1b/de59c57bae1d148ef298852abd31909ac3089cff370dfd4cd84cc99cbc42/orjson-3.11.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:411ebaf34d735e25e358a6d9e7978954a9c9d58cfb47bc6683cdc3964cd2f910", size = 141756, upload-time = "2026-02-02T15:37:32.985Z" },
{ url = "https://files.pythonhosted.org/packages/ee/9e/9decc59f4499f695f65c650f6cfa6cd4c37a3fbe8fa235a0a3614cb54386/orjson-3.11.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a16bcd08ab0bcdfc7e8801d9c4a9cc17e58418e4d48ddc6ded4e9e4b1a94062b", size = 130812, upload-time = "2026-02-02T15:37:34.204Z" },
{ url = "https://files.pythonhosted.org/packages/28/e6/59f932bcabd1eac44e334fe8e3281a92eacfcb450586e1f4bde0423728d8/orjson-3.11.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c0b51672e466fd7e56230ffbae7f1639e18d0ce023351fb75da21b71bc2c960", size = 133444, upload-time = "2026-02-02T15:37:35.446Z" },
{ url = "https://files.pythonhosted.org/packages/f1/36/b0f05c0eaa7ca30bc965e37e6a2956b0d67adb87a9872942d3568da846ae/orjson-3.11.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:136dcd6a2e796dfd9ffca9fc027d778567b0b7c9968d092842d3c323cef88aa8", size = 138609, upload-time = "2026-02-02T15:37:36.657Z" },
{ url = "https://files.pythonhosted.org/packages/b8/03/58ec7d302b8d86944c60c7b4b82975d5161fcce4c9bc8c6cb1d6741b6115/orjson-3.11.7-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:7ba61079379b0ae29e117db13bda5f28d939766e410d321ec1624afc6a0b0504", size = 408918, upload-time = "2026-02-02T15:37:38.076Z" },
{ url = "https://files.pythonhosted.org/packages/06/3a/868d65ef9a8b99be723bd510de491349618abd9f62c826cf206d962db295/orjson-3.11.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0527a4510c300e3b406591b0ba69b5dc50031895b0a93743526a3fc45f59d26e", size = 143998, upload-time = "2026-02-02T15:37:39.706Z" },
{ url = "https://files.pythonhosted.org/packages/5b/c7/1e18e1c83afe3349f4f6dc9e14910f0ae5f82eac756d1412ea4018938535/orjson-3.11.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a709e881723c9b18acddcfb8ba357322491ad553e277cf467e1e7e20e2d90561", size = 134802, upload-time = "2026-02-02T15:37:41.002Z" },
{ url = "https://files.pythonhosted.org/packages/d4/0b/ccb7ee1a65b37e8eeb8b267dc953561d72370e85185e459616d4345bab34/orjson-3.11.7-cp311-cp311-win32.whl", hash = "sha256:c43b8b5bab288b6b90dac410cca7e986a4fa747a2e8f94615aea407da706980d", size = 127828, upload-time = "2026-02-02T15:37:42.241Z" },
{ url = "https://files.pythonhosted.org/packages/af/9e/55c776dffda3f381e0f07d010a4f5f3902bf48eaba1bb7684d301acd4924/orjson-3.11.7-cp311-cp311-win_amd64.whl", hash = "sha256:6543001328aa857187f905308a028935864aefe9968af3848401b6fe80dbb471", size = 124941, upload-time = "2026-02-02T15:37:43.444Z" },
{ url = "https://files.pythonhosted.org/packages/aa/8e/424a620fa7d263b880162505fb107ef5e0afaa765b5b06a88312ac291560/orjson-3.11.7-cp311-cp311-win_arm64.whl", hash = "sha256:1ee5cc7160a821dfe14f130bc8e63e7611051f964b463d9e2a3a573204446a4d", size = 126245, upload-time = "2026-02-02T15:37:45.18Z" },
{ url = "https://files.pythonhosted.org/packages/80/bf/76f4f1665f6983385938f0e2a5d7efa12a58171b8456c252f3bae8a4cf75/orjson-3.11.7-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:bd03ea7606833655048dab1a00734a2875e3e86c276e1d772b2a02556f0d895f", size = 228545, upload-time = "2026-02-02T15:37:46.376Z" },
{ url = "https://files.pythonhosted.org/packages/79/53/6c72c002cb13b5a978a068add59b25a8bdf2800ac1c9c8ecdb26d6d97064/orjson-3.11.7-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:89e440ebc74ce8ab5c7bc4ce6757b4a6b1041becb127df818f6997b5c71aa60b", size = 125224, upload-time = "2026-02-02T15:37:47.697Z" },
{ url = "https://files.pythonhosted.org/packages/2c/83/10e48852865e5dd151bdfe652c06f7da484578ed02c5fca938e3632cb0b8/orjson-3.11.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ede977b5fe5ac91b1dffc0a517ca4542d2ec8a6a4ff7b2652d94f640796342a", size = 128154, upload-time = "2026-02-02T15:37:48.954Z" },
{ url = "https://files.pythonhosted.org/packages/6e/52/a66e22a2b9abaa374b4a081d410edab6d1e30024707b87eab7c734afe28d/orjson-3.11.7-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b7b1dae39230a393df353827c855a5f176271c23434cfd2db74e0e424e693e10", size = 123548, upload-time = "2026-02-02T15:37:50.187Z" },
{ url = "https://files.pythonhosted.org/packages/de/38/605d371417021359f4910c496f764c48ceb8997605f8c25bf1dfe58c0ebe/orjson-3.11.7-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed46f17096e28fb28d2975834836a639af7278aa87c84f68ab08fbe5b8bd75fa", size = 129000, upload-time = "2026-02-02T15:37:51.426Z" },
{ url = "https://files.pythonhosted.org/packages/44/98/af32e842b0ffd2335c89714d48ca4e3917b42f5d6ee5537832e069a4b3ac/orjson-3.11.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3726be79e36e526e3d9c1aceaadbfb4a04ee80a72ab47b3f3c17fefb9812e7b8", size = 141686, upload-time = "2026-02-02T15:37:52.607Z" },
{ url = "https://files.pythonhosted.org/packages/96/0b/fc793858dfa54be6feee940c1463370ece34b3c39c1ca0aa3845f5ba9892/orjson-3.11.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0724e265bc548af1dedebd9cb3d24b4e1c1e685a343be43e87ba922a5c5fff2f", size = 130812, upload-time = "2026-02-02T15:37:53.944Z" },
{ url = "https://files.pythonhosted.org/packages/dc/91/98a52415059db3f374757d0b7f0f16e3b5cd5976c90d1c2b56acaea039e6/orjson-3.11.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7745312efa9e11c17fbd3cb3097262d079da26930ae9ae7ba28fb738367cbad", size = 133440, upload-time = "2026-02-02T15:37:55.615Z" },
{ url = "https://files.pythonhosted.org/packages/dc/b6/cb540117bda61791f46381f8c26c8f93e802892830a6055748d3bb1925ab/orjson-3.11.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f904c24bdeabd4298f7a977ef14ca2a022ca921ed670b92ecd16ab6f3d01f867", size = 138386, upload-time = "2026-02-02T15:37:56.814Z" },
{ url = "https://files.pythonhosted.org/packages/63/1a/50a3201c334a7f17c231eee5f841342190723794e3b06293f26e7cf87d31/orjson-3.11.7-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:b9fc4d0f81f394689e0814617aadc4f2ea0e8025f38c226cbf22d3b5ddbf025d", size = 408853, upload-time = "2026-02-02T15:37:58.291Z" },
{ url = "https://files.pythonhosted.org/packages/87/cd/8de1c67d0be44fdc22701e5989c0d015a2adf391498ad42c4dc589cd3013/orjson-3.11.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:849e38203e5be40b776ed2718e587faf204d184fc9a008ae441f9442320c0cab", size = 144130, upload-time = "2026-02-02T15:38:00.163Z" },
{ url = "https://files.pythonhosted.org/packages/0f/fe/d605d700c35dd55f51710d159fc54516a280923cd1b7e47508982fbb387d/orjson-3.11.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4682d1db3bcebd2b64757e0ddf9e87ae5f00d29d16c5cdf3a62f561d08cc3dd2", size = 134818, upload-time = "2026-02-02T15:38:01.507Z" },
{ url = "https://files.pythonhosted.org/packages/e4/e4/15ecc67edb3ddb3e2f46ae04475f2d294e8b60c1825fbe28a428b93b3fbd/orjson-3.11.7-cp312-cp312-win32.whl", hash = "sha256:f4f7c956b5215d949a1f65334cf9d7612dde38f20a95f2315deef167def91a6f", size = 127923, upload-time = "2026-02-02T15:38:02.75Z" },
{ url = "https://files.pythonhosted.org/packages/34/70/2e0855361f76198a3965273048c8e50a9695d88cd75811a5b46444895845/orjson-3.11.7-cp312-cp312-win_amd64.whl", hash = "sha256:bf742e149121dc5648ba0a08ea0871e87b660467ef168a3a5e53bc1fbd64bb74", size = 125007, upload-time = "2026-02-02T15:38:04.032Z" },
{ url = "https://files.pythonhosted.org/packages/68/40/c2051bd19fc467610fed469dc29e43ac65891571138f476834ca192bc290/orjson-3.11.7-cp312-cp312-win_arm64.whl", hash = "sha256:26c3b9132f783b7d7903bf1efb095fed8d4a3a85ec0d334ee8beff3d7a4749d5", size = 126089, upload-time = "2026-02-02T15:38:05.297Z" },
{ url = "https://files.pythonhosted.org/packages/89/25/6e0e52cac5aab51d7b6dcd257e855e1dec1c2060f6b28566c509b4665f62/orjson-3.11.7-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:1d98b30cc1313d52d4af17d9c3d307b08389752ec5f2e5febdfada70b0f8c733", size = 228390, upload-time = "2026-02-02T15:38:06.8Z" },
{ url = "https://files.pythonhosted.org/packages/a5/29/a77f48d2fc8a05bbc529e5ff481fb43d914f9e383ea2469d4f3d51df3d00/orjson-3.11.7-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:d897e81f8d0cbd2abb82226d1860ad2e1ab3ff16d7b08c96ca00df9d45409ef4", size = 125189, upload-time = "2026-02-02T15:38:08.181Z" },
{ url = "https://files.pythonhosted.org/packages/89/25/0a16e0729a0e6a1504f9d1a13cdd365f030068aab64cec6958396b9969d7/orjson-3.11.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:814be4b49b228cfc0b3c565acf642dd7d13538f966e3ccde61f4f55be3e20785", size = 128106, upload-time = "2026-02-02T15:38:09.41Z" },
{ url = "https://files.pythonhosted.org/packages/66/da/a2e505469d60666a05ab373f1a6322eb671cb2ba3a0ccfc7d4bc97196787/orjson-3.11.7-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d06e5c5fed5caedd2e540d62e5b1c25e8c82431b9e577c33537e5fa4aa909539", size = 123363, upload-time = "2026-02-02T15:38:10.73Z" },
{ url = "https://files.pythonhosted.org/packages/23/bf/ed73f88396ea35c71b38961734ea4a4746f7ca0768bf28fd551d37e48dd0/orjson-3.11.7-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:31c80ce534ac4ea3739c5ee751270646cbc46e45aea7576a38ffec040b4029a1", size = 129007, upload-time = "2026-02-02T15:38:12.138Z" },
{ url = "https://files.pythonhosted.org/packages/73/3c/b05d80716f0225fc9008fbf8ab22841dcc268a626aa550561743714ce3bf/orjson-3.11.7-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f50979824bde13d32b4320eedd513431c921102796d86be3eee0b58e58a3ecd1", size = 141667, upload-time = "2026-02-02T15:38:13.398Z" },
{ url = "https://files.pythonhosted.org/packages/61/e8/0be9b0addd9bf86abfc938e97441dcd0375d494594b1c8ad10fe57479617/orjson-3.11.7-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e54f3808e2b6b945078c41aa8d9b5834b28c50843846e97807e5adb75fa9705", size = 130832, upload-time = "2026-02-02T15:38:14.698Z" },
{ url = "https://files.pythonhosted.org/packages/c9/ec/c68e3b9021a31d9ec15a94931db1410136af862955854ed5dd7e7e4f5bff/orjson-3.11.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a12b80df61aab7b98b490fe9e4879925ba666fccdfcd175252ce4d9035865ace", size = 133373, upload-time = "2026-02-02T15:38:16.109Z" },
{ url = "https://files.pythonhosted.org/packages/d2/45/f3466739aaafa570cc8e77c6dbb853c48bf56e3b43738020e2661e08b0ac/orjson-3.11.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:996b65230271f1a97026fd0e6a753f51fbc0c335d2ad0c6201f711b0da32693b", size = 138307, upload-time = "2026-02-02T15:38:17.453Z" },
{ url = "https://files.pythonhosted.org/packages/e1/84/9f7f02288da1ffb31405c1be07657afd1eecbcb4b64ee2817b6fe0f785fa/orjson-3.11.7-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:ab49d4b2a6a1d415ddb9f37a21e02e0d5dbfe10b7870b21bf779fc21e9156157", size = 408695, upload-time = "2026-02-02T15:38:18.831Z" },
{ url = "https://files.pythonhosted.org/packages/18/07/9dd2f0c0104f1a0295ffbe912bc8d63307a539b900dd9e2c48ef7810d971/orjson-3.11.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:390a1dce0c055ddf8adb6aa94a73b45a4a7d7177b5c584b8d1c1947f2ba60fb3", size = 144099, upload-time = "2026-02-02T15:38:20.28Z" },
{ url = "https://files.pythonhosted.org/packages/a5/66/857a8e4a3292e1f7b1b202883bcdeb43a91566cf59a93f97c53b44bd6801/orjson-3.11.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1eb80451a9c351a71dfaf5b7ccc13ad065405217726b59fdbeadbcc544f9d223", size = 134806, upload-time = "2026-02-02T15:38:22.186Z" },
{ url = "https://files.pythonhosted.org/packages/0a/5b/6ebcf3defc1aab3a338ca777214966851e92efb1f30dc7fc8285216e6d1b/orjson-3.11.7-cp313-cp313-win32.whl", hash = "sha256:7477aa6a6ec6139c5cb1cc7b214643592169a5494d200397c7fc95d740d5fcf3", size = 127914, upload-time = "2026-02-02T15:38:23.511Z" },
{ url = "https://files.pythonhosted.org/packages/00/04/c6f72daca5092e3117840a1b1e88dfc809cc1470cf0734890d0366b684a1/orjson-3.11.7-cp313-cp313-win_amd64.whl", hash = "sha256:b9f95dcdea9d4f805daa9ddf02617a89e484c6985fa03055459f90e87d7a0757", size = 124986, upload-time = "2026-02-02T15:38:24.836Z" },
{ url = "https://files.pythonhosted.org/packages/03/ba/077a0f6f1085d6b806937246860fafbd5b17f3919c70ee3f3d8d9c713f38/orjson-3.11.7-cp313-cp313-win_arm64.whl", hash = "sha256:800988273a014a0541483dc81021247d7eacb0c845a9d1a34a422bc718f41539", size = 126045, upload-time = "2026-02-02T15:38:26.216Z" },
{ url = "https://files.pythonhosted.org/packages/e9/1e/745565dca749813db9a093c5ebc4bac1a9475c64d54b95654336ac3ed961/orjson-3.11.7-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:de0a37f21d0d364954ad5de1970491d7fbd0fb1ef7417d4d56a36dc01ba0c0a0", size = 228391, upload-time = "2026-02-02T15:38:27.757Z" },
{ url = "https://files.pythonhosted.org/packages/46/19/e40f6225da4d3aa0c8dc6e5219c5e87c2063a560fe0d72a88deb59776794/orjson-3.11.7-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:c2428d358d85e8da9d37cba18b8c4047c55222007a84f97156a5b22028dfbfc0", size = 125188, upload-time = "2026-02-02T15:38:29.241Z" },
{ url = "https://files.pythonhosted.org/packages/9d/7e/c4de2babef2c0817fd1f048fd176aa48c37bec8aef53d2fa932983032cce/orjson-3.11.7-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c4bc6c6ac52cdaa267552544c73e486fecbd710b7ac09bc024d5a78555a22f6", size = 128097, upload-time = "2026-02-02T15:38:30.618Z" },
{ url = "https://files.pythonhosted.org/packages/eb/74/233d360632bafd2197f217eee7fb9c9d0229eac0c18128aee5b35b0014fe/orjson-3.11.7-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd0d68edd7dfca1b2eca9361a44ac9f24b078de3481003159929a0573f21a6bf", size = 123364, upload-time = "2026-02-02T15:38:32.363Z" },
{ url = "https://files.pythonhosted.org/packages/79/51/af79504981dd31efe20a9e360eb49c15f06df2b40e7f25a0a52d9ae888e8/orjson-3.11.7-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:623ad1b9548ef63886319c16fa317848e465a21513b31a6ad7b57443c3e0dcf5", size = 129076, upload-time = "2026-02-02T15:38:33.68Z" },
{ url = "https://files.pythonhosted.org/packages/67/e2/da898eb68b72304f8de05ca6715870d09d603ee98d30a27e8a9629abc64b/orjson-3.11.7-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6e776b998ac37c0396093d10290e60283f59cfe0fc3fccbd0ccc4bd04dd19892", size = 141705, upload-time = "2026-02-02T15:38:34.989Z" },
{ url = "https://files.pythonhosted.org/packages/c5/89/15364d92acb3d903b029e28d834edb8780c2b97404cbf7929aa6b9abdb24/orjson-3.11.7-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:652c6c3af76716f4a9c290371ba2e390ede06f6603edb277b481daf37f6f464e", size = 130855, upload-time = "2026-02-02T15:38:36.379Z" },
{ url = "https://files.pythonhosted.org/packages/c2/8b/ecdad52d0b38d4b8f514be603e69ccd5eacf4e7241f972e37e79792212ec/orjson-3.11.7-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a56df3239294ea5964adf074c54bcc4f0ccd21636049a2cf3ca9cf03b5d03cf1", size = 133386, upload-time = "2026-02-02T15:38:37.704Z" },
{ url = "https://files.pythonhosted.org/packages/b9/0e/45e1dcf10e17d0924b7c9162f87ec7b4ca79e28a0548acf6a71788d3e108/orjson-3.11.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:bda117c4148e81f746655d5a3239ae9bd00cb7bc3ca178b5fc5a5997e9744183", size = 138295, upload-time = "2026-02-02T15:38:39.096Z" },
{ url = "https://files.pythonhosted.org/packages/63/d7/4d2e8b03561257af0450f2845b91fbd111d7e526ccdf737267108075e0ba/orjson-3.11.7-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:23d6c20517a97a9daf1d48b580fcdc6f0516c6f4b5038823426033690b4d2650", size = 408720, upload-time = "2026-02-02T15:38:40.634Z" },
{ url = "https://files.pythonhosted.org/packages/78/cf/d45343518282108b29c12a65892445fc51f9319dc3c552ceb51bb5905ed2/orjson-3.11.7-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:8ff206156006da5b847c9304b6308a01e8cdbc8cce824e2779a5ba71c3def141", size = 144152, upload-time = "2026-02-02T15:38:42.262Z" },
{ url = "https://files.pythonhosted.org/packages/a9/3a/d6001f51a7275aacd342e77b735c71fa04125a3f93c36fee4526bc8c654e/orjson-3.11.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:962d046ee1765f74a1da723f4b33e3b228fe3a48bd307acce5021dfefe0e29b2", size = 134814, upload-time = "2026-02-02T15:38:43.627Z" },
{ url = "https://files.pythonhosted.org/packages/1d/d3/f19b47ce16820cc2c480f7f1723e17f6d411b3a295c60c8ad3aa9ff1c96a/orjson-3.11.7-cp314-cp314-win32.whl", hash = "sha256:89e13dd3f89f1c38a9c9eba5fbf7cdc2d1feca82f5f290864b4b7a6aac704576", size = 127997, upload-time = "2026-02-02T15:38:45.06Z" },
{ url = "https://files.pythonhosted.org/packages/12/df/172771902943af54bf661a8d102bdf2e7f932127968080632bda6054b62c/orjson-3.11.7-cp314-cp314-win_amd64.whl", hash = "sha256:845c3e0d8ded9c9271cd79596b9b552448b885b97110f628fb687aee2eed11c1", size = 124985, upload-time = "2026-02-02T15:38:46.388Z" },
{ url = "https://files.pythonhosted.org/packages/6f/1c/f2a8d8a1b17514660a614ce5f7aac74b934e69f5abc2700cc7ced882a009/orjson-3.11.7-cp314-cp314-win_arm64.whl", hash = "sha256:4a2e9c5be347b937a2e0203866f12bba36082e89b402ddb9e927d5822e43088d", size = 126038, upload-time = "2026-02-02T15:38:47.703Z" },
]
[[package]]
@@ -1073,28 +1073,27 @@ wheels = [
[[package]]
name = "ruff"
version = "0.14.13"
version = "0.15.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/50/0a/1914efb7903174b381ee2ffeebb4253e729de57f114e63595114c8ca451f/ruff-0.14.13.tar.gz", hash = "sha256:83cd6c0763190784b99650a20fec7633c59f6ebe41c5cc9d45ee42749563ad47", size = 6059504, upload-time = "2026-01-15T20:15:16.918Z" }
sdist = { url = "https://files.pythonhosted.org/packages/04/dc/4e6ac71b511b141cf626357a3946679abeba4cf67bc7cc5a17920f31e10d/ruff-0.15.1.tar.gz", hash = "sha256:c590fe13fb57c97141ae975c03a1aedb3d3156030cabd740d6ff0b0d601e203f", size = 4540855, upload-time = "2026-02-12T23:09:09.998Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c3/ae/0deefbc65ca74b0ab1fd3917f94dc3b398233346a74b8bbb0a916a1a6bf6/ruff-0.14.13-py3-none-linux_armv6l.whl", hash = "sha256:76f62c62cd37c276cb03a275b198c7c15bd1d60c989f944db08a8c1c2dbec18b", size = 13062418, upload-time = "2026-01-15T20:14:50.779Z" },
{ url = "https://files.pythonhosted.org/packages/47/df/5916604faa530a97a3c154c62a81cb6b735c0cb05d1e26d5ad0f0c8ac48a/ruff-0.14.13-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:914a8023ece0528d5cc33f5a684f5f38199bbb566a04815c2c211d8f40b5d0ed", size = 13442344, upload-time = "2026-01-15T20:15:07.94Z" },
{ url = "https://files.pythonhosted.org/packages/4c/f3/e0e694dd69163c3a1671e102aa574a50357536f18a33375050334d5cd517/ruff-0.14.13-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d24899478c35ebfa730597a4a775d430ad0d5631b8647a3ab368c29b7e7bd063", size = 12354720, upload-time = "2026-01-15T20:15:09.854Z" },
{ url = "https://files.pythonhosted.org/packages/c3/e8/67f5fcbbaee25e8fc3b56cc33e9892eca7ffe09f773c8e5907757a7e3bdb/ruff-0.14.13-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9aaf3870f14d925bbaf18b8a2347ee0ae7d95a2e490e4d4aea6813ed15ebc80e", size = 12774493, upload-time = "2026-01-15T20:15:20.908Z" },
{ url = "https://files.pythonhosted.org/packages/6b/ce/d2e9cb510870b52a9565d885c0d7668cc050e30fa2c8ac3fb1fda15c083d/ruff-0.14.13-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac5b7f63dd3b27cc811850f5ffd8fff845b00ad70e60b043aabf8d6ecc304e09", size = 12815174, upload-time = "2026-01-15T20:15:05.74Z" },
{ url = "https://files.pythonhosted.org/packages/88/00/c38e5da58beebcf4fa32d0ddd993b63dfacefd02ab7922614231330845bf/ruff-0.14.13-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78d2b1097750d90ba82ce4ba676e85230a0ed694178ca5e61aa9b459970b3eb9", size = 13680909, upload-time = "2026-01-15T20:15:14.537Z" },
{ url = "https://files.pythonhosted.org/packages/61/61/cd37c9dd5bd0a3099ba79b2a5899ad417d8f3b04038810b0501a80814fd7/ruff-0.14.13-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:7d0bf87705acbbcb8d4c24b2d77fbb73d40210a95c3903b443cd9e30824a5032", size = 15144215, upload-time = "2026-01-15T20:15:22.886Z" },
{ url = "https://files.pythonhosted.org/packages/56/8a/85502d7edbf98c2df7b8876f316c0157359165e16cdf98507c65c8d07d3d/ruff-0.14.13-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a3eb5da8e2c9e9f13431032fdcbe7681de9ceda5835efee3269417c13f1fed5c", size = 14706067, upload-time = "2026-01-15T20:14:48.271Z" },
{ url = "https://files.pythonhosted.org/packages/7e/2f/de0df127feb2ee8c1e54354dc1179b4a23798f0866019528c938ba439aca/ruff-0.14.13-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:642442b42957093811cd8d2140dfadd19c7417030a7a68cf8d51fcdd5f217427", size = 14133916, upload-time = "2026-01-15T20:14:57.357Z" },
{ url = "https://files.pythonhosted.org/packages/0d/77/9b99686bb9fe07a757c82f6f95e555c7a47801a9305576a9c67e0a31d280/ruff-0.14.13-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4acdf009f32b46f6e8864af19cbf6841eaaed8638e65c8dac845aea0d703c841", size = 13859207, upload-time = "2026-01-15T20:14:55.111Z" },
{ url = "https://files.pythonhosted.org/packages/7d/46/2bdcb34a87a179a4d23022d818c1c236cb40e477faf0d7c9afb6813e5876/ruff-0.14.13-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:591a7f68860ea4e003917d19b5c4f5ac39ff558f162dc753a2c5de897fd5502c", size = 14043686, upload-time = "2026-01-15T20:14:52.841Z" },
{ url = "https://files.pythonhosted.org/packages/1a/a9/5c6a4f56a0512c691cf143371bcf60505ed0f0860f24a85da8bd123b2bf1/ruff-0.14.13-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:774c77e841cc6e046fc3e91623ce0903d1cd07e3a36b1a9fe79b81dab3de506b", size = 12663837, upload-time = "2026-01-15T20:15:18.921Z" },
{ url = "https://files.pythonhosted.org/packages/fe/bb/b920016ece7651fa7fcd335d9d199306665486694d4361547ccb19394c44/ruff-0.14.13-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:61f4e40077a1248436772bb6512db5fc4457fe4c49e7a94ea7c5088655dd21ae", size = 12805867, upload-time = "2026-01-15T20:14:59.272Z" },
{ url = "https://files.pythonhosted.org/packages/7d/b3/0bd909851e5696cd21e32a8fc25727e5f58f1934b3596975503e6e85415c/ruff-0.14.13-py3-none-musllinux_1_2_i686.whl", hash = "sha256:6d02f1428357fae9e98ac7aa94b7e966fd24151088510d32cf6f902d6c09235e", size = 13208528, upload-time = "2026-01-15T20:15:03.732Z" },
{ url = "https://files.pythonhosted.org/packages/3b/3b/e2d94cb613f6bbd5155a75cbe072813756363eba46a3f2177a1fcd0cd670/ruff-0.14.13-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e399341472ce15237be0c0ae5fbceca4b04cd9bebab1a2b2c979e015455d8f0c", size = 13929242, upload-time = "2026-01-15T20:15:11.918Z" },
{ url = "https://files.pythonhosted.org/packages/6a/c5/abd840d4132fd51a12f594934af5eba1d5d27298a6f5b5d6c3be45301caf/ruff-0.14.13-py3-none-win32.whl", hash = "sha256:ef720f529aec113968b45dfdb838ac8934e519711da53a0456038a0efecbd680", size = 12919024, upload-time = "2026-01-15T20:14:43.647Z" },
{ url = "https://files.pythonhosted.org/packages/c2/55/6384b0b8ce731b6e2ade2b5449bf07c0e4c31e8a2e68ea65b3bafadcecc5/ruff-0.14.13-py3-none-win_amd64.whl", hash = "sha256:6070bd026e409734b9257e03e3ef18c6e1a216f0435c6751d7a8ec69cb59abef", size = 14097887, upload-time = "2026-01-15T20:15:01.48Z" },
{ url = "https://files.pythonhosted.org/packages/4d/e1/7348090988095e4e39560cfc2f7555b1b2a7357deba19167b600fdf5215d/ruff-0.14.13-py3-none-win_arm64.whl", hash = "sha256:7ab819e14f1ad9fe39f246cfcc435880ef7a9390d81a2b6ac7e01039083dd247", size = 13080224, upload-time = "2026-01-15T20:14:45.853Z" },
{ url = "https://files.pythonhosted.org/packages/23/bf/e6e4324238c17f9d9120a9d60aa99a7daaa21204c07fcd84e2ef03bb5fd1/ruff-0.15.1-py3-none-linux_armv6l.whl", hash = "sha256:b101ed7cf4615bda6ffe65bdb59f964e9f4a0d3f85cbf0e54f0ab76d7b90228a", size = 10367819, upload-time = "2026-02-12T23:09:03.598Z" },
{ url = "https://files.pythonhosted.org/packages/b3/ea/c8f89d32e7912269d38c58f3649e453ac32c528f93bb7f4219258be2e7ed/ruff-0.15.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:939c995e9277e63ea632cc8d3fae17aa758526f49a9a850d2e7e758bfef46602", size = 10798618, upload-time = "2026-02-12T23:09:22.928Z" },
{ url = "https://files.pythonhosted.org/packages/5e/0f/1d0d88bc862624247d82c20c10d4c0f6bb2f346559d8af281674cf327f15/ruff-0.15.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1d83466455fdefe60b8d9c8df81d3c1bbb2115cede53549d3b522ce2bc703899", size = 10148518, upload-time = "2026-02-12T23:08:58.339Z" },
{ url = "https://files.pythonhosted.org/packages/f5/c8/291c49cefaa4a9248e986256df2ade7add79388fe179e0691be06fae6f37/ruff-0.15.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9457e3c3291024866222b96108ab2d8265b477e5b1534c7ddb1810904858d16", size = 10518811, upload-time = "2026-02-12T23:09:31.865Z" },
{ url = "https://files.pythonhosted.org/packages/c3/1a/f5707440e5ae43ffa5365cac8bbb91e9665f4a883f560893829cf16a606b/ruff-0.15.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:92c92b003e9d4f7fbd33b1867bb15a1b785b1735069108dfc23821ba045b29bc", size = 10196169, upload-time = "2026-02-12T23:09:17.306Z" },
{ url = "https://files.pythonhosted.org/packages/2a/ff/26ddc8c4da04c8fd3ee65a89c9fb99eaa5c30394269d424461467be2271f/ruff-0.15.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fe5c41ab43e3a06778844c586251eb5a510f67125427625f9eb2b9526535779", size = 10990491, upload-time = "2026-02-12T23:09:25.503Z" },
{ url = "https://files.pythonhosted.org/packages/fc/00/50920cb385b89413f7cdb4bb9bc8fc59c1b0f30028d8bccc294189a54955/ruff-0.15.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66a6dd6df4d80dc382c6484f8ce1bcceb55c32e9f27a8b94c32f6c7331bf14fb", size = 11843280, upload-time = "2026-02-12T23:09:19.88Z" },
{ url = "https://files.pythonhosted.org/packages/5d/6d/2f5cad8380caf5632a15460c323ae326f1e1a2b5b90a6ee7519017a017ca/ruff-0.15.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6a4a42cbb8af0bda9bcd7606b064d7c0bc311a88d141d02f78920be6acb5aa83", size = 11274336, upload-time = "2026-02-12T23:09:14.907Z" },
{ url = "https://files.pythonhosted.org/packages/a3/1d/5f56cae1d6c40b8a318513599b35ea4b075d7dc1cd1d04449578c29d1d75/ruff-0.15.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ab064052c31dddada35079901592dfba2e05f5b1e43af3954aafcbc1096a5b2", size = 11137288, upload-time = "2026-02-12T23:09:07.475Z" },
{ url = "https://files.pythonhosted.org/packages/cd/20/6f8d7d8f768c93b0382b33b9306b3b999918816da46537d5a61635514635/ruff-0.15.1-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:5631c940fe9fe91f817a4c2ea4e81f47bee3ca4aa646134a24374f3c19ad9454", size = 11070681, upload-time = "2026-02-12T23:08:55.43Z" },
{ url = "https://files.pythonhosted.org/packages/9a/67/d640ac76069f64cdea59dba02af2e00b1fa30e2103c7f8d049c0cff4cafd/ruff-0.15.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:68138a4ba184b4691ccdc39f7795c66b3c68160c586519e7e8444cf5a53e1b4c", size = 10486401, upload-time = "2026-02-12T23:09:27.927Z" },
{ url = "https://files.pythonhosted.org/packages/65/3d/e1429f64a3ff89297497916b88c32a5cc88eeca7e9c787072d0e7f1d3e1e/ruff-0.15.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:518f9af03bfc33c03bdb4cb63fabc935341bb7f54af500f92ac309ecfbba6330", size = 10197452, upload-time = "2026-02-12T23:09:12.147Z" },
{ url = "https://files.pythonhosted.org/packages/78/83/e2c3bade17dad63bf1e1c2ffaf11490603b760be149e1419b07049b36ef2/ruff-0.15.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:da79f4d6a826caaea95de0237a67e33b81e6ec2e25fc7e1993a4015dffca7c61", size = 10693900, upload-time = "2026-02-12T23:09:34.418Z" },
{ url = "https://files.pythonhosted.org/packages/a1/27/fdc0e11a813e6338e0706e8b39bb7a1d61ea5b36873b351acee7e524a72a/ruff-0.15.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:3dd86dccb83cd7d4dcfac303ffc277e6048600dfc22e38158afa208e8bf94a1f", size = 11227302, upload-time = "2026-02-12T23:09:36.536Z" },
{ url = "https://files.pythonhosted.org/packages/f6/58/ac864a75067dcbd3b95be5ab4eb2b601d7fbc3d3d736a27e391a4f92a5c1/ruff-0.15.1-py3-none-win32.whl", hash = "sha256:660975d9cb49b5d5278b12b03bb9951d554543a90b74ed5d366b20e2c57c2098", size = 10462555, upload-time = "2026-02-12T23:09:29.899Z" },
{ url = "https://files.pythonhosted.org/packages/e0/5e/d4ccc8a27ecdb78116feac4935dfc39d1304536f4296168f91ed3ec00cd2/ruff-0.15.1-py3-none-win_amd64.whl", hash = "sha256:c820fef9dd5d4172a6570e5721704a96c6679b80cf7be41659ed439653f62336", size = 11599956, upload-time = "2026-02-12T23:09:01.157Z" },
{ url = "https://files.pythonhosted.org/packages/2a/07/5bda6a85b220c64c65686bc85bd0bbb23b29c62b3a9f9433fa55f17cda93/ruff-0.15.1-py3-none-win_arm64.whl", hash = "sha256:5ff7d5f0f88567850f45081fac8f4ec212be8d0b963e385c3f7d0d2eb4899416", size = 10874604, upload-time = "2026-02-12T23:09:05.515Z" },
]
[[package]]
+22 -23
View File
@@ -249,7 +249,7 @@ wheels = [
[[package]]
name = "langchain-core"
version = "1.2.7"
version = "1.2.11"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "jsonpatch" },
@@ -261,9 +261,9 @@ dependencies = [
{ name = "typing-extensions" },
{ name = "uuid-utils" },
]
sdist = { url = "https://files.pythonhosted.org/packages/a2/0e/664d8d81b3493e09cbab72448d2f9d693d1fa5aa2bcc488602203a9b6da0/langchain_core-1.2.7.tar.gz", hash = "sha256:e1460639f96c352b4a41c375f25aeb8d16ffc1769499fb1c20503aad59305ced", size = 837039, upload-time = "2026-01-09T17:44:25.505Z" }
sdist = { url = "https://files.pythonhosted.org/packages/12/17/1943cedfc118e04b8128e4c3e1dbf0fa0ea58eefddbb6198cfd699d19f01/langchain_core-1.2.11.tar.gz", hash = "sha256:f164bb36602dd74a3a50c1334fca75309ad5ed95767acdfdbb9fa95ce28a1e01", size = 831211, upload-time = "2026-02-10T20:35:28.35Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/6e/6f/34a9fba14d191a67f7e2ee3dbce3e9b86d2fa7310e2c7f2c713583481bd2/langchain_core-1.2.7-py3-none-any.whl", hash = "sha256:452f4fef7a3d883357b22600788d37e3d8854ef29da345b7ac7099f33c31828b", size = 490232, upload-time = "2026-01-09T17:44:24.236Z" },
{ url = "https://files.pythonhosted.org/packages/10/30/1f80e3fc674353cad975ed5294353d42512535d2094ef032c06454c2c873/langchain_core-1.2.11-py3-none-any.whl", hash = "sha256:ae11ceb8dda60d0b9d09e763116e592f1683327c17be5b715f350fd29aee65d3", size = 500062, upload-time = "2026-02-10T20:35:26.698Z" },
]
[[package]]
@@ -997,28 +997,27 @@ wheels = [
[[package]]
name = "ruff"
version = "0.14.13"
version = "0.15.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/50/0a/1914efb7903174b381ee2ffeebb4253e729de57f114e63595114c8ca451f/ruff-0.14.13.tar.gz", hash = "sha256:83cd6c0763190784b99650a20fec7633c59f6ebe41c5cc9d45ee42749563ad47", size = 6059504, upload-time = "2026-01-15T20:15:16.918Z" }
sdist = { url = "https://files.pythonhosted.org/packages/04/dc/4e6ac71b511b141cf626357a3946679abeba4cf67bc7cc5a17920f31e10d/ruff-0.15.1.tar.gz", hash = "sha256:c590fe13fb57c97141ae975c03a1aedb3d3156030cabd740d6ff0b0d601e203f", size = 4540855, upload-time = "2026-02-12T23:09:09.998Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c3/ae/0deefbc65ca74b0ab1fd3917f94dc3b398233346a74b8bbb0a916a1a6bf6/ruff-0.14.13-py3-none-linux_armv6l.whl", hash = "sha256:76f62c62cd37c276cb03a275b198c7c15bd1d60c989f944db08a8c1c2dbec18b", size = 13062418, upload-time = "2026-01-15T20:14:50.779Z" },
{ url = "https://files.pythonhosted.org/packages/47/df/5916604faa530a97a3c154c62a81cb6b735c0cb05d1e26d5ad0f0c8ac48a/ruff-0.14.13-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:914a8023ece0528d5cc33f5a684f5f38199bbb566a04815c2c211d8f40b5d0ed", size = 13442344, upload-time = "2026-01-15T20:15:07.94Z" },
{ url = "https://files.pythonhosted.org/packages/4c/f3/e0e694dd69163c3a1671e102aa574a50357536f18a33375050334d5cd517/ruff-0.14.13-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d24899478c35ebfa730597a4a775d430ad0d5631b8647a3ab368c29b7e7bd063", size = 12354720, upload-time = "2026-01-15T20:15:09.854Z" },
{ url = "https://files.pythonhosted.org/packages/c3/e8/67f5fcbbaee25e8fc3b56cc33e9892eca7ffe09f773c8e5907757a7e3bdb/ruff-0.14.13-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9aaf3870f14d925bbaf18b8a2347ee0ae7d95a2e490e4d4aea6813ed15ebc80e", size = 12774493, upload-time = "2026-01-15T20:15:20.908Z" },
{ url = "https://files.pythonhosted.org/packages/6b/ce/d2e9cb510870b52a9565d885c0d7668cc050e30fa2c8ac3fb1fda15c083d/ruff-0.14.13-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac5b7f63dd3b27cc811850f5ffd8fff845b00ad70e60b043aabf8d6ecc304e09", size = 12815174, upload-time = "2026-01-15T20:15:05.74Z" },
{ url = "https://files.pythonhosted.org/packages/88/00/c38e5da58beebcf4fa32d0ddd993b63dfacefd02ab7922614231330845bf/ruff-0.14.13-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78d2b1097750d90ba82ce4ba676e85230a0ed694178ca5e61aa9b459970b3eb9", size = 13680909, upload-time = "2026-01-15T20:15:14.537Z" },
{ url = "https://files.pythonhosted.org/packages/61/61/cd37c9dd5bd0a3099ba79b2a5899ad417d8f3b04038810b0501a80814fd7/ruff-0.14.13-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:7d0bf87705acbbcb8d4c24b2d77fbb73d40210a95c3903b443cd9e30824a5032", size = 15144215, upload-time = "2026-01-15T20:15:22.886Z" },
{ url = "https://files.pythonhosted.org/packages/56/8a/85502d7edbf98c2df7b8876f316c0157359165e16cdf98507c65c8d07d3d/ruff-0.14.13-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a3eb5da8e2c9e9f13431032fdcbe7681de9ceda5835efee3269417c13f1fed5c", size = 14706067, upload-time = "2026-01-15T20:14:48.271Z" },
{ url = "https://files.pythonhosted.org/packages/7e/2f/de0df127feb2ee8c1e54354dc1179b4a23798f0866019528c938ba439aca/ruff-0.14.13-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:642442b42957093811cd8d2140dfadd19c7417030a7a68cf8d51fcdd5f217427", size = 14133916, upload-time = "2026-01-15T20:14:57.357Z" },
{ url = "https://files.pythonhosted.org/packages/0d/77/9b99686bb9fe07a757c82f6f95e555c7a47801a9305576a9c67e0a31d280/ruff-0.14.13-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4acdf009f32b46f6e8864af19cbf6841eaaed8638e65c8dac845aea0d703c841", size = 13859207, upload-time = "2026-01-15T20:14:55.111Z" },
{ url = "https://files.pythonhosted.org/packages/7d/46/2bdcb34a87a179a4d23022d818c1c236cb40e477faf0d7c9afb6813e5876/ruff-0.14.13-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:591a7f68860ea4e003917d19b5c4f5ac39ff558f162dc753a2c5de897fd5502c", size = 14043686, upload-time = "2026-01-15T20:14:52.841Z" },
{ url = "https://files.pythonhosted.org/packages/1a/a9/5c6a4f56a0512c691cf143371bcf60505ed0f0860f24a85da8bd123b2bf1/ruff-0.14.13-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:774c77e841cc6e046fc3e91623ce0903d1cd07e3a36b1a9fe79b81dab3de506b", size = 12663837, upload-time = "2026-01-15T20:15:18.921Z" },
{ url = "https://files.pythonhosted.org/packages/fe/bb/b920016ece7651fa7fcd335d9d199306665486694d4361547ccb19394c44/ruff-0.14.13-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:61f4e40077a1248436772bb6512db5fc4457fe4c49e7a94ea7c5088655dd21ae", size = 12805867, upload-time = "2026-01-15T20:14:59.272Z" },
{ url = "https://files.pythonhosted.org/packages/7d/b3/0bd909851e5696cd21e32a8fc25727e5f58f1934b3596975503e6e85415c/ruff-0.14.13-py3-none-musllinux_1_2_i686.whl", hash = "sha256:6d02f1428357fae9e98ac7aa94b7e966fd24151088510d32cf6f902d6c09235e", size = 13208528, upload-time = "2026-01-15T20:15:03.732Z" },
{ url = "https://files.pythonhosted.org/packages/3b/3b/e2d94cb613f6bbd5155a75cbe072813756363eba46a3f2177a1fcd0cd670/ruff-0.14.13-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e399341472ce15237be0c0ae5fbceca4b04cd9bebab1a2b2c979e015455d8f0c", size = 13929242, upload-time = "2026-01-15T20:15:11.918Z" },
{ url = "https://files.pythonhosted.org/packages/6a/c5/abd840d4132fd51a12f594934af5eba1d5d27298a6f5b5d6c3be45301caf/ruff-0.14.13-py3-none-win32.whl", hash = "sha256:ef720f529aec113968b45dfdb838ac8934e519711da53a0456038a0efecbd680", size = 12919024, upload-time = "2026-01-15T20:14:43.647Z" },
{ url = "https://files.pythonhosted.org/packages/c2/55/6384b0b8ce731b6e2ade2b5449bf07c0e4c31e8a2e68ea65b3bafadcecc5/ruff-0.14.13-py3-none-win_amd64.whl", hash = "sha256:6070bd026e409734b9257e03e3ef18c6e1a216f0435c6751d7a8ec69cb59abef", size = 14097887, upload-time = "2026-01-15T20:15:01.48Z" },
{ url = "https://files.pythonhosted.org/packages/4d/e1/7348090988095e4e39560cfc2f7555b1b2a7357deba19167b600fdf5215d/ruff-0.14.13-py3-none-win_arm64.whl", hash = "sha256:7ab819e14f1ad9fe39f246cfcc435880ef7a9390d81a2b6ac7e01039083dd247", size = 13080224, upload-time = "2026-01-15T20:14:45.853Z" },
{ url = "https://files.pythonhosted.org/packages/23/bf/e6e4324238c17f9d9120a9d60aa99a7daaa21204c07fcd84e2ef03bb5fd1/ruff-0.15.1-py3-none-linux_armv6l.whl", hash = "sha256:b101ed7cf4615bda6ffe65bdb59f964e9f4a0d3f85cbf0e54f0ab76d7b90228a", size = 10367819, upload-time = "2026-02-12T23:09:03.598Z" },
{ url = "https://files.pythonhosted.org/packages/b3/ea/c8f89d32e7912269d38c58f3649e453ac32c528f93bb7f4219258be2e7ed/ruff-0.15.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:939c995e9277e63ea632cc8d3fae17aa758526f49a9a850d2e7e758bfef46602", size = 10798618, upload-time = "2026-02-12T23:09:22.928Z" },
{ url = "https://files.pythonhosted.org/packages/5e/0f/1d0d88bc862624247d82c20c10d4c0f6bb2f346559d8af281674cf327f15/ruff-0.15.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1d83466455fdefe60b8d9c8df81d3c1bbb2115cede53549d3b522ce2bc703899", size = 10148518, upload-time = "2026-02-12T23:08:58.339Z" },
{ url = "https://files.pythonhosted.org/packages/f5/c8/291c49cefaa4a9248e986256df2ade7add79388fe179e0691be06fae6f37/ruff-0.15.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9457e3c3291024866222b96108ab2d8265b477e5b1534c7ddb1810904858d16", size = 10518811, upload-time = "2026-02-12T23:09:31.865Z" },
{ url = "https://files.pythonhosted.org/packages/c3/1a/f5707440e5ae43ffa5365cac8bbb91e9665f4a883f560893829cf16a606b/ruff-0.15.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:92c92b003e9d4f7fbd33b1867bb15a1b785b1735069108dfc23821ba045b29bc", size = 10196169, upload-time = "2026-02-12T23:09:17.306Z" },
{ url = "https://files.pythonhosted.org/packages/2a/ff/26ddc8c4da04c8fd3ee65a89c9fb99eaa5c30394269d424461467be2271f/ruff-0.15.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fe5c41ab43e3a06778844c586251eb5a510f67125427625f9eb2b9526535779", size = 10990491, upload-time = "2026-02-12T23:09:25.503Z" },
{ url = "https://files.pythonhosted.org/packages/fc/00/50920cb385b89413f7cdb4bb9bc8fc59c1b0f30028d8bccc294189a54955/ruff-0.15.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66a6dd6df4d80dc382c6484f8ce1bcceb55c32e9f27a8b94c32f6c7331bf14fb", size = 11843280, upload-time = "2026-02-12T23:09:19.88Z" },
{ url = "https://files.pythonhosted.org/packages/5d/6d/2f5cad8380caf5632a15460c323ae326f1e1a2b5b90a6ee7519017a017ca/ruff-0.15.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6a4a42cbb8af0bda9bcd7606b064d7c0bc311a88d141d02f78920be6acb5aa83", size = 11274336, upload-time = "2026-02-12T23:09:14.907Z" },
{ url = "https://files.pythonhosted.org/packages/a3/1d/5f56cae1d6c40b8a318513599b35ea4b075d7dc1cd1d04449578c29d1d75/ruff-0.15.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ab064052c31dddada35079901592dfba2e05f5b1e43af3954aafcbc1096a5b2", size = 11137288, upload-time = "2026-02-12T23:09:07.475Z" },
{ url = "https://files.pythonhosted.org/packages/cd/20/6f8d7d8f768c93b0382b33b9306b3b999918816da46537d5a61635514635/ruff-0.15.1-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:5631c940fe9fe91f817a4c2ea4e81f47bee3ca4aa646134a24374f3c19ad9454", size = 11070681, upload-time = "2026-02-12T23:08:55.43Z" },
{ url = "https://files.pythonhosted.org/packages/9a/67/d640ac76069f64cdea59dba02af2e00b1fa30e2103c7f8d049c0cff4cafd/ruff-0.15.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:68138a4ba184b4691ccdc39f7795c66b3c68160c586519e7e8444cf5a53e1b4c", size = 10486401, upload-time = "2026-02-12T23:09:27.927Z" },
{ url = "https://files.pythonhosted.org/packages/65/3d/e1429f64a3ff89297497916b88c32a5cc88eeca7e9c787072d0e7f1d3e1e/ruff-0.15.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:518f9af03bfc33c03bdb4cb63fabc935341bb7f54af500f92ac309ecfbba6330", size = 10197452, upload-time = "2026-02-12T23:09:12.147Z" },
{ url = "https://files.pythonhosted.org/packages/78/83/e2c3bade17dad63bf1e1c2ffaf11490603b760be149e1419b07049b36ef2/ruff-0.15.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:da79f4d6a826caaea95de0237a67e33b81e6ec2e25fc7e1993a4015dffca7c61", size = 10693900, upload-time = "2026-02-12T23:09:34.418Z" },
{ url = "https://files.pythonhosted.org/packages/a1/27/fdc0e11a813e6338e0706e8b39bb7a1d61ea5b36873b351acee7e524a72a/ruff-0.15.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:3dd86dccb83cd7d4dcfac303ffc277e6048600dfc22e38158afa208e8bf94a1f", size = 11227302, upload-time = "2026-02-12T23:09:36.536Z" },
{ url = "https://files.pythonhosted.org/packages/f6/58/ac864a75067dcbd3b95be5ab4eb2b601d7fbc3d3d736a27e391a4f92a5c1/ruff-0.15.1-py3-none-win32.whl", hash = "sha256:660975d9cb49b5d5278b12b03bb9951d554543a90b74ed5d366b20e2c57c2098", size = 10462555, upload-time = "2026-02-12T23:09:29.899Z" },
{ url = "https://files.pythonhosted.org/packages/e0/5e/d4ccc8a27ecdb78116feac4935dfc39d1304536f4296168f91ed3ec00cd2/ruff-0.15.1-py3-none-win_amd64.whl", hash = "sha256:c820fef9dd5d4172a6570e5721704a96c6679b80cf7be41659ed439653f62336", size = 11599956, upload-time = "2026-02-12T23:09:01.157Z" },
{ url = "https://files.pythonhosted.org/packages/2a/07/5bda6a85b220c64c65686bc85bd0bbb23b29c62b3a9f9433fa55f17cda93/ruff-0.15.1-py3-none-win_arm64.whl", hash = "sha256:5ff7d5f0f88567850f45081fac8f4ec212be8d0b963e385c3f7d0d2eb4899416", size = 10874604, upload-time = "2026-02-12T23:09:05.515Z" },
]
[[package]]
@@ -51,6 +51,8 @@ class CheckpointMetadata(TypedDict, total=False):
Mapping from checkpoint namespace to checkpoint ID.
"""
run_id: str
"""The ID of the run that created this checkpoint."""
ChannelVersions = dict[str, str | int | float]
@@ -268,6 +270,45 @@ class BaseCheckpointSaver(Generic[V]):
"""
raise NotImplementedError
def delete_for_runs(
self,
run_ids: Sequence[str],
) -> None:
"""Delete all checkpoints and writes associated with the given run IDs.
Args:
run_ids: The run IDs whose checkpoints should be deleted.
"""
raise NotImplementedError
def copy_thread(
self,
source_thread_id: str,
target_thread_id: str,
) -> None:
"""Copy all checkpoints and writes from one thread to another.
Args:
source_thread_id: The thread ID to copy from.
target_thread_id: The thread ID to copy to.
"""
raise NotImplementedError
def prune(
self,
thread_ids: Sequence[str],
*,
strategy: str = "keep_latest",
) -> None:
"""Prune checkpoints for the given threads.
Args:
thread_ids: The thread IDs to prune.
strategy: The pruning strategy. `"keep_latest"` retains only the most
recent checkpoint per namespace. `"delete"` removes all checkpoints.
"""
raise NotImplementedError
async def aget(self, config: RunnableConfig) -> Checkpoint | None:
"""Asynchronously fetch a checkpoint using the given configuration.
@@ -373,6 +414,45 @@ class BaseCheckpointSaver(Generic[V]):
"""
raise NotImplementedError
async def adelete_for_runs(
self,
run_ids: Sequence[str],
) -> None:
"""Asynchronously delete all checkpoints and writes for the given run IDs.
Args:
run_ids: The run IDs whose checkpoints should be deleted.
"""
raise NotImplementedError
async def acopy_thread(
self,
source_thread_id: str,
target_thread_id: str,
) -> None:
"""Asynchronously copy all checkpoints and writes from one thread to another.
Args:
source_thread_id: The thread ID to copy from.
target_thread_id: The thread ID to copy to.
"""
raise NotImplementedError
async def aprune(
self,
thread_ids: Sequence[str],
*,
strategy: str = "keep_latest",
) -> None:
"""Asynchronously prune checkpoints for the given threads.
Args:
thread_ids: The thread IDs to prune.
strategy: The pruning strategy. `"keep_latest"` retains only the most
recent checkpoint per namespace. `"delete"` removes all checkpoints.
"""
raise NotImplementedError
def get_next_version(self, current: V | None, channel: None) -> V:
"""Generate the next version ID for a channel.
+75 -75
View File
@@ -267,7 +267,7 @@ wheels = [
[[package]]
name = "langchain-core"
version = "1.2.7"
version = "1.2.13"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "jsonpatch" },
@@ -279,9 +279,9 @@ dependencies = [
{ name = "typing-extensions" },
{ name = "uuid-utils" },
]
sdist = { url = "https://files.pythonhosted.org/packages/a2/0e/664d8d81b3493e09cbab72448d2f9d693d1fa5aa2bcc488602203a9b6da0/langchain_core-1.2.7.tar.gz", hash = "sha256:e1460639f96c352b4a41c375f25aeb8d16ffc1769499fb1c20503aad59305ced", size = 837039, upload-time = "2026-01-09T17:44:25.505Z" }
sdist = { url = "https://files.pythonhosted.org/packages/fb/bb/c501ca60556c11ac80d1454bdcac63cb33583ce4e64fc4535ad5a7d5c6ba/langchain_core-1.2.13.tar.gz", hash = "sha256:d2773d0d0130a356378db9a858cfeef64c3d64bc03722f1d4d6c40eb46fdf01b", size = 831612, upload-time = "2026-02-15T07:45:57.014Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/6e/6f/34a9fba14d191a67f7e2ee3dbce3e9b86d2fa7310e2c7f2c713583481bd2/langchain_core-1.2.7-py3-none-any.whl", hash = "sha256:452f4fef7a3d883357b22600788d37e3d8854ef29da345b7ac7099f33c31828b", size = 490232, upload-time = "2026-01-09T17:44:24.236Z" },
{ url = "https://files.pythonhosted.org/packages/12/ab/60fd69e5d55f67d422baefddaaca523c42cd7510ab6aeb17db6ae57fb107/langchain_core-1.2.13-py3-none-any.whl", hash = "sha256:b31823e28d3eff1e237096d0bd3bf80c6f9624eb471a9496dbfbd427779f8d82", size = 500485, upload-time = "2026-02-15T07:45:55.422Z" },
]
[[package]]
@@ -755,57 +755,58 @@ wheels = [
[[package]]
name = "ormsgpack"
version = "1.12.1"
version = "1.12.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/fe/96/34c40d621996c2f377a18decbd3c59f031dde73c3ba47d1e1e8f29a05aaa/ormsgpack-1.12.1.tar.gz", hash = "sha256:a3877fde1e4f27a39f92681a0aab6385af3a41d0c25375d33590ae20410ea2ac", size = 39476, upload-time = "2025-12-14T07:57:43.248Z" }
sdist = { url = "https://files.pythonhosted.org/packages/12/0c/f1761e21486942ab9bb6feaebc610fa074f7c5e496e6962dea5873348077/ormsgpack-1.12.2.tar.gz", hash = "sha256:944a2233640273bee67521795a73cf1e959538e0dfb7ac635505010455e53b33", size = 39031, upload-time = "2026-01-18T20:55:28.023Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b5/da/caf25cc54d6870089a0b5614c4c5914dd3fae45f9f7f84a32445ad0612e3/ormsgpack-1.12.1-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:62e3614cab63fa5aa42f5f0ca3cd12899f0bfc5eb8a5a0ebab09d571c89d427d", size = 376182, upload-time = "2025-12-14T07:56:46.094Z" },
{ url = "https://files.pythonhosted.org/packages/fc/02/ccc9170c6bee86f428707f15b5ad68d42c71d43856e1b8e37cdfea50af5b/ormsgpack-1.12.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:86d9fbf85c05c69c33c229d2eba7c8c3500a56596cd8348131c918acd040d6af", size = 202339, upload-time = "2025-12-14T07:56:47.609Z" },
{ url = "https://files.pythonhosted.org/packages/86/c7/10309a5a6421adaedab710a72470143d664bb0a043cc095c1311878325a0/ormsgpack-1.12.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8d246e66f09d8e0f96e770829149ee83206e90ed12f5987998bb7be84aec99fe", size = 210720, upload-time = "2025-12-14T07:56:48.66Z" },
{ url = "https://files.pythonhosted.org/packages/1b/b4/92a0f7a00c5f0c71b51dc3112e53b1ca937b9891a08979d06524db11b799/ormsgpack-1.12.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cfc2c830a1ed2d00de713d08c9e62efa699e8fd29beafa626aaebe466f583ebb", size = 211264, upload-time = "2025-12-14T07:56:49.976Z" },
{ url = "https://files.pythonhosted.org/packages/33/fa/5cce85c8e58fcaa048c75fbbe37816a1b3fb58ba4289a7dedc4f4ed9ce82/ormsgpack-1.12.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:bc892757d8f9eea5208268a527cf93c98409802f6a9f7c8d71a7b8f9ba5cb944", size = 386076, upload-time = "2025-12-14T07:56:51.74Z" },
{ url = "https://files.pythonhosted.org/packages/88/d0/f18d258c733eb22eadad748659f7984d0b6a851fb3deefcb33f50e9a947a/ormsgpack-1.12.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:0de1dbcf11ea739ac4a882b43d5c2055e6d99ce64e8d6502e25d6d881700c017", size = 479570, upload-time = "2025-12-14T07:56:52.912Z" },
{ url = "https://files.pythonhosted.org/packages/3f/3a/b362dff090f4740090fe51d512f24b1e320d1f96497ebf9248e2a04ac88f/ormsgpack-1.12.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d5065dfb9ec4db93241c60847624d9aeef4ccb449c26a018c216b55c69be83c0", size = 387859, upload-time = "2025-12-14T07:56:53.968Z" },
{ url = "https://files.pythonhosted.org/packages/7c/8a/d948965598b2b7872800076da5c02573aa72f716be57a3d4fe60490b2a2a/ormsgpack-1.12.1-cp310-cp310-win_amd64.whl", hash = "sha256:7d17103c4726181d7000c61b751c881f1b6f401d146df12da028fc730227df19", size = 115906, upload-time = "2025-12-14T07:56:55.068Z" },
{ url = "https://files.pythonhosted.org/packages/57/e2/f5b89365c8dc8025c27d31316038f1c103758ddbf87dc0fa8e3f78f66907/ormsgpack-1.12.1-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:4038f59ae0e19dac5e5d9aae4ec17ff84a79e046342ee73ccdecf3547ecf0d34", size = 376180, upload-time = "2025-12-14T07:56:56.521Z" },
{ url = "https://files.pythonhosted.org/packages/ca/87/3f694e06f5e32c6d65066f53b4a025282a5072b6b336c17560b00e04606d/ormsgpack-1.12.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16c63b0c5a3eec467e4bb33a14dabba076b7d934dff62898297b5c0b5f7c3cb3", size = 202338, upload-time = "2025-12-14T07:56:57.585Z" },
{ url = "https://files.pythonhosted.org/packages/e5/f5/6d95d7b7c11f97a92522082fc7e5d1ab34537929f1e13f4c369f392f19d0/ormsgpack-1.12.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:74fd6a8e037eb310dda865298e8d122540af00fe5658ec18b97a1d34f4012e4d", size = 210720, upload-time = "2025-12-14T07:56:58.968Z" },
{ url = "https://files.pythonhosted.org/packages/2b/9d/9a49a2686f8b7165dcb2342b8554951263c30c0f0825f1fcc2d56e736a6b/ormsgpack-1.12.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58ad60308e233dd824a1859eabb5fe092e123e885eafa4ad5789322329c80fb5", size = 211264, upload-time = "2025-12-14T07:57:00.099Z" },
{ url = "https://files.pythonhosted.org/packages/02/31/2fdc36eaeca2182900b96fc7b19755f293283fe681750e3d295733d62f0e/ormsgpack-1.12.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:35127464c941c1219acbe1a220e48d55e7933373d12257202f4042f7044b4c90", size = 386081, upload-time = "2025-12-14T07:57:01.177Z" },
{ url = "https://files.pythonhosted.org/packages/f0/65/0a765432f08ae26b4013c6a9aed97be17a9ef85f1600948a474b518e27dd/ormsgpack-1.12.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:c48d1c50794692d1e6e3f8c3bb65f5c3acfaae9347e506484a65d60b3d91fb50", size = 479572, upload-time = "2025-12-14T07:57:02.738Z" },
{ url = "https://files.pythonhosted.org/packages/4e/4f/f2f15ebef786ad71cea420bf8692448fbddf04d1bf3feaa68bd5ee3172e6/ormsgpack-1.12.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b512b2ad6feaaefdc26e05431ed2843e42483041e354e167c53401afaa83d919", size = 387862, upload-time = "2025-12-14T07:57:03.842Z" },
{ url = "https://files.pythonhosted.org/packages/15/eb/86fbef1d605fa91ecef077f93f9d0e34fc39b23475dfe3ffb92f6c8db28d/ormsgpack-1.12.1-cp311-cp311-win_amd64.whl", hash = "sha256:93f30db95e101a9616323bfc50807ad00e7f6197cea2216d2d24af42afc77d88", size = 115900, upload-time = "2025-12-14T07:57:05.137Z" },
{ url = "https://files.pythonhosted.org/packages/5b/67/7ba1a46e6a6e263fc42a4fafc24afc1ab21a66116553cad670426f0bd9ef/ormsgpack-1.12.1-cp311-cp311-win_arm64.whl", hash = "sha256:d75b5fa14f6abffce2c392ee03b4731199d8a964c81ee8645c4c79af0e80fd50", size = 109868, upload-time = "2025-12-14T07:57:06.834Z" },
{ url = "https://files.pythonhosted.org/packages/17/fe/ab9167ca037406b5703add24049cf3e18021a3b16133ea20615b1f160ea4/ormsgpack-1.12.1-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:4d7fb0e1b6fbc701d75269f7405a4f79230a6ce0063fb1092e4f6577e312f86d", size = 376725, upload-time = "2025-12-14T07:57:07.894Z" },
{ url = "https://files.pythonhosted.org/packages/c7/ea/2820e65f506894c459b840d1091ae6e327fde3d5a3f3b002a11a1b9bdf7d/ormsgpack-1.12.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:43a9353e2db5b024c91a47d864ef15eaa62d81824cfc7740fed4cef7db738694", size = 202466, upload-time = "2025-12-14T07:57:09.049Z" },
{ url = "https://files.pythonhosted.org/packages/45/8b/def01c13339c5bbec2ee1469ef53e7fadd66c8d775df974ee4def1572515/ormsgpack-1.12.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fc8fe866b7706fc25af0adf1f600bc06ece5b15ca44e34641327198b821e5c3c", size = 210748, upload-time = "2025-12-14T07:57:10.074Z" },
{ url = "https://files.pythonhosted.org/packages/5d/d2/bf350c92f7f067dd9484499705f2d8366d8d9008a670e3d1d0add1908f85/ormsgpack-1.12.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:813755b5f598a78242042e05dfd1ada4e769e94b98c9ab82554550f97ff4d641", size = 211510, upload-time = "2025-12-14T07:57:11.165Z" },
{ url = "https://files.pythonhosted.org/packages/74/92/9d689bcb95304a6da26c4d59439c350940c25d1b35f146d402ccc6344c51/ormsgpack-1.12.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8eea2a13536fae45d78f93f2cc846c9765c7160c85f19cfefecc20873c137cdd", size = 386237, upload-time = "2025-12-14T07:57:12.306Z" },
{ url = "https://files.pythonhosted.org/packages/17/fe/bd3107547f8b6129265dd957f40b9cd547d2445db2292aacb13335a7ea89/ormsgpack-1.12.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:7a02ebda1a863cbc604740e76faca8eee1add322db2dcbe6cf32669fffdff65c", size = 479589, upload-time = "2025-12-14T07:57:13.475Z" },
{ url = "https://files.pythonhosted.org/packages/c1/7c/e8e5cc9edb967d44f6f85e9ebdad440b59af3fae00b137a4327dc5aed9bb/ormsgpack-1.12.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3c0bd63897c439931cdf29348e5e6e8c330d529830e848d10767615c0f3d1b82", size = 388077, upload-time = "2025-12-14T07:57:14.551Z" },
{ url = "https://files.pythonhosted.org/packages/35/6b/5031797e43b58506f28a8760b26dc23f2620fb4f2200c4c1b3045603e67e/ormsgpack-1.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:362f2e812f8d7035dc25a009171e09d7cc97cb30d3c9e75a16aeae00ca3c1dcf", size = 116190, upload-time = "2025-12-14T07:57:15.575Z" },
{ url = "https://files.pythonhosted.org/packages/1e/fd/9f43ea6425e383a6b2dbfafebb06fd60e8d68c700ef715adfbcdb499f75d/ormsgpack-1.12.1-cp312-cp312-win_arm64.whl", hash = "sha256:6190281e381db2ed0045052208f47a995ccf61eed48f1215ae3cce3fbccd59c5", size = 109990, upload-time = "2025-12-14T07:57:16.419Z" },
{ url = "https://files.pythonhosted.org/packages/11/42/f110dfe7cf23a52a82e23eb23d9a6a76ae495447d474686dfa758f3d71d6/ormsgpack-1.12.1-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:9663d6b3ecc917c063d61a99169ce196a80f3852e541ae404206836749459279", size = 376746, upload-time = "2025-12-14T07:57:17.699Z" },
{ url = "https://files.pythonhosted.org/packages/11/76/b386e508a8ae207daec240201a81adb26467bf99b163560724e86bd9ff33/ormsgpack-1.12.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32e85cfbaf01a94a92520e7fe7851cfcfe21a5698299c28ab86194895f9b9233", size = 202489, upload-time = "2025-12-14T07:57:18.807Z" },
{ url = "https://files.pythonhosted.org/packages/ea/0e/5db7a63f387149024572daa3d9512fe8fb14bf4efa0722d6d491bed280e7/ormsgpack-1.12.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dabfd2c24b59c7c69870a5ecee480dfae914a42a0c2e7c9d971cf531e2ba471a", size = 210757, upload-time = "2025-12-14T07:57:19.893Z" },
{ url = "https://files.pythonhosted.org/packages/64/79/3a9899e57cb57430bd766fc1b4c9ad410cb2ba6070bc8cf6301e7d385768/ormsgpack-1.12.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51bbf2b64afeded34ccd8e25402e4bca038757913931fa0d693078d75563f6f9", size = 211518, upload-time = "2025-12-14T07:57:20.972Z" },
{ url = "https://files.pythonhosted.org/packages/d7/cd/4f41710ae9fe50d7fcbe476793b3c487746d0e1cc194cc0fee42ff6d989b/ormsgpack-1.12.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9959a71dde1bd0ced84af17facc06a8afada495a34e9cb1bad8e9b20d4c59cef", size = 386251, upload-time = "2025-12-14T07:57:22.099Z" },
{ url = "https://files.pythonhosted.org/packages/bf/54/ba0c97d6231b1f01daafaa520c8cce1e1b7fceaae6fdc1c763925874a7de/ormsgpack-1.12.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:e9be0e3b62d758f21f5b20e0e06b3a240ec546c4a327bf771f5825462aa74714", size = 479607, upload-time = "2025-12-14T07:57:23.525Z" },
{ url = "https://files.pythonhosted.org/packages/18/75/19a9a97a462776d525baf41cfb7072734528775f0a3d5fbfab3aa7756b9b/ormsgpack-1.12.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a29d49ab7fdd77ea787818e60cb4ef491708105b9c4c9b0f919201625eb036b5", size = 388062, upload-time = "2025-12-14T07:57:24.616Z" },
{ url = "https://files.pythonhosted.org/packages/a8/6a/ec26e3f44e9632ecd2f43638b7b37b500eaea5d79cab984ad0b94be14f82/ormsgpack-1.12.1-cp313-cp313-win_amd64.whl", hash = "sha256:c418390b47a1d367e803f6c187f77e4d67c7ae07ba962e3a4a019001f4b0291a", size = 116195, upload-time = "2025-12-14T07:57:25.626Z" },
{ url = "https://files.pythonhosted.org/packages/7d/64/bfa5f4a34d0f15c6aba1b73e73f7441a66d635bd03249d334a4796b7a924/ormsgpack-1.12.1-cp313-cp313-win_arm64.whl", hash = "sha256:cfa22c91cffc10a7fbd43729baff2de7d9c28cef2509085a704168ae31f02568", size = 109986, upload-time = "2025-12-14T07:57:26.569Z" },
{ url = "https://files.pythonhosted.org/packages/87/0e/78e5697164e3223b9b216c13e99f1acbc1ee9833490d68842b13da8ba883/ormsgpack-1.12.1-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:b93c91efb1a70751a1902a5b43b27bd8fd38e0ca0365cf2cde2716423c15c3a6", size = 376758, upload-time = "2025-12-14T07:57:27.641Z" },
{ url = "https://files.pythonhosted.org/packages/2c/0e/3a3cbb64703263d7bbaed7effa3ce78cb9add360a60aa7c544d7df28b641/ormsgpack-1.12.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cf0ea0389167b5fa8d2933dd3f33e887ec4ba68f89c25214d7eec4afd746d22", size = 202487, upload-time = "2025-12-14T07:57:29.051Z" },
{ url = "https://files.pythonhosted.org/packages/d7/2c/807ebe2b77995599bbb1dec8c3f450d5d7dddee14ce3e1e71dc60e2e2a74/ormsgpack-1.12.1-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f4c29af837f35af3375070689e781161e7cf019eb2f7cd641734ae45cd001c0d", size = 210853, upload-time = "2025-12-14T07:57:30.508Z" },
{ url = "https://files.pythonhosted.org/packages/25/57/2cdfc354e3ad8e847628f511f4d238799d90e9e090941e50b9d5ba955ae2/ormsgpack-1.12.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:336fc65aa0fe65896a3dabaae31e332a0a98b4a00ad7b0afde21a7505fd23ff3", size = 211545, upload-time = "2025-12-14T07:57:31.585Z" },
{ url = "https://files.pythonhosted.org/packages/76/1d/c6fda560e4a8ff865b3aec8a86f7c95ab53f4532193a6ae4ab9db35f85aa/ormsgpack-1.12.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:940f60aabfefe71dd6b82cb33f4ff10b2e7f5fcfa5f103cdb0a23b6aae4c713c", size = 386333, upload-time = "2025-12-14T07:57:32.957Z" },
{ url = "https://files.pythonhosted.org/packages/fc/3e/715081b36fceb8b497c68b87d384e1cc6d9c9c130ce3b435634d3d785b86/ormsgpack-1.12.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:596ad9e1b6d4c95595c54aaf49b1392609ca68f562ce06f4f74a5bc4053bcda4", size = 479701, upload-time = "2025-12-14T07:57:34.686Z" },
{ url = "https://files.pythonhosted.org/packages/6d/cf/01ad04def42b3970fc1a302c07f4b46339edf62ef9650247097260471f40/ormsgpack-1.12.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:575210e8fcbc7b0375026ba040a5eef223e9f66a4453d9623fc23282ae09c3c8", size = 388148, upload-time = "2025-12-14T07:57:35.771Z" },
{ url = "https://files.pythonhosted.org/packages/15/91/1fff2fc2b5943c740028f339154e7103c8f2edf1a881d9fbba2ce11c3b1d/ormsgpack-1.12.1-cp314-cp314-win_amd64.whl", hash = "sha256:647daa3718572280893456be44c60aea6690b7f2edc54c55648ee66e8f06550f", size = 116201, upload-time = "2025-12-14T07:57:36.763Z" },
{ url = "https://files.pythonhosted.org/packages/ed/66/142b542aed3f96002c7d1c33507ca6e1e0d0a42b9253ab27ef7ed5793bd9/ormsgpack-1.12.1-cp314-cp314-win_arm64.whl", hash = "sha256:a8b3ab762a6deaf1b6490ab46dda0c51528cf8037e0246c40875c6fe9e37b699", size = 110029, upload-time = "2025-12-14T07:57:37.703Z" },
{ url = "https://files.pythonhosted.org/packages/38/b3/ef4494438c90359e1547eaed3c5ec46e2c431d59a3de2af4e70ebd594c49/ormsgpack-1.12.1-cp314-cp314t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:12087214e436c1f6c28491949571abea759a63111908c4f7266586d78144d7a8", size = 376777, upload-time = "2025-12-14T07:57:38.795Z" },
{ url = "https://files.pythonhosted.org/packages/05/a0/1149a7163f8b0dfbc64bf9099b6f16d102ad3b03bcc11afee198d751da2d/ormsgpack-1.12.1-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e6d54c14cf86ef13f10ccade94d1e7de146aa9b17d371e18b16e95f329393b7", size = 202490, upload-time = "2025-12-14T07:57:40.168Z" },
{ url = "https://files.pythonhosted.org/packages/68/82/f2ec5e758d6a7106645cca9bb7137d98bce5d363789fa94075be6572057c/ormsgpack-1.12.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f3584d07882b7ea2a1a589f795a3af97fe4c2932b739408e6d1d9d286cad862", size = 211733, upload-time = "2025-12-14T07:57:42.253Z" },
{ url = "https://files.pythonhosted.org/packages/93/fa/a91f70829ebccf6387c4946e0a1a109f6ba0d6a28d65f628bedfad94b890/ormsgpack-1.12.2-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:c1429217f8f4d7fcb053523bbbac6bed5e981af0b85ba616e6df7cce53c19657", size = 378262, upload-time = "2026-01-18T20:55:22.284Z" },
{ url = "https://files.pythonhosted.org/packages/5f/62/3698a9a0c487252b5c6a91926e5654e79e665708ea61f67a8bdeceb022bf/ormsgpack-1.12.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f13034dc6c84a6280c6c33db7ac420253852ea233fc3ee27c8875f8dd651163", size = 203034, upload-time = "2026-01-18T20:55:53.324Z" },
{ url = "https://files.pythonhosted.org/packages/66/3a/f716f64edc4aec2744e817660b317e2f9bb8de372338a95a96198efa1ac1/ormsgpack-1.12.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:59f5da97000c12bc2d50e988bdc8576b21f6ab4e608489879d35b2c07a8ab51a", size = 210538, upload-time = "2026-01-18T20:55:20.097Z" },
{ url = "https://files.pythonhosted.org/packages/72/30/a436be9ce27d693d4e19fa94900028067133779f09fc45776db3f689c822/ormsgpack-1.12.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e4459c3f27066beadb2b81ea48a076a417aafffff7df1d3c11c519190ed44f2", size = 212401, upload-time = "2026-01-18T20:55:46.447Z" },
{ url = "https://files.pythonhosted.org/packages/10/c5/cde98300fd33fee84ca71de4751b19aeeca675f0cf3c0ec4b043f40f3b76/ormsgpack-1.12.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7a1c460655d7288407ffa09065e322a7231997c0d62ce914bf3a96ad2dc6dedd", size = 387080, upload-time = "2026-01-18T20:56:00.884Z" },
{ url = "https://files.pythonhosted.org/packages/6a/31/30bf445ef827546747c10889dd254b3d84f92b591300efe4979d792f4c41/ormsgpack-1.12.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:458e4568be13d311ef7d8877275e7ccbe06c0e01b39baaac874caaa0f46d826c", size = 482346, upload-time = "2026-01-18T20:55:39.831Z" },
{ url = "https://files.pythonhosted.org/packages/2e/f5/e1745ddf4fa246c921b5ca253636c4c700ff768d78032f79171289159f6e/ormsgpack-1.12.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8cde5eaa6c6cbc8622db71e4a23de56828e3d876aeb6460ffbcb5b8aff91093b", size = 425178, upload-time = "2026-01-18T20:55:27.106Z" },
{ url = "https://files.pythonhosted.org/packages/8d/a2/e6532ed7716aed03dede8df2d0d0d4150710c2122647d94b474147ccd891/ormsgpack-1.12.2-cp310-cp310-win_amd64.whl", hash = "sha256:dc7a33be14c347893edbb1ceda89afbf14c467d593a5ee92c11de4f1666b4d4f", size = 117183, upload-time = "2026-01-18T20:55:55.52Z" },
{ url = "https://files.pythonhosted.org/packages/4b/08/8b68f24b18e69d92238aa8f258218e6dfeacf4381d9d07ab8df303f524a9/ormsgpack-1.12.2-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:bd5f4bf04c37888e864f08e740c5a573c4017f6fd6e99fa944c5c935fabf2dd9", size = 378266, upload-time = "2026-01-18T20:55:59.876Z" },
{ url = "https://files.pythonhosted.org/packages/0d/24/29fc13044ecb7c153523ae0a1972269fcd613650d1fa1a9cec1044c6b666/ormsgpack-1.12.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34d5b28b3570e9fed9a5a76528fc7230c3c76333bc214798958e58e9b79cc18a", size = 203035, upload-time = "2026-01-18T20:55:30.59Z" },
{ url = "https://files.pythonhosted.org/packages/ad/c2/00169fb25dd8f9213f5e8a549dfb73e4d592009ebc85fbbcd3e1dcac575b/ormsgpack-1.12.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3708693412c28f3538fb5a65da93787b6bbab3484f6bc6e935bfb77a62400ae5", size = 210539, upload-time = "2026-01-18T20:55:48.569Z" },
{ url = "https://files.pythonhosted.org/packages/1b/33/543627f323ff3c73091f51d6a20db28a1a33531af30873ea90c5ac95a9b5/ormsgpack-1.12.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:43013a3f3e2e902e1d05e72c0f1aeb5bedbb8e09240b51e26792a3c89267e181", size = 212401, upload-time = "2026-01-18T20:56:10.101Z" },
{ url = "https://files.pythonhosted.org/packages/e8/5d/f70e2c3da414f46186659d24745483757bcc9adccb481a6eb93e2b729301/ormsgpack-1.12.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7c8b1667a72cbba74f0ae7ecf3105a5e01304620ed14528b2cb4320679d2869b", size = 387082, upload-time = "2026-01-18T20:56:12.047Z" },
{ url = "https://files.pythonhosted.org/packages/c0/d6/06e8dc920c7903e051f30934d874d4afccc9bb1c09dcaf0bc03a7de4b343/ormsgpack-1.12.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:df6961442140193e517303d0b5d7bc2e20e69a879c2d774316125350c4a76b92", size = 482346, upload-time = "2026-01-18T20:56:05.152Z" },
{ url = "https://files.pythonhosted.org/packages/66/c4/f337ac0905eed9c393ef990c54565cd33644918e0a8031fe48c098c71dbf/ormsgpack-1.12.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c6a4c34ddef109647c769d69be65fa1de7a6022b02ad45546a69b3216573eb4a", size = 425181, upload-time = "2026-01-18T20:55:37.83Z" },
{ url = "https://files.pythonhosted.org/packages/78/29/6d5758fabef3babdf4bbbc453738cc7de9cd3334e4c38dd5737e27b85653/ormsgpack-1.12.2-cp311-cp311-win_amd64.whl", hash = "sha256:73670ed0375ecc303858e3613f407628dd1fca18fe6ac57b7b7ce66cc7bb006c", size = 117182, upload-time = "2026-01-18T20:55:31.472Z" },
{ url = "https://files.pythonhosted.org/packages/c4/57/17a15549233c37e7fd054c48fe9207492e06b026dbd872b826a0b5f833b6/ormsgpack-1.12.2-cp311-cp311-win_arm64.whl", hash = "sha256:c2be829954434e33601ae5da328cccce3266b098927ca7a30246a0baec2ce7bd", size = 111464, upload-time = "2026-01-18T20:55:38.811Z" },
{ url = "https://files.pythonhosted.org/packages/4c/36/16c4b1921c308a92cef3bf6663226ae283395aa0ff6e154f925c32e91ff5/ormsgpack-1.12.2-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:7a29d09b64b9694b588ff2f80e9826bdceb3a2b91523c5beae1fab27d5c940e7", size = 378618, upload-time = "2026-01-18T20:55:50.835Z" },
{ url = "https://files.pythonhosted.org/packages/c0/68/468de634079615abf66ed13bb5c34ff71da237213f29294363beeeca5306/ormsgpack-1.12.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b39e629fd2e1c5b2f46f99778450b59454d1f901bc507963168985e79f09c5d", size = 203186, upload-time = "2026-01-18T20:56:11.163Z" },
{ url = "https://files.pythonhosted.org/packages/73/a9/d756e01961442688b7939bacd87ce13bfad7d26ce24f910f6028178b2cc8/ormsgpack-1.12.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:958dcb270d30a7cb633a45ee62b9444433fa571a752d2ca484efdac07480876e", size = 210738, upload-time = "2026-01-18T20:56:09.181Z" },
{ url = "https://files.pythonhosted.org/packages/7b/ba/795b1036888542c9113269a3f5690ab53dd2258c6fb17676ac4bd44fcf94/ormsgpack-1.12.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58d379d72b6c5e964851c77cfedfb386e474adee4fd39791c2c5d9efb53505cc", size = 212569, upload-time = "2026-01-18T20:56:06.135Z" },
{ url = "https://files.pythonhosted.org/packages/6c/aa/bff73c57497b9e0cba8837c7e4bcab584b1a6dbc91a5dd5526784a5030c8/ormsgpack-1.12.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8463a3fc5f09832e67bdb0e2fda6d518dc4281b133166146a67f54c08496442e", size = 387166, upload-time = "2026-01-18T20:55:36.738Z" },
{ url = "https://files.pythonhosted.org/packages/d3/cf/f8283cba44bcb7b14f97b6274d449db276b3a86589bdb363169b51bc12de/ormsgpack-1.12.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:eddffb77eff0bad4e67547d67a130604e7e2dfbb7b0cde0796045be4090f35c6", size = 482498, upload-time = "2026-01-18T20:55:29.626Z" },
{ url = "https://files.pythonhosted.org/packages/05/be/71e37b852d723dfcbe952ad04178c030df60d6b78eba26bfd14c9a40575e/ormsgpack-1.12.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fcd55e5f6ba0dbce624942adf9f152062135f991a0126064889f68eb850de0dd", size = 425518, upload-time = "2026-01-18T20:55:49.556Z" },
{ url = "https://files.pythonhosted.org/packages/7a/0c/9803aa883d18c7ef197213cd2cbf73ba76472a11fe100fb7dab2884edf48/ormsgpack-1.12.2-cp312-cp312-win_amd64.whl", hash = "sha256:d024b40828f1dde5654faebd0d824f9cc29ad46891f626272dd5bfd7af2333a4", size = 117462, upload-time = "2026-01-18T20:55:47.726Z" },
{ url = "https://files.pythonhosted.org/packages/c8/9e/029e898298b2cc662f10d7a15652a53e3b525b1e7f07e21fef8536a09bb8/ormsgpack-1.12.2-cp312-cp312-win_arm64.whl", hash = "sha256:da538c542bac7d1c8f3f2a937863dba36f013108ce63e55745941dda4b75dbb6", size = 111559, upload-time = "2026-01-18T20:55:54.273Z" },
{ url = "https://files.pythonhosted.org/packages/eb/29/bb0eba3288c0449efbb013e9c6f58aea79cf5cb9ee1921f8865f04c1a9d7/ormsgpack-1.12.2-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:5ea60cb5f210b1cfbad8c002948d73447508e629ec375acb82910e3efa8ff355", size = 378661, upload-time = "2026-01-18T20:55:57.765Z" },
{ url = "https://files.pythonhosted.org/packages/6e/31/5efa31346affdac489acade2926989e019e8ca98129658a183e3add7af5e/ormsgpack-1.12.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3601f19afdbea273ed70b06495e5794606a8b690a568d6c996a90d7255e51c1", size = 203194, upload-time = "2026-01-18T20:56:08.252Z" },
{ url = "https://files.pythonhosted.org/packages/eb/56/d0087278beef833187e0167f8527235ebe6f6ffc2a143e9de12a98b1ce87/ormsgpack-1.12.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:29a9f17a3dac6054c0dce7925e0f4995c727f7c41859adf9b5572180f640d172", size = 210778, upload-time = "2026-01-18T20:55:17.694Z" },
{ url = "https://files.pythonhosted.org/packages/1c/a2/072343e1413d9443e5a252a8eb591c2d5b1bffbe5e7bfc78c069361b92eb/ormsgpack-1.12.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39c1bd2092880e413902910388be8715f70b9f15f20779d44e673033a6146f2d", size = 212592, upload-time = "2026-01-18T20:55:32.747Z" },
{ url = "https://files.pythonhosted.org/packages/a2/8b/a0da3b98a91d41187a63b02dda14267eefc2a74fcb43cc2701066cf1510e/ormsgpack-1.12.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:50b7249244382209877deedeee838aef1542f3d0fc28b8fe71ca9d7e1896a0d7", size = 387164, upload-time = "2026-01-18T20:55:40.853Z" },
{ url = "https://files.pythonhosted.org/packages/19/bb/6d226bc4cf9fc20d8eb1d976d027a3f7c3491e8f08289a2e76abe96a65f3/ormsgpack-1.12.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:5af04800d844451cf102a59c74a841324868d3f1625c296a06cc655c542a6685", size = 482516, upload-time = "2026-01-18T20:55:42.033Z" },
{ url = "https://files.pythonhosted.org/packages/fb/f1/bb2c7223398543dedb3dbf8bb93aaa737b387de61c5feaad6f908841b782/ormsgpack-1.12.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:cec70477d4371cd524534cd16472d8b9cc187e0e3043a8790545a9a9b296c258", size = 425539, upload-time = "2026-01-18T20:55:24.727Z" },
{ url = "https://files.pythonhosted.org/packages/7b/e8/0fb45f57a2ada1fed374f7494c8cd55e2f88ccd0ab0a669aa3468716bf5f/ormsgpack-1.12.2-cp313-cp313-win_amd64.whl", hash = "sha256:21f4276caca5c03a818041d637e4019bc84f9d6ca8baa5ea03e5cc8bf56140e9", size = 117459, upload-time = "2026-01-18T20:55:56.876Z" },
{ url = "https://files.pythonhosted.org/packages/7a/d4/0cfeea1e960d550a131001a7f38a5132c7ae3ebde4c82af1f364ccc5d904/ormsgpack-1.12.2-cp313-cp313-win_arm64.whl", hash = "sha256:baca4b6773d20a82e36d6fd25f341064244f9f86a13dead95dd7d7f996f51709", size = 111577, upload-time = "2026-01-18T20:55:43.605Z" },
{ url = "https://files.pythonhosted.org/packages/94/16/24d18851334be09c25e87f74307c84950f18c324a4d3c0b41dabdbf19c29/ormsgpack-1.12.2-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:bc68dd5915f4acf66ff2010ee47c8906dc1cf07399b16f4089f8c71733f6e36c", size = 378717, upload-time = "2026-01-18T20:55:26.164Z" },
{ url = "https://files.pythonhosted.org/packages/b5/a2/88b9b56f83adae8032ac6a6fa7f080c65b3baf9b6b64fd3d37bd202991d4/ormsgpack-1.12.2-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46d084427b4132553940070ad95107266656cb646ea9da4975f85cb1a6676553", size = 203183, upload-time = "2026-01-18T20:55:18.815Z" },
{ url = "https://files.pythonhosted.org/packages/a9/80/43e4555963bf602e5bdc79cbc8debd8b6d5456c00d2504df9775e74b450b/ormsgpack-1.12.2-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c010da16235806cf1d7bc4c96bf286bfa91c686853395a299b3ddb49499a3e13", size = 210814, upload-time = "2026-01-18T20:55:33.973Z" },
{ url = "https://files.pythonhosted.org/packages/78/e1/7cfbf28de8bca6efe7e525b329c31277d1b64ce08dcba723971c241a9d60/ormsgpack-1.12.2-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18867233df592c997154ff942a6503df274b5ac1765215bceba7a231bea2745d", size = 212634, upload-time = "2026-01-18T20:55:28.634Z" },
{ url = "https://files.pythonhosted.org/packages/95/f8/30ae5716e88d792a4e879debee195653c26ddd3964c968594ddef0a3cc7e/ormsgpack-1.12.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b009049086ddc6b8f80c76b3955df1aa22a5fbd7673c525cd63bf91f23122ede", size = 387139, upload-time = "2026-01-18T20:56:02.013Z" },
{ url = "https://files.pythonhosted.org/packages/dc/81/aee5b18a3e3a0e52f718b37ab4b8af6fae0d9d6a65103036a90c2a8ffb5d/ormsgpack-1.12.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:1dcc17d92b6390d4f18f937cf0b99054824a7815818012ddca925d6e01c2e49e", size = 482578, upload-time = "2026-01-18T20:55:35.117Z" },
{ url = "https://files.pythonhosted.org/packages/bd/17/71c9ba472d5d45f7546317f467a5fc941929cd68fb32796ca3d13dcbaec2/ormsgpack-1.12.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f04b5e896d510b07c0ad733d7fce2d44b260c5e6c402d272128f8941984e4285", size = 425539, upload-time = "2026-01-18T20:56:04.009Z" },
{ url = "https://files.pythonhosted.org/packages/2e/a6/ac99cd7fe77e822fed5250ff4b86fa66dd4238937dd178d2299f10b69816/ormsgpack-1.12.2-cp314-cp314-win_amd64.whl", hash = "sha256:ae3aba7eed4ca7cb79fd3436eddd29140f17ea254b91604aa1eb19bfcedb990f", size = 117493, upload-time = "2026-01-18T20:56:07.343Z" },
{ url = "https://files.pythonhosted.org/packages/3a/67/339872846a1ae4592535385a1c1f93614138566d7af094200c9c3b45d1e5/ormsgpack-1.12.2-cp314-cp314-win_arm64.whl", hash = "sha256:118576ea6006893aea811b17429bfc561b4778fad393f5f538c84af70b01260c", size = 111579, upload-time = "2026-01-18T20:55:21.161Z" },
{ url = "https://files.pythonhosted.org/packages/49/c2/6feb972dc87285ad381749d3882d8aecbde9f6ecf908dd717d33d66df095/ormsgpack-1.12.2-cp314-cp314t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:7121b3d355d3858781dc40dafe25a32ff8a8242b9d80c692fd548a4b1f7fd3c8", size = 378721, upload-time = "2026-01-18T20:55:52.12Z" },
{ url = "https://files.pythonhosted.org/packages/a3/9a/900a6b9b413e0f8a471cf07830f9cf65939af039a362204b36bd5b581d8b/ormsgpack-1.12.2-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ee766d2e78251b7a63daf1cddfac36a73562d3ddef68cacfb41b2af64698033", size = 203170, upload-time = "2026-01-18T20:55:44.469Z" },
{ url = "https://files.pythonhosted.org/packages/87/4c/27a95466354606b256f24fad464d7c97ab62bce6cc529dd4673e1179b8fb/ormsgpack-1.12.2-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:292410a7d23de9b40444636b9b8f1e4e4b814af7f1ef476e44887e52a123f09d", size = 212816, upload-time = "2026-01-18T20:55:23.501Z" },
{ url = "https://files.pythonhosted.org/packages/73/cd/29cee6007bddf7a834e6cd6f536754c0535fcb939d384f0f37a38b1cddb8/ormsgpack-1.12.2-cp314-cp314t-win_amd64.whl", hash = "sha256:837dd316584485b72ef451d08dd3e96c4a11d12e4963aedb40e08f89685d8ec2", size = 117232, upload-time = "2026-01-18T20:55:45.448Z" },
]
[[package]]
@@ -1197,14 +1198,14 @@ wheels = [
[[package]]
name = "redis"
version = "7.1.0"
version = "7.2.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "async-timeout", marker = "python_full_version < '3.11.3'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/43/c8/983d5c6579a411d8a99bc5823cc5712768859b5ce2c8afe1a65b37832c81/redis-7.1.0.tar.gz", hash = "sha256:b1cc3cfa5a2cb9c2ab3ba700864fb0ad75617b41f01352ce5779dabf6d5f9c3c", size = 4796669, upload-time = "2025-11-19T15:54:39.961Z" }
sdist = { url = "https://files.pythonhosted.org/packages/9f/32/6fac13a11e73e1bc67a2ae821a72bfe4c2d8c4c48f0267e4a952be0f1bae/redis-7.2.0.tar.gz", hash = "sha256:4dd5bf4bd4ae80510267f14185a15cba2a38666b941aff68cccf0256b51c1f26", size = 4901247, upload-time = "2026-02-16T17:16:22.797Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/89/f0/8956f8a86b20d7bb9d6ac0187cf4cd54d8065bc9a1a09eb8011d4d326596/redis-7.1.0-py3-none-any.whl", hash = "sha256:23c52b208f92b56103e17c5d06bdc1a6c2c0b3106583985a76a18f83b265de2b", size = 354159, upload-time = "2025-11-19T15:54:38.064Z" },
{ url = "https://files.pythonhosted.org/packages/86/cf/f6180b67f99688d83e15c84c5beda831d1d341e95872d224f87ccafafe61/redis-7.2.0-py3-none-any.whl", hash = "sha256:01f591f8598e483f1842d429e8ae3a820804566f1c73dca1b80e23af9fba0497", size = 394898, upload-time = "2026-02-16T17:16:20.693Z" },
]
[[package]]
@@ -1236,28 +1237,27 @@ wheels = [
[[package]]
name = "ruff"
version = "0.14.13"
version = "0.15.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/50/0a/1914efb7903174b381ee2ffeebb4253e729de57f114e63595114c8ca451f/ruff-0.14.13.tar.gz", hash = "sha256:83cd6c0763190784b99650a20fec7633c59f6ebe41c5cc9d45ee42749563ad47", size = 6059504, upload-time = "2026-01-15T20:15:16.918Z" }
sdist = { url = "https://files.pythonhosted.org/packages/04/dc/4e6ac71b511b141cf626357a3946679abeba4cf67bc7cc5a17920f31e10d/ruff-0.15.1.tar.gz", hash = "sha256:c590fe13fb57c97141ae975c03a1aedb3d3156030cabd740d6ff0b0d601e203f", size = 4540855, upload-time = "2026-02-12T23:09:09.998Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c3/ae/0deefbc65ca74b0ab1fd3917f94dc3b398233346a74b8bbb0a916a1a6bf6/ruff-0.14.13-py3-none-linux_armv6l.whl", hash = "sha256:76f62c62cd37c276cb03a275b198c7c15bd1d60c989f944db08a8c1c2dbec18b", size = 13062418, upload-time = "2026-01-15T20:14:50.779Z" },
{ url = "https://files.pythonhosted.org/packages/47/df/5916604faa530a97a3c154c62a81cb6b735c0cb05d1e26d5ad0f0c8ac48a/ruff-0.14.13-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:914a8023ece0528d5cc33f5a684f5f38199bbb566a04815c2c211d8f40b5d0ed", size = 13442344, upload-time = "2026-01-15T20:15:07.94Z" },
{ url = "https://files.pythonhosted.org/packages/4c/f3/e0e694dd69163c3a1671e102aa574a50357536f18a33375050334d5cd517/ruff-0.14.13-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d24899478c35ebfa730597a4a775d430ad0d5631b8647a3ab368c29b7e7bd063", size = 12354720, upload-time = "2026-01-15T20:15:09.854Z" },
{ url = "https://files.pythonhosted.org/packages/c3/e8/67f5fcbbaee25e8fc3b56cc33e9892eca7ffe09f773c8e5907757a7e3bdb/ruff-0.14.13-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9aaf3870f14d925bbaf18b8a2347ee0ae7d95a2e490e4d4aea6813ed15ebc80e", size = 12774493, upload-time = "2026-01-15T20:15:20.908Z" },
{ url = "https://files.pythonhosted.org/packages/6b/ce/d2e9cb510870b52a9565d885c0d7668cc050e30fa2c8ac3fb1fda15c083d/ruff-0.14.13-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac5b7f63dd3b27cc811850f5ffd8fff845b00ad70e60b043aabf8d6ecc304e09", size = 12815174, upload-time = "2026-01-15T20:15:05.74Z" },
{ url = "https://files.pythonhosted.org/packages/88/00/c38e5da58beebcf4fa32d0ddd993b63dfacefd02ab7922614231330845bf/ruff-0.14.13-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78d2b1097750d90ba82ce4ba676e85230a0ed694178ca5e61aa9b459970b3eb9", size = 13680909, upload-time = "2026-01-15T20:15:14.537Z" },
{ url = "https://files.pythonhosted.org/packages/61/61/cd37c9dd5bd0a3099ba79b2a5899ad417d8f3b04038810b0501a80814fd7/ruff-0.14.13-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:7d0bf87705acbbcb8d4c24b2d77fbb73d40210a95c3903b443cd9e30824a5032", size = 15144215, upload-time = "2026-01-15T20:15:22.886Z" },
{ url = "https://files.pythonhosted.org/packages/56/8a/85502d7edbf98c2df7b8876f316c0157359165e16cdf98507c65c8d07d3d/ruff-0.14.13-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a3eb5da8e2c9e9f13431032fdcbe7681de9ceda5835efee3269417c13f1fed5c", size = 14706067, upload-time = "2026-01-15T20:14:48.271Z" },
{ url = "https://files.pythonhosted.org/packages/7e/2f/de0df127feb2ee8c1e54354dc1179b4a23798f0866019528c938ba439aca/ruff-0.14.13-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:642442b42957093811cd8d2140dfadd19c7417030a7a68cf8d51fcdd5f217427", size = 14133916, upload-time = "2026-01-15T20:14:57.357Z" },
{ url = "https://files.pythonhosted.org/packages/0d/77/9b99686bb9fe07a757c82f6f95e555c7a47801a9305576a9c67e0a31d280/ruff-0.14.13-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4acdf009f32b46f6e8864af19cbf6841eaaed8638e65c8dac845aea0d703c841", size = 13859207, upload-time = "2026-01-15T20:14:55.111Z" },
{ url = "https://files.pythonhosted.org/packages/7d/46/2bdcb34a87a179a4d23022d818c1c236cb40e477faf0d7c9afb6813e5876/ruff-0.14.13-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:591a7f68860ea4e003917d19b5c4f5ac39ff558f162dc753a2c5de897fd5502c", size = 14043686, upload-time = "2026-01-15T20:14:52.841Z" },
{ url = "https://files.pythonhosted.org/packages/1a/a9/5c6a4f56a0512c691cf143371bcf60505ed0f0860f24a85da8bd123b2bf1/ruff-0.14.13-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:774c77e841cc6e046fc3e91623ce0903d1cd07e3a36b1a9fe79b81dab3de506b", size = 12663837, upload-time = "2026-01-15T20:15:18.921Z" },
{ url = "https://files.pythonhosted.org/packages/fe/bb/b920016ece7651fa7fcd335d9d199306665486694d4361547ccb19394c44/ruff-0.14.13-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:61f4e40077a1248436772bb6512db5fc4457fe4c49e7a94ea7c5088655dd21ae", size = 12805867, upload-time = "2026-01-15T20:14:59.272Z" },
{ url = "https://files.pythonhosted.org/packages/7d/b3/0bd909851e5696cd21e32a8fc25727e5f58f1934b3596975503e6e85415c/ruff-0.14.13-py3-none-musllinux_1_2_i686.whl", hash = "sha256:6d02f1428357fae9e98ac7aa94b7e966fd24151088510d32cf6f902d6c09235e", size = 13208528, upload-time = "2026-01-15T20:15:03.732Z" },
{ url = "https://files.pythonhosted.org/packages/3b/3b/e2d94cb613f6bbd5155a75cbe072813756363eba46a3f2177a1fcd0cd670/ruff-0.14.13-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e399341472ce15237be0c0ae5fbceca4b04cd9bebab1a2b2c979e015455d8f0c", size = 13929242, upload-time = "2026-01-15T20:15:11.918Z" },
{ url = "https://files.pythonhosted.org/packages/6a/c5/abd840d4132fd51a12f594934af5eba1d5d27298a6f5b5d6c3be45301caf/ruff-0.14.13-py3-none-win32.whl", hash = "sha256:ef720f529aec113968b45dfdb838ac8934e519711da53a0456038a0efecbd680", size = 12919024, upload-time = "2026-01-15T20:14:43.647Z" },
{ url = "https://files.pythonhosted.org/packages/c2/55/6384b0b8ce731b6e2ade2b5449bf07c0e4c31e8a2e68ea65b3bafadcecc5/ruff-0.14.13-py3-none-win_amd64.whl", hash = "sha256:6070bd026e409734b9257e03e3ef18c6e1a216f0435c6751d7a8ec69cb59abef", size = 14097887, upload-time = "2026-01-15T20:15:01.48Z" },
{ url = "https://files.pythonhosted.org/packages/4d/e1/7348090988095e4e39560cfc2f7555b1b2a7357deba19167b600fdf5215d/ruff-0.14.13-py3-none-win_arm64.whl", hash = "sha256:7ab819e14f1ad9fe39f246cfcc435880ef7a9390d81a2b6ac7e01039083dd247", size = 13080224, upload-time = "2026-01-15T20:14:45.853Z" },
{ url = "https://files.pythonhosted.org/packages/23/bf/e6e4324238c17f9d9120a9d60aa99a7daaa21204c07fcd84e2ef03bb5fd1/ruff-0.15.1-py3-none-linux_armv6l.whl", hash = "sha256:b101ed7cf4615bda6ffe65bdb59f964e9f4a0d3f85cbf0e54f0ab76d7b90228a", size = 10367819, upload-time = "2026-02-12T23:09:03.598Z" },
{ url = "https://files.pythonhosted.org/packages/b3/ea/c8f89d32e7912269d38c58f3649e453ac32c528f93bb7f4219258be2e7ed/ruff-0.15.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:939c995e9277e63ea632cc8d3fae17aa758526f49a9a850d2e7e758bfef46602", size = 10798618, upload-time = "2026-02-12T23:09:22.928Z" },
{ url = "https://files.pythonhosted.org/packages/5e/0f/1d0d88bc862624247d82c20c10d4c0f6bb2f346559d8af281674cf327f15/ruff-0.15.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1d83466455fdefe60b8d9c8df81d3c1bbb2115cede53549d3b522ce2bc703899", size = 10148518, upload-time = "2026-02-12T23:08:58.339Z" },
{ url = "https://files.pythonhosted.org/packages/f5/c8/291c49cefaa4a9248e986256df2ade7add79388fe179e0691be06fae6f37/ruff-0.15.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9457e3c3291024866222b96108ab2d8265b477e5b1534c7ddb1810904858d16", size = 10518811, upload-time = "2026-02-12T23:09:31.865Z" },
{ url = "https://files.pythonhosted.org/packages/c3/1a/f5707440e5ae43ffa5365cac8bbb91e9665f4a883f560893829cf16a606b/ruff-0.15.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:92c92b003e9d4f7fbd33b1867bb15a1b785b1735069108dfc23821ba045b29bc", size = 10196169, upload-time = "2026-02-12T23:09:17.306Z" },
{ url = "https://files.pythonhosted.org/packages/2a/ff/26ddc8c4da04c8fd3ee65a89c9fb99eaa5c30394269d424461467be2271f/ruff-0.15.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fe5c41ab43e3a06778844c586251eb5a510f67125427625f9eb2b9526535779", size = 10990491, upload-time = "2026-02-12T23:09:25.503Z" },
{ url = "https://files.pythonhosted.org/packages/fc/00/50920cb385b89413f7cdb4bb9bc8fc59c1b0f30028d8bccc294189a54955/ruff-0.15.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66a6dd6df4d80dc382c6484f8ce1bcceb55c32e9f27a8b94c32f6c7331bf14fb", size = 11843280, upload-time = "2026-02-12T23:09:19.88Z" },
{ url = "https://files.pythonhosted.org/packages/5d/6d/2f5cad8380caf5632a15460c323ae326f1e1a2b5b90a6ee7519017a017ca/ruff-0.15.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6a4a42cbb8af0bda9bcd7606b064d7c0bc311a88d141d02f78920be6acb5aa83", size = 11274336, upload-time = "2026-02-12T23:09:14.907Z" },
{ url = "https://files.pythonhosted.org/packages/a3/1d/5f56cae1d6c40b8a318513599b35ea4b075d7dc1cd1d04449578c29d1d75/ruff-0.15.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ab064052c31dddada35079901592dfba2e05f5b1e43af3954aafcbc1096a5b2", size = 11137288, upload-time = "2026-02-12T23:09:07.475Z" },
{ url = "https://files.pythonhosted.org/packages/cd/20/6f8d7d8f768c93b0382b33b9306b3b999918816da46537d5a61635514635/ruff-0.15.1-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:5631c940fe9fe91f817a4c2ea4e81f47bee3ca4aa646134a24374f3c19ad9454", size = 11070681, upload-time = "2026-02-12T23:08:55.43Z" },
{ url = "https://files.pythonhosted.org/packages/9a/67/d640ac76069f64cdea59dba02af2e00b1fa30e2103c7f8d049c0cff4cafd/ruff-0.15.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:68138a4ba184b4691ccdc39f7795c66b3c68160c586519e7e8444cf5a53e1b4c", size = 10486401, upload-time = "2026-02-12T23:09:27.927Z" },
{ url = "https://files.pythonhosted.org/packages/65/3d/e1429f64a3ff89297497916b88c32a5cc88eeca7e9c787072d0e7f1d3e1e/ruff-0.15.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:518f9af03bfc33c03bdb4cb63fabc935341bb7f54af500f92ac309ecfbba6330", size = 10197452, upload-time = "2026-02-12T23:09:12.147Z" },
{ url = "https://files.pythonhosted.org/packages/78/83/e2c3bade17dad63bf1e1c2ffaf11490603b760be149e1419b07049b36ef2/ruff-0.15.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:da79f4d6a826caaea95de0237a67e33b81e6ec2e25fc7e1993a4015dffca7c61", size = 10693900, upload-time = "2026-02-12T23:09:34.418Z" },
{ url = "https://files.pythonhosted.org/packages/a1/27/fdc0e11a813e6338e0706e8b39bb7a1d61ea5b36873b351acee7e524a72a/ruff-0.15.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:3dd86dccb83cd7d4dcfac303ffc277e6048600dfc22e38158afa208e8bf94a1f", size = 11227302, upload-time = "2026-02-12T23:09:36.536Z" },
{ url = "https://files.pythonhosted.org/packages/f6/58/ac864a75067dcbd3b95be5ab4eb2b601d7fbc3d3d736a27e391a4f92a5c1/ruff-0.15.1-py3-none-win32.whl", hash = "sha256:660975d9cb49b5d5278b12b03bb9951d554543a90b74ed5d366b20e2c57c2098", size = 10462555, upload-time = "2026-02-12T23:09:29.899Z" },
{ url = "https://files.pythonhosted.org/packages/e0/5e/d4ccc8a27ecdb78116feac4935dfc39d1304536f4296168f91ed3ec00cd2/ruff-0.15.1-py3-none-win_amd64.whl", hash = "sha256:c820fef9dd5d4172a6570e5721704a96c6679b80cf7be41659ed439653f62336", size = 11599956, upload-time = "2026-02-12T23:09:01.157Z" },
{ url = "https://files.pythonhosted.org/packages/2a/07/5bda6a85b220c64c65686bc85bd0bbb23b29c62b3a9f9433fa55f17cda93/ruff-0.15.1-py3-none-win_arm64.whl", hash = "sha256:5ff7d5f0f88567850f45081fac8f4ec212be8d0b963e385c3f7d0d2eb4899416", size = 10874604, upload-time = "2026-02-12T23:09:05.515Z" },
]
[[package]]
@@ -5,5 +5,5 @@ description = "Test for prerelease stuff"
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
"langgraph==1.0.2"
"langgraph==1.0.8"
]
@@ -7,7 +7,7 @@ requires-python = ">=3.10"
dependencies = [
"langchain-openai==1.0.0a2",
"langchain-anthropic==1.0.0a5",
"langgraph==1.0.2"
"langgraph==1.0.8"
]
[tool.uv]
+17 -17
View File
@@ -21,25 +21,25 @@
"test:all": "yarn test && yarn test:int && yarn lint:langgraph"
},
"dependencies": {
"@langchain/core": "^0.3.2",
"@langchain/langgraph": "^0.2.5"
"@langchain/core": "^1.1.24",
"@langchain/langgraph": "^1.1.4"
},
"devDependencies": {
"@eslint/eslintrc": "^3.1.0",
"@eslint/js": "^9.9.1",
"@tsconfig/recommended": "^1.0.7",
"@types/jest": "^29.5.0",
"@typescript-eslint/eslint-plugin": "^5.59.8",
"@typescript-eslint/parser": "^5.59.8",
"dotenv": "^16.4.5",
"eslint": "^8.41.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-import": "^2.27.5",
"@eslint/eslintrc": "^3.3.3",
"@eslint/js": "^10.0.1",
"@tsconfig/recommended": "^1.0.13",
"@types/jest": "^30.0.0",
"@typescript-eslint/eslint-plugin": "^8.56.0",
"@typescript-eslint/parser": "^8.56.0",
"dotenv": "^17.3.1",
"eslint": "^10.0.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-no-instanceof": "^1.0.1",
"eslint-plugin-prettier": "^4.2.1",
"jest": "^29.7.0",
"prettier": "^3.3.3",
"ts-jest": "^29.1.0",
"typescript": "^5.3.3"
"eslint-plugin-prettier": "^5.5.5",
"jest": "^30.2.0",
"prettier": "^3.8.1",
"ts-jest": "^29.4.6",
"typescript": "^5.9.3"
}
}
File diff suppressed because it is too large Load Diff
@@ -9,10 +9,10 @@
},
"dependencies": {
"@js-monorepo-example/shared": "*",
"@langchain/core": "^0.3.2",
"@langchain/langgraph": "^0.2.5"
"@langchain/core": "^1.1.24",
"@langchain/langgraph": "^1.1.4"
},
"devDependencies": {
"typescript": "^5.3.3"
"typescript": "^5.9.3"
}
}
@@ -9,6 +9,6 @@
"clean": "rm -rf dist"
},
"devDependencies": {
"typescript": "^5.3.3"
"typescript": "^5.9.3"
}
}
+11 -11
View File
@@ -17,18 +17,18 @@
"lint": "eslint 'apps/**/*.ts' 'libs/**/*.ts'"
},
"devDependencies": {
"turbo": "^2.5.0",
"typescript": "^5.3.3",
"@tsconfig/recommended": "^1.0.7",
"@eslint/eslintrc": "^3.1.0",
"@eslint/js": "^9.9.1",
"eslint": "^8.41.0",
"eslint-config-prettier": "^8.8.0",
"turbo": "^2.8.9",
"typescript": "^5.9.3",
"@tsconfig/recommended": "^1.0.13",
"@eslint/eslintrc": "^3.3.3",
"@eslint/js": "^10.0.1",
"eslint": "^10.0.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-no-instanceof": "^1.0.1",
"eslint-plugin-prettier": "^4.2.1",
"@typescript-eslint/eslint-plugin": "^5.59.8",
"@typescript-eslint/parser": "^5.59.8",
"prettier": "^3.3.3"
"eslint-plugin-prettier": "^5.5.5",
"@typescript-eslint/eslint-plugin": "^8.56.0",
"@typescript-eslint/parser": "^8.56.0",
"prettier": "^3.8.1"
}
}
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1 +1 @@
__version__ = "0.4.12"
__version__ = "0.4.13"
+11 -1
View File
@@ -196,6 +196,11 @@ def validate_config(config: Config) -> Config:
f"Python version {pyversion} is not supported. "
f"Minimum required version is {MIN_PYTHON_VERSION}."
)
if "bullseye" in pyversion:
raise click.UsageError(
"Bullseye images were deprecated in version 0.4.13. "
"Please use 'bookworm' or 'debian' instead."
)
if not config["dependencies"]:
raise click.UsageError(
@@ -210,10 +215,15 @@ def validate_config(config: Config) -> Config:
# Validate image_distro config
if image_distro := config.get("image_distro"):
if image_distro == "bullseye":
raise click.UsageError(
"Bullseye images were deprecated in version 0.4.13. "
"Please use 'bookworm' or 'debian' instead."
)
if image_distro not in Distros.__args__:
raise click.UsageError(
f"Invalid image_distro: '{image_distro}'. "
"Must be one of 'debian', 'bullseye', or 'bookworm'."
"Must be one of 'debian', 'wolfi', or 'bookworm'."
)
if pip_installer := config.get("pip_installer"):
+10 -10
View File
@@ -1,6 +1,6 @@
from typing import Any, Literal, TypedDict
Distros = Literal["debian", "wolfi", "bullseye", "bookworm"]
Distros = Literal["debian", "wolfi", "bookworm"]
MiddlewareOrders = Literal["auth_first", "middleware_first"]
@@ -107,17 +107,19 @@ class StoreConfig(TypedDict, total=False):
class ThreadTTLConfig(TypedDict, total=False):
"""Configure a default TTL for checkpointed data within threads."""
strategy: Literal["delete"]
"""Strategy to use for deleting checkpointed data.
Choices:
- "delete": Delete all checkpoints for a thread after TTL expires.
strategy: Literal["delete", "keep_latest"]
"""Action taken when a thread exceeds its TTL.
- "delete": Remove the thread and all its data entirely.
- "keep_latest": Prune old checkpoints but keep the thread and its latest state.
"""
default_ttl: float | None
"""Default TTL (time-to-live) in minutes for checkpointed data."""
sweep_interval_minutes: int | None
"""Interval in minutes between sweep iterations.
If omitted, a default interval will be used (typically ~ 5 minutes)."""
sweep_limit: int | None
"""Maximum number of threads to process per sweep iteration. Defaults to 1000."""
class SerdeConfig(TypedDict, total=False):
@@ -173,14 +175,12 @@ class CheckpointerConfig(TypedDict, total=False):
"""
serde: SerdeConfig | None
"""Optional. Defines the serde configuration.
If provided, the checkpointer will apply serde settings according to the configuration.
If omitted, no serde behavior is configured.
This configuration requires server version 0.5 or later to take effect.
"""
sweep_limit: int | None
"""Maximum number of threads to process per sweep iteration. Defaults to 1000."""
class SecurityConfig(TypedDict, total=False):
@@ -559,7 +559,7 @@ class Config(TypedDict, total=False):
image_distro: Distros | None
"""Optional. Linux distribution for the base image.
Must be one of 'wolfi', 'debian', 'bullseye', or 'bookworm'.
Must be one of 'wolfi', 'debian', or 'bookworm'.
If omitted, defaults to 'debian' ('latest').
"""
+16 -16
View File
@@ -147,7 +147,6 @@
{
"enum": [
"bookworm",
"bullseye",
"debian",
"wolfi"
]
@@ -156,7 +155,7 @@
"type": "null"
}
],
"description": "Optional. Linux distribution for the base image.\n\nMust be one of 'wolfi', 'debian', 'bullseye', or 'bookworm'.\nIf omitted, defaults to 'debian' ('latest').\n"
"description": "Optional. Linux distribution for the base image.\n\nMust be one of 'wolfi', 'debian', or 'bookworm'.\nIf omitted, defaults to 'debian' ('latest').\n"
},
"keep_pkg_tools": {
"anyOf": [
@@ -370,7 +369,7 @@
"type": "null"
}
],
"description": "Optional. Linux distribution for the base image.\n\nMust be one of 'wolfi', 'debian', 'bullseye', or 'bookworm'.\nIf omitted, defaults to 'debian' ('latest').\n"
"description": "Optional. Linux distribution for the base image.\n\nMust be one of 'wolfi', 'debian', or 'bookworm'.\nIf omitted, defaults to 'debian' ('latest').\n"
},
"keep_pkg_tools": {
"anyOf": [
@@ -554,17 +553,6 @@
],
"description": "Optional. Defines the serde configuration.\n\nIf provided, the checkpointer will apply serde settings according to the configuration.\nIf omitted, no serde behavior is configured.\n\nThis configuration requires server version 0.5 or later to take effect.\n"
},
"sweep_limit": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"description": "Maximum number of threads to process per sweep iteration. Defaults to 1000."
},
"ttl": {
"anyOf": [
{
@@ -629,9 +617,10 @@
},
"strategy": {
"enum": [
"delete"
"delete",
"keep_latest"
],
"description": "Strategy to use for deleting checkpointed data.\n"
"description": "Action taken when a thread exceeds its TTL.\n\n"
},
"sweep_interval_minutes": {
"anyOf": [
@@ -643,6 +632,17 @@
}
],
"description": "Interval in minutes between sweep iterations.\nIf omitted, a default interval will be used (typically ~ 5 minutes)."
},
"sweep_limit": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"description": "Maximum number of threads to process per sweep iteration. Defaults to 1000."
}
},
"required": []
+16 -16
View File
@@ -147,7 +147,6 @@
{
"enum": [
"bookworm",
"bullseye",
"debian",
"wolfi"
]
@@ -156,7 +155,7 @@
"type": "null"
}
],
"description": "Optional. Linux distribution for the base image.\n\nMust be one of 'wolfi', 'debian', 'bullseye', or 'bookworm'.\nIf omitted, defaults to 'debian' ('latest').\n"
"description": "Optional. Linux distribution for the base image.\n\nMust be one of 'wolfi', 'debian', or 'bookworm'.\nIf omitted, defaults to 'debian' ('latest').\n"
},
"keep_pkg_tools": {
"anyOf": [
@@ -370,7 +369,7 @@
"type": "null"
}
],
"description": "Optional. Linux distribution for the base image.\n\nMust be one of 'wolfi', 'debian', 'bullseye', or 'bookworm'.\nIf omitted, defaults to 'debian' ('latest').\n"
"description": "Optional. Linux distribution for the base image.\n\nMust be one of 'wolfi', 'debian', or 'bookworm'.\nIf omitted, defaults to 'debian' ('latest').\n"
},
"keep_pkg_tools": {
"anyOf": [
@@ -554,17 +553,6 @@
],
"description": "Optional. Defines the serde configuration.\n\nIf provided, the checkpointer will apply serde settings according to the configuration.\nIf omitted, no serde behavior is configured.\n\nThis configuration requires server version 0.5 or later to take effect.\n"
},
"sweep_limit": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"description": "Maximum number of threads to process per sweep iteration. Defaults to 1000."
},
"ttl": {
"anyOf": [
{
@@ -629,9 +617,10 @@
},
"strategy": {
"enum": [
"delete"
"delete",
"keep_latest"
],
"description": "Strategy to use for deleting checkpointed data.\n"
"description": "Action taken when a thread exceeds its TTL.\n\n"
},
"sweep_interval_minutes": {
"anyOf": [
@@ -643,6 +632,17 @@
}
],
"description": "Interval in minutes between sweep iterations.\nIf omitted, a default interval will be used (typically ~ 5 minutes)."
},
"sweep_limit": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"description": "Maximum number of threads to process per sweep iteration. Defaults to 1000."
}
},
"required": []
+19 -8
View File
@@ -120,14 +120,14 @@ def test_validate_config():
validate_config({"python_version": "3.10"})
assert "Minimum required version" in str(exc_info.value)
config = validate_config(
{
"python_version": "3.11-bullseye",
"dependencies": ["."],
"graphs": {"agent": "./agent.py:graph"},
}
)
assert config["python_version"] == "3.11-bullseye"
with pytest.raises(click.UsageError, match="Bullseye images were deprecated"):
validate_config(
{
"python_version": "3.11-bullseye",
"dependencies": ["."],
"graphs": {"agent": "./agent.py:graph"},
}
)
config = validate_config(
{
@@ -181,6 +181,17 @@ def test_validate_config_image_distro():
)
assert config["image_distro"] == "debian"
# Bullseye should raise deprecation error
with pytest.raises(click.UsageError, match="Bullseye images were deprecated"):
validate_config(
{
"python_version": "3.11",
"dependencies": ["."],
"graphs": {"agent": "./agent.py:graph"},
"image_distro": "bullseye",
}
)
# Invalid image_distro values should raise error
with pytest.raises(click.UsageError) as exc_info:
validate_config(
+84 -90
View File
@@ -385,67 +385,62 @@ wheels = [
[[package]]
name = "cryptography"
version = "46.0.3"
version = "46.0.5"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "cffi", marker = "platform_python_implementation != 'PyPy'" },
{ name = "typing-extensions", marker = "python_full_version < '3.11'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/9f/33/c00162f49c0e2fe8064a62cb92b93e50c74a72bc370ab92f86112b33ff62/cryptography-46.0.3.tar.gz", hash = "sha256:a8b17438104fed022ce745b362294d9ce35b4c2e45c1d958ad4a4b019285f4a1", size = 749258, upload-time = "2025-10-15T23:18:31.74Z" }
sdist = { url = "https://files.pythonhosted.org/packages/60/04/ee2a9e8542e4fa2773b81771ff8349ff19cdd56b7258a0cc442639052edb/cryptography-46.0.5.tar.gz", hash = "sha256:abace499247268e3757271b2f1e244b36b06f8515cf27c4d49468fc9eb16e93d", size = 750064, upload-time = "2026-02-10T19:18:38.255Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/1d/42/9c391dd801d6cf0d561b5890549d4b27bafcc53b39c31a817e69d87c625b/cryptography-46.0.3-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:109d4ddfadf17e8e7779c39f9b18111a09efb969a301a31e987416a0191ed93a", size = 7225004, upload-time = "2025-10-15T23:16:52.239Z" },
{ url = "https://files.pythonhosted.org/packages/1c/67/38769ca6b65f07461eb200e85fc1639b438bdc667be02cf7f2cd6a64601c/cryptography-46.0.3-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:09859af8466b69bc3c27bdf4f5d84a665e0f7ab5088412e9e2ec49758eca5cbc", size = 4296667, upload-time = "2025-10-15T23:16:54.369Z" },
{ url = "https://files.pythonhosted.org/packages/5c/49/498c86566a1d80e978b42f0d702795f69887005548c041636df6ae1ca64c/cryptography-46.0.3-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:01ca9ff2885f3acc98c29f1860552e37f6d7c7d013d7334ff2a9de43a449315d", size = 4450807, upload-time = "2025-10-15T23:16:56.414Z" },
{ url = "https://files.pythonhosted.org/packages/4b/0a/863a3604112174c8624a2ac3c038662d9e59970c7f926acdcfaed8d61142/cryptography-46.0.3-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:6eae65d4c3d33da080cff9c4ab1f711b15c1d9760809dad6ea763f3812d254cb", size = 4299615, upload-time = "2025-10-15T23:16:58.442Z" },
{ url = "https://files.pythonhosted.org/packages/64/02/b73a533f6b64a69f3cd3872acb6ebc12aef924d8d103133bb3ea750dc703/cryptography-46.0.3-cp311-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5bf0ed4490068a2e72ac03d786693adeb909981cc596425d09032d372bcc849", size = 4016800, upload-time = "2025-10-15T23:17:00.378Z" },
{ url = "https://files.pythonhosted.org/packages/25/d5/16e41afbfa450cde85a3b7ec599bebefaef16b5c6ba4ec49a3532336ed72/cryptography-46.0.3-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:5ecfccd2329e37e9b7112a888e76d9feca2347f12f37918facbb893d7bb88ee8", size = 4984707, upload-time = "2025-10-15T23:17:01.98Z" },
{ url = "https://files.pythonhosted.org/packages/c9/56/e7e69b427c3878352c2fb9b450bd0e19ed552753491d39d7d0a2f5226d41/cryptography-46.0.3-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:a2c0cd47381a3229c403062f764160d57d4d175e022c1df84e168c6251a22eec", size = 4482541, upload-time = "2025-10-15T23:17:04.078Z" },
{ url = "https://files.pythonhosted.org/packages/78/f6/50736d40d97e8483172f1bb6e698895b92a223dba513b0ca6f06b2365339/cryptography-46.0.3-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:549e234ff32571b1f4076ac269fcce7a808d3bf98b76c8dd560e42dbc66d7d91", size = 4299464, upload-time = "2025-10-15T23:17:05.483Z" },
{ url = "https://files.pythonhosted.org/packages/00/de/d8e26b1a855f19d9994a19c702fa2e93b0456beccbcfe437eda00e0701f2/cryptography-46.0.3-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:c0a7bb1a68a5d3471880e264621346c48665b3bf1c3759d682fc0864c540bd9e", size = 4950838, upload-time = "2025-10-15T23:17:07.425Z" },
{ url = "https://files.pythonhosted.org/packages/8f/29/798fc4ec461a1c9e9f735f2fc58741b0daae30688f41b2497dcbc9ed1355/cryptography-46.0.3-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:10b01676fc208c3e6feeb25a8b83d81767e8059e1fe86e1dc62d10a3018fa926", size = 4481596, upload-time = "2025-10-15T23:17:09.343Z" },
{ url = "https://files.pythonhosted.org/packages/15/8d/03cd48b20a573adfff7652b76271078e3045b9f49387920e7f1f631d125e/cryptography-46.0.3-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:0abf1ffd6e57c67e92af68330d05760b7b7efb243aab8377e583284dbab72c71", size = 4426782, upload-time = "2025-10-15T23:17:11.22Z" },
{ url = "https://files.pythonhosted.org/packages/fa/b1/ebacbfe53317d55cf33165bda24c86523497a6881f339f9aae5c2e13e57b/cryptography-46.0.3-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a04bee9ab6a4da801eb9b51f1b708a1b5b5c9eb48c03f74198464c66f0d344ac", size = 4698381, upload-time = "2025-10-15T23:17:12.829Z" },
{ url = "https://files.pythonhosted.org/packages/96/92/8a6a9525893325fc057a01f654d7efc2c64b9de90413adcf605a85744ff4/cryptography-46.0.3-cp311-abi3-win32.whl", hash = "sha256:f260d0d41e9b4da1ed1e0f1ce571f97fe370b152ab18778e9e8f67d6af432018", size = 3055988, upload-time = "2025-10-15T23:17:14.65Z" },
{ url = "https://files.pythonhosted.org/packages/7e/bf/80fbf45253ea585a1e492a6a17efcb93467701fa79e71550a430c5e60df0/cryptography-46.0.3-cp311-abi3-win_amd64.whl", hash = "sha256:a9a3008438615669153eb86b26b61e09993921ebdd75385ddd748702c5adfddb", size = 3514451, upload-time = "2025-10-15T23:17:16.142Z" },
{ url = "https://files.pythonhosted.org/packages/2e/af/9b302da4c87b0beb9db4e756386a7c6c5b8003cd0e742277888d352ae91d/cryptography-46.0.3-cp311-abi3-win_arm64.whl", hash = "sha256:5d7f93296ee28f68447397bf5198428c9aeeab45705a55d53a6343455dcb2c3c", size = 2928007, upload-time = "2025-10-15T23:17:18.04Z" },
{ url = "https://files.pythonhosted.org/packages/f5/e2/a510aa736755bffa9d2f75029c229111a1d02f8ecd5de03078f4c18d91a3/cryptography-46.0.3-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:00a5e7e87938e5ff9ff5447ab086a5706a957137e6e433841e9d24f38a065217", size = 7158012, upload-time = "2025-10-15T23:17:19.982Z" },
{ url = "https://files.pythonhosted.org/packages/73/dc/9aa866fbdbb95b02e7f9d086f1fccfeebf8953509b87e3f28fff927ff8a0/cryptography-46.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c8daeb2d2174beb4575b77482320303f3d39b8e81153da4f0fb08eb5fe86a6c5", size = 4288728, upload-time = "2025-10-15T23:17:21.527Z" },
{ url = "https://files.pythonhosted.org/packages/c5/fd/bc1daf8230eaa075184cbbf5f8cd00ba9db4fd32d63fb83da4671b72ed8a/cryptography-46.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:39b6755623145ad5eff1dab323f4eae2a32a77a7abef2c5089a04a3d04366715", size = 4435078, upload-time = "2025-10-15T23:17:23.042Z" },
{ url = "https://files.pythonhosted.org/packages/82/98/d3bd5407ce4c60017f8ff9e63ffee4200ab3e23fe05b765cab805a7db008/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:db391fa7c66df6762ee3f00c95a89e6d428f4d60e7abc8328f4fe155b5ac6e54", size = 4293460, upload-time = "2025-10-15T23:17:24.885Z" },
{ url = "https://files.pythonhosted.org/packages/26/e9/e23e7900983c2b8af7a08098db406cf989d7f09caea7897e347598d4cd5b/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:78a97cf6a8839a48c49271cdcbd5cf37ca2c1d6b7fdd86cc864f302b5e9bf459", size = 3995237, upload-time = "2025-10-15T23:17:26.449Z" },
{ url = "https://files.pythonhosted.org/packages/91/15/af68c509d4a138cfe299d0d7ddb14afba15233223ebd933b4bbdbc7155d3/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:dfb781ff7eaa91a6f7fd41776ec37c5853c795d3b358d4896fdbb5df168af422", size = 4967344, upload-time = "2025-10-15T23:17:28.06Z" },
{ url = "https://files.pythonhosted.org/packages/ca/e3/8643d077c53868b681af077edf6b3cb58288b5423610f21c62aadcbe99f4/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:6f61efb26e76c45c4a227835ddeae96d83624fb0d29eb5df5b96e14ed1a0afb7", size = 4466564, upload-time = "2025-10-15T23:17:29.665Z" },
{ url = "https://files.pythonhosted.org/packages/0e/43/c1e8726fa59c236ff477ff2b5dc071e54b21e5a1e51aa2cee1676f1c986f/cryptography-46.0.3-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:23b1a8f26e43f47ceb6d6a43115f33a5a37d57df4ea0ca295b780ae8546e8044", size = 4292415, upload-time = "2025-10-15T23:17:31.686Z" },
{ url = "https://files.pythonhosted.org/packages/42/f9/2f8fefdb1aee8a8e3256a0568cffc4e6d517b256a2fe97a029b3f1b9fe7e/cryptography-46.0.3-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:b419ae593c86b87014b9be7396b385491ad7f320bde96826d0dd174459e54665", size = 4931457, upload-time = "2025-10-15T23:17:33.478Z" },
{ url = "https://files.pythonhosted.org/packages/79/30/9b54127a9a778ccd6d27c3da7563e9f2d341826075ceab89ae3b41bf5be2/cryptography-46.0.3-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:50fc3343ac490c6b08c0cf0d704e881d0d660be923fd3076db3e932007e726e3", size = 4466074, upload-time = "2025-10-15T23:17:35.158Z" },
{ url = "https://files.pythonhosted.org/packages/ac/68/b4f4a10928e26c941b1b6a179143af9f4d27d88fe84a6a3c53592d2e76bf/cryptography-46.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:22d7e97932f511d6b0b04f2bfd818d73dcd5928db509460aaf48384778eb6d20", size = 4420569, upload-time = "2025-10-15T23:17:37.188Z" },
{ url = "https://files.pythonhosted.org/packages/a3/49/3746dab4c0d1979888f125226357d3262a6dd40e114ac29e3d2abdf1ec55/cryptography-46.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:d55f3dffadd674514ad19451161118fd010988540cee43d8bc20675e775925de", size = 4681941, upload-time = "2025-10-15T23:17:39.236Z" },
{ url = "https://files.pythonhosted.org/packages/fd/30/27654c1dbaf7e4a3531fa1fc77986d04aefa4d6d78259a62c9dc13d7ad36/cryptography-46.0.3-cp314-cp314t-win32.whl", hash = "sha256:8a6e050cb6164d3f830453754094c086ff2d0b2f3a897a1d9820f6139a1f0914", size = 3022339, upload-time = "2025-10-15T23:17:40.888Z" },
{ url = "https://files.pythonhosted.org/packages/f6/30/640f34ccd4d2a1bc88367b54b926b781b5a018d65f404d409aba76a84b1c/cryptography-46.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:760f83faa07f8b64e9c33fc963d790a2edb24efb479e3520c14a45741cd9b2db", size = 3494315, upload-time = "2025-10-15T23:17:42.769Z" },
{ url = "https://files.pythonhosted.org/packages/ba/8b/88cc7e3bd0a8e7b861f26981f7b820e1f46aa9d26cc482d0feba0ecb4919/cryptography-46.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:516ea134e703e9fe26bcd1277a4b59ad30586ea90c365a87781d7887a646fe21", size = 2919331, upload-time = "2025-10-15T23:17:44.468Z" },
{ url = "https://files.pythonhosted.org/packages/fd/23/45fe7f376a7df8daf6da3556603b36f53475a99ce4faacb6ba2cf3d82021/cryptography-46.0.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:cb3d760a6117f621261d662bccc8ef5bc32ca673e037c83fbe565324f5c46936", size = 7218248, upload-time = "2025-10-15T23:17:46.294Z" },
{ url = "https://files.pythonhosted.org/packages/27/32/b68d27471372737054cbd34c84981f9edbc24fe67ca225d389799614e27f/cryptography-46.0.3-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:4b7387121ac7d15e550f5cb4a43aef2559ed759c35df7336c402bb8275ac9683", size = 4294089, upload-time = "2025-10-15T23:17:48.269Z" },
{ url = "https://files.pythonhosted.org/packages/26/42/fa8389d4478368743e24e61eea78846a0006caffaf72ea24a15159215a14/cryptography-46.0.3-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:15ab9b093e8f09daab0f2159bb7e47532596075139dd74365da52ecc9cb46c5d", size = 4440029, upload-time = "2025-10-15T23:17:49.837Z" },
{ url = "https://files.pythonhosted.org/packages/5f/eb/f483db0ec5ac040824f269e93dd2bd8a21ecd1027e77ad7bdf6914f2fd80/cryptography-46.0.3-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:46acf53b40ea38f9c6c229599a4a13f0d46a6c3fa9ef19fc1a124d62e338dfa0", size = 4297222, upload-time = "2025-10-15T23:17:51.357Z" },
{ url = "https://files.pythonhosted.org/packages/fd/cf/da9502c4e1912cb1da3807ea3618a6829bee8207456fbbeebc361ec38ba3/cryptography-46.0.3-cp38-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:10ca84c4668d066a9878890047f03546f3ae0a6b8b39b697457b7757aaf18dbc", size = 4012280, upload-time = "2025-10-15T23:17:52.964Z" },
{ url = "https://files.pythonhosted.org/packages/6b/8f/9adb86b93330e0df8b3dcf03eae67c33ba89958fc2e03862ef1ac2b42465/cryptography-46.0.3-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:36e627112085bb3b81b19fed209c05ce2a52ee8b15d161b7c643a7d5a88491f3", size = 4978958, upload-time = "2025-10-15T23:17:54.965Z" },
{ url = "https://files.pythonhosted.org/packages/d1/a0/5fa77988289c34bdb9f913f5606ecc9ada1adb5ae870bd0d1054a7021cc4/cryptography-46.0.3-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:1000713389b75c449a6e979ffc7dcc8ac90b437048766cef052d4d30b8220971", size = 4473714, upload-time = "2025-10-15T23:17:56.754Z" },
{ url = "https://files.pythonhosted.org/packages/14/e5/fc82d72a58d41c393697aa18c9abe5ae1214ff6f2a5c18ac470f92777895/cryptography-46.0.3-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:b02cf04496f6576afffef5ddd04a0cb7d49cf6be16a9059d793a30b035f6b6ac", size = 4296970, upload-time = "2025-10-15T23:17:58.588Z" },
{ url = "https://files.pythonhosted.org/packages/78/06/5663ed35438d0b09056973994f1aec467492b33bd31da36e468b01ec1097/cryptography-46.0.3-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:71e842ec9bc7abf543b47cf86b9a743baa95f4677d22baa4c7d5c69e49e9bc04", size = 4940236, upload-time = "2025-10-15T23:18:00.897Z" },
{ url = "https://files.pythonhosted.org/packages/fc/59/873633f3f2dcd8a053b8dd1d38f783043b5fce589c0f6988bf55ef57e43e/cryptography-46.0.3-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:402b58fc32614f00980b66d6e56a5b4118e6cb362ae8f3fda141ba4689bd4506", size = 4472642, upload-time = "2025-10-15T23:18:02.749Z" },
{ url = "https://files.pythonhosted.org/packages/3d/39/8e71f3930e40f6877737d6f69248cf74d4e34b886a3967d32f919cc50d3b/cryptography-46.0.3-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ef639cb3372f69ec44915fafcd6698b6cc78fbe0c2ea41be867f6ed612811963", size = 4423126, upload-time = "2025-10-15T23:18:04.85Z" },
{ url = "https://files.pythonhosted.org/packages/cd/c7/f65027c2810e14c3e7268353b1681932b87e5a48e65505d8cc17c99e36ae/cryptography-46.0.3-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3b51b8ca4f1c6453d8829e1eb7299499ca7f313900dd4d89a24b8b87c0a780d4", size = 4686573, upload-time = "2025-10-15T23:18:06.908Z" },
{ url = "https://files.pythonhosted.org/packages/0a/6e/1c8331ddf91ca4730ab3086a0f1be19c65510a33b5a441cb334e7a2d2560/cryptography-46.0.3-cp38-abi3-win32.whl", hash = "sha256:6276eb85ef938dc035d59b87c8a7dc559a232f954962520137529d77b18ff1df", size = 3036695, upload-time = "2025-10-15T23:18:08.672Z" },
{ url = "https://files.pythonhosted.org/packages/90/45/b0d691df20633eff80955a0fc7695ff9051ffce8b69741444bd9ed7bd0db/cryptography-46.0.3-cp38-abi3-win_amd64.whl", hash = "sha256:416260257577718c05135c55958b674000baef9a1c7d9e8f306ec60d71db850f", size = 3501720, upload-time = "2025-10-15T23:18:10.632Z" },
{ url = "https://files.pythonhosted.org/packages/e8/cb/2da4cc83f5edb9c3257d09e1e7ab7b23f049c7962cae8d842bbef0a9cec9/cryptography-46.0.3-cp38-abi3-win_arm64.whl", hash = "sha256:d89c3468de4cdc4f08a57e214384d0471911a3830fcdaf7a8cc587e42a866372", size = 2918740, upload-time = "2025-10-15T23:18:12.277Z" },
{ url = "https://files.pythonhosted.org/packages/d9/cd/1a8633802d766a0fa46f382a77e096d7e209e0817892929655fe0586ae32/cryptography-46.0.3-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a23582810fedb8c0bc47524558fb6c56aac3fc252cb306072fd2815da2a47c32", size = 3689163, upload-time = "2025-10-15T23:18:13.821Z" },
{ url = "https://files.pythonhosted.org/packages/4c/59/6b26512964ace6480c3e54681a9859c974172fb141c38df11eadd8416947/cryptography-46.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:e7aec276d68421f9574040c26e2a7c3771060bc0cff408bae1dcb19d3ab1e63c", size = 3429474, upload-time = "2025-10-15T23:18:15.477Z" },
{ url = "https://files.pythonhosted.org/packages/06/8a/e60e46adab4362a682cf142c7dcb5bf79b782ab2199b0dcb81f55970807f/cryptography-46.0.3-pp311-pypy311_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7ce938a99998ed3c8aa7e7272dca1a610401ede816d36d0693907d863b10d9ea", size = 3698132, upload-time = "2025-10-15T23:18:17.056Z" },
{ url = "https://files.pythonhosted.org/packages/da/38/f59940ec4ee91e93d3311f7532671a5cef5570eb04a144bf203b58552d11/cryptography-46.0.3-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:191bb60a7be5e6f54e30ba16fdfae78ad3a342a0599eb4193ba88e3f3d6e185b", size = 4243992, upload-time = "2025-10-15T23:18:18.695Z" },
{ url = "https://files.pythonhosted.org/packages/b0/0c/35b3d92ddebfdfda76bb485738306545817253d0a3ded0bfe80ef8e67aa5/cryptography-46.0.3-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c70cc23f12726be8f8bc72e41d5065d77e4515efae3690326764ea1b07845cfb", size = 4409944, upload-time = "2025-10-15T23:18:20.597Z" },
{ url = "https://files.pythonhosted.org/packages/99/55/181022996c4063fc0e7666a47049a1ca705abb9c8a13830f074edb347495/cryptography-46.0.3-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:9394673a9f4de09e28b5356e7fff97d778f8abad85c9d5ac4a4b7e25a0de7717", size = 4242957, upload-time = "2025-10-15T23:18:22.18Z" },
{ url = "https://files.pythonhosted.org/packages/ba/af/72cd6ef29f9c5f731251acadaeb821559fe25f10852f44a63374c9ca08c1/cryptography-46.0.3-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:94cd0549accc38d1494e1f8de71eca837d0509d0d44bf11d158524b0e12cebf9", size = 4409447, upload-time = "2025-10-15T23:18:24.209Z" },
{ url = "https://files.pythonhosted.org/packages/0d/c3/e90f4a4feae6410f914f8ebac129b9ae7a8c92eb60a638012dde42030a9d/cryptography-46.0.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:6b5063083824e5509fdba180721d55909ffacccc8adbec85268b48439423d78c", size = 3438528, upload-time = "2025-10-15T23:18:26.227Z" },
{ url = "https://files.pythonhosted.org/packages/f7/81/b0bb27f2ba931a65409c6b8a8b358a7f03c0e46eceacddff55f7c84b1f3b/cryptography-46.0.5-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:351695ada9ea9618b3500b490ad54c739860883df6c1f555e088eaf25b1bbaad", size = 7176289, upload-time = "2026-02-10T19:17:08.274Z" },
{ url = "https://files.pythonhosted.org/packages/ff/9e/6b4397a3e3d15123de3b1806ef342522393d50736c13b20ec4c9ea6693a6/cryptography-46.0.5-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c18ff11e86df2e28854939acde2d003f7984f721eba450b56a200ad90eeb0e6b", size = 4275637, upload-time = "2026-02-10T19:17:10.53Z" },
{ url = "https://files.pythonhosted.org/packages/63/e7/471ab61099a3920b0c77852ea3f0ea611c9702f651600397ac567848b897/cryptography-46.0.5-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4d7e3d356b8cd4ea5aff04f129d5f66ebdc7b6f8eae802b93739ed520c47c79b", size = 4424742, upload-time = "2026-02-10T19:17:12.388Z" },
{ url = "https://files.pythonhosted.org/packages/37/53/a18500f270342d66bf7e4d9f091114e31e5ee9e7375a5aba2e85a91e0044/cryptography-46.0.5-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:50bfb6925eff619c9c023b967d5b77a54e04256c4281b0e21336a130cd7fc263", size = 4277528, upload-time = "2026-02-10T19:17:13.853Z" },
{ url = "https://files.pythonhosted.org/packages/22/29/c2e812ebc38c57b40e7c583895e73c8c5adb4d1e4a0cc4c5a4fdab2b1acc/cryptography-46.0.5-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:803812e111e75d1aa73690d2facc295eaefd4439be1023fefc4995eaea2af90d", size = 4947993, upload-time = "2026-02-10T19:17:15.618Z" },
{ url = "https://files.pythonhosted.org/packages/6b/e7/237155ae19a9023de7e30ec64e5d99a9431a567407ac21170a046d22a5a3/cryptography-46.0.5-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3ee190460e2fbe447175cda91b88b84ae8322a104fc27766ad09428754a618ed", size = 4456855, upload-time = "2026-02-10T19:17:17.221Z" },
{ url = "https://files.pythonhosted.org/packages/2d/87/fc628a7ad85b81206738abbd213b07702bcbdada1dd43f72236ef3cffbb5/cryptography-46.0.5-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:f145bba11b878005c496e93e257c1e88f154d278d2638e6450d17e0f31e558d2", size = 3984635, upload-time = "2026-02-10T19:17:18.792Z" },
{ url = "https://files.pythonhosted.org/packages/84/29/65b55622bde135aedf4565dc509d99b560ee4095e56989e815f8fd2aa910/cryptography-46.0.5-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:e9251e3be159d1020c4030bd2e5f84d6a43fe54b6c19c12f51cde9542a2817b2", size = 4277038, upload-time = "2026-02-10T19:17:20.256Z" },
{ url = "https://files.pythonhosted.org/packages/bc/36/45e76c68d7311432741faf1fbf7fac8a196a0a735ca21f504c75d37e2558/cryptography-46.0.5-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:47fb8a66058b80e509c47118ef8a75d14c455e81ac369050f20ba0d23e77fee0", size = 4912181, upload-time = "2026-02-10T19:17:21.825Z" },
{ url = "https://files.pythonhosted.org/packages/6d/1a/c1ba8fead184d6e3d5afcf03d569acac5ad063f3ac9fb7258af158f7e378/cryptography-46.0.5-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:4c3341037c136030cb46e4b1e17b7418ea4cbd9dd207e4a6f3b2b24e0d4ac731", size = 4456482, upload-time = "2026-02-10T19:17:25.133Z" },
{ url = "https://files.pythonhosted.org/packages/f9/e5/3fb22e37f66827ced3b902cf895e6a6bc1d095b5b26be26bd13c441fdf19/cryptography-46.0.5-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:890bcb4abd5a2d3f852196437129eb3667d62630333aacc13dfd470fad3aaa82", size = 4405497, upload-time = "2026-02-10T19:17:26.66Z" },
{ url = "https://files.pythonhosted.org/packages/1a/df/9d58bb32b1121a8a2f27383fabae4d63080c7ca60b9b5c88be742be04ee7/cryptography-46.0.5-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:80a8d7bfdf38f87ca30a5391c0c9ce4ed2926918e017c29ddf643d0ed2778ea1", size = 4667819, upload-time = "2026-02-10T19:17:28.569Z" },
{ url = "https://files.pythonhosted.org/packages/ea/ed/325d2a490c5e94038cdb0117da9397ece1f11201f425c4e9c57fe5b9f08b/cryptography-46.0.5-cp311-abi3-win32.whl", hash = "sha256:60ee7e19e95104d4c03871d7d7dfb3d22ef8a9b9c6778c94e1c8fcc8365afd48", size = 3028230, upload-time = "2026-02-10T19:17:30.518Z" },
{ url = "https://files.pythonhosted.org/packages/e9/5a/ac0f49e48063ab4255d9e3b79f5def51697fce1a95ea1370f03dc9db76f6/cryptography-46.0.5-cp311-abi3-win_amd64.whl", hash = "sha256:38946c54b16c885c72c4f59846be9743d699eee2b69b6988e0a00a01f46a61a4", size = 3480909, upload-time = "2026-02-10T19:17:32.083Z" },
{ url = "https://files.pythonhosted.org/packages/00/13/3d278bfa7a15a96b9dc22db5a12ad1e48a9eb3d40e1827ef66a5df75d0d0/cryptography-46.0.5-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:94a76daa32eb78d61339aff7952ea819b1734b46f73646a07decb40e5b3448e2", size = 7119287, upload-time = "2026-02-10T19:17:33.801Z" },
{ url = "https://files.pythonhosted.org/packages/67/c8/581a6702e14f0898a0848105cbefd20c058099e2c2d22ef4e476dfec75d7/cryptography-46.0.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5be7bf2fb40769e05739dd0046e7b26f9d4670badc7b032d6ce4db64dddc0678", size = 4265728, upload-time = "2026-02-10T19:17:35.569Z" },
{ url = "https://files.pythonhosted.org/packages/dd/4a/ba1a65ce8fc65435e5a849558379896c957870dd64fecea97b1ad5f46a37/cryptography-46.0.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fe346b143ff9685e40192a4960938545c699054ba11d4f9029f94751e3f71d87", size = 4408287, upload-time = "2026-02-10T19:17:36.938Z" },
{ url = "https://files.pythonhosted.org/packages/f8/67/8ffdbf7b65ed1ac224d1c2df3943553766914a8ca718747ee3871da6107e/cryptography-46.0.5-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:c69fd885df7d089548a42d5ec05be26050ebcd2283d89b3d30676eb32ff87dee", size = 4270291, upload-time = "2026-02-10T19:17:38.748Z" },
{ url = "https://files.pythonhosted.org/packages/f8/e5/f52377ee93bc2f2bba55a41a886fd208c15276ffbd2569f2ddc89d50e2c5/cryptography-46.0.5-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:8293f3dea7fc929ef7240796ba231413afa7b68ce38fd21da2995549f5961981", size = 4927539, upload-time = "2026-02-10T19:17:40.241Z" },
{ url = "https://files.pythonhosted.org/packages/3b/02/cfe39181b02419bbbbcf3abdd16c1c5c8541f03ca8bda240debc467d5a12/cryptography-46.0.5-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:1abfdb89b41c3be0365328a410baa9df3ff8a9110fb75e7b52e66803ddabc9a9", size = 4442199, upload-time = "2026-02-10T19:17:41.789Z" },
{ url = "https://files.pythonhosted.org/packages/c0/96/2fcaeb4873e536cf71421a388a6c11b5bc846e986b2b069c79363dc1648e/cryptography-46.0.5-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:d66e421495fdb797610a08f43b05269e0a5ea7f5e652a89bfd5a7d3c1dee3648", size = 3960131, upload-time = "2026-02-10T19:17:43.379Z" },
{ url = "https://files.pythonhosted.org/packages/d8/d2/b27631f401ddd644e94c5cf33c9a4069f72011821cf3dc7309546b0642a0/cryptography-46.0.5-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:4e817a8920bfbcff8940ecfd60f23d01836408242b30f1a708d93198393a80b4", size = 4270072, upload-time = "2026-02-10T19:17:45.481Z" },
{ url = "https://files.pythonhosted.org/packages/f4/a7/60d32b0370dae0b4ebe55ffa10e8599a2a59935b5ece1b9f06edb73abdeb/cryptography-46.0.5-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:68f68d13f2e1cb95163fa3b4db4bf9a159a418f5f6e7242564fc75fcae667fd0", size = 4892170, upload-time = "2026-02-10T19:17:46.997Z" },
{ url = "https://files.pythonhosted.org/packages/d2/b9/cf73ddf8ef1164330eb0b199a589103c363afa0cf794218c24d524a58eab/cryptography-46.0.5-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:a3d1fae9863299076f05cb8a778c467578262fae09f9dc0ee9b12eb4268ce663", size = 4441741, upload-time = "2026-02-10T19:17:48.661Z" },
{ url = "https://files.pythonhosted.org/packages/5f/eb/eee00b28c84c726fe8fa0158c65afe312d9c3b78d9d01daf700f1f6e37ff/cryptography-46.0.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c4143987a42a2397f2fc3b4d7e3a7d313fbe684f67ff443999e803dd75a76826", size = 4396728, upload-time = "2026-02-10T19:17:50.058Z" },
{ url = "https://files.pythonhosted.org/packages/65/f4/6bc1a9ed5aef7145045114b75b77c2a8261b4d38717bd8dea111a63c3442/cryptography-46.0.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:7d731d4b107030987fd61a7f8ab512b25b53cef8f233a97379ede116f30eb67d", size = 4652001, upload-time = "2026-02-10T19:17:51.54Z" },
{ url = "https://files.pythonhosted.org/packages/86/ef/5d00ef966ddd71ac2e6951d278884a84a40ffbd88948ef0e294b214ae9e4/cryptography-46.0.5-cp314-cp314t-win32.whl", hash = "sha256:c3bcce8521d785d510b2aad26ae2c966092b7daa8f45dd8f44734a104dc0bc1a", size = 3003637, upload-time = "2026-02-10T19:17:52.997Z" },
{ url = "https://files.pythonhosted.org/packages/b7/57/f3f4160123da6d098db78350fdfd9705057aad21de7388eacb2401dceab9/cryptography-46.0.5-cp314-cp314t-win_amd64.whl", hash = "sha256:4d8ae8659ab18c65ced284993c2265910f6c9e650189d4e3f68445ef82a810e4", size = 3469487, upload-time = "2026-02-10T19:17:54.549Z" },
{ url = "https://files.pythonhosted.org/packages/e2/fa/a66aa722105ad6a458bebd64086ca2b72cdd361fed31763d20390f6f1389/cryptography-46.0.5-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:4108d4c09fbbf2789d0c926eb4152ae1760d5a2d97612b92d508d96c861e4d31", size = 7170514, upload-time = "2026-02-10T19:17:56.267Z" },
{ url = "https://files.pythonhosted.org/packages/0f/04/c85bdeab78c8bc77b701bf0d9bdcf514c044e18a46dcff330df5448631b0/cryptography-46.0.5-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7d1f30a86d2757199cb2d56e48cce14deddf1f9c95f1ef1b64ee91ea43fe2e18", size = 4275349, upload-time = "2026-02-10T19:17:58.419Z" },
{ url = "https://files.pythonhosted.org/packages/5c/32/9b87132a2f91ee7f5223b091dc963055503e9b442c98fc0b8a5ca765fab0/cryptography-46.0.5-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:039917b0dc418bb9f6edce8a906572d69e74bd330b0b3fea4f79dab7f8ddd235", size = 4420667, upload-time = "2026-02-10T19:18:00.619Z" },
{ url = "https://files.pythonhosted.org/packages/a1/a6/a7cb7010bec4b7c5692ca6f024150371b295ee1c108bdc1c400e4c44562b/cryptography-46.0.5-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ba2a27ff02f48193fc4daeadf8ad2590516fa3d0adeeb34336b96f7fa64c1e3a", size = 4276980, upload-time = "2026-02-10T19:18:02.379Z" },
{ url = "https://files.pythonhosted.org/packages/8e/7c/c4f45e0eeff9b91e3f12dbd0e165fcf2a38847288fcfd889deea99fb7b6d/cryptography-46.0.5-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:61aa400dce22cb001a98014f647dc21cda08f7915ceb95df0c9eaf84b4b6af76", size = 4939143, upload-time = "2026-02-10T19:18:03.964Z" },
{ url = "https://files.pythonhosted.org/packages/37/19/e1b8f964a834eddb44fa1b9a9976f4e414cbb7aa62809b6760c8803d22d1/cryptography-46.0.5-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3ce58ba46e1bc2aac4f7d9290223cead56743fa6ab94a5d53292ffaac6a91614", size = 4453674, upload-time = "2026-02-10T19:18:05.588Z" },
{ url = "https://files.pythonhosted.org/packages/db/ed/db15d3956f65264ca204625597c410d420e26530c4e2943e05a0d2f24d51/cryptography-46.0.5-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:420d0e909050490d04359e7fdb5ed7e667ca5c3c402b809ae2563d7e66a92229", size = 3978801, upload-time = "2026-02-10T19:18:07.167Z" },
{ url = "https://files.pythonhosted.org/packages/41/e2/df40a31d82df0a70a0daf69791f91dbb70e47644c58581d654879b382d11/cryptography-46.0.5-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:582f5fcd2afa31622f317f80426a027f30dc792e9c80ffee87b993200ea115f1", size = 4276755, upload-time = "2026-02-10T19:18:09.813Z" },
{ url = "https://files.pythonhosted.org/packages/33/45/726809d1176959f4a896b86907b98ff4391a8aa29c0aaaf9450a8a10630e/cryptography-46.0.5-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:bfd56bb4b37ed4f330b82402f6f435845a5f5648edf1ad497da51a8452d5d62d", size = 4901539, upload-time = "2026-02-10T19:18:11.263Z" },
{ url = "https://files.pythonhosted.org/packages/99/0f/a3076874e9c88ecb2ecc31382f6e7c21b428ede6f55aafa1aa272613e3cd/cryptography-46.0.5-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:a3d507bb6a513ca96ba84443226af944b0f7f47dcc9a399d110cd6146481d24c", size = 4452794, upload-time = "2026-02-10T19:18:12.914Z" },
{ url = "https://files.pythonhosted.org/packages/02/ef/ffeb542d3683d24194a38f66ca17c0a4b8bf10631feef44a7ef64e631b1a/cryptography-46.0.5-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9f16fbdf4da055efb21c22d81b89f155f02ba420558db21288b3d0035bafd5f4", size = 4404160, upload-time = "2026-02-10T19:18:14.375Z" },
{ url = "https://files.pythonhosted.org/packages/96/93/682d2b43c1d5f1406ed048f377c0fc9fc8f7b0447a478d5c65ab3d3a66eb/cryptography-46.0.5-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:ced80795227d70549a411a4ab66e8ce307899fad2220ce5ab2f296e687eacde9", size = 4667123, upload-time = "2026-02-10T19:18:15.886Z" },
{ url = "https://files.pythonhosted.org/packages/45/2d/9c5f2926cb5300a8eefc3f4f0b3f3df39db7f7ce40c8365444c49363cbda/cryptography-46.0.5-cp38-abi3-win32.whl", hash = "sha256:02f547fce831f5096c9a567fd41bc12ca8f11df260959ecc7c3202555cc47a72", size = 3010220, upload-time = "2026-02-10T19:18:17.361Z" },
{ url = "https://files.pythonhosted.org/packages/48/ef/0c2f4a8e31018a986949d34a01115dd057bf536905dca38897bacd21fac3/cryptography-46.0.5-cp38-abi3-win_amd64.whl", hash = "sha256:556e106ee01aa13484ce9b0239bca667be5004efb0aabbed28d353df86445595", size = 3467050, upload-time = "2026-02-10T19:18:18.899Z" },
{ url = "https://files.pythonhosted.org/packages/eb/dd/2d9fdb07cebdf3d51179730afb7d5e576153c6744c3ff8fded23030c204e/cryptography-46.0.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:3b4995dc971c9fb83c25aa44cf45f02ba86f71ee600d81091c2f0cbae116b06c", size = 3476964, upload-time = "2026-02-10T19:18:20.687Z" },
{ url = "https://files.pythonhosted.org/packages/e9/6f/6cc6cc9955caa6eaf83660b0da2b077c7fe8ff9950a3c5e45d605038d439/cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:bc84e875994c3b445871ea7181d424588171efec3e185dced958dad9e001950a", size = 4218321, upload-time = "2026-02-10T19:18:22.349Z" },
{ url = "https://files.pythonhosted.org/packages/3e/5d/c4da701939eeee699566a6c1367427ab91a8b7088cc2328c09dbee940415/cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:2ae6971afd6246710480e3f15824ed3029a60fc16991db250034efd0b9fb4356", size = 4381786, upload-time = "2026-02-10T19:18:24.529Z" },
{ url = "https://files.pythonhosted.org/packages/ac/97/a538654732974a94ff96c1db621fa464f455c02d4bb7d2652f4edc21d600/cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:d861ee9e76ace6cf36a6a89b959ec08e7bc2493ee39d07ffe5acb23ef46d27da", size = 4217990, upload-time = "2026-02-10T19:18:25.957Z" },
{ url = "https://files.pythonhosted.org/packages/ae/11/7e500d2dd3ba891197b9efd2da5454b74336d64a7cc419aa7327ab74e5f6/cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:2b7a67c9cd56372f3249b39699f2ad479f6991e62ea15800973b956f4b73e257", size = 4381252, upload-time = "2026-02-10T19:18:27.496Z" },
{ url = "https://files.pythonhosted.org/packages/bc/58/6b3d24e6b9bc474a2dcdee65dfd1f008867015408a271562e4b690561a4d/cryptography-46.0.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:8456928655f856c6e1533ff59d5be76578a7157224dbd9ce6872f25055ab9ab7", size = 3407605, upload-time = "2026-02-10T19:18:29.233Z" },
]
[[package]]
@@ -884,7 +879,7 @@ wheels = [
[[package]]
name = "langchain-core"
version = "1.2.7"
version = "1.2.11"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "jsonpatch", marker = "python_full_version >= '3.11'" },
@@ -896,9 +891,9 @@ dependencies = [
{ name = "typing-extensions", marker = "python_full_version >= '3.11'" },
{ name = "uuid-utils", marker = "python_full_version >= '3.11'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/a2/0e/664d8d81b3493e09cbab72448d2f9d693d1fa5aa2bcc488602203a9b6da0/langchain_core-1.2.7.tar.gz", hash = "sha256:e1460639f96c352b4a41c375f25aeb8d16ffc1769499fb1c20503aad59305ced", size = 837039, upload-time = "2026-01-09T17:44:25.505Z" }
sdist = { url = "https://files.pythonhosted.org/packages/12/17/1943cedfc118e04b8128e4c3e1dbf0fa0ea58eefddbb6198cfd699d19f01/langchain_core-1.2.11.tar.gz", hash = "sha256:f164bb36602dd74a3a50c1334fca75309ad5ed95767acdfdbb9fa95ce28a1e01", size = 831211, upload-time = "2026-02-10T20:35:28.35Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/6e/6f/34a9fba14d191a67f7e2ee3dbce3e9b86d2fa7310e2c7f2c713583481bd2/langchain_core-1.2.7-py3-none-any.whl", hash = "sha256:452f4fef7a3d883357b22600788d37e3d8854ef29da345b7ac7099f33c31828b", size = 490232, upload-time = "2026-01-09T17:44:24.236Z" },
{ url = "https://files.pythonhosted.org/packages/10/30/1f80e3fc674353cad975ed5294353d42512535d2094ef032c06454c2c873/langchain_core-1.2.11-py3-none-any.whl", hash = "sha256:ae11ceb8dda60d0b9d09e763116e592f1683327c17be5b715f350fd29aee65d3", size = 500062, upload-time = "2026-02-10T20:35:26.698Z" },
]
[[package]]
@@ -1076,15 +1071,15 @@ wheels = [
[[package]]
name = "langgraph-sdk"
version = "0.3.3"
version = "0.3.6"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "httpx", marker = "python_full_version >= '3.11'" },
{ name = "orjson", marker = "python_full_version >= '3.11'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/c3/0f/ed0634c222eed48a31ba48eab6881f94ad690d65e44fe7ca838240a260c1/langgraph_sdk-0.3.3.tar.gz", hash = "sha256:c34c3dce3b6848755eb61f0c94369d1ba04aceeb1b76015db1ea7362c544fb26", size = 130589, upload-time = "2026-01-13T00:30:43.894Z" }
sdist = { url = "https://files.pythonhosted.org/packages/3e/ec/477fa8b408f948b145d90fd935c0a9f37945fa5ec1dfabfc71e7cafba6d8/langgraph_sdk-0.3.6.tar.gz", hash = "sha256:7650f607f89c1586db5bee391b1a8754cbe1fc83b721ff2f1450f8906e790bd7", size = 182666, upload-time = "2026-02-14T19:46:03.752Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/6e/be/4ad511bacfdd854afb12974f407cb30010dceb982dc20c55491867b34526/langgraph_sdk-0.3.3-py3-none-any.whl", hash = "sha256:a52ebaf09d91143e55378bb2d0b033ed98f57f48c9ad35c8f81493b88705fc7b", size = 67021, upload-time = "2026-01-13T00:30:42.264Z" },
{ url = "https://files.pythonhosted.org/packages/d8/61/12508e12652edd1874327271a5a8834c728a605f53a1a1c945f13ab69664/langgraph_sdk-0.3.6-py3-none-any.whl", hash = "sha256:7df2fd552ad7262d0baf8e1f849dce1d62186e76dcdd36db9dc5bdfa5c3fc20f", size = 88277, upload-time = "2026-02-14T19:46:02.48Z" },
]
[[package]]
@@ -1596,17 +1591,17 @@ wheels = [
[[package]]
name = "protobuf"
version = "6.33.4"
version = "6.33.5"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/53/b8/cda15d9d46d03d4aa3a67cb6bffe05173440ccf86a9541afaf7ac59a1b6b/protobuf-6.33.4.tar.gz", hash = "sha256:dc2e61bca3b10470c1912d166fe0af67bfc20eb55971dcef8dfa48ce14f0ed91", size = 444346, upload-time = "2026-01-12T18:33:40.109Z" }
sdist = { url = "https://files.pythonhosted.org/packages/ba/25/7c72c307aafc96fa87062aa6291d9f7c94836e43214d43722e86037aac02/protobuf-6.33.5.tar.gz", hash = "sha256:6ddcac2a081f8b7b9642c09406bc6a4290128fce5f471cddd165960bb9119e5c", size = 444465, upload-time = "2026-01-29T21:51:33.494Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e0/be/24ef9f3095bacdf95b458543334d0c4908ccdaee5130420bf064492c325f/protobuf-6.33.4-cp310-abi3-win32.whl", hash = "sha256:918966612c8232fc6c24c78e1cd89784307f5814ad7506c308ee3cf86662850d", size = 425612, upload-time = "2026-01-12T18:33:29.656Z" },
{ url = "https://files.pythonhosted.org/packages/31/ad/e5693e1974a28869e7cd244302911955c1cebc0161eb32dfa2b25b6e96f0/protobuf-6.33.4-cp310-abi3-win_amd64.whl", hash = "sha256:8f11ffae31ec67fc2554c2ef891dcb561dae9a2a3ed941f9e134c2db06657dbc", size = 436962, upload-time = "2026-01-12T18:33:31.345Z" },
{ url = "https://files.pythonhosted.org/packages/66/15/6ee23553b6bfd82670207ead921f4d8ef14c107e5e11443b04caeb5ab5ec/protobuf-6.33.4-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:2fe67f6c014c84f655ee06f6f66213f9254b3a8b6bda6cda0ccd4232c73c06f0", size = 427612, upload-time = "2026-01-12T18:33:32.646Z" },
{ url = "https://files.pythonhosted.org/packages/2b/48/d301907ce6d0db75f959ca74f44b475a9caa8fcba102d098d3c3dd0f2d3f/protobuf-6.33.4-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:757c978f82e74d75cba88eddec479df9b99a42b31193313b75e492c06a51764e", size = 324484, upload-time = "2026-01-12T18:33:33.789Z" },
{ url = "https://files.pythonhosted.org/packages/92/1c/e53078d3f7fe710572ab2dcffd993e1e3b438ae71cfc031b71bae44fcb2d/protobuf-6.33.4-cp39-abi3-manylinux2014_s390x.whl", hash = "sha256:c7c64f259c618f0bef7bee042075e390debbf9682334be2b67408ec7c1c09ee6", size = 339256, upload-time = "2026-01-12T18:33:35.231Z" },
{ url = "https://files.pythonhosted.org/packages/e8/8e/971c0edd084914f7ee7c23aa70ba89e8903918adca179319ee94403701d5/protobuf-6.33.4-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:3df850c2f8db9934de4cf8f9152f8dc2558f49f298f37f90c517e8e5c84c30e9", size = 323311, upload-time = "2026-01-12T18:33:36.305Z" },
{ url = "https://files.pythonhosted.org/packages/75/b1/1dc83c2c661b4c62d56cc081706ee33a4fc2835bd90f965baa2663ef7676/protobuf-6.33.4-py3-none-any.whl", hash = "sha256:1fe3730068fcf2e595816a6c34fe66eeedd37d51d0400b72fabc848811fdc1bc", size = 170532, upload-time = "2026-01-12T18:33:39.199Z" },
{ url = "https://files.pythonhosted.org/packages/b1/79/af92d0a8369732b027e6d6084251dd8e782c685c72da161bd4a2e00fbabb/protobuf-6.33.5-cp310-abi3-win32.whl", hash = "sha256:d71b040839446bac0f4d162e758bea99c8251161dae9d0983a3b88dee345153b", size = 425769, upload-time = "2026-01-29T21:51:21.751Z" },
{ url = "https://files.pythonhosted.org/packages/55/75/bb9bc917d10e9ee13dee8607eb9ab963b7cf8be607c46e7862c748aa2af7/protobuf-6.33.5-cp310-abi3-win_amd64.whl", hash = "sha256:3093804752167bcab3998bec9f1048baae6e29505adaf1afd14a37bddede533c", size = 437118, upload-time = "2026-01-29T21:51:24.022Z" },
{ url = "https://files.pythonhosted.org/packages/a2/6b/e48dfc1191bc5b52950246275bf4089773e91cb5ba3592621723cdddca62/protobuf-6.33.5-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:a5cb85982d95d906df1e2210e58f8e4f1e3cdc088e52c921a041f9c9a0386de5", size = 427766, upload-time = "2026-01-29T21:51:25.413Z" },
{ url = "https://files.pythonhosted.org/packages/4e/b1/c79468184310de09d75095ed1314b839eb2f72df71097db9d1404a1b2717/protobuf-6.33.5-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:9b71e0281f36f179d00cbcb119cb19dec4d14a81393e5ea220f64b286173e190", size = 324638, upload-time = "2026-01-29T21:51:26.423Z" },
{ url = "https://files.pythonhosted.org/packages/c5/f5/65d838092fd01c44d16037953fd4c2cc851e783de9b8f02b27ec4ffd906f/protobuf-6.33.5-cp39-abi3-manylinux2014_s390x.whl", hash = "sha256:8afa18e1d6d20af15b417e728e9f60f3aa108ee76f23c3b2c07a2c3b546d3afd", size = 339411, upload-time = "2026-01-29T21:51:27.446Z" },
{ url = "https://files.pythonhosted.org/packages/9b/53/a9443aa3ca9ba8724fdfa02dd1887c1bcd8e89556b715cfbacca6b63dbec/protobuf-6.33.5-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:cbf16ba3350fb7b889fca858fb215967792dc125b35c7976ca4818bee3521cf0", size = 323465, upload-time = "2026-01-29T21:51:28.925Z" },
{ url = "https://files.pythonhosted.org/packages/57/bf/2086963c69bdac3d7cff1cc7ff79b8ce5ea0bec6797a017e1be338a46248/protobuf-6.33.5-py3-none-any.whl", hash = "sha256:69915a973dd0f60f31a08b8318b73eab2bd6a392c79184b3612226b0a3f8ec02", size = 170687, upload-time = "2026-01-29T21:51:32.557Z" },
]
[[package]]
@@ -1967,28 +1962,27 @@ wheels = [
[[package]]
name = "ruff"
version = "0.14.14"
version = "0.15.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/2e/06/f71e3a86b2df0dfa2d2f72195941cd09b44f87711cb7fa5193732cb9a5fc/ruff-0.14.14.tar.gz", hash = "sha256:2d0f819c9a90205f3a867dbbd0be083bee9912e170fd7d9704cc8ae45824896b", size = 4515732, upload-time = "2026-01-22T22:30:17.527Z" }
sdist = { url = "https://files.pythonhosted.org/packages/04/dc/4e6ac71b511b141cf626357a3946679abeba4cf67bc7cc5a17920f31e10d/ruff-0.15.1.tar.gz", hash = "sha256:c590fe13fb57c97141ae975c03a1aedb3d3156030cabd740d6ff0b0d601e203f", size = 4540855, upload-time = "2026-02-12T23:09:09.998Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d2/89/20a12e97bc6b9f9f68343952da08a8099c57237aef953a56b82711d55edd/ruff-0.14.14-py3-none-linux_armv6l.whl", hash = "sha256:7cfe36b56e8489dee8fbc777c61959f60ec0f1f11817e8f2415f429552846aed", size = 10467650, upload-time = "2026-01-22T22:30:08.578Z" },
{ url = "https://files.pythonhosted.org/packages/a3/b1/c5de3fd2d5a831fcae21beda5e3589c0ba67eec8202e992388e4b17a6040/ruff-0.14.14-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6006a0082336e7920b9573ef8a7f52eec837add1265cc74e04ea8a4368cd704c", size = 10883245, upload-time = "2026-01-22T22:30:04.155Z" },
{ url = "https://files.pythonhosted.org/packages/b8/7c/3c1db59a10e7490f8f6f8559d1db8636cbb13dccebf18686f4e3c9d7c772/ruff-0.14.14-py3-none-macosx_11_0_arm64.whl", hash = "sha256:026c1d25996818f0bf498636686199d9bd0d9d6341c9c2c3b62e2a0198b758de", size = 10231273, upload-time = "2026-01-22T22:30:34.642Z" },
{ url = "https://files.pythonhosted.org/packages/a1/6e/5e0e0d9674be0f8581d1f5e0f0a04761203affce3232c1a1189d0e3b4dad/ruff-0.14.14-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f666445819d31210b71e0a6d1c01e24447a20b85458eea25a25fe8142210ae0e", size = 10585753, upload-time = "2026-01-22T22:30:31.781Z" },
{ url = "https://files.pythonhosted.org/packages/23/09/754ab09f46ff1884d422dc26d59ba18b4e5d355be147721bb2518aa2a014/ruff-0.14.14-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3c0f18b922c6d2ff9a5e6c3ee16259adc513ca775bcf82c67ebab7cbd9da5bc8", size = 10286052, upload-time = "2026-01-22T22:30:24.827Z" },
{ url = "https://files.pythonhosted.org/packages/c8/cc/e71f88dd2a12afb5f50733851729d6b571a7c3a35bfdb16c3035132675a0/ruff-0.14.14-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1629e67489c2dea43e8658c3dba659edbfd87361624b4040d1df04c9740ae906", size = 11043637, upload-time = "2026-01-22T22:30:13.239Z" },
{ url = "https://files.pythonhosted.org/packages/67/b2/397245026352494497dac935d7f00f1468c03a23a0c5db6ad8fc49ca3fb2/ruff-0.14.14-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:27493a2131ea0f899057d49d303e4292b2cae2bb57253c1ed1f256fbcd1da480", size = 12194761, upload-time = "2026-01-22T22:30:22.542Z" },
{ url = "https://files.pythonhosted.org/packages/5b/06/06ef271459f778323112c51b7587ce85230785cd64e91772034ddb88f200/ruff-0.14.14-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:01ff589aab3f5b539e35db38425da31a57521efd1e4ad1ae08fc34dbe30bd7df", size = 12005701, upload-time = "2026-01-22T22:30:20.499Z" },
{ url = "https://files.pythonhosted.org/packages/41/d6/99364514541cf811ccc5ac44362f88df66373e9fec1b9d1c4cc830593fe7/ruff-0.14.14-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1cc12d74eef0f29f51775f5b755913eb523546b88e2d733e1d701fe65144e89b", size = 11282455, upload-time = "2026-01-22T22:29:59.679Z" },
{ url = "https://files.pythonhosted.org/packages/ca/71/37daa46f89475f8582b7762ecd2722492df26421714a33e72ccc9a84d7a5/ruff-0.14.14-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb8481604b7a9e75eff53772496201690ce2687067e038b3cc31aaf16aa0b974", size = 11215882, upload-time = "2026-01-22T22:29:57.032Z" },
{ url = "https://files.pythonhosted.org/packages/2c/10/a31f86169ec91c0705e618443ee74ede0bdd94da0a57b28e72db68b2dbac/ruff-0.14.14-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:14649acb1cf7b5d2d283ebd2f58d56b75836ed8c6f329664fa91cdea19e76e66", size = 11180549, upload-time = "2026-01-22T22:30:27.175Z" },
{ url = "https://files.pythonhosted.org/packages/fd/1e/c723f20536b5163adf79bdd10c5f093414293cdf567eed9bdb7b83940f3f/ruff-0.14.14-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e8058d2145566510790eab4e2fad186002e288dec5e0d343a92fe7b0bc1b3e13", size = 10543416, upload-time = "2026-01-22T22:30:01.964Z" },
{ url = "https://files.pythonhosted.org/packages/3e/34/8a84cea7e42c2d94ba5bde1d7a4fae164d6318f13f933d92da6d7c2041ff/ruff-0.14.14-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:e651e977a79e4c758eb807f0481d673a67ffe53cfa92209781dfa3a996cf8412", size = 10285491, upload-time = "2026-01-22T22:30:29.51Z" },
{ url = "https://files.pythonhosted.org/packages/55/ef/b7c5ea0be82518906c978e365e56a77f8de7678c8bb6651ccfbdc178c29f/ruff-0.14.14-py3-none-musllinux_1_2_i686.whl", hash = "sha256:cc8b22da8d9d6fdd844a68ae937e2a0adf9b16514e9a97cc60355e2d4b219fc3", size = 10733525, upload-time = "2026-01-22T22:30:06.499Z" },
{ url = "https://files.pythonhosted.org/packages/6a/5b/aaf1dfbcc53a2811f6cc0a1759de24e4b03e02ba8762daabd9b6bd8c59e3/ruff-0.14.14-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:16bc890fb4cc9781bb05beb5ab4cd51be9e7cb376bf1dd3580512b24eb3fda2b", size = 11315626, upload-time = "2026-01-22T22:30:36.848Z" },
{ url = "https://files.pythonhosted.org/packages/2c/aa/9f89c719c467dfaf8ad799b9bae0df494513fb21d31a6059cb5870e57e74/ruff-0.14.14-py3-none-win32.whl", hash = "sha256:b530c191970b143375b6a68e6f743800b2b786bbcf03a7965b06c4bf04568167", size = 10502442, upload-time = "2026-01-22T22:30:38.93Z" },
{ url = "https://files.pythonhosted.org/packages/87/44/90fa543014c45560cae1fffc63ea059fb3575ee6e1cb654562197e5d16fb/ruff-0.14.14-py3-none-win_amd64.whl", hash = "sha256:3dde1435e6b6fe5b66506c1dff67a421d0b7f6488d466f651c07f4cab3bf20fd", size = 11630486, upload-time = "2026-01-22T22:30:10.852Z" },
{ url = "https://files.pythonhosted.org/packages/9e/6a/40fee331a52339926a92e17ae748827270b288a35ef4a15c9c8f2ec54715/ruff-0.14.14-py3-none-win_arm64.whl", hash = "sha256:56e6981a98b13a32236a72a8da421d7839221fa308b223b9283312312e5ac76c", size = 10920448, upload-time = "2026-01-22T22:30:15.417Z" },
{ url = "https://files.pythonhosted.org/packages/23/bf/e6e4324238c17f9d9120a9d60aa99a7daaa21204c07fcd84e2ef03bb5fd1/ruff-0.15.1-py3-none-linux_armv6l.whl", hash = "sha256:b101ed7cf4615bda6ffe65bdb59f964e9f4a0d3f85cbf0e54f0ab76d7b90228a", size = 10367819, upload-time = "2026-02-12T23:09:03.598Z" },
{ url = "https://files.pythonhosted.org/packages/b3/ea/c8f89d32e7912269d38c58f3649e453ac32c528f93bb7f4219258be2e7ed/ruff-0.15.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:939c995e9277e63ea632cc8d3fae17aa758526f49a9a850d2e7e758bfef46602", size = 10798618, upload-time = "2026-02-12T23:09:22.928Z" },
{ url = "https://files.pythonhosted.org/packages/5e/0f/1d0d88bc862624247d82c20c10d4c0f6bb2f346559d8af281674cf327f15/ruff-0.15.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1d83466455fdefe60b8d9c8df81d3c1bbb2115cede53549d3b522ce2bc703899", size = 10148518, upload-time = "2026-02-12T23:08:58.339Z" },
{ url = "https://files.pythonhosted.org/packages/f5/c8/291c49cefaa4a9248e986256df2ade7add79388fe179e0691be06fae6f37/ruff-0.15.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9457e3c3291024866222b96108ab2d8265b477e5b1534c7ddb1810904858d16", size = 10518811, upload-time = "2026-02-12T23:09:31.865Z" },
{ url = "https://files.pythonhosted.org/packages/c3/1a/f5707440e5ae43ffa5365cac8bbb91e9665f4a883f560893829cf16a606b/ruff-0.15.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:92c92b003e9d4f7fbd33b1867bb15a1b785b1735069108dfc23821ba045b29bc", size = 10196169, upload-time = "2026-02-12T23:09:17.306Z" },
{ url = "https://files.pythonhosted.org/packages/2a/ff/26ddc8c4da04c8fd3ee65a89c9fb99eaa5c30394269d424461467be2271f/ruff-0.15.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fe5c41ab43e3a06778844c586251eb5a510f67125427625f9eb2b9526535779", size = 10990491, upload-time = "2026-02-12T23:09:25.503Z" },
{ url = "https://files.pythonhosted.org/packages/fc/00/50920cb385b89413f7cdb4bb9bc8fc59c1b0f30028d8bccc294189a54955/ruff-0.15.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66a6dd6df4d80dc382c6484f8ce1bcceb55c32e9f27a8b94c32f6c7331bf14fb", size = 11843280, upload-time = "2026-02-12T23:09:19.88Z" },
{ url = "https://files.pythonhosted.org/packages/5d/6d/2f5cad8380caf5632a15460c323ae326f1e1a2b5b90a6ee7519017a017ca/ruff-0.15.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6a4a42cbb8af0bda9bcd7606b064d7c0bc311a88d141d02f78920be6acb5aa83", size = 11274336, upload-time = "2026-02-12T23:09:14.907Z" },
{ url = "https://files.pythonhosted.org/packages/a3/1d/5f56cae1d6c40b8a318513599b35ea4b075d7dc1cd1d04449578c29d1d75/ruff-0.15.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ab064052c31dddada35079901592dfba2e05f5b1e43af3954aafcbc1096a5b2", size = 11137288, upload-time = "2026-02-12T23:09:07.475Z" },
{ url = "https://files.pythonhosted.org/packages/cd/20/6f8d7d8f768c93b0382b33b9306b3b999918816da46537d5a61635514635/ruff-0.15.1-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:5631c940fe9fe91f817a4c2ea4e81f47bee3ca4aa646134a24374f3c19ad9454", size = 11070681, upload-time = "2026-02-12T23:08:55.43Z" },
{ url = "https://files.pythonhosted.org/packages/9a/67/d640ac76069f64cdea59dba02af2e00b1fa30e2103c7f8d049c0cff4cafd/ruff-0.15.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:68138a4ba184b4691ccdc39f7795c66b3c68160c586519e7e8444cf5a53e1b4c", size = 10486401, upload-time = "2026-02-12T23:09:27.927Z" },
{ url = "https://files.pythonhosted.org/packages/65/3d/e1429f64a3ff89297497916b88c32a5cc88eeca7e9c787072d0e7f1d3e1e/ruff-0.15.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:518f9af03bfc33c03bdb4cb63fabc935341bb7f54af500f92ac309ecfbba6330", size = 10197452, upload-time = "2026-02-12T23:09:12.147Z" },
{ url = "https://files.pythonhosted.org/packages/78/83/e2c3bade17dad63bf1e1c2ffaf11490603b760be149e1419b07049b36ef2/ruff-0.15.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:da79f4d6a826caaea95de0237a67e33b81e6ec2e25fc7e1993a4015dffca7c61", size = 10693900, upload-time = "2026-02-12T23:09:34.418Z" },
{ url = "https://files.pythonhosted.org/packages/a1/27/fdc0e11a813e6338e0706e8b39bb7a1d61ea5b36873b351acee7e524a72a/ruff-0.15.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:3dd86dccb83cd7d4dcfac303ffc277e6048600dfc22e38158afa208e8bf94a1f", size = 11227302, upload-time = "2026-02-12T23:09:36.536Z" },
{ url = "https://files.pythonhosted.org/packages/f6/58/ac864a75067dcbd3b95be5ab4eb2b601d7fbc3d3d736a27e391a4f92a5c1/ruff-0.15.1-py3-none-win32.whl", hash = "sha256:660975d9cb49b5d5278b12b03bb9951d554543a90b74ed5d366b20e2c57c2098", size = 10462555, upload-time = "2026-02-12T23:09:29.899Z" },
{ url = "https://files.pythonhosted.org/packages/e0/5e/d4ccc8a27ecdb78116feac4935dfc39d1304536f4296168f91ed3ec00cd2/ruff-0.15.1-py3-none-win_amd64.whl", hash = "sha256:c820fef9dd5d4172a6570e5721704a96c6679b80cf7be41659ed439653f62336", size = 11599956, upload-time = "2026-02-12T23:09:01.157Z" },
{ url = "https://files.pythonhosted.org/packages/2a/07/5bda6a85b220c64c65686bc85bd0bbb23b29c62b3a9f9433fa55f17cda93/ruff-0.15.1-py3-none-win_arm64.whl", hash = "sha256:5ff7d5f0f88567850f45081fac8f4ec212be8d0b963e385c3f7d0d2eb4899416", size = 10874604, upload-time = "2026-02-12T23:09:05.515Z" },
]
[[package]]
+1 -1
View File
@@ -25,7 +25,7 @@ class AsyncQueue(asyncio.Queue):
self._getters.append(getter)
try:
await getter
except:
except BaseException:
getter.cancel() # Just in case getter is not done yet.
try:
# Clean self._getters from canceled getters.
+24 -24
View File
@@ -1,6 +1,7 @@
from __future__ import annotations
from collections.abc import AsyncIterator, Callable, Iterator, Sequence
from dataclasses import fields, is_dataclass
from typing import (
Any,
TypeVar,
@@ -11,6 +12,7 @@ from uuid import UUID, uuid4
from langchain_core.callbacks import BaseCallbackHandler
from langchain_core.messages import BaseMessage
from langchain_core.outputs import ChatGeneration, ChatGenerationChunk, LLMResult
from pydantic import BaseModel
from langgraph._internal._constants import NS_SEP
from langgraph.constants import TAG_HIDDEN, TAG_NOSTREAM
@@ -26,6 +28,17 @@ T = TypeVar("T")
Meta = tuple[tuple[str, ...], dict[str, Any]]
def _state_values(obj: Any) -> Sequence[Any]:
"""Extract top-level field values from a state object (dict, BaseModel, or dataclass)."""
if isinstance(obj, dict):
return list(obj.values())
elif isinstance(obj, BaseModel):
return [getattr(obj, k) for k in type(obj).model_fields]
elif is_dataclass(obj) and not isinstance(obj, type):
return [getattr(obj, f.name) for f in fields(obj)]
return ()
class StreamMessagesHandler(BaseCallbackHandler, _StreamingCallbackHandler):
"""A callback handler that implements stream_mode=messages.
@@ -90,26 +103,14 @@ class StreamMessagesHandler(BaseCallbackHandler, _StreamingCallbackHandler):
for value in response:
if isinstance(value, BaseMessage):
self._emit(meta, value, dedupe=True)
elif isinstance(response, dict):
for value in response.values():
else:
for value in _state_values(response):
if isinstance(value, BaseMessage):
self._emit(meta, value, dedupe=True)
elif isinstance(value, Sequence):
for item in value:
if isinstance(item, BaseMessage):
self._emit(meta, item, dedupe=True)
elif hasattr(response, "__dir__") and callable(response.__dir__):
for key in dir(response):
try:
value = getattr(response, key)
if isinstance(value, BaseMessage):
self._emit(meta, value, dedupe=True)
elif isinstance(value, Sequence):
for item in value:
if isinstance(item, BaseMessage):
self._emit(meta, item, dedupe=True)
except AttributeError:
pass
def tap_output_aiter(
self, run_id: UUID, output: AsyncIterator[T]
@@ -203,16 +204,15 @@ class StreamMessagesHandler(BaseCallbackHandler, _StreamingCallbackHandler):
if not self.subgraphs and len(ns) > 0:
return
self.metadata[run_id] = (ns, metadata)
if isinstance(inputs, dict):
for key, value in inputs.items():
if isinstance(value, BaseMessage):
if value.id is not None:
self.seen.add(value.id)
elif isinstance(value, Sequence) and not isinstance(value, str):
for item in value:
if isinstance(item, BaseMessage):
if item.id is not None:
self.seen.add(item.id)
for value in _state_values(inputs):
if isinstance(value, BaseMessage):
if value.id is not None:
self.seen.add(value.id)
elif isinstance(value, Sequence) and not isinstance(value, str):
for item in value:
if isinstance(item, BaseMessage):
if item.id is not None:
self.seen.add(item.id)
def on_chain_end(
self,
+2 -3
View File
@@ -565,7 +565,7 @@ def _call(
if fut := next(
(
f
for f, t in futures().items() # type: ignore[union-attr]
for f, t in list(futures().items()) # type: ignore[union-attr]
if t is not None and t == next_task.id
),
None,
@@ -708,7 +708,7 @@ async def _acall_impl(
if fut := next(
(
f
for f, t in futures().items() # type: ignore[union-attr]
for f, t in list(futures().items()) # type: ignore[union-attr]
if t is not None and t == next_task.id
),
None,
@@ -728,7 +728,6 @@ async def _acall_impl(
)
else:
fut.set_result(None)
futures()[fut] = next_task # type: ignore[index]
else:
# schedule the next task
fut = cast(
+3 -3
View File
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project]
name = "langgraph"
version = "1.0.7"
version = "1.0.9"
description = "Building stateful, multi-actor applications with LLMs"
authors = []
requires-python = ">=3.10"
@@ -27,7 +27,7 @@ dependencies = [
"langchain-core>=0.1",
"langgraph-checkpoint>=2.1.0,<5.0.0",
"langgraph-sdk>=0.3.0,<0.4.0",
"langgraph-prebuilt>=1.0.7,<1.1.0",
"langgraph-prebuilt>=1.0.8,<1.1.0",
"xxhash>=3.5.0",
"pydantic>=2.7.4",
]
@@ -60,7 +60,7 @@ test = [
"langgraph-checkpoint-postgres",
"langgraph-sdk",
"psycopg[binary]",
"uvloop==0.21.0beta1",
"uvloop==0.22.1",
"pyperf",
"py-spy",
"pycryptodome",
File diff suppressed because one or more lines are too long
+377 -10
View File
@@ -16,7 +16,7 @@ from typing import Annotated, Any, Literal, get_type_hints
import pytest
from langchain_core.language_models import GenericFakeChatModel
from langchain_core.messages import AnyMessage
from langchain_core.messages import AIMessage, AnyMessage, HumanMessage
from langchain_core.runnables import (
RunnableConfig,
RunnableLambda,
@@ -1264,18 +1264,20 @@ def test_imp_task(
}
thread1 = {"configurable": {"thread_id": "1"}}
assert [*graph.stream([0, 1], thread1, durability=durability)] == [
result = [*graph.stream([0, 1], thread1, durability=durability)]
# mapper tasks run concurrently so output order is non-deterministic
assert sorted(result[:-1], key=lambda d: str(d)) == [
{"mapper": "00"},
{"mapper": "11"},
{
"__interrupt__": (
Interrupt(
value="question",
id=AnyStr(),
),
)
},
]
assert result[-1] == {
"__interrupt__": (
Interrupt(
value="question",
id=AnyStr(),
),
)
}
assert mapper_calls == 2
assert graph.invoke(Command(resume="answer"), thread1, durability=durability) == [
@@ -5798,6 +5800,284 @@ def test_multiple_interrupts_functional_cache(
assert counter == 6
def test_task_before_interrupt_resume(
sync_checkpointer: BaseCheckpointSaver,
) -> None:
"""Test that Command(resume=value) works correctly when a @task runs
before interrupt-producing tasks in an @entrypoint.
The @task wrapper on both setup and ask is essential to reproduce the bug:
- @task on setup triggers a mid-step put_writes (creating a new pending_writes list)
- @task on ask means interrupt() runs in a child scratchpad that must
delegate to the parent for null resume consumption tracking
"""
@entrypoint(checkpointer=sync_checkpointer)
def workflow(number_of_topics: int) -> dict:
@task
def setup() -> int:
return number_of_topics
@task
def ask(question: str) -> str:
return interrupt(question)
n = setup().result()
answers = []
for i in range(n):
q = f"Whats the answer for topic {i + 1}?"
answers.append(ask(q).result())
return {"answers": answers}
config = {"configurable": {"thread_id": "1"}}
# First invocation - should get first interrupt
result = workflow.invoke(2, config=config)
assert "__interrupt__" in result
assert len(result["__interrupt__"]) == 1
assert result["__interrupt__"][0].value == "Whats the answer for topic 1?"
# Resume with answer for topic 1 - should get second interrupt
result = workflow.invoke(Command(resume="answer1"), config=config)
assert "__interrupt__" in result, f"Expected interrupt for topic 2, got: {result}"
assert len(result["__interrupt__"]) == 1
assert result["__interrupt__"][0].value == "Whats the answer for topic 2?"
# Resume with answer for topic 2 - should get final result
result = workflow.invoke(Command(resume="answer2"), config=config)
assert result == {"answers": ["answer1", "answer2"]}
def test_multiple_tasks_before_interrupt_resume(
sync_checkpointer: BaseCheckpointSaver,
) -> None:
"""Test that Command(resume=value) works correctly when multiple @tasks
run before an interrupt-producing task in an @entrypoint."""
@entrypoint(checkpointer=sync_checkpointer)
def workflow(inputs: dict) -> dict:
@task
def step_a(x: int) -> int:
return x + 1
@task
def step_b(x: int) -> int:
return x * 2
@task
def ask(question: str) -> str:
return interrupt(question)
a = step_a(inputs["x"]).result()
b = step_b(a).result()
answer = ask(f"Result so far is {b}. What next?").result()
return {"computed": b, "answer": answer}
config = {"configurable": {"thread_id": "1"}}
# First invocation - should get interrupt
result = workflow.invoke({"x": 5}, config=config)
assert "__interrupt__" in result
assert result["__interrupt__"][0].value == "Result so far is 12. What next?"
# Resume
result = workflow.invoke(Command(resume="continue"), config=config)
assert result == {"computed": 12, "answer": "continue"}
def test_no_redundant_put_writes_for_cached_task(
sync_checkpointer: BaseCheckpointSaver,
) -> None:
"""Cached @tasks on resume must not trigger redundant put_writes."""
from unittest.mock import patch
from langgraph.pregel._loop import PregelLoop
@task
def setup(x: int) -> int:
return x
@task
def ask(question: str) -> str:
return interrupt(question)
@entrypoint(checkpointer=sync_checkpointer)
def workflow(x: int) -> dict:
n = setup(x).result()
answer = ask(f"q{n}").result()
return {"answer": answer}
config = {"configurable": {"thread_id": "1"}}
result = workflow.invoke(1, config=config)
assert "__interrupt__" in result
put_writes_task_ids: list[str] = []
orig = PregelLoop.put_writes
def spy(self, task_id, writes):
put_writes_task_ids.append(task_id)
return orig(self, task_id, writes)
with patch.object(PregelLoop, "put_writes", spy):
result = workflow.invoke(Command(resume="ans"), config=config)
assert result == {"answer": "ans"}
# Count unique non-null task IDs that got put_writes.
# Should be exactly 2: the ask task and the entrypoint task.
# If 3, the cached setup task is being redundantly re-committed.
non_null = set(tid for tid in put_writes_task_ids if not tid.startswith("00000000"))
assert len(non_null) == 2, (
f"Expected 2 task IDs in put_writes (ask + entrypoint), got {len(non_null)}"
)
def test_node_before_interrupt_resume_graph_api(
sync_checkpointer: BaseCheckpointSaver,
) -> None:
"""Test that Command(resume=value) works correctly in a StateGraph when a
node runs before a node that calls interrupt(). This is the graph-API
analog of test_task_before_interrupt_resume (entrypoint API)."""
class State(TypedDict):
topics: list[str]
answers: Annotated[list[str], operator.add]
def setup(state: State) -> dict:
return {"topics": [f"topic {i + 1}" for i in range(len(state["topics"]))]}
def ask(state: State) -> dict:
answers = []
for topic in state["topics"]:
answer = interrupt(f"Whats the answer for {topic}?")
answers.append(answer)
return {"answers": answers}
graph = (
StateGraph(State)
.add_node("setup", setup)
.add_node("ask", ask)
.add_edge(START, "setup")
.add_edge("setup", "ask")
.add_edge("ask", END)
.compile(checkpointer=sync_checkpointer)
)
config = {"configurable": {"thread_id": "1"}}
# First invocation - setup runs, then ask interrupts on the first topic
result = graph.invoke({"topics": ["a", "b"], "answers": []}, config=config)
assert "__interrupt__" in result
assert len(result["__interrupt__"]) == 1
assert result["__interrupt__"][0].value == "Whats the answer for topic 1?"
# Resume with answer for topic 1 - should get second interrupt
result = graph.invoke(Command(resume="answer1"), config=config)
assert "__interrupt__" in result, f"Expected interrupt for topic 2, got: {result}"
assert len(result["__interrupt__"]) == 1
assert result["__interrupt__"][0].value == "Whats the answer for topic 2?"
# Resume with answer for topic 2 - should complete
result = graph.invoke(Command(resume="answer2"), config=config)
assert result == {
"topics": ["topic 1", "topic 2"],
"answers": ["answer1", "answer2"],
}
def test_multiple_nodes_before_interrupt_resume_graph_api(
sync_checkpointer: BaseCheckpointSaver,
) -> None:
"""Test that Command(resume=value) works correctly in a StateGraph when
multiple nodes run before a node that calls interrupt(). This is the
graph-API analog of test_multiple_tasks_before_interrupt_resume."""
class State(TypedDict):
value: int
answer: str
def step_a(state: State) -> dict:
return {"value": state["value"] + 1}
def step_b(state: State) -> dict:
return {"value": state["value"] * 2}
def ask(state: State) -> dict:
answer = interrupt(f"Result so far is {state['value']}. What next?")
return {"answer": answer}
graph = (
StateGraph(State)
.add_node("step_a", step_a)
.add_node("step_b", step_b)
.add_node("ask", ask)
.add_edge(START, "step_a")
.add_edge("step_a", "step_b")
.add_edge("step_b", "ask")
.add_edge("ask", END)
.compile(checkpointer=sync_checkpointer)
)
config = {"configurable": {"thread_id": "1"}}
# First invocation - step_a and step_b run, then ask interrupts
result = graph.invoke({"value": 5, "answer": ""}, config=config)
assert "__interrupt__" in result
assert result["__interrupt__"][0].value == "Result so far is 12. What next?"
# Resume - should complete
result = graph.invoke(Command(resume="continue"), config=config)
assert result == {"value": 12, "answer": "continue"}
def test_node_before_multiple_interrupt_cycles_graph_api(
sync_checkpointer: BaseCheckpointSaver,
) -> None:
"""Test that a node running before an interrupt node does not interfere
with multiple interrupt/resume cycles in a StateGraph."""
class State(TypedDict):
count: int
data: str
def prepare(state: State) -> dict:
return {"count": state["count"] + 10}
def multi_interrupt(state: State) -> dict:
first = interrupt("First question?")
second = interrupt("Second question?")
return {"data": f"{first},{second}"}
graph = (
StateGraph(State)
.add_node("prepare", prepare)
.add_node("multi_interrupt", multi_interrupt)
.add_edge(START, "prepare")
.add_edge("prepare", "multi_interrupt")
.add_edge("multi_interrupt", END)
.compile(checkpointer=sync_checkpointer)
)
config = {"configurable": {"thread_id": "1"}}
# First invocation - prepare runs, multi_interrupt hits first interrupt
result = graph.invoke({"count": 0, "data": ""}, config=config)
assert "__interrupt__" in result
assert result["__interrupt__"][0].value == "First question?"
# Resume first interrupt - hits second interrupt
result = graph.invoke(Command(resume="first_answer"), config=config)
assert "__interrupt__" in result
assert result["__interrupt__"][0].value == "Second question?"
# Resume second interrupt - completes
result = graph.invoke(Command(resume="second_answer"), config=config)
assert result == {"count": 10, "data": "first_answer,second_answer"}
def test_double_interrupt_subgraph(sync_checkpointer: BaseCheckpointSaver) -> None:
class AgentState(TypedDict):
input: str
@@ -6978,6 +7258,93 @@ def test_stream_messages_dedupe_state(sync_checkpointer: BaseCheckpointSaver) ->
assert chunks[0][1]["langgraph_node"] == "call_model"
def test_stream_messages_dedupe_pydantic_subgraph_interrupt(
sync_checkpointer: BaseCheckpointSaver,
) -> None:
"""Pydantic BaseModel state should not cause duplicate messages when
streaming from subgraphs that use interrupts. Regression test for a bug
where ``on_chain_start`` only populated the ``seen`` set for dict inputs,
skipping Pydantic model inputs entirely."""
class PydanticState(BaseModel):
messages: Annotated[list[AnyMessage], add_messages] = Field(
default_factory=list
)
def subgraph_proposal(state) -> Command[Literal["subgraph_approval"]]:
return Command(
goto="subgraph_approval",
update={"messages": [AIMessage(content="Proposal", id="proposal_msg")]},
)
def subgraph_approval(state) -> Command[Literal["__end__"]]:
resume_value = interrupt({"message": "Waiting for approval"})
user_msg = resume_value.get("user_message", "")
msgs = [HumanMessage(content=user_msg)] if user_msg else []
return Command(goto="__end__", update={"messages": msgs})
subgraph = (
StateGraph(PydanticState)
.add_node("proposal", subgraph_proposal)
.add_node("subgraph_approval", subgraph_approval)
.add_edge(START, "proposal")
.compile(checkpointer=sync_checkpointer)
)
def finalize(state) -> Command[Literal["__end__"]]:
return Command(
goto="__end__",
update={"messages": [AIMessage(content="Finalized", id="finalize_msg")]},
)
graph = (
StateGraph(PydanticState)
.add_node("subgraph", subgraph)
.add_node("finalize", finalize)
.add_edge(START, "subgraph")
.add_edge("subgraph", "finalize")
.compile(checkpointer=sync_checkpointer)
)
thread1 = {"configurable": {"thread_id": "1"}}
# First stream: should hit interrupt after proposal
chunks_req0 = [
(ns, chunk)
for ns, chunk in graph.stream(
{"messages": [HumanMessage(content="Create a proposal")]},
thread1,
stream_mode="messages",
subgraphs=True,
)
]
msg_ids_req0 = {chunk[0].id for _, chunk in chunks_req0}
assert "proposal_msg" in msg_ids_req0
# Verify interrupted
state = graph.get_state(thread1)
assert state.next
# Second stream: resume — should NOT duplicate messages from first stream
chunks_req1 = [
(ns, chunk)
for ns, chunk in graph.stream(
Command(resume={"user_message": "Yes"}),
thread1,
stream_mode="messages",
subgraphs=True,
)
]
msg_ids_req1 = {chunk[0].id for _, chunk in chunks_req1}
assert "finalize_msg" in msg_ids_req1
# The key assertion: no message IDs from request 0 should appear in request 1
duplicates = msg_ids_req0 & msg_ids_req1
assert not duplicates, f"Duplicate message IDs across requests: {duplicates}"
def test_interrupt_subgraph_reenter_checkpointer_true(
sync_checkpointer: BaseCheckpointSaver,
) -> None:
+295 -9
View File
@@ -2262,18 +2262,20 @@ async def test_imp_task(
tracer = FakeTracer()
thread1 = {"configurable": {"thread_id": "1"}, "callbacks": [tracer]}
assert [c async for c in graph.astream([0, 1], thread1, durability=durability)] == [
result = [c async for c in graph.astream([0, 1], thread1, durability=durability)]
# mapper tasks run concurrently so output order is non-deterministic
assert sorted(result[:-1], key=lambda d: str(d)) == [
{"mapper": "00"},
{"mapper": "11"},
{
"__interrupt__": (
Interrupt(
value="question",
id=AnyStr(),
),
)
},
]
assert result[-1] == {
"__interrupt__": (
Interrupt(
value="question",
id=AnyStr(),
),
)
}
assert mapper_calls == 2
assert len(tracer.runs) == 1
assert len(tracer.runs[0].child_runs) == 1
@@ -7918,6 +7920,290 @@ async def test_interrupts_in_tasks_surfaced_once(
assert result[1] == "Added Will!"
@NEEDS_CONTEXTVARS
async def test_task_before_interrupt_resume(
async_checkpointer: BaseCheckpointSaver,
) -> None:
"""Test that Command(resume=value) works correctly when a @task runs
before interrupt-producing tasks in an @entrypoint.
The @task wrapper on both setup and ask is essential to reproduce the bug:
- @task on setup triggers a mid-step put_writes (creating a new pending_writes list)
- @task on ask means interrupt() runs in a child scratchpad that must
delegate to the parent for null resume consumption tracking
"""
@entrypoint(checkpointer=async_checkpointer)
async def workflow(number_of_topics: int) -> dict:
@task
async def setup() -> int:
return number_of_topics
@task
async def ask(question: str) -> str:
return interrupt(question)
n = await setup()
answers = []
for i in range(n):
q = f"Whats the answer for topic {i + 1}?"
answers.append(await ask(q))
return {"answers": answers}
config = {"configurable": {"thread_id": "1"}}
# First invocation - should get first interrupt
result = await workflow.ainvoke(2, config=config)
assert "__interrupt__" in result
assert len(result["__interrupt__"]) == 1
assert result["__interrupt__"][0].value == "Whats the answer for topic 1?"
# Resume with answer for topic 1 - should get second interrupt
result = await workflow.ainvoke(Command(resume="answer1"), config=config)
assert "__interrupt__" in result, f"Expected interrupt for topic 2, got: {result}"
assert len(result["__interrupt__"]) == 1
assert result["__interrupt__"][0].value == "Whats the answer for topic 2?"
# Resume with answer for topic 2 - should get final result
result = await workflow.ainvoke(Command(resume="answer2"), config=config)
assert result == {"answers": ["answer1", "answer2"]}
@NEEDS_CONTEXTVARS
async def test_multiple_tasks_before_interrupt_resume(
async_checkpointer: BaseCheckpointSaver,
) -> None:
"""Test that Command(resume=value) works correctly when multiple @tasks
run before an interrupt-producing task in an @entrypoint."""
@entrypoint(checkpointer=async_checkpointer)
async def workflow(inputs: dict) -> dict:
@task
async def step_a(x: int) -> int:
return x + 1
@task
async def step_b(x: int) -> int:
return x * 2
@task
async def ask(question: str) -> str:
return interrupt(question)
a = await step_a(inputs["x"])
b = await step_b(a)
answer = await ask(f"Result so far is {b}. What next?")
return {"computed": b, "answer": answer}
config = {"configurable": {"thread_id": "1"}}
# First invocation - should get interrupt
result = await workflow.ainvoke({"x": 5}, config=config)
assert "__interrupt__" in result
assert result["__interrupt__"][0].value == "Result so far is 12. What next?"
# Resume
result = await workflow.ainvoke(Command(resume="continue"), config=config)
assert result == {"computed": 12, "answer": "continue"}
@NEEDS_CONTEXTVARS
async def test_no_redundant_put_writes_for_cached_task(
async_checkpointer: BaseCheckpointSaver,
) -> None:
"""Cached @tasks on resume must not trigger redundant put_writes."""
from unittest.mock import patch
from langgraph.pregel._loop import PregelLoop
@task
async def setup(x: int) -> int:
return x
@task
async def ask(question: str) -> str:
return interrupt(question)
@entrypoint(checkpointer=async_checkpointer)
async def workflow(x: int) -> dict:
n = await setup(x)
answer = await ask(f"q{n}")
return {"answer": answer}
config = {"configurable": {"thread_id": "1"}}
result = await workflow.ainvoke(1, config=config)
assert "__interrupt__" in result
put_writes_task_ids: list[str] = []
orig = PregelLoop.put_writes
def spy(self, task_id, writes):
put_writes_task_ids.append(task_id)
return orig(self, task_id, writes)
with patch.object(PregelLoop, "put_writes", spy):
result = await workflow.ainvoke(Command(resume="ans"), config=config)
assert result == {"answer": "ans"}
# Count unique non-null task IDs that got put_writes.
# Should be exactly 2: the ask task and the entrypoint task.
# If 3, the cached setup task is being redundantly re-committed.
non_null = set(tid for tid in put_writes_task_ids if not tid.startswith("00000000"))
assert len(non_null) == 2, (
f"Expected 2 task IDs in put_writes (ask + entrypoint), got {len(non_null)}"
)
@NEEDS_CONTEXTVARS
async def test_node_before_interrupt_resume_graph_api(
async_checkpointer: BaseCheckpointSaver,
) -> None:
"""Test that Command(resume=value) works correctly in a StateGraph when a
node runs before a node that calls interrupt(). This is the graph-API
analog of test_task_before_interrupt_resume (entrypoint API)."""
class State(TypedDict):
topics: list[str]
answers: Annotated[list[str], operator.add]
def setup(state: State) -> dict:
return {"topics": [f"topic {i + 1}" for i in range(len(state["topics"]))]}
def ask(state: State) -> dict:
answers = []
for topic in state["topics"]:
answer = interrupt(f"Whats the answer for {topic}?")
answers.append(answer)
return {"answers": answers}
graph = (
StateGraph(State)
.add_node("setup", setup)
.add_node("ask", ask)
.add_edge(START, "setup")
.add_edge("setup", "ask")
.add_edge("ask", END)
.compile(checkpointer=async_checkpointer)
)
config = {"configurable": {"thread_id": "1"}}
# First invocation - setup runs, then ask interrupts on the first topic
result = await graph.ainvoke({"topics": ["a", "b"], "answers": []}, config=config)
assert "__interrupt__" in result
assert len(result["__interrupt__"]) == 1
assert result["__interrupt__"][0].value == "Whats the answer for topic 1?"
# Resume with answer for topic 1 - should get second interrupt
result = await graph.ainvoke(Command(resume="answer1"), config=config)
assert "__interrupt__" in result, f"Expected interrupt for topic 2, got: {result}"
assert len(result["__interrupt__"]) == 1
assert result["__interrupt__"][0].value == "Whats the answer for topic 2?"
# Resume with answer for topic 2 - should complete
result = await graph.ainvoke(Command(resume="answer2"), config=config)
assert result == {
"topics": ["topic 1", "topic 2"],
"answers": ["answer1", "answer2"],
}
@NEEDS_CONTEXTVARS
async def test_multiple_nodes_before_interrupt_resume_graph_api(
async_checkpointer: BaseCheckpointSaver,
) -> None:
"""Test that Command(resume=value) works correctly in a StateGraph when
multiple nodes run before a node that calls interrupt(). This is the
graph-API analog of test_multiple_tasks_before_interrupt_resume."""
class State(TypedDict):
value: int
answer: str
def step_a(state: State) -> dict:
return {"value": state["value"] + 1}
def step_b(state: State) -> dict:
return {"value": state["value"] * 2}
def ask(state: State) -> dict:
answer = interrupt(f"Result so far is {state['value']}. What next?")
return {"answer": answer}
graph = (
StateGraph(State)
.add_node("step_a", step_a)
.add_node("step_b", step_b)
.add_node("ask", ask)
.add_edge(START, "step_a")
.add_edge("step_a", "step_b")
.add_edge("step_b", "ask")
.add_edge("ask", END)
.compile(checkpointer=async_checkpointer)
)
config = {"configurable": {"thread_id": "1"}}
# First invocation - step_a and step_b run, then ask interrupts
result = await graph.ainvoke({"value": 5, "answer": ""}, config=config)
assert "__interrupt__" in result
assert result["__interrupt__"][0].value == "Result so far is 12. What next?"
# Resume - should complete
result = await graph.ainvoke(Command(resume="continue"), config=config)
assert result == {"value": 12, "answer": "continue"}
@NEEDS_CONTEXTVARS
async def test_node_before_multiple_interrupt_cycles_graph_api(
async_checkpointer: BaseCheckpointSaver,
) -> None:
"""Test that a node running before an interrupt node does not interfere
with multiple interrupt/resume cycles in a StateGraph."""
class State(TypedDict):
count: int
data: str
def prepare(state: State) -> dict:
return {"count": state["count"] + 10}
def multi_interrupt(state: State) -> dict:
first = interrupt("First question?")
second = interrupt("Second question?")
return {"data": f"{first},{second}"}
graph = (
StateGraph(State)
.add_node("prepare", prepare)
.add_node("multi_interrupt", multi_interrupt)
.add_edge(START, "prepare")
.add_edge("prepare", "multi_interrupt")
.add_edge("multi_interrupt", END)
.compile(checkpointer=async_checkpointer)
)
config = {"configurable": {"thread_id": "1"}}
# First invocation - prepare runs, multi_interrupt hits first interrupt
result = await graph.ainvoke({"count": 0, "data": ""}, config=config)
assert "__interrupt__" in result
assert result["__interrupt__"][0].value == "First question?"
# Resume first interrupt - hits second interrupt
result = await graph.ainvoke(Command(resume="first_answer"), config=config)
assert "__interrupt__" in result
assert result["__interrupt__"][0].value == "Second question?"
# Resume second interrupt - completes
result = await graph.ainvoke(Command(resume="second_answer"), config=config)
assert result == {"count": 10, "data": "first_answer,second_answer"}
async def test_pregel_loop_refcount():
gc.collect()
try:
+144 -137
View File
@@ -524,66 +524,61 @@ toml = [
[[package]]
name = "cryptography"
version = "46.0.3"
version = "46.0.5"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "cffi", marker = "python_full_version >= '3.11' and python_full_version < '3.14' and platform_python_implementation != 'PyPy'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/9f/33/c00162f49c0e2fe8064a62cb92b93e50c74a72bc370ab92f86112b33ff62/cryptography-46.0.3.tar.gz", hash = "sha256:a8b17438104fed022ce745b362294d9ce35b4c2e45c1d958ad4a4b019285f4a1", size = 749258, upload-time = "2025-10-15T23:18:31.74Z" }
sdist = { url = "https://files.pythonhosted.org/packages/60/04/ee2a9e8542e4fa2773b81771ff8349ff19cdd56b7258a0cc442639052edb/cryptography-46.0.5.tar.gz", hash = "sha256:abace499247268e3757271b2f1e244b36b06f8515cf27c4d49468fc9eb16e93d", size = 750064, upload-time = "2026-02-10T19:18:38.255Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/1d/42/9c391dd801d6cf0d561b5890549d4b27bafcc53b39c31a817e69d87c625b/cryptography-46.0.3-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:109d4ddfadf17e8e7779c39f9b18111a09efb969a301a31e987416a0191ed93a", size = 7225004, upload-time = "2025-10-15T23:16:52.239Z" },
{ url = "https://files.pythonhosted.org/packages/1c/67/38769ca6b65f07461eb200e85fc1639b438bdc667be02cf7f2cd6a64601c/cryptography-46.0.3-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:09859af8466b69bc3c27bdf4f5d84a665e0f7ab5088412e9e2ec49758eca5cbc", size = 4296667, upload-time = "2025-10-15T23:16:54.369Z" },
{ url = "https://files.pythonhosted.org/packages/5c/49/498c86566a1d80e978b42f0d702795f69887005548c041636df6ae1ca64c/cryptography-46.0.3-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:01ca9ff2885f3acc98c29f1860552e37f6d7c7d013d7334ff2a9de43a449315d", size = 4450807, upload-time = "2025-10-15T23:16:56.414Z" },
{ url = "https://files.pythonhosted.org/packages/4b/0a/863a3604112174c8624a2ac3c038662d9e59970c7f926acdcfaed8d61142/cryptography-46.0.3-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:6eae65d4c3d33da080cff9c4ab1f711b15c1d9760809dad6ea763f3812d254cb", size = 4299615, upload-time = "2025-10-15T23:16:58.442Z" },
{ url = "https://files.pythonhosted.org/packages/64/02/b73a533f6b64a69f3cd3872acb6ebc12aef924d8d103133bb3ea750dc703/cryptography-46.0.3-cp311-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5bf0ed4490068a2e72ac03d786693adeb909981cc596425d09032d372bcc849", size = 4016800, upload-time = "2025-10-15T23:17:00.378Z" },
{ url = "https://files.pythonhosted.org/packages/25/d5/16e41afbfa450cde85a3b7ec599bebefaef16b5c6ba4ec49a3532336ed72/cryptography-46.0.3-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:5ecfccd2329e37e9b7112a888e76d9feca2347f12f37918facbb893d7bb88ee8", size = 4984707, upload-time = "2025-10-15T23:17:01.98Z" },
{ url = "https://files.pythonhosted.org/packages/c9/56/e7e69b427c3878352c2fb9b450bd0e19ed552753491d39d7d0a2f5226d41/cryptography-46.0.3-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:a2c0cd47381a3229c403062f764160d57d4d175e022c1df84e168c6251a22eec", size = 4482541, upload-time = "2025-10-15T23:17:04.078Z" },
{ url = "https://files.pythonhosted.org/packages/78/f6/50736d40d97e8483172f1bb6e698895b92a223dba513b0ca6f06b2365339/cryptography-46.0.3-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:549e234ff32571b1f4076ac269fcce7a808d3bf98b76c8dd560e42dbc66d7d91", size = 4299464, upload-time = "2025-10-15T23:17:05.483Z" },
{ url = "https://files.pythonhosted.org/packages/00/de/d8e26b1a855f19d9994a19c702fa2e93b0456beccbcfe437eda00e0701f2/cryptography-46.0.3-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:c0a7bb1a68a5d3471880e264621346c48665b3bf1c3759d682fc0864c540bd9e", size = 4950838, upload-time = "2025-10-15T23:17:07.425Z" },
{ url = "https://files.pythonhosted.org/packages/8f/29/798fc4ec461a1c9e9f735f2fc58741b0daae30688f41b2497dcbc9ed1355/cryptography-46.0.3-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:10b01676fc208c3e6feeb25a8b83d81767e8059e1fe86e1dc62d10a3018fa926", size = 4481596, upload-time = "2025-10-15T23:17:09.343Z" },
{ url = "https://files.pythonhosted.org/packages/15/8d/03cd48b20a573adfff7652b76271078e3045b9f49387920e7f1f631d125e/cryptography-46.0.3-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:0abf1ffd6e57c67e92af68330d05760b7b7efb243aab8377e583284dbab72c71", size = 4426782, upload-time = "2025-10-15T23:17:11.22Z" },
{ url = "https://files.pythonhosted.org/packages/fa/b1/ebacbfe53317d55cf33165bda24c86523497a6881f339f9aae5c2e13e57b/cryptography-46.0.3-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a04bee9ab6a4da801eb9b51f1b708a1b5b5c9eb48c03f74198464c66f0d344ac", size = 4698381, upload-time = "2025-10-15T23:17:12.829Z" },
{ url = "https://files.pythonhosted.org/packages/96/92/8a6a9525893325fc057a01f654d7efc2c64b9de90413adcf605a85744ff4/cryptography-46.0.3-cp311-abi3-win32.whl", hash = "sha256:f260d0d41e9b4da1ed1e0f1ce571f97fe370b152ab18778e9e8f67d6af432018", size = 3055988, upload-time = "2025-10-15T23:17:14.65Z" },
{ url = "https://files.pythonhosted.org/packages/7e/bf/80fbf45253ea585a1e492a6a17efcb93467701fa79e71550a430c5e60df0/cryptography-46.0.3-cp311-abi3-win_amd64.whl", hash = "sha256:a9a3008438615669153eb86b26b61e09993921ebdd75385ddd748702c5adfddb", size = 3514451, upload-time = "2025-10-15T23:17:16.142Z" },
{ url = "https://files.pythonhosted.org/packages/2e/af/9b302da4c87b0beb9db4e756386a7c6c5b8003cd0e742277888d352ae91d/cryptography-46.0.3-cp311-abi3-win_arm64.whl", hash = "sha256:5d7f93296ee28f68447397bf5198428c9aeeab45705a55d53a6343455dcb2c3c", size = 2928007, upload-time = "2025-10-15T23:17:18.04Z" },
{ url = "https://files.pythonhosted.org/packages/f5/e2/a510aa736755bffa9d2f75029c229111a1d02f8ecd5de03078f4c18d91a3/cryptography-46.0.3-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:00a5e7e87938e5ff9ff5447ab086a5706a957137e6e433841e9d24f38a065217", size = 7158012, upload-time = "2025-10-15T23:17:19.982Z" },
{ url = "https://files.pythonhosted.org/packages/73/dc/9aa866fbdbb95b02e7f9d086f1fccfeebf8953509b87e3f28fff927ff8a0/cryptography-46.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c8daeb2d2174beb4575b77482320303f3d39b8e81153da4f0fb08eb5fe86a6c5", size = 4288728, upload-time = "2025-10-15T23:17:21.527Z" },
{ url = "https://files.pythonhosted.org/packages/c5/fd/bc1daf8230eaa075184cbbf5f8cd00ba9db4fd32d63fb83da4671b72ed8a/cryptography-46.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:39b6755623145ad5eff1dab323f4eae2a32a77a7abef2c5089a04a3d04366715", size = 4435078, upload-time = "2025-10-15T23:17:23.042Z" },
{ url = "https://files.pythonhosted.org/packages/82/98/d3bd5407ce4c60017f8ff9e63ffee4200ab3e23fe05b765cab805a7db008/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:db391fa7c66df6762ee3f00c95a89e6d428f4d60e7abc8328f4fe155b5ac6e54", size = 4293460, upload-time = "2025-10-15T23:17:24.885Z" },
{ url = "https://files.pythonhosted.org/packages/26/e9/e23e7900983c2b8af7a08098db406cf989d7f09caea7897e347598d4cd5b/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:78a97cf6a8839a48c49271cdcbd5cf37ca2c1d6b7fdd86cc864f302b5e9bf459", size = 3995237, upload-time = "2025-10-15T23:17:26.449Z" },
{ url = "https://files.pythonhosted.org/packages/91/15/af68c509d4a138cfe299d0d7ddb14afba15233223ebd933b4bbdbc7155d3/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:dfb781ff7eaa91a6f7fd41776ec37c5853c795d3b358d4896fdbb5df168af422", size = 4967344, upload-time = "2025-10-15T23:17:28.06Z" },
{ url = "https://files.pythonhosted.org/packages/ca/e3/8643d077c53868b681af077edf6b3cb58288b5423610f21c62aadcbe99f4/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:6f61efb26e76c45c4a227835ddeae96d83624fb0d29eb5df5b96e14ed1a0afb7", size = 4466564, upload-time = "2025-10-15T23:17:29.665Z" },
{ url = "https://files.pythonhosted.org/packages/0e/43/c1e8726fa59c236ff477ff2b5dc071e54b21e5a1e51aa2cee1676f1c986f/cryptography-46.0.3-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:23b1a8f26e43f47ceb6d6a43115f33a5a37d57df4ea0ca295b780ae8546e8044", size = 4292415, upload-time = "2025-10-15T23:17:31.686Z" },
{ url = "https://files.pythonhosted.org/packages/42/f9/2f8fefdb1aee8a8e3256a0568cffc4e6d517b256a2fe97a029b3f1b9fe7e/cryptography-46.0.3-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:b419ae593c86b87014b9be7396b385491ad7f320bde96826d0dd174459e54665", size = 4931457, upload-time = "2025-10-15T23:17:33.478Z" },
{ url = "https://files.pythonhosted.org/packages/79/30/9b54127a9a778ccd6d27c3da7563e9f2d341826075ceab89ae3b41bf5be2/cryptography-46.0.3-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:50fc3343ac490c6b08c0cf0d704e881d0d660be923fd3076db3e932007e726e3", size = 4466074, upload-time = "2025-10-15T23:17:35.158Z" },
{ url = "https://files.pythonhosted.org/packages/ac/68/b4f4a10928e26c941b1b6a179143af9f4d27d88fe84a6a3c53592d2e76bf/cryptography-46.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:22d7e97932f511d6b0b04f2bfd818d73dcd5928db509460aaf48384778eb6d20", size = 4420569, upload-time = "2025-10-15T23:17:37.188Z" },
{ url = "https://files.pythonhosted.org/packages/a3/49/3746dab4c0d1979888f125226357d3262a6dd40e114ac29e3d2abdf1ec55/cryptography-46.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:d55f3dffadd674514ad19451161118fd010988540cee43d8bc20675e775925de", size = 4681941, upload-time = "2025-10-15T23:17:39.236Z" },
{ url = "https://files.pythonhosted.org/packages/fd/30/27654c1dbaf7e4a3531fa1fc77986d04aefa4d6d78259a62c9dc13d7ad36/cryptography-46.0.3-cp314-cp314t-win32.whl", hash = "sha256:8a6e050cb6164d3f830453754094c086ff2d0b2f3a897a1d9820f6139a1f0914", size = 3022339, upload-time = "2025-10-15T23:17:40.888Z" },
{ url = "https://files.pythonhosted.org/packages/f6/30/640f34ccd4d2a1bc88367b54b926b781b5a018d65f404d409aba76a84b1c/cryptography-46.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:760f83faa07f8b64e9c33fc963d790a2edb24efb479e3520c14a45741cd9b2db", size = 3494315, upload-time = "2025-10-15T23:17:42.769Z" },
{ url = "https://files.pythonhosted.org/packages/ba/8b/88cc7e3bd0a8e7b861f26981f7b820e1f46aa9d26cc482d0feba0ecb4919/cryptography-46.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:516ea134e703e9fe26bcd1277a4b59ad30586ea90c365a87781d7887a646fe21", size = 2919331, upload-time = "2025-10-15T23:17:44.468Z" },
{ url = "https://files.pythonhosted.org/packages/fd/23/45fe7f376a7df8daf6da3556603b36f53475a99ce4faacb6ba2cf3d82021/cryptography-46.0.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:cb3d760a6117f621261d662bccc8ef5bc32ca673e037c83fbe565324f5c46936", size = 7218248, upload-time = "2025-10-15T23:17:46.294Z" },
{ url = "https://files.pythonhosted.org/packages/27/32/b68d27471372737054cbd34c84981f9edbc24fe67ca225d389799614e27f/cryptography-46.0.3-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:4b7387121ac7d15e550f5cb4a43aef2559ed759c35df7336c402bb8275ac9683", size = 4294089, upload-time = "2025-10-15T23:17:48.269Z" },
{ url = "https://files.pythonhosted.org/packages/26/42/fa8389d4478368743e24e61eea78846a0006caffaf72ea24a15159215a14/cryptography-46.0.3-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:15ab9b093e8f09daab0f2159bb7e47532596075139dd74365da52ecc9cb46c5d", size = 4440029, upload-time = "2025-10-15T23:17:49.837Z" },
{ url = "https://files.pythonhosted.org/packages/5f/eb/f483db0ec5ac040824f269e93dd2bd8a21ecd1027e77ad7bdf6914f2fd80/cryptography-46.0.3-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:46acf53b40ea38f9c6c229599a4a13f0d46a6c3fa9ef19fc1a124d62e338dfa0", size = 4297222, upload-time = "2025-10-15T23:17:51.357Z" },
{ url = "https://files.pythonhosted.org/packages/fd/cf/da9502c4e1912cb1da3807ea3618a6829bee8207456fbbeebc361ec38ba3/cryptography-46.0.3-cp38-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:10ca84c4668d066a9878890047f03546f3ae0a6b8b39b697457b7757aaf18dbc", size = 4012280, upload-time = "2025-10-15T23:17:52.964Z" },
{ url = "https://files.pythonhosted.org/packages/6b/8f/9adb86b93330e0df8b3dcf03eae67c33ba89958fc2e03862ef1ac2b42465/cryptography-46.0.3-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:36e627112085bb3b81b19fed209c05ce2a52ee8b15d161b7c643a7d5a88491f3", size = 4978958, upload-time = "2025-10-15T23:17:54.965Z" },
{ url = "https://files.pythonhosted.org/packages/d1/a0/5fa77988289c34bdb9f913f5606ecc9ada1adb5ae870bd0d1054a7021cc4/cryptography-46.0.3-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:1000713389b75c449a6e979ffc7dcc8ac90b437048766cef052d4d30b8220971", size = 4473714, upload-time = "2025-10-15T23:17:56.754Z" },
{ url = "https://files.pythonhosted.org/packages/14/e5/fc82d72a58d41c393697aa18c9abe5ae1214ff6f2a5c18ac470f92777895/cryptography-46.0.3-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:b02cf04496f6576afffef5ddd04a0cb7d49cf6be16a9059d793a30b035f6b6ac", size = 4296970, upload-time = "2025-10-15T23:17:58.588Z" },
{ url = "https://files.pythonhosted.org/packages/78/06/5663ed35438d0b09056973994f1aec467492b33bd31da36e468b01ec1097/cryptography-46.0.3-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:71e842ec9bc7abf543b47cf86b9a743baa95f4677d22baa4c7d5c69e49e9bc04", size = 4940236, upload-time = "2025-10-15T23:18:00.897Z" },
{ url = "https://files.pythonhosted.org/packages/fc/59/873633f3f2dcd8a053b8dd1d38f783043b5fce589c0f6988bf55ef57e43e/cryptography-46.0.3-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:402b58fc32614f00980b66d6e56a5b4118e6cb362ae8f3fda141ba4689bd4506", size = 4472642, upload-time = "2025-10-15T23:18:02.749Z" },
{ url = "https://files.pythonhosted.org/packages/3d/39/8e71f3930e40f6877737d6f69248cf74d4e34b886a3967d32f919cc50d3b/cryptography-46.0.3-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ef639cb3372f69ec44915fafcd6698b6cc78fbe0c2ea41be867f6ed612811963", size = 4423126, upload-time = "2025-10-15T23:18:04.85Z" },
{ url = "https://files.pythonhosted.org/packages/cd/c7/f65027c2810e14c3e7268353b1681932b87e5a48e65505d8cc17c99e36ae/cryptography-46.0.3-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3b51b8ca4f1c6453d8829e1eb7299499ca7f313900dd4d89a24b8b87c0a780d4", size = 4686573, upload-time = "2025-10-15T23:18:06.908Z" },
{ url = "https://files.pythonhosted.org/packages/0a/6e/1c8331ddf91ca4730ab3086a0f1be19c65510a33b5a441cb334e7a2d2560/cryptography-46.0.3-cp38-abi3-win32.whl", hash = "sha256:6276eb85ef938dc035d59b87c8a7dc559a232f954962520137529d77b18ff1df", size = 3036695, upload-time = "2025-10-15T23:18:08.672Z" },
{ url = "https://files.pythonhosted.org/packages/90/45/b0d691df20633eff80955a0fc7695ff9051ffce8b69741444bd9ed7bd0db/cryptography-46.0.3-cp38-abi3-win_amd64.whl", hash = "sha256:416260257577718c05135c55958b674000baef9a1c7d9e8f306ec60d71db850f", size = 3501720, upload-time = "2025-10-15T23:18:10.632Z" },
{ url = "https://files.pythonhosted.org/packages/e8/cb/2da4cc83f5edb9c3257d09e1e7ab7b23f049c7962cae8d842bbef0a9cec9/cryptography-46.0.3-cp38-abi3-win_arm64.whl", hash = "sha256:d89c3468de4cdc4f08a57e214384d0471911a3830fcdaf7a8cc587e42a866372", size = 2918740, upload-time = "2025-10-15T23:18:12.277Z" },
{ url = "https://files.pythonhosted.org/packages/d9/cd/1a8633802d766a0fa46f382a77e096d7e209e0817892929655fe0586ae32/cryptography-46.0.3-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a23582810fedb8c0bc47524558fb6c56aac3fc252cb306072fd2815da2a47c32", size = 3689163, upload-time = "2025-10-15T23:18:13.821Z" },
{ url = "https://files.pythonhosted.org/packages/4c/59/6b26512964ace6480c3e54681a9859c974172fb141c38df11eadd8416947/cryptography-46.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:e7aec276d68421f9574040c26e2a7c3771060bc0cff408bae1dcb19d3ab1e63c", size = 3429474, upload-time = "2025-10-15T23:18:15.477Z" },
{ url = "https://files.pythonhosted.org/packages/06/8a/e60e46adab4362a682cf142c7dcb5bf79b782ab2199b0dcb81f55970807f/cryptography-46.0.3-pp311-pypy311_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7ce938a99998ed3c8aa7e7272dca1a610401ede816d36d0693907d863b10d9ea", size = 3698132, upload-time = "2025-10-15T23:18:17.056Z" },
{ url = "https://files.pythonhosted.org/packages/da/38/f59940ec4ee91e93d3311f7532671a5cef5570eb04a144bf203b58552d11/cryptography-46.0.3-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:191bb60a7be5e6f54e30ba16fdfae78ad3a342a0599eb4193ba88e3f3d6e185b", size = 4243992, upload-time = "2025-10-15T23:18:18.695Z" },
{ url = "https://files.pythonhosted.org/packages/b0/0c/35b3d92ddebfdfda76bb485738306545817253d0a3ded0bfe80ef8e67aa5/cryptography-46.0.3-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c70cc23f12726be8f8bc72e41d5065d77e4515efae3690326764ea1b07845cfb", size = 4409944, upload-time = "2025-10-15T23:18:20.597Z" },
{ url = "https://files.pythonhosted.org/packages/99/55/181022996c4063fc0e7666a47049a1ca705abb9c8a13830f074edb347495/cryptography-46.0.3-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:9394673a9f4de09e28b5356e7fff97d778f8abad85c9d5ac4a4b7e25a0de7717", size = 4242957, upload-time = "2025-10-15T23:18:22.18Z" },
{ url = "https://files.pythonhosted.org/packages/ba/af/72cd6ef29f9c5f731251acadaeb821559fe25f10852f44a63374c9ca08c1/cryptography-46.0.3-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:94cd0549accc38d1494e1f8de71eca837d0509d0d44bf11d158524b0e12cebf9", size = 4409447, upload-time = "2025-10-15T23:18:24.209Z" },
{ url = "https://files.pythonhosted.org/packages/0d/c3/e90f4a4feae6410f914f8ebac129b9ae7a8c92eb60a638012dde42030a9d/cryptography-46.0.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:6b5063083824e5509fdba180721d55909ffacccc8adbec85268b48439423d78c", size = 3438528, upload-time = "2025-10-15T23:18:26.227Z" },
{ url = "https://files.pythonhosted.org/packages/f7/81/b0bb27f2ba931a65409c6b8a8b358a7f03c0e46eceacddff55f7c84b1f3b/cryptography-46.0.5-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:351695ada9ea9618b3500b490ad54c739860883df6c1f555e088eaf25b1bbaad", size = 7176289, upload-time = "2026-02-10T19:17:08.274Z" },
{ url = "https://files.pythonhosted.org/packages/ff/9e/6b4397a3e3d15123de3b1806ef342522393d50736c13b20ec4c9ea6693a6/cryptography-46.0.5-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c18ff11e86df2e28854939acde2d003f7984f721eba450b56a200ad90eeb0e6b", size = 4275637, upload-time = "2026-02-10T19:17:10.53Z" },
{ url = "https://files.pythonhosted.org/packages/63/e7/471ab61099a3920b0c77852ea3f0ea611c9702f651600397ac567848b897/cryptography-46.0.5-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4d7e3d356b8cd4ea5aff04f129d5f66ebdc7b6f8eae802b93739ed520c47c79b", size = 4424742, upload-time = "2026-02-10T19:17:12.388Z" },
{ url = "https://files.pythonhosted.org/packages/37/53/a18500f270342d66bf7e4d9f091114e31e5ee9e7375a5aba2e85a91e0044/cryptography-46.0.5-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:50bfb6925eff619c9c023b967d5b77a54e04256c4281b0e21336a130cd7fc263", size = 4277528, upload-time = "2026-02-10T19:17:13.853Z" },
{ url = "https://files.pythonhosted.org/packages/22/29/c2e812ebc38c57b40e7c583895e73c8c5adb4d1e4a0cc4c5a4fdab2b1acc/cryptography-46.0.5-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:803812e111e75d1aa73690d2facc295eaefd4439be1023fefc4995eaea2af90d", size = 4947993, upload-time = "2026-02-10T19:17:15.618Z" },
{ url = "https://files.pythonhosted.org/packages/6b/e7/237155ae19a9023de7e30ec64e5d99a9431a567407ac21170a046d22a5a3/cryptography-46.0.5-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3ee190460e2fbe447175cda91b88b84ae8322a104fc27766ad09428754a618ed", size = 4456855, upload-time = "2026-02-10T19:17:17.221Z" },
{ url = "https://files.pythonhosted.org/packages/2d/87/fc628a7ad85b81206738abbd213b07702bcbdada1dd43f72236ef3cffbb5/cryptography-46.0.5-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:f145bba11b878005c496e93e257c1e88f154d278d2638e6450d17e0f31e558d2", size = 3984635, upload-time = "2026-02-10T19:17:18.792Z" },
{ url = "https://files.pythonhosted.org/packages/84/29/65b55622bde135aedf4565dc509d99b560ee4095e56989e815f8fd2aa910/cryptography-46.0.5-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:e9251e3be159d1020c4030bd2e5f84d6a43fe54b6c19c12f51cde9542a2817b2", size = 4277038, upload-time = "2026-02-10T19:17:20.256Z" },
{ url = "https://files.pythonhosted.org/packages/bc/36/45e76c68d7311432741faf1fbf7fac8a196a0a735ca21f504c75d37e2558/cryptography-46.0.5-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:47fb8a66058b80e509c47118ef8a75d14c455e81ac369050f20ba0d23e77fee0", size = 4912181, upload-time = "2026-02-10T19:17:21.825Z" },
{ url = "https://files.pythonhosted.org/packages/6d/1a/c1ba8fead184d6e3d5afcf03d569acac5ad063f3ac9fb7258af158f7e378/cryptography-46.0.5-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:4c3341037c136030cb46e4b1e17b7418ea4cbd9dd207e4a6f3b2b24e0d4ac731", size = 4456482, upload-time = "2026-02-10T19:17:25.133Z" },
{ url = "https://files.pythonhosted.org/packages/f9/e5/3fb22e37f66827ced3b902cf895e6a6bc1d095b5b26be26bd13c441fdf19/cryptography-46.0.5-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:890bcb4abd5a2d3f852196437129eb3667d62630333aacc13dfd470fad3aaa82", size = 4405497, upload-time = "2026-02-10T19:17:26.66Z" },
{ url = "https://files.pythonhosted.org/packages/1a/df/9d58bb32b1121a8a2f27383fabae4d63080c7ca60b9b5c88be742be04ee7/cryptography-46.0.5-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:80a8d7bfdf38f87ca30a5391c0c9ce4ed2926918e017c29ddf643d0ed2778ea1", size = 4667819, upload-time = "2026-02-10T19:17:28.569Z" },
{ url = "https://files.pythonhosted.org/packages/ea/ed/325d2a490c5e94038cdb0117da9397ece1f11201f425c4e9c57fe5b9f08b/cryptography-46.0.5-cp311-abi3-win32.whl", hash = "sha256:60ee7e19e95104d4c03871d7d7dfb3d22ef8a9b9c6778c94e1c8fcc8365afd48", size = 3028230, upload-time = "2026-02-10T19:17:30.518Z" },
{ url = "https://files.pythonhosted.org/packages/e9/5a/ac0f49e48063ab4255d9e3b79f5def51697fce1a95ea1370f03dc9db76f6/cryptography-46.0.5-cp311-abi3-win_amd64.whl", hash = "sha256:38946c54b16c885c72c4f59846be9743d699eee2b69b6988e0a00a01f46a61a4", size = 3480909, upload-time = "2026-02-10T19:17:32.083Z" },
{ url = "https://files.pythonhosted.org/packages/00/13/3d278bfa7a15a96b9dc22db5a12ad1e48a9eb3d40e1827ef66a5df75d0d0/cryptography-46.0.5-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:94a76daa32eb78d61339aff7952ea819b1734b46f73646a07decb40e5b3448e2", size = 7119287, upload-time = "2026-02-10T19:17:33.801Z" },
{ url = "https://files.pythonhosted.org/packages/67/c8/581a6702e14f0898a0848105cbefd20c058099e2c2d22ef4e476dfec75d7/cryptography-46.0.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5be7bf2fb40769e05739dd0046e7b26f9d4670badc7b032d6ce4db64dddc0678", size = 4265728, upload-time = "2026-02-10T19:17:35.569Z" },
{ url = "https://files.pythonhosted.org/packages/dd/4a/ba1a65ce8fc65435e5a849558379896c957870dd64fecea97b1ad5f46a37/cryptography-46.0.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fe346b143ff9685e40192a4960938545c699054ba11d4f9029f94751e3f71d87", size = 4408287, upload-time = "2026-02-10T19:17:36.938Z" },
{ url = "https://files.pythonhosted.org/packages/f8/67/8ffdbf7b65ed1ac224d1c2df3943553766914a8ca718747ee3871da6107e/cryptography-46.0.5-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:c69fd885df7d089548a42d5ec05be26050ebcd2283d89b3d30676eb32ff87dee", size = 4270291, upload-time = "2026-02-10T19:17:38.748Z" },
{ url = "https://files.pythonhosted.org/packages/f8/e5/f52377ee93bc2f2bba55a41a886fd208c15276ffbd2569f2ddc89d50e2c5/cryptography-46.0.5-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:8293f3dea7fc929ef7240796ba231413afa7b68ce38fd21da2995549f5961981", size = 4927539, upload-time = "2026-02-10T19:17:40.241Z" },
{ url = "https://files.pythonhosted.org/packages/3b/02/cfe39181b02419bbbbcf3abdd16c1c5c8541f03ca8bda240debc467d5a12/cryptography-46.0.5-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:1abfdb89b41c3be0365328a410baa9df3ff8a9110fb75e7b52e66803ddabc9a9", size = 4442199, upload-time = "2026-02-10T19:17:41.789Z" },
{ url = "https://files.pythonhosted.org/packages/c0/96/2fcaeb4873e536cf71421a388a6c11b5bc846e986b2b069c79363dc1648e/cryptography-46.0.5-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:d66e421495fdb797610a08f43b05269e0a5ea7f5e652a89bfd5a7d3c1dee3648", size = 3960131, upload-time = "2026-02-10T19:17:43.379Z" },
{ url = "https://files.pythonhosted.org/packages/d8/d2/b27631f401ddd644e94c5cf33c9a4069f72011821cf3dc7309546b0642a0/cryptography-46.0.5-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:4e817a8920bfbcff8940ecfd60f23d01836408242b30f1a708d93198393a80b4", size = 4270072, upload-time = "2026-02-10T19:17:45.481Z" },
{ url = "https://files.pythonhosted.org/packages/f4/a7/60d32b0370dae0b4ebe55ffa10e8599a2a59935b5ece1b9f06edb73abdeb/cryptography-46.0.5-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:68f68d13f2e1cb95163fa3b4db4bf9a159a418f5f6e7242564fc75fcae667fd0", size = 4892170, upload-time = "2026-02-10T19:17:46.997Z" },
{ url = "https://files.pythonhosted.org/packages/d2/b9/cf73ddf8ef1164330eb0b199a589103c363afa0cf794218c24d524a58eab/cryptography-46.0.5-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:a3d1fae9863299076f05cb8a778c467578262fae09f9dc0ee9b12eb4268ce663", size = 4441741, upload-time = "2026-02-10T19:17:48.661Z" },
{ url = "https://files.pythonhosted.org/packages/5f/eb/eee00b28c84c726fe8fa0158c65afe312d9c3b78d9d01daf700f1f6e37ff/cryptography-46.0.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c4143987a42a2397f2fc3b4d7e3a7d313fbe684f67ff443999e803dd75a76826", size = 4396728, upload-time = "2026-02-10T19:17:50.058Z" },
{ url = "https://files.pythonhosted.org/packages/65/f4/6bc1a9ed5aef7145045114b75b77c2a8261b4d38717bd8dea111a63c3442/cryptography-46.0.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:7d731d4b107030987fd61a7f8ab512b25b53cef8f233a97379ede116f30eb67d", size = 4652001, upload-time = "2026-02-10T19:17:51.54Z" },
{ url = "https://files.pythonhosted.org/packages/86/ef/5d00ef966ddd71ac2e6951d278884a84a40ffbd88948ef0e294b214ae9e4/cryptography-46.0.5-cp314-cp314t-win32.whl", hash = "sha256:c3bcce8521d785d510b2aad26ae2c966092b7daa8f45dd8f44734a104dc0bc1a", size = 3003637, upload-time = "2026-02-10T19:17:52.997Z" },
{ url = "https://files.pythonhosted.org/packages/b7/57/f3f4160123da6d098db78350fdfd9705057aad21de7388eacb2401dceab9/cryptography-46.0.5-cp314-cp314t-win_amd64.whl", hash = "sha256:4d8ae8659ab18c65ced284993c2265910f6c9e650189d4e3f68445ef82a810e4", size = 3469487, upload-time = "2026-02-10T19:17:54.549Z" },
{ url = "https://files.pythonhosted.org/packages/e2/fa/a66aa722105ad6a458bebd64086ca2b72cdd361fed31763d20390f6f1389/cryptography-46.0.5-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:4108d4c09fbbf2789d0c926eb4152ae1760d5a2d97612b92d508d96c861e4d31", size = 7170514, upload-time = "2026-02-10T19:17:56.267Z" },
{ url = "https://files.pythonhosted.org/packages/0f/04/c85bdeab78c8bc77b701bf0d9bdcf514c044e18a46dcff330df5448631b0/cryptography-46.0.5-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7d1f30a86d2757199cb2d56e48cce14deddf1f9c95f1ef1b64ee91ea43fe2e18", size = 4275349, upload-time = "2026-02-10T19:17:58.419Z" },
{ url = "https://files.pythonhosted.org/packages/5c/32/9b87132a2f91ee7f5223b091dc963055503e9b442c98fc0b8a5ca765fab0/cryptography-46.0.5-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:039917b0dc418bb9f6edce8a906572d69e74bd330b0b3fea4f79dab7f8ddd235", size = 4420667, upload-time = "2026-02-10T19:18:00.619Z" },
{ url = "https://files.pythonhosted.org/packages/a1/a6/a7cb7010bec4b7c5692ca6f024150371b295ee1c108bdc1c400e4c44562b/cryptography-46.0.5-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ba2a27ff02f48193fc4daeadf8ad2590516fa3d0adeeb34336b96f7fa64c1e3a", size = 4276980, upload-time = "2026-02-10T19:18:02.379Z" },
{ url = "https://files.pythonhosted.org/packages/8e/7c/c4f45e0eeff9b91e3f12dbd0e165fcf2a38847288fcfd889deea99fb7b6d/cryptography-46.0.5-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:61aa400dce22cb001a98014f647dc21cda08f7915ceb95df0c9eaf84b4b6af76", size = 4939143, upload-time = "2026-02-10T19:18:03.964Z" },
{ url = "https://files.pythonhosted.org/packages/37/19/e1b8f964a834eddb44fa1b9a9976f4e414cbb7aa62809b6760c8803d22d1/cryptography-46.0.5-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3ce58ba46e1bc2aac4f7d9290223cead56743fa6ab94a5d53292ffaac6a91614", size = 4453674, upload-time = "2026-02-10T19:18:05.588Z" },
{ url = "https://files.pythonhosted.org/packages/db/ed/db15d3956f65264ca204625597c410d420e26530c4e2943e05a0d2f24d51/cryptography-46.0.5-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:420d0e909050490d04359e7fdb5ed7e667ca5c3c402b809ae2563d7e66a92229", size = 3978801, upload-time = "2026-02-10T19:18:07.167Z" },
{ url = "https://files.pythonhosted.org/packages/41/e2/df40a31d82df0a70a0daf69791f91dbb70e47644c58581d654879b382d11/cryptography-46.0.5-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:582f5fcd2afa31622f317f80426a027f30dc792e9c80ffee87b993200ea115f1", size = 4276755, upload-time = "2026-02-10T19:18:09.813Z" },
{ url = "https://files.pythonhosted.org/packages/33/45/726809d1176959f4a896b86907b98ff4391a8aa29c0aaaf9450a8a10630e/cryptography-46.0.5-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:bfd56bb4b37ed4f330b82402f6f435845a5f5648edf1ad497da51a8452d5d62d", size = 4901539, upload-time = "2026-02-10T19:18:11.263Z" },
{ url = "https://files.pythonhosted.org/packages/99/0f/a3076874e9c88ecb2ecc31382f6e7c21b428ede6f55aafa1aa272613e3cd/cryptography-46.0.5-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:a3d507bb6a513ca96ba84443226af944b0f7f47dcc9a399d110cd6146481d24c", size = 4452794, upload-time = "2026-02-10T19:18:12.914Z" },
{ url = "https://files.pythonhosted.org/packages/02/ef/ffeb542d3683d24194a38f66ca17c0a4b8bf10631feef44a7ef64e631b1a/cryptography-46.0.5-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9f16fbdf4da055efb21c22d81b89f155f02ba420558db21288b3d0035bafd5f4", size = 4404160, upload-time = "2026-02-10T19:18:14.375Z" },
{ url = "https://files.pythonhosted.org/packages/96/93/682d2b43c1d5f1406ed048f377c0fc9fc8f7b0447a478d5c65ab3d3a66eb/cryptography-46.0.5-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:ced80795227d70549a411a4ab66e8ce307899fad2220ce5ab2f296e687eacde9", size = 4667123, upload-time = "2026-02-10T19:18:15.886Z" },
{ url = "https://files.pythonhosted.org/packages/45/2d/9c5f2926cb5300a8eefc3f4f0b3f3df39db7f7ce40c8365444c49363cbda/cryptography-46.0.5-cp38-abi3-win32.whl", hash = "sha256:02f547fce831f5096c9a567fd41bc12ca8f11df260959ecc7c3202555cc47a72", size = 3010220, upload-time = "2026-02-10T19:18:17.361Z" },
{ url = "https://files.pythonhosted.org/packages/48/ef/0c2f4a8e31018a986949d34a01115dd057bf536905dca38897bacd21fac3/cryptography-46.0.5-cp38-abi3-win_amd64.whl", hash = "sha256:556e106ee01aa13484ce9b0239bca667be5004efb0aabbed28d353df86445595", size = 3467050, upload-time = "2026-02-10T19:18:18.899Z" },
{ url = "https://files.pythonhosted.org/packages/eb/dd/2d9fdb07cebdf3d51179730afb7d5e576153c6744c3ff8fded23030c204e/cryptography-46.0.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:3b4995dc971c9fb83c25aa44cf45f02ba86f71ee600d81091c2f0cbae116b06c", size = 3476964, upload-time = "2026-02-10T19:18:20.687Z" },
{ url = "https://files.pythonhosted.org/packages/e9/6f/6cc6cc9955caa6eaf83660b0da2b077c7fe8ff9950a3c5e45d605038d439/cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:bc84e875994c3b445871ea7181d424588171efec3e185dced958dad9e001950a", size = 4218321, upload-time = "2026-02-10T19:18:22.349Z" },
{ url = "https://files.pythonhosted.org/packages/3e/5d/c4da701939eeee699566a6c1367427ab91a8b7088cc2328c09dbee940415/cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:2ae6971afd6246710480e3f15824ed3029a60fc16991db250034efd0b9fb4356", size = 4381786, upload-time = "2026-02-10T19:18:24.529Z" },
{ url = "https://files.pythonhosted.org/packages/ac/97/a538654732974a94ff96c1db621fa464f455c02d4bb7d2652f4edc21d600/cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:d861ee9e76ace6cf36a6a89b959ec08e7bc2493ee39d07ffe5acb23ef46d27da", size = 4217990, upload-time = "2026-02-10T19:18:25.957Z" },
{ url = "https://files.pythonhosted.org/packages/ae/11/7e500d2dd3ba891197b9efd2da5454b74336d64a7cc419aa7327ab74e5f6/cryptography-46.0.5-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:2b7a67c9cd56372f3249b39699f2ad479f6991e62ea15800973b956f4b73e257", size = 4381252, upload-time = "2026-02-10T19:18:27.496Z" },
{ url = "https://files.pythonhosted.org/packages/bc/58/6b3d24e6b9bc474a2dcdee65dfd1f008867015408a271562e4b690561a4d/cryptography-46.0.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:8456928655f856c6e1533ff59d5be76578a7157224dbd9ce6872f25055ab9ab7", size = 3407605, upload-time = "2026-02-10T19:18:29.233Z" },
]
[[package]]
@@ -1353,7 +1348,7 @@ wheels = [
[[package]]
name = "langchain-core"
version = "1.2.7"
version = "1.2.13"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "jsonpatch" },
@@ -1365,14 +1360,14 @@ dependencies = [
{ name = "typing-extensions" },
{ name = "uuid-utils" },
]
sdist = { url = "https://files.pythonhosted.org/packages/a2/0e/664d8d81b3493e09cbab72448d2f9d693d1fa5aa2bcc488602203a9b6da0/langchain_core-1.2.7.tar.gz", hash = "sha256:e1460639f96c352b4a41c375f25aeb8d16ffc1769499fb1c20503aad59305ced", size = 837039, upload-time = "2026-01-09T17:44:25.505Z" }
sdist = { url = "https://files.pythonhosted.org/packages/fb/bb/c501ca60556c11ac80d1454bdcac63cb33583ce4e64fc4535ad5a7d5c6ba/langchain_core-1.2.13.tar.gz", hash = "sha256:d2773d0d0130a356378db9a858cfeef64c3d64bc03722f1d4d6c40eb46fdf01b", size = 831612, upload-time = "2026-02-15T07:45:57.014Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/6e/6f/34a9fba14d191a67f7e2ee3dbce3e9b86d2fa7310e2c7f2c713583481bd2/langchain_core-1.2.7-py3-none-any.whl", hash = "sha256:452f4fef7a3d883357b22600788d37e3d8854ef29da345b7ac7099f33c31828b", size = 490232, upload-time = "2026-01-09T17:44:24.236Z" },
{ url = "https://files.pythonhosted.org/packages/12/ab/60fd69e5d55f67d422baefddaaca523c42cd7510ab6aeb17db6ae57fb107/langchain_core-1.2.13-py3-none-any.whl", hash = "sha256:b31823e28d3eff1e237096d0bd3bf80c6f9624eb471a9496dbfbd427779f8d82", size = 500485, upload-time = "2026-02-15T07:45:55.422Z" },
]
[[package]]
name = "langgraph"
version = "1.0.7"
version = "1.0.9"
source = { editable = "." }
dependencies = [
{ name = "langchain-core" },
@@ -1480,7 +1475,7 @@ dev = [
{ name = "ruff" },
{ name = "syrupy" },
{ name = "types-requests" },
{ name = "uvloop", specifier = "==0.21.0b1" },
{ name = "uvloop", specifier = "==0.22.1" },
]
lint = [
{ name = "mypy" },
@@ -1510,7 +1505,7 @@ test = [
{ name = "pytest-xdist", extras = ["psutil"] },
{ name = "redis" },
{ name = "syrupy" },
{ name = "uvloop", specifier = "==0.21.0b1" },
{ name = "uvloop", specifier = "==0.22.1" },
]
[[package]]
@@ -1612,7 +1607,7 @@ dependencies = [
[package.metadata]
requires-dist = [
{ name = "langgraph-checkpoint", editable = "../checkpoint" },
{ name = "orjson", specifier = ">=3.10.1" },
{ name = "orjson", specifier = ">=3.11.5" },
{ name = "psycopg", specifier = ">=3.2.0" },
{ name = "psycopg-pool", specifier = ">=3.2.0" },
]
@@ -1740,7 +1735,7 @@ test = [
[[package]]
name = "langgraph-prebuilt"
version = "1.0.7"
version = "1.0.8"
source = { editable = "../prebuilt" }
dependencies = [
{ name = "langchain-core" },
@@ -1817,28 +1812,29 @@ dependencies = [
[package.metadata]
requires-dist = [
{ name = "httpx", specifier = ">=0.25.2" },
{ name = "orjson", specifier = ">=3.10.1" },
{ name = "orjson", specifier = ">=3.11.5" },
]
[package.metadata.requires-dev]
dev = [
{ name = "codespell" },
{ name = "mypy", specifier = "==1.19.0" },
{ name = "langgraph", editable = "." },
{ name = "mypy", specifier = "==1.19.1" },
{ name = "pydantic", specifier = ">=2.12.4" },
{ name = "pytest" },
{ name = "pytest-asyncio" },
{ name = "pytest-mock" },
{ name = "pytest-watch" },
{ name = "ruff", specifier = "==0.14.11" },
{ name = "ruff", specifier = "==0.15.1" },
{ name = "starlette" },
{ name = "ty", specifier = "==0.0.1a27" },
{ name = "ty", specifier = "==0.0.17" },
]
lint = [
{ name = "codespell" },
{ name = "mypy", specifier = "==1.19.0" },
{ name = "ruff", specifier = "==0.14.11" },
{ name = "mypy", specifier = "==1.19.1" },
{ name = "ruff", specifier = "==0.15.1" },
{ name = "starlette" },
{ name = "ty", specifier = "==0.0.1a27" },
{ name = "ty", specifier = "==0.0.17" },
]
test = [
{ name = "pytest" },
@@ -2136,7 +2132,7 @@ wheels = [
[[package]]
name = "nbconvert"
version = "7.16.6"
version = "7.17.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "beautifulsoup4" },
@@ -2154,9 +2150,9 @@ dependencies = [
{ name = "pygments" },
{ name = "traitlets" },
]
sdist = { url = "https://files.pythonhosted.org/packages/a3/59/f28e15fc47ffb73af68a8d9b47367a8630d76e97ae85ad18271b9db96fdf/nbconvert-7.16.6.tar.gz", hash = "sha256:576a7e37c6480da7b8465eefa66c17844243816ce1ccc372633c6b71c3c0f582", size = 857715, upload-time = "2025-01-28T09:29:14.724Z" }
sdist = { url = "https://files.pythonhosted.org/packages/38/47/81f886b699450d0569f7bc551df2b1673d18df7ff25cc0c21ca36ed8a5ff/nbconvert-7.17.0.tar.gz", hash = "sha256:1b2696f1b5be12309f6c7d707c24af604b87dfaf6d950794c7b07acab96dda78", size = 862855, upload-time = "2026-01-29T16:37:48.478Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/cc/9a/cd673b2f773a12c992f41309ef81b99da1690426bd2f96957a7ade0d3ed7/nbconvert-7.16.6-py3-none-any.whl", hash = "sha256:1375a7b67e0c2883678c48e506dc320febb57685e5ee67faa51b18a90f3a712b", size = 258525, upload-time = "2025-01-28T09:29:12.551Z" },
{ url = "https://files.pythonhosted.org/packages/0d/4b/8d5f796a792f8a25f6925a96032f098789f448571eb92011df1ae59e8ea8/nbconvert-7.17.0-py3-none-any.whl", hash = "sha256:4f99a63b337b9a23504347afdab24a11faa7d86b405e5c8f9881cd313336d518", size = 261510, upload-time = "2026-01-29T16:37:46.322Z" },
]
[[package]]
@@ -2527,17 +2523,17 @@ wheels = [
[[package]]
name = "protobuf"
version = "6.33.4"
version = "6.33.5"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/53/b8/cda15d9d46d03d4aa3a67cb6bffe05173440ccf86a9541afaf7ac59a1b6b/protobuf-6.33.4.tar.gz", hash = "sha256:dc2e61bca3b10470c1912d166fe0af67bfc20eb55971dcef8dfa48ce14f0ed91", size = 444346, upload-time = "2026-01-12T18:33:40.109Z" }
sdist = { url = "https://files.pythonhosted.org/packages/ba/25/7c72c307aafc96fa87062aa6291d9f7c94836e43214d43722e86037aac02/protobuf-6.33.5.tar.gz", hash = "sha256:6ddcac2a081f8b7b9642c09406bc6a4290128fce5f471cddd165960bb9119e5c", size = 444465, upload-time = "2026-01-29T21:51:33.494Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e0/be/24ef9f3095bacdf95b458543334d0c4908ccdaee5130420bf064492c325f/protobuf-6.33.4-cp310-abi3-win32.whl", hash = "sha256:918966612c8232fc6c24c78e1cd89784307f5814ad7506c308ee3cf86662850d", size = 425612, upload-time = "2026-01-12T18:33:29.656Z" },
{ url = "https://files.pythonhosted.org/packages/31/ad/e5693e1974a28869e7cd244302911955c1cebc0161eb32dfa2b25b6e96f0/protobuf-6.33.4-cp310-abi3-win_amd64.whl", hash = "sha256:8f11ffae31ec67fc2554c2ef891dcb561dae9a2a3ed941f9e134c2db06657dbc", size = 436962, upload-time = "2026-01-12T18:33:31.345Z" },
{ url = "https://files.pythonhosted.org/packages/66/15/6ee23553b6bfd82670207ead921f4d8ef14c107e5e11443b04caeb5ab5ec/protobuf-6.33.4-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:2fe67f6c014c84f655ee06f6f66213f9254b3a8b6bda6cda0ccd4232c73c06f0", size = 427612, upload-time = "2026-01-12T18:33:32.646Z" },
{ url = "https://files.pythonhosted.org/packages/2b/48/d301907ce6d0db75f959ca74f44b475a9caa8fcba102d098d3c3dd0f2d3f/protobuf-6.33.4-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:757c978f82e74d75cba88eddec479df9b99a42b31193313b75e492c06a51764e", size = 324484, upload-time = "2026-01-12T18:33:33.789Z" },
{ url = "https://files.pythonhosted.org/packages/92/1c/e53078d3f7fe710572ab2dcffd993e1e3b438ae71cfc031b71bae44fcb2d/protobuf-6.33.4-cp39-abi3-manylinux2014_s390x.whl", hash = "sha256:c7c64f259c618f0bef7bee042075e390debbf9682334be2b67408ec7c1c09ee6", size = 339256, upload-time = "2026-01-12T18:33:35.231Z" },
{ url = "https://files.pythonhosted.org/packages/e8/8e/971c0edd084914f7ee7c23aa70ba89e8903918adca179319ee94403701d5/protobuf-6.33.4-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:3df850c2f8db9934de4cf8f9152f8dc2558f49f298f37f90c517e8e5c84c30e9", size = 323311, upload-time = "2026-01-12T18:33:36.305Z" },
{ url = "https://files.pythonhosted.org/packages/75/b1/1dc83c2c661b4c62d56cc081706ee33a4fc2835bd90f965baa2663ef7676/protobuf-6.33.4-py3-none-any.whl", hash = "sha256:1fe3730068fcf2e595816a6c34fe66eeedd37d51d0400b72fabc848811fdc1bc", size = 170532, upload-time = "2026-01-12T18:33:39.199Z" },
{ url = "https://files.pythonhosted.org/packages/b1/79/af92d0a8369732b027e6d6084251dd8e782c685c72da161bd4a2e00fbabb/protobuf-6.33.5-cp310-abi3-win32.whl", hash = "sha256:d71b040839446bac0f4d162e758bea99c8251161dae9d0983a3b88dee345153b", size = 425769, upload-time = "2026-01-29T21:51:21.751Z" },
{ url = "https://files.pythonhosted.org/packages/55/75/bb9bc917d10e9ee13dee8607eb9ab963b7cf8be607c46e7862c748aa2af7/protobuf-6.33.5-cp310-abi3-win_amd64.whl", hash = "sha256:3093804752167bcab3998bec9f1048baae6e29505adaf1afd14a37bddede533c", size = 437118, upload-time = "2026-01-29T21:51:24.022Z" },
{ url = "https://files.pythonhosted.org/packages/a2/6b/e48dfc1191bc5b52950246275bf4089773e91cb5ba3592621723cdddca62/protobuf-6.33.5-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:a5cb85982d95d906df1e2210e58f8e4f1e3cdc088e52c921a041f9c9a0386de5", size = 427766, upload-time = "2026-01-29T21:51:25.413Z" },
{ url = "https://files.pythonhosted.org/packages/4e/b1/c79468184310de09d75095ed1314b839eb2f72df71097db9d1404a1b2717/protobuf-6.33.5-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:9b71e0281f36f179d00cbcb119cb19dec4d14a81393e5ea220f64b286173e190", size = 324638, upload-time = "2026-01-29T21:51:26.423Z" },
{ url = "https://files.pythonhosted.org/packages/c5/f5/65d838092fd01c44d16037953fd4c2cc851e783de9b8f02b27ec4ffd906f/protobuf-6.33.5-cp39-abi3-manylinux2014_s390x.whl", hash = "sha256:8afa18e1d6d20af15b417e728e9f60f3aa108ee76f23c3b2c07a2c3b546d3afd", size = 339411, upload-time = "2026-01-29T21:51:27.446Z" },
{ url = "https://files.pythonhosted.org/packages/9b/53/a9443aa3ca9ba8724fdfa02dd1887c1bcd8e89556b715cfbacca6b63dbec/protobuf-6.33.5-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:cbf16ba3350fb7b889fca858fb215967792dc125b35c7976ca4818bee3521cf0", size = 323465, upload-time = "2026-01-29T21:51:28.925Z" },
{ url = "https://files.pythonhosted.org/packages/57/bf/2086963c69bdac3d7cff1cc7ff79b8ce5ea0bec6797a017e1be338a46248/protobuf-6.33.5-py3-none-any.whl", hash = "sha256:69915a973dd0f60f31a08b8318b73eab2bd6a392c79184b3612226b0a3f8ec02", size = 170687, upload-time = "2026-01-29T21:51:32.557Z" },
]
[[package]]
@@ -2890,14 +2886,14 @@ wheels = [
[[package]]
name = "pyperf"
version = "2.9.0"
version = "2.10.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "psutil" },
]
sdist = { url = "https://files.pythonhosted.org/packages/89/f9/27bd50fb5475147ad04e288a076f29a893c1e94f10866fc3623a84ad75d2/pyperf-2.9.0.tar.gz", hash = "sha256:dbe0feef8ec1a465df191bba2576149762d15a8c9985c9fea93ab625d875c362", size = 227189, upload-time = "2025-03-04T13:45:44.335Z" }
sdist = { url = "https://files.pythonhosted.org/packages/16/91/39ca77aa58f13e8c65d747ac7e06584b55acabfa98987fb8d546bc24860d/pyperf-2.10.0.tar.gz", hash = "sha256:dd93ccfda79214725293e95f1fa6e00cb4a64adcf1326039486d4e1f91caaa62", size = 227609, upload-time = "2026-02-07T11:35:14.693Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/19/29/ce5d2dcb095debb3bed0654950c45207a7d138e194abef0ded4b86de1dc1/pyperf-2.9.0-py3-none-any.whl", hash = "sha256:215673fb60f3fbbc6c7a90b609b0806d8466fded8dd502bf5731e2b92506076e", size = 144204, upload-time = "2025-03-04T13:45:40.491Z" },
{ url = "https://files.pythonhosted.org/packages/91/26/f7bd5e37c254c2671f4dfff316d123eba13663bdfee941a01b09ab02d72d/pyperf-2.10.0-py3-none-any.whl", hash = "sha256:79196bc4a11e3c926dd4c6b14c80136c6b37f884fe913cbc57037f37636e9841", size = 144430, upload-time = "2026-02-07T11:35:12.636Z" },
]
[[package]]
@@ -3184,14 +3180,14 @@ wheels = [
[[package]]
name = "redis"
version = "7.1.0"
version = "7.2.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "async-timeout", marker = "python_full_version < '3.11.3'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/43/c8/983d5c6579a411d8a99bc5823cc5712768859b5ce2c8afe1a65b37832c81/redis-7.1.0.tar.gz", hash = "sha256:b1cc3cfa5a2cb9c2ab3ba700864fb0ad75617b41f01352ce5779dabf6d5f9c3c", size = 4796669, upload-time = "2025-11-19T15:54:39.961Z" }
sdist = { url = "https://files.pythonhosted.org/packages/9f/32/6fac13a11e73e1bc67a2ae821a72bfe4c2d8c4c48f0267e4a952be0f1bae/redis-7.2.0.tar.gz", hash = "sha256:4dd5bf4bd4ae80510267f14185a15cba2a38666b941aff68cccf0256b51c1f26", size = 4901247, upload-time = "2026-02-16T17:16:22.797Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/89/f0/8956f8a86b20d7bb9d6ac0187cf4cd54d8065bc9a1a09eb8011d4d326596/redis-7.1.0-py3-none-any.whl", hash = "sha256:23c52b208f92b56103e17c5d06bdc1a6c2c0b3106583985a76a18f83b265de2b", size = 354159, upload-time = "2025-11-19T15:54:38.064Z" },
{ url = "https://files.pythonhosted.org/packages/86/cf/f6180b67f99688d83e15c84c5beda831d1d341e95872d224f87ccafafe61/redis-7.2.0-py3-none-any.whl", hash = "sha256:01f591f8598e483f1842d429e8ae3a820804566f1c73dca1b80e23af9fba0497", size = 394898, upload-time = "2026-02-16T17:16:20.693Z" },
]
[[package]]
@@ -3392,28 +3388,27 @@ wheels = [
[[package]]
name = "ruff"
version = "0.14.13"
version = "0.15.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/50/0a/1914efb7903174b381ee2ffeebb4253e729de57f114e63595114c8ca451f/ruff-0.14.13.tar.gz", hash = "sha256:83cd6c0763190784b99650a20fec7633c59f6ebe41c5cc9d45ee42749563ad47", size = 6059504, upload-time = "2026-01-15T20:15:16.918Z" }
sdist = { url = "https://files.pythonhosted.org/packages/04/dc/4e6ac71b511b141cf626357a3946679abeba4cf67bc7cc5a17920f31e10d/ruff-0.15.1.tar.gz", hash = "sha256:c590fe13fb57c97141ae975c03a1aedb3d3156030cabd740d6ff0b0d601e203f", size = 4540855, upload-time = "2026-02-12T23:09:09.998Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c3/ae/0deefbc65ca74b0ab1fd3917f94dc3b398233346a74b8bbb0a916a1a6bf6/ruff-0.14.13-py3-none-linux_armv6l.whl", hash = "sha256:76f62c62cd37c276cb03a275b198c7c15bd1d60c989f944db08a8c1c2dbec18b", size = 13062418, upload-time = "2026-01-15T20:14:50.779Z" },
{ url = "https://files.pythonhosted.org/packages/47/df/5916604faa530a97a3c154c62a81cb6b735c0cb05d1e26d5ad0f0c8ac48a/ruff-0.14.13-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:914a8023ece0528d5cc33f5a684f5f38199bbb566a04815c2c211d8f40b5d0ed", size = 13442344, upload-time = "2026-01-15T20:15:07.94Z" },
{ url = "https://files.pythonhosted.org/packages/4c/f3/e0e694dd69163c3a1671e102aa574a50357536f18a33375050334d5cd517/ruff-0.14.13-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d24899478c35ebfa730597a4a775d430ad0d5631b8647a3ab368c29b7e7bd063", size = 12354720, upload-time = "2026-01-15T20:15:09.854Z" },
{ url = "https://files.pythonhosted.org/packages/c3/e8/67f5fcbbaee25e8fc3b56cc33e9892eca7ffe09f773c8e5907757a7e3bdb/ruff-0.14.13-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9aaf3870f14d925bbaf18b8a2347ee0ae7d95a2e490e4d4aea6813ed15ebc80e", size = 12774493, upload-time = "2026-01-15T20:15:20.908Z" },
{ url = "https://files.pythonhosted.org/packages/6b/ce/d2e9cb510870b52a9565d885c0d7668cc050e30fa2c8ac3fb1fda15c083d/ruff-0.14.13-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac5b7f63dd3b27cc811850f5ffd8fff845b00ad70e60b043aabf8d6ecc304e09", size = 12815174, upload-time = "2026-01-15T20:15:05.74Z" },
{ url = "https://files.pythonhosted.org/packages/88/00/c38e5da58beebcf4fa32d0ddd993b63dfacefd02ab7922614231330845bf/ruff-0.14.13-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78d2b1097750d90ba82ce4ba676e85230a0ed694178ca5e61aa9b459970b3eb9", size = 13680909, upload-time = "2026-01-15T20:15:14.537Z" },
{ url = "https://files.pythonhosted.org/packages/61/61/cd37c9dd5bd0a3099ba79b2a5899ad417d8f3b04038810b0501a80814fd7/ruff-0.14.13-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:7d0bf87705acbbcb8d4c24b2d77fbb73d40210a95c3903b443cd9e30824a5032", size = 15144215, upload-time = "2026-01-15T20:15:22.886Z" },
{ url = "https://files.pythonhosted.org/packages/56/8a/85502d7edbf98c2df7b8876f316c0157359165e16cdf98507c65c8d07d3d/ruff-0.14.13-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a3eb5da8e2c9e9f13431032fdcbe7681de9ceda5835efee3269417c13f1fed5c", size = 14706067, upload-time = "2026-01-15T20:14:48.271Z" },
{ url = "https://files.pythonhosted.org/packages/7e/2f/de0df127feb2ee8c1e54354dc1179b4a23798f0866019528c938ba439aca/ruff-0.14.13-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:642442b42957093811cd8d2140dfadd19c7417030a7a68cf8d51fcdd5f217427", size = 14133916, upload-time = "2026-01-15T20:14:57.357Z" },
{ url = "https://files.pythonhosted.org/packages/0d/77/9b99686bb9fe07a757c82f6f95e555c7a47801a9305576a9c67e0a31d280/ruff-0.14.13-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4acdf009f32b46f6e8864af19cbf6841eaaed8638e65c8dac845aea0d703c841", size = 13859207, upload-time = "2026-01-15T20:14:55.111Z" },
{ url = "https://files.pythonhosted.org/packages/7d/46/2bdcb34a87a179a4d23022d818c1c236cb40e477faf0d7c9afb6813e5876/ruff-0.14.13-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:591a7f68860ea4e003917d19b5c4f5ac39ff558f162dc753a2c5de897fd5502c", size = 14043686, upload-time = "2026-01-15T20:14:52.841Z" },
{ url = "https://files.pythonhosted.org/packages/1a/a9/5c6a4f56a0512c691cf143371bcf60505ed0f0860f24a85da8bd123b2bf1/ruff-0.14.13-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:774c77e841cc6e046fc3e91623ce0903d1cd07e3a36b1a9fe79b81dab3de506b", size = 12663837, upload-time = "2026-01-15T20:15:18.921Z" },
{ url = "https://files.pythonhosted.org/packages/fe/bb/b920016ece7651fa7fcd335d9d199306665486694d4361547ccb19394c44/ruff-0.14.13-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:61f4e40077a1248436772bb6512db5fc4457fe4c49e7a94ea7c5088655dd21ae", size = 12805867, upload-time = "2026-01-15T20:14:59.272Z" },
{ url = "https://files.pythonhosted.org/packages/7d/b3/0bd909851e5696cd21e32a8fc25727e5f58f1934b3596975503e6e85415c/ruff-0.14.13-py3-none-musllinux_1_2_i686.whl", hash = "sha256:6d02f1428357fae9e98ac7aa94b7e966fd24151088510d32cf6f902d6c09235e", size = 13208528, upload-time = "2026-01-15T20:15:03.732Z" },
{ url = "https://files.pythonhosted.org/packages/3b/3b/e2d94cb613f6bbd5155a75cbe072813756363eba46a3f2177a1fcd0cd670/ruff-0.14.13-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e399341472ce15237be0c0ae5fbceca4b04cd9bebab1a2b2c979e015455d8f0c", size = 13929242, upload-time = "2026-01-15T20:15:11.918Z" },
{ url = "https://files.pythonhosted.org/packages/6a/c5/abd840d4132fd51a12f594934af5eba1d5d27298a6f5b5d6c3be45301caf/ruff-0.14.13-py3-none-win32.whl", hash = "sha256:ef720f529aec113968b45dfdb838ac8934e519711da53a0456038a0efecbd680", size = 12919024, upload-time = "2026-01-15T20:14:43.647Z" },
{ url = "https://files.pythonhosted.org/packages/c2/55/6384b0b8ce731b6e2ade2b5449bf07c0e4c31e8a2e68ea65b3bafadcecc5/ruff-0.14.13-py3-none-win_amd64.whl", hash = "sha256:6070bd026e409734b9257e03e3ef18c6e1a216f0435c6751d7a8ec69cb59abef", size = 14097887, upload-time = "2026-01-15T20:15:01.48Z" },
{ url = "https://files.pythonhosted.org/packages/4d/e1/7348090988095e4e39560cfc2f7555b1b2a7357deba19167b600fdf5215d/ruff-0.14.13-py3-none-win_arm64.whl", hash = "sha256:7ab819e14f1ad9fe39f246cfcc435880ef7a9390d81a2b6ac7e01039083dd247", size = 13080224, upload-time = "2026-01-15T20:14:45.853Z" },
{ url = "https://files.pythonhosted.org/packages/23/bf/e6e4324238c17f9d9120a9d60aa99a7daaa21204c07fcd84e2ef03bb5fd1/ruff-0.15.1-py3-none-linux_armv6l.whl", hash = "sha256:b101ed7cf4615bda6ffe65bdb59f964e9f4a0d3f85cbf0e54f0ab76d7b90228a", size = 10367819, upload-time = "2026-02-12T23:09:03.598Z" },
{ url = "https://files.pythonhosted.org/packages/b3/ea/c8f89d32e7912269d38c58f3649e453ac32c528f93bb7f4219258be2e7ed/ruff-0.15.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:939c995e9277e63ea632cc8d3fae17aa758526f49a9a850d2e7e758bfef46602", size = 10798618, upload-time = "2026-02-12T23:09:22.928Z" },
{ url = "https://files.pythonhosted.org/packages/5e/0f/1d0d88bc862624247d82c20c10d4c0f6bb2f346559d8af281674cf327f15/ruff-0.15.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1d83466455fdefe60b8d9c8df81d3c1bbb2115cede53549d3b522ce2bc703899", size = 10148518, upload-time = "2026-02-12T23:08:58.339Z" },
{ url = "https://files.pythonhosted.org/packages/f5/c8/291c49cefaa4a9248e986256df2ade7add79388fe179e0691be06fae6f37/ruff-0.15.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9457e3c3291024866222b96108ab2d8265b477e5b1534c7ddb1810904858d16", size = 10518811, upload-time = "2026-02-12T23:09:31.865Z" },
{ url = "https://files.pythonhosted.org/packages/c3/1a/f5707440e5ae43ffa5365cac8bbb91e9665f4a883f560893829cf16a606b/ruff-0.15.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:92c92b003e9d4f7fbd33b1867bb15a1b785b1735069108dfc23821ba045b29bc", size = 10196169, upload-time = "2026-02-12T23:09:17.306Z" },
{ url = "https://files.pythonhosted.org/packages/2a/ff/26ddc8c4da04c8fd3ee65a89c9fb99eaa5c30394269d424461467be2271f/ruff-0.15.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fe5c41ab43e3a06778844c586251eb5a510f67125427625f9eb2b9526535779", size = 10990491, upload-time = "2026-02-12T23:09:25.503Z" },
{ url = "https://files.pythonhosted.org/packages/fc/00/50920cb385b89413f7cdb4bb9bc8fc59c1b0f30028d8bccc294189a54955/ruff-0.15.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66a6dd6df4d80dc382c6484f8ce1bcceb55c32e9f27a8b94c32f6c7331bf14fb", size = 11843280, upload-time = "2026-02-12T23:09:19.88Z" },
{ url = "https://files.pythonhosted.org/packages/5d/6d/2f5cad8380caf5632a15460c323ae326f1e1a2b5b90a6ee7519017a017ca/ruff-0.15.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6a4a42cbb8af0bda9bcd7606b064d7c0bc311a88d141d02f78920be6acb5aa83", size = 11274336, upload-time = "2026-02-12T23:09:14.907Z" },
{ url = "https://files.pythonhosted.org/packages/a3/1d/5f56cae1d6c40b8a318513599b35ea4b075d7dc1cd1d04449578c29d1d75/ruff-0.15.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ab064052c31dddada35079901592dfba2e05f5b1e43af3954aafcbc1096a5b2", size = 11137288, upload-time = "2026-02-12T23:09:07.475Z" },
{ url = "https://files.pythonhosted.org/packages/cd/20/6f8d7d8f768c93b0382b33b9306b3b999918816da46537d5a61635514635/ruff-0.15.1-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:5631c940fe9fe91f817a4c2ea4e81f47bee3ca4aa646134a24374f3c19ad9454", size = 11070681, upload-time = "2026-02-12T23:08:55.43Z" },
{ url = "https://files.pythonhosted.org/packages/9a/67/d640ac76069f64cdea59dba02af2e00b1fa30e2103c7f8d049c0cff4cafd/ruff-0.15.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:68138a4ba184b4691ccdc39f7795c66b3c68160c586519e7e8444cf5a53e1b4c", size = 10486401, upload-time = "2026-02-12T23:09:27.927Z" },
{ url = "https://files.pythonhosted.org/packages/65/3d/e1429f64a3ff89297497916b88c32a5cc88eeca7e9c787072d0e7f1d3e1e/ruff-0.15.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:518f9af03bfc33c03bdb4cb63fabc935341bb7f54af500f92ac309ecfbba6330", size = 10197452, upload-time = "2026-02-12T23:09:12.147Z" },
{ url = "https://files.pythonhosted.org/packages/78/83/e2c3bade17dad63bf1e1c2ffaf11490603b760be149e1419b07049b36ef2/ruff-0.15.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:da79f4d6a826caaea95de0237a67e33b81e6ec2e25fc7e1993a4015dffca7c61", size = 10693900, upload-time = "2026-02-12T23:09:34.418Z" },
{ url = "https://files.pythonhosted.org/packages/a1/27/fdc0e11a813e6338e0706e8b39bb7a1d61ea5b36873b351acee7e524a72a/ruff-0.15.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:3dd86dccb83cd7d4dcfac303ffc277e6048600dfc22e38158afa208e8bf94a1f", size = 11227302, upload-time = "2026-02-12T23:09:36.536Z" },
{ url = "https://files.pythonhosted.org/packages/f6/58/ac864a75067dcbd3b95be5ab4eb2b601d7fbc3d3d736a27e391a4f92a5c1/ruff-0.15.1-py3-none-win32.whl", hash = "sha256:660975d9cb49b5d5278b12b03bb9951d554543a90b74ed5d366b20e2c57c2098", size = 10462555, upload-time = "2026-02-12T23:09:29.899Z" },
{ url = "https://files.pythonhosted.org/packages/e0/5e/d4ccc8a27ecdb78116feac4935dfc39d1304536f4296168f91ed3ec00cd2/ruff-0.15.1-py3-none-win_amd64.whl", hash = "sha256:c820fef9dd5d4172a6570e5721704a96c6679b80cf7be41659ed439653f62336", size = 11599956, upload-time = "2026-02-12T23:09:01.157Z" },
{ url = "https://files.pythonhosted.org/packages/2a/07/5bda6a85b220c64c65686bc85bd0bbb23b29c62b3a9f9433fa55f17cda93/ruff-0.15.1-py3-none-win_arm64.whl", hash = "sha256:5ff7d5f0f88567850f45081fac8f4ec212be8d0b963e385c3f7d0d2eb4899416", size = 10874604, upload-time = "2026-02-12T23:09:05.515Z" },
]
[[package]]
@@ -3516,14 +3511,14 @@ wheels = [
[[package]]
name = "syrupy"
version = "5.0.0"
version = "5.1.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pytest" },
]
sdist = { url = "https://files.pythonhosted.org/packages/c1/90/1a442d21527009d4b40f37fe50b606ebb68a6407142c2b5cc508c34b696b/syrupy-5.0.0.tar.gz", hash = "sha256:3282fe963fa5d4d3e47231b16d1d4d0f4523705e8199eeb99a22a1bc9f5942f2", size = 48881, upload-time = "2025-09-28T21:15:12.783Z" }
sdist = { url = "https://files.pythonhosted.org/packages/2e/b0/24bca682d6a6337854be37f242d116cceeda9942571d5804c44bc1bdd427/syrupy-5.1.0.tar.gz", hash = "sha256:df543c7aa50d3cf1246e83d58fe490afe5f7dab7b41e74ecc0d8d23ae19bd4b8", size = 50495, upload-time = "2026-01-25T14:53:06.2Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/9d/9a/6c68aad2ccfce6e2eeebbf5bb709d0240592eb51ff142ec4c8fbf3c2460a/syrupy-5.0.0-py3-none-any.whl", hash = "sha256:c848e1a980ca52a28715cd2d2b4d434db424699c05653bd1158fb31cf56e9546", size = 49087, upload-time = "2025-09-28T21:15:11.639Z" },
{ url = "https://files.pythonhosted.org/packages/de/70/cf880c3b95a6034ef673e74b369941b42315c01f1554a5637a4f8b911009/syrupy-5.1.0-py3-none-any.whl", hash = "sha256:95162d2b05e61ed3e13f117b88dfab7c58bd6f90e66ebbf918e8a77114ad51c5", size = 51658, upload-time = "2026-01-25T14:53:05.105Z" },
]
[[package]]
@@ -3756,34 +3751,46 @@ wheels = [
[[package]]
name = "uvloop"
version = "0.21.0b1"
version = "0.22.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/cf/3d/a150e044b5bc69961168b024c531d21b63acd9948b7d681b03e551be01e1/uvloop-0.21.0b1.tar.gz", hash = "sha256:5e12901bd67c5ba374741fc497adc44de14854895c416cd0672b2e5b676ca23c", size = 2492824, upload-time = "2024-09-03T00:05:35.885Z" }
sdist = { url = "https://files.pythonhosted.org/packages/06/f0/18d39dbd1971d6d62c4629cc7fa67f74821b0dc1f5a77af43719de7936a7/uvloop-0.22.1.tar.gz", hash = "sha256:6c84bae345b9147082b17371e3dd5d42775bddce91f885499017f4607fdaf39f", size = 2443250, upload-time = "2025-10-16T22:17:19.342Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/43/66/9ec788eebd74f04a2756667d95c1d0f92f6a6bd9e5080e3d8b52ac32b682/uvloop-0.21.0b1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b47c276e66f2a26b58eafd0745c788e7345c9445a9e4b7799dd7065445ca91bf", size = 1442073, upload-time = "2024-09-03T00:04:35.033Z" },
{ url = "https://files.pythonhosted.org/packages/b9/de/74daae1ae950c694ea8a9b1cc66a64835ebe795ed664d9b94e0a7e03a444/uvloop-0.21.0b1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5aec94e40549d8fd1b04dc50d1b4480d4e8e1ed61066798dade0b4ecd408e7ed", size = 801933, upload-time = "2024-09-03T00:04:36.983Z" },
{ url = "https://files.pythonhosted.org/packages/1b/0a/2a096412380fed5f7f253ee1b2019dde271a3b8905b3ab54706f3f10ef96/uvloop-0.21.0b1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e867c5ffde9ec8880253a484a33a961e5af40e26757eda67a34798aabe471af", size = 3827869, upload-time = "2024-09-03T00:04:38.907Z" },
{ url = "https://files.pythonhosted.org/packages/b0/b4/bb6fc45e128e019c51a1561c72999f4d3777a42429b82a44acb672e6ce54/uvloop-0.21.0b1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1299f155b8dbe3374d1db810cb994cf22a3fadf8c5a85032aa8f31e18745a9c6", size = 3825264, upload-time = "2024-09-03T00:04:40.764Z" },
{ url = "https://files.pythonhosted.org/packages/c5/78/daae6af20422ec0436b297830355f934371cf20b149aaa6237dff8074864/uvloop-0.21.0b1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2abfc1738c3fbb5a5552ea9fb34cca5cbdf73868caf78bdacdcd6ffbab438870", size = 3705923, upload-time = "2024-09-03T00:04:42.592Z" },
{ url = "https://files.pythonhosted.org/packages/a9/e6/cbfeaec2f2cacb1b30c9c71252a0660e0e4d5bbe57ba4789d5949157d2a2/uvloop-0.21.0b1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b3ac2b88f32612f7c4d792b3ed9b63eed414a1e85e004881a6ff08031c4ecf6c", size = 3800663, upload-time = "2024-09-03T00:04:44.523Z" },
{ url = "https://files.pythonhosted.org/packages/41/58/113611cee5a47023d70bd4310e4a54a49b91e9f0214e801dc7f5dcd77eb1/uvloop-0.21.0b1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a156feb70518fd4d748209726463adf92d4dde895a137442956c66d6d3867fb8", size = 1447462, upload-time = "2024-09-03T00:04:46.128Z" },
{ url = "https://files.pythonhosted.org/packages/ac/0c/be081409798b7601788879646f4dab5794f54e19b38654257657ba1363dc/uvloop-0.21.0b1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:115c90a7ef29375104b153e474c7fdf1c2bbd409f0c13ecaa823ed92b2c145e7", size = 805502, upload-time = "2024-09-03T00:04:47.326Z" },
{ url = "https://files.pythonhosted.org/packages/38/e8/158fbbef8ddd7cddb8a0b8e6351c0d208284bc101e5f9ab8c9c76fd70550/uvloop-0.21.0b1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79d0b7c1c1a98282ad3384bc4cf4f199431efa3f4e5eeda6785cb902703c9691", size = 3960996, upload-time = "2024-09-03T00:04:48.556Z" },
{ url = "https://files.pythonhosted.org/packages/ee/7e/840749f44fd277ee45f15773dc551e4119ac3ebb5601cfd7dce6c7ac0941/uvloop-0.21.0b1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:586c229730e74308763147195d908e7568c0769d05bafc132f4faaf655f6cffe", size = 3973317, upload-time = "2024-09-03T00:04:50.58Z" },
{ url = "https://files.pythonhosted.org/packages/2e/c7/49bba193c023ae4987fb05d90ae023f9e9da33535f74009159f8e77fc873/uvloop-0.21.0b1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:bcddc39a94971bb5b8c76f243a8b467f7b69674bd25531b85b4d25d5917dd52f", size = 3820394, upload-time = "2024-09-03T00:04:52.227Z" },
{ url = "https://files.pythonhosted.org/packages/34/30/e501868d7e46aeebe40fdf679c866a908c395a1ef2801777977b8c794585/uvloop-0.21.0b1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6c0332893fa201a60c4db7d6d296b131eb91793a062cfc9845bdcdab9cc6c22a", size = 3937456, upload-time = "2024-09-03T00:04:54.295Z" },
{ url = "https://files.pythonhosted.org/packages/a2/12/eb875804e318cf2b62958cc73830646354d30422d7766148898d7268b3d9/uvloop-0.21.0b1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:ea815a3046d31e3a88c09c13d46956f9b872a6951dd7ddee02ac8e3aa642a2de", size = 1471491, upload-time = "2024-09-03T00:04:56.203Z" },
{ url = "https://files.pythonhosted.org/packages/ae/4a/55aba98b01712e2074d0c4e8a8d4a9e17586ade0882609ba24af52c71393/uvloop-0.21.0b1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cb788e15561dab81f5c562fb2496926a1b8b47d8ff1986d9b37acfa98b37faa9", size = 821594, upload-time = "2024-09-03T00:04:58.427Z" },
{ url = "https://files.pythonhosted.org/packages/07/d4/fb855a16886212ad90acdad44442f08b278deeb870f9081626723df12f93/uvloop-0.21.0b1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0029380131aae418f4034520d853c85880d049eb1232214fda209a40a41c806c", size = 4580223, upload-time = "2024-09-03T00:05:00.134Z" },
{ url = "https://files.pythonhosted.org/packages/b1/19/8e0185567b072627ec9c103c7ec3abe002d03344d813ac8d79753de0adb9/uvloop-0.21.0b1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d692df286fe1df2659c2e26e1d4e582b02bf32847e675f7e6a770cc107ca4987", size = 4693904, upload-time = "2024-09-03T00:05:01.736Z" },
{ url = "https://files.pythonhosted.org/packages/d6/7b/79aba40e0850018fc575fd2289fd724e846231b66adbf7df080b7e62339e/uvloop-0.21.0b1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:19641b992c05a47169cc655b7fbe4628dd5f29cafc910ce87dbd1702609d3bb1", size = 4451455, upload-time = "2024-09-03T00:05:03.137Z" },
{ url = "https://files.pythonhosted.org/packages/9c/b7/9bf50763d2ea33b6db33d4d4d2ba792d326e217c2a9d7c749480f9c1b536/uvloop-0.21.0b1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:61b1c1d32df0a1ed0c8dca000ed15bab59e008349787d1d21b2a9d21ac7e5c8a", size = 4659154, upload-time = "2024-09-03T00:05:06.316Z" },
{ url = "https://files.pythonhosted.org/packages/22/4b/b307b11ac3367cd8f5fd31614a2fa314d9ee639a71c435c79c9681a447d7/uvloop-0.21.0b1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:51f9ce02856cec8c7346875e40068b58fdf9c1f5326dbdf342c751abbcff40df", size = 1468145, upload-time = "2024-09-03T00:05:07.775Z" },
{ url = "https://files.pythonhosted.org/packages/71/46/ef3cc31b1bce230879aa7fb164584b8101a882ff22503b666184c92ce130/uvloop-0.21.0b1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7fbd38cf672c6477ccd5d034a6c25db7fdb7ef3964f82d209cde41c9a2dfe09b", size = 819354, upload-time = "2024-09-03T00:05:09.066Z" },
{ url = "https://files.pythonhosted.org/packages/94/80/20f933576d95bcc0eb4461b3ab7d7e3b63e69f69b4c83479a923ab9e612f/uvloop-0.21.0b1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d2c4ae86218435cd76cb2f556433281923e15c22417d4ecb2f464325ed0dde3", size = 4583158, upload-time = "2024-09-03T00:05:10.398Z" },
{ url = "https://files.pythonhosted.org/packages/2c/a0/a70bab5bb54e6a5b2efab475e36aad6d1ffcbb2e31cb5132cba459f2e3e0/uvloop-0.21.0b1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea6c55bbbdbf6cb7bc3693aa52d93c5efb4ded5be903b7faf0eb08e57f8dbfd5", size = 4701180, upload-time = "2024-09-03T00:05:11.91Z" },
{ url = "https://files.pythonhosted.org/packages/f9/78/3734fd63b1ae4c994af546fe4418b2c0af7b272cd0294bf5aa99bbf1b57f/uvloop-0.21.0b1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c5038ebc2f436398a153926db21d235ce75b050450af6bad17faee6336f6ef0b", size = 4454595, upload-time = "2024-09-03T00:05:13.764Z" },
{ url = "https://files.pythonhosted.org/packages/b3/ff/0d7cb5bce39f624a0aa8f2945cd52f4f946b1ca4aea8ef112c8c785649b1/uvloop-0.21.0b1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6af42e66212598a507879518f1fa8f13a489d52285e3715d1b4c91bcc70dd0ff", size = 4660273, upload-time = "2024-09-03T00:05:15.506Z" },
{ url = "https://files.pythonhosted.org/packages/eb/14/ecceb239b65adaaf7fde510aa8bd534075695d1e5f8dadfa32b5723d9cfb/uvloop-0.22.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ef6f0d4cc8a9fa1f6a910230cd53545d9a14479311e87e3cb225495952eb672c", size = 1343335, upload-time = "2025-10-16T22:16:11.43Z" },
{ url = "https://files.pythonhosted.org/packages/ba/ae/6f6f9af7f590b319c94532b9567409ba11f4fa71af1148cab1bf48a07048/uvloop-0.22.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7cd375a12b71d33d46af85a3343b35d98e8116134ba404bd657b3b1d15988792", size = 742903, upload-time = "2025-10-16T22:16:12.979Z" },
{ url = "https://files.pythonhosted.org/packages/09/bd/3667151ad0702282a1f4d5d29288fce8a13c8b6858bf0978c219cd52b231/uvloop-0.22.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ac33ed96229b7790eb729702751c0e93ac5bc3bcf52ae9eccbff30da09194b86", size = 3648499, upload-time = "2025-10-16T22:16:14.451Z" },
{ url = "https://files.pythonhosted.org/packages/b3/f6/21657bb3beb5f8c57ce8be3b83f653dd7933c2fd00545ed1b092d464799a/uvloop-0.22.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:481c990a7abe2c6f4fc3d98781cc9426ebd7f03a9aaa7eb03d3bfc68ac2a46bd", size = 3700133, upload-time = "2025-10-16T22:16:16.272Z" },
{ url = "https://files.pythonhosted.org/packages/09/e0/604f61d004ded805f24974c87ddd8374ef675644f476f01f1df90e4cdf72/uvloop-0.22.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a592b043a47ad17911add5fbd087c76716d7c9ccc1d64ec9249ceafd735f03c2", size = 3512681, upload-time = "2025-10-16T22:16:18.07Z" },
{ url = "https://files.pythonhosted.org/packages/bb/ce/8491fd370b0230deb5eac69c7aae35b3be527e25a911c0acdffb922dc1cd/uvloop-0.22.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1489cf791aa7b6e8c8be1c5a080bae3a672791fcb4e9e12249b05862a2ca9cec", size = 3615261, upload-time = "2025-10-16T22:16:19.596Z" },
{ url = "https://files.pythonhosted.org/packages/c7/d5/69900f7883235562f1f50d8184bb7dd84a2fb61e9ec63f3782546fdbd057/uvloop-0.22.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c60ebcd36f7b240b30788554b6f0782454826a0ed765d8430652621b5de674b9", size = 1352420, upload-time = "2025-10-16T22:16:21.187Z" },
{ url = "https://files.pythonhosted.org/packages/a8/73/c4e271b3bce59724e291465cc936c37758886a4868787da0278b3b56b905/uvloop-0.22.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3b7f102bf3cb1995cfeaee9321105e8f5da76fdb104cdad8986f85461a1b7b77", size = 748677, upload-time = "2025-10-16T22:16:22.558Z" },
{ url = "https://files.pythonhosted.org/packages/86/94/9fb7fad2f824d25f8ecac0d70b94d0d48107ad5ece03769a9c543444f78a/uvloop-0.22.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:53c85520781d84a4b8b230e24a5af5b0778efdb39142b424990ff1ef7c48ba21", size = 3753819, upload-time = "2025-10-16T22:16:23.903Z" },
{ url = "https://files.pythonhosted.org/packages/74/4f/256aca690709e9b008b7108bc85fba619a2bc37c6d80743d18abad16ee09/uvloop-0.22.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:56a2d1fae65fd82197cb8c53c367310b3eabe1bbb9fb5a04d28e3e3520e4f702", size = 3804529, upload-time = "2025-10-16T22:16:25.246Z" },
{ url = "https://files.pythonhosted.org/packages/7f/74/03c05ae4737e871923d21a76fe28b6aad57f5c03b6e6bfcfa5ad616013e4/uvloop-0.22.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:40631b049d5972c6755b06d0bfe8233b1bd9a8a6392d9d1c45c10b6f9e9b2733", size = 3621267, upload-time = "2025-10-16T22:16:26.819Z" },
{ url = "https://files.pythonhosted.org/packages/75/be/f8e590fe61d18b4a92070905497aec4c0e64ae1761498cad09023f3f4b3e/uvloop-0.22.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:535cc37b3a04f6cd2c1ef65fa1d370c9a35b6695df735fcff5427323f2cd5473", size = 3723105, upload-time = "2025-10-16T22:16:28.252Z" },
{ url = "https://files.pythonhosted.org/packages/3d/ff/7f72e8170be527b4977b033239a83a68d5c881cc4775fca255c677f7ac5d/uvloop-0.22.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:fe94b4564e865d968414598eea1a6de60adba0c040ba4ed05ac1300de402cd42", size = 1359936, upload-time = "2025-10-16T22:16:29.436Z" },
{ url = "https://files.pythonhosted.org/packages/c3/c6/e5d433f88fd54d81ef4be58b2b7b0cea13c442454a1db703a1eea0db1a59/uvloop-0.22.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:51eb9bd88391483410daad430813d982010f9c9c89512321f5b60e2cddbdddd6", size = 752769, upload-time = "2025-10-16T22:16:30.493Z" },
{ url = "https://files.pythonhosted.org/packages/24/68/a6ac446820273e71aa762fa21cdcc09861edd3536ff47c5cd3b7afb10eeb/uvloop-0.22.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:700e674a166ca5778255e0e1dc4e9d79ab2acc57b9171b79e65feba7184b3370", size = 4317413, upload-time = "2025-10-16T22:16:31.644Z" },
{ url = "https://files.pythonhosted.org/packages/5f/6f/e62b4dfc7ad6518e7eff2516f680d02a0f6eb62c0c212e152ca708a0085e/uvloop-0.22.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7b5b1ac819a3f946d3b2ee07f09149578ae76066d70b44df3fa990add49a82e4", size = 4426307, upload-time = "2025-10-16T22:16:32.917Z" },
{ url = "https://files.pythonhosted.org/packages/90/60/97362554ac21e20e81bcef1150cb2a7e4ffdaf8ea1e5b2e8bf7a053caa18/uvloop-0.22.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e047cc068570bac9866237739607d1313b9253c3051ad84738cbb095be0537b2", size = 4131970, upload-time = "2025-10-16T22:16:34.015Z" },
{ url = "https://files.pythonhosted.org/packages/99/39/6b3f7d234ba3964c428a6e40006340f53ba37993f46ed6e111c6e9141d18/uvloop-0.22.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:512fec6815e2dd45161054592441ef76c830eddaad55c8aa30952e6fe1ed07c0", size = 4296343, upload-time = "2025-10-16T22:16:35.149Z" },
{ url = "https://files.pythonhosted.org/packages/89/8c/182a2a593195bfd39842ea68ebc084e20c850806117213f5a299dfc513d9/uvloop-0.22.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:561577354eb94200d75aca23fbde86ee11be36b00e52a4eaf8f50fb0c86b7705", size = 1358611, upload-time = "2025-10-16T22:16:36.833Z" },
{ url = "https://files.pythonhosted.org/packages/d2/14/e301ee96a6dc95224b6f1162cd3312f6d1217be3907b79173b06785f2fe7/uvloop-0.22.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1cdf5192ab3e674ca26da2eada35b288d2fa49fdd0f357a19f0e7c4e7d5077c8", size = 751811, upload-time = "2025-10-16T22:16:38.275Z" },
{ url = "https://files.pythonhosted.org/packages/b7/02/654426ce265ac19e2980bfd9ea6590ca96a56f10c76e63801a2df01c0486/uvloop-0.22.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e2ea3d6190a2968f4a14a23019d3b16870dd2190cd69c8180f7c632d21de68d", size = 4288562, upload-time = "2025-10-16T22:16:39.375Z" },
{ url = "https://files.pythonhosted.org/packages/15/c0/0be24758891ef825f2065cd5db8741aaddabe3e248ee6acc5e8a80f04005/uvloop-0.22.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0530a5fbad9c9e4ee3f2b33b148c6a64d47bbad8000ea63704fa8260f4cf728e", size = 4366890, upload-time = "2025-10-16T22:16:40.547Z" },
{ url = "https://files.pythonhosted.org/packages/d2/53/8369e5219a5855869bcee5f4d317f6da0e2c669aecf0ef7d371e3d084449/uvloop-0.22.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bc5ef13bbc10b5335792360623cc378d52d7e62c2de64660616478c32cd0598e", size = 4119472, upload-time = "2025-10-16T22:16:41.694Z" },
{ url = "https://files.pythonhosted.org/packages/f8/ba/d69adbe699b768f6b29a5eec7b47dd610bd17a69de51b251126a801369ea/uvloop-0.22.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1f38ec5e3f18c8a10ded09742f7fb8de0108796eb673f30ce7762ce1b8550cad", size = 4239051, upload-time = "2025-10-16T22:16:43.224Z" },
{ url = "https://files.pythonhosted.org/packages/90/cd/b62bdeaa429758aee8de8b00ac0dd26593a9de93d302bff3d21439e9791d/uvloop-0.22.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3879b88423ec7e97cd4eba2a443aa26ed4e59b45e6b76aabf13fe2f27023a142", size = 1362067, upload-time = "2025-10-16T22:16:44.503Z" },
{ url = "https://files.pythonhosted.org/packages/0d/f8/a132124dfda0777e489ca86732e85e69afcd1ff7686647000050ba670689/uvloop-0.22.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:4baa86acedf1d62115c1dc6ad1e17134476688f08c6efd8a2ab076e815665c74", size = 752423, upload-time = "2025-10-16T22:16:45.968Z" },
{ url = "https://files.pythonhosted.org/packages/a3/94/94af78c156f88da4b3a733773ad5ba0b164393e357cc4bd0ab2e2677a7d6/uvloop-0.22.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:297c27d8003520596236bdb2335e6b3f649480bd09e00d1e3a99144b691d2a35", size = 4272437, upload-time = "2025-10-16T22:16:47.451Z" },
{ url = "https://files.pythonhosted.org/packages/b5/35/60249e9fd07b32c665192cec7af29e06c7cd96fa1d08b84f012a56a0b38e/uvloop-0.22.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c1955d5a1dd43198244d47664a5858082a3239766a839b2102a269aaff7a4e25", size = 4292101, upload-time = "2025-10-16T22:16:49.318Z" },
{ url = "https://files.pythonhosted.org/packages/02/62/67d382dfcb25d0a98ce73c11ed1a6fba5037a1a1d533dcbb7cab033a2636/uvloop-0.22.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b31dc2fccbd42adc73bc4e7cdbae4fc5086cf378979e53ca5d0301838c5682c6", size = 4114158, upload-time = "2025-10-16T22:16:50.517Z" },
{ url = "https://files.pythonhosted.org/packages/f0/7a/f1171b4a882a5d13c8b7576f348acfe6074d72eaf52cccef752f748d4a9f/uvloop-0.22.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:93f617675b2d03af4e72a5333ef89450dfaa5321303ede6e67ba9c9d26878079", size = 4177360, upload-time = "2025-10-16T22:16:52.646Z" },
{ url = "https://files.pythonhosted.org/packages/79/7b/b01414f31546caf0919da80ad57cbfe24c56b151d12af68cee1b04922ca8/uvloop-0.22.1-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:37554f70528f60cad66945b885eb01f1bb514f132d92b6eeed1c90fd54ed6289", size = 1454790, upload-time = "2025-10-16T22:16:54.355Z" },
{ url = "https://files.pythonhosted.org/packages/d4/31/0bb232318dd838cad3fa8fb0c68c8b40e1145b32025581975e18b11fab40/uvloop-0.22.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:b76324e2dc033a0b2f435f33eb88ff9913c156ef78e153fb210e03c13da746b3", size = 796783, upload-time = "2025-10-16T22:16:55.906Z" },
{ url = "https://files.pythonhosted.org/packages/42/38/c9b09f3271a7a723a5de69f8e237ab8e7803183131bc57c890db0b6bb872/uvloop-0.22.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:badb4d8e58ee08dad957002027830d5c3b06aea446a6a3744483c2b3b745345c", size = 4647548, upload-time = "2025-10-16T22:16:57.008Z" },
{ url = "https://files.pythonhosted.org/packages/c1/37/945b4ca0ac27e3dc4952642d4c900edd030b3da6c9634875af6e13ae80e5/uvloop-0.22.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b91328c72635f6f9e0282e4a57da7470c7350ab1c9f48546c0f2866205349d21", size = 4467065, upload-time = "2025-10-16T22:16:58.206Z" },
{ url = "https://files.pythonhosted.org/packages/97/cc/48d232f33d60e2e2e0b42f4e73455b146b76ebe216487e862700457fbf3c/uvloop-0.22.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:daf620c2995d193449393d6c62131b3fbd40a63bf7b307a1527856ace637fe88", size = 4328384, upload-time = "2025-10-16T22:16:59.36Z" },
{ url = "https://files.pythonhosted.org/packages/e4/16/c1fd27e9549f3c4baf1dc9c20c456cd2f822dbf8de9f463824b0c0357e06/uvloop-0.22.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6cde23eeda1a25c75b2e07d39970f3374105d5eafbaab2a4482be82f272d5a5e", size = 4296730, upload-time = "2025-10-16T22:17:00.744Z" },
]
[[package]]
@@ -308,7 +308,13 @@ def create_react_agent(
) -> CompiledStateGraph:
"""Creates an agent graph that calls tools in a loop until a stopping condition is met.
For more details on using `create_react_agent`, visit [Agents](https://langchain-ai.github.io/langgraph/agents/overview/) documentation.
!!! warning
This function is deprecated in favor of
[`create_agent`][langchain.agents.create_agent] from the `langchain`
package, which provides an equivalent agent factory with a flexible
middleware system. For migration guidance, see
[Migrating from LangGraph v0](https://docs.langchain.com/oss/python/migrate/langgraph-v1).
Args:
model: The language model for the agent. Supports static and dynamic
+11 -5
View File
@@ -922,7 +922,7 @@ class ToolNode(RunnableCallable):
raise TypeError(msg)
# Inject state, store, and runtime right before invocation
injected_call = self._inject_tool_args(call, request.runtime)
injected_call = self._inject_tool_args(call, request.runtime, tool)
call_args = {**injected_call, "type": "tool_call"}
try:
@@ -1075,7 +1075,7 @@ class ToolNode(RunnableCallable):
raise TypeError(msg)
# Inject state, store, and runtime right before invocation
injected_call = self._inject_tool_args(call, request.runtime)
injected_call = self._inject_tool_args(call, request.runtime, tool)
call_args = {**injected_call, "type": "tool_call"}
try:
@@ -1281,6 +1281,7 @@ class ToolNode(RunnableCallable):
self,
tool_call: ToolCall,
tool_runtime: ToolRuntime,
tool: BaseTool | None = None,
) -> ToolCall:
"""Inject graph state, store, and runtime into tool call arguments.
@@ -1299,6 +1300,9 @@ class ToolNode(RunnableCallable):
Must contain 'name', 'args', 'id', and 'type' fields.
tool_runtime: The ToolRuntime instance containing all runtime context
(state, config, store, context, stream_writer) to inject into tools.
tool: Optional tool instance. When provided, allows injection for
dynamically registered tools that are not in self.tools_by_name
(e.g., tools added via middleware's wrap_tool_call).
Returns:
A new ToolCall dictionary with the same structure as the input but with
@@ -1312,10 +1316,12 @@ class ToolNode(RunnableCallable):
This method is called automatically during tool execution. It should not
be called from outside the `ToolNode`.
"""
if tool_call["name"] not in self.tools_by_name:
return tool_call
injected = self._injected_args.get(tool_call["name"])
if not injected and tool is not None:
# For dynamically registered tools (e.g., added via middleware's
# wrap_tool_call), compute injected args on-the-fly since they
# were not present during ToolNode initialization.
injected = _get_all_injected_args(tool)
if not injected:
return tool_call
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project]
name = "langgraph-prebuilt"
version = "1.0.7"
version = "1.0.8"
description = "Library with high-level APIs for creating and executing LangGraph agents and tools."
authors = []
requires-python = ">=3.10"
+106
View File
@@ -1902,3 +1902,109 @@ async def test_tool_node_tool_runtime_generic() -> None:
assert tool_message.type == "tool"
assert tool_message.content == "test_info"
assert tool_message.tool_call_id == "call_1"
def test_tool_node_inject_runtime_dynamic_tool_via_wrap_tool_call() -> None:
"""Test that ToolRuntime is injected for dynamically registered tools.
Regression test for https://github.com/langchain-ai/langchain/issues/35305.
When a tool is dynamically provided via wrap_tool_call (not registered at
ToolNode init time), ToolRuntime should still be injected into the tool.
"""
@dec_tool
def static_tool(x: int) -> str:
"""A static tool registered at init."""
return f"static: {x}"
@dec_tool
def dynamic_tool_with_runtime(x: int, runtime: ToolRuntime) -> str:
"""A dynamic tool that needs ToolRuntime injection."""
return f"dynamic: x={x}, tool_call_id={runtime.tool_call_id}"
def wrap_tool_call(request, execute):
"""Middleware that swaps in a dynamic tool."""
if request.tool_call["name"] == "dynamic_tool_with_runtime":
# Override tool to the dynamic one (not registered at init)
new_request = request.override(tool=dynamic_tool_with_runtime)
return execute(new_request)
return execute(request)
# ToolNode only knows about static_tool at init time
tool_node = ToolNode(
[static_tool],
wrap_tool_call=wrap_tool_call,
)
# Verify the dynamic tool is NOT in the tool node's registered tools
assert "dynamic_tool_with_runtime" not in tool_node.tools_by_name
# Call the dynamic tool
tool_call = {
"name": "dynamic_tool_with_runtime",
"args": {"x": 42},
"id": "call_dynamic_1",
"type": "tool_call",
}
msg = AIMessage("", tool_calls=[tool_call])
result = tool_node.invoke(
{"messages": [msg]},
config=_create_config_with_runtime(),
)
# ToolRuntime should be injected and the tool should execute successfully
tool_message = result["messages"][-1]
assert tool_message.content == "dynamic: x=42, tool_call_id=call_dynamic_1"
assert tool_message.tool_call_id == "call_dynamic_1"
async def test_tool_node_inject_runtime_dynamic_tool_via_wrap_tool_call_async() -> None:
"""Test that ToolRuntime is injected for dynamically registered tools (async).
Async version of the regression test for
https://github.com/langchain-ai/langchain/issues/35305.
"""
@dec_tool
def static_tool(x: int) -> str:
"""A static tool registered at init."""
return f"static: {x}"
@dec_tool
async def dynamic_tool_with_runtime(x: int, runtime: ToolRuntime) -> str:
"""A dynamic async tool that needs ToolRuntime injection."""
return f"dynamic: x={x}, tool_call_id={runtime.tool_call_id}"
async def awrap_tool_call(request, execute):
"""Async middleware that swaps in a dynamic tool."""
if request.tool_call["name"] == "dynamic_tool_with_runtime":
new_request = request.override(tool=dynamic_tool_with_runtime)
return await execute(new_request)
return await execute(request)
# ToolNode only knows about static_tool at init time
tool_node = ToolNode(
[static_tool],
awrap_tool_call=awrap_tool_call,
)
# Verify the dynamic tool is NOT in the tool node's registered tools
assert "dynamic_tool_with_runtime" not in tool_node.tools_by_name
# Call the dynamic tool
tool_call = {
"name": "dynamic_tool_with_runtime",
"args": {"x": 42},
"id": "call_dynamic_2",
"type": "tool_call",
}
msg = AIMessage("", tool_calls=[tool_call])
result = await tool_node.ainvoke(
{"messages": [msg]},
config=_create_config_with_runtime(),
)
# ToolRuntime should be injected and the tool should execute successfully
tool_message = result["messages"][-1]
assert tool_message.content == "dynamic: x=42, tool_call_id=call_dynamic_2"
assert tool_message.tool_call_id == "call_dynamic_2"
+38 -38
View File
@@ -249,7 +249,7 @@ wheels = [
[[package]]
name = "langchain-core"
version = "1.2.7"
version = "1.2.13"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "jsonpatch" },
@@ -261,14 +261,14 @@ dependencies = [
{ name = "typing-extensions" },
{ name = "uuid-utils" },
]
sdist = { url = "https://files.pythonhosted.org/packages/a2/0e/664d8d81b3493e09cbab72448d2f9d693d1fa5aa2bcc488602203a9b6da0/langchain_core-1.2.7.tar.gz", hash = "sha256:e1460639f96c352b4a41c375f25aeb8d16ffc1769499fb1c20503aad59305ced", size = 837039, upload-time = "2026-01-09T17:44:25.505Z" }
sdist = { url = "https://files.pythonhosted.org/packages/fb/bb/c501ca60556c11ac80d1454bdcac63cb33583ce4e64fc4535ad5a7d5c6ba/langchain_core-1.2.13.tar.gz", hash = "sha256:d2773d0d0130a356378db9a858cfeef64c3d64bc03722f1d4d6c40eb46fdf01b", size = 831612, upload-time = "2026-02-15T07:45:57.014Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/6e/6f/34a9fba14d191a67f7e2ee3dbce3e9b86d2fa7310e2c7f2c713583481bd2/langchain_core-1.2.7-py3-none-any.whl", hash = "sha256:452f4fef7a3d883357b22600788d37e3d8854ef29da345b7ac7099f33c31828b", size = 490232, upload-time = "2026-01-09T17:44:24.236Z" },
{ url = "https://files.pythonhosted.org/packages/12/ab/60fd69e5d55f67d422baefddaaca523c42cd7510ab6aeb17db6ae57fb107/langchain_core-1.2.13-py3-none-any.whl", hash = "sha256:b31823e28d3eff1e237096d0bd3bf80c6f9624eb471a9496dbfbd427779f8d82", size = 500485, upload-time = "2026-02-15T07:45:55.422Z" },
]
[[package]]
name = "langgraph"
version = "1.0.7"
version = "1.0.9"
source = { editable = "../langgraph" }
dependencies = [
{ name = "langchain-core" },
@@ -317,7 +317,7 @@ dev = [
{ name = "ruff" },
{ name = "syrupy" },
{ name = "types-requests" },
{ name = "uvloop", specifier = "==0.21.0b1" },
{ name = "uvloop", specifier = "==0.22.1" },
]
lint = [
{ name = "mypy" },
@@ -347,7 +347,7 @@ test = [
{ name = "pytest-xdist", extras = ["psutil"] },
{ name = "redis" },
{ name = "syrupy" },
{ name = "uvloop", specifier = "==0.21.0b1" },
{ name = "uvloop", specifier = "==0.22.1" },
]
[[package]]
@@ -411,7 +411,7 @@ dependencies = [
[package.metadata]
requires-dist = [
{ name = "langgraph-checkpoint", editable = "../checkpoint" },
{ name = "orjson", specifier = ">=3.10.1" },
{ name = "orjson", specifier = ">=3.11.5" },
{ name = "psycopg", specifier = ">=3.2.0" },
{ name = "psycopg-pool", specifier = ">=3.2.0" },
]
@@ -489,7 +489,7 @@ test = [
[[package]]
name = "langgraph-prebuilt"
version = "1.0.7"
version = "1.0.8"
source = { editable = "." }
dependencies = [
{ name = "langchain-core" },
@@ -585,28 +585,29 @@ dependencies = [
[package.metadata]
requires-dist = [
{ name = "httpx", specifier = ">=0.25.2" },
{ name = "orjson", specifier = ">=3.10.1" },
{ name = "orjson", specifier = ">=3.11.5" },
]
[package.metadata.requires-dev]
dev = [
{ name = "codespell" },
{ name = "mypy", specifier = "==1.19.0" },
{ name = "langgraph", editable = "../langgraph" },
{ name = "mypy", specifier = "==1.19.1" },
{ name = "pydantic", specifier = ">=2.12.4" },
{ name = "pytest" },
{ name = "pytest-asyncio" },
{ name = "pytest-mock" },
{ name = "pytest-watch" },
{ name = "ruff", specifier = "==0.14.11" },
{ name = "ruff", specifier = "==0.15.1" },
{ name = "starlette" },
{ name = "ty", specifier = "==0.0.1a27" },
{ name = "ty", specifier = "==0.0.17" },
]
lint = [
{ name = "codespell" },
{ name = "mypy", specifier = "==1.19.0" },
{ name = "ruff", specifier = "==0.14.11" },
{ name = "mypy", specifier = "==1.19.1" },
{ name = "ruff", specifier = "==0.15.1" },
{ name = "starlette" },
{ name = "ty", specifier = "==0.0.1a27" },
{ name = "ty", specifier = "==0.0.17" },
]
test = [
{ name = "pytest" },
@@ -1304,28 +1305,27 @@ wheels = [
[[package]]
name = "ruff"
version = "0.14.13"
version = "0.15.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/50/0a/1914efb7903174b381ee2ffeebb4253e729de57f114e63595114c8ca451f/ruff-0.14.13.tar.gz", hash = "sha256:83cd6c0763190784b99650a20fec7633c59f6ebe41c5cc9d45ee42749563ad47", size = 6059504, upload-time = "2026-01-15T20:15:16.918Z" }
sdist = { url = "https://files.pythonhosted.org/packages/04/dc/4e6ac71b511b141cf626357a3946679abeba4cf67bc7cc5a17920f31e10d/ruff-0.15.1.tar.gz", hash = "sha256:c590fe13fb57c97141ae975c03a1aedb3d3156030cabd740d6ff0b0d601e203f", size = 4540855, upload-time = "2026-02-12T23:09:09.998Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c3/ae/0deefbc65ca74b0ab1fd3917f94dc3b398233346a74b8bbb0a916a1a6bf6/ruff-0.14.13-py3-none-linux_armv6l.whl", hash = "sha256:76f62c62cd37c276cb03a275b198c7c15bd1d60c989f944db08a8c1c2dbec18b", size = 13062418, upload-time = "2026-01-15T20:14:50.779Z" },
{ url = "https://files.pythonhosted.org/packages/47/df/5916604faa530a97a3c154c62a81cb6b735c0cb05d1e26d5ad0f0c8ac48a/ruff-0.14.13-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:914a8023ece0528d5cc33f5a684f5f38199bbb566a04815c2c211d8f40b5d0ed", size = 13442344, upload-time = "2026-01-15T20:15:07.94Z" },
{ url = "https://files.pythonhosted.org/packages/4c/f3/e0e694dd69163c3a1671e102aa574a50357536f18a33375050334d5cd517/ruff-0.14.13-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d24899478c35ebfa730597a4a775d430ad0d5631b8647a3ab368c29b7e7bd063", size = 12354720, upload-time = "2026-01-15T20:15:09.854Z" },
{ url = "https://files.pythonhosted.org/packages/c3/e8/67f5fcbbaee25e8fc3b56cc33e9892eca7ffe09f773c8e5907757a7e3bdb/ruff-0.14.13-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9aaf3870f14d925bbaf18b8a2347ee0ae7d95a2e490e4d4aea6813ed15ebc80e", size = 12774493, upload-time = "2026-01-15T20:15:20.908Z" },
{ url = "https://files.pythonhosted.org/packages/6b/ce/d2e9cb510870b52a9565d885c0d7668cc050e30fa2c8ac3fb1fda15c083d/ruff-0.14.13-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac5b7f63dd3b27cc811850f5ffd8fff845b00ad70e60b043aabf8d6ecc304e09", size = 12815174, upload-time = "2026-01-15T20:15:05.74Z" },
{ url = "https://files.pythonhosted.org/packages/88/00/c38e5da58beebcf4fa32d0ddd993b63dfacefd02ab7922614231330845bf/ruff-0.14.13-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78d2b1097750d90ba82ce4ba676e85230a0ed694178ca5e61aa9b459970b3eb9", size = 13680909, upload-time = "2026-01-15T20:15:14.537Z" },
{ url = "https://files.pythonhosted.org/packages/61/61/cd37c9dd5bd0a3099ba79b2a5899ad417d8f3b04038810b0501a80814fd7/ruff-0.14.13-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:7d0bf87705acbbcb8d4c24b2d77fbb73d40210a95c3903b443cd9e30824a5032", size = 15144215, upload-time = "2026-01-15T20:15:22.886Z" },
{ url = "https://files.pythonhosted.org/packages/56/8a/85502d7edbf98c2df7b8876f316c0157359165e16cdf98507c65c8d07d3d/ruff-0.14.13-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a3eb5da8e2c9e9f13431032fdcbe7681de9ceda5835efee3269417c13f1fed5c", size = 14706067, upload-time = "2026-01-15T20:14:48.271Z" },
{ url = "https://files.pythonhosted.org/packages/7e/2f/de0df127feb2ee8c1e54354dc1179b4a23798f0866019528c938ba439aca/ruff-0.14.13-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:642442b42957093811cd8d2140dfadd19c7417030a7a68cf8d51fcdd5f217427", size = 14133916, upload-time = "2026-01-15T20:14:57.357Z" },
{ url = "https://files.pythonhosted.org/packages/0d/77/9b99686bb9fe07a757c82f6f95e555c7a47801a9305576a9c67e0a31d280/ruff-0.14.13-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4acdf009f32b46f6e8864af19cbf6841eaaed8638e65c8dac845aea0d703c841", size = 13859207, upload-time = "2026-01-15T20:14:55.111Z" },
{ url = "https://files.pythonhosted.org/packages/7d/46/2bdcb34a87a179a4d23022d818c1c236cb40e477faf0d7c9afb6813e5876/ruff-0.14.13-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:591a7f68860ea4e003917d19b5c4f5ac39ff558f162dc753a2c5de897fd5502c", size = 14043686, upload-time = "2026-01-15T20:14:52.841Z" },
{ url = "https://files.pythonhosted.org/packages/1a/a9/5c6a4f56a0512c691cf143371bcf60505ed0f0860f24a85da8bd123b2bf1/ruff-0.14.13-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:774c77e841cc6e046fc3e91623ce0903d1cd07e3a36b1a9fe79b81dab3de506b", size = 12663837, upload-time = "2026-01-15T20:15:18.921Z" },
{ url = "https://files.pythonhosted.org/packages/fe/bb/b920016ece7651fa7fcd335d9d199306665486694d4361547ccb19394c44/ruff-0.14.13-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:61f4e40077a1248436772bb6512db5fc4457fe4c49e7a94ea7c5088655dd21ae", size = 12805867, upload-time = "2026-01-15T20:14:59.272Z" },
{ url = "https://files.pythonhosted.org/packages/7d/b3/0bd909851e5696cd21e32a8fc25727e5f58f1934b3596975503e6e85415c/ruff-0.14.13-py3-none-musllinux_1_2_i686.whl", hash = "sha256:6d02f1428357fae9e98ac7aa94b7e966fd24151088510d32cf6f902d6c09235e", size = 13208528, upload-time = "2026-01-15T20:15:03.732Z" },
{ url = "https://files.pythonhosted.org/packages/3b/3b/e2d94cb613f6bbd5155a75cbe072813756363eba46a3f2177a1fcd0cd670/ruff-0.14.13-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e399341472ce15237be0c0ae5fbceca4b04cd9bebab1a2b2c979e015455d8f0c", size = 13929242, upload-time = "2026-01-15T20:15:11.918Z" },
{ url = "https://files.pythonhosted.org/packages/6a/c5/abd840d4132fd51a12f594934af5eba1d5d27298a6f5b5d6c3be45301caf/ruff-0.14.13-py3-none-win32.whl", hash = "sha256:ef720f529aec113968b45dfdb838ac8934e519711da53a0456038a0efecbd680", size = 12919024, upload-time = "2026-01-15T20:14:43.647Z" },
{ url = "https://files.pythonhosted.org/packages/c2/55/6384b0b8ce731b6e2ade2b5449bf07c0e4c31e8a2e68ea65b3bafadcecc5/ruff-0.14.13-py3-none-win_amd64.whl", hash = "sha256:6070bd026e409734b9257e03e3ef18c6e1a216f0435c6751d7a8ec69cb59abef", size = 14097887, upload-time = "2026-01-15T20:15:01.48Z" },
{ url = "https://files.pythonhosted.org/packages/4d/e1/7348090988095e4e39560cfc2f7555b1b2a7357deba19167b600fdf5215d/ruff-0.14.13-py3-none-win_arm64.whl", hash = "sha256:7ab819e14f1ad9fe39f246cfcc435880ef7a9390d81a2b6ac7e01039083dd247", size = 13080224, upload-time = "2026-01-15T20:14:45.853Z" },
{ url = "https://files.pythonhosted.org/packages/23/bf/e6e4324238c17f9d9120a9d60aa99a7daaa21204c07fcd84e2ef03bb5fd1/ruff-0.15.1-py3-none-linux_armv6l.whl", hash = "sha256:b101ed7cf4615bda6ffe65bdb59f964e9f4a0d3f85cbf0e54f0ab76d7b90228a", size = 10367819, upload-time = "2026-02-12T23:09:03.598Z" },
{ url = "https://files.pythonhosted.org/packages/b3/ea/c8f89d32e7912269d38c58f3649e453ac32c528f93bb7f4219258be2e7ed/ruff-0.15.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:939c995e9277e63ea632cc8d3fae17aa758526f49a9a850d2e7e758bfef46602", size = 10798618, upload-time = "2026-02-12T23:09:22.928Z" },
{ url = "https://files.pythonhosted.org/packages/5e/0f/1d0d88bc862624247d82c20c10d4c0f6bb2f346559d8af281674cf327f15/ruff-0.15.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1d83466455fdefe60b8d9c8df81d3c1bbb2115cede53549d3b522ce2bc703899", size = 10148518, upload-time = "2026-02-12T23:08:58.339Z" },
{ url = "https://files.pythonhosted.org/packages/f5/c8/291c49cefaa4a9248e986256df2ade7add79388fe179e0691be06fae6f37/ruff-0.15.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9457e3c3291024866222b96108ab2d8265b477e5b1534c7ddb1810904858d16", size = 10518811, upload-time = "2026-02-12T23:09:31.865Z" },
{ url = "https://files.pythonhosted.org/packages/c3/1a/f5707440e5ae43ffa5365cac8bbb91e9665f4a883f560893829cf16a606b/ruff-0.15.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:92c92b003e9d4f7fbd33b1867bb15a1b785b1735069108dfc23821ba045b29bc", size = 10196169, upload-time = "2026-02-12T23:09:17.306Z" },
{ url = "https://files.pythonhosted.org/packages/2a/ff/26ddc8c4da04c8fd3ee65a89c9fb99eaa5c30394269d424461467be2271f/ruff-0.15.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fe5c41ab43e3a06778844c586251eb5a510f67125427625f9eb2b9526535779", size = 10990491, upload-time = "2026-02-12T23:09:25.503Z" },
{ url = "https://files.pythonhosted.org/packages/fc/00/50920cb385b89413f7cdb4bb9bc8fc59c1b0f30028d8bccc294189a54955/ruff-0.15.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66a6dd6df4d80dc382c6484f8ce1bcceb55c32e9f27a8b94c32f6c7331bf14fb", size = 11843280, upload-time = "2026-02-12T23:09:19.88Z" },
{ url = "https://files.pythonhosted.org/packages/5d/6d/2f5cad8380caf5632a15460c323ae326f1e1a2b5b90a6ee7519017a017ca/ruff-0.15.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6a4a42cbb8af0bda9bcd7606b064d7c0bc311a88d141d02f78920be6acb5aa83", size = 11274336, upload-time = "2026-02-12T23:09:14.907Z" },
{ url = "https://files.pythonhosted.org/packages/a3/1d/5f56cae1d6c40b8a318513599b35ea4b075d7dc1cd1d04449578c29d1d75/ruff-0.15.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ab064052c31dddada35079901592dfba2e05f5b1e43af3954aafcbc1096a5b2", size = 11137288, upload-time = "2026-02-12T23:09:07.475Z" },
{ url = "https://files.pythonhosted.org/packages/cd/20/6f8d7d8f768c93b0382b33b9306b3b999918816da46537d5a61635514635/ruff-0.15.1-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:5631c940fe9fe91f817a4c2ea4e81f47bee3ca4aa646134a24374f3c19ad9454", size = 11070681, upload-time = "2026-02-12T23:08:55.43Z" },
{ url = "https://files.pythonhosted.org/packages/9a/67/d640ac76069f64cdea59dba02af2e00b1fa30e2103c7f8d049c0cff4cafd/ruff-0.15.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:68138a4ba184b4691ccdc39f7795c66b3c68160c586519e7e8444cf5a53e1b4c", size = 10486401, upload-time = "2026-02-12T23:09:27.927Z" },
{ url = "https://files.pythonhosted.org/packages/65/3d/e1429f64a3ff89297497916b88c32a5cc88eeca7e9c787072d0e7f1d3e1e/ruff-0.15.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:518f9af03bfc33c03bdb4cb63fabc935341bb7f54af500f92ac309ecfbba6330", size = 10197452, upload-time = "2026-02-12T23:09:12.147Z" },
{ url = "https://files.pythonhosted.org/packages/78/83/e2c3bade17dad63bf1e1c2ffaf11490603b760be149e1419b07049b36ef2/ruff-0.15.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:da79f4d6a826caaea95de0237a67e33b81e6ec2e25fc7e1993a4015dffca7c61", size = 10693900, upload-time = "2026-02-12T23:09:34.418Z" },
{ url = "https://files.pythonhosted.org/packages/a1/27/fdc0e11a813e6338e0706e8b39bb7a1d61ea5b36873b351acee7e524a72a/ruff-0.15.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:3dd86dccb83cd7d4dcfac303ffc277e6048600dfc22e38158afa208e8bf94a1f", size = 11227302, upload-time = "2026-02-12T23:09:36.536Z" },
{ url = "https://files.pythonhosted.org/packages/f6/58/ac864a75067dcbd3b95be5ab4eb2b601d7fbc3d3d736a27e391a4f92a5c1/ruff-0.15.1-py3-none-win32.whl", hash = "sha256:660975d9cb49b5d5278b12b03bb9951d554543a90b74ed5d366b20e2c57c2098", size = 10462555, upload-time = "2026-02-12T23:09:29.899Z" },
{ url = "https://files.pythonhosted.org/packages/e0/5e/d4ccc8a27ecdb78116feac4935dfc39d1304536f4296168f91ed3ec00cd2/ruff-0.15.1-py3-none-win_amd64.whl", hash = "sha256:c820fef9dd5d4172a6570e5721704a96c6679b80cf7be41659ed439653f62336", size = 11599956, upload-time = "2026-02-12T23:09:01.157Z" },
{ url = "https://files.pythonhosted.org/packages/2a/07/5bda6a85b220c64c65686bc85bd0bbb23b29c62b3a9f9433fa55f17cda93/ruff-0.15.1-py3-none-win_arm64.whl", hash = "sha256:5ff7d5f0f88567850f45081fac8f4ec212be8d0b963e385c3f7d0d2eb4899416", size = 10874604, upload-time = "2026-02-12T23:09:05.515Z" },
]
[[package]]
@@ -1342,14 +1342,14 @@ wheels = [
[[package]]
name = "syrupy"
version = "5.0.0"
version = "5.1.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pytest" },
]
sdist = { url = "https://files.pythonhosted.org/packages/c1/90/1a442d21527009d4b40f37fe50b606ebb68a6407142c2b5cc508c34b696b/syrupy-5.0.0.tar.gz", hash = "sha256:3282fe963fa5d4d3e47231b16d1d4d0f4523705e8199eeb99a22a1bc9f5942f2", size = 48881, upload-time = "2025-09-28T21:15:12.783Z" }
sdist = { url = "https://files.pythonhosted.org/packages/2e/b0/24bca682d6a6337854be37f242d116cceeda9942571d5804c44bc1bdd427/syrupy-5.1.0.tar.gz", hash = "sha256:df543c7aa50d3cf1246e83d58fe490afe5f7dab7b41e74ecc0d8d23ae19bd4b8", size = 50495, upload-time = "2026-01-25T14:53:06.2Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/9d/9a/6c68aad2ccfce6e2eeebbf5bb709d0240592eb51ff142ec4c8fbf3c2460a/syrupy-5.0.0-py3-none-any.whl", hash = "sha256:c848e1a980ca52a28715cd2d2b4d434db424699c05653bd1158fb31cf56e9546", size = 49087, upload-time = "2025-09-28T21:15:11.639Z" },
{ url = "https://files.pythonhosted.org/packages/de/70/cf880c3b95a6034ef673e74b369941b42315c01f1554a5637a4f8b911009/syrupy-5.1.0-py3-none-any.whl", hash = "sha256:95162d2b05e61ed3e13f117b88dfab7c58bd6f90e66ebbf918e8a77114ad51c5", size = 51658, upload-time = "2026-01-25T14:53:05.105Z" },
]
[[package]]
+1 -1
View File
@@ -3,6 +3,6 @@ from langgraph_sdk.client import get_client, get_sync_client
from langgraph_sdk.encryption import Encryption
from langgraph_sdk.encryption.types import EncryptionContext
__version__ = "0.3.4"
__version__ = "0.3.7"
__all__ = ["Auth", "Encryption", "EncryptionContext", "get_client", "get_sync_client"]
@@ -0,0 +1,20 @@
"""Async client exports."""
from langgraph_sdk._async.assistants import AssistantsClient
from langgraph_sdk._async.client import LangGraphClient, get_client
from langgraph_sdk._async.cron import CronClient
from langgraph_sdk._async.http import HttpClient
from langgraph_sdk._async.runs import RunsClient
from langgraph_sdk._async.store import StoreClient
from langgraph_sdk._async.threads import ThreadsClient
__all__ = [
"AssistantsClient",
"CronClient",
"HttpClient",
"LangGraphClient",
"RunsClient",
"StoreClient",
"ThreadsClient",
"get_client",
]
@@ -0,0 +1,733 @@
"""Async client for managing assistants in LangGraph."""
from __future__ import annotations
from collections.abc import Mapping
from typing import Any, Literal, cast, overload
import httpx
from langgraph_sdk._async.http import HttpClient
from langgraph_sdk.schema import (
Assistant,
AssistantSelectField,
AssistantSortBy,
AssistantsSearchResponse,
AssistantVersion,
Config,
Context,
GraphSchema,
Json,
OnConflictBehavior,
QueryParamTypes,
SortOrder,
Subgraphs,
)
class AssistantsClient:
"""Client for managing assistants in LangGraph.
This class provides methods to interact with assistants,
which are versioned configurations of your graph.
???+ example "Example"
```python
client = get_client(url="http://localhost:2024")
assistant = await client.assistants.get("assistant_id_123")
```
"""
def __init__(self, http: HttpClient) -> None:
self.http = http
async def get(
self,
assistant_id: str,
*,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> Assistant:
"""Get an assistant by ID.
Args:
assistant_id: The ID of the assistant to get.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
Assistant: Assistant Object.
???+ example "Example Usage"
```python
assistant = await client.assistants.get(
assistant_id="my_assistant_id"
)
print(assistant)
```
```shell
----------------------------------------------------
{
'assistant_id': 'my_assistant_id',
'graph_id': 'agent',
'created_at': '2024-06-25T17:10:33.109781+00:00',
'updated_at': '2024-06-25T17:10:33.109781+00:00',
'config': {},
'metadata': {'created_by': 'system'},
'version': 1,
'name': 'my_assistant'
}
```
"""
return await self.http.get(
f"/assistants/{assistant_id}", headers=headers, params=params
)
async def get_graph(
self,
assistant_id: str,
*,
xray: int | bool = False,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> dict[str, list[dict[str, Any]]]:
"""Get the graph of an assistant by ID.
Args:
assistant_id: The ID of the assistant to get the graph of.
xray: Include graph representation of subgraphs. If an integer value is provided, only subgraphs with a depth less than or equal to the value will be included.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
Graph: The graph information for the assistant in JSON format.
???+ example "Example Usage"
```python
client = get_client(url="http://localhost:2024")
graph_info = await client.assistants.get_graph(
assistant_id="my_assistant_id"
)
print(graph_info)
```
```shell
--------------------------------------------------------------------------------------------------------------------------
{
'nodes':
[
{'id': '__start__', 'type': 'schema', 'data': '__start__'},
{'id': '__end__', 'type': 'schema', 'data': '__end__'},
{'id': 'agent','type': 'runnable','data': {'id': ['langgraph', 'utils', 'RunnableCallable'],'name': 'agent'}},
],
'edges':
[
{'source': '__start__', 'target': 'agent'},
{'source': 'agent','target': '__end__'}
]
}
```
"""
query_params = {"xray": xray}
if params:
query_params.update(params)
return await self.http.get(
f"/assistants/{assistant_id}/graph", params=query_params, headers=headers
)
async def get_schemas(
self,
assistant_id: str,
*,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> GraphSchema:
"""Get the schemas of an assistant by ID.
Args:
assistant_id: The ID of the assistant to get the schema of.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
GraphSchema: The graph schema for the assistant.
???+ example "Example Usage"
```python
client = get_client(url="http://localhost:2024")
schema = await client.assistants.get_schemas(
assistant_id="my_assistant_id"
)
print(schema)
```
```shell
----------------------------------------------------------------------------------------------------------------------------
{
'graph_id': 'agent',
'state_schema':
{
'title': 'LangGraphInput',
'$ref': '#/definitions/AgentState',
'definitions':
{
'BaseMessage':
{
'title': 'BaseMessage',
'description': 'Base abstract Message class. Messages are the inputs and outputs of ChatModels.',
'type': 'object',
'properties':
{
'content':
{
'title': 'Content',
'anyOf': [
{'type': 'string'},
{'type': 'array','items': {'anyOf': [{'type': 'string'}, {'type': 'object'}]}}
]
},
'additional_kwargs':
{
'title': 'Additional Kwargs',
'type': 'object'
},
'response_metadata':
{
'title': 'Response Metadata',
'type': 'object'
},
'type':
{
'title': 'Type',
'type': 'string'
},
'name':
{
'title': 'Name',
'type': 'string'
},
'id':
{
'title': 'Id',
'type': 'string'
}
},
'required': ['content', 'type']
},
'AgentState':
{
'title': 'AgentState',
'type': 'object',
'properties':
{
'messages':
{
'title': 'Messages',
'type': 'array',
'items': {'$ref': '#/definitions/BaseMessage'}
}
},
'required': ['messages']
}
}
},
'context_schema':
{
'title': 'Context',
'type': 'object',
'properties':
{
'model_name':
{
'title': 'Model Name',
'enum': ['anthropic', 'openai'],
'type': 'string'
}
}
}
}
```
"""
return await self.http.get(
f"/assistants/{assistant_id}/schemas", headers=headers, params=params
)
async def get_subgraphs(
self,
assistant_id: str,
namespace: str | None = None,
recurse: bool = False,
*,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> Subgraphs:
"""Get the schemas of an assistant by ID.
Args:
assistant_id: The ID of the assistant to get the schema of.
namespace: Optional namespace to filter by.
recurse: Whether to recursively get subgraphs.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
Subgraphs: The graph schema for the assistant.
"""
get_params = {"recurse": recurse}
if params:
get_params = {**get_params, **dict(params)}
if namespace is not None:
return await self.http.get(
f"/assistants/{assistant_id}/subgraphs/{namespace}",
params=get_params,
headers=headers,
)
else:
return await self.http.get(
f"/assistants/{assistant_id}/subgraphs",
params=get_params,
headers=headers,
)
async def create(
self,
graph_id: str | None,
config: Config | None = None,
*,
context: Context | None = None,
metadata: Json = None,
assistant_id: str | None = None,
if_exists: OnConflictBehavior | None = None,
name: str | None = None,
headers: Mapping[str, str] | None = None,
description: str | None = None,
params: QueryParamTypes | None = None,
) -> Assistant:
"""Create a new assistant.
Useful when graph is configurable and you want to create different assistants based on different configurations.
Args:
graph_id: The ID of the graph the assistant should use. The graph ID is normally set in your langgraph.json configuration.
config: Configuration to use for the graph.
metadata: Metadata to add to assistant.
context: Static context to add to the assistant.
!!! version-added "Added in version 0.6.0"
assistant_id: Assistant ID to use, will default to a random UUID if not provided.
if_exists: How to handle duplicate creation. Defaults to 'raise' under the hood.
Must be either 'raise' (raise error if duplicate), or 'do_nothing' (return existing assistant).
name: The name of the assistant. Defaults to 'Untitled' under the hood.
headers: Optional custom headers to include with the request.
description: Optional description of the assistant.
The description field is available for langgraph-api server version>=0.0.45
params: Optional query parameters to include with the request.
Returns:
Assistant: The created assistant.
???+ example "Example Usage"
```python
client = get_client(url="http://localhost:2024")
assistant = await client.assistants.create(
graph_id="agent",
context={"model_name": "openai"},
metadata={"number":1},
assistant_id="my-assistant-id",
if_exists="do_nothing",
name="my_name"
)
```
"""
payload: dict[str, Any] = {
"graph_id": graph_id,
}
if config:
payload["config"] = config
if context:
payload["context"] = context
if metadata:
payload["metadata"] = metadata
if assistant_id:
payload["assistant_id"] = assistant_id
if if_exists:
payload["if_exists"] = if_exists
if name:
payload["name"] = name
if description:
payload["description"] = description
return await self.http.post(
"/assistants", json=payload, headers=headers, params=params
)
async def update(
self,
assistant_id: str,
*,
graph_id: str | None = None,
config: Config | None = None,
context: Context | None = None,
metadata: Json = None,
name: str | None = None,
headers: Mapping[str, str] | None = None,
description: str | None = None,
params: QueryParamTypes | None = None,
) -> Assistant:
"""Update an assistant.
Use this to point to a different graph, update the configuration, or change the metadata of an assistant.
Args:
assistant_id: Assistant to update.
graph_id: The ID of the graph the assistant should use.
The graph ID is normally set in your langgraph.json configuration. If `None`, assistant will keep pointing to same graph.
config: Configuration to use for the graph.
context: Static context to add to the assistant.
!!! version-added "Added in version 0.6.0"
metadata: Metadata to merge with existing assistant metadata.
name: The new name for the assistant.
headers: Optional custom headers to include with the request.
description: Optional description of the assistant.
The description field is available for langgraph-api server version>=0.0.45
params: Optional query parameters to include with the request.
Returns:
The updated assistant.
???+ example "Example Usage"
```python
client = get_client(url="http://localhost:2024")
assistant = await client.assistants.update(
assistant_id='e280dad7-8618-443f-87f1-8e41841c180f',
graph_id="other-graph",
context={"model_name": "anthropic"},
metadata={"number":2}
)
```
"""
payload: dict[str, Any] = {}
if graph_id:
payload["graph_id"] = graph_id
if config is not None:
payload["config"] = config
if context is not None:
payload["context"] = context
if metadata:
payload["metadata"] = metadata
if name:
payload["name"] = name
if description:
payload["description"] = description
return await self.http.patch(
f"/assistants/{assistant_id}",
json=payload,
headers=headers,
params=params,
)
async def delete(
self,
assistant_id: str,
*,
delete_threads: bool = False,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> None:
"""Delete an assistant.
Args:
assistant_id: The assistant ID to delete.
delete_threads: If true, delete all threads with `metadata.assistant_id`
matching this assistant, along with runs and checkpoints belonging to
those threads.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
`None`
???+ example "Example Usage"
```python
client = get_client(url="http://localhost:2024")
await client.assistants.delete(
assistant_id="my_assistant_id"
)
```
"""
query_params: dict[str, Any] = {}
if delete_threads:
query_params["delete_threads"] = True
if params:
query_params.update(params)
await self.http.delete(
f"/assistants/{assistant_id}",
headers=headers,
params=query_params or None,
)
@overload
async def search(
self,
*,
metadata: Json = None,
graph_id: str | None = None,
name: str | None = None,
limit: int = 10,
offset: int = 0,
sort_by: AssistantSortBy | None = None,
sort_order: SortOrder | None = None,
select: list[AssistantSelectField] | None = None,
response_format: Literal["object"],
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> AssistantsSearchResponse: ...
@overload
async def search(
self,
*,
metadata: Json = None,
graph_id: str | None = None,
name: str | None = None,
limit: int = 10,
offset: int = 0,
sort_by: AssistantSortBy | None = None,
sort_order: SortOrder | None = None,
select: list[AssistantSelectField] | None = None,
response_format: Literal["array"] = "array",
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> list[Assistant]: ...
async def search(
self,
*,
metadata: Json = None,
graph_id: str | None = None,
name: str | None = None,
limit: int = 10,
offset: int = 0,
sort_by: AssistantSortBy | None = None,
sort_order: SortOrder | None = None,
select: list[AssistantSelectField] | None = None,
response_format: Literal["array", "object"] = "array",
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> AssistantsSearchResponse | list[Assistant]:
"""Search for assistants.
Args:
metadata: Metadata to filter by. Exact match filter for each KV pair.
graph_id: The ID of the graph to filter by.
The graph ID is normally set in your langgraph.json configuration.
name: The name of the assistant to filter by.
The filtering logic will match assistants where 'name' is a substring (case insensitive) of the assistant name.
limit: The maximum number of results to return.
offset: The number of results to skip.
sort_by: The field to sort by.
sort_order: The order to sort by.
select: Specific assistant fields to include in the response.
response_format: Controls the response shape. Use `"array"` (default)
to return a bare list of assistants, or `"object"` to return
a mapping containing assistants plus pagination metadata.
Defaults to "array", though this default will be changed to "object" in a future release.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
A list of assistants (when `response_format="array"`) or a mapping
with the assistants and the next pagination cursor (when
`response_format="object"`).
???+ example "Example Usage"
```python
client = get_client(url="http://localhost:2024")
response = await client.assistants.search(
metadata = {"name":"my_name"},
graph_id="my_graph_id",
limit=5,
offset=5,
response_format="object"
)
next_cursor = response["next"]
assistants = response["assistants"]
```
"""
if response_format not in ("array", "object"):
raise ValueError(
f"response_format must be 'array' or 'object', got {response_format!r}"
)
payload: dict[str, Any] = {
"limit": limit,
"offset": offset,
}
if metadata:
payload["metadata"] = metadata
if graph_id:
payload["graph_id"] = graph_id
if name:
payload["name"] = name
if sort_by:
payload["sort_by"] = sort_by
if sort_order:
payload["sort_order"] = sort_order
if select:
payload["select"] = select
next_cursor: str | None = None
def capture_pagination(response: httpx.Response) -> None:
nonlocal next_cursor
next_cursor = response.headers.get("X-Pagination-Next")
assistants = cast(
list[Assistant],
await self.http.post(
"/assistants/search",
json=payload,
headers=headers,
params=params,
on_response=capture_pagination if response_format == "object" else None,
),
)
if response_format == "object":
return {"assistants": assistants, "next": next_cursor}
return assistants
async def count(
self,
*,
metadata: Json = None,
graph_id: str | None = None,
name: str | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> int:
"""Count assistants matching filters.
Args:
metadata: Metadata to filter by. Exact match for each key/value.
graph_id: Optional graph id to filter by.
name: Optional name to filter by.
The filtering logic will match assistants where 'name' is a substring (case insensitive) of the assistant name.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
int: Number of assistants matching the criteria.
"""
payload: dict[str, Any] = {}
if metadata:
payload["metadata"] = metadata
if graph_id:
payload["graph_id"] = graph_id
if name:
payload["name"] = name
return await self.http.post(
"/assistants/count", json=payload, headers=headers, params=params
)
async def get_versions(
self,
assistant_id: str,
metadata: Json = None,
limit: int = 10,
offset: int = 0,
*,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> list[AssistantVersion]:
"""List all versions of an assistant.
Args:
assistant_id: The assistant ID to get versions for.
metadata: Metadata to filter versions by. Exact match filter for each KV pair.
limit: The maximum number of versions to return.
offset: The number of versions to skip.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
A list of assistant versions.
???+ example "Example Usage"
```python
client = get_client(url="http://localhost:2024")
assistant_versions = await client.assistants.get_versions(
assistant_id="my_assistant_id"
)
```
"""
payload: dict[str, Any] = {
"limit": limit,
"offset": offset,
}
if metadata:
payload["metadata"] = metadata
return await self.http.post(
f"/assistants/{assistant_id}/versions",
json=payload,
headers=headers,
params=params,
)
async def set_latest(
self,
assistant_id: str,
version: int,
*,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> Assistant:
"""Change the version of an assistant.
Args:
assistant_id: The assistant ID to delete.
version: The version to change to.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
Assistant Object.
???+ example "Example Usage"
```python
client = get_client(url="http://localhost:2024")
new_version_assistant = await client.assistants.set_latest(
assistant_id="my_assistant_id",
version=3
)
```
"""
payload: dict[str, Any] = {"version": version}
return await self.http.post(
f"/assistants/{assistant_id}/latest",
json=payload,
headers=headers,
params=params,
)
+178
View File
@@ -0,0 +1,178 @@
"""Async LangGraph client."""
from __future__ import annotations
import logging
import os
from collections.abc import Mapping
from types import TracebackType
import httpx
from langgraph_sdk._async.assistants import AssistantsClient
from langgraph_sdk._async.cron import CronClient
from langgraph_sdk._async.http import HttpClient
from langgraph_sdk._async.runs import RunsClient
from langgraph_sdk._async.store import StoreClient
from langgraph_sdk._async.threads import ThreadsClient
from langgraph_sdk._shared.types import TimeoutTypes
from langgraph_sdk._shared.utilities import (
NOT_PROVIDED,
_get_headers,
_registered_transports,
get_asgi_transport,
)
logger = logging.getLogger(__name__)
def get_client(
*,
url: str | None = None,
api_key: str | None = NOT_PROVIDED,
headers: Mapping[str, str] | None = None,
timeout: TimeoutTypes | None = None,
) -> LangGraphClient:
"""Create and configure a LangGraphClient.
The client provides programmatic access to LangSmith Deployment. It supports
both remote servers and local in-process connections (when running inside a LangGraph server).
Args:
url:
Base URL of the LangGraph API.
- If `None`, the client first attempts an in-process connection via ASGI transport.
If that fails, it defers registration until after app initialization. This
only works if the client is used from within the Agent server.
api_key:
API key for authentication. Can be:
- A string: use this exact API key
- `None`: explicitly skip loading from environment variables
- Not provided (default): auto-load from environment in this order:
1. `LANGGRAPH_API_KEY`
2. `LANGSMITH_API_KEY`
3. `LANGCHAIN_API_KEY`
headers:
Additional HTTP headers to include in requests. Merged with authentication headers.
timeout:
HTTP timeout configuration. May be:
- `httpx.Timeout` instance
- float (total seconds)
- tuple `(connect, read, write, pool)` in seconds
Defaults: connect=5, read=300, write=300, pool=5.
Returns:
LangGraphClient:
A top-level client exposing sub-clients for assistants, threads,
runs, and cron operations.
???+ example "Connect to a remote server:"
```python
from langgraph_sdk import get_client
# get top-level LangGraphClient
client = get_client(url="http://localhost:8123")
# example usage: client.<model>.<method_name>()
assistants = await client.assistants.get(assistant_id="some_uuid")
```
???+ example "Connect in-process to a running LangGraph server:"
```python
from langgraph_sdk import get_client
client = get_client(url=None)
async def my_node(...):
subagent_result = await client.runs.wait(
thread_id=None,
assistant_id="agent",
input={"messages": [{"role": "user", "content": "Foo"}]},
)
```
???+ example "Skip auto-loading API key from environment:"
```python
from langgraph_sdk import get_client
# Don't load API key from environment variables
client = get_client(
url="http://localhost:8123",
api_key=None
)
```
"""
transport: httpx.AsyncBaseTransport | None = None
if url is None:
url = "http://api"
if os.environ.get("__LANGGRAPH_DEFER_LOOPBACK_TRANSPORT") == "true":
transport = get_asgi_transport()(app=None, root_path="/noauth") # type: ignore[invalid-argument-type]
_registered_transports.append(transport)
else:
try:
from langgraph_api.server import app # type: ignore
transport = get_asgi_transport()(app, root_path="/noauth")
except Exception:
logger.debug(
"Failed to connect to in-process LangGraph server. Deferring configuration.",
exc_info=True,
)
transport = get_asgi_transport()(app=None, root_path="/noauth") # type: ignore[invalid-argument-type]
_registered_transports.append(transport)
if transport is None:
transport = httpx.AsyncHTTPTransport(retries=5)
client = httpx.AsyncClient(
base_url=url,
transport=transport,
timeout=(
httpx.Timeout(timeout) # type: ignore[arg-type]
if timeout is not None
else httpx.Timeout(connect=5, read=300, write=300, pool=5)
),
headers=_get_headers(api_key, headers),
)
return LangGraphClient(client)
class LangGraphClient:
"""Top-level client for LangGraph API.
Attributes:
assistants: Manages versioned configuration for your graphs.
threads: Handles (potentially) multi-turn interactions, such as conversational threads.
runs: Controls individual invocations of the graph.
crons: Manages scheduled operations.
store: Interfaces with persistent, shared data storage.
"""
def __init__(self, client: httpx.AsyncClient) -> None:
self.http = HttpClient(client)
self.assistants = AssistantsClient(self.http)
self.threads = ThreadsClient(self.http)
self.runs = RunsClient(self.http)
self.crons = CronClient(self.http)
self.store = StoreClient(self.http)
async def __aenter__(self) -> LangGraphClient:
"""Enter the async context manager."""
return self
async def __aexit__(
self,
exc_type: type[BaseException] | None,
exc_val: BaseException | None,
exc_tb: TracebackType | None,
) -> None:
"""Exit the async context manager."""
await self.aclose()
async def aclose(self) -> None:
"""Close the underlying HTTP client."""
if hasattr(self, "http"):
await self.http.client.aclose()
+452
View File
@@ -0,0 +1,452 @@
"""Async client for managing recurrent runs (cron jobs) in LangGraph."""
from __future__ import annotations
from collections.abc import Mapping
from datetime import datetime
from typing import Any
from langgraph_sdk._async.http import HttpClient
from langgraph_sdk.schema import (
All,
Config,
Context,
Cron,
CronSelectField,
CronSortBy,
Input,
OnCompletionBehavior,
QueryParamTypes,
Run,
SortOrder,
)
class CronClient:
"""Client for managing recurrent runs (cron jobs) in LangGraph.
A run is a single invocation of an assistant with optional input, config, and context.
This client allows scheduling recurring runs to occur automatically.
???+ example "Example Usage"
```python
client = get_client(url="http://localhost:2024"))
cron_job = await client.crons.create_for_thread(
thread_id="thread_123",
assistant_id="asst_456",
schedule="0 9 * * *",
input={"message": "Daily update"}
)
```
!!! note "Feature Availability"
The crons client functionality is not supported on all licenses.
Please check the relevant license documentation for the most up-to-date
details on feature availability.
"""
def __init__(self, http_client: HttpClient) -> None:
self.http = http_client
async def create_for_thread(
self,
thread_id: str,
assistant_id: str,
*,
schedule: str,
input: Input | None = None,
metadata: Mapping[str, Any] | None = None,
config: Config | None = None,
context: Context | None = None,
checkpoint_during: bool | None = None,
interrupt_before: All | list[str] | None = None,
interrupt_after: All | list[str] | None = None,
webhook: str | None = None,
multitask_strategy: str | None = None,
end_time: datetime | None = None,
enabled: bool | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> Run:
"""Create a cron job for a thread.
Args:
thread_id: the thread ID to run the cron job on.
assistant_id: The assistant ID or graph name to use for the cron job.
If using graph name, will default to first assistant created from that graph.
schedule: The cron schedule to execute this job on.
Schedules are interpreted in UTC.
input: The input to the graph.
metadata: Metadata to assign to the cron job runs.
config: The configuration for the assistant.
context: Static context to add to the assistant.
!!! version-added "Added in version 0.6.0"
checkpoint_during: Whether to checkpoint during the run (or only at the end/interruption).
interrupt_before: Nodes to interrupt immediately before they get executed.
interrupt_after: Nodes to Nodes to interrupt immediately after they get executed.
webhook: Webhook to call after LangGraph API call is done.
multitask_strategy: Multitask strategy to use.
Must be one of 'reject', 'interrupt', 'rollback', or 'enqueue'.
end_time: The time to stop running the cron job. If not provided, the cron job will run indefinitely.
enabled: Whether the cron job is enabled or not.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
The cron run.
???+ example "Example Usage"
```python
client = get_client(url="http://localhost:2024")
cron_run = await client.crons.create_for_thread(
thread_id="my-thread-id",
assistant_id="agent",
schedule="27 15 * * *",
input={"messages": [{"role": "user", "content": "hello!"}]},
metadata={"name":"my_run"},
context={"model_name": "openai"},
interrupt_before=["node_to_stop_before_1","node_to_stop_before_2"],
interrupt_after=["node_to_stop_after_1","node_to_stop_after_2"],
webhook="https://my.fake.webhook.com",
multitask_strategy="interrupt",
enabled=True,
)
```
"""
payload = {
"schedule": schedule,
"input": input,
"config": config,
"metadata": metadata,
"context": context,
"assistant_id": assistant_id,
"checkpoint_during": checkpoint_during,
"interrupt_before": interrupt_before,
"interrupt_after": interrupt_after,
"webhook": webhook,
"end_time": end_time.isoformat() if end_time else None,
"enabled": enabled,
}
if multitask_strategy:
payload["multitask_strategy"] = multitask_strategy
payload = {k: v for k, v in payload.items() if v is not None}
return await self.http.post(
f"/threads/{thread_id}/runs/crons",
json=payload,
headers=headers,
params=params,
)
async def create(
self,
assistant_id: str,
*,
schedule: str,
input: Input | None = None,
metadata: Mapping[str, Any] | None = None,
config: Config | None = None,
context: Context | None = None,
checkpoint_during: bool | None = None,
interrupt_before: All | list[str] | None = None,
interrupt_after: All | list[str] | None = None,
webhook: str | None = None,
on_run_completed: OnCompletionBehavior | None = None,
multitask_strategy: str | None = None,
end_time: datetime | None = None,
enabled: bool | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> Run:
"""Create a cron run.
Args:
assistant_id: The assistant ID or graph name to use for the cron job.
If using graph name, will default to first assistant created from that graph.
schedule: The cron schedule to execute this job on.
Schedules are interpreted in UTC.
input: The input to the graph.
metadata: Metadata to assign to the cron job runs.
config: The configuration for the assistant.
context: Static context to add to the assistant.
!!! version-added "Added in version 0.6.0"
checkpoint_during: Whether to checkpoint during the run (or only at the end/interruption).
interrupt_before: Nodes to interrupt immediately before they get executed.
interrupt_after: Nodes to Nodes to interrupt immediately after they get executed.
webhook: Webhook to call after LangGraph API call is done.
on_run_completed: What to do with the thread after the run completes.
Must be one of 'delete' (default) or 'keep'. 'delete' removes the thread
after execution. 'keep' creates a new thread for each execution but does not
clean them up. Clients are responsible for cleaning up kept threads.
multitask_strategy: Multitask strategy to use.
Must be one of 'reject', 'interrupt', 'rollback', or 'enqueue'.
end_time: The time to stop running the cron job. If not provided, the cron job will run indefinitely.
enabled: Whether the cron job is enabled or not.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
The cron run.
???+ example "Example Usage"
```python
client = get_client(url="http://localhost:2024")
cron_run = client.crons.create(
assistant_id="agent",
schedule="27 15 * * *",
input={"messages": [{"role": "user", "content": "hello!"}]},
metadata={"name":"my_run"},
context={"model_name": "openai"},
interrupt_before=["node_to_stop_before_1","node_to_stop_before_2"],
interrupt_after=["node_to_stop_after_1","node_to_stop_after_2"],
webhook="https://my.fake.webhook.com",
multitask_strategy="interrupt",
enabled=True,
)
```
"""
payload = {
"schedule": schedule,
"input": input,
"config": config,
"metadata": metadata,
"context": context,
"assistant_id": assistant_id,
"checkpoint_during": checkpoint_during,
"interrupt_before": interrupt_before,
"interrupt_after": interrupt_after,
"webhook": webhook,
"on_run_completed": on_run_completed,
"end_time": end_time.isoformat() if end_time else None,
"enabled": enabled,
}
if multitask_strategy:
payload["multitask_strategy"] = multitask_strategy
payload = {k: v for k, v in payload.items() if v is not None}
return await self.http.post(
"/runs/crons", json=payload, headers=headers, params=params
)
async def delete(
self,
cron_id: str,
*,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> None:
"""Delete a cron.
Args:
cron_id: The cron ID to delete.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
`None`
???+ example "Example Usage"
```python
client = get_client(url="http://localhost:2024")
await client.crons.delete(
cron_id="cron_to_delete"
)
```
"""
await self.http.delete(f"/runs/crons/{cron_id}", headers=headers, params=params)
async def update(
self,
cron_id: str,
*,
schedule: str | None = None,
end_time: datetime | None = None,
input: Input | None = None,
metadata: Mapping[str, Any] | None = None,
config: Config | None = None,
context: Context | None = None,
webhook: str | None = None,
interrupt_before: All | list[str] | None = None,
interrupt_after: All | list[str] | None = None,
on_run_completed: OnCompletionBehavior | None = None,
enabled: bool | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> Cron:
"""Update a cron job by ID.
Args:
cron_id: The cron ID to update.
schedule: The cron schedule to execute this job on.
Schedules are interpreted in UTC.
end_time: The end date to stop running the cron.
input: The input to the graph.
metadata: Metadata to assign to the cron job runs.
config: The configuration for the assistant.
context: Static context added to the assistant.
webhook: Webhook to call after LangGraph API call is done.
interrupt_before: Nodes to interrupt immediately before they get executed.
interrupt_after: Nodes to interrupt immediately after they get executed.
on_run_completed: What to do with the thread after the run completes.
Must be one of 'delete' or 'keep'. 'delete' removes the thread
after execution. 'keep' creates a new thread for each execution but does not
clean them up.
enabled: Enable or disable the cron job.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
The updated cron job.
???+ example "Example Usage"
```python
client = get_client(url="http://localhost:2024")
updated_cron = await client.crons.update(
cron_id="1ef3cefa-4c09-6926-96d0-3dc97fd5e39b",
schedule="0 10 * * *",
enabled=False,
)
```
"""
payload = {
"schedule": schedule,
"end_time": end_time.isoformat() if end_time else None,
"input": input,
"metadata": metadata,
"config": config,
"context": context,
"webhook": webhook,
"interrupt_before": interrupt_before,
"interrupt_after": interrupt_after,
"on_run_completed": on_run_completed,
"enabled": enabled,
}
payload = {k: v for k, v in payload.items() if v is not None}
return await self.http.patch(
f"/runs/crons/{cron_id}",
json=payload,
headers=headers,
params=params,
)
async def search(
self,
*,
assistant_id: str | None = None,
thread_id: str | None = None,
enabled: bool | None = None,
limit: int = 10,
offset: int = 0,
sort_by: CronSortBy | None = None,
sort_order: SortOrder | None = None,
select: list[CronSelectField] | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> list[Cron]:
"""Get a list of cron jobs.
Args:
assistant_id: The assistant ID or graph name to search for.
thread_id: the thread ID to search for.
enabled: The enabled status to search for.
limit: The maximum number of results to return.
offset: The number of results to skip.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
The list of cron jobs returned by the search,
???+ example "Example Usage"
```python
client = get_client(url="http://localhost:2024")
cron_jobs = await client.crons.search(
assistant_id="my_assistant_id",
thread_id="my_thread_id",
enabled=True,
limit=5,
offset=5,
)
print(cron_jobs)
```
```shell
----------------------------------------------------------
[
{
'cron_id': '1ef3cefa-4c09-6926-96d0-3dc97fd5e39b',
'assistant_id': 'my_assistant_id',
'thread_id': 'my_thread_id',
'user_id': None,
'payload':
{
'input': {'start_time': ''},
'schedule': '4 * * * *',
'assistant_id': 'my_assistant_id'
},
'schedule': '4 * * * *',
'next_run_date': '2024-07-25T17:04:00+00:00',
'end_time': None,
'created_at': '2024-07-08T06:02:23.073257+00:00',
'updated_at': '2024-07-08T06:02:23.073257+00:00'
}
]
```
"""
payload = {
"assistant_id": assistant_id,
"thread_id": thread_id,
"enabled": enabled,
"limit": limit,
"offset": offset,
}
if sort_by:
payload["sort_by"] = sort_by
if sort_order:
payload["sort_order"] = sort_order
if select:
payload["select"] = select
payload = {k: v for k, v in payload.items() if v is not None}
return await self.http.post(
"/runs/crons/search", json=payload, headers=headers, params=params
)
async def count(
self,
*,
assistant_id: str | None = None,
thread_id: str | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> int:
"""Count cron jobs matching filters.
Args:
assistant_id: Assistant ID to filter by.
thread_id: Thread ID to filter by.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
int: Number of crons matching the criteria.
"""
payload: dict[str, Any] = {}
if assistant_id:
payload["assistant_id"] = assistant_id
if thread_id:
payload["thread_id"] = thread_id
return await self.http.post(
"/runs/crons/count", json=payload, headers=headers, params=params
)
+305
View File
@@ -0,0 +1,305 @@
"""HTTP client for async operations."""
from __future__ import annotations
import asyncio
import logging
import sys
import warnings
from collections.abc import AsyncIterator, Callable, Mapping
from typing import Any, cast
import httpx
import orjson
from langgraph_sdk._shared.utilities import _orjson_default
from langgraph_sdk.errors import _araise_for_status_typed
from langgraph_sdk.schema import QueryParamTypes, StreamPart
from langgraph_sdk.sse import SSEDecoder, aiter_lines_raw
logger = logging.getLogger(__name__)
class HttpClient:
"""Handle async requests to the LangGraph API.
Adds additional error messaging & content handling above the
provided httpx client.
Attributes:
client (httpx.AsyncClient): Underlying HTTPX async client.
"""
def __init__(self, client: httpx.AsyncClient) -> None:
self.client = client
async def get(
self,
path: str,
*,
params: QueryParamTypes | None = None,
headers: Mapping[str, str] | None = None,
on_response: Callable[[httpx.Response], None] | None = None,
) -> Any:
"""Send a `GET` request."""
r = await self.client.get(path, params=params, headers=headers)
if on_response:
on_response(r)
await _araise_for_status_typed(r)
return await _adecode_json(r)
async def post(
self,
path: str,
*,
json: dict[str, Any] | list | None,
params: QueryParamTypes | None = None,
headers: Mapping[str, str] | None = None,
on_response: Callable[[httpx.Response], None] | None = None,
) -> Any:
"""Send a `POST` request."""
if json is not None:
request_headers, content = await _aencode_json(json)
else:
request_headers, content = {}, b""
# Merge headers, with runtime headers taking precedence
if headers:
request_headers.update(headers)
r = await self.client.post(
path, headers=request_headers, content=content, params=params
)
if on_response:
on_response(r)
await _araise_for_status_typed(r)
return await _adecode_json(r)
async def put(
self,
path: str,
*,
json: dict,
params: QueryParamTypes | None = None,
headers: Mapping[str, str] | None = None,
on_response: Callable[[httpx.Response], None] | None = None,
) -> Any:
"""Send a `PUT` request."""
request_headers, content = await _aencode_json(json)
if headers:
request_headers.update(headers)
r = await self.client.put(
path, headers=request_headers, content=content, params=params
)
if on_response:
on_response(r)
await _araise_for_status_typed(r)
return await _adecode_json(r)
async def patch(
self,
path: str,
*,
json: dict,
params: QueryParamTypes | None = None,
headers: Mapping[str, str] | None = None,
on_response: Callable[[httpx.Response], None] | None = None,
) -> Any:
"""Send a `PATCH` request."""
request_headers, content = await _aencode_json(json)
if headers:
request_headers.update(headers)
r = await self.client.patch(
path, headers=request_headers, content=content, params=params
)
if on_response:
on_response(r)
await _araise_for_status_typed(r)
return await _adecode_json(r)
async def delete(
self,
path: str,
*,
json: Any | None = None,
params: QueryParamTypes | None = None,
headers: Mapping[str, str] | None = None,
on_response: Callable[[httpx.Response], None] | None = None,
) -> None:
"""Send a `DELETE` request."""
r = await self.client.request(
"DELETE", path, json=json, params=params, headers=headers
)
if on_response:
on_response(r)
await _araise_for_status_typed(r)
async def request_reconnect(
self,
path: str,
method: str,
*,
json: dict[str, Any] | None = None,
params: QueryParamTypes | None = None,
headers: Mapping[str, str] | None = None,
on_response: Callable[[httpx.Response], None] | None = None,
reconnect_limit: int = 5,
) -> Any:
"""Send a request that automatically reconnects to Location header."""
request_headers, content = await _aencode_json(json)
if headers:
request_headers.update(headers)
async with self.client.stream(
method, path, headers=request_headers, content=content, params=params
) as r:
if on_response:
on_response(r)
try:
r.raise_for_status()
except httpx.HTTPStatusError as e:
body = (await r.aread()).decode()
if sys.version_info >= (3, 11):
e.add_note(body)
else:
logger.error(f"Error from langgraph-api: {body}", exc_info=e)
raise e
loc = r.headers.get("location")
if reconnect_limit <= 0 or not loc:
return await _adecode_json(r)
try:
return await _adecode_json(r)
except httpx.HTTPError:
warnings.warn(
f"Request failed, attempting reconnect to Location: {loc}",
stacklevel=2,
)
await r.aclose()
return await self.request_reconnect(
loc,
"GET",
headers=request_headers,
# don't pass on_response so it's only called once
reconnect_limit=reconnect_limit - 1,
)
async def stream(
self,
path: str,
method: str,
*,
json: dict[str, Any] | None = None,
params: QueryParamTypes | None = None,
headers: Mapping[str, str] | None = None,
on_response: Callable[[httpx.Response], None] | None = None,
) -> AsyncIterator[StreamPart]:
"""Stream results using SSE."""
request_headers, content = await _aencode_json(json)
request_headers["Accept"] = "text/event-stream"
request_headers["Cache-Control"] = "no-store"
# Add runtime headers with precedence
if headers:
request_headers.update(headers)
reconnect_headers = {
key: value
for key, value in request_headers.items()
if key.lower() not in {"content-length", "content-type"}
}
last_event_id: str | None = None
reconnect_path: str | None = None
reconnect_attempts = 0
max_reconnect_attempts = 5
while True:
current_headers = dict(
request_headers if reconnect_path is None else reconnect_headers
)
if last_event_id is not None:
current_headers["Last-Event-ID"] = last_event_id
current_method = method if reconnect_path is None else "GET"
current_content = content if reconnect_path is None else None
current_params = params if reconnect_path is None else None
retry = False
async with self.client.stream(
current_method,
reconnect_path or path,
headers=current_headers,
content=current_content,
params=current_params,
) as res:
if reconnect_path is None and on_response:
on_response(res)
# check status
await _araise_for_status_typed(res)
# check content type
content_type = res.headers.get("content-type", "").partition(";")[0]
if "text/event-stream" not in content_type:
raise httpx.TransportError(
"Expected response header Content-Type to contain 'text/event-stream', "
f"got {content_type!r}"
)
reconnect_location = res.headers.get("location")
if reconnect_location:
reconnect_path = reconnect_location
# parse SSE
decoder = SSEDecoder()
try:
async for line in aiter_lines_raw(res):
sse = decoder.decode(line=cast("bytes", line).rstrip(b"\n"))
if sse is not None:
if decoder.last_event_id is not None:
last_event_id = decoder.last_event_id
if sse.event or sse.data is not None:
yield sse
except httpx.HTTPError:
# httpx.TransportError inherits from HTTPError, so transient
# disconnects during streaming land here.
if reconnect_path is None:
raise
retry = True
else:
if sse := decoder.decode(b""):
if decoder.last_event_id is not None:
last_event_id = decoder.last_event_id
if sse.event or sse.data is not None:
# decoder.decode(b"") flushes the in-flight event and may
# return an empty placeholder when there is no pending
# message. Skip these no-op events so the stream doesn't
# emit a trailing blank item after reconnects.
yield sse
if retry:
reconnect_attempts += 1
if reconnect_attempts > max_reconnect_attempts:
raise httpx.TransportError(
"Exceeded maximum SSE reconnection attempts"
)
continue
break
async def _aencode_json(json: Any) -> tuple[dict[str, str], bytes | None]:
if json is None:
return {}, None
body = await asyncio.get_running_loop().run_in_executor(
None,
orjson.dumps,
json,
_orjson_default,
orjson.OPT_SERIALIZE_NUMPY | orjson.OPT_NON_STR_KEYS,
)
content_length = str(len(body))
content_type = "application/json"
headers = {"Content-Length": content_length, "Content-Type": content_type}
return headers, body
async def _adecode_json(r: httpx.Response) -> Any:
body = await r.aread()
return (
await asyncio.get_running_loop().run_in_executor(None, orjson.loads, body)
if body
else None
)
File diff suppressed because it is too large Load Diff
+313
View File
@@ -0,0 +1,313 @@
"""Async Store client for LangGraph SDK."""
from __future__ import annotations
from collections.abc import Mapping, Sequence
from typing import Any, Literal
from langgraph_sdk._async.http import HttpClient
from langgraph_sdk._shared.utilities import _provided_vals
from langgraph_sdk.schema import (
Item,
ListNamespaceResponse,
QueryParamTypes,
SearchItemsResponse,
)
class StoreClient:
"""Client for interacting with the graph's shared storage.
The Store provides a key-value storage system for persisting data across graph executions,
allowing for stateful operations and data sharing across threads.
???+ example "Example"
```python
client = get_client(url="http://localhost:2024")
await client.store.put_item(["users", "user123"], "mem-123451342", {"name": "Alice", "score": 100})
```
"""
def __init__(self, http: HttpClient) -> None:
self.http = http
async def put_item(
self,
namespace: Sequence[str],
/,
key: str,
value: Mapping[str, Any],
index: Literal[False] | list[str] | None = None,
ttl: int | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> None:
"""Store or update an item.
Args:
namespace: A list of strings representing the namespace path.
key: The unique identifier for the item within the namespace.
value: A dictionary containing the item's data.
index: Controls search indexing - None (use defaults), False (disable), or list of field paths to index.
ttl: Optional time-to-live in minutes for the item, or None for no expiration.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
`None`
???+ example "Example Usage"
```python
client = get_client(url="http://localhost:2024")
await client.store.put_item(
["documents", "user123"],
key="item456",
value={"title": "My Document", "content": "Hello World"}
)
```
"""
for label in namespace:
if "." in label:
raise ValueError(
f"Invalid namespace label '{label}'. Namespace labels cannot contain periods ('.')."
)
payload = {
"namespace": namespace,
"key": key,
"value": value,
"index": index,
"ttl": ttl,
}
await self.http.put(
"/store/items", json=_provided_vals(payload), headers=headers, params=params
)
async def get_item(
self,
namespace: Sequence[str],
/,
key: str,
*,
refresh_ttl: bool | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> Item:
"""Retrieve a single item.
Args:
key: The unique identifier for the item.
namespace: Optional list of strings representing the namespace path.
refresh_ttl: Whether to refresh the TTL on this read operation. If `None`, uses the store's default behavior.
Returns:
Item: The retrieved item.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
???+ example "Example Usage"
```python
client = get_client(url="http://localhost:2024")
item = await client.store.get_item(
["documents", "user123"],
key="item456",
)
print(item)
```
```shell
----------------------------------------------------------------
{
'namespace': ['documents', 'user123'],
'key': 'item456',
'value': {'title': 'My Document', 'content': 'Hello World'},
'created_at': '2024-07-30T12:00:00Z',
'updated_at': '2024-07-30T12:00:00Z'
}
```
"""
for label in namespace:
if "." in label:
raise ValueError(
f"Invalid namespace label '{label}'. Namespace labels cannot contain periods ('.')."
)
get_params = {"namespace": ".".join(namespace), "key": key}
if refresh_ttl is not None:
get_params["refresh_ttl"] = refresh_ttl
if params:
get_params = {**get_params, **dict(params)}
return await self.http.get("/store/items", params=get_params, headers=headers)
async def delete_item(
self,
namespace: Sequence[str],
/,
key: str,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> None:
"""Delete an item.
Args:
key: The unique identifier for the item.
namespace: Optional list of strings representing the namespace path.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
`None`
???+ example "Example Usage"
```python
client = get_client(url="http://localhost:2024")
await client.store.delete_item(
["documents", "user123"],
key="item456",
)
```
"""
await self.http.delete(
"/store/items",
json={"namespace": namespace, "key": key},
headers=headers,
params=params,
)
async def search_items(
self,
namespace_prefix: Sequence[str],
/,
filter: Mapping[str, Any] | None = None,
limit: int = 10,
offset: int = 0,
query: str | None = None,
refresh_ttl: bool | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> SearchItemsResponse:
"""Search for items within a namespace prefix.
Args:
namespace_prefix: List of strings representing the namespace prefix.
filter: Optional dictionary of key-value pairs to filter results.
limit: Maximum number of items to return (default is 10).
offset: Number of items to skip before returning results (default is 0).
query: Optional query for natural language search.
refresh_ttl: Whether to refresh the TTL on items returned by this search. If `None`, uses the store's default behavior.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
A list of items matching the search criteria.
???+ example "Example Usage"
```python
client = get_client(url="http://localhost:2024")
items = await client.store.search_items(
["documents"],
filter={"author": "John Doe"},
limit=5,
offset=0
)
print(items)
```
```shell
----------------------------------------------------------------
{
"items": [
{
"namespace": ["documents", "user123"],
"key": "item789",
"value": {
"title": "Another Document",
"author": "John Doe"
},
"created_at": "2024-07-30T12:00:00Z",
"updated_at": "2024-07-30T12:00:00Z"
},
# ... additional items ...
]
}
```
"""
payload = {
"namespace_prefix": namespace_prefix,
"filter": filter,
"limit": limit,
"offset": offset,
"query": query,
"refresh_ttl": refresh_ttl,
}
return await self.http.post(
"/store/items/search",
json=_provided_vals(payload),
headers=headers,
params=params,
)
async def list_namespaces(
self,
prefix: list[str] | None = None,
suffix: list[str] | None = None,
max_depth: int | None = None,
limit: int = 100,
offset: int = 0,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> ListNamespaceResponse:
"""List namespaces with optional match conditions.
Args:
prefix: Optional list of strings representing the prefix to filter namespaces.
suffix: Optional list of strings representing the suffix to filter namespaces.
max_depth: Optional integer specifying the maximum depth of namespaces to return.
limit: Maximum number of namespaces to return (default is 100).
offset: Number of namespaces to skip before returning results (default is 0).
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
A list of namespaces matching the criteria.
???+ example "Example Usage"
```python
client = get_client(url="http://localhost:2024")
namespaces = await client.store.list_namespaces(
prefix=["documents"],
max_depth=3,
limit=10,
offset=0
)
print(namespaces)
----------------------------------------------------------------
[
["documents", "user123", "reports"],
["documents", "user456", "invoices"],
...
]
```
"""
payload = {
"prefix": prefix,
"suffix": suffix,
"max_depth": max_depth,
"limit": limit,
"offset": offset,
}
return await self.http.post(
"/store/namespaces",
json=_provided_vals(payload),
headers=headers,
params=params,
)
+722
View File
@@ -0,0 +1,722 @@
"""Async client for managing threads in LangGraph."""
from __future__ import annotations
from collections.abc import AsyncIterator, Mapping, Sequence
from typing import Any
from langgraph_sdk._async.http import HttpClient
from langgraph_sdk.schema import (
Checkpoint,
Json,
OnConflictBehavior,
PruneStrategy,
QueryParamTypes,
SortOrder,
StreamPart,
Thread,
ThreadSelectField,
ThreadSortBy,
ThreadState,
ThreadStatus,
ThreadStreamMode,
ThreadUpdateStateResponse,
)
class ThreadsClient:
"""Client for managing threads in LangGraph.
A thread maintains the state of a graph across multiple interactions/invocations (aka runs).
It accumulates and persists the graph's state, allowing for continuity between separate
invocations of the graph.
???+ example "Example"
```python
client = get_client(url="http://localhost:2024"))
new_thread = await client.threads.create(metadata={"user_id": "123"})
```
"""
def __init__(self, http: HttpClient) -> None:
self.http = http
async def get(
self,
thread_id: str,
*,
include: Sequence[str] | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> Thread:
"""Get a thread by ID.
Args:
thread_id: The ID of the thread to get.
include: Additional fields to include in the response.
Supported values: `"ttl"`.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
Thread object.
???+ example "Example Usage"
```python
client = get_client(url="http://localhost:2024")
thread = await client.threads.get(
thread_id="my_thread_id"
)
print(thread)
```
```shell
-----------------------------------------------------
{
'thread_id': 'my_thread_id',
'created_at': '2024-07-18T18:35:15.540834+00:00',
'updated_at': '2024-07-18T18:35:15.540834+00:00',
'metadata': {'graph_id': 'agent'}
}
```
"""
query_params: dict[str, Any] = {}
if include:
query_params["include"] = ",".join(include)
if params:
query_params.update(params)
return await self.http.get(
f"/threads/{thread_id}",
headers=headers,
params=query_params or None,
)
async def create(
self,
*,
metadata: Json = None,
thread_id: str | None = None,
if_exists: OnConflictBehavior | None = None,
supersteps: Sequence[dict[str, Sequence[dict[str, Any]]]] | None = None,
graph_id: str | None = None,
ttl: int | Mapping[str, Any] | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> Thread:
"""Create a new thread.
Args:
metadata: Metadata to add to thread.
thread_id: ID of thread.
If `None`, ID will be a randomly generated UUID.
if_exists: How to handle duplicate creation. Defaults to 'raise' under the hood.
Must be either 'raise' (raise error if duplicate), or 'do_nothing' (return existing thread).
supersteps: Apply a list of supersteps when creating a thread, each containing a sequence of updates.
Each update has `values` or `command` and `as_node`. Used for copying a thread between deployments.
graph_id: Optional graph ID to associate with the thread.
ttl: Optional time-to-live in minutes for the thread. You can pass an
integer (minutes) or a mapping with keys `ttl` and optional
`strategy` (defaults to "delete").
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
The created thread.
???+ example "Example Usage"
```python
client = get_client(url="http://localhost:2024")
thread = await client.threads.create(
metadata={"number":1},
thread_id="my-thread-id",
if_exists="raise"
)
```
"""
payload: dict[str, Any] = {}
if thread_id:
payload["thread_id"] = thread_id
if metadata or graph_id:
payload["metadata"] = {
**(metadata or {}),
**({"graph_id": graph_id} if graph_id else {}),
}
if if_exists:
payload["if_exists"] = if_exists
if supersteps:
payload["supersteps"] = [
{
"updates": [
{
"values": u["values"],
"command": u.get("command"),
"as_node": u["as_node"],
}
for u in s["updates"]
]
}
for s in supersteps
]
if ttl is not None:
if isinstance(ttl, (int, float)):
payload["ttl"] = {"ttl": ttl, "strategy": "delete"}
else:
payload["ttl"] = ttl
return await self.http.post(
"/threads", json=payload, headers=headers, params=params
)
async def update(
self,
thread_id: str,
*,
metadata: Mapping[str, Any],
ttl: int | Mapping[str, Any] | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> Thread:
"""Update a thread.
Args:
thread_id: ID of thread to update.
metadata: Metadata to merge with existing thread metadata.
ttl: Optional time-to-live in minutes for the thread. You can pass an
integer (minutes) or a mapping with keys `ttl` and optional
`strategy` (defaults to "delete").
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
The created thread.
???+ example "Example Usage"
```python
client = get_client(url="http://localhost:2024")
thread = await client.threads.update(
thread_id="my-thread-id",
metadata={"number":1},
ttl=43_200,
)
```
"""
payload: dict[str, Any] = {"metadata": metadata}
if ttl is not None:
if isinstance(ttl, (int, float)):
payload["ttl"] = {"ttl": ttl, "strategy": "delete"}
else:
payload["ttl"] = ttl
return await self.http.patch(
f"/threads/{thread_id}",
json=payload,
headers=headers,
params=params,
)
async def delete(
self,
thread_id: str,
*,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> None:
"""Delete a thread.
Args:
thread_id: The ID of the thread to delete.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
`None`
???+ example "Example Usage"
```python
client = get_client(url="http://localhost2024)
await client.threads.delete(
thread_id="my_thread_id"
)
```
"""
await self.http.delete(f"/threads/{thread_id}", headers=headers, params=params)
async def search(
self,
*,
metadata: Json = None,
values: Json = None,
ids: Sequence[str] | None = None,
status: ThreadStatus | None = None,
limit: int = 10,
offset: int = 0,
sort_by: ThreadSortBy | None = None,
sort_order: SortOrder | None = None,
select: list[ThreadSelectField] | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> list[Thread]:
"""Search for threads.
Args:
metadata: Thread metadata to filter on.
values: State values to filter on.
ids: List of thread IDs to filter by.
status: Thread status to filter on.
Must be one of 'idle', 'busy', 'interrupted' or 'error'.
limit: Limit on number of threads to return.
offset: Offset in threads table to start search from.
sort_by: Sort by field.
sort_order: Sort order.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
List of the threads matching the search parameters.
???+ example "Example Usage"
```python
client = get_client(url="http://localhost:2024")
threads = await client.threads.search(
metadata={"number":1},
status="interrupted",
limit=15,
offset=5
)
```
"""
payload: dict[str, Any] = {
"limit": limit,
"offset": offset,
}
if metadata:
payload["metadata"] = metadata
if values:
payload["values"] = values
if ids:
payload["ids"] = ids
if status:
payload["status"] = status
if sort_by:
payload["sort_by"] = sort_by
if sort_order:
payload["sort_order"] = sort_order
if select:
payload["select"] = select
return await self.http.post(
"/threads/search",
json=payload,
headers=headers,
params=params,
)
async def count(
self,
*,
metadata: Json = None,
values: Json = None,
status: ThreadStatus | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> int:
"""Count threads matching filters.
Args:
metadata: Thread metadata to filter on.
values: State values to filter on.
status: Thread status to filter on.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
int: Number of threads matching the criteria.
"""
payload: dict[str, Any] = {}
if metadata:
payload["metadata"] = metadata
if values:
payload["values"] = values
if status:
payload["status"] = status
return await self.http.post(
"/threads/count", json=payload, headers=headers, params=params
)
async def copy(
self,
thread_id: str,
*,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> None:
"""Copy a thread.
Args:
thread_id: The ID of the thread to copy.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
`None`
???+ example "Example Usage"
```python
client = get_client(url="http://localhost:2024)
await client.threads.copy(
thread_id="my_thread_id"
)
```
"""
return await self.http.post(
f"/threads/{thread_id}/copy", json=None, headers=headers, params=params
)
async def prune(
self,
thread_ids: Sequence[str],
*,
strategy: PruneStrategy = "delete",
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> dict[str, Any]:
"""Prune threads by ID.
Args:
thread_ids: List of thread IDs to prune.
strategy: The prune strategy. `"delete"` removes threads entirely.
`"keep_latest"` prunes old checkpoints but keeps threads and their
latest state. Defaults to `"delete"`.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
A dict containing `pruned_count` (number of threads pruned).
???+ example "Example Usage"
```python
client = get_client(url="http://localhost:2024")
result = await client.threads.prune(
thread_ids=["thread_1", "thread_2"],
)
print(result) # {'pruned_count': 2}
```
"""
payload: dict[str, Any] = {
"thread_ids": thread_ids,
}
if strategy != "delete":
payload["strategy"] = strategy
return await self.http.post(
"/threads/prune", json=payload, headers=headers, params=params
)
async def get_state(
self,
thread_id: str,
checkpoint: Checkpoint | None = None,
checkpoint_id: str | None = None, # deprecated
*,
subgraphs: bool = False,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> ThreadState:
"""Get the state of a thread.
Args:
thread_id: The ID of the thread to get the state of.
checkpoint: The checkpoint to get the state of.
checkpoint_id: (deprecated) The checkpoint ID to get the state of.
subgraphs: Include subgraphs states.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
The thread of the state.
???+ example "Example Usage"
```python
client = get_client(url="http://localhost:2024)
thread_state = await client.threads.get_state(
thread_id="my_thread_id",
checkpoint_id="my_checkpoint_id"
)
print(thread_state)
```
```shell
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
{
'values': {
'messages': [
{
'content': 'how are you?',
'additional_kwargs': {},
'response_metadata': {},
'type': 'human',
'name': None,
'id': 'fe0a5778-cfe9-42ee-b807-0adaa1873c10',
'example': False
},
{
'content': "I'm doing well, thanks for asking! I'm an AI assistant created by Anthropic to be helpful, honest, and harmless.",
'additional_kwargs': {},
'response_metadata': {},
'type': 'ai',
'name': None,
'id': 'run-159b782c-b679-4830-83c6-cef87798fe8b',
'example': False,
'tool_calls': [],
'invalid_tool_calls': [],
'usage_metadata': None
}
]
},
'next': [],
'checkpoint':
{
'thread_id': 'e2496803-ecd5-4e0c-a779-3226296181c2',
'checkpoint_ns': '',
'checkpoint_id': '1ef4a9b8-e6fb-67b1-8001-abd5184439d1'
}
'metadata':
{
'step': 1,
'run_id': '1ef4a9b8-d7da-679a-a45a-872054341df2',
'source': 'loop',
'writes':
{
'agent':
{
'messages': [
{
'id': 'run-159b782c-b679-4830-83c6-cef87798fe8b',
'name': None,
'type': 'ai',
'content': "I'm doing well, thanks for asking! I'm an AI assistant created by Anthropic to be helpful, honest, and harmless.",
'example': False,
'tool_calls': [],
'usage_metadata': None,
'additional_kwargs': {},
'response_metadata': {},
'invalid_tool_calls': []
}
]
}
},
'user_id': None,
'graph_id': 'agent',
'thread_id': 'e2496803-ecd5-4e0c-a779-3226296181c2',
'created_by': 'system',
'assistant_id': 'fe096781-5601-53d2-b2f6-0d3403f7e9ca'},
'created_at': '2024-07-25T15:35:44.184703+00:00',
'parent_config':
{
'thread_id': 'e2496803-ecd5-4e0c-a779-3226296181c2',
'checkpoint_ns': '',
'checkpoint_id': '1ef4a9b8-d80d-6fa7-8000-9300467fad0f'
}
}
```
"""
if checkpoint:
return await self.http.post(
f"/threads/{thread_id}/state/checkpoint",
json={"checkpoint": checkpoint, "subgraphs": subgraphs},
headers=headers,
params=params,
)
elif checkpoint_id:
get_params = {"subgraphs": subgraphs}
if params:
get_params = {**get_params, **dict(params)}
return await self.http.get(
f"/threads/{thread_id}/state/{checkpoint_id}",
params=get_params,
headers=headers,
)
else:
get_params = {"subgraphs": subgraphs}
if params:
get_params = {**get_params, **dict(params)}
return await self.http.get(
f"/threads/{thread_id}/state",
params=get_params,
headers=headers,
)
async def update_state(
self,
thread_id: str,
values: dict[str, Any] | Sequence[dict] | None,
*,
as_node: str | None = None,
checkpoint: Checkpoint | None = None,
checkpoint_id: str | None = None, # deprecated
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> ThreadUpdateStateResponse:
"""Update the state of a thread.
Args:
thread_id: The ID of the thread to update.
values: The values to update the state with.
as_node: Update the state as if this node had just executed.
checkpoint: The checkpoint to update the state of.
checkpoint_id: (deprecated) The checkpoint ID to update the state of.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
Response after updating a thread's state.
???+ example "Example Usage"
```python
client = get_client(url="http://localhost:2024)
response = await client.threads.update_state(
thread_id="my_thread_id",
values={"messages":[{"role": "user", "content": "hello!"}]},
as_node="my_node",
)
print(response)
```
```shell
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
{
'checkpoint': {
'thread_id': 'e2496803-ecd5-4e0c-a779-3226296181c2',
'checkpoint_ns': '',
'checkpoint_id': '1ef4a9b8-e6fb-67b1-8001-abd5184439d1',
'checkpoint_map': {}
}
}
```
"""
payload: dict[str, Any] = {
"values": values,
}
if checkpoint_id:
payload["checkpoint_id"] = checkpoint_id
if checkpoint:
payload["checkpoint"] = checkpoint
if as_node:
payload["as_node"] = as_node
return await self.http.post(
f"/threads/{thread_id}/state", json=payload, headers=headers, params=params
)
async def get_history(
self,
thread_id: str,
*,
limit: int = 10,
before: str | Checkpoint | None = None,
metadata: Mapping[str, Any] | None = None,
checkpoint: Checkpoint | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> list[ThreadState]:
"""Get the state history of a thread.
Args:
thread_id: The ID of the thread to get the state history for.
checkpoint: Return states for this subgraph. If empty defaults to root.
limit: The maximum number of states to return.
before: Return states before this checkpoint.
metadata: Filter states by metadata key-value pairs.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
The state history of the thread.
???+ example "Example Usage"
```python
client = get_client(url="http://localhost:2024)
thread_state = await client.threads.get_history(
thread_id="my_thread_id",
limit=5,
)
```
"""
payload: dict[str, Any] = {
"limit": limit,
}
if before:
payload["before"] = before
if metadata:
payload["metadata"] = metadata
if checkpoint:
payload["checkpoint"] = checkpoint
return await self.http.post(
f"/threads/{thread_id}/history",
json=payload,
headers=headers,
params=params,
)
async def join_stream(
self,
thread_id: str,
*,
last_event_id: str | None = None,
stream_mode: ThreadStreamMode | Sequence[ThreadStreamMode] = "run_modes",
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> AsyncIterator[StreamPart]:
"""Get a stream of events for a thread.
Args:
thread_id: The ID of the thread to get the stream for.
last_event_id: The ID of the last event to get.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
An iterator of stream parts.
???+ example "Example Usage"
```python
for chunk in client.threads.join_stream(
thread_id="my_thread_id",
last_event_id="my_event_id",
):
print(chunk)
```
"""
query_params = {
"stream_mode": stream_mode,
}
if params:
query_params.update(params)
return self.http.stream(
f"/threads/{thread_id}/stream",
"GET",
headers={
**({"Last-Event-ID": last_event_id} if last_event_id else {}),
**(headers or {}),
},
params=query_params,
)
@@ -0,0 +1 @@
"""Shared utilities for async and sync clients."""
@@ -0,0 +1,10 @@
"""Type aliases and constants."""
from __future__ import annotations
TimeoutTypes = (
None
| float
| tuple[float | None, float | None]
| tuple[float | None, float | None, float | None, float | None]
)
@@ -0,0 +1,131 @@
"""Shared utility functions for async and sync clients."""
from __future__ import annotations
import functools
import os
import re
from collections.abc import Mapping
from typing import Any, cast
import httpx
import langgraph_sdk
from langgraph_sdk.schema import RunCreateMetadata
RESERVED_HEADERS = ("x-api-key",)
NOT_PROVIDED = cast(None, object())
def _get_api_key(api_key: str | None = NOT_PROVIDED) -> str | None:
"""Get the API key from the environment.
Precedence:
1. explicit string argument
2. LANGGRAPH_API_KEY (if api_key not provided)
3. LANGSMITH_API_KEY (if api_key not provided)
4. LANGCHAIN_API_KEY (if api_key not provided)
Args:
api_key: The API key to use. Can be:
- A string: use this exact API key
- None: explicitly skip loading from environment
- NOT_PROVIDED (default): auto-load from environment variables
"""
if isinstance(api_key, str):
return api_key
if api_key is NOT_PROVIDED:
# api_key is not explicitly provided, try to load from environment
for prefix in ["LANGGRAPH", "LANGSMITH", "LANGCHAIN"]:
if env := os.getenv(f"{prefix}_API_KEY"):
return env.strip().strip('"').strip("'")
# api_key is explicitly None, don't load from environment
return None
def _get_headers(
api_key: str | None,
custom_headers: Mapping[str, str] | None,
) -> dict[str, str]:
"""Combine api_key and custom user-provided headers."""
custom_headers = custom_headers or {}
for header in RESERVED_HEADERS:
if header in custom_headers:
raise ValueError(f"Cannot set reserved header '{header}'")
headers = {
"User-Agent": f"langgraph-sdk-py/{langgraph_sdk.__version__}",
**custom_headers,
}
resolved_api_key = _get_api_key(api_key)
if resolved_api_key:
headers["x-api-key"] = resolved_api_key
return headers
def _orjson_default(obj: Any) -> Any:
is_class = isinstance(obj, type)
if hasattr(obj, "model_dump") and callable(obj.model_dump):
if is_class:
raise TypeError(
f"Cannot JSON-serialize type object: {obj!r}. Did you mean to pass an instance of the object instead?"
f"\nReceived type: {obj!r}"
)
return obj.model_dump()
elif hasattr(obj, "dict") and callable(obj.dict):
if is_class:
raise TypeError(
f"Cannot JSON-serialize type object: {obj!r}. Did you mean to pass an instance of the object instead?"
f"\nReceived type: {obj!r}"
)
return obj.dict()
elif isinstance(obj, (set, frozenset)):
return list(obj)
else:
raise TypeError(f"Object of type {type(obj)} is not JSON serializable")
# Compiled regex pattern for extracting run metadata from Content-Location header
_RUN_METADATA_PATTERN = re.compile(
r"(\/threads\/(?P<thread_id>.+))?\/runs\/(?P<run_id>.+)"
)
def _get_run_metadata_from_response(
response: httpx.Response,
) -> RunCreateMetadata | None:
"""Extract run metadata from the response headers."""
if (content_location := response.headers.get("Content-Location")) and (
match := _RUN_METADATA_PATTERN.search(content_location)
):
return RunCreateMetadata(
run_id=match.group("run_id"),
thread_id=match.group("thread_id") or None,
)
return None
def _provided_vals(d: Mapping[str, Any]) -> dict[str, Any]:
return {k: v for k, v in d.items() if v is not None}
_registered_transports: list[httpx.ASGITransport] = []
# Do not move; this is used in the server.
def configure_loopback_transports(app: Any) -> None:
for transport in _registered_transports:
transport.app = app
@functools.lru_cache(maxsize=1)
def get_asgi_transport() -> type[httpx.ASGITransport]:
try:
from langgraph_api import asgi_transport # type: ignore[unresolved-import]
return asgi_transport.ASGITransport
except ImportError:
# Older versions of the server
return httpx.ASGITransport
@@ -0,0 +1,20 @@
"""Sync client exports."""
from langgraph_sdk._sync.assistants import SyncAssistantsClient
from langgraph_sdk._sync.client import SyncLangGraphClient, get_sync_client
from langgraph_sdk._sync.cron import SyncCronClient
from langgraph_sdk._sync.http import SyncHttpClient
from langgraph_sdk._sync.runs import SyncRunsClient
from langgraph_sdk._sync.store import SyncStoreClient
from langgraph_sdk._sync.threads import SyncThreadsClient
__all__ = [
"SyncAssistantsClient",
"SyncCronClient",
"SyncHttpClient",
"SyncLangGraphClient",
"SyncRunsClient",
"SyncStoreClient",
"SyncThreadsClient",
"get_sync_client",
]
@@ -0,0 +1,731 @@
"""Synchronous client for managing assistants in LangGraph."""
from __future__ import annotations
from collections.abc import Mapping
from typing import Any, Literal, cast, overload
import httpx
from langgraph_sdk._sync.http import SyncHttpClient
from langgraph_sdk.schema import (
Assistant,
AssistantSelectField,
AssistantSortBy,
AssistantsSearchResponse,
AssistantVersion,
Config,
Context,
GraphSchema,
Json,
OnConflictBehavior,
QueryParamTypes,
SortOrder,
Subgraphs,
)
class SyncAssistantsClient:
"""Client for managing assistants in LangGraph synchronously.
This class provides methods to interact with assistants, which are versioned configurations of your graph.
???+ example "Example"
```python
client = get_sync_client(url="http://localhost:2024")
assistant = client.assistants.get("assistant_id_123")
```
"""
def __init__(self, http: SyncHttpClient) -> None:
self.http = http
def get(
self,
assistant_id: str,
*,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> Assistant:
"""Get an assistant by ID.
Args:
assistant_id: The ID of the assistant to get OR the name of the graph (to use the default assistant).
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
`Assistant` Object.
???+ example "Example Usage"
```python
assistant = client.assistants.get(
assistant_id="my_assistant_id"
)
print(assistant)
```
```shell
----------------------------------------------------
{
'assistant_id': 'my_assistant_id',
'graph_id': 'agent',
'created_at': '2024-06-25T17:10:33.109781+00:00',
'updated_at': '2024-06-25T17:10:33.109781+00:00',
'config': {},
'context': {},
'metadata': {'created_by': 'system'}
}
```
"""
return self.http.get(
f"/assistants/{assistant_id}", headers=headers, params=params
)
def get_graph(
self,
assistant_id: str,
*,
xray: int | bool = False,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> dict[str, list[dict[str, Any]]]:
"""Get the graph of an assistant by ID.
Args:
assistant_id: The ID of the assistant to get the graph of.
xray: Include graph representation of subgraphs. If an integer value is provided, only subgraphs with a depth less than or equal to the value will be included.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
The graph information for the assistant in JSON format.
???+ example "Example Usage"
```python
client = get_sync_client(url="http://localhost:2024")
graph_info = client.assistants.get_graph(
assistant_id="my_assistant_id"
)
print(graph_info)
--------------------------------------------------------------------------------------------------------------------------
{
'nodes':
[
{'id': '__start__', 'type': 'schema', 'data': '__start__'},
{'id': '__end__', 'type': 'schema', 'data': '__end__'},
{'id': 'agent','type': 'runnable','data': {'id': ['langgraph', 'utils', 'RunnableCallable'],'name': 'agent'}},
],
'edges':
[
{'source': '__start__', 'target': 'agent'},
{'source': 'agent','target': '__end__'}
]
}
```
"""
query_params = {"xray": xray}
if params:
query_params.update(params)
return self.http.get(
f"/assistants/{assistant_id}/graph", params=query_params, headers=headers
)
def get_schemas(
self,
assistant_id: str,
*,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> GraphSchema:
"""Get the schemas of an assistant by ID.
Args:
assistant_id: The ID of the assistant to get the schema of.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
GraphSchema: The graph schema for the assistant.
???+ example "Example Usage"
```python
client = get_sync_client(url="http://localhost:2024")
schema = client.assistants.get_schemas(
assistant_id="my_assistant_id"
)
print(schema)
```
```shell
----------------------------------------------------------------------------------------------------------------------------
{
'graph_id': 'agent',
'state_schema':
{
'title': 'LangGraphInput',
'$ref': '#/definitions/AgentState',
'definitions':
{
'BaseMessage':
{
'title': 'BaseMessage',
'description': 'Base abstract Message class. Messages are the inputs and outputs of ChatModels.',
'type': 'object',
'properties':
{
'content':
{
'title': 'Content',
'anyOf': [
{'type': 'string'},
{'type': 'array','items': {'anyOf': [{'type': 'string'}, {'type': 'object'}]}}
]
},
'additional_kwargs':
{
'title': 'Additional Kwargs',
'type': 'object'
},
'response_metadata':
{
'title': 'Response Metadata',
'type': 'object'
},
'type':
{
'title': 'Type',
'type': 'string'
},
'name':
{
'title': 'Name',
'type': 'string'
},
'id':
{
'title': 'Id',
'type': 'string'
}
},
'required': ['content', 'type']
},
'AgentState':
{
'title': 'AgentState',
'type': 'object',
'properties':
{
'messages':
{
'title': 'Messages',
'type': 'array',
'items': {'$ref': '#/definitions/BaseMessage'}
}
},
'required': ['messages']
}
}
},
'config_schema':
{
'title': 'Configurable',
'type': 'object',
'properties':
{
'model_name':
{
'title': 'Model Name',
'enum': ['anthropic', 'openai'],
'type': 'string'
}
}
},
'context_schema':
{
'title': 'Context',
'type': 'object',
'properties':
{
'model_name':
{
'title': 'Model Name',
'enum': ['anthropic', 'openai'],
'type': 'string'
}
}
}
}
```
"""
return self.http.get(
f"/assistants/{assistant_id}/schemas", headers=headers, params=params
)
def get_subgraphs(
self,
assistant_id: str,
namespace: str | None = None,
recurse: bool = False,
*,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> Subgraphs:
"""Get the schemas of an assistant by ID.
Args:
assistant_id: The ID of the assistant to get the schema of.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
Subgraphs: The graph schema for the assistant.
"""
get_params = {"recurse": recurse}
if params:
get_params = {**get_params, **dict(params)}
if namespace is not None:
return self.http.get(
f"/assistants/{assistant_id}/subgraphs/{namespace}",
params=get_params,
headers=headers,
)
else:
return self.http.get(
f"/assistants/{assistant_id}/subgraphs",
params=get_params,
headers=headers,
)
def create(
self,
graph_id: str | None,
config: Config | None = None,
*,
context: Context | None = None,
metadata: Json = None,
assistant_id: str | None = None,
if_exists: OnConflictBehavior | None = None,
name: str | None = None,
headers: Mapping[str, str] | None = None,
description: str | None = None,
params: QueryParamTypes | None = None,
) -> Assistant:
"""Create a new assistant.
Useful when graph is configurable and you want to create different assistants based on different configurations.
Args:
graph_id: The ID of the graph the assistant should use. The graph ID is normally set in your langgraph.json configuration.
config: Configuration to use for the graph.
context: Static context to add to the assistant.
!!! version-added "Added in version 0.6.0"
metadata: Metadata to add to assistant.
assistant_id: Assistant ID to use, will default to a random UUID if not provided.
if_exists: How to handle duplicate creation. Defaults to 'raise' under the hood.
Must be either 'raise' (raise error if duplicate), or 'do_nothing' (return existing assistant).
name: The name of the assistant. Defaults to 'Untitled' under the hood.
headers: Optional custom headers to include with the request.
description: Optional description of the assistant.
The description field is available for langgraph-api server version>=0.0.45
params: Optional query parameters to include with the request.
Returns:
The created assistant.
???+ example "Example Usage"
```python
client = get_sync_client(url="http://localhost:2024")
assistant = client.assistants.create(
graph_id="agent",
context={"model_name": "openai"},
metadata={"number":1},
assistant_id="my-assistant-id",
if_exists="do_nothing",
name="my_name"
)
```
"""
payload: dict[str, Any] = {
"graph_id": graph_id,
}
if config:
payload["config"] = config
if context:
payload["context"] = context
if metadata:
payload["metadata"] = metadata
if assistant_id:
payload["assistant_id"] = assistant_id
if if_exists:
payload["if_exists"] = if_exists
if name:
payload["name"] = name
if description:
payload["description"] = description
return self.http.post(
"/assistants", json=payload, headers=headers, params=params
)
def update(
self,
assistant_id: str,
*,
graph_id: str | None = None,
config: Config | None = None,
context: Context | None = None,
metadata: Json = None,
name: str | None = None,
headers: Mapping[str, str] | None = None,
description: str | None = None,
params: QueryParamTypes | None = None,
) -> Assistant:
"""Update an assistant.
Use this to point to a different graph, update the configuration, or change the metadata of an assistant.
Args:
assistant_id: Assistant to update.
graph_id: The ID of the graph the assistant should use.
The graph ID is normally set in your langgraph.json configuration. If `None`, assistant will keep pointing to same graph.
config: Configuration to use for the graph.
context: Static context to add to the assistant.
!!! version-added "Added in version 0.6.0"
metadata: Metadata to merge with existing assistant metadata.
name: The new name for the assistant.
headers: Optional custom headers to include with the request.
description: Optional description of the assistant.
The description field is available for langgraph-api server version>=0.0.45
Returns:
The updated assistant.
???+ example "Example Usage"
```python
client = get_sync_client(url="http://localhost:2024")
assistant = client.assistants.update(
assistant_id='e280dad7-8618-443f-87f1-8e41841c180f',
graph_id="other-graph",
context={"model_name": "anthropic"},
metadata={"number":2}
)
```
"""
payload: dict[str, Any] = {}
if graph_id:
payload["graph_id"] = graph_id
if config is not None:
payload["config"] = config
if context is not None:
payload["context"] = context
if metadata:
payload["metadata"] = metadata
if name:
payload["name"] = name
if description:
payload["description"] = description
return self.http.patch(
f"/assistants/{assistant_id}",
json=payload,
headers=headers,
params=params,
)
def delete(
self,
assistant_id: str,
*,
delete_threads: bool = False,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> None:
"""Delete an assistant.
Args:
assistant_id: The assistant ID to delete.
delete_threads: If true, delete all threads with `metadata.assistant_id`
matching this assistant, along with runs and checkpoints belonging to
those threads.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
`None`
???+ example "Example Usage"
```python
client = get_sync_client(url="http://localhost:2024")
client.assistants.delete(
assistant_id="my_assistant_id"
)
```
"""
query_params: dict[str, Any] = {}
if delete_threads:
query_params["delete_threads"] = True
if params:
query_params.update(params)
self.http.delete(
f"/assistants/{assistant_id}",
headers=headers,
params=query_params or None,
)
@overload
def search(
self,
*,
metadata: Json = None,
graph_id: str | None = None,
name: str | None = None,
limit: int = 10,
offset: int = 0,
sort_by: AssistantSortBy | None = None,
sort_order: SortOrder | None = None,
select: list[AssistantSelectField] | None = None,
response_format: Literal["object"],
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> AssistantsSearchResponse: ...
@overload
def search(
self,
*,
metadata: Json = None,
graph_id: str | None = None,
name: str | None = None,
limit: int = 10,
offset: int = 0,
sort_by: AssistantSortBy | None = None,
sort_order: SortOrder | None = None,
select: list[AssistantSelectField] | None = None,
response_format: Literal["array"] = "array",
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> list[Assistant]: ...
def search(
self,
*,
metadata: Json = None,
graph_id: str | None = None,
name: str | None = None,
limit: int = 10,
offset: int = 0,
sort_by: AssistantSortBy | None = None,
sort_order: SortOrder | None = None,
select: list[AssistantSelectField] | None = None,
response_format: Literal["array", "object"] = "array",
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> AssistantsSearchResponse | list[Assistant]:
"""Search for assistants.
Args:
metadata: Metadata to filter by. Exact match filter for each KV pair.
graph_id: The ID of the graph to filter by.
The graph ID is normally set in your langgraph.json configuration.
name: The name of the assistant to filter by.
The filtering logic will match assistants where 'name' is a substring (case insensitive) of the assistant name.
limit: The maximum number of results to return.
offset: The number of results to skip.
sort_by: The field to sort by.
sort_order: The order to sort by.
select: Specific assistant fields to include in the response.
response_format: Controls the response shape. Use `"array"` (default)
to return a bare list of assistants, or `"object"` to return
a mapping containing assistants plus pagination metadata.
Defaults to "array", though this default will be changed to "object" in a future release.
headers: Optional custom headers to include with the request.
Returns:
A list of assistants (when `response_format="array"`) or a mapping
with the assistants and the next pagination cursor (when
`response_format="object"`).
???+ example "Example Usage"
```python
client = get_sync_client(url="http://localhost:2024")
response = client.assistants.search(
metadata = {"name":"my_name"},
graph_id="my_graph_id",
limit=5,
offset=5,
response_format="object",
)
assistants = response["assistants"]
next_cursor = response["next"]
```
"""
if response_format not in ("array", "object"):
raise ValueError("response_format must be 'array' or 'object'")
payload: dict[str, Any] = {
"limit": limit,
"offset": offset,
}
if metadata:
payload["metadata"] = metadata
if graph_id:
payload["graph_id"] = graph_id
if name:
payload["name"] = name
if sort_by:
payload["sort_by"] = sort_by
if sort_order:
payload["sort_order"] = sort_order
if select:
payload["select"] = select
next_cursor: str | None = None
def capture_pagination(response: httpx.Response) -> None:
nonlocal next_cursor
next_cursor = response.headers.get("X-Pagination-Next")
assistants = cast(
list[Assistant],
self.http.post(
"/assistants/search",
json=payload,
headers=headers,
params=params,
on_response=capture_pagination if response_format == "object" else None,
),
)
if response_format == "object":
return {"assistants": assistants, "next": next_cursor}
return assistants
def count(
self,
*,
metadata: Json = None,
graph_id: str | None = None,
name: str | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> int:
"""Count assistants matching filters.
Args:
metadata: Metadata to filter by. Exact match for each key/value.
graph_id: Optional graph id to filter by.
name: Optional name to filter by.
The filtering logic will match assistants where 'name' is a substring (case insensitive) of the assistant name.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
int: Number of assistants matching the criteria.
"""
payload: dict[str, Any] = {}
if metadata:
payload["metadata"] = metadata
if graph_id:
payload["graph_id"] = graph_id
if name:
payload["name"] = name
return self.http.post(
"/assistants/count", json=payload, headers=headers, params=params
)
def get_versions(
self,
assistant_id: str,
metadata: Json = None,
limit: int = 10,
offset: int = 0,
*,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> list[AssistantVersion]:
"""List all versions of an assistant.
Args:
assistant_id: The assistant ID to get versions for.
metadata: Metadata to filter versions by. Exact match filter for each KV pair.
limit: The maximum number of versions to return.
offset: The number of versions to skip.
headers: Optional custom headers to include with the request.
Returns:
A list of assistants.
???+ example "Example Usage"
```python
client = get_sync_client(url="http://localhost:2024")
assistant_versions = client.assistants.get_versions(
assistant_id="my_assistant_id"
)
```
"""
payload: dict[str, Any] = {
"limit": limit,
"offset": offset,
}
if metadata:
payload["metadata"] = metadata
return self.http.post(
f"/assistants/{assistant_id}/versions",
json=payload,
headers=headers,
params=params,
)
def set_latest(
self,
assistant_id: str,
version: int,
*,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> Assistant:
"""Change the version of an assistant.
Args:
assistant_id: The assistant ID to delete.
version: The version to change to.
headers: Optional custom headers to include with the request.
Returns:
`Assistant` Object.
???+ example "Example Usage"
```python
client = get_sync_client(url="http://localhost:2024")
new_version_assistant = client.assistants.set_latest(
assistant_id="my_assistant_id",
version=3
)
```
"""
payload: dict[str, Any] = {"version": version}
return self.http.post(
f"/assistants/{assistant_id}/latest",
json=payload,
headers=headers,
params=params,
)
+127
View File
@@ -0,0 +1,127 @@
"""Sync LangGraph client."""
from __future__ import annotations
from collections.abc import Mapping
from types import TracebackType
import httpx
from langgraph_sdk._shared.types import TimeoutTypes
from langgraph_sdk._shared.utilities import NOT_PROVIDED, _get_headers
from langgraph_sdk._sync.assistants import SyncAssistantsClient
from langgraph_sdk._sync.cron import SyncCronClient
from langgraph_sdk._sync.http import SyncHttpClient
from langgraph_sdk._sync.runs import SyncRunsClient
from langgraph_sdk._sync.store import SyncStoreClient
from langgraph_sdk._sync.threads import SyncThreadsClient
def get_sync_client(
*,
url: str | None = None,
api_key: str | None = NOT_PROVIDED,
headers: Mapping[str, str] | None = None,
timeout: TimeoutTypes | None = None,
) -> SyncLangGraphClient:
"""Get a synchronous LangGraphClient instance.
Args:
url: The URL of the LangGraph API.
api_key: API key for authentication. Can be:
- A string: use this exact API key
- `None`: explicitly skip loading from environment variables
- Not provided (default): auto-load from environment in this order:
1. `LANGGRAPH_API_KEY`
2. `LANGSMITH_API_KEY`
3. `LANGCHAIN_API_KEY`
headers: Optional custom headers
timeout: Optional timeout configuration for the HTTP client.
Accepts an httpx.Timeout instance, a float (seconds), or a tuple of timeouts.
Tuple format is (connect, read, write, pool)
If not provided, defaults to connect=5s, read=300s, write=300s, and pool=5s.
Returns:
SyncLangGraphClient: The top-level synchronous client for accessing AssistantsClient,
ThreadsClient, RunsClient, and CronClient.
???+ example "Example"
```python
from langgraph_sdk import get_sync_client
# get top-level synchronous LangGraphClient
client = get_sync_client(url="http://localhost:8123")
# example usage: client.<model>.<method_name>()
assistant = client.assistants.get(assistant_id="some_uuid")
```
???+ example "Skip auto-loading API key from environment:"
```python
from langgraph_sdk import get_sync_client
# Don't load API key from environment variables
client = get_sync_client(
url="http://localhost:8123",
api_key=None
)
```
"""
if url is None:
url = "http://localhost:8123"
transport = httpx.HTTPTransport(retries=5)
client = httpx.Client(
base_url=url,
transport=transport,
timeout=(
httpx.Timeout(timeout) # type: ignore[arg-type]
if timeout is not None
else httpx.Timeout(connect=5, read=300, write=300, pool=5)
),
headers=_get_headers(api_key, headers),
)
return SyncLangGraphClient(client)
class SyncLangGraphClient:
"""Synchronous client for interacting with the LangGraph API.
This class provides synchronous access to LangGraph API endpoints for managing
assistants, threads, runs, cron jobs, and data storage.
???+ example "Example"
```python
client = get_sync_client(url="http://localhost:2024")
assistant = client.assistants.get("asst_123")
```
"""
def __init__(self, client: httpx.Client) -> None:
self.http = SyncHttpClient(client)
self.assistants = SyncAssistantsClient(self.http)
self.threads = SyncThreadsClient(self.http)
self.runs = SyncRunsClient(self.http)
self.crons = SyncCronClient(self.http)
self.store = SyncStoreClient(self.http)
def __enter__(self) -> SyncLangGraphClient:
"""Enter the sync context manager."""
return self
def __exit__(
self,
exc_type: type[BaseException] | None,
exc_val: BaseException | None,
exc_tb: TracebackType | None,
) -> None:
"""Exit the sync context manager."""
self.close()
def close(self) -> None:
"""Close the underlying HTTP client."""
if hasattr(self, "http"):
self.http.client.close()
+439
View File
@@ -0,0 +1,439 @@
"""Synchronous cron client for LangGraph SDK."""
from __future__ import annotations
from collections.abc import Mapping
from datetime import datetime
from typing import Any
from langgraph_sdk._sync.http import SyncHttpClient
from langgraph_sdk.schema import (
All,
Config,
Context,
Cron,
CronSelectField,
CronSortBy,
Input,
OnCompletionBehavior,
QueryParamTypes,
Run,
SortOrder,
)
class SyncCronClient:
"""Synchronous client for managing cron jobs in LangGraph.
This class provides methods to create and manage scheduled tasks (cron jobs) for automated graph executions.
???+ example "Example"
```python
client = get_sync_client(url="http://localhost:8123")
cron_job = client.crons.create_for_thread(thread_id="thread_123", assistant_id="asst_456", schedule="0 * * * *")
```
!!! note "Feature Availability"
The crons client functionality is not supported on all licenses.
Please check the relevant license documentation for the most up-to-date
details on feature availability.
"""
def __init__(self, http_client: SyncHttpClient) -> None:
self.http = http_client
def create_for_thread(
self,
thread_id: str,
assistant_id: str,
*,
schedule: str,
input: Input | None = None,
metadata: Mapping[str, Any] | None = None,
config: Config | None = None,
context: Context | None = None,
checkpoint_during: bool | None = None,
interrupt_before: All | list[str] | None = None,
interrupt_after: All | list[str] | None = None,
webhook: str | None = None,
multitask_strategy: str | None = None,
end_time: datetime | None = None,
enabled: bool | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> Run:
"""Create a cron job for a thread.
Args:
thread_id: the thread ID to run the cron job on.
assistant_id: The assistant ID or graph name to use for the cron job.
If using graph name, will default to first assistant created from that graph.
schedule: The cron schedule to execute this job on.
Schedules are interpreted in UTC.
input: The input to the graph.
metadata: Metadata to assign to the cron job runs.
config: The configuration for the assistant.
context: Static context to add to the assistant.
!!! version-added "Added in version 0.6.0"
checkpoint_during: Whether to checkpoint during the run (or only at the end/interruption).
interrupt_before: Nodes to interrupt immediately before they get executed.
interrupt_after: Nodes to Nodes to interrupt immediately after they get executed.
webhook: Webhook to call after LangGraph API call is done.
multitask_strategy: Multitask strategy to use.
Must be one of 'reject', 'interrupt', 'rollback', or 'enqueue'.
end_time: The time to stop running the cron job. If not provided, the cron job will run indefinitely.
enabled: Whether the cron job is enabled. By default, it is considered enabled.
headers: Optional custom headers to include with the request.
Returns:
The cron `Run`.
???+ example "Example Usage"
```python
client = get_sync_client(url="http://localhost:8123")
cron_run = client.crons.create_for_thread(
thread_id="my-thread-id",
assistant_id="agent",
schedule="27 15 * * *",
input={"messages": [{"role": "user", "content": "hello!"}]},
metadata={"name":"my_run"},
context={"model_name": "openai"},
interrupt_before=["node_to_stop_before_1","node_to_stop_before_2"],
interrupt_after=["node_to_stop_after_1","node_to_stop_after_2"],
webhook="https://my.fake.webhook.com",
multitask_strategy="interrupt",
enabled=True
)
```
"""
payload = {
"schedule": schedule,
"input": input,
"config": config,
"metadata": metadata,
"context": context,
"assistant_id": assistant_id,
"interrupt_before": interrupt_before,
"interrupt_after": interrupt_after,
"checkpoint_during": checkpoint_during,
"webhook": webhook,
"multitask_strategy": multitask_strategy,
"end_time": end_time.isoformat() if end_time else None,
"enabled": enabled,
}
payload = {k: v for k, v in payload.items() if v is not None}
return self.http.post(
f"/threads/{thread_id}/runs/crons",
json=payload,
headers=headers,
params=params,
)
def create(
self,
assistant_id: str,
*,
schedule: str,
input: Input | None = None,
metadata: Mapping[str, Any] | None = None,
config: Config | None = None,
context: Context | None = None,
checkpoint_during: bool | None = None,
interrupt_before: All | list[str] | None = None,
interrupt_after: All | list[str] | None = None,
webhook: str | None = None,
on_run_completed: OnCompletionBehavior | None = None,
multitask_strategy: str | None = None,
end_time: datetime | None = None,
enabled: bool | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> Run:
"""Create a cron run.
Args:
assistant_id: The assistant ID or graph name to use for the cron job.
If using graph name, will default to first assistant created from that graph.
schedule: The cron schedule to execute this job on.
Schedules are interpreted in UTC.
input: The input to the graph.
metadata: Metadata to assign to the cron job runs.
config: The configuration for the assistant.
context: Static context to add to the assistant.
!!! version-added "Added in version 0.6.0"
checkpoint_during: Whether to checkpoint during the run (or only at the end/interruption).
interrupt_before: Nodes to interrupt immediately before they get executed.
interrupt_after: Nodes to Nodes to interrupt immediately after they get executed.
webhook: Webhook to call after LangGraph API call is done.
on_run_completed: What to do with the thread after the run completes.
Must be one of 'delete' (default) or 'keep'. 'delete' removes the thread
after execution. 'keep' creates a new thread for each execution but does not
clean them up. Clients are responsible for cleaning up kept threads.
multitask_strategy: Multitask strategy to use.
Must be one of 'reject', 'interrupt', 'rollback', or 'enqueue'.
end_time: The time to stop running the cron job. If not provided, the cron job will run indefinitely.
enabled: Whether the cron job is enabled. By default, it is considered enabled.
headers: Optional custom headers to include with the request.
Returns:
The cron `Run`.
???+ example "Example Usage"
```python
client = get_sync_client(url="http://localhost:8123")
cron_run = client.crons.create(
assistant_id="agent",
schedule="27 15 * * *",
input={"messages": [{"role": "user", "content": "hello!"}]},
metadata={"name":"my_run"},
context={"model_name": "openai"},
checkpoint_during=True,
interrupt_before=["node_to_stop_before_1","node_to_stop_before_2"],
interrupt_after=["node_to_stop_after_1","node_to_stop_after_2"],
webhook="https://my.fake.webhook.com",
multitask_strategy="interrupt",
enabled=True
)
```
"""
payload = {
"schedule": schedule,
"input": input,
"config": config,
"metadata": metadata,
"context": context,
"assistant_id": assistant_id,
"interrupt_before": interrupt_before,
"interrupt_after": interrupt_after,
"webhook": webhook,
"checkpoint_during": checkpoint_during,
"on_run_completed": on_run_completed,
"multitask_strategy": multitask_strategy,
"end_time": end_time.isoformat() if end_time else None,
"enabled": enabled,
}
payload = {k: v for k, v in payload.items() if v is not None}
return self.http.post(
"/runs/crons", json=payload, headers=headers, params=params
)
def delete(
self,
cron_id: str,
*,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> None:
"""Delete a cron.
Args:
cron_id: The cron ID to delete.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
`None`
???+ example "Example Usage"
```python
client = get_sync_client(url="http://localhost:8123")
client.crons.delete(
cron_id="cron_to_delete"
)
```
"""
self.http.delete(f"/runs/crons/{cron_id}", headers=headers, params=params)
def update(
self,
cron_id: str,
*,
schedule: str | None = None,
end_time: datetime | None = None,
input: Input | None = None,
metadata: Mapping[str, Any] | None = None,
config: Config | None = None,
context: Context | None = None,
webhook: str | None = None,
interrupt_before: All | list[str] | None = None,
interrupt_after: All | list[str] | None = None,
on_run_completed: OnCompletionBehavior | None = None,
enabled: bool | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> Cron:
"""Update a cron job by ID.
Args:
cron_id: The cron ID to update.
schedule: The cron schedule to execute this job on.
Schedules are interpreted in UTC.
end_time: The end date to stop running the cron.
input: The input to the graph.
metadata: Metadata to assign to the cron job runs.
config: The configuration for the assistant.
context: Static context added to the assistant.
webhook: Webhook to call after LangGraph API call is done.
interrupt_before: Nodes to interrupt immediately before they get executed.
interrupt_after: Nodes to interrupt immediately after they get executed.
on_run_completed: What to do with the thread after the run completes.
Must be one of 'delete' or 'keep'. 'delete' removes the thread
after execution. 'keep' creates a new thread for each execution but does not
clean them up.
enabled: Enable or disable the cron job.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
The updated cron job.
???+ example "Example Usage"
```python
client = get_sync_client(url="http://localhost:8123")
updated_cron = client.crons.update(
cron_id="1ef3cefa-4c09-6926-96d0-3dc97fd5e39b",
schedule="0 10 * * *",
enabled=False,
)
```
"""
payload = {
"schedule": schedule,
"end_time": end_time.isoformat() if end_time else None,
"input": input,
"metadata": metadata,
"config": config,
"context": context,
"webhook": webhook,
"interrupt_before": interrupt_before,
"interrupt_after": interrupt_after,
"on_run_completed": on_run_completed,
"enabled": enabled,
}
payload = {k: v for k, v in payload.items() if v is not None}
return self.http.patch(
f"/runs/crons/{cron_id}",
json=payload,
headers=headers,
params=params,
)
def search(
self,
*,
assistant_id: str | None = None,
thread_id: str | None = None,
enabled: bool | None = None,
limit: int = 10,
offset: int = 0,
sort_by: CronSortBy | None = None,
sort_order: SortOrder | None = None,
select: list[CronSelectField] | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> list[Cron]:
"""Get a list of cron jobs.
Args:
assistant_id: The assistant ID or graph name to search for.
thread_id: the thread ID to search for.
enabled: Whether the cron job is enabled.
limit: The maximum number of results to return.
offset: The number of results to skip.
headers: Optional custom headers to include with the request.
Returns:
The list of cron jobs returned by the search,
???+ example "Example Usage"
```python
client = get_sync_client(url="http://localhost:8123")
cron_jobs = client.crons.search(
assistant_id="my_assistant_id",
thread_id="my_thread_id",
enabled=True,
limit=5,
offset=5,
)
print(cron_jobs)
```
```shell
----------------------------------------------------------
[
{
'cron_id': '1ef3cefa-4c09-6926-96d0-3dc97fd5e39b',
'assistant_id': 'my_assistant_id',
'thread_id': 'my_thread_id',
'user_id': None,
'payload':
{
'input': {'start_time': ''},
'schedule': '4 * * * *',
'assistant_id': 'my_assistant_id'
},
'schedule': '4 * * * *',
'next_run_date': '2024-07-25T17:04:00+00:00',
'end_time': None,
'created_at': '2024-07-08T06:02:23.073257+00:00',
'updated_at': '2024-07-08T06:02:23.073257+00:00'
}
]
```
"""
payload = {
"assistant_id": assistant_id,
"thread_id": thread_id,
"enabled": enabled,
"limit": limit,
"offset": offset,
}
if sort_by:
payload["sort_by"] = sort_by
if sort_order:
payload["sort_order"] = sort_order
if select:
payload["select"] = select
payload = {k: v for k, v in payload.items() if v is not None}
return self.http.post(
"/runs/crons/search", json=payload, headers=headers, params=params
)
def count(
self,
*,
assistant_id: str | None = None,
thread_id: str | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> int:
"""Count cron jobs matching filters.
Args:
assistant_id: Assistant ID to filter by.
thread_id: Thread ID to filter by.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
int: Number of crons matching the criteria.
"""
payload: dict[str, Any] = {}
if assistant_id:
payload["assistant_id"] = assistant_id
if thread_id:
payload["thread_id"] = thread_id
return self.http.post(
"/runs/crons/count", json=payload, headers=headers, params=params
)
+296
View File
@@ -0,0 +1,296 @@
"""Synchronous HTTP client for LangGraph API."""
from __future__ import annotations
import logging
import sys
import warnings
from collections.abc import Callable, Iterator, Mapping
from typing import Any, cast
import httpx
import orjson
from langgraph_sdk._shared.utilities import _orjson_default
from langgraph_sdk.errors import _raise_for_status_typed
from langgraph_sdk.schema import QueryParamTypes, StreamPart
from langgraph_sdk.sse import SSEDecoder, iter_lines_raw
logger = logging.getLogger(__name__)
class SyncHttpClient:
"""Handle synchronous requests to the LangGraph API.
Provides error messaging and content handling enhancements above the
underlying httpx client, mirroring the interface of [HttpClient](#HttpClient)
but for sync usage.
Attributes:
client (httpx.Client): Underlying HTTPX sync client.
"""
def __init__(self, client: httpx.Client) -> None:
self.client = client
def get(
self,
path: str,
*,
params: QueryParamTypes | None = None,
headers: Mapping[str, str] | None = None,
on_response: Callable[[httpx.Response], None] | None = None,
) -> Any:
"""Send a `GET` request."""
r = self.client.get(path, params=params, headers=headers)
if on_response:
on_response(r)
_raise_for_status_typed(r)
return _decode_json(r)
def post(
self,
path: str,
*,
json: dict[str, Any] | list | None,
params: QueryParamTypes | None = None,
headers: Mapping[str, str] | None = None,
on_response: Callable[[httpx.Response], None] | None = None,
) -> Any:
"""Send a `POST` request."""
if json is not None:
request_headers, content = _encode_json(json)
else:
request_headers, content = {}, b""
if headers:
request_headers.update(headers)
r = self.client.post(
path, headers=request_headers, content=content, params=params
)
if on_response:
on_response(r)
_raise_for_status_typed(r)
return _decode_json(r)
def put(
self,
path: str,
*,
json: dict,
params: QueryParamTypes | None = None,
headers: Mapping[str, str] | None = None,
on_response: Callable[[httpx.Response], None] | None = None,
) -> Any:
"""Send a `PUT` request."""
request_headers, content = _encode_json(json)
if headers:
request_headers.update(headers)
r = self.client.put(
path, headers=request_headers, content=content, params=params
)
if on_response:
on_response(r)
_raise_for_status_typed(r)
return _decode_json(r)
def patch(
self,
path: str,
*,
json: dict,
params: QueryParamTypes | None = None,
headers: Mapping[str, str] | None = None,
on_response: Callable[[httpx.Response], None] | None = None,
) -> Any:
"""Send a `PATCH` request."""
request_headers, content = _encode_json(json)
if headers:
request_headers.update(headers)
r = self.client.patch(
path, headers=request_headers, content=content, params=params
)
if on_response:
on_response(r)
_raise_for_status_typed(r)
return _decode_json(r)
def delete(
self,
path: str,
*,
json: Any | None = None,
params: QueryParamTypes | None = None,
headers: Mapping[str, str] | None = None,
on_response: Callable[[httpx.Response], None] | None = None,
) -> None:
"""Send a `DELETE` request."""
r = self.client.request(
"DELETE", path, json=json, params=params, headers=headers
)
if on_response:
on_response(r)
_raise_for_status_typed(r)
def request_reconnect(
self,
path: str,
method: str,
*,
json: dict[str, Any] | None = None,
params: QueryParamTypes | None = None,
headers: Mapping[str, str] | None = None,
on_response: Callable[[httpx.Response], None] | None = None,
reconnect_limit: int = 5,
) -> Any:
"""Send a request that automatically reconnects to Location header."""
request_headers, content = _encode_json(json)
if headers:
request_headers.update(headers)
with self.client.stream(
method, path, headers=request_headers, content=content, params=params
) as r:
if on_response:
on_response(r)
try:
r.raise_for_status()
except httpx.HTTPStatusError as e:
body = r.read().decode()
if sys.version_info >= (3, 11):
e.add_note(body)
else:
logger.error(f"Error from langgraph-api: {body}", exc_info=e)
raise e
loc = r.headers.get("location")
if reconnect_limit <= 0 or not loc:
return _decode_json(r)
try:
return _decode_json(r)
except httpx.HTTPError:
warnings.warn(
f"Request failed, attempting reconnect to Location: {loc}",
stacklevel=2,
)
r.close()
return self.request_reconnect(
loc,
"GET",
headers=request_headers,
# don't pass on_response so it's only called once
reconnect_limit=reconnect_limit - 1,
)
def stream(
self,
path: str,
method: str,
*,
json: dict[str, Any] | None = None,
params: QueryParamTypes | None = None,
headers: Mapping[str, str] | None = None,
on_response: Callable[[httpx.Response], None] | None = None,
) -> Iterator[StreamPart]:
"""Stream the results of a request using SSE."""
if json is not None:
request_headers, content = _encode_json(json)
else:
request_headers, content = {}, None
request_headers["Accept"] = "text/event-stream"
request_headers["Cache-Control"] = "no-store"
if headers:
request_headers.update(headers)
reconnect_headers = {
key: value
for key, value in request_headers.items()
if key.lower() not in {"content-length", "content-type"}
}
last_event_id: str | None = None
reconnect_path: str | None = None
reconnect_attempts = 0
max_reconnect_attempts = 5
while True:
current_headers = dict(
request_headers if reconnect_path is None else reconnect_headers
)
if last_event_id is not None:
current_headers["Last-Event-ID"] = last_event_id
current_method = method if reconnect_path is None else "GET"
current_content = content if reconnect_path is None else None
current_params = params if reconnect_path is None else None
retry = False
with self.client.stream(
current_method,
reconnect_path or path,
headers=current_headers,
content=current_content,
params=current_params,
) as res:
if reconnect_path is None and on_response:
on_response(res)
# check status
_raise_for_status_typed(res)
# check content type
content_type = res.headers.get("content-type", "").partition(";")[0]
if "text/event-stream" not in content_type:
raise httpx.TransportError(
"Expected response header Content-Type to contain 'text/event-stream', "
f"got {content_type!r}"
)
reconnect_location = res.headers.get("location")
if reconnect_location:
reconnect_path = reconnect_location
decoder = SSEDecoder()
try:
for line in iter_lines_raw(res):
sse = decoder.decode(cast(bytes, line).rstrip(b"\n"))
if sse is not None:
if decoder.last_event_id is not None:
last_event_id = decoder.last_event_id
if sse.event or sse.data is not None:
yield sse
except httpx.HTTPError:
# httpx.TransportError inherits from HTTPError, so transient
# disconnects during streaming land here.
if reconnect_path is None:
raise
retry = True
else:
if sse := decoder.decode(b""):
if decoder.last_event_id is not None:
last_event_id = decoder.last_event_id
if sse.event or sse.data is not None:
# See async stream implementation for rationale on
# skipping empty flush events.
yield sse
if retry:
reconnect_attempts += 1
if reconnect_attempts > max_reconnect_attempts:
raise httpx.TransportError(
"Exceeded maximum SSE reconnection attempts"
)
continue
break
def _encode_json(json: Any) -> tuple[dict[str, str], bytes]:
body = orjson.dumps(
json,
_orjson_default,
orjson.OPT_SERIALIZE_NUMPY | orjson.OPT_NON_STR_KEYS,
)
content_length = str(len(body))
content_type = "application/json"
headers = {"Content-Length": content_length, "Content-Type": content_type}
return headers, body
def _decode_json(r: httpx.Response) -> Any:
body = r.read()
return orjson.loads(body) if body else None
File diff suppressed because it is too large Load Diff
+313
View File
@@ -0,0 +1,313 @@
"""Synchronous store client for LangGraph SDK."""
from __future__ import annotations
from collections.abc import Mapping, Sequence
from typing import Any, Literal
from langgraph_sdk._shared.utilities import _provided_vals
from langgraph_sdk._sync.http import SyncHttpClient
from langgraph_sdk.schema import (
Item,
ListNamespaceResponse,
QueryParamTypes,
SearchItemsResponse,
)
class SyncStoreClient:
"""A client for synchronous operations on a key-value store.
Provides methods to interact with a remote key-value store, allowing
storage and retrieval of items within namespaced hierarchies.
???+ example "Example"
```python
client = get_sync_client(url="http://localhost:2024"))
client.store.put_item(["users", "profiles"], "user123", {"name": "Alice", "age": 30})
```
"""
def __init__(self, http: SyncHttpClient) -> None:
self.http = http
def put_item(
self,
namespace: Sequence[str],
/,
key: str,
value: Mapping[str, Any],
index: Literal[False] | list[str] | None = None,
ttl: int | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> None:
"""Store or update an item.
Args:
namespace: A list of strings representing the namespace path.
key: The unique identifier for the item within the namespace.
value: A dictionary containing the item's data.
index: Controls search indexing - None (use defaults), False (disable), or list of field paths to index.
ttl: Optional time-to-live in minutes for the item, or None for no expiration.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
`None`
???+ example "Example Usage"
```python
client = get_sync_client(url="http://localhost:8123")
client.store.put_item(
["documents", "user123"],
key="item456",
value={"title": "My Document", "content": "Hello World"}
)
```
"""
for label in namespace:
if "." in label:
raise ValueError(
f"Invalid namespace label '{label}'. Namespace labels cannot contain periods ('.')."
)
payload = {
"namespace": namespace,
"key": key,
"value": value,
"index": index,
"ttl": ttl,
}
self.http.put(
"/store/items", json=_provided_vals(payload), headers=headers, params=params
)
def get_item(
self,
namespace: Sequence[str],
/,
key: str,
*,
refresh_ttl: bool | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> Item:
"""Retrieve a single item.
Args:
key: The unique identifier for the item.
namespace: Optional list of strings representing the namespace path.
refresh_ttl: Whether to refresh the TTL on this read operation. If `None`, uses the store's default behavior.
headers: Optional custom headers to include with the request.
Returns:
The retrieved item.
???+ example "Example Usage"
```python
client = get_sync_client(url="http://localhost:8123")
item = client.store.get_item(
["documents", "user123"],
key="item456",
)
print(item)
```
```shell
----------------------------------------------------------------
{
'namespace': ['documents', 'user123'],
'key': 'item456',
'value': {'title': 'My Document', 'content': 'Hello World'},
'created_at': '2024-07-30T12:00:00Z',
'updated_at': '2024-07-30T12:00:00Z'
}
```
"""
for label in namespace:
if "." in label:
raise ValueError(
f"Invalid namespace label '{label}'. Namespace labels cannot contain periods ('.')."
)
query_params = {"key": key, "namespace": ".".join(namespace)}
if refresh_ttl is not None:
query_params["refresh_ttl"] = refresh_ttl
if params:
query_params.update(params)
return self.http.get("/store/items", params=query_params, headers=headers)
def delete_item(
self,
namespace: Sequence[str],
/,
key: str,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> None:
"""Delete an item.
Args:
key: The unique identifier for the item.
namespace: Optional list of strings representing the namespace path.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
`None`
???+ example "Example Usage"
```python
client = get_sync_client(url="http://localhost:8123")
client.store.delete_item(
["documents", "user123"],
key="item456",
)
```
"""
self.http.delete(
"/store/items",
json={"key": key, "namespace": namespace},
headers=headers,
params=params,
)
def search_items(
self,
namespace_prefix: Sequence[str],
/,
filter: Mapping[str, Any] | None = None,
limit: int = 10,
offset: int = 0,
query: str | None = None,
refresh_ttl: bool | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> SearchItemsResponse:
"""Search for items within a namespace prefix.
Args:
namespace_prefix: List of strings representing the namespace prefix.
filter: Optional dictionary of key-value pairs to filter results.
limit: Maximum number of items to return (default is 10).
offset: Number of items to skip before returning results (default is 0).
query: Optional query for natural language search.
refresh_ttl: Whether to refresh the TTL on items returned by this search. If `None`, uses the store's default behavior.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
A list of items matching the search criteria.
???+ example "Example Usage"
```python
client = get_sync_client(url="http://localhost:8123")
items = client.store.search_items(
["documents"],
filter={"author": "John Doe"},
limit=5,
offset=0
)
print(items)
```
```shell
----------------------------------------------------------------
{
"items": [
{
"namespace": ["documents", "user123"],
"key": "item789",
"value": {
"title": "Another Document",
"author": "John Doe"
},
"created_at": "2024-07-30T12:00:00Z",
"updated_at": "2024-07-30T12:00:00Z"
},
# ... additional items ...
]
}
```
"""
payload = {
"namespace_prefix": namespace_prefix,
"filter": filter,
"limit": limit,
"offset": offset,
"query": query,
"refresh_ttl": refresh_ttl,
}
return self.http.post(
"/store/items/search",
json=_provided_vals(payload),
headers=headers,
params=params,
)
def list_namespaces(
self,
prefix: list[str] | None = None,
suffix: list[str] | None = None,
max_depth: int | None = None,
limit: int = 100,
offset: int = 0,
*,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> ListNamespaceResponse:
"""List namespaces with optional match conditions.
Args:
prefix: Optional list of strings representing the prefix to filter namespaces.
suffix: Optional list of strings representing the suffix to filter namespaces.
max_depth: Optional integer specifying the maximum depth of namespaces to return.
limit: Maximum number of namespaces to return (default is 100).
offset: Number of namespaces to skip before returning results (default is 0).
headers: Optional custom headers to include with the request.
Returns:
A list of namespaces matching the criteria.
???+ example "Example Usage"
```python
client = get_sync_client(url="http://localhost:8123")
namespaces = client.store.list_namespaces(
prefix=["documents"],
max_depth=3,
limit=10,
offset=0
)
print(namespaces)
```
```shell
----------------------------------------------------------------
[
["documents", "user123", "reports"],
["documents", "user456", "invoices"],
...
]
```
"""
payload = {
"prefix": prefix,
"suffix": suffix,
"max_depth": max_depth,
"limit": limit,
"offset": offset,
}
return self.http.post(
"/store/namespaces",
json=_provided_vals(payload),
headers=headers,
params=params,
)
+708
View File
@@ -0,0 +1,708 @@
"""Synchronous client for managing threads in LangGraph."""
from __future__ import annotations
from collections.abc import Iterator, Mapping, Sequence
from typing import Any
from langgraph_sdk._sync.http import SyncHttpClient
from langgraph_sdk.schema import (
Checkpoint,
Json,
OnConflictBehavior,
PruneStrategy,
QueryParamTypes,
SortOrder,
StreamPart,
Thread,
ThreadSelectField,
ThreadSortBy,
ThreadState,
ThreadStatus,
ThreadStreamMode,
ThreadUpdateStateResponse,
)
class SyncThreadsClient:
"""Synchronous client for managing threads in LangGraph.
This class provides methods to create, retrieve, and manage threads,
which represent conversations or stateful interactions.
???+ example "Example"
```python
client = get_sync_client(url="http://localhost:2024")
thread = client.threads.create(metadata={"user_id": "123"})
```
"""
def __init__(self, http: SyncHttpClient) -> None:
self.http = http
def get(
self,
thread_id: str,
*,
include: Sequence[str] | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> Thread:
"""Get a thread by ID.
Args:
thread_id: The ID of the thread to get.
include: Additional fields to include in the response.
Supported values: `"ttl"`.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
`Thread` object.
???+ example "Example Usage"
```python
client = get_sync_client(url="http://localhost:2024")
thread = client.threads.get(
thread_id="my_thread_id"
)
print(thread)
```
```shell
-----------------------------------------------------
{
'thread_id': 'my_thread_id',
'created_at': '2024-07-18T18:35:15.540834+00:00',
'updated_at': '2024-07-18T18:35:15.540834+00:00',
'metadata': {'graph_id': 'agent'}
}
```
"""
query_params: dict[str, Any] = {}
if include:
query_params["include"] = ",".join(include)
if params:
query_params.update(params)
return self.http.get(
f"/threads/{thread_id}",
headers=headers,
params=query_params or None,
)
def create(
self,
*,
metadata: Json = None,
thread_id: str | None = None,
if_exists: OnConflictBehavior | None = None,
supersteps: Sequence[dict[str, Sequence[dict[str, Any]]]] | None = None,
graph_id: str | None = None,
ttl: int | Mapping[str, Any] | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> Thread:
"""Create a new thread.
Args:
metadata: Metadata to add to thread.
thread_id: ID of thread.
If `None`, ID will be a randomly generated UUID.
if_exists: How to handle duplicate creation. Defaults to 'raise' under the hood.
Must be either 'raise' (raise error if duplicate), or 'do_nothing' (return existing thread).
supersteps: Apply a list of supersteps when creating a thread, each containing a sequence of updates.
Each update has `values` or `command` and `as_node`. Used for copying a thread between deployments.
graph_id: Optional graph ID to associate with the thread.
ttl: Optional time-to-live in minutes for the thread. You can pass an
integer (minutes) or a mapping with keys `ttl` and optional
`strategy` (defaults to "delete").
headers: Optional custom headers to include with the request.
Returns:
The created `Thread`.
???+ example "Example Usage"
```python
client = get_sync_client(url="http://localhost:2024")
thread = client.threads.create(
metadata={"number":1},
thread_id="my-thread-id",
if_exists="raise"
)
```
)
"""
payload: dict[str, Any] = {}
if thread_id:
payload["thread_id"] = thread_id
if metadata or graph_id:
payload["metadata"] = {
**(metadata or {}),
**({"graph_id": graph_id} if graph_id else {}),
}
if if_exists:
payload["if_exists"] = if_exists
if supersteps:
payload["supersteps"] = [
{
"updates": [
{
"values": u["values"],
"command": u.get("command"),
"as_node": u["as_node"],
}
for u in s["updates"]
]
}
for s in supersteps
]
if ttl is not None:
if isinstance(ttl, (int, float)):
payload["ttl"] = {"ttl": ttl, "strategy": "delete"}
else:
payload["ttl"] = ttl
return self.http.post("/threads", json=payload, headers=headers, params=params)
def update(
self,
thread_id: str,
*,
metadata: Mapping[str, Any],
ttl: int | Mapping[str, Any] | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> Thread:
"""Update a thread.
Args:
thread_id: ID of thread to update.
metadata: Metadata to merge with existing thread metadata.
ttl: Optional time-to-live in minutes for the thread. You can pass an
integer (minutes) or a mapping with keys `ttl` and optional
`strategy` (defaults to "delete").
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
The created `Thread`.
???+ example "Example Usage"
```python
client = get_sync_client(url="http://localhost:2024")
thread = client.threads.update(
thread_id="my-thread-id",
metadata={"number":1},
ttl=43_200,
)
```
"""
payload: dict[str, Any] = {"metadata": metadata}
if ttl is not None:
if isinstance(ttl, (int, float)):
payload["ttl"] = {"ttl": ttl, "strategy": "delete"}
else:
payload["ttl"] = ttl
return self.http.patch(
f"/threads/{thread_id}",
json=payload,
headers=headers,
params=params,
)
def delete(
self,
thread_id: str,
*,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> None:
"""Delete a thread.
Args:
thread_id: The ID of the thread to delete.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
`None`
???+ example "Example Usage"
```python
client.threads.delete(
thread_id="my_thread_id"
)
```
"""
self.http.delete(f"/threads/{thread_id}", headers=headers, params=params)
def search(
self,
*,
metadata: Json = None,
values: Json = None,
ids: Sequence[str] | None = None,
status: ThreadStatus | None = None,
limit: int = 10,
offset: int = 0,
sort_by: ThreadSortBy | None = None,
sort_order: SortOrder | None = None,
select: list[ThreadSelectField] | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> list[Thread]:
"""Search for threads.
Args:
metadata: Thread metadata to filter on.
values: State values to filter on.
ids: List of thread IDs to filter by.
status: Thread status to filter on.
Must be one of 'idle', 'busy', 'interrupted' or 'error'.
limit: Limit on number of threads to return.
offset: Offset in threads table to start search from.
headers: Optional custom headers to include with the request.
Returns:
List of the threads matching the search parameters.
???+ example "Example Usage"
```python
client = get_sync_client(url="http://localhost:2024")
threads = client.threads.search(
metadata={"number":1},
status="interrupted",
limit=15,
offset=5
)
```
"""
payload: dict[str, Any] = {
"limit": limit,
"offset": offset,
}
if metadata:
payload["metadata"] = metadata
if values:
payload["values"] = values
if ids:
payload["ids"] = ids
if status:
payload["status"] = status
if sort_by:
payload["sort_by"] = sort_by
if sort_order:
payload["sort_order"] = sort_order
if select:
payload["select"] = select
return self.http.post(
"/threads/search", json=payload, headers=headers, params=params
)
def count(
self,
*,
metadata: Json = None,
values: Json = None,
status: ThreadStatus | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> int:
"""Count threads matching filters.
Args:
metadata: Thread metadata to filter on.
values: State values to filter on.
status: Thread status to filter on.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
int: Number of threads matching the criteria.
"""
payload: dict[str, Any] = {}
if metadata:
payload["metadata"] = metadata
if values:
payload["values"] = values
if status:
payload["status"] = status
return self.http.post(
"/threads/count", json=payload, headers=headers, params=params
)
def copy(
self,
thread_id: str,
*,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> None:
"""Copy a thread.
Args:
thread_id: The ID of the thread to copy.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
`None`
???+ example "Example Usage"
```python
client = get_sync_client(url="http://localhost:2024")
client.threads.copy(
thread_id="my_thread_id"
)
```
"""
return self.http.post(
f"/threads/{thread_id}/copy", json=None, headers=headers, params=params
)
def prune(
self,
thread_ids: Sequence[str],
*,
strategy: PruneStrategy = "delete",
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> dict[str, Any]:
"""Prune threads by ID.
Args:
thread_ids: List of thread IDs to prune.
strategy: The prune strategy. `"delete"` removes threads entirely.
`"keep_latest"` prunes old checkpoints but keeps threads and their
latest state. Defaults to `"delete"`.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
A dict containing `pruned_count` (number of threads pruned).
???+ example "Example Usage"
```python
client = get_sync_client(url="http://localhost:2024")
result = client.threads.prune(
thread_ids=["thread_1", "thread_2"],
)
print(result) # {'pruned_count': 2}
```
"""
payload: dict[str, Any] = {
"thread_ids": thread_ids,
}
if strategy != "delete":
payload["strategy"] = strategy
return self.http.post(
"/threads/prune", json=payload, headers=headers, params=params
)
def get_state(
self,
thread_id: str,
checkpoint: Checkpoint | None = None,
checkpoint_id: str | None = None, # deprecated
*,
subgraphs: bool = False,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> ThreadState:
"""Get the state of a thread.
Args:
thread_id: The ID of the thread to get the state of.
checkpoint: The checkpoint to get the state of.
subgraphs: Include subgraphs states.
headers: Optional custom headers to include with the request.
Returns:
The thread of the state.
???+ example "Example Usage"
```python
client = get_sync_client(url="http://localhost:2024")
thread_state = client.threads.get_state(
thread_id="my_thread_id",
checkpoint_id="my_checkpoint_id"
)
print(thread_state)
```
```shell
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
{
'values': {
'messages': [
{
'content': 'how are you?',
'additional_kwargs': {},
'response_metadata': {},
'type': 'human',
'name': None,
'id': 'fe0a5778-cfe9-42ee-b807-0adaa1873c10',
'example': False
},
{
'content': "I'm doing well, thanks for asking! I'm an AI assistant created by Anthropic to be helpful, honest, and harmless.",
'additional_kwargs': {},
'response_metadata': {},
'type': 'ai',
'name': None,
'id': 'run-159b782c-b679-4830-83c6-cef87798fe8b',
'example': False,
'tool_calls': [],
'invalid_tool_calls': [],
'usage_metadata': None
}
]
},
'next': [],
'checkpoint':
{
'thread_id': 'e2496803-ecd5-4e0c-a779-3226296181c2',
'checkpoint_ns': '',
'checkpoint_id': '1ef4a9b8-e6fb-67b1-8001-abd5184439d1'
}
'metadata':
{
'step': 1,
'run_id': '1ef4a9b8-d7da-679a-a45a-872054341df2',
'source': 'loop',
'writes':
{
'agent':
{
'messages': [
{
'id': 'run-159b782c-b679-4830-83c6-cef87798fe8b',
'name': None,
'type': 'ai',
'content': "I'm doing well, thanks for asking! I'm an AI assistant created by Anthropic to be helpful, honest, and harmless.",
'example': False,
'tool_calls': [],
'usage_metadata': None,
'additional_kwargs': {},
'response_metadata': {},
'invalid_tool_calls': []
}
]
}
},
'user_id': None,
'graph_id': 'agent',
'thread_id': 'e2496803-ecd5-4e0c-a779-3226296181c2',
'created_by': 'system',
'assistant_id': 'fe096781-5601-53d2-b2f6-0d3403f7e9ca'},
'created_at': '2024-07-25T15:35:44.184703+00:00',
'parent_config':
{
'thread_id': 'e2496803-ecd5-4e0c-a779-3226296181c2',
'checkpoint_ns': '',
'checkpoint_id': '1ef4a9b8-d80d-6fa7-8000-9300467fad0f'
}
}
```
"""
if checkpoint:
return self.http.post(
f"/threads/{thread_id}/state/checkpoint",
json={"checkpoint": checkpoint, "subgraphs": subgraphs},
headers=headers,
params=params,
)
elif checkpoint_id:
get_params = {"subgraphs": subgraphs}
if params:
get_params = {**get_params, **dict(params)}
return self.http.get(
f"/threads/{thread_id}/state/{checkpoint_id}",
params=get_params,
headers=headers,
)
else:
get_params = {"subgraphs": subgraphs}
if params:
get_params = {**get_params, **dict(params)}
return self.http.get(
f"/threads/{thread_id}/state",
params=get_params,
headers=headers,
)
def update_state(
self,
thread_id: str,
values: dict[str, Any] | Sequence[dict] | None,
*,
as_node: str | None = None,
checkpoint: Checkpoint | None = None,
checkpoint_id: str | None = None, # deprecated
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> ThreadUpdateStateResponse:
"""Update the state of a thread.
Args:
thread_id: The ID of the thread to update.
values: The values to update the state with.
as_node: Update the state as if this node had just executed.
checkpoint: The checkpoint to update the state of.
headers: Optional custom headers to include with the request.
Returns:
Response after updating a thread's state.
???+ example "Example Usage"
```python
response = await client.threads.update_state(
thread_id="my_thread_id",
values={"messages":[{"role": "user", "content": "hello!"}]},
as_node="my_node",
)
print(response)
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
{
'checkpoint': {
'thread_id': 'e2496803-ecd5-4e0c-a779-3226296181c2',
'checkpoint_ns': '',
'checkpoint_id': '1ef4a9b8-e6fb-67b1-8001-abd5184439d1',
'checkpoint_map': {}
}
}
```
"""
payload: dict[str, Any] = {
"values": values,
}
if checkpoint_id:
payload["checkpoint_id"] = checkpoint_id
if checkpoint:
payload["checkpoint"] = checkpoint
if as_node:
payload["as_node"] = as_node
return self.http.post(
f"/threads/{thread_id}/state", json=payload, headers=headers, params=params
)
def get_history(
self,
thread_id: str,
*,
limit: int = 10,
before: str | Checkpoint | None = None,
metadata: Mapping[str, Any] | None = None,
checkpoint: Checkpoint | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> list[ThreadState]:
"""Get the state history of a thread.
Args:
thread_id: The ID of the thread to get the state history for.
checkpoint: Return states for this subgraph. If empty defaults to root.
limit: The maximum number of states to return.
before: Return states before this checkpoint.
metadata: Filter states by metadata key-value pairs.
headers: Optional custom headers to include with the request.
Returns:
The state history of the `Thread`.
???+ example "Example Usage"
```python
thread_state = client.threads.get_history(
thread_id="my_thread_id",
limit=5,
before="my_timestamp",
metadata={"name":"my_name"}
)
```
"""
payload: dict[str, Any] = {
"limit": limit,
}
if before:
payload["before"] = before
if metadata:
payload["metadata"] = metadata
if checkpoint:
payload["checkpoint"] = checkpoint
return self.http.post(
f"/threads/{thread_id}/history",
json=payload,
headers=headers,
params=params,
)
def join_stream(
self,
thread_id: str,
*,
stream_mode: ThreadStreamMode | Sequence[ThreadStreamMode] = "run_modes",
last_event_id: str | None = None,
headers: Mapping[str, str] | None = None,
params: QueryParamTypes | None = None,
) -> Iterator[StreamPart]:
"""Get a stream of events for a thread.
Args:
thread_id: The ID of the thread to get the stream for.
last_event_id: The ID of the last event to get.
headers: Optional custom headers to include with the request.
params: Optional query parameters to include with the request.
Returns:
An iterator of stream parts.
???+ example "Example Usage"
```python
for chunk in client.threads.join_stream(
thread_id="my_thread_id",
last_event_id="my_event_id",
stream_mode="run_modes",
):
print(chunk)
```
"""
query_params = {
"stream_mode": stream_mode,
}
if params:
query_params.update(params)
return self.http.stream(
f"/threads/{thread_id}/stream",
"GET",
headers={
**({"Last-Event-ID": last_event_id} if last_event_id else {}),
**(headers or {}),
},
params=query_params,
)
+106 -6
View File
@@ -72,8 +72,13 @@ class Auth:
assert params.get("metadata", {}).get("owner") == "allowed_user"
@auth.on.store
async def authorize_store(ctx: Auth.types.AuthContext, value: Auth.types.on):
assert ctx.user.identity in value["namespace"], "Not authorized"
async def authorize_store(ctx: Auth.types.AuthContext, value: Auth.types.on.store.value):
# Automatically scope all store operations to the user's namespace.
namespace = tuple(value["namespace"]) if value.get("namespace") else ()
assert isinstance(namespace, tuple)
if not namespace or namespace[0] != ctx.user.identity:
namespace = (ctx.user.identity, *namespace)
value["namespace"] = namespace
```
???+ note "Request Processing Flow"
@@ -170,13 +175,32 @@ class Auth:
```
Auth for the `store` resource is a bit different since its structure is developer defined.
You typically want to enforce user creds in the namespace.
You typically want to scope store operations by rewriting the namespace to include the user's identity.
The `value` dict is mutable changes to `value["namespace"]` are used by the server for the actual operation.
```python
@auth.on.store
async def check_store_access(ctx: AuthContext, value: Auth.types.on) -> bool:
# Assuming you structure your store like (store.aput((user_id, application_context), key, value))
assert value["namespace"][0] == ctx.user.identity
async def authorize_store(ctx: AuthContext, value: Auth.types.on.store.value):
# Automatically scope all store operations to the user's namespace.
namespace = tuple(value["namespace"]) if value.get("namespace") else ()
assert isinstance(namespace, tuple)
if not namespace or namespace[0] != ctx.user.identity:
namespace = (ctx.user.identity, *namespace)
value["namespace"] = namespace
```
You can also register handlers for specific store actions:
```python
@auth.on.store.put
async def on_put(ctx: AuthContext, value: Auth.types.on.store.put.value):
# value has typed fields: namespace, key, value, index
...
@auth.on.store.get
async def on_get(ctx: AuthContext, value: Auth.types.on.store.get.value):
# value has typed fields: namespace, key
...
```
"""
# These are accessed by the API. Changes to their names or types is
@@ -483,9 +507,85 @@ class _CronsOn(
Search = types.CronsSearch
class _StoreActionOn(typing.Generic[T]):
"""Decorator for registering a handler for a specific store action."""
def __init__(
self,
auth: Auth,
action: typing.Literal["put", "get", "search", "delete", "list_namespaces"],
value: type[T],
) -> None:
self.auth = auth
self.action = action
self.value = value
def __call__(self, fn: _ActionHandler[T]) -> _ActionHandler[T]:
_validate_handler(fn)
_register_handler(self.auth, "store", self.action, fn)
return fn
class _StoreOn:
def __init__(self, auth: Auth) -> None:
self._auth = auth
self.put = _StoreActionOn(auth, "put", types.StorePut)
"""Register a handler for store put operations.
???+ example "Example"
```python
@auth.on.store.put
async def on_store_put(ctx: Auth.types.AuthContext, value: Auth.types.on.store.put.value):
# Scope puts to user's namespace
...
```
"""
self.get = _StoreActionOn(auth, "get", types.StoreGet)
"""Register a handler for store get operations.
???+ example "Example"
```python
@auth.on.store.get
async def on_store_get(ctx: Auth.types.AuthContext, value: Auth.types.on.store.get.value):
# Scope gets to user's namespace
...
```
"""
self.search = _StoreActionOn(auth, "search", types.StoreSearch)
"""Register a handler for store search operations.
???+ example "Example"
```python
@auth.on.store.search
async def on_store_search(ctx: Auth.types.AuthContext, value: Auth.types.on.store.search.value):
# Scope searches to user's namespace
...
```
"""
self.delete = _StoreActionOn(auth, "delete", types.StoreDelete)
"""Register a handler for store delete operations.
???+ example "Example"
```python
@auth.on.store.delete
async def on_store_delete(ctx: Auth.types.AuthContext, value: Auth.types.on.store.delete.value):
# Scope deletes to user's namespace
...
```
"""
self.list_namespaces = _StoreActionOn(
auth, "list_namespaces", types.StoreListNamespaces
)
"""Register a handler for store list_namespaces operations.
???+ example "Example"
```python
@auth.on.store.list_namespaces
async def on_list_ns(ctx: Auth.types.AuthContext, value: Auth.types.on.store.list_namespaces.value):
# Scope namespace listing to user's prefix
...
```
"""
@typing.overload
def __call__(
+52 -14
View File
@@ -402,7 +402,7 @@ class AuthContext(BaseAuthContext):
"list_namespaces",
]
"""The action being performed on the resource.
Most resources support the following actions:
- create: Create a new resource
- read: Read information about a resource
@@ -411,8 +411,10 @@ class AuthContext(BaseAuthContext):
- search: Search for resources
The store supports the following actions:
- put: Add or update a document in the store
- get: Get a document from the store
- put: Add or update an item in the store
- get: Get an item from the store
- search: Search for items within a namespace prefix
- delete: Delete an item from the store
- list_namespaces: List the namespaces in the store
"""
@@ -851,20 +853,34 @@ class CronsSearch(typing.TypedDict, total=False):
class StoreGet(typing.TypedDict):
"""Operation to retrieve a specific item by its namespace and key."""
"""Operation to retrieve a specific item by its namespace and key.
This dict is mutable auth handlers can modify `namespace` to enforce
access scoping (e.g., prepending the user's identity).
"""
namespace: tuple[str, ...]
"""Hierarchical path that uniquely identifies the item's location."""
"""Hierarchical path that uniquely identifies the item's location.
Auth handlers can modify this to enforce per-user scoping.
"""
key: str
"""Unique identifier for the item within its specific namespace."""
class StoreSearch(typing.TypedDict):
"""Operation to search for items within a specified namespace hierarchy."""
"""Operation to search for items within a specified namespace hierarchy.
This dict is mutable auth handlers can modify `namespace` to enforce
access scoping (e.g., prepending the user's identity).
"""
namespace: tuple[str, ...]
"""Prefix filter for defining the search scope."""
"""Prefix filter for defining the search scope.
Auth handlers can modify this to enforce per-user scoping.
"""
filter: dict[str, typing.Any] | None
"""Key-value pairs for filtering results based on exact matches or comparison operators."""
@@ -876,14 +892,22 @@ class StoreSearch(typing.TypedDict):
"""Number of matching items to skip for pagination."""
query: str | None
"""Naturalj language search query for semantic search capabilities."""
"""Natural language search query for semantic search capabilities."""
class StoreListNamespaces(typing.TypedDict):
"""Operation to list and filter namespaces in the store."""
"""Operation to list and filter namespaces in the store.
This dict is mutable auth handlers can modify `namespace` (the prefix)
to enforce access scoping (e.g., prepending the user's identity).
"""
namespace: tuple[str, ...] | None
"""Prefix filter namespaces."""
"""Prefix filter for namespaces. Can be `None` if no prefix was provided.
Auth handlers can modify this to enforce per-user scoping. When `None`,
handlers should set it to `(user_id,)` to scope listing to the user's namespaces.
"""
suffix: tuple[str, ...] | None
"""Optional conditions for filtering namespaces."""
@@ -903,10 +927,17 @@ class StoreListNamespaces(typing.TypedDict):
class StorePut(typing.TypedDict):
"""Operation to store, update, or delete an item in the store."""
"""Operation to store, update, or delete an item in the store.
This dict is mutable auth handlers can modify `namespace` to enforce
access scoping (e.g., prepending the user's identity).
"""
namespace: tuple[str, ...]
"""Hierarchical path that identifies the location of the item."""
"""Hierarchical path that identifies the location of the item.
Auth handlers can modify this to enforce per-user scoping.
"""
key: str
"""Unique identifier for the item within its namespace."""
@@ -919,10 +950,17 @@ class StorePut(typing.TypedDict):
class StoreDelete(typing.TypedDict):
"""Operation to delete an item from the store."""
"""Operation to delete an item from the store.
This dict is mutable auth handlers can modify `namespace` to enforce
access scoping (e.g., prepending the user's identity).
"""
namespace: tuple[str, ...]
"""Hierarchical path that uniquely identifies the item's location."""
"""Hierarchical path that uniquely identifies the item's location.
Auth handlers can modify this to enforce per-user scoping.
"""
key: str
"""Unique identifier for the item within its specific namespace."""
File diff suppressed because it is too large Load Diff
+238
View File
@@ -0,0 +1,238 @@
from __future__ import annotations
import sys
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Generic, Literal, TypeVar
if sys.version_info >= (3, 13):
ContextT = TypeVar("ContextT", default=None)
else:
ContextT = TypeVar("ContextT")
if sys.version_info >= (3, 12):
from typing import TypeAliasType
else:
from typing_extensions import TypeAliasType
from langgraph_sdk.auth.types import BaseUser
if TYPE_CHECKING:
from langgraph.store.base import BaseStore
__all__ = [
"AccessContext",
"ServerRuntime",
]
AccessContext = Literal[
"threads.create_run",
"threads.update",
"threads.read",
"assistants.read",
]
@dataclass(kw_only=True, slots=True, frozen=True)
class _ServerRuntimeBase(Generic[ContextT]):
"""Base for server runtime variants.
!!! warning "Beta"
This API is in beta and may change in future releases.
"""
access_context: AccessContext
"""Why the graph factory is being called.
The server accesses graphs in several contexts beyond just executing runs.
For example, it calls the graph factory to retrieve schemas, render the
graph structure, or read state history. This field tells you which
operation triggered the current call.
In all contexts, the returned graph must have the same topology (nodes,
edges, state schema) as the graph used for execution. Use
`.execution_runtime` to conditionally set up expensive *resources*
(MCP servers, DB connections) without changing the graph structure.
Write contexts (graph is used to write state):
- `threads.create_run` (`graph.astream`) full graph execution
(nodes + edges). `context` is available (use `.execution_runtime`
to narrow).
- `threads.update` (`graph.aupdate_state`) does NOT execute node
functions or evaluate edges. Only runs the node's channel writers
to apply the provided values to state channels as if the specified
node had returned them. Reducers are applied and channel triggers
are set, so the next `invoke`/`stream` call will evaluate edges
from that node to determine the next step. Does not need access to
external resources, but a different graph topology will apply
writes to the wrong channels.
Read state contexts (graph used to format the returned
`StateSnapshot`). A different topology may cause `get_state` to
report incorrect pending tasks. Note that `useStream` uses the state
history endpoint to render interrupts and support branching:
- `threads.read` (`graph.aget_state`, `graph.aget_state_history`)
the graph structure informs which tasks to include in the prepared
view of the latest checkpoint and how to process subgraphs.
Introspection contexts (graph structure only, no execution).
A different topology may cause schemas and visualizations to not
match actual execution:
- `assistants.read` (`graph.aget_graph`, `graph.aget_subgraphs`,
`graph.aget_schemas`) return the graph definition, subgraph
definitions, and input/output/config schemas. Used for
visualization in the studio UI and to populate schemas for MCP,
A2A, and other protocol integrations.
"""
user: BaseUser | None = field(default=None)
"""The authenticated user, or `None` if no custom auth is configured."""
store: BaseStore
"""Store for the graph run, enabling persistence and memory."""
@property
def execution_runtime(self) -> _ExecutionRuntime[ContextT] | None:
"""Narrow to the execution runtime, or `None` if not in an execution context.
When the server calls the graph factory for `threads.create_run`, the returned
object provides access to `context` (typed by the graph's
`context_schema`). For all other access contexts (introspection, state
reads, state updates), this returns `None`.
Use this to conditionally set up expensive resources (MCP tool servers,
database connections, etc.) that are only needed during execution:
```python
import contextlib
from langgraph_sdk.runtime import ServerRuntime
@contextlib.asynccontextmanager
async def my_factory(runtime: ServerRuntime[MyCtx]):
if ert := runtime.execution_runtime:
# Only connect to MCP servers when actually executing a run.
# Introspection calls (get_schema, get_graph, ...) skip this.
mcp_tools = await connect_mcp(ert.context.mcp_endpoint)
yield create_agent(model, tools=mcp_tools)
await disconnect_mcp()
else:
yield create_agent(model, tools=[])
```
"""
if isinstance(self, _ExecutionRuntime):
return self
return None
def ensure_user(self) -> BaseUser:
"""Return the authenticated user, or raise if not available.
When custom auth is configured, `user` is set for all access contexts
(the factory is only called from HTTP handlers where the auth
middleware has already run). This method raises only when no custom
auth is configured.
Raises:
PermissionError: If no user is authenticated.
"""
if self.user is None:
raise PermissionError(
f"No authenticated user available in access_context='{self.access_context}'. "
"Ensure custom auth is configured for the server."
)
return self.user
@dataclass(kw_only=True, slots=True, frozen=True)
class _ExecutionRuntime(_ServerRuntimeBase[ContextT], Generic[ContextT]):
"""Runtime for `threads.create_run` — the graph will be fully executed.
Access this via `.execution_runtime` on `ServerRuntime`. Do not
construct directly.
!!! warning "Beta"
This API is in beta and may change in future releases.
"""
context: ContextT = field(default=None) # type: ignore[assignment]
"""The graph run context, typed by the graph's `context_schema`.
Only available during `threads.create_run`.
"""
@dataclass(kw_only=True, slots=True, frozen=True)
class _ReadRuntime(_ServerRuntimeBase[ContextT], Generic[ContextT]):
"""Runtime for non-execution access contexts.
Used for introspection (`assistants.read`), state operations
(`threads.read`), and state updates (`threads.update`).
No `context` is available.
!!! warning "Beta"
This API is in beta and may change in future releases.
"""
ServerRuntime = TypeAliasType(
"ServerRuntime",
_ExecutionRuntime[ContextT] | _ReadRuntime[ContextT],
type_params=(ContextT,),
)
"""Runtime context passed to graph builder factories within the Agent Server.
Requires version 0.7.30 or later of the agent server.
The server calls your graph factory in multiple contexts: executing runs,
reading state, fetching schemas, and more. `ServerRuntime` provides
the authenticated user, store, and access context for every call. Use
`.execution_runtime` to narrow to the execution variant and access
`context`.
Example conditionally initialize MCP tools only during execution:
```python
import contextlib
from dataclasses import dataclass
from langchain.agents import create_agent
from langgraph_sdk.runtime import ServerRuntime
from my_agent import connect_mcp, disconnect_mcp
@dataclass
class MyCtx:
mcp_endpoint: str
_readonly_agent = create_agent("anthropic:claude-3-5-haiku", tools=[])
@contextlib.asynccontextmanager
async def my_factory(runtime: ServerRuntime[MyCtx]):
if ert := runtime.execution_runtime:
# Only connect to MCP servers for actual runs.
# Schema / graph introspection calls skip this.
user_id = runtime.ensure_user().identity
mcp_tools = await connect_mcp(ert.context.mcp_endpoint, user_id)
yield create_agent("anthropic:claude-3-5-haiku", tools=mcp_tools)
await disconnect_mcp()
else:
yield _readonly_agent
```
Example simple factory that ignores context:
```python
from langgraph_sdk.runtime import ServerRuntime
def build_graph(user: BaseUser) -> CompiledGraph:
...
async def my_factory(runtime: ServerRuntime) -> CompiledGraph:
# No generic needed if you don't use context.
return build_graph(runtime.ensure_user())
```
!!! warning "Beta"
This API is in beta and may change in future releases.
"""
+25 -2
View File
@@ -117,6 +117,13 @@ Specifies behavior if the thread doesn't exist:
- "reject": Reject the operation if the thread doesn't exist.
"""
PruneStrategy = Literal["delete", "keep_latest"]
"""
Strategy for pruning threads:
- "delete": Remove threads entirely.
- "keep_latest": Prune old checkpoints but keep threads and their latest state.
"""
CancelAction = Literal["interrupt", "rollback"]
"""
Action to take when cancelling the run.
@@ -124,6 +131,14 @@ Action to take when cancelling the run.
- "rollback": Cancel the run. Then delete the run and associated checkpoints.
"""
BulkCancelRunsStatus = Literal["pending", "running", "all"]
"""
Filter runs by status when bulk-cancelling:
- "pending": Cancel only pending runs.
- "running": Cancel only running runs.
- "all": Cancel all runs regardless of status.
"""
AssistantSortBy = Literal[
"assistant_id", "graph_id", "name", "created_at", "updated_at"
]
@@ -131,13 +146,21 @@ AssistantSortBy = Literal[
The field to sort by.
"""
ThreadSortBy = Literal["thread_id", "status", "created_at", "updated_at"]
ThreadSortBy = Literal[
"thread_id", "status", "created_at", "updated_at", "state_updated_at"
]
"""
The field to sort by.
"""
CronSortBy = Literal[
"cron_id", "assistant_id", "thread_id", "created_at", "updated_at", "next_run_date"
"cron_id",
"assistant_id",
"thread_id",
"created_at",
"updated_at",
"next_run_date",
"end_time",
]
"""
The field to sort by.
+8 -4
View File
@@ -11,7 +11,7 @@ requires-python = ">=3.10"
readme = "README.md"
license = "MIT"
license-files = ['LICENSE']
dependencies = ["httpx>=0.25.2", "orjson>=3.10.1"]
dependencies = ["httpx>=0.25.2", "orjson>=3.11.5"]
[tool.hatch.version]
path = "langgraph_sdk/__init__.py"
@@ -30,15 +30,16 @@ test = [
"pytest-watch",
]
lint = [
"ruff==0.14.11",
"ruff==0.15.1",
"codespell",
"mypy==1.19.0",
"ty==0.0.1a27",
"mypy==1.19.1",
"ty==0.0.17",
"starlette",
]
dev = [
{ include-group = "test" },
{ include-group = "lint" },
"langgraph",
"pydantic>=2.12.4",
]
@@ -52,6 +53,9 @@ asyncio_mode = "auto"
[tool.uv]
default-groups = ['dev']
[tool.uv.sources]
langgraph = { path = "../langgraph", editable = true }
[tool.ruff]
exclude = ["venv", ".venv", "build", "dist"]
[tool.ruff.lint]
+91
View File
@@ -0,0 +1,91 @@
"""Test that all expected symbols are exported from langgraph_sdk.client.
This test ensures backwards compatibility during refactoring.
"""
import httpx
from langgraph_sdk import get_client as public_get_client
from langgraph_sdk import get_sync_client as public_get_sync_client
from langgraph_sdk.client import (
AssistantsClient,
CronClient,
HttpClient,
LangGraphClient,
RunsClient,
StoreClient,
SyncAssistantsClient,
SyncCronClient,
SyncHttpClient,
SyncLangGraphClient,
SyncRunsClient,
SyncStoreClient,
SyncThreadsClient,
ThreadsClient,
_adecode_json,
_aencode_json,
_decode_json,
_encode_json,
configure_loopback_transports,
get_client,
get_sync_client,
)
def test_client_exports():
"""Verify all expected symbols can be imported from langgraph_sdk.client."""
# Factory functions (public API)
assert callable(get_client)
assert callable(get_sync_client)
# Top-level client classes
assert LangGraphClient is not None
assert SyncLangGraphClient is not None
# HTTP client classes
assert HttpClient is not None
assert SyncHttpClient is not None
# Resource client classes - Async
assert AssistantsClient is not None
assert ThreadsClient is not None
assert RunsClient is not None
assert CronClient is not None
assert StoreClient is not None
# Resource client classes - Sync
assert SyncAssistantsClient is not None
assert SyncThreadsClient is not None
assert SyncRunsClient is not None
assert SyncCronClient is not None
assert SyncStoreClient is not None
# Internal utilities (used by tests)
assert callable(_aencode_json)
assert callable(_adecode_json)
# Sync JSON utilities (might be used internally)
assert callable(_encode_json)
assert callable(_decode_json)
# Loopback transport configuration (used by langgraph-api)
assert callable(configure_loopback_transports)
def test_public_api_exports():
"""Verify public API exports from langgraph_sdk package."""
assert callable(public_get_client)
assert callable(public_get_sync_client)
def test_client_instantiation():
"""Verify that we can instantiate clients."""
# Test async client instantiation
async_http = httpx.AsyncClient(base_url="http://test.example.com")
async_client = HttpClient(async_http)
assert async_client is not None
# Test sync client instantiation
sync_http = httpx.Client(base_url="http://test.example.com")
sync_client = SyncHttpClient(sync_http)
assert sync_client is not None
+2 -2
View File
@@ -19,7 +19,7 @@ class AsyncListByteStream(httpx.AsyncByteStream):
self._chunks = list(chunks)
self._exc = exc
async def __aiter__(self): # type: ignore[override]
async def __aiter__(self):
for chunk in self._chunks:
yield chunk
if self._exc is not None:
@@ -34,7 +34,7 @@ class ListByteStream(httpx.ByteStream):
self._chunks = list(chunks)
self._exc = exc
def __iter__(self): # type: ignore[override]
def __iter__(self):
yield from self._chunks
if self._exc is not None:
raise self._exc
+2 -2
View File
@@ -65,7 +65,7 @@ def test_raise_for_status_typed_maps_exceptions_and_sets_status_code(
with pytest.raises(exc_type) as ei:
_raise_for_status_typed(r)
err = cast("APIStatusError", ei.value)
err = ei.value
assert err.status_code == status
# response attribute should be present and match
assert err.response.status_code == status
@@ -113,7 +113,7 @@ def test_error_message_in_str_and_args() -> None:
r = make_response(422, json_body={"message": "Validation failed"})
with pytest.raises(UnprocessableEntityError) as ei:
_raise_for_status_typed(r)
err = cast("UnprocessableEntityError", ei.value)
err = ei.value
assert str(err) == "Validation failed"
assert err.args == ("Validation failed",)
assert err.message == "Validation failed"
+889 -156
View File
File diff suppressed because it is too large Load Diff