From 4ec897033fc790f85e4253c737aba2f54b1eecc2 Mon Sep 17 00:00:00 2001 From: Josh Rogers Date: Tue, 1 Jul 2025 14:45:30 -0400 Subject: [PATCH 001/129] Update LGP api reference docs (#5297) --- docs/docs/cloud/reference/api/openapi.json | 1713 +++++++++++++++----- 1 file changed, 1327 insertions(+), 386 deletions(-) diff --git a/docs/docs/cloud/reference/api/openapi.json b/docs/docs/cloud/reference/api/openapi.json index 782619368..8a3b7f5fc 100644 --- a/docs/docs/cloud/reference/api/openapi.json +++ b/docs/docs/cloud/reference/api/openapi.json @@ -1,6 +1,9 @@ { "openapi": "3.1.0", - "info": { "title": "LangGraph Platform", "version": "0.1.0" }, + "info": { + "title": "LangGraph Platform", + "version": "0.1.0" + }, "tags": [ { "name": "Assistants", @@ -30,14 +33,18 @@ "paths": { "/assistants": { "post": { - "tags": ["Assistants"], + "tags": [ + "Assistants" + ], "summary": "Create Assistant", "description": "Create an assistant.\n\nAn initial version of the assistant will be created and the assistant is set to that version. To change versions, use the `POST /assistants/{assistant_id}/latest` endpoint.", "operationId": "create_assistant_assistants_post", "requestBody": { "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/AssistantCreate" } + "schema": { + "$ref": "#/components/schemas/AssistantCreate" + } } }, "required": true @@ -47,7 +54,9 @@ "description": "Success", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/Assistant" } + "schema": { + "$ref": "#/components/schemas/Assistant" + } } } }, @@ -55,7 +64,9 @@ "description": "Not Found", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -63,7 +74,9 @@ "description": "Conflict", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -71,7 +84,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -80,7 +95,9 @@ }, "/assistants/search": { "post": { - "tags": ["Assistants"], + "tags": [ + "Assistants" + ], "summary": "Search Assistants", "description": "Search for assistants.\n\nThis endpoint also functions as the endpoint to list all assistants.", "operationId": "search_assistants_assistants_search_post", @@ -100,7 +117,9 @@ "content": { "application/json": { "schema": { - "items": { "$ref": "#/components/schemas/Assistant" }, + "items": { + "$ref": "#/components/schemas/Assistant" + }, "type": "array", "title": "Response Search Assistants Assistants Search Post" } @@ -111,7 +130,9 @@ "description": "Not Found", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -119,7 +140,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -128,7 +151,9 @@ }, "/assistants/{assistant_id}": { "get": { - "tags": ["Assistants"], + "tags": [ + "Assistants" + ], "summary": "Get Assistant", "description": "Get an assistant by ID.", "operationId": "get_assistant_assistants__assistant_id__get", @@ -151,7 +176,9 @@ "description": "Success", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/Assistant" } + "schema": { + "$ref": "#/components/schemas/Assistant" + } } } }, @@ -159,14 +186,18 @@ "description": "Not Found", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } } }, "delete": { - "tags": ["Assistants"], + "tags": [ + "Assistants" + ], "summary": "Delete Assistant", "description": "Delete an assistant by ID.\n\nAll versions of the assistant will be deleted as well.", "operationId": "delete_assistant_assistants__assistant_id__delete", @@ -187,13 +218,19 @@ "responses": { "200": { "description": "Success", - "content": { "application/json": { "schema": {} } } + "content": { + "application/json": { + "schema": {} + } + } }, "404": { "description": "Not Found", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -201,14 +238,18 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } } }, "patch": { - "tags": ["Assistants"], + "tags": [ + "Assistants" + ], "summary": "Patch Assistant", "description": "Update an assistant.", "operationId": "patch_assistant_assistants__assistant_id__patch", @@ -229,7 +270,9 @@ "requestBody": { "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/AssistantPatch" } + "schema": { + "$ref": "#/components/schemas/AssistantPatch" + } } }, "required": true @@ -239,7 +282,9 @@ "description": "Success", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/Assistant" } + "schema": { + "$ref": "#/components/schemas/Assistant" + } } } }, @@ -247,7 +292,9 @@ "description": "Not Found", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -255,7 +302,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -264,7 +313,9 @@ }, "/assistants/{assistant_id}/graph": { "get": { - "tags": ["Assistants"], + "tags": [ + "Assistants" + ], "summary": "Get Assistant Graph", "description": "Get an assistant by ID.", "operationId": "get_assistant_graph_assistants__assistant_id__graph_get", @@ -294,7 +345,14 @@ "description": "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.", "required": false, "schema": { - "oneOf": [{ "type": "boolean" }, { "type": "integer" }], + "oneOf": [ + { + "type": "boolean" + }, + { + "type": "integer" + } + ], "title": "Xray", "default": false, "description": "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." @@ -310,7 +368,9 @@ "application/json": { "schema": { "additionalProperties": { - "items": { "type": "object" }, + "items": { + "type": "object" + }, "type": "array" }, "type": "object", @@ -323,7 +383,9 @@ "description": "Not Found", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -331,7 +393,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -340,7 +404,9 @@ }, "/assistants/{assistant_id}/subgraphs": { "get": { - "tags": ["Assistants"], + "tags": [ + "Assistants" + ], "summary": "Get Assistant Subgraphs", "description": "Get an assistant's subgraphs.", "operationId": "get_assistant_subgraphs_assistants__assistant_id__subgraphs_get", @@ -373,7 +439,9 @@ "description": "Success", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/Subgraphs" } + "schema": { + "$ref": "#/components/schemas/Subgraphs" + } } } }, @@ -381,7 +449,9 @@ "description": "Not Found", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -389,7 +459,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -398,7 +470,9 @@ }, "/assistants/{assistant_id}/subgraphs/{namespace}": { "get": { - "tags": ["Assistants"], + "tags": [ + "Assistants" + ], "summary": "Get Assistant Subgraphs by Namespace", "description": "Get an assistant's subgraphs filtered by namespace.", "operationId": "get_assistant_subgraphs_assistants__assistant_id__subgraphs__namespace__get", @@ -417,7 +491,10 @@ { "description": "Namespace of the subgraph to filter by.", "required": true, - "schema": { "type": "string", "title": "Namespace" }, + "schema": { + "type": "string", + "title": "Namespace" + }, "name": "namespace", "in": "path" }, @@ -438,7 +515,9 @@ "description": "Success", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/Subgraphs" } + "schema": { + "$ref": "#/components/schemas/Subgraphs" + } } } }, @@ -446,7 +525,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -455,7 +536,9 @@ }, "/assistants/{assistant_id}/schemas": { "get": { - "tags": ["Assistants"], + "tags": [ + "Assistants" + ], "summary": "Get Assistant Schemas", "description": "Get an assistant by ID.", "operationId": "get_assistant_schemas_assistants__assistant_id__schemas_get", @@ -478,7 +561,9 @@ "description": "Success", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/GraphSchema" } + "schema": { + "$ref": "#/components/schemas/GraphSchema" + } } } }, @@ -486,7 +571,9 @@ "description": "Not Found", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -494,7 +581,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -503,7 +592,9 @@ }, "/assistants/{assistant_id}/versions": { "post": { - "tags": ["Assistants"], + "tags": [ + "Assistants" + ], "summary": "Get Assistant Versions", "description": "Get all versions of an assistant.", "operationId": "get_assistant_versions_assistants__assistant_id__versions_get", @@ -527,7 +618,9 @@ "content": { "application/json": { "schema": { - "items": { "$ref": "#/components/schemas/Assistant" }, + "items": { + "$ref": "#/components/schemas/Assistant" + }, "type": "array", "title": "Response Search Assistants Assistants Search Post" } @@ -538,7 +631,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -547,7 +642,9 @@ }, "/assistants/{assistant_id}/latest": { "post": { - "tags": ["Assistants"], + "tags": [ + "Assistants" + ], "summary": "Set Latest Assistant Version", "description": "Set the latest version for an assistant.", "operationId": "set_latest_assistant_version_assistants__assistant_id__versions_post", @@ -581,7 +678,9 @@ "description": "Success", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/Assistant" } + "schema": { + "$ref": "#/components/schemas/Assistant" + } } } }, @@ -589,7 +688,9 @@ "description": "Not Found", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -597,7 +698,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -606,14 +709,18 @@ }, "/threads": { "post": { - "tags": ["Threads"], + "tags": [ + "Threads" + ], "summary": "Create Thread", "description": "Create a thread.", "operationId": "create_thread_threads_post", "requestBody": { "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ThreadCreate" } + "schema": { + "$ref": "#/components/schemas/ThreadCreate" + } } }, "required": true @@ -623,7 +730,9 @@ "description": "Success", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/Thread" } + "schema": { + "$ref": "#/components/schemas/Thread" + } } } }, @@ -631,7 +740,9 @@ "description": "Conflict", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -639,7 +750,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -648,7 +761,9 @@ }, "/threads/search": { "post": { - "tags": ["Threads"], + "tags": [ + "Threads" + ], "summary": "Search Threads", "description": "Search for threads.\n\nThis endpoint also functions as the endpoint to list all threads.", "operationId": "search_threads_threads_search_post", @@ -668,7 +783,9 @@ "content": { "application/json": { "schema": { - "items": { "$ref": "#/components/schemas/Thread" }, + "items": { + "$ref": "#/components/schemas/Thread" + }, "type": "array", "title": "Response Search Threads Threads Search Post" } @@ -679,7 +796,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -688,7 +807,9 @@ }, "/threads/{thread_id}/state": { "get": { - "tags": ["Threads"], + "tags": [ + "Threads" + ], "summary": "Get Thread State", "description": "Get state for a thread.\n\nThe latest state of the thread (i.e. latest checkpoint) is returned.", "operationId": "get_latest_thread_state_threads__thread_id__state_get", @@ -722,7 +843,9 @@ "description": "Success", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ThreadState" } + "schema": { + "$ref": "#/components/schemas/ThreadState" + } } } }, @@ -730,14 +853,18 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } } }, "post": { - "tags": ["Threads"], + "tags": [ + "Threads" + ], "summary": "Update Thread State", "description": "Add state to a thread.", "operationId": "update_thread_state_threads__thread_id__state_post", @@ -758,7 +885,9 @@ "requestBody": { "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ThreadStateUpdate" } + "schema": { + "$ref": "#/components/schemas/ThreadStateUpdate" + } } }, "required": true @@ -778,7 +907,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -787,7 +918,9 @@ }, "/threads/{thread_id}/state/{checkpoint_id}": { "get": { - "tags": ["Threads"], + "tags": [ + "Threads" + ], "summary": "Get Thread State At Checkpoint", "description": "Get state for a thread at a specific checkpoint.", "operationId": "get_thread_state_at_checkpoint_threads__thread_id__state__checkpoint_id__get", @@ -833,7 +966,9 @@ "description": "Success", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ThreadState" } + "schema": { + "$ref": "#/components/schemas/ThreadState" + } } } }, @@ -841,7 +976,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -850,7 +987,9 @@ }, "/threads/{thread_id}/state/checkpoint": { "post": { - "tags": ["Threads"], + "tags": [ + "Threads" + ], "summary": "Get Thread State At Checkpoint", "description": "Get state for a thread at a specific checkpoint.", "operationId": "post_thread_state_at_checkpoint_threads__thread_id__state__checkpoint_id__get", @@ -893,7 +1032,9 @@ "description": "Success", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ThreadState" } + "schema": { + "$ref": "#/components/schemas/ThreadState" + } } } }, @@ -901,7 +1042,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -910,7 +1053,9 @@ }, "/threads/{thread_id}/history": { "get": { - "tags": ["Threads"], + "tags": [ + "Threads" + ], "summary": "Get Thread History", "description": "Get all past states for a thread.", "operationId": "get_thread_history_threads__thread_id__history_get", @@ -929,13 +1074,20 @@ }, { "required": false, - "schema": { "type": "integer", "title": "Limit", "default": 10 }, + "schema": { + "type": "integer", + "title": "Limit", + "default": 10 + }, "name": "limit", "in": "query" }, { "required": false, - "schema": { "type": "string", "title": "Before" }, + "schema": { + "type": "string", + "title": "Before" + }, "name": "before", "in": "query" } @@ -959,14 +1111,18 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } } }, "post": { - "tags": ["Threads"], + "tags": [ + "Threads" + ], "summary": "Get Thread History Post", "description": "Get all past states for a thread.", "operationId": "get_thread_history_post_threads__thread_id__history_post", @@ -987,7 +1143,9 @@ "requestBody": { "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ThreadStateSearch" } + "schema": { + "$ref": "#/components/schemas/ThreadStateSearch" + } } }, "required": true @@ -1011,7 +1169,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -1020,7 +1180,9 @@ }, "/threads/{thread_id}/copy": { "post": { - "tags": ["Threads"], + "tags": [ + "Threads" + ], "summary": "Copy Thread", "description": "Create a new thread with a copy of the state and checkpoints from an existing thread.", "operationId": "copy_thread_post_threads__thread_id__copy_post", @@ -1043,7 +1205,9 @@ "description": "Success", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/Thread" } + "schema": { + "$ref": "#/components/schemas/Thread" + } } } }, @@ -1051,7 +1215,9 @@ "description": "Conflict", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -1059,7 +1225,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -1068,7 +1236,9 @@ }, "/threads/{thread_id}": { "get": { - "tags": ["Threads"], + "tags": [ + "Threads" + ], "summary": "Get Thread", "description": "Get a thread by ID.", "operationId": "get_thread_threads__thread_id__get", @@ -1091,7 +1261,9 @@ "description": "Success", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/Thread" } + "schema": { + "$ref": "#/components/schemas/Thread" + } } } }, @@ -1099,7 +1271,9 @@ "description": "Not Found", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -1107,14 +1281,18 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } } }, "delete": { - "tags": ["Threads"], + "tags": [ + "Threads" + ], "summary": "Delete Thread", "description": "Delete a thread by ID.", "operationId": "delete_thread_threads__thread_id__delete", @@ -1135,13 +1313,19 @@ "responses": { "200": { "description": "Success", - "content": { "application/json": { "schema": {} } } + "content": { + "application/json": { + "schema": {} + } + } }, "404": { "description": "Not Found", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -1149,14 +1333,18 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } } }, "patch": { - "tags": ["Threads"], + "tags": [ + "Threads" + ], "summary": "Patch Thread", "description": "Update a thread.", "operationId": "patch_thread_threads__thread_id__patch", @@ -1177,7 +1365,9 @@ "requestBody": { "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ThreadPatch" } + "schema": { + "$ref": "#/components/schemas/ThreadPatch" + } } }, "required": true @@ -1187,7 +1377,9 @@ "description": "Success", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/Thread" } + "schema": { + "$ref": "#/components/schemas/Thread" + } } } }, @@ -1195,7 +1387,9 @@ "description": "Not Found", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -1203,7 +1397,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -1212,7 +1408,9 @@ }, "/threads/{thread_id}/runs": { "get": { - "tags": ["Thread Runs"], + "tags": [ + "Thread Runs" + ], "summary": "List Runs", "description": "List runs for a thread.", "operationId": "list_runs_http_threads__thread_id__runs_get", @@ -1231,13 +1429,21 @@ }, { "required": false, - "schema": { "type": "integer", "title": "Limit", "default": 10 }, + "schema": { + "type": "integer", + "title": "Limit", + "default": 10 + }, "name": "limit", "in": "query" }, { "required": false, - "schema": { "type": "integer", "title": "Offset", "default": 0 }, + "schema": { + "type": "integer", + "title": "Offset", + "default": 0 + }, "name": "offset", "in": "query" }, @@ -1245,7 +1451,13 @@ "required": false, "schema": { "type": "string", - "enum": ["pending", "error", "success", "timeout", "interrupted"] + "enum": [ + "pending", + "error", + "success", + "timeout", + "interrupted" + ] }, "name": "status", "in": "query" @@ -1257,7 +1469,9 @@ "content": { "application/json": { "schema": { - "items": { "$ref": "#/components/schemas/Run" }, + "items": { + "$ref": "#/components/schemas/Run" + }, "type": "array" } } @@ -1267,7 +1481,9 @@ "description": "Not Found", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -1275,14 +1491,18 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } } }, "post": { - "tags": ["Thread Runs"], + "tags": [ + "Thread Runs" + ], "summary": "Create Background Run", "description": "Create a run in existing thread, return the run ID immediately. Don't wait for the final run output.", "operationId": "create_run_threads__thread_id__runs_post", @@ -1303,7 +1523,9 @@ "requestBody": { "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/RunCreateStateful" } + "schema": { + "$ref": "#/components/schemas/RunCreateStateful" + } } }, "required": true @@ -1313,7 +1535,17 @@ "description": "Success", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/Run" } + "schema": { + "$ref": "#/components/schemas/Run" + } + } + }, + "headers": { + "Content-Location": { + "description": "The URL of the run that was created. Can be used to later join the stream.", + "schema": { + "type": "string" + } } } }, @@ -1321,7 +1553,9 @@ "description": "Not Found", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -1329,7 +1563,9 @@ "description": "Conflict", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -1337,7 +1573,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -1346,7 +1584,9 @@ }, "/threads/{thread_id}/runs/crons": { "post": { - "tags": ["Crons (Plus tier)"], + "tags": [ + "Crons (Plus tier)" + ], "summary": "Create Thread Cron", "description": "Create a cron to schedule runs on a thread.", "operationId": "create_thread_cron_threads__thread_id__runs_crons_post", @@ -1367,7 +1607,9 @@ "requestBody": { "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/CronCreate" } + "schema": { + "$ref": "#/components/schemas/CronCreate" + } } }, "required": true @@ -1377,7 +1619,9 @@ "description": "Success", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/Cron" } + "schema": { + "$ref": "#/components/schemas/Cron" + } } } }, @@ -1385,7 +1629,9 @@ "description": "Not Found", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -1393,7 +1639,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -1402,7 +1650,9 @@ }, "/threads/{thread_id}/runs/stream": { "post": { - "tags": ["Thread Runs"], + "tags": [ + "Thread Runs" + ], "summary": "Create Run, Stream Output", "description": "Create a run in existing thread. Stream the output.", "operationId": "stream_run_threads__thread_id__runs_stream_post", @@ -1423,7 +1673,9 @@ "requestBody": { "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/RunCreateStateful" } + "schema": { + "$ref": "#/components/schemas/RunCreateStateful" + } } }, "required": true @@ -1438,13 +1690,23 @@ "description": "The server will send a stream of events in SSE format.\n\n**Example event**:\n\nid: 1\n\nevent: message\n\ndata: {}" } } + }, + "headers": { + "Content-Location": { + "description": "The URL of the run that was created. Can be used to later join the stream.", + "schema": { + "type": "string" + } + } } }, "404": { "description": "Not Found", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -1452,7 +1714,9 @@ "description": "Conflict", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -1460,7 +1724,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -1469,7 +1735,9 @@ }, "/threads/{thread_id}/runs/wait": { "post": { - "tags": ["Thread Runs"], + "tags": [ + "Thread Runs" + ], "summary": "Create Run, Wait for Output", "description": "Create a run in existing thread. Wait for the final output and then return it.", "operationId": "wait_run_threads__thread_id__runs_wait_post", @@ -1490,7 +1758,9 @@ "requestBody": { "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/RunCreateStateful" } + "schema": { + "$ref": "#/components/schemas/RunCreateStateful" + } } }, "required": true @@ -1498,13 +1768,27 @@ "responses": { "200": { "description": "Success", - "content": { "application/json": { "schema": {} } } + "content": { + "application/json": { + "schema": {} + } + }, + "headers": { + "Content-Location": { + "description": "The URL of the run that was created. Can be used to later join the stream.", + "schema": { + "type": "string" + } + } + } }, "404": { "description": "Not Found", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -1512,7 +1796,9 @@ "description": "Conflict", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -1520,7 +1806,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -1529,7 +1817,9 @@ }, "/threads/{thread_id}/runs/{run_id}": { "get": { - "tags": ["Thread Runs"], + "tags": [ + "Thread Runs" + ], "summary": "Get Run", "description": "Get a run by ID.", "operationId": "get_run_http_threads__thread_id__runs__run_id__get", @@ -1564,7 +1854,9 @@ "description": "Success", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/Run" } + "schema": { + "$ref": "#/components/schemas/Run" + } } } }, @@ -1572,7 +1864,9 @@ "description": "Not Found", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -1580,14 +1874,18 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } } }, "delete": { - "tags": ["Thread Runs"], + "tags": [ + "Thread Runs" + ], "summary": "Delete Run", "description": "Delete a run by ID.", "operationId": "delete_run_threads__thread_id__runs__run_id__delete", @@ -1620,13 +1918,19 @@ "responses": { "200": { "description": "Success", - "content": { "application/json": { "schema": {} } } + "content": { + "application/json": { + "schema": {} + } + } }, "404": { "description": "Not Found", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -1634,7 +1938,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -1643,7 +1949,9 @@ }, "/threads/{thread_id}/runs/{run_id}/join": { "get": { - "tags": ["Thread Runs"], + "tags": [ + "Thread Runs" + ], "summary": "Join Run", "description": "Wait for a run to finish.", "operationId": "join_run_http_threads__thread_id__runs__run_id__join_get", @@ -1687,13 +1995,19 @@ "responses": { "200": { "description": "Success", - "content": { "application/json": { "schema": {} } } + "content": { + "application/json": { + "schema": {} + } + } }, "404": { "description": "Not Found", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -1701,7 +2015,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -1710,9 +2026,11 @@ }, "/threads/{thread_id}/runs/{run_id}/stream": { "get": { - "tags": ["Thread Runs"], + "tags": [ + "Thread Runs" + ], "summary": "Join Run Stream", - "description": "Join a run stream. This endpoint streams output in real-time from a run similar to the /threads/__THREAD_ID__/runs/stream endpoint. Only output produced after this endpoint is called will be streamed.", + "description": "Join a run stream. This endpoint streams output in real-time from a run similar to the /threads/__THREAD_ID__/runs/stream endpoint. If the run has been created with `stream_resumable=true`, the stream can be resumed from the last seen event ID.", "operationId": "stream_run_http_threads__thread_id__runs__run_id__join_get", "parameters": [ { @@ -1738,6 +2056,37 @@ }, "name": "run_id", "in": "path" + }, + { + "required": false, + "schema": { + "type": "string", + "title": "Last Event ID", + "description": "The ID of the last event received. Set to -1 if you want to stream all events. Requires `stream_resumable=true` to be set when creating the run." + }, + "name": "Last-Event-ID", + "in": "header" + }, + { + "required": false, + "schema": { + "type": "string", + "title": "Stream Mode", + "description": "The mode to stream the run in. If not provided, the default mode will be used." + }, + "name": "stream_mode", + "in": "query" + }, + { + "required": false, + "schema": { + "type": "boolean", + "title": "Cancel On Disconnect", + "description": "If true, the run will be cancelled if the client disconnects.", + "default": false + }, + "name": "cancel_on_disconnect", + "in": "query" } ], "responses": { @@ -1756,7 +2105,9 @@ "description": "Not Found", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -1764,7 +2115,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -1773,7 +2126,9 @@ }, "/threads/{thread_id}/runs/{run_id}/cancel": { "post": { - "tags": ["Thread Runs"], + "tags": [ + "Thread Runs" + ], "summary": "Cancel Run", "operationId": "cancel_run_http_threads__thread_id__runs__run_id__cancel_post", "parameters": [ @@ -1816,7 +2171,10 @@ "required": false, "schema": { "type": "string", - "enum": ["interrupt", "rollback"], + "enum": [ + "interrupt", + "rollback" + ], "title": "Action", "default": "interrupt" }, @@ -1827,13 +2185,19 @@ "responses": { "200": { "description": "Success", - "content": { "application/json": { "schema": {} } } + "content": { + "application/json": { + "schema": {} + } + } }, "404": { "description": "Not Found", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -1841,7 +2205,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -1850,58 +2216,20 @@ }, "/runs/crons": { "post": { - "tags": ["Crons (Plus tier)"], + "tags": [ + "Crons (Plus tier)" + ], "summary": "Create Cron", "description": "Create a cron to schedule runs on new threads.", "operationId": "create_cron_runs_crons_post", "requestBody": { "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/CronCreate" } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Success", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/Cron" } + "schema": { + "$ref": "#/components/schemas/CronCreate" } } }, - "404": { - "description": "Not Found", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } - } - } - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } - } - } - } - } - } - }, - "/runs/crons/search": { - "post": { - "tags": ["Crons (Plus tier)"], - "summary": "Search Crons", - "description": "Search all active crons", - "operationId": "search_crons_runs_crons_post", - "requestBody": { - "content": { - "application/json": { - "schema": { "$ref": "#/components/schemas/CronSearch" } - } - }, "required": true }, "responses": { @@ -1910,7 +2238,61 @@ "content": { "application/json": { "schema": { - "items": { "$ref": "#/components/schemas/Cron" }, + "$ref": "#/components/schemas/Cron" + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + } + }, + "/runs/crons/search": { + "post": { + "tags": [ + "Crons (Plus tier)" + ], + "summary": "Search Crons", + "description": "Search all active crons", + "operationId": "search_crons_runs_crons_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CronSearch" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "items": { + "$ref": "#/components/schemas/Cron" + }, "type": "array", "title": "Response Search Crons Search Post" } @@ -1921,7 +2303,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -1930,7 +2314,9 @@ }, "/runs/stream": { "post": { - "tags": ["Stateless Runs"], + "tags": [ + "Stateless Runs" + ], "summary": "Create Run, Stream Output", "description": "Create a run in a new thread, stream the output.", "operationId": "stream_run_stateless_runs_stream_post", @@ -1954,13 +2340,23 @@ "description": "The server will send a stream of events in SSE format.\n\n**Example event**:\n\nid: 1\n\nevent: message\n\ndata: {}" } } + }, + "headers": { + "Content-Location": { + "description": "The URL of the run that was created. Can be used to later join the stream.", + "schema": { + "type": "string" + } + } } }, "404": { "description": "Not Found", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -1968,7 +2364,9 @@ "description": "Conflict", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -1976,7 +2374,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -1985,7 +2385,9 @@ }, "/runs/cancel": { "post": { - "tags": ["Thread Runs"], + "tags": [ + "Thread Runs" + ], "summary": "Cancel Runs", "description": "Cancel one or more runs. Can cancel runs by thread ID and run IDs, or by status filter.", "operationId": "cancel_runs_post", @@ -1995,7 +2397,10 @@ "required": false, "schema": { "type": "string", - "enum": ["interrupt", "rollback"], + "enum": [ + "interrupt", + "rollback" + ], "title": "Action", "default": "interrupt" }, @@ -2006,18 +2411,24 @@ "requestBody": { "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/RunsCancel" } + "schema": { + "$ref": "#/components/schemas/RunsCancel" + } } }, "required": true }, "responses": { - "204": { "description": "Success - Runs cancelled" }, + "204": { + "description": "Success - Runs cancelled" + }, "404": { "description": "Not Found", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -2025,7 +2436,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -2034,7 +2447,9 @@ }, "/runs/wait": { "post": { - "tags": ["Stateless Runs"], + "tags": [ + "Stateless Runs" + ], "summary": "Create Run, Wait for Output", "description": "Create a run in a new thread. Wait for the final output and then return it.", "operationId": "wait_run_stateless_runs_wait_post", @@ -2051,13 +2466,27 @@ "responses": { "200": { "description": "Success", - "content": { "application/json": { "schema": {} } } + "content": { + "application/json": { + "schema": {} + } + }, + "headers": { + "Content-Location": { + "description": "The URL of the run that was created. Can be used to later join the stream.", + "schema": { + "type": "string" + } + } + } }, "404": { "description": "Not Found", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -2065,7 +2494,9 @@ "description": "Conflict", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -2073,7 +2504,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -2082,7 +2515,9 @@ }, "/runs": { "post": { - "tags": ["Stateless Runs"], + "tags": [ + "Stateless Runs" + ], "summary": "Create Background Run", "description": "Create a run in a new thread, return the run ID immediately. Don't wait for the final run output.", "operationId": "run_stateless_runs_post", @@ -2099,13 +2534,27 @@ "responses": { "200": { "description": "Success", - "content": { "application/json": { "schema": {} } } + "content": { + "application/json": { + "schema": {} + } + }, + "headers": { + "Content-Location": { + "description": "The URL of the run that was created. Can be used to later join the stream.", + "schema": { + "type": "string" + } + } + } }, "404": { "description": "Not Found", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -2113,7 +2562,9 @@ "description": "Conflict", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -2121,7 +2572,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -2130,14 +2583,18 @@ }, "/runs/batch": { "post": { - "tags": ["Stateless Runs"], + "tags": [ + "Stateless Runs" + ], "summary": "Create Run Batch", "description": "Create a batch of runs in new threads, return immediately.", "operationId": "run_batch_stateless_runs_post", "requestBody": { "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/RunBatchCreate" } + "schema": { + "$ref": "#/components/schemas/RunBatchCreate" + } } }, "required": true @@ -2145,13 +2602,19 @@ "responses": { "200": { "description": "Success", - "content": { "application/json": { "schema": {} } } + "content": { + "application/json": { + "schema": {} + } + } }, "404": { "description": "Not Found", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -2159,7 +2622,9 @@ "description": "Conflict", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -2167,7 +2632,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -2176,7 +2643,9 @@ }, "/runs/crons/{cron_id}": { "delete": { - "tags": ["Crons (Plus tier)"], + "tags": [ + "Crons (Plus tier)" + ], "summary": "Delete Cron", "description": "Delete a cron by ID.", "operationId": "delete_cron_runs_crons__cron_id__delete", @@ -2195,13 +2664,19 @@ "responses": { "200": { "description": "Success", - "content": { "application/json": { "schema": {} } } + "content": { + "application/json": { + "schema": {} + } + } }, "404": { "description": "Not Found", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -2209,7 +2684,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -2218,31 +2695,41 @@ }, "/store/items": { "put": { - "tags": ["Store"], + "tags": [ + "Store" + ], "summary": "Store or update an item.", "operationId": "put_item", "requestBody": { "required": true, "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/StorePutRequest" } + "schema": { + "$ref": "#/components/schemas/StorePutRequest" + } } } }, "responses": { - "204": { "description": "Success" }, + "204": { + "description": "Success" + }, "422": { "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } } }, "delete": { - "tags": ["Store"], + "tags": [ + "Store" + ], "summary": "Delete an item.", "operationId": "delete_item", "requestBody": { @@ -2256,19 +2743,25 @@ } }, "responses": { - "204": { "description": "Success" }, + "204": { + "description": "Success" + }, "422": { "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } } }, "get": { - "tags": ["Store"], + "tags": [ + "Store" + ], "summary": "Retrieve a single item.", "operationId": "get_item", "parameters": [ @@ -2276,13 +2769,20 @@ "name": "key", "in": "query", "required": true, - "schema": { "type": "string" } + "schema": { + "type": "string" + } }, { "name": "namespace", "in": "query", "required": false, - "schema": { "type": "array", "items": { "type": "string" } } + "schema": { + "type": "array", + "items": { + "type": "string" + } + } } ], "responses": { @@ -2290,7 +2790,9 @@ "description": "Success", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/Item" } + "schema": { + "$ref": "#/components/schemas/Item" + } } } }, @@ -2298,7 +2800,9 @@ "description": "Bad Request", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } }, @@ -2306,7 +2810,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -2315,7 +2821,9 @@ }, "/store/items/search": { "post": { - "tags": ["Store"], + "tags": [ + "Store" + ], "summary": "Search for items within a namespace prefix.", "operationId": "search_items", "requestBody": { @@ -2343,7 +2851,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -2352,7 +2862,9 @@ }, "/store/namespaces": { "post": { - "tags": ["Store"], + "tags": [ + "Store" + ], "summary": "List namespaces with optional match conditions.", "operationId": "list_namespaces", "requestBody": { @@ -2380,7 +2892,9 @@ "description": "Validation Error", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } @@ -2399,7 +2913,9 @@ "required": true, "schema": { "type": "string", - "enum": ["application/json, text/event-stream"] + "enum": [ + "application/json, text/event-stream" + ] }, "description": "Accept header must include both 'application/json' and 'text/event-stream' media types." } @@ -2408,7 +2924,9 @@ "required": true, "content": { "application/json": { - "schema": { "type": "object" }, + "schema": { + "type": "object" + }, "description": "A JSON-RPC 2.0 request, notification, or response object.", "example": { "jsonrpc": "2.0", @@ -2430,7 +2948,11 @@ "200": { "description": "Successful JSON-RPC response.", "content": { - "application/json": { "schema": { "type": "object" } } + "application/json": { + "schema": { + "type": "object" + } + } } }, "202": { @@ -2439,12 +2961,16 @@ "400": { "description": "Bad request: invalid JSON or message format, or unacceptable Accept header." }, - "405": { "description": "HTTP method not allowed." }, + "405": { + "description": "HTTP method not allowed." + }, "500": { "description": "Internal server error or unexpected failure." } }, - "tags": ["MCP"] + "tags": [ + "MCP" + ] }, "get": { "operationId": "get_mcp", @@ -2455,14 +2981,20 @@ "description": "GET method not allowed; streaming not supported." } }, - "tags": ["MCP"] + "tags": [ + "MCP" + ] }, "delete": { "operationId": "delete_mcp", "summary": "Terminate Session", "description": "Implemented according to the Streamable HTTP Transport specification.\nTerminate an MCP session. The server implementation is stateless, so this is a no-op.\n\n", - "responses": { "404": {} }, - "tags": ["MCP"] + "responses": { + "404": {} + }, + "tags": [ + "MCP" + ] } } }, @@ -2484,7 +3016,9 @@ "config": { "properties": { "tags": { - "items": { "type": "string" }, + "items": { + "type": "string" + }, "type": "array", "title": "Tags" }, @@ -2492,7 +3026,10 @@ "type": "integer", "title": "Recursion Limit" }, - "configurable": { "type": "object", "title": "Configurable" } + "configurable": { + "type": "object", + "title": "Configurable" + } }, "type": "object", "title": "Config", @@ -2526,7 +3063,10 @@ "description": "The name of the assistant" }, "description": { - "type": ["string", "null"], + "type": [ + "string", + "null" + ], "title": "Assistant Description", "description": "The description of the assistant" } @@ -2567,7 +3107,10 @@ }, "if_exists": { "type": "string", - "enum": ["raise", "do_nothing"], + "enum": [ + "raise", + "do_nothing" + ], "title": "If Exists", "description": "How to handle duplicate creation. Must be either 'raise' (raise error if duplicate), or 'do_nothing' (return existing assistant).", "default": "raise" @@ -2578,13 +3121,18 @@ "description": "The name of the assistant. Defaults to 'Untitled'." }, "description": { - "type": ["string", "null"], + "type": [ + "string", + "null" + ], "title": "Description", "description": "The description of the assistant. Defaults to null." } }, "type": "object", - "required": ["graph_id"], + "required": [ + "graph_id" + ], "title": "AssistantCreate", "description": "Payload for creating an assistant." }, @@ -2601,7 +3149,8 @@ "description": "Configuration to use for the graph. Useful when graph is configurable and you want to update the assistant's configuration." }, "metadata": { - "type": "object", "title": "Metadata", + "type": "object", + "title": "Metadata", "description": "Metadata to merge with existing assistant metadata." }, "name": { @@ -2634,12 +3183,20 @@ "Config": { "properties": { "tags": { - "items": { "type": "string" }, + "items": { + "type": "string" + }, "type": "array", "title": "Tags" }, - "recursion_limit": { "type": "integer", "title": "Recursion Limit" }, - "configurable": { "type": "object", "title": "Configurable" } + "recursion_limit": { + "type": "integer", + "title": "Recursion Limit" + }, + "configurable": { + "type": "object", + "title": "Configurable" + } }, "type": "object", "title": "Config" @@ -2713,7 +3270,6 @@ "title": "End Time", "description": "The end date to stop running the cron." }, - "assistant_id": { "anyOf": [ { @@ -2721,14 +3277,24 @@ "format": "uuid", "title": "Assistant Id" }, - { "type": "string", "title": "Graph Id" } + { + "type": "string", + "title": "Graph Id" + } ], "description": "The assistant ID or graph name to run. If using graph name, will default to the assistant automatically created from that graph by the server." }, "input": { "anyOf": [ - { "items": { "type": "object" }, "type": "array" }, - { "type": "object" } + { + "items": { + "type": "object" + }, + "type": "array" + }, + { + "type": "object" + } ], "title": "Input", "description": "The input to the graph." @@ -2741,7 +3307,9 @@ "config": { "properties": { "tags": { - "items": { "type": "string" }, + "items": { + "type": "string" + }, "type": "array", "title": "Tags" }, @@ -2749,7 +3317,10 @@ "type": "integer", "title": "Recursion Limit" }, - "configurable": { "type": "object", "title": "Configurable" } + "configurable": { + "type": "object", + "title": "Configurable" + } }, "type": "object", "title": "Config", @@ -2765,30 +3336,58 @@ }, "interrupt_before": { "anyOf": [ - { "type": "string", "enum": ["*"] }, - { "items": { "type": "string" }, "type": "array" } + { + "type": "string", + "enum": [ + "*" + ] + }, + { + "items": { + "type": "string" + }, + "type": "array" + } ], "title": "Interrupt Before", "description": "Nodes to interrupt immediately before they get executed." }, "interrupt_after": { "anyOf": [ - { "type": "string", "enum": ["*"] }, - { "items": { "type": "string" }, "type": "array" } + { + "type": "string", + "enum": [ + "*" + ] + }, + { + "items": { + "type": "string" + }, + "type": "array" + } ], "title": "Interrupt After", "description": "Nodes to interrupt immediately after they get executed." }, "multitask_strategy": { "type": "string", - "enum": ["reject", "rollback", "interrupt", "enqueue"], + "enum": [ + "reject", + "rollback", + "interrupt", + "enqueue" + ], "title": "Multitask Strategy", "description": "Multitask strategy to use. Must be one of 'reject', 'interrupt', 'rollback', or 'enqueue'.", "default": "reject" } }, "type": "object", - "required": ["assistant_id", "schedule"], + "required": [ + "assistant_id", + "schedule" + ], "title": "CronCreate", "description": "Payload for creating a cron job." }, @@ -2823,15 +3422,17 @@ }, "sort_by": { "type": "string", - "enum": ["cron_id", "assistant_id", "thread_id", "next_run_date", "end_time", "created_at", "updated_at"], "title": "Sort By", - "description": "The field to sort by." + "description": "The field to sort by.", + "default": "created_at", + "enum": ["cron_id", "assistant_id", "thread_id", "next_run_date", "end_time", "created_at", "updated_at"] }, "sort_order": { "type": "string", - "enum": ["asc", "desc"], "title": "Sort Order", - "description": "The order to sort by." + "description": "The order to sort by.", + "default": "desc", + "enum": ["asc", "desc"] } }, "type": "object", @@ -2868,7 +3469,11 @@ } }, "type": "object", - "required": ["graph_id", "state_schema", "config_schema"], + "required": [ + "graph_id", + "state_schema", + "config_schema" + ], "title": "GraphSchema", "description": "Defines the structure and properties of a graph." }, @@ -2947,19 +3552,34 @@ }, "status": { "type": "string", - "enum": ["pending", "error", "success", "timeout", "interrupted"], + "enum": [ + "pending", + "running", + "error", + "success", + "timeout", + "interrupted" + ], "title": "Status", - "description": "The status of the run. One of 'pending', 'error', 'success', 'timeout', 'interrupted'." + "description": "The status of the run. One of 'pending', 'running', 'error', 'success', 'timeout', 'interrupted'." }, "metadata": { "type": "object", "title": "Metadata", "description": "The run metadata." }, - "kwargs": { "type": "object", "title": "Kwargs" }, + "kwargs": { + "type": "object", + "title": "Kwargs" + }, "multitask_strategy": { "type": "string", - "enum": ["reject", "rollback", "interrupt", "enqueue"], + "enum": [ + "reject", + "rollback", + "interrupt", + "enqueue" + ], "title": "Multitask Strategy", "description": "Strategy to handle concurrent runs on the same thread." } @@ -2989,12 +3609,22 @@ "description": "The node to send the message to." }, "input": { - "type": ["object", "array", "number", "string", "boolean", "null"], + "type": [ + "object", + "array", + "number", + "string", + "boolean", + "null" + ], "title": "Message", "description": "The message to send." } }, - "required": ["node", "input"] + "required": [ + "node", + "input" + ] }, "Command": { "type": "object", @@ -3002,25 +3632,49 @@ "description": "The command to run.", "properties": { "update": { - "type": ["object", "array", "null"], + "type": [ + "object", + "array", + "null" + ], "title": "Update", "description": "An update to the state." }, "resume": { - "type": ["object", "array", "number", "string", "boolean", "null"], + "type": [ + "object", + "array", + "number", + "string", + "boolean", + "null" + ], "title": "Resume", "description": "A value to pass to an interrupted node." }, "goto": { "anyOf": [ - { "$ref": "#/components/schemas/Send" }, + { + "$ref": "#/components/schemas/Send" + }, { "type": "array", - "items": { "$ref": "#/components/schemas/Send" } + "items": { + "$ref": "#/components/schemas/Send" + } }, - { "type": "string" }, - { "type": "array", "items": { "type": "string" } }, - { "type": "null" } + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } ], "title": "Goto", "description": "Name of the node(s) to navigate to next or node(s) to be executed with a provided input." @@ -3036,7 +3690,10 @@ "format": "uuid", "title": "Assistant Id" }, - { "type": "string", "title": "Graph Id" } + { + "type": "string", + "title": "Graph Id" + } ], "description": "The assistant ID or graph name to run. If using graph name, will default to first assistant created from that graph." }, @@ -3048,20 +3705,36 @@ }, "input": { "anyOf": [ - { "type": "object" }, - { "type": "array" }, - { "type": "string" }, - { "type": "number" }, - { "type": "boolean" }, - { "type": "null" } + { + "type": "object" + }, + { + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } ], "title": "Input", "description": "The input to the graph." }, "command": { "anyOf": [ - { "$ref": "#/components/schemas/Command" }, - { "type": "null" } + { + "$ref": "#/components/schemas/Command" + }, + { + "type": "null" + } ], "title": "Input", "description": "The input to the graph." @@ -3074,7 +3747,9 @@ "config": { "properties": { "tags": { - "items": { "type": "string" }, + "items": { + "type": "string" + }, "type": "array", "title": "Tags" }, @@ -3082,7 +3757,10 @@ "type": "integer", "title": "Recursion Limit" }, - "configurable": { "type": "object", "title": "Configurable" } + "configurable": { + "type": "object", + "title": "Configurable" + } }, "type": "object", "title": "Config", @@ -3098,16 +3776,36 @@ }, "interrupt_before": { "anyOf": [ - { "type": "string", "enum": ["*"] }, - { "items": { "type": "string" }, "type": "array" } + { + "type": "string", + "enum": [ + "*" + ] + }, + { + "items": { + "type": "string" + }, + "type": "array" + } ], "title": "Interrupt Before", "description": "Nodes to interrupt immediately before they get executed." }, "interrupt_after": { "anyOf": [ - { "type": "string", "enum": ["*"] }, - { "items": { "type": "string" }, "type": "array" } + { + "type": "string", + "enum": [ + "*" + ] + }, + { + "items": { + "type": "string" + }, + "type": "array" + } ], "title": "Interrupt After", "description": "Nodes to interrupt immediately after they get executed." @@ -3144,7 +3842,9 @@ ], "title": "Stream Mode", "description": "The stream mode(s) to use.", - "default": ["values"] + "default": [ + "values" + ] }, "stream_subgraphs": { "type": "boolean", @@ -3152,35 +3852,54 @@ "description": "Whether to stream output from subgraphs.", "default": false }, + "stream_resumable": { + "type": "boolean", + "title": "Stream Resumable", + "description": "Whether to persist the stream chunks in order to resume the stream later.", + "default": false + }, "on_disconnect": { "type": "string", - "enum": ["cancel", "continue"], + "enum": [ + "cancel", + "continue" + ], "title": "On Disconnect", "description": "The disconnect mode to use. Must be one of 'cancel' or 'continue'.", "default": "cancel" }, "feedback_keys": { - "items": { "type": "string" }, + "items": { + "type": "string" + }, "type": "array", "title": "Feedback Keys", "description": "Feedback keys to assign to run." }, "multitask_strategy": { "type": "string", - "enum": ["reject", "rollback", "interrupt", "enqueue"], + "enum": [ + "reject", + "rollback", + "interrupt", + "enqueue" + ], "title": "Multitask Strategy", "description": "Multitask strategy to use. Must be one of 'reject', 'interrupt', 'rollback', or 'enqueue'.", "default": "reject" }, "if_not_exists": { "type": "string", - "enum": ["create", "reject"], + "enum": [ + "create", + "reject" + ], "title": "If Not Exists", "description": "How to handle missing thread. Must be either 'reject' (raise error if missing), or 'create' (create new thread).", "default": "reject" }, "after_seconds": { - "type": "integer", + "type": "number", "title": "After Seconds", "description": "The number of seconds to wait before starting the run. Use to schedule future runs." }, @@ -3192,13 +3911,17 @@ } }, "type": "object", - "required": ["assistant_id"], + "required": [ + "assistant_id" + ], "title": "RunCreateStateful", "description": "Payload for creating a run." }, "RunBatchCreate": { "type": "array", - "items": { "$ref": "#/components/schemas/RunCreateStateless" }, + "items": { + "$ref": "#/components/schemas/RunCreateStateless" + }, "minItems": 1, "title": "RunBatchCreate", "description": "Payload for creating a batch of runs." @@ -3212,26 +3935,45 @@ "format": "uuid", "title": "Assistant Id" }, - { "type": "string", "title": "Graph Id" } + { + "type": "string", + "title": "Graph Id" + } ], "description": "The assistant ID or graph name to run. If using graph name, will default to first assistant created from that graph." }, "input": { "anyOf": [ - { "type": "object" }, - { "type": "array" }, - { "type": "string" }, - { "type": "number" }, - { "type": "boolean" }, - { "type": "null" } + { + "type": "object" + }, + { + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + } ], "title": "Input", "description": "The input to the graph." }, "command": { "anyOf": [ - { "$ref": "#/components/schemas/Command" }, - { "type": "null" } + { + "$ref": "#/components/schemas/Command" + }, + { + "type": "null" + } ], "title": "Input", "description": "The input to the graph." @@ -3244,7 +3986,9 @@ "config": { "properties": { "tags": { - "items": { "type": "string" }, + "items": { + "type": "string" + }, "type": "array", "title": "Tags" }, @@ -3252,7 +3996,10 @@ "type": "integer", "title": "Recursion Limit" }, - "configurable": { "type": "object", "title": "Configurable" } + "configurable": { + "type": "object", + "title": "Configurable" + } }, "type": "object", "title": "Config", @@ -3268,16 +4015,36 @@ }, "interrupt_before": { "anyOf": [ - { "type": "string", "enum": ["*"] }, - { "items": { "type": "string" }, "type": "array" } + { + "type": "string", + "enum": [ + "*" + ] + }, + { + "items": { + "type": "string" + }, + "type": "array" + } ], "title": "Interrupt Before", "description": "Nodes to interrupt immediately before they get executed." }, "interrupt_after": { "anyOf": [ - { "type": "string", "enum": ["*"] }, - { "items": { "type": "string" }, "type": "array" } + { + "type": "string", + "enum": [ + "*" + ] + }, + { + "items": { + "type": "string" + }, + "type": "array" + } ], "title": "Interrupt After", "description": "Nodes to interrupt immediately after they get executed." @@ -3314,10 +4081,14 @@ ], "title": "Stream Mode", "description": "The stream mode(s) to use.", - "default": ["values"] + "default": [ + "values" + ] }, "feedback_keys": { - "items": { "type": "string" }, + "items": { + "type": "string" + }, "type": "array", "title": "Feedback Keys", "description": "Feedback keys to assign to run." @@ -3328,22 +4099,34 @@ "description": "Whether to stream output from subgraphs.", "default": false }, + "stream_resumable": { + "type": "boolean", + "title": "Stream Resumable", + "description": "Whether to persist the stream chunks in order to resume the stream later.", + "default": false + }, "on_completion": { "type": "string", - "enum": ["delete", "keep"], + "enum": [ + "delete", + "keep" + ], "title": "On Completion", "description": "Whether to delete or keep the thread created for a stateless run. Must be one of 'delete' or 'keep'.", "default": "delete" }, "on_disconnect": { "type": "string", - "enum": ["cancel", "continue"], + "enum": [ + "cancel", + "continue" + ], "title": "On Disconnect", "description": "The disconnect mode to use. Must be one of 'cancel' or 'continue'.", "default": "cancel" }, "after_seconds": { - "type": "integer", + "type": "number", "title": "After Seconds", "description": "The number of seconds to wait before starting the run. Use to schedule future runs." }, @@ -3355,7 +4138,9 @@ } }, "type": "object", - "required": ["assistant_id"], + "required": [ + "assistant_id" + ], "title": "RunCreateStateless", "description": "Payload for creating a run." }, @@ -3400,7 +4185,10 @@ }, "sort_order": { "type": "string", - "enum": ["asc", "desc"], + "enum": [ + "asc", + "desc" + ], "title": "Sort Order", "description": "The order to sort by." } @@ -3450,7 +4238,12 @@ }, "status": { "type": "string", - "enum": ["idle", "busy", "interrupted", "error"], + "enum": [ + "idle", + "busy", + "interrupted", + "error" + ], "title": "Status", "description": "Thread status to filter on." }, @@ -3471,13 +4264,21 @@ }, "sort_by": { "type": "string", - "enum": ["thread_id", "status", "created_at", "updated_at"], + "enum": [ + "thread_id", + "status", + "created_at", + "updated_at" + ], "title": "Sort By", "description": "Sort by field." }, "sort_order": { "type": "string", - "enum": ["asc", "desc"], + "enum": [ + "asc", + "desc" + ], "title": "Sort Order", "description": "Sort order." } @@ -3513,7 +4314,12 @@ }, "status": { "type": "string", - "enum": ["idle", "busy", "interrupted", "error"], + "enum": [ + "idle", + "busy", + "interrupted", + "error" + ], "title": "Status", "description": "The status of the thread." }, @@ -3548,7 +4354,10 @@ }, "if_exists": { "type": "string", - "enum": ["raise", "do_nothing"], + "enum": [ + "raise", + "do_nothing" + ], "title": "If Exists", "description": "How to handle duplicate creation. Must be either 'raise' (raise error if duplicate), or 'do_nothing' (return existing thread).", "default": "raise" @@ -3560,7 +4369,9 @@ "properties": { "strategy": { "type": "string", - "enum": ["delete"], + "enum": [ + "delete" + ], "description": "The TTL strategy. 'delete' removes the entire thread.", "default": "delete" }, @@ -3582,7 +4393,9 @@ } } }, - "required": ["updates"] + "required": [ + "updates" + ] } } }, @@ -3615,7 +4428,9 @@ "description": "Include subgraph states." } }, - "required": ["checkpoint"], + "required": [ + "checkpoint" + ], "type": "object", "title": "ThreadStateCheckpointRequest", "description": "Payload for getting the state of a thread at a checkpoint." @@ -3624,13 +4439,22 @@ "properties": { "values": { "anyOf": [ - { "items": { "type": "object" }, "type": "array" }, - { "type": "object" } + { + "items": { + "type": "object" + }, + "type": "array" + }, + { + "type": "object" + } ], "title": "Values" }, "next": { - "items": { "type": "string" }, + "items": { + "type": "string" + }, "type": "array", "title": "Next" }, @@ -3638,17 +4462,34 @@ "items": { "type": "object", "properties": { - "id": { "type": "string", "title": "Task Id" }, - "name": { "type": "string", "title": "Node Name" }, - "error": { "type": "string", "title": "Error" }, - "interrupts": { "type": "array", "items": {} }, + "id": { + "type": "string", + "title": "Task Id" + }, + "name": { + "type": "string", + "title": "Node Name" + }, + "error": { + "type": "string", + "title": "Error" + }, + "interrupts": { + "type": "array", + "items": {} + }, "checkpoint": { "$ref": "#/components/schemas/CheckpointConfig", "title": "Checkpoint" }, - "state": { "$ref": "#/components/schemas/ThreadState" } + "state": { + "$ref": "#/components/schemas/ThreadState" + } }, - "required": ["id", "name"] + "required": [ + "id", + "name" + ] }, "type": "array", "title": "Tasks" @@ -3657,15 +4498,27 @@ "$ref": "#/components/schemas/CheckpointConfig", "title": "Checkpoint" }, - "metadata": { "type": "object", "title": "Metadata" }, - "created_at": { "type": "string", "title": "Created At" }, + "metadata": { + "type": "object", + "title": "Metadata" + }, + "created_at": { + "type": "string", + "title": "Created At" + }, "parent_checkpoint": { "type": "object", "title": "Parent Checkpoint" } }, "type": "object", - "required": ["values", "next", "checkpoint", "metadata", "created_at"], + "required": [ + "values", + "next", + "checkpoint", + "metadata", + "created_at" + ], "title": "ThreadState" }, "ThreadStateSearch": { @@ -3701,9 +4554,16 @@ "properties": { "values": { "anyOf": [ - { "items": { "type": "object" }, "type": "array" }, - { "type": "object" }, - { "type": "null" } + { + "items": {}, + "type": "array" + }, + { + "type": "object" + }, + { + "type": "null" + } ], "title": "Values", "description": "The values to update the state with." @@ -3727,15 +4587,28 @@ "properties": { "values": { "anyOf": [ - { "type": "array", "items": { "type": "object" } }, - { "type": "object" }, - { "type": "null" } + { + "type": "array", + "items": { + "type": "object" + } + }, + { + "type": "object" + }, + { + "type": "null" + } ] }, "command": { "anyOf": [ - { "$ref": "#/components/schemas/Command" }, - { "type": "null" } + { + "$ref": "#/components/schemas/Command" + }, + { + "type": "null" + } ], "description": "The command associated with the update." }, @@ -3744,12 +4617,17 @@ "description": "Update the state as if this node had just executed." } }, - "required": ["as_node"], + "required": [ + "as_node" + ], "type": "object" }, "ThreadStateUpdateResponse": { "properties": { - "checkpoint": { "type": "object", "title": "Checkpoint" } + "checkpoint": { + "type": "object", + "title": "Checkpoint" + } }, "type": "object", "title": "ThreadStateUpdateResponse", @@ -3780,11 +4658,17 @@ }, "StorePutRequest": { "type": "object", - "required": ["namespace", "key", "value"], + "required": [ + "namespace", + "key", + "value" + ], "properties": { "namespace": { "type": "array", - "items": { "type": "string" }, + "items": { + "type": "string" + }, "title": "Namespace", "description": "A list of strings representing the namespace path." }, @@ -3804,11 +4688,15 @@ }, "StoreDeleteRequest": { "type": "object", - "required": ["key"], + "required": [ + "key" + ], "properties": { "namespace": { "type": "array", - "items": { "type": "string" }, + "items": { + "type": "string" + }, "title": "Namespace", "description": "A list of strings representing the namespace path." }, @@ -3825,25 +4713,25 @@ "type": "object", "properties": { "namespace_prefix": { - "type": ["array", "null"], - "items": { "type": "string" }, + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, "title": "Namespace Prefix", "description": "List of strings representing the namespace prefix." }, "filter": { - "type": ["object", "null"], + "type": [ + "object", + "null" + ], "additionalProperties": true, "title": "Filter", "description": "Optional dictionary of key-value pairs to filter results." }, - "query": { - "type": [ - "string", - "null" - ], - "title": "Query", - "description": "Query string for semantic/vector search." - }, "limit": { "type": "integer", "default": 10, @@ -3855,6 +4743,14 @@ "default": 0, "title": "Offset", "description": "Number of items to skip before returning results (default is 0)." + }, + "query": { + "type": [ + "string", + "null" + ], + "title": "Query", + "description": "Query string for semantic/vector search." } }, "title": "StoreSearchRequest", @@ -3865,13 +4761,17 @@ "properties": { "prefix": { "type": "array", - "items": { "type": "string" }, + "items": { + "type": "string" + }, "title": "Prefix", "description": "Optional list of strings representing the prefix to filter namespaces." }, "suffix": { "type": "array", - "items": { "type": "string" }, + "items": { + "type": "string" + }, "title": "Suffix", "description": "Optional list of strings representing the suffix to filter namespaces." }, @@ -3896,11 +4796,19 @@ }, "Item": { "type": "object", - "required": ["namespace", "key", "value", "created_at", "updated_at"], + "required": [ + "namespace", + "key", + "value", + "created_at", + "updated_at" + ], "properties": { "namespace": { "type": "array", - "items": { "type": "string" }, + "items": { + "type": "string" + }, "description": "The namespace of the item. A namespace is analogous to a document's directory." }, "key": { @@ -3931,7 +4839,11 @@ "properties": { "status": { "type": "string", - "enum": ["pending", "running", "all"], + "enum": [ + "pending", + "running", + "all" + ], "title": "Status", "description": "Filter runs by status to cancel. Must be one of 'pending', 'running', or 'all'." }, @@ -3943,29 +4855,50 @@ }, "run_ids": { "type": "array", - "items": { "type": "string", "format": "uuid" }, + "items": { + "type": "string", + "format": "uuid" + }, "title": "Run Ids", "description": "List of run IDs to cancel." } }, "oneOf": [ - { "required": ["status"] }, - { "required": ["thread_id", "run_ids"] } + { + "required": [ + "status" + ] + }, + { + "required": [ + "thread_id", + "run_ids" + ] + } ] }, "SearchItemsResponse": { "type": "object", - "required": ["items"], + "required": [ + "items" + ], "properties": { "items": { "type": "array", - "items": { "$ref": "#/components/schemas/Item" } + "items": { + "$ref": "#/components/schemas/Item" + } } } }, "ListNamespaceResponse": { "type": "array", - "items": { "type": "array", "items": { "type": "string" } } + "items": { + "type": "array", + "items": { + "type": "string" + } + } }, "ErrorResponse": { "type": "string", @@ -3978,7 +4911,9 @@ "description": "Successful retrieval of an item.", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/Item" } + "schema": { + "$ref": "#/components/schemas/Item" + } } } }, @@ -3994,7 +4929,9 @@ "description": "Successful search operation.", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/SearchItemsResponse" } + "schema": { + "$ref": "#/components/schemas/SearchItemsResponse" + } } } }, @@ -4002,7 +4939,9 @@ "description": "Successful retrieval of namespaces.", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ListNamespaceResponse" } + "schema": { + "$ref": "#/components/schemas/ListNamespaceResponse" + } } } }, @@ -4010,7 +4949,9 @@ "description": "An error occurred.", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } } } } From df368bdd3046f00d96ce8f7dabf3e7f9aee51ede Mon Sep 17 00:00:00 2001 From: Josh Rogers Date: Tue, 1 Jul 2025 18:40:13 -0400 Subject: [PATCH 002/129] Updating message types to include all base message fields (#5298) --- libs/sdk-js/src/types.messages.ts | 39 +++++++++++++------------------ 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/libs/sdk-js/src/types.messages.ts b/libs/sdk-js/src/types.messages.ts index 49123cf1a..26b929535 100644 --- a/libs/sdk-js/src/types.messages.ts +++ b/libs/sdk-js/src/types.messages.ts @@ -13,16 +13,22 @@ type MessageContent = string | MessageContentComplex[]; */ type MessageAdditionalKwargs = Record; -export type HumanMessage = { - type: "human"; - id?: string | undefined; +type BaseMessage = { + additional_kwargs?: MessageAdditionalKwargs | undefined; content: MessageContent; + id?: string | undefined; + name?: string | undefined; + response_metadata?: Record | undefined; }; -export type AIMessage = { +export type HumanMessage = BaseMessage & { + type: "human"; + example?: boolean | undefined; +}; + +export type AIMessage = BaseMessage & { type: "ai"; - id?: string | undefined; - content: MessageContent; + example?: boolean | undefined; tool_calls?: | { name: string; @@ -57,19 +63,12 @@ export type AIMessage = { | undefined; } | undefined; - additional_kwargs?: MessageAdditionalKwargs | undefined; - response_metadata?: Record | undefined; }; -export type ToolMessage = { +export type ToolMessage = BaseMessage & { type: "tool"; - name?: string | undefined; - id?: string | undefined; - content: MessageContent; status?: "error" | "success" | undefined; tool_call_id: string; - additional_kwargs?: MessageAdditionalKwargs | undefined; - response_metadata?: Record | undefined; /** * Artifact of the Tool execution which is not meant to be sent to the model. * @@ -81,22 +80,16 @@ export type ToolMessage = { artifact?: any; }; -export type SystemMessage = { +export type SystemMessage = BaseMessage & { type: "system"; - id?: string | undefined; - content: MessageContent; }; -export type FunctionMessage = { +export type FunctionMessage = BaseMessage & { type: "function"; - id?: string | undefined; - content: MessageContent; }; -export type RemoveMessage = { +export type RemoveMessage = BaseMessage & { type: "remove"; - id: string; - content: MessageContent; }; export type Message = From 191192b1426364d37f010ef2d4582e674895518c Mon Sep 17 00:00:00 2001 From: Sydney Runkle <54324534+sydney-runkle@users.noreply.github.com> Date: Wed, 2 Jul 2025 09:09:11 -0400 Subject: [PATCH 003/129] upgrade dependabot scope (#5303) --- .github/dependabot.yml | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index fcf1bd801..24b12451c 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,11 +1,18 @@ -# Please see the documentation for all configuration options: -# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates -# and -# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file - version: 2 updates: - package-ecosystem: "github-actions" directory: "/" schedule: interval: "weekly" + + - package-ecosystem: "pip" + directories: + - "libs/checkpoint-postgres" + - "libs/checkpoint-sqlite" + - "libs/cli" + - "libs/langgraph" + - "libs/prebuilt" + - "libs/runtime-inmem" + - "libs/sdk" + schedule: + interval: "weekly" From e2acfb24cc3ead7bece409ee3888f9bd8c0860ea Mon Sep 17 00:00:00 2001 From: waqarahmed6095 <54316628+waqarahmed6095@users.noreply.github.com> Date: Wed, 2 Jul 2025 16:10:57 +0300 Subject: [PATCH 004/129] Update use_stream_react.md (#5304) Problem of two times heading "How to integrate LangGraph into your React application" --- docs/docs/cloud/how-tos/use_stream_react.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/cloud/how-tos/use_stream_react.md b/docs/docs/cloud/how-tos/use_stream_react.md index 29703761e..3ddcbe5b4 100644 --- a/docs/docs/cloud/how-tos/use_stream_react.md +++ b/docs/docs/cloud/how-tos/use_stream_react.md @@ -1,4 +1,4 @@ -How to integrate LangGraph into your React application# How to integrate LangGraph into your React application +# How to integrate LangGraph into your React application !!! info "Prerequisites" From 60560ea755664c0cb228d9f3243a1d4e64f433e0 Mon Sep 17 00:00:00 2001 From: Sydney Runkle <54324534+sydney-runkle@users.noreply.github.com> Date: Wed, 2 Jul 2025 09:12:22 -0400 Subject: [PATCH 005/129] dependabot: fix list of dirs for `pip` updates (#5305) fix list of dirs --- .github/dependabot.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 24b12451c..bbb262889 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -7,12 +7,13 @@ updates: - package-ecosystem: "pip" directories: + - "libs/checkpoint" - "libs/checkpoint-postgres" - "libs/checkpoint-sqlite" - "libs/cli" - "libs/langgraph" - "libs/prebuilt" - - "libs/runtime-inmem" - - "libs/sdk" + - "libs/scheduler-kafka" + - "libs/sdk-py" schedule: interval: "weekly" From 8271e39e00e409c2904d243161bc2630ba912361 Mon Sep 17 00:00:00 2001 From: Sydney Runkle <54324534+sydney-runkle@users.noreply.github.com> Date: Wed, 2 Jul 2025 09:15:00 -0400 Subject: [PATCH 006/129] dependabot: no kafka (#5306) * fix list of dirs * another patch --- .github/dependabot.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index bbb262889..84770db13 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -13,7 +13,6 @@ updates: - "libs/cli" - "libs/langgraph" - "libs/prebuilt" - - "libs/scheduler-kafka" - "libs/sdk-py" schedule: interval: "weekly" From b3708bd7f66675f7a04bf9950c33d495c49cd843 Mon Sep 17 00:00:00 2001 From: Sydney Runkle <54324534+sydney-runkle@users.noreply.github.com> Date: Wed, 2 Jul 2025 10:10:01 -0400 Subject: [PATCH 007/129] ci: add automated `uv lock --upgrade` workflow (#5307) --- .github/workflows/ci.yml | 12 ++++--- .github/workflows/uv_lock_ugprade.yml | 45 +++++++++++++++++++++++++++ Makefile | 10 ++++++ 3 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/uv_lock_ugprade.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ece56b460..43752eddf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,6 +22,7 @@ jobs: outputs: python: ${{ steps.filter.outputs.python }} sdk-js: ${{ steps.filter.outputs.sdk-js }} + deps: ${{ steps.filter.outputs.deps }} steps: - uses: actions/checkout@v4 - uses: dorny/paths-filter@v3 @@ -38,6 +39,9 @@ jobs: - 'libs/prebuilt/**' sdk-js: - 'libs/sdk-js/**' + deps: + - '**/pyproject.toml' + - '**/uv.lock' lint: needs: changes @@ -55,7 +59,7 @@ jobs: "libs/prebuilt", ] - if: needs.changes.outputs.python == 'true' + if: needs.changes.outputs.python == 'true' || needs.changes.outputs.deps == 'true' uses: ./.github/workflows/_lint.yml with: working-directory: ${{ matrix.working-directory }} @@ -74,7 +78,7 @@ jobs: "libs/checkpoint-postgres", "libs/prebuilt", ] - if: needs.changes.outputs.python == 'true' + if: needs.changes.outputs.python == 'true' || needs.changes.outputs.deps == 'true' uses: ./.github/workflows/_test.yml with: working-directory: ${{ matrix.working-directory }} @@ -83,7 +87,7 @@ jobs: # NOTE: we're testing langgraph separately because it requires a different matrix test-langgraph: needs: changes - if: needs.changes.outputs.python == 'true' + if: needs.changes.outputs.python == 'true' || needs.changes.outputs.deps == 'true' name: "cd libs/langgraph" uses: ./.github/workflows/_test_langgraph.yml secrets: inherit @@ -140,7 +144,7 @@ jobs: integration-test: needs: changes - if: needs.changes.outputs.python == 'true' + if: needs.changes.outputs.python == 'true' || needs.changes.outputs.deps == 'true' name: CLI integration test uses: ./.github/workflows/_integration_test.yml secrets: inherit diff --git a/.github/workflows/uv_lock_ugprade.yml b/.github/workflows/uv_lock_ugprade.yml new file mode 100644 index 000000000..8acd39393 --- /dev/null +++ b/.github/workflows/uv_lock_ugprade.yml @@ -0,0 +1,45 @@ +name: UV Lock Upgrade + +on: + schedule: + # run at midnight every Sunday + - cron: '0 0 * * 0' + # allow manual triggering + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + +jobs: + upgrade-dependencies: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Set up uv + uses: astral-sh/setup-uv@v6 + with: + # use minimum supported Python version + python-version: "3.9" + enable-cache: true + cache-suffix: "uv-lock-upgrade" + + - name: Run uv lock --upgrade in all Python packages + run: make lock-upgrade + + - name: Create Pull Request + uses: peter-evans/create-pull-request@v6 + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: "chore: upgrade dependencies with `uv lock --upgrade`" + title: "chore: upgrade dependencies with `uv lock --upgrade`" + body: | + This PR updates the dependencies in all Python packages using `uv lock --upgrade`. + + This is an automated PR created by the UV Lock Upgrade workflow. + branch: deps/uv-lock-upgrade + delete-branch: true + labels: | + dependencies diff --git a/Makefile b/Makefile index aa4eb9945..477e03123 100644 --- a/Makefile +++ b/Makefile @@ -47,6 +47,16 @@ lock: fi; \ done +# Lock all projects and upgrade dependencies +.PHONY: lock-upgrade +lock-upgrade: + @for dir in $(LIBS_DIRS); do \ + if [ -f $$dir/Makefile ]; then \ + echo "Running lock-upgrade in $$dir"; \ + (cd $$dir && uv lock --upgrade); \ + fi; \ + done + # Test all projects .PHONY: test test: From 000f5c3043ee73ab71565951bfee29bdd3e18c25 Mon Sep 17 00:00:00 2001 From: Sydney Runkle <54324534+sydney-runkle@users.noreply.github.com> Date: Wed, 2 Jul 2025 10:30:55 -0400 Subject: [PATCH 008/129] fix[deps]: update lockfiles / deps bounds for internal tools (#5301) update lockfiles / deps bounds --- libs/checkpoint-postgres/pyproject.toml | 2 +- libs/checkpoint-sqlite/pyproject.toml | 2 +- libs/cli/pyproject.toml | 4 ++-- libs/cli/uv.lock | 4 ++-- libs/langgraph/pyproject.toml | 6 +++--- libs/prebuilt/pyproject.toml | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libs/checkpoint-postgres/pyproject.toml b/libs/checkpoint-postgres/pyproject.toml index 0442cfcd5..15e7b9aed 100644 --- a/libs/checkpoint-postgres/pyproject.toml +++ b/libs/checkpoint-postgres/pyproject.toml @@ -12,7 +12,7 @@ readme = "README.md" license = "MIT" license-files = ['LICENSE'] dependencies = [ - "langgraph-checkpoint>=2.0.21", + "langgraph-checkpoint>=2.0.21,<3.0.0", "orjson>=3.10.1", "psycopg>=3.2.0", "psycopg-pool>=3.2.0", diff --git a/libs/checkpoint-sqlite/pyproject.toml b/libs/checkpoint-sqlite/pyproject.toml index 7f378d892..d9907153a 100644 --- a/libs/checkpoint-sqlite/pyproject.toml +++ b/libs/checkpoint-sqlite/pyproject.toml @@ -12,7 +12,7 @@ readme = "README.md" license = "MIT" license-files = ['LICENSE'] dependencies = [ - "langgraph-checkpoint>=2.0.21", + "langgraph-checkpoint>=2.0.21,<3.0.0", "aiosqlite>=0.20", "sqlite-vec>=0.1.6", ] diff --git a/libs/cli/pyproject.toml b/libs/cli/pyproject.toml index 4cb4a561a..1a781e6f2 100644 --- a/libs/cli/pyproject.toml +++ b/libs/cli/pyproject.toml @@ -18,8 +18,8 @@ dependencies = [ [project.optional-dependencies] inmem = [ - "langgraph-api>=0.2.67 ; python_version >= '3.11'", - "langgraph-runtime-inmem>=0.3.0 ; python_version >= '3.11'", + "langgraph-api>=0.2.67,<0.3.0 ; python_version >= '3.11'", + "langgraph-runtime-inmem>=0.3.0,<0.4.0 ; python_version >= '3.11'", "python-dotenv>=0.8.0", ] diff --git a/libs/cli/uv.lock b/libs/cli/uv.lock index b256a721c..839e68015 100644 --- a/libs/cli/uv.lock +++ b/libs/cli/uv.lock @@ -530,8 +530,8 @@ dev = [ [package.metadata] requires-dist = [ { name = "click", specifier = ">=8.1.7" }, - { name = "langgraph-api", marker = "python_full_version >= '3.11' and extra == 'inmem'", specifier = ">=0.2.67" }, - { name = "langgraph-runtime-inmem", marker = "python_full_version >= '3.11' and extra == 'inmem'", specifier = ">=0.3.0" }, + { name = "langgraph-api", marker = "python_full_version >= '3.11' and extra == 'inmem'", specifier = ">=0.2.67,<0.3.0" }, + { name = "langgraph-runtime-inmem", marker = "python_full_version >= '3.11' and extra == 'inmem'", specifier = ">=0.3.0,<0.4.0" }, { name = "langgraph-sdk", marker = "python_full_version >= '3.11'", specifier = ">=0.1.0" }, { name = "python-dotenv", marker = "extra == 'inmem'", specifier = ">=0.8.0" }, ] diff --git a/libs/langgraph/pyproject.toml b/libs/langgraph/pyproject.toml index b04d64a36..1d5518052 100644 --- a/libs/langgraph/pyproject.toml +++ b/libs/langgraph/pyproject.toml @@ -13,9 +13,9 @@ license = "MIT" license-files = ['LICENSE'] dependencies = [ "langchain-core>=0.1", - "langgraph-checkpoint>=2.1.0", - "langgraph-sdk>=0.1.42", - "langgraph-prebuilt>=0.5.0", + "langgraph-checkpoint>=2.1.0,<3.0.0", + "langgraph-sdk>=0.1.42,<0.2.0", + "langgraph-prebuilt>=0.5.0,<0.6.0", "xxhash>=3.5.0", "pydantic>=2.7.4", ] diff --git a/libs/prebuilt/pyproject.toml b/libs/prebuilt/pyproject.toml index c294cd7fa..a4d389343 100644 --- a/libs/prebuilt/pyproject.toml +++ b/libs/prebuilt/pyproject.toml @@ -12,7 +12,7 @@ readme = "README.md" license = "MIT" license-files = ['LICENSE'] dependencies = [ - "langgraph-checkpoint>=2.1.0", + "langgraph-checkpoint>=2.1.0,<3.0.0", "langchain-core>=0.3.67", ] From 669cf817e89898465b1d12d3175cb2ffed5b56c4 Mon Sep 17 00:00:00 2001 From: Josh Rogers Date: Wed, 2 Jul 2025 12:56:04 -0400 Subject: [PATCH 009/129] Bump js sdk to 0.0.89 (#5313) --- libs/sdk-js/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/sdk-js/package.json b/libs/sdk-js/package.json index 24862107e..bc2b2fa5d 100644 --- a/libs/sdk-js/package.json +++ b/libs/sdk-js/package.json @@ -1,6 +1,6 @@ { "name": "@langchain/langgraph-sdk", - "version": "0.0.88", + "version": "0.0.89", "description": "Client library for interacting with the LangGraph API", "type": "module", "packageManager": "yarn@1.22.19", From 0885e7833b5d3a0b76fb89a1babafdd1d6f8f6b1 Mon Sep 17 00:00:00 2001 From: lc-arjun Date: Wed, 2 Jul 2025 12:19:46 -0700 Subject: [PATCH 010/129] docs: cli data storage handling (#5188) Write up initial docs on how data is managed in the langgraph server, what telemetry is collected (and why), and how to opt-out. --- .../concepts/data_storage_and_privacy.md | 54 +++++++++++++++++++ docs/mkdocs.yml | 1 + 2 files changed, 55 insertions(+) create mode 100644 docs/docs/cloud/concepts/data_storage_and_privacy.md diff --git a/docs/docs/cloud/concepts/data_storage_and_privacy.md b/docs/docs/cloud/concepts/data_storage_and_privacy.md new file mode 100644 index 000000000..c9ca1f59d --- /dev/null +++ b/docs/docs/cloud/concepts/data_storage_and_privacy.md @@ -0,0 +1,54 @@ +# Data Storage and Privacy + +This document describes how data is processed in the LangGraph CLI and the LangGraph Server for both the in-memory server (`langgraph dev`) and the local Docker server (`langgraph up`). It also describes what data is tracked when interacting with the hosted LangGraph Studio frontend. + +## CLI + +LangGraph **CLI** is the command-line interface for building and running LangGraph applications; see the [CLI guide](../../concepts/langgraph_cli.md) to learn more. + +By default, calls to most CLI commands log a single analytics event upon invocation. This helps us better prioritize improvements to the CLI experience. Each telemetry event contains the calling process's OS, OS version, Python version, the CLI version, the command name (`dev`, `up`, `run`, etc.), and booleans representing whether a flag was passed to the command. You can see the full analytics logic [here](https://github.com/langchain-ai/langgraph/blob/main/libs/cli/langgraph_cli/analytics.py). + +You can disable all CLI telemetry by setting `LANGGRAPH_CLI_NO_ANALYTICS=1`. + +## LangGraph Server (in-memory & docker) + +The [LangGraph Server](../../concepts/langgraph_server.md) provides a durable execution runtime that relies on persisting checkpoints of your application state, long-term memories, thread metadata, assistants, and similar resources to the local file system or a database. Unless you have deliberately customized the storage location, this information is either written to local disk (for `langgraph dev`) or a PostgreSQL database (for `langgraph up` and in all deployments). + +### LangSmith Tracing + +When running the LangGraph server (either in-memory or in Docker), LangSmith tracing may be enabled to facilitate faster debugging and offer observability of graph state and LLM prompts in production. You can always disable tracing by setting `LANGSMITH_TRACING=false` in your server's runtime environment. + +### In-memory development server (`langgraph dev`) + +`langgraph dev` runs an [in-memory development server](../../tutorials/langgraph-platform/local-server.md) as a single Python process, designed for quick development and testing. It saves all checkpointing and memory data to disk within a `.langgraph_api` directory in the current working directory. Apart from the telemetry data described in the [CLI](#cli) section, no data leaves the machine unless you have enabled tracing or your graph code explicitly contacts an external service. + +### Standalone Container (`langgraph up`) + +`langgraph up` builds your local package into a Docker image and runs the server as a [standalone container](../../concepts/deployment_options.md#standalone-container) consisting of three containers: the API server, a PostgreSQL container, and a Redis container. All persistent data (checkpoints, assistants, etc.) are stored in the PostgreSQL database. Redis is used as a pubsub connection for real-time streaming of events. You can encrypt all checkpoints before saving to the database by setting a valid `LANGGRAPH_AES_KEY` environment variable. You can also specify [TTLs](../../how-tos/ttl/configure_ttl.md) for checkpoints and cross-thread memories in `langgraph.json` to control how long data is stored. All persisted threads, memories, and other data can be deleted via the relevant API endpoints. + +Additional API calls are made to confirm that the server has a valid license and to track the number of executed runs and tasks. Periodically, the API server validates the provided license key (or API key). + +If you've disabled [tracing](#langsmith-tracing), no user data is persisted externally unless your graph code explicitly contacts an external service. + +## Studio + +[LangGraph Studio](../../concepts/langgraph_studio.md) is a graphical interface for interacting with your LangGraph server. It does not persist any private data (the data you send to your server is not sent to LangSmith). Though the studio interface is served at [smith.langchain.com](https://smith.langchain.com), it is run in your browser and connects directly to your local LangGraph server so that no data needs to be sent to LangSmith. + +If you are logged in, LangSmith does collect some usage analytics to help improve studio's user experience. This includes: + +- Page visits and navigation patterns +- User actions (button clicks) +- Browser type and version +- Screen resolution and viewport size + +Importantly, no application data or code (or other sensitive configuration details) are collected. All of that is stored in the persistence layer of your LangGraph server. When using Studio anonymously, no account creation is required and usage analytics are not collected. + +## Quick reference + +In summary, you can opt-out of server-side telemetry by turning off CLI analytics and disabling tracing. + +| Variable | Purpose | Default | +| ------------------------------ | ------------------------- | -------------------------------- | +| `LANGGRAPH_CLI_NO_ANALYTICS=1` | Disable CLI analytics | Analytics enabled | +| `LANGSMITH_API_KEY` | Enable LangSmith tracing | Tracing disabled | +| `LANGSMITH_TRACING=false` | Disable LangSmith tracing | Depends on environment | diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 487662a16..34a352fb0 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -215,6 +215,7 @@ nav: - how-tos/http/custom_middleware.md - how-tos/http/custom_routes.md - Data management: + - cloud/concepts/data_storage_and_privacy.md - Add semantic search: cloud/deployment/semantic_search.md - Add TTLs: how-tos/ttl/configure_ttl.md - Deployment: From 339de4c2049972aabd9030749074c10bd80f86ce Mon Sep 17 00:00:00 2001 From: Sydney Runkle <54324534+sydney-runkle@users.noreply.github.com> Date: Wed, 2 Jul 2025 16:08:48 -0400 Subject: [PATCH 011/129] langgraph[fix]: remove deprecated pydantic logic + fix schema gen behavior for typed dicts (#5296) --- libs/langgraph/langgraph/graph/state.py | 28 +-- libs/langgraph/langgraph/pregel/__init__.py | 15 +- libs/langgraph/langgraph/utils/fields.py | 6 +- .../tests/__snapshots__/test_large_cases.ambr | 12 +- .../tests/__snapshots__/test_pregel.ambr | 12 +- libs/langgraph/tests/test_large_cases.py | 12 +- libs/langgraph/tests/test_pregel.py | 22 +- libs/langgraph/tests/test_pregel_async.py | 4 +- libs/langgraph/tests/test_state.py | 17 +- libs/langgraph/uv.lock | 197 +++++++++++------- 10 files changed, 177 insertions(+), 148 deletions(-) diff --git a/libs/langgraph/langgraph/graph/state.py b/libs/langgraph/langgraph/graph/state.py index 151b1b278..ac0a11e7d 100644 --- a/libs/langgraph/langgraph/graph/state.py +++ b/libs/langgraph/langgraph/graph/state.py @@ -25,8 +25,8 @@ from typing import ( ) from langchain_core.runnables import Runnable, RunnableConfig -from pydantic import BaseModel -from typing_extensions import Self, TypeAlias, Unpack +from pydantic import BaseModel, TypeAdapter +from typing_extensions import Self, TypeAlias, Unpack, is_typeddict from langgraph._typing import UNSET, DeprecatedKwargs from langgraph.cache.base import BaseCache @@ -904,18 +904,20 @@ class CompiledStateGraph( self.builder = builder self.schema_to_mapper = schema_to_mapper - def get_input_schema(self, config: RunnableConfig | None = None) -> type[BaseModel]: - return _get_schema( + def get_input_jsonschema( + self, config: RunnableConfig | None = None + ) -> dict[str, Any]: + return _get_json_schema( typ=self.builder.input_schema, schemas=self.builder.schemas, channels=self.builder.channels, name=self.get_name("Input"), ) - def get_output_schema( + def get_output_jsonschema( self, config: RunnableConfig | None = None - ) -> type[BaseModel]: - return _get_schema( + ) -> dict[str, Any]: + return _get_json_schema( typ=self.builder.output_schema, schemas=self.builder.schemas, channels=self.builder.channels, @@ -1382,21 +1384,23 @@ def _is_field_managed_value(name: str, typ: type[Any]) -> ManagedValueSpec | Non return None -def _get_schema( +def _get_json_schema( typ: type, schemas: dict, channels: dict, name: str, -) -> type[BaseModel]: +) -> dict[str, Any]: if isclass(typ) and issubclass(typ, BaseModel): - return typ + return typ.model_json_schema() + elif is_typeddict(typ): + return TypeAdapter(typ).json_schema() else: keys = list(schemas[typ].keys()) if len(keys) == 1 and keys[0] == "__root__": return create_model( name, root=(channels[keys[0]].UpdateType, None), - ) + ).model_json_schema() else: return create_model( name, @@ -1414,7 +1418,7 @@ def _get_schema( for k in schemas[typ] if k in channels and isinstance(channels[k], BaseChannel) }, - ) + ).model_json_schema() CHANNEL_BRANCH_TO = "branch:to:{}" diff --git a/libs/langgraph/langgraph/pregel/__init__.py b/libs/langgraph/langgraph/pregel/__init__.py index 67c938611..2397c1978 100644 --- a/libs/langgraph/langgraph/pregel/__init__.py +++ b/libs/langgraph/langgraph/pregel/__init__.py @@ -771,10 +771,7 @@ class Pregel(PregelProtocol[StateT, InputT, OutputT], Generic[StateT, InputT, Ou self, *, include: Sequence[str] | None = None ) -> dict[str, Any]: schema = self.config_schema(include=include) - if hasattr(schema, "model_json_schema"): - return schema.model_json_schema() - else: - return schema.schema() + return schema.model_json_schema() @property def InputType(self) -> Any: @@ -801,10 +798,7 @@ class Pregel(PregelProtocol[StateT, InputT, OutputT], Generic[StateT, InputT, Ou self, config: RunnableConfig | None = None ) -> dict[str, Any]: schema = self.get_input_schema(config) - if hasattr(schema, "model_json_schema"): - return schema.model_json_schema() - else: - return schema.schema() + return schema.model_json_schema() @property def OutputType(self) -> Any: @@ -833,10 +827,7 @@ class Pregel(PregelProtocol[StateT, InputT, OutputT], Generic[StateT, InputT, Ou self, config: RunnableConfig | None = None ) -> dict[str, Any]: schema = self.get_output_schema(config) - if hasattr(schema, "model_json_schema"): - return schema.model_json_schema() - else: - return schema.schema() + return schema.model_json_schema() @property def stream_channels_list(self) -> Sequence[str]: diff --git a/libs/langgraph/langgraph/utils/fields.py b/libs/langgraph/langgraph/utils/fields.py index 33a8f2951..5b9c8dca6 100644 --- a/libs/langgraph/langgraph/utils/fields.py +++ b/libs/langgraph/langgraph/utils/fields.py @@ -128,8 +128,8 @@ def get_enhanced_type_hints( # Pydantic models try: - if hasattr(type, "__fields__") and name in type.__fields__: - field = type.__fields__[name] + if hasattr(type, "model_fields") and name in type.model_fields: + field = type.model_fields[name] if hasattr(field, "description") and field.description is not None: description = field.description @@ -163,7 +163,7 @@ def get_update_as_tuples(input: Any, keys: Sequence[str]) -> list[tuple[str, Any """Get Pydantic state update as a list of (key, value) tuples.""" if isinstance(input, BaseModel): keep = input.model_fields_set - defaults = {k: v.default for k, v in input.model_fields.items()} + defaults = {k: v.default for k, v in type(input).model_fields.items()} else: keep = None defaults = {} diff --git a/libs/langgraph/tests/__snapshots__/test_large_cases.ambr b/libs/langgraph/tests/__snapshots__/test_large_cases.ambr index 9f4d08cf9..56b3fb6aa 100644 --- a/libs/langgraph/tests/__snapshots__/test_large_cases.ambr +++ b/libs/langgraph/tests/__snapshots__/test_large_cases.ambr @@ -101,10 +101,10 @@ ''' # --- # name: test_conditional_state_graph[memory] - '{"$defs": {"AgentAction": {"description": "Represents a request to execute an action by an agent.\\n\\nThe action consists of the name of the tool to execute and the input to pass\\nto the tool. The log is used to pass along extra information about the action.", "properties": {"tool": {"title": "Tool", "type": "string"}, "tool_input": {"anyOf": [{"type": "string"}, {"type": "object"}], "title": "Tool Input"}, "log": {"title": "Log", "type": "string"}, "type": {"const": "AgentAction", "default": "AgentAction", "enum": ["AgentAction"], "title": "Type", "type": "string"}}, "required": ["tool", "tool_input", "log"], "title": "AgentAction", "type": "object"}, "AgentFinish": {"description": "Final return value of an ActionAgent.\\n\\nAgents return an AgentFinish when they have reached a stopping condition.", "properties": {"return_values": {"title": "Return Values", "type": "object"}, "log": {"title": "Log", "type": "string"}, "type": {"const": "AgentFinish", "default": "AgentFinish", "enum": ["AgentFinish"], "title": "Type", "type": "string"}}, "required": ["return_values", "log"], "title": "AgentFinish", "type": "object"}}, "properties": {"input": {"default": null, "title": "Input", "type": "string"}, "agent_outcome": {"anyOf": [{"$ref": "#/$defs/AgentAction"}, {"$ref": "#/$defs/AgentFinish"}, {"type": "null"}], "default": null, "title": "Agent Outcome"}, "intermediate_steps": {"default": null, "items": {"maxItems": 2, "minItems": 2, "prefixItems": [{"$ref": "#/$defs/AgentAction"}, {"type": "string"}], "type": "array"}, "title": "Intermediate Steps", "type": "array"}}, "title": "LangGraphInput", "type": "object"}' + '{"$defs": {"AgentAction": {"description": "Represents a request to execute an action by an agent.\\n\\nThe action consists of the name of the tool to execute and the input to pass\\nto the tool. The log is used to pass along extra information about the action.", "properties": {"tool": {"title": "Tool", "type": "string"}, "tool_input": {"anyOf": [{"type": "string"}, {"additionalProperties": true, "type": "object"}], "title": "Tool Input"}, "log": {"title": "Log", "type": "string"}, "type": {"const": "AgentAction", "default": "AgentAction", "title": "Type", "type": "string"}}, "required": ["tool", "tool_input", "log"], "title": "AgentAction", "type": "object"}, "AgentFinish": {"description": "Final return value of an ActionAgent.\\n\\nAgents return an AgentFinish when they have reached a stopping condition.", "properties": {"return_values": {"additionalProperties": true, "title": "Return Values", "type": "object"}, "log": {"title": "Log", "type": "string"}, "type": {"const": "AgentFinish", "default": "AgentFinish", "title": "Type", "type": "string"}}, "required": ["return_values", "log"], "title": "AgentFinish", "type": "object"}}, "properties": {"input": {"title": "Input", "type": "string"}, "agent_outcome": {"anyOf": [{"$ref": "#/$defs/AgentAction"}, {"$ref": "#/$defs/AgentFinish"}, {"type": "null"}], "title": "Agent Outcome"}, "intermediate_steps": {"items": {"maxItems": 2, "minItems": 2, "prefixItems": [{"$ref": "#/$defs/AgentAction"}, {"type": "string"}], "type": "array"}, "title": "Intermediate Steps", "type": "array"}}, "title": "AgentState", "type": "object"}' # --- # name: test_conditional_state_graph[memory].1 - '{"$defs": {"AgentAction": {"description": "Represents a request to execute an action by an agent.\\n\\nThe action consists of the name of the tool to execute and the input to pass\\nto the tool. The log is used to pass along extra information about the action.", "properties": {"tool": {"title": "Tool", "type": "string"}, "tool_input": {"anyOf": [{"type": "string"}, {"type": "object"}], "title": "Tool Input"}, "log": {"title": "Log", "type": "string"}, "type": {"const": "AgentAction", "default": "AgentAction", "enum": ["AgentAction"], "title": "Type", "type": "string"}}, "required": ["tool", "tool_input", "log"], "title": "AgentAction", "type": "object"}, "AgentFinish": {"description": "Final return value of an ActionAgent.\\n\\nAgents return an AgentFinish when they have reached a stopping condition.", "properties": {"return_values": {"title": "Return Values", "type": "object"}, "log": {"title": "Log", "type": "string"}, "type": {"const": "AgentFinish", "default": "AgentFinish", "enum": ["AgentFinish"], "title": "Type", "type": "string"}}, "required": ["return_values", "log"], "title": "AgentFinish", "type": "object"}}, "properties": {"input": {"default": null, "title": "Input", "type": "string"}, "agent_outcome": {"anyOf": [{"$ref": "#/$defs/AgentAction"}, {"$ref": "#/$defs/AgentFinish"}, {"type": "null"}], "default": null, "title": "Agent Outcome"}, "intermediate_steps": {"default": null, "items": {"maxItems": 2, "minItems": 2, "prefixItems": [{"$ref": "#/$defs/AgentAction"}, {"type": "string"}], "type": "array"}, "title": "Intermediate Steps", "type": "array"}}, "title": "LangGraphOutput", "type": "object"}' + '{"$defs": {"AgentAction": {"description": "Represents a request to execute an action by an agent.\\n\\nThe action consists of the name of the tool to execute and the input to pass\\nto the tool. The log is used to pass along extra information about the action.", "properties": {"tool": {"title": "Tool", "type": "string"}, "tool_input": {"anyOf": [{"type": "string"}, {"additionalProperties": true, "type": "object"}], "title": "Tool Input"}, "log": {"title": "Log", "type": "string"}, "type": {"const": "AgentAction", "default": "AgentAction", "title": "Type", "type": "string"}}, "required": ["tool", "tool_input", "log"], "title": "AgentAction", "type": "object"}, "AgentFinish": {"description": "Final return value of an ActionAgent.\\n\\nAgents return an AgentFinish when they have reached a stopping condition.", "properties": {"return_values": {"additionalProperties": true, "title": "Return Values", "type": "object"}, "log": {"title": "Log", "type": "string"}, "type": {"const": "AgentFinish", "default": "AgentFinish", "title": "Type", "type": "string"}}, "required": ["return_values", "log"], "title": "AgentFinish", "type": "object"}}, "properties": {"input": {"title": "Input", "type": "string"}, "agent_outcome": {"anyOf": [{"$ref": "#/$defs/AgentAction"}, {"$ref": "#/$defs/AgentFinish"}, {"type": "null"}], "title": "Agent Outcome"}, "intermediate_steps": {"items": {"maxItems": 2, "minItems": 2, "prefixItems": [{"$ref": "#/$defs/AgentAction"}, {"type": "string"}], "type": "array"}, "title": "Intermediate Steps", "type": "array"}}, "title": "AgentState", "type": "object"}' # --- # name: test_conditional_state_graph[memory].2 ''' @@ -189,10 +189,10 @@ ''' # --- # name: test_message_graph[memory] - '{"$defs": {"AIMessage": {"additionalProperties": true, "description": "Message from an AI.\\n\\nAIMessage is returned from a chat model as a response to a prompt.\\n\\nThis message represents the output of the model and consists of both\\nthe raw output as returned by the model together standardized fields\\n(e.g., tool calls, usage metadata) added by the LangChain framework.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"title": "Additional Kwargs", "type": "object"}, "response_metadata": {"title": "Response Metadata", "type": "object"}, "type": {"const": "ai", "default": "ai", "enum": ["ai"], "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "example": {"default": false, "title": "Example", "type": "boolean"}, "tool_calls": {"default": [], "items": {"$ref": "#/$defs/ToolCall"}, "title": "Tool Calls", "type": "array"}, "invalid_tool_calls": {"default": [], "items": {"$ref": "#/$defs/InvalidToolCall"}, "title": "Invalid Tool Calls", "type": "array"}, "usage_metadata": {"anyOf": [{"$ref": "#/$defs/UsageMetadata"}, {"type": "null"}], "default": null}}, "required": ["content"], "title": "AIMessage", "type": "object"}, "AIMessageChunk": {"additionalProperties": true, "description": "Message chunk from an AI.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"title": "Additional Kwargs", "type": "object"}, "response_metadata": {"title": "Response Metadata", "type": "object"}, "type": {"const": "AIMessageChunk", "default": "AIMessageChunk", "enum": ["AIMessageChunk"], "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "example": {"default": false, "title": "Example", "type": "boolean"}, "tool_calls": {"default": [], "items": {"$ref": "#/$defs/ToolCall"}, "title": "Tool Calls", "type": "array"}, "invalid_tool_calls": {"default": [], "items": {"$ref": "#/$defs/InvalidToolCall"}, "title": "Invalid Tool Calls", "type": "array"}, "usage_metadata": {"anyOf": [{"$ref": "#/$defs/UsageMetadata"}, {"type": "null"}], "default": null}, "tool_call_chunks": {"default": [], "items": {"$ref": "#/$defs/ToolCallChunk"}, "title": "Tool Call Chunks", "type": "array"}}, "required": ["content"], "title": "AIMessageChunk", "type": "object"}, "ChatMessage": {"additionalProperties": true, "description": "Message that can be assigned an arbitrary speaker (i.e. role).", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"title": "Additional Kwargs", "type": "object"}, "response_metadata": {"title": "Response Metadata", "type": "object"}, "type": {"const": "chat", "default": "chat", "enum": ["chat"], "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "role": {"title": "Role", "type": "string"}}, "required": ["content", "role"], "title": "ChatMessage", "type": "object"}, "ChatMessageChunk": {"additionalProperties": true, "description": "Chat Message chunk.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"title": "Additional Kwargs", "type": "object"}, "response_metadata": {"title": "Response Metadata", "type": "object"}, "type": {"const": "ChatMessageChunk", "default": "ChatMessageChunk", "enum": ["ChatMessageChunk"], "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "role": {"title": "Role", "type": "string"}}, "required": ["content", "role"], "title": "ChatMessageChunk", "type": "object"}, "FunctionMessage": {"additionalProperties": true, "description": "Message for passing the result of executing a tool back to a model.\\n\\nFunctionMessage are an older version of the ToolMessage schema, and\\ndo not contain the tool_call_id field.\\n\\nThe tool_call_id field is used to associate the tool call request with the\\ntool call response. This is useful in situations where a chat model is able\\nto request multiple tool calls in parallel.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"title": "Additional Kwargs", "type": "object"}, "response_metadata": {"title": "Response Metadata", "type": "object"}, "type": {"const": "function", "default": "function", "enum": ["function"], "title": "Type", "type": "string"}, "name": {"title": "Name", "type": "string"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}}, "required": ["content", "name"], "title": "FunctionMessage", "type": "object"}, "FunctionMessageChunk": {"additionalProperties": true, "description": "Function Message chunk.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"title": "Additional Kwargs", "type": "object"}, "response_metadata": {"title": "Response Metadata", "type": "object"}, "type": {"const": "FunctionMessageChunk", "default": "FunctionMessageChunk", "enum": ["FunctionMessageChunk"], "title": "Type", "type": "string"}, "name": {"title": "Name", "type": "string"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}}, "required": ["content", "name"], "title": "FunctionMessageChunk", "type": "object"}, "HumanMessage": {"additionalProperties": true, "description": "Message from a human.\\n\\nHumanMessages are messages that are passed in from a human to the model.\\n\\nExample:\\n\\n .. code-block:: python\\n\\n from langchain_core.messages import HumanMessage, SystemMessage\\n\\n messages = [\\n SystemMessage(\\n content=\\"You are a helpful assistant! Your name is Bob.\\"\\n ),\\n HumanMessage(\\n content=\\"What is your name?\\"\\n )\\n ]\\n\\n # Instantiate a chat model and invoke it with the messages\\n model = ...\\n print(model.invoke(messages))", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"title": "Additional Kwargs", "type": "object"}, "response_metadata": {"title": "Response Metadata", "type": "object"}, "type": {"const": "human", "default": "human", "enum": ["human"], "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "example": {"default": false, "title": "Example", "type": "boolean"}}, "required": ["content"], "title": "HumanMessage", "type": "object"}, "HumanMessageChunk": {"additionalProperties": true, "description": "Human Message chunk.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"title": "Additional Kwargs", "type": "object"}, "response_metadata": {"title": "Response Metadata", "type": "object"}, "type": {"const": "HumanMessageChunk", "default": "HumanMessageChunk", "enum": ["HumanMessageChunk"], "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "example": {"default": false, "title": "Example", "type": "boolean"}}, "required": ["content"], "title": "HumanMessageChunk", "type": "object"}, "InputTokenDetails": {"description": "Breakdown of input token counts.\\n\\nDoes *not* need to sum to full input token count. Does *not* need to have all keys.\\n\\nExample:\\n\\n .. code-block:: python\\n\\n {\\n \\"audio\\": 10,\\n \\"cache_creation\\": 200,\\n \\"cache_read\\": 100,\\n }\\n\\n.. versionadded:: 0.3.9\\n\\nMay also hold extra provider-specific keys.", "properties": {"audio": {"title": "Audio", "type": "integer"}, "cache_creation": {"title": "Cache Creation", "type": "integer"}, "cache_read": {"title": "Cache Read", "type": "integer"}}, "title": "InputTokenDetails", "type": "object"}, "InvalidToolCall": {"description": "Allowance for errors made by LLM.\\n\\nHere we add an `error` key to surface errors made during generation\\n(e.g., invalid JSON arguments.)", "properties": {"name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "args": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Args"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Id"}, "error": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Error"}, "type": {"const": "invalid_tool_call", "enum": ["invalid_tool_call"], "title": "Type", "type": "string"}}, "required": ["name", "args", "id", "error"], "title": "InvalidToolCall", "type": "object"}, "OutputTokenDetails": {"description": "Breakdown of output token counts.\\n\\nDoes *not* need to sum to full output token count. Does *not* need to have all keys.\\n\\nExample:\\n\\n .. code-block:: python\\n\\n {\\n \\"audio\\": 10,\\n \\"reasoning\\": 200,\\n }\\n\\n.. versionadded:: 0.3.9", "properties": {"audio": {"title": "Audio", "type": "integer"}, "reasoning": {"title": "Reasoning", "type": "integer"}}, "title": "OutputTokenDetails", "type": "object"}, "SystemMessage": {"additionalProperties": true, "description": "Message for priming AI behavior.\\n\\nThe system message is usually passed in as the first of a sequence\\nof input messages.\\n\\nExample:\\n\\n .. code-block:: python\\n\\n from langchain_core.messages import HumanMessage, SystemMessage\\n\\n messages = [\\n SystemMessage(\\n content=\\"You are a helpful assistant! Your name is Bob.\\"\\n ),\\n HumanMessage(\\n content=\\"What is your name?\\"\\n )\\n ]\\n\\n # Define a chat model and invoke it with the messages\\n print(model.invoke(messages))", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"title": "Additional Kwargs", "type": "object"}, "response_metadata": {"title": "Response Metadata", "type": "object"}, "type": {"const": "system", "default": "system", "enum": ["system"], "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}}, "required": ["content"], "title": "SystemMessage", "type": "object"}, "SystemMessageChunk": {"additionalProperties": true, "description": "System Message chunk.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"title": "Additional Kwargs", "type": "object"}, "response_metadata": {"title": "Response Metadata", "type": "object"}, "type": {"const": "SystemMessageChunk", "default": "SystemMessageChunk", "enum": ["SystemMessageChunk"], "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}}, "required": ["content"], "title": "SystemMessageChunk", "type": "object"}, "ToolCall": {"description": "Represents a request to call a tool.\\n\\nExample:\\n\\n .. code-block:: python\\n\\n {\\n \\"name\\": \\"foo\\",\\n \\"args\\": {\\"a\\": 1},\\n \\"id\\": \\"123\\"\\n }\\n\\n This represents a request to call the tool named \\"foo\\" with arguments {\\"a\\": 1}\\n and an identifier of \\"123\\".", "properties": {"name": {"title": "Name", "type": "string"}, "args": {"title": "Args", "type": "object"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Id"}, "type": {"const": "tool_call", "enum": ["tool_call"], "title": "Type", "type": "string"}}, "required": ["name", "args", "id"], "title": "ToolCall", "type": "object"}, "ToolCallChunk": {"description": "A chunk of a tool call (e.g., as part of a stream).\\n\\nWhen merging ToolCallChunks (e.g., via AIMessageChunk.__add__),\\nall string attributes are concatenated. Chunks are only merged if their\\nvalues of `index` are equal and not None.\\n\\nExample:\\n\\n.. code-block:: python\\n\\n left_chunks = [ToolCallChunk(name=\\"foo\\", args=\'{\\"a\\":\', index=0)]\\n right_chunks = [ToolCallChunk(name=None, args=\'1}\', index=0)]\\n\\n (\\n AIMessageChunk(content=\\"\\", tool_call_chunks=left_chunks)\\n + AIMessageChunk(content=\\"\\", tool_call_chunks=right_chunks)\\n ).tool_call_chunks == [ToolCallChunk(name=\'foo\', args=\'{\\"a\\":1}\', index=0)]", "properties": {"name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "args": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Args"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Id"}, "index": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Index"}, "type": {"const": "tool_call_chunk", "enum": ["tool_call_chunk"], "title": "Type", "type": "string"}}, "required": ["name", "args", "id", "index"], "title": "ToolCallChunk", "type": "object"}, "ToolMessage": {"additionalProperties": true, "description": "Message for passing the result of executing a tool back to a model.\\n\\nToolMessages contain the result of a tool invocation. Typically, the result\\nis encoded inside the `content` field.\\n\\nExample: A ToolMessage representing a result of 42 from a tool call with id\\n\\n .. code-block:: python\\n\\n from langchain_core.messages import ToolMessage\\n\\n ToolMessage(content=\'42\', tool_call_id=\'call_Jja7J89XsjrOLA5r!MEOW!SL\')\\n\\n\\nExample: A ToolMessage where only part of the tool output is sent to the model\\n and the full output is passed in to artifact.\\n\\n .. versionadded:: 0.2.17\\n\\n .. code-block:: python\\n\\n from langchain_core.messages import ToolMessage\\n\\n tool_output = {\\n \\"stdout\\": \\"From the graph we can see that the correlation between x and y is ...\\",\\n \\"stderr\\": None,\\n \\"artifacts\\": {\\"type\\": \\"image\\", \\"base64_data\\": \\"/9j/4gIcSU...\\"},\\n }\\n\\n ToolMessage(\\n content=tool_output[\\"stdout\\"],\\n artifact=tool_output,\\n tool_call_id=\'call_Jja7J89XsjrOLA5r!MEOW!SL\',\\n )\\n\\nThe tool_call_id field is used to associate the tool call request with the\\ntool call response. This is useful in situations where a chat model is able\\nto request multiple tool calls in parallel.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"title": "Additional Kwargs", "type": "object"}, "response_metadata": {"title": "Response Metadata", "type": "object"}, "type": {"const": "tool", "default": "tool", "enum": ["tool"], "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "tool_call_id": {"title": "Tool Call Id", "type": "string"}, "artifact": {"default": null, "title": "Artifact"}, "status": {"default": "success", "enum": ["success", "error"], "title": "Status", "type": "string"}}, "required": ["content", "tool_call_id"], "title": "ToolMessage", "type": "object"}, "ToolMessageChunk": {"additionalProperties": true, "description": "Tool Message chunk.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"title": "Additional Kwargs", "type": "object"}, "response_metadata": {"title": "Response Metadata", "type": "object"}, "type": {"const": "ToolMessageChunk", "default": "ToolMessageChunk", "enum": ["ToolMessageChunk"], "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "tool_call_id": {"title": "Tool Call Id", "type": "string"}, "artifact": {"default": null, "title": "Artifact"}, "status": {"default": "success", "enum": ["success", "error"], "title": "Status", "type": "string"}}, "required": ["content", "tool_call_id"], "title": "ToolMessageChunk", "type": "object"}, "UsageMetadata": {"description": "Usage metadata for a message, such as token counts.\\n\\nThis is a standard representation of token usage that is consistent across models.\\n\\nExample:\\n\\n .. code-block:: python\\n\\n {\\n \\"input_tokens\\": 350,\\n \\"output_tokens\\": 240,\\n \\"total_tokens\\": 590,\\n \\"input_token_details\\": {\\n \\"audio\\": 10,\\n \\"cache_creation\\": 200,\\n \\"cache_read\\": 100,\\n },\\n \\"output_token_details\\": {\\n \\"audio\\": 10,\\n \\"reasoning\\": 200,\\n }\\n }\\n\\n.. versionchanged:: 0.3.9\\n\\n Added ``input_token_details`` and ``output_token_details``.", "properties": {"input_tokens": {"title": "Input Tokens", "type": "integer"}, "output_tokens": {"title": "Output Tokens", "type": "integer"}, "total_tokens": {"title": "Total Tokens", "type": "integer"}, "input_token_details": {"$ref": "#/$defs/InputTokenDetails"}, "output_token_details": {"$ref": "#/$defs/OutputTokenDetails"}}, "required": ["input_tokens", "output_tokens", "total_tokens"], "title": "UsageMetadata", "type": "object"}}, "default": null, "items": {"oneOf": [{"$ref": "#/$defs/AIMessage"}, {"$ref": "#/$defs/HumanMessage"}, {"$ref": "#/$defs/ChatMessage"}, {"$ref": "#/$defs/SystemMessage"}, {"$ref": "#/$defs/FunctionMessage"}, {"$ref": "#/$defs/ToolMessage"}, {"$ref": "#/$defs/AIMessageChunk"}, {"$ref": "#/$defs/HumanMessageChunk"}, {"$ref": "#/$defs/ChatMessageChunk"}, {"$ref": "#/$defs/SystemMessageChunk"}, {"$ref": "#/$defs/FunctionMessageChunk"}, {"$ref": "#/$defs/ToolMessageChunk"}]}, "title": "LangGraphInput", "type": "array"}' + '{"$defs": {"AIMessage": {"additionalProperties": true, "description": "Message from an AI.\\n\\nAIMessage is returned from a chat model as a response to a prompt.\\n\\nThis message represents the output of the model and consists of both\\nthe raw output as returned by the model together standardized fields\\n(e.g., tool calls, usage metadata) added by the LangChain framework.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"additionalProperties": true, "type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"additionalProperties": true, "title": "Additional Kwargs", "type": "object"}, "response_metadata": {"additionalProperties": true, "title": "Response Metadata", "type": "object"}, "type": {"const": "ai", "default": "ai", "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "example": {"default": false, "title": "Example", "type": "boolean"}, "tool_calls": {"default": [], "items": {"$ref": "#/$defs/ToolCall"}, "title": "Tool Calls", "type": "array"}, "invalid_tool_calls": {"default": [], "items": {"$ref": "#/$defs/InvalidToolCall"}, "title": "Invalid Tool Calls", "type": "array"}, "usage_metadata": {"anyOf": [{"$ref": "#/$defs/UsageMetadata"}, {"type": "null"}], "default": null}}, "required": ["content"], "title": "AIMessage", "type": "object"}, "AIMessageChunk": {"additionalProperties": true, "description": "Message chunk from an AI.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"additionalProperties": true, "type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"additionalProperties": true, "title": "Additional Kwargs", "type": "object"}, "response_metadata": {"additionalProperties": true, "title": "Response Metadata", "type": "object"}, "type": {"const": "AIMessageChunk", "default": "AIMessageChunk", "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "example": {"default": false, "title": "Example", "type": "boolean"}, "tool_calls": {"default": [], "items": {"$ref": "#/$defs/ToolCall"}, "title": "Tool Calls", "type": "array"}, "invalid_tool_calls": {"default": [], "items": {"$ref": "#/$defs/InvalidToolCall"}, "title": "Invalid Tool Calls", "type": "array"}, "usage_metadata": {"anyOf": [{"$ref": "#/$defs/UsageMetadata"}, {"type": "null"}], "default": null}, "tool_call_chunks": {"default": [], "items": {"$ref": "#/$defs/ToolCallChunk"}, "title": "Tool Call Chunks", "type": "array"}}, "required": ["content"], "title": "AIMessageChunk", "type": "object"}, "ChatMessage": {"additionalProperties": true, "description": "Message that can be assigned an arbitrary speaker (i.e. role).", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"additionalProperties": true, "type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"additionalProperties": true, "title": "Additional Kwargs", "type": "object"}, "response_metadata": {"additionalProperties": true, "title": "Response Metadata", "type": "object"}, "type": {"const": "chat", "default": "chat", "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "role": {"title": "Role", "type": "string"}}, "required": ["content", "role"], "title": "ChatMessage", "type": "object"}, "ChatMessageChunk": {"additionalProperties": true, "description": "Chat Message chunk.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"additionalProperties": true, "type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"additionalProperties": true, "title": "Additional Kwargs", "type": "object"}, "response_metadata": {"additionalProperties": true, "title": "Response Metadata", "type": "object"}, "type": {"const": "ChatMessageChunk", "default": "ChatMessageChunk", "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "role": {"title": "Role", "type": "string"}}, "required": ["content", "role"], "title": "ChatMessageChunk", "type": "object"}, "FunctionMessage": {"additionalProperties": true, "description": "Message for passing the result of executing a tool back to a model.\\n\\nFunctionMessage are an older version of the ToolMessage schema, and\\ndo not contain the tool_call_id field.\\n\\nThe tool_call_id field is used to associate the tool call request with the\\ntool call response. This is useful in situations where a chat model is able\\nto request multiple tool calls in parallel.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"additionalProperties": true, "type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"additionalProperties": true, "title": "Additional Kwargs", "type": "object"}, "response_metadata": {"additionalProperties": true, "title": "Response Metadata", "type": "object"}, "type": {"const": "function", "default": "function", "title": "Type", "type": "string"}, "name": {"title": "Name", "type": "string"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}}, "required": ["content", "name"], "title": "FunctionMessage", "type": "object"}, "FunctionMessageChunk": {"additionalProperties": true, "description": "Function Message chunk.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"additionalProperties": true, "type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"additionalProperties": true, "title": "Additional Kwargs", "type": "object"}, "response_metadata": {"additionalProperties": true, "title": "Response Metadata", "type": "object"}, "type": {"const": "FunctionMessageChunk", "default": "FunctionMessageChunk", "title": "Type", "type": "string"}, "name": {"title": "Name", "type": "string"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}}, "required": ["content", "name"], "title": "FunctionMessageChunk", "type": "object"}, "HumanMessage": {"additionalProperties": true, "description": "Message from a human.\\n\\nHumanMessages are messages that are passed in from a human to the model.\\n\\nExample:\\n\\n .. code-block:: python\\n\\n from langchain_core.messages import HumanMessage, SystemMessage\\n\\n messages = [\\n SystemMessage(\\n content=\\"You are a helpful assistant! Your name is Bob.\\"\\n ),\\n HumanMessage(\\n content=\\"What is your name?\\"\\n )\\n ]\\n\\n # Instantiate a chat model and invoke it with the messages\\n model = ...\\n print(model.invoke(messages))", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"additionalProperties": true, "type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"additionalProperties": true, "title": "Additional Kwargs", "type": "object"}, "response_metadata": {"additionalProperties": true, "title": "Response Metadata", "type": "object"}, "type": {"const": "human", "default": "human", "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "example": {"default": false, "title": "Example", "type": "boolean"}}, "required": ["content"], "title": "HumanMessage", "type": "object"}, "HumanMessageChunk": {"additionalProperties": true, "description": "Human Message chunk.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"additionalProperties": true, "type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"additionalProperties": true, "title": "Additional Kwargs", "type": "object"}, "response_metadata": {"additionalProperties": true, "title": "Response Metadata", "type": "object"}, "type": {"const": "HumanMessageChunk", "default": "HumanMessageChunk", "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "example": {"default": false, "title": "Example", "type": "boolean"}}, "required": ["content"], "title": "HumanMessageChunk", "type": "object"}, "InputTokenDetails": {"description": "Breakdown of input token counts.\\n\\nDoes *not* need to sum to full input token count. Does *not* need to have all keys.\\n\\nExample:\\n\\n .. code-block:: python\\n\\n {\\n \\"audio\\": 10,\\n \\"cache_creation\\": 200,\\n \\"cache_read\\": 100,\\n }\\n\\n.. versionadded:: 0.3.9\\n\\nMay also hold extra provider-specific keys.", "properties": {"audio": {"title": "Audio", "type": "integer"}, "cache_creation": {"title": "Cache Creation", "type": "integer"}, "cache_read": {"title": "Cache Read", "type": "integer"}}, "title": "InputTokenDetails", "type": "object"}, "InvalidToolCall": {"description": "Allowance for errors made by LLM.\\n\\nHere we add an `error` key to surface errors made during generation\\n(e.g., invalid JSON arguments.)", "properties": {"name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "args": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Args"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Id"}, "error": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Error"}, "type": {"const": "invalid_tool_call", "title": "Type", "type": "string"}}, "required": ["name", "args", "id", "error"], "title": "InvalidToolCall", "type": "object"}, "OutputTokenDetails": {"description": "Breakdown of output token counts.\\n\\nDoes *not* need to sum to full output token count. Does *not* need to have all keys.\\n\\nExample:\\n\\n .. code-block:: python\\n\\n {\\n \\"audio\\": 10,\\n \\"reasoning\\": 200,\\n }\\n\\n.. versionadded:: 0.3.9", "properties": {"audio": {"title": "Audio", "type": "integer"}, "reasoning": {"title": "Reasoning", "type": "integer"}}, "title": "OutputTokenDetails", "type": "object"}, "SystemMessage": {"additionalProperties": true, "description": "Message for priming AI behavior.\\n\\nThe system message is usually passed in as the first of a sequence\\nof input messages.\\n\\nExample:\\n\\n .. code-block:: python\\n\\n from langchain_core.messages import HumanMessage, SystemMessage\\n\\n messages = [\\n SystemMessage(\\n content=\\"You are a helpful assistant! Your name is Bob.\\"\\n ),\\n HumanMessage(\\n content=\\"What is your name?\\"\\n )\\n ]\\n\\n # Define a chat model and invoke it with the messages\\n print(model.invoke(messages))", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"additionalProperties": true, "type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"additionalProperties": true, "title": "Additional Kwargs", "type": "object"}, "response_metadata": {"additionalProperties": true, "title": "Response Metadata", "type": "object"}, "type": {"const": "system", "default": "system", "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}}, "required": ["content"], "title": "SystemMessage", "type": "object"}, "SystemMessageChunk": {"additionalProperties": true, "description": "System Message chunk.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"additionalProperties": true, "type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"additionalProperties": true, "title": "Additional Kwargs", "type": "object"}, "response_metadata": {"additionalProperties": true, "title": "Response Metadata", "type": "object"}, "type": {"const": "SystemMessageChunk", "default": "SystemMessageChunk", "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}}, "required": ["content"], "title": "SystemMessageChunk", "type": "object"}, "ToolCall": {"description": "Represents a request to call a tool.\\n\\nExample:\\n\\n .. code-block:: python\\n\\n {\\n \\"name\\": \\"foo\\",\\n \\"args\\": {\\"a\\": 1},\\n \\"id\\": \\"123\\"\\n }\\n\\n This represents a request to call the tool named \\"foo\\" with arguments {\\"a\\": 1}\\n and an identifier of \\"123\\".", "properties": {"name": {"title": "Name", "type": "string"}, "args": {"additionalProperties": true, "title": "Args", "type": "object"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Id"}, "type": {"const": "tool_call", "title": "Type", "type": "string"}}, "required": ["name", "args", "id"], "title": "ToolCall", "type": "object"}, "ToolCallChunk": {"description": "A chunk of a tool call (e.g., as part of a stream).\\n\\nWhen merging ToolCallChunks (e.g., via AIMessageChunk.__add__),\\nall string attributes are concatenated. Chunks are only merged if their\\nvalues of `index` are equal and not None.\\n\\nExample:\\n\\n.. code-block:: python\\n\\n left_chunks = [ToolCallChunk(name=\\"foo\\", args=\'{\\"a\\":\', index=0)]\\n right_chunks = [ToolCallChunk(name=None, args=\'1}\', index=0)]\\n\\n (\\n AIMessageChunk(content=\\"\\", tool_call_chunks=left_chunks)\\n + AIMessageChunk(content=\\"\\", tool_call_chunks=right_chunks)\\n ).tool_call_chunks == [ToolCallChunk(name=\'foo\', args=\'{\\"a\\":1}\', index=0)]", "properties": {"name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "args": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Args"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Id"}, "index": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Index"}, "type": {"const": "tool_call_chunk", "title": "Type", "type": "string"}}, "required": ["name", "args", "id", "index"], "title": "ToolCallChunk", "type": "object"}, "ToolMessage": {"additionalProperties": true, "description": "Message for passing the result of executing a tool back to a model.\\n\\nToolMessages contain the result of a tool invocation. Typically, the result\\nis encoded inside the `content` field.\\n\\nExample: A ToolMessage representing a result of 42 from a tool call with id\\n\\n .. code-block:: python\\n\\n from langchain_core.messages import ToolMessage\\n\\n ToolMessage(content=\'42\', tool_call_id=\'call_Jja7J89XsjrOLA5r!MEOW!SL\')\\n\\n\\nExample: A ToolMessage where only part of the tool output is sent to the model\\n and the full output is passed in to artifact.\\n\\n .. versionadded:: 0.2.17\\n\\n .. code-block:: python\\n\\n from langchain_core.messages import ToolMessage\\n\\n tool_output = {\\n \\"stdout\\": \\"From the graph we can see that the correlation between x and y is ...\\",\\n \\"stderr\\": None,\\n \\"artifacts\\": {\\"type\\": \\"image\\", \\"base64_data\\": \\"/9j/4gIcSU...\\"},\\n }\\n\\n ToolMessage(\\n content=tool_output[\\"stdout\\"],\\n artifact=tool_output,\\n tool_call_id=\'call_Jja7J89XsjrOLA5r!MEOW!SL\',\\n )\\n\\nThe tool_call_id field is used to associate the tool call request with the\\ntool call response. This is useful in situations where a chat model is able\\nto request multiple tool calls in parallel.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"additionalProperties": true, "type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"additionalProperties": true, "title": "Additional Kwargs", "type": "object"}, "response_metadata": {"additionalProperties": true, "title": "Response Metadata", "type": "object"}, "type": {"const": "tool", "default": "tool", "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "tool_call_id": {"title": "Tool Call Id", "type": "string"}, "artifact": {"default": null, "title": "Artifact"}, "status": {"default": "success", "enum": ["success", "error"], "title": "Status", "type": "string"}}, "required": ["content", "tool_call_id"], "title": "ToolMessage", "type": "object"}, "ToolMessageChunk": {"additionalProperties": true, "description": "Tool Message chunk.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"additionalProperties": true, "type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"additionalProperties": true, "title": "Additional Kwargs", "type": "object"}, "response_metadata": {"additionalProperties": true, "title": "Response Metadata", "type": "object"}, "type": {"const": "ToolMessageChunk", "default": "ToolMessageChunk", "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "tool_call_id": {"title": "Tool Call Id", "type": "string"}, "artifact": {"default": null, "title": "Artifact"}, "status": {"default": "success", "enum": ["success", "error"], "title": "Status", "type": "string"}}, "required": ["content", "tool_call_id"], "title": "ToolMessageChunk", "type": "object"}, "UsageMetadata": {"description": "Usage metadata for a message, such as token counts.\\n\\nThis is a standard representation of token usage that is consistent across models.\\n\\nExample:\\n\\n .. code-block:: python\\n\\n {\\n \\"input_tokens\\": 350,\\n \\"output_tokens\\": 240,\\n \\"total_tokens\\": 590,\\n \\"input_token_details\\": {\\n \\"audio\\": 10,\\n \\"cache_creation\\": 200,\\n \\"cache_read\\": 100,\\n },\\n \\"output_token_details\\": {\\n \\"audio\\": 10,\\n \\"reasoning\\": 200,\\n }\\n }\\n\\n.. versionchanged:: 0.3.9\\n\\n Added ``input_token_details`` and ``output_token_details``.", "properties": {"input_tokens": {"title": "Input Tokens", "type": "integer"}, "output_tokens": {"title": "Output Tokens", "type": "integer"}, "total_tokens": {"title": "Total Tokens", "type": "integer"}, "input_token_details": {"$ref": "#/$defs/InputTokenDetails"}, "output_token_details": {"$ref": "#/$defs/OutputTokenDetails"}}, "required": ["input_tokens", "output_tokens", "total_tokens"], "title": "UsageMetadata", "type": "object"}}, "default": null, "items": {"oneOf": [{"$ref": "#/$defs/AIMessage"}, {"$ref": "#/$defs/HumanMessage"}, {"$ref": "#/$defs/ChatMessage"}, {"$ref": "#/$defs/SystemMessage"}, {"$ref": "#/$defs/FunctionMessage"}, {"$ref": "#/$defs/ToolMessage"}, {"$ref": "#/$defs/AIMessageChunk"}, {"$ref": "#/$defs/HumanMessageChunk"}, {"$ref": "#/$defs/ChatMessageChunk"}, {"$ref": "#/$defs/SystemMessageChunk"}, {"$ref": "#/$defs/FunctionMessageChunk"}, {"$ref": "#/$defs/ToolMessageChunk"}]}, "title": "LangGraphInput", "type": "array"}' # --- # name: test_message_graph[memory].1 - '{"$defs": {"AIMessage": {"additionalProperties": true, "description": "Message from an AI.\\n\\nAIMessage is returned from a chat model as a response to a prompt.\\n\\nThis message represents the output of the model and consists of both\\nthe raw output as returned by the model together standardized fields\\n(e.g., tool calls, usage metadata) added by the LangChain framework.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"title": "Additional Kwargs", "type": "object"}, "response_metadata": {"title": "Response Metadata", "type": "object"}, "type": {"const": "ai", "default": "ai", "enum": ["ai"], "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "example": {"default": false, "title": "Example", "type": "boolean"}, "tool_calls": {"default": [], "items": {"$ref": "#/$defs/ToolCall"}, "title": "Tool Calls", "type": "array"}, "invalid_tool_calls": {"default": [], "items": {"$ref": "#/$defs/InvalidToolCall"}, "title": "Invalid Tool Calls", "type": "array"}, "usage_metadata": {"anyOf": [{"$ref": "#/$defs/UsageMetadata"}, {"type": "null"}], "default": null}}, "required": ["content"], "title": "AIMessage", "type": "object"}, "AIMessageChunk": {"additionalProperties": true, "description": "Message chunk from an AI.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"title": "Additional Kwargs", "type": "object"}, "response_metadata": {"title": "Response Metadata", "type": "object"}, "type": {"const": "AIMessageChunk", "default": "AIMessageChunk", "enum": ["AIMessageChunk"], "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "example": {"default": false, "title": "Example", "type": "boolean"}, "tool_calls": {"default": [], "items": {"$ref": "#/$defs/ToolCall"}, "title": "Tool Calls", "type": "array"}, "invalid_tool_calls": {"default": [], "items": {"$ref": "#/$defs/InvalidToolCall"}, "title": "Invalid Tool Calls", "type": "array"}, "usage_metadata": {"anyOf": [{"$ref": "#/$defs/UsageMetadata"}, {"type": "null"}], "default": null}, "tool_call_chunks": {"default": [], "items": {"$ref": "#/$defs/ToolCallChunk"}, "title": "Tool Call Chunks", "type": "array"}}, "required": ["content"], "title": "AIMessageChunk", "type": "object"}, "ChatMessage": {"additionalProperties": true, "description": "Message that can be assigned an arbitrary speaker (i.e. role).", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"title": "Additional Kwargs", "type": "object"}, "response_metadata": {"title": "Response Metadata", "type": "object"}, "type": {"const": "chat", "default": "chat", "enum": ["chat"], "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "role": {"title": "Role", "type": "string"}}, "required": ["content", "role"], "title": "ChatMessage", "type": "object"}, "ChatMessageChunk": {"additionalProperties": true, "description": "Chat Message chunk.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"title": "Additional Kwargs", "type": "object"}, "response_metadata": {"title": "Response Metadata", "type": "object"}, "type": {"const": "ChatMessageChunk", "default": "ChatMessageChunk", "enum": ["ChatMessageChunk"], "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "role": {"title": "Role", "type": "string"}}, "required": ["content", "role"], "title": "ChatMessageChunk", "type": "object"}, "FunctionMessage": {"additionalProperties": true, "description": "Message for passing the result of executing a tool back to a model.\\n\\nFunctionMessage are an older version of the ToolMessage schema, and\\ndo not contain the tool_call_id field.\\n\\nThe tool_call_id field is used to associate the tool call request with the\\ntool call response. This is useful in situations where a chat model is able\\nto request multiple tool calls in parallel.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"title": "Additional Kwargs", "type": "object"}, "response_metadata": {"title": "Response Metadata", "type": "object"}, "type": {"const": "function", "default": "function", "enum": ["function"], "title": "Type", "type": "string"}, "name": {"title": "Name", "type": "string"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}}, "required": ["content", "name"], "title": "FunctionMessage", "type": "object"}, "FunctionMessageChunk": {"additionalProperties": true, "description": "Function Message chunk.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"title": "Additional Kwargs", "type": "object"}, "response_metadata": {"title": "Response Metadata", "type": "object"}, "type": {"const": "FunctionMessageChunk", "default": "FunctionMessageChunk", "enum": ["FunctionMessageChunk"], "title": "Type", "type": "string"}, "name": {"title": "Name", "type": "string"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}}, "required": ["content", "name"], "title": "FunctionMessageChunk", "type": "object"}, "HumanMessage": {"additionalProperties": true, "description": "Message from a human.\\n\\nHumanMessages are messages that are passed in from a human to the model.\\n\\nExample:\\n\\n .. code-block:: python\\n\\n from langchain_core.messages import HumanMessage, SystemMessage\\n\\n messages = [\\n SystemMessage(\\n content=\\"You are a helpful assistant! Your name is Bob.\\"\\n ),\\n HumanMessage(\\n content=\\"What is your name?\\"\\n )\\n ]\\n\\n # Instantiate a chat model and invoke it with the messages\\n model = ...\\n print(model.invoke(messages))", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"title": "Additional Kwargs", "type": "object"}, "response_metadata": {"title": "Response Metadata", "type": "object"}, "type": {"const": "human", "default": "human", "enum": ["human"], "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "example": {"default": false, "title": "Example", "type": "boolean"}}, "required": ["content"], "title": "HumanMessage", "type": "object"}, "HumanMessageChunk": {"additionalProperties": true, "description": "Human Message chunk.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"title": "Additional Kwargs", "type": "object"}, "response_metadata": {"title": "Response Metadata", "type": "object"}, "type": {"const": "HumanMessageChunk", "default": "HumanMessageChunk", "enum": ["HumanMessageChunk"], "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "example": {"default": false, "title": "Example", "type": "boolean"}}, "required": ["content"], "title": "HumanMessageChunk", "type": "object"}, "InputTokenDetails": {"description": "Breakdown of input token counts.\\n\\nDoes *not* need to sum to full input token count. Does *not* need to have all keys.\\n\\nExample:\\n\\n .. code-block:: python\\n\\n {\\n \\"audio\\": 10,\\n \\"cache_creation\\": 200,\\n \\"cache_read\\": 100,\\n }\\n\\n.. versionadded:: 0.3.9\\n\\nMay also hold extra provider-specific keys.", "properties": {"audio": {"title": "Audio", "type": "integer"}, "cache_creation": {"title": "Cache Creation", "type": "integer"}, "cache_read": {"title": "Cache Read", "type": "integer"}}, "title": "InputTokenDetails", "type": "object"}, "InvalidToolCall": {"description": "Allowance for errors made by LLM.\\n\\nHere we add an `error` key to surface errors made during generation\\n(e.g., invalid JSON arguments.)", "properties": {"name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "args": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Args"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Id"}, "error": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Error"}, "type": {"const": "invalid_tool_call", "enum": ["invalid_tool_call"], "title": "Type", "type": "string"}}, "required": ["name", "args", "id", "error"], "title": "InvalidToolCall", "type": "object"}, "OutputTokenDetails": {"description": "Breakdown of output token counts.\\n\\nDoes *not* need to sum to full output token count. Does *not* need to have all keys.\\n\\nExample:\\n\\n .. code-block:: python\\n\\n {\\n \\"audio\\": 10,\\n \\"reasoning\\": 200,\\n }\\n\\n.. versionadded:: 0.3.9", "properties": {"audio": {"title": "Audio", "type": "integer"}, "reasoning": {"title": "Reasoning", "type": "integer"}}, "title": "OutputTokenDetails", "type": "object"}, "SystemMessage": {"additionalProperties": true, "description": "Message for priming AI behavior.\\n\\nThe system message is usually passed in as the first of a sequence\\nof input messages.\\n\\nExample:\\n\\n .. code-block:: python\\n\\n from langchain_core.messages import HumanMessage, SystemMessage\\n\\n messages = [\\n SystemMessage(\\n content=\\"You are a helpful assistant! Your name is Bob.\\"\\n ),\\n HumanMessage(\\n content=\\"What is your name?\\"\\n )\\n ]\\n\\n # Define a chat model and invoke it with the messages\\n print(model.invoke(messages))", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"title": "Additional Kwargs", "type": "object"}, "response_metadata": {"title": "Response Metadata", "type": "object"}, "type": {"const": "system", "default": "system", "enum": ["system"], "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}}, "required": ["content"], "title": "SystemMessage", "type": "object"}, "SystemMessageChunk": {"additionalProperties": true, "description": "System Message chunk.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"title": "Additional Kwargs", "type": "object"}, "response_metadata": {"title": "Response Metadata", "type": "object"}, "type": {"const": "SystemMessageChunk", "default": "SystemMessageChunk", "enum": ["SystemMessageChunk"], "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}}, "required": ["content"], "title": "SystemMessageChunk", "type": "object"}, "ToolCall": {"description": "Represents a request to call a tool.\\n\\nExample:\\n\\n .. code-block:: python\\n\\n {\\n \\"name\\": \\"foo\\",\\n \\"args\\": {\\"a\\": 1},\\n \\"id\\": \\"123\\"\\n }\\n\\n This represents a request to call the tool named \\"foo\\" with arguments {\\"a\\": 1}\\n and an identifier of \\"123\\".", "properties": {"name": {"title": "Name", "type": "string"}, "args": {"title": "Args", "type": "object"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Id"}, "type": {"const": "tool_call", "enum": ["tool_call"], "title": "Type", "type": "string"}}, "required": ["name", "args", "id"], "title": "ToolCall", "type": "object"}, "ToolCallChunk": {"description": "A chunk of a tool call (e.g., as part of a stream).\\n\\nWhen merging ToolCallChunks (e.g., via AIMessageChunk.__add__),\\nall string attributes are concatenated. Chunks are only merged if their\\nvalues of `index` are equal and not None.\\n\\nExample:\\n\\n.. code-block:: python\\n\\n left_chunks = [ToolCallChunk(name=\\"foo\\", args=\'{\\"a\\":\', index=0)]\\n right_chunks = [ToolCallChunk(name=None, args=\'1}\', index=0)]\\n\\n (\\n AIMessageChunk(content=\\"\\", tool_call_chunks=left_chunks)\\n + AIMessageChunk(content=\\"\\", tool_call_chunks=right_chunks)\\n ).tool_call_chunks == [ToolCallChunk(name=\'foo\', args=\'{\\"a\\":1}\', index=0)]", "properties": {"name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "args": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Args"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Id"}, "index": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Index"}, "type": {"const": "tool_call_chunk", "enum": ["tool_call_chunk"], "title": "Type", "type": "string"}}, "required": ["name", "args", "id", "index"], "title": "ToolCallChunk", "type": "object"}, "ToolMessage": {"additionalProperties": true, "description": "Message for passing the result of executing a tool back to a model.\\n\\nToolMessages contain the result of a tool invocation. Typically, the result\\nis encoded inside the `content` field.\\n\\nExample: A ToolMessage representing a result of 42 from a tool call with id\\n\\n .. code-block:: python\\n\\n from langchain_core.messages import ToolMessage\\n\\n ToolMessage(content=\'42\', tool_call_id=\'call_Jja7J89XsjrOLA5r!MEOW!SL\')\\n\\n\\nExample: A ToolMessage where only part of the tool output is sent to the model\\n and the full output is passed in to artifact.\\n\\n .. versionadded:: 0.2.17\\n\\n .. code-block:: python\\n\\n from langchain_core.messages import ToolMessage\\n\\n tool_output = {\\n \\"stdout\\": \\"From the graph we can see that the correlation between x and y is ...\\",\\n \\"stderr\\": None,\\n \\"artifacts\\": {\\"type\\": \\"image\\", \\"base64_data\\": \\"/9j/4gIcSU...\\"},\\n }\\n\\n ToolMessage(\\n content=tool_output[\\"stdout\\"],\\n artifact=tool_output,\\n tool_call_id=\'call_Jja7J89XsjrOLA5r!MEOW!SL\',\\n )\\n\\nThe tool_call_id field is used to associate the tool call request with the\\ntool call response. This is useful in situations where a chat model is able\\nto request multiple tool calls in parallel.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"title": "Additional Kwargs", "type": "object"}, "response_metadata": {"title": "Response Metadata", "type": "object"}, "type": {"const": "tool", "default": "tool", "enum": ["tool"], "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "tool_call_id": {"title": "Tool Call Id", "type": "string"}, "artifact": {"default": null, "title": "Artifact"}, "status": {"default": "success", "enum": ["success", "error"], "title": "Status", "type": "string"}}, "required": ["content", "tool_call_id"], "title": "ToolMessage", "type": "object"}, "ToolMessageChunk": {"additionalProperties": true, "description": "Tool Message chunk.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"title": "Additional Kwargs", "type": "object"}, "response_metadata": {"title": "Response Metadata", "type": "object"}, "type": {"const": "ToolMessageChunk", "default": "ToolMessageChunk", "enum": ["ToolMessageChunk"], "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "tool_call_id": {"title": "Tool Call Id", "type": "string"}, "artifact": {"default": null, "title": "Artifact"}, "status": {"default": "success", "enum": ["success", "error"], "title": "Status", "type": "string"}}, "required": ["content", "tool_call_id"], "title": "ToolMessageChunk", "type": "object"}, "UsageMetadata": {"description": "Usage metadata for a message, such as token counts.\\n\\nThis is a standard representation of token usage that is consistent across models.\\n\\nExample:\\n\\n .. code-block:: python\\n\\n {\\n \\"input_tokens\\": 350,\\n \\"output_tokens\\": 240,\\n \\"total_tokens\\": 590,\\n \\"input_token_details\\": {\\n \\"audio\\": 10,\\n \\"cache_creation\\": 200,\\n \\"cache_read\\": 100,\\n },\\n \\"output_token_details\\": {\\n \\"audio\\": 10,\\n \\"reasoning\\": 200,\\n }\\n }\\n\\n.. versionchanged:: 0.3.9\\n\\n Added ``input_token_details`` and ``output_token_details``.", "properties": {"input_tokens": {"title": "Input Tokens", "type": "integer"}, "output_tokens": {"title": "Output Tokens", "type": "integer"}, "total_tokens": {"title": "Total Tokens", "type": "integer"}, "input_token_details": {"$ref": "#/$defs/InputTokenDetails"}, "output_token_details": {"$ref": "#/$defs/OutputTokenDetails"}}, "required": ["input_tokens", "output_tokens", "total_tokens"], "title": "UsageMetadata", "type": "object"}}, "default": null, "items": {"oneOf": [{"$ref": "#/$defs/AIMessage"}, {"$ref": "#/$defs/HumanMessage"}, {"$ref": "#/$defs/ChatMessage"}, {"$ref": "#/$defs/SystemMessage"}, {"$ref": "#/$defs/FunctionMessage"}, {"$ref": "#/$defs/ToolMessage"}, {"$ref": "#/$defs/AIMessageChunk"}, {"$ref": "#/$defs/HumanMessageChunk"}, {"$ref": "#/$defs/ChatMessageChunk"}, {"$ref": "#/$defs/SystemMessageChunk"}, {"$ref": "#/$defs/FunctionMessageChunk"}, {"$ref": "#/$defs/ToolMessageChunk"}]}, "title": "LangGraphOutput", "type": "array"}' + '{"$defs": {"AIMessage": {"additionalProperties": true, "description": "Message from an AI.\\n\\nAIMessage is returned from a chat model as a response to a prompt.\\n\\nThis message represents the output of the model and consists of both\\nthe raw output as returned by the model together standardized fields\\n(e.g., tool calls, usage metadata) added by the LangChain framework.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"additionalProperties": true, "type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"additionalProperties": true, "title": "Additional Kwargs", "type": "object"}, "response_metadata": {"additionalProperties": true, "title": "Response Metadata", "type": "object"}, "type": {"const": "ai", "default": "ai", "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "example": {"default": false, "title": "Example", "type": "boolean"}, "tool_calls": {"default": [], "items": {"$ref": "#/$defs/ToolCall"}, "title": "Tool Calls", "type": "array"}, "invalid_tool_calls": {"default": [], "items": {"$ref": "#/$defs/InvalidToolCall"}, "title": "Invalid Tool Calls", "type": "array"}, "usage_metadata": {"anyOf": [{"$ref": "#/$defs/UsageMetadata"}, {"type": "null"}], "default": null}}, "required": ["content"], "title": "AIMessage", "type": "object"}, "AIMessageChunk": {"additionalProperties": true, "description": "Message chunk from an AI.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"additionalProperties": true, "type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"additionalProperties": true, "title": "Additional Kwargs", "type": "object"}, "response_metadata": {"additionalProperties": true, "title": "Response Metadata", "type": "object"}, "type": {"const": "AIMessageChunk", "default": "AIMessageChunk", "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "example": {"default": false, "title": "Example", "type": "boolean"}, "tool_calls": {"default": [], "items": {"$ref": "#/$defs/ToolCall"}, "title": "Tool Calls", "type": "array"}, "invalid_tool_calls": {"default": [], "items": {"$ref": "#/$defs/InvalidToolCall"}, "title": "Invalid Tool Calls", "type": "array"}, "usage_metadata": {"anyOf": [{"$ref": "#/$defs/UsageMetadata"}, {"type": "null"}], "default": null}, "tool_call_chunks": {"default": [], "items": {"$ref": "#/$defs/ToolCallChunk"}, "title": "Tool Call Chunks", "type": "array"}}, "required": ["content"], "title": "AIMessageChunk", "type": "object"}, "ChatMessage": {"additionalProperties": true, "description": "Message that can be assigned an arbitrary speaker (i.e. role).", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"additionalProperties": true, "type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"additionalProperties": true, "title": "Additional Kwargs", "type": "object"}, "response_metadata": {"additionalProperties": true, "title": "Response Metadata", "type": "object"}, "type": {"const": "chat", "default": "chat", "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "role": {"title": "Role", "type": "string"}}, "required": ["content", "role"], "title": "ChatMessage", "type": "object"}, "ChatMessageChunk": {"additionalProperties": true, "description": "Chat Message chunk.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"additionalProperties": true, "type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"additionalProperties": true, "title": "Additional Kwargs", "type": "object"}, "response_metadata": {"additionalProperties": true, "title": "Response Metadata", "type": "object"}, "type": {"const": "ChatMessageChunk", "default": "ChatMessageChunk", "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "role": {"title": "Role", "type": "string"}}, "required": ["content", "role"], "title": "ChatMessageChunk", "type": "object"}, "FunctionMessage": {"additionalProperties": true, "description": "Message for passing the result of executing a tool back to a model.\\n\\nFunctionMessage are an older version of the ToolMessage schema, and\\ndo not contain the tool_call_id field.\\n\\nThe tool_call_id field is used to associate the tool call request with the\\ntool call response. This is useful in situations where a chat model is able\\nto request multiple tool calls in parallel.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"additionalProperties": true, "type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"additionalProperties": true, "title": "Additional Kwargs", "type": "object"}, "response_metadata": {"additionalProperties": true, "title": "Response Metadata", "type": "object"}, "type": {"const": "function", "default": "function", "title": "Type", "type": "string"}, "name": {"title": "Name", "type": "string"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}}, "required": ["content", "name"], "title": "FunctionMessage", "type": "object"}, "FunctionMessageChunk": {"additionalProperties": true, "description": "Function Message chunk.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"additionalProperties": true, "type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"additionalProperties": true, "title": "Additional Kwargs", "type": "object"}, "response_metadata": {"additionalProperties": true, "title": "Response Metadata", "type": "object"}, "type": {"const": "FunctionMessageChunk", "default": "FunctionMessageChunk", "title": "Type", "type": "string"}, "name": {"title": "Name", "type": "string"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}}, "required": ["content", "name"], "title": "FunctionMessageChunk", "type": "object"}, "HumanMessage": {"additionalProperties": true, "description": "Message from a human.\\n\\nHumanMessages are messages that are passed in from a human to the model.\\n\\nExample:\\n\\n .. code-block:: python\\n\\n from langchain_core.messages import HumanMessage, SystemMessage\\n\\n messages = [\\n SystemMessage(\\n content=\\"You are a helpful assistant! Your name is Bob.\\"\\n ),\\n HumanMessage(\\n content=\\"What is your name?\\"\\n )\\n ]\\n\\n # Instantiate a chat model and invoke it with the messages\\n model = ...\\n print(model.invoke(messages))", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"additionalProperties": true, "type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"additionalProperties": true, "title": "Additional Kwargs", "type": "object"}, "response_metadata": {"additionalProperties": true, "title": "Response Metadata", "type": "object"}, "type": {"const": "human", "default": "human", "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "example": {"default": false, "title": "Example", "type": "boolean"}}, "required": ["content"], "title": "HumanMessage", "type": "object"}, "HumanMessageChunk": {"additionalProperties": true, "description": "Human Message chunk.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"additionalProperties": true, "type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"additionalProperties": true, "title": "Additional Kwargs", "type": "object"}, "response_metadata": {"additionalProperties": true, "title": "Response Metadata", "type": "object"}, "type": {"const": "HumanMessageChunk", "default": "HumanMessageChunk", "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "example": {"default": false, "title": "Example", "type": "boolean"}}, "required": ["content"], "title": "HumanMessageChunk", "type": "object"}, "InputTokenDetails": {"description": "Breakdown of input token counts.\\n\\nDoes *not* need to sum to full input token count. Does *not* need to have all keys.\\n\\nExample:\\n\\n .. code-block:: python\\n\\n {\\n \\"audio\\": 10,\\n \\"cache_creation\\": 200,\\n \\"cache_read\\": 100,\\n }\\n\\n.. versionadded:: 0.3.9\\n\\nMay also hold extra provider-specific keys.", "properties": {"audio": {"title": "Audio", "type": "integer"}, "cache_creation": {"title": "Cache Creation", "type": "integer"}, "cache_read": {"title": "Cache Read", "type": "integer"}}, "title": "InputTokenDetails", "type": "object"}, "InvalidToolCall": {"description": "Allowance for errors made by LLM.\\n\\nHere we add an `error` key to surface errors made during generation\\n(e.g., invalid JSON arguments.)", "properties": {"name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "args": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Args"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Id"}, "error": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Error"}, "type": {"const": "invalid_tool_call", "title": "Type", "type": "string"}}, "required": ["name", "args", "id", "error"], "title": "InvalidToolCall", "type": "object"}, "OutputTokenDetails": {"description": "Breakdown of output token counts.\\n\\nDoes *not* need to sum to full output token count. Does *not* need to have all keys.\\n\\nExample:\\n\\n .. code-block:: python\\n\\n {\\n \\"audio\\": 10,\\n \\"reasoning\\": 200,\\n }\\n\\n.. versionadded:: 0.3.9", "properties": {"audio": {"title": "Audio", "type": "integer"}, "reasoning": {"title": "Reasoning", "type": "integer"}}, "title": "OutputTokenDetails", "type": "object"}, "SystemMessage": {"additionalProperties": true, "description": "Message for priming AI behavior.\\n\\nThe system message is usually passed in as the first of a sequence\\nof input messages.\\n\\nExample:\\n\\n .. code-block:: python\\n\\n from langchain_core.messages import HumanMessage, SystemMessage\\n\\n messages = [\\n SystemMessage(\\n content=\\"You are a helpful assistant! Your name is Bob.\\"\\n ),\\n HumanMessage(\\n content=\\"What is your name?\\"\\n )\\n ]\\n\\n # Define a chat model and invoke it with the messages\\n print(model.invoke(messages))", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"additionalProperties": true, "type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"additionalProperties": true, "title": "Additional Kwargs", "type": "object"}, "response_metadata": {"additionalProperties": true, "title": "Response Metadata", "type": "object"}, "type": {"const": "system", "default": "system", "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}}, "required": ["content"], "title": "SystemMessage", "type": "object"}, "SystemMessageChunk": {"additionalProperties": true, "description": "System Message chunk.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"additionalProperties": true, "type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"additionalProperties": true, "title": "Additional Kwargs", "type": "object"}, "response_metadata": {"additionalProperties": true, "title": "Response Metadata", "type": "object"}, "type": {"const": "SystemMessageChunk", "default": "SystemMessageChunk", "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}}, "required": ["content"], "title": "SystemMessageChunk", "type": "object"}, "ToolCall": {"description": "Represents a request to call a tool.\\n\\nExample:\\n\\n .. code-block:: python\\n\\n {\\n \\"name\\": \\"foo\\",\\n \\"args\\": {\\"a\\": 1},\\n \\"id\\": \\"123\\"\\n }\\n\\n This represents a request to call the tool named \\"foo\\" with arguments {\\"a\\": 1}\\n and an identifier of \\"123\\".", "properties": {"name": {"title": "Name", "type": "string"}, "args": {"additionalProperties": true, "title": "Args", "type": "object"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Id"}, "type": {"const": "tool_call", "title": "Type", "type": "string"}}, "required": ["name", "args", "id"], "title": "ToolCall", "type": "object"}, "ToolCallChunk": {"description": "A chunk of a tool call (e.g., as part of a stream).\\n\\nWhen merging ToolCallChunks (e.g., via AIMessageChunk.__add__),\\nall string attributes are concatenated. Chunks are only merged if their\\nvalues of `index` are equal and not None.\\n\\nExample:\\n\\n.. code-block:: python\\n\\n left_chunks = [ToolCallChunk(name=\\"foo\\", args=\'{\\"a\\":\', index=0)]\\n right_chunks = [ToolCallChunk(name=None, args=\'1}\', index=0)]\\n\\n (\\n AIMessageChunk(content=\\"\\", tool_call_chunks=left_chunks)\\n + AIMessageChunk(content=\\"\\", tool_call_chunks=right_chunks)\\n ).tool_call_chunks == [ToolCallChunk(name=\'foo\', args=\'{\\"a\\":1}\', index=0)]", "properties": {"name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "args": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Args"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Id"}, "index": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Index"}, "type": {"const": "tool_call_chunk", "title": "Type", "type": "string"}}, "required": ["name", "args", "id", "index"], "title": "ToolCallChunk", "type": "object"}, "ToolMessage": {"additionalProperties": true, "description": "Message for passing the result of executing a tool back to a model.\\n\\nToolMessages contain the result of a tool invocation. Typically, the result\\nis encoded inside the `content` field.\\n\\nExample: A ToolMessage representing a result of 42 from a tool call with id\\n\\n .. code-block:: python\\n\\n from langchain_core.messages import ToolMessage\\n\\n ToolMessage(content=\'42\', tool_call_id=\'call_Jja7J89XsjrOLA5r!MEOW!SL\')\\n\\n\\nExample: A ToolMessage where only part of the tool output is sent to the model\\n and the full output is passed in to artifact.\\n\\n .. versionadded:: 0.2.17\\n\\n .. code-block:: python\\n\\n from langchain_core.messages import ToolMessage\\n\\n tool_output = {\\n \\"stdout\\": \\"From the graph we can see that the correlation between x and y is ...\\",\\n \\"stderr\\": None,\\n \\"artifacts\\": {\\"type\\": \\"image\\", \\"base64_data\\": \\"/9j/4gIcSU...\\"},\\n }\\n\\n ToolMessage(\\n content=tool_output[\\"stdout\\"],\\n artifact=tool_output,\\n tool_call_id=\'call_Jja7J89XsjrOLA5r!MEOW!SL\',\\n )\\n\\nThe tool_call_id field is used to associate the tool call request with the\\ntool call response. This is useful in situations where a chat model is able\\nto request multiple tool calls in parallel.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"additionalProperties": true, "type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"additionalProperties": true, "title": "Additional Kwargs", "type": "object"}, "response_metadata": {"additionalProperties": true, "title": "Response Metadata", "type": "object"}, "type": {"const": "tool", "default": "tool", "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "tool_call_id": {"title": "Tool Call Id", "type": "string"}, "artifact": {"default": null, "title": "Artifact"}, "status": {"default": "success", "enum": ["success", "error"], "title": "Status", "type": "string"}}, "required": ["content", "tool_call_id"], "title": "ToolMessage", "type": "object"}, "ToolMessageChunk": {"additionalProperties": true, "description": "Tool Message chunk.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"additionalProperties": true, "type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"additionalProperties": true, "title": "Additional Kwargs", "type": "object"}, "response_metadata": {"additionalProperties": true, "title": "Response Metadata", "type": "object"}, "type": {"const": "ToolMessageChunk", "default": "ToolMessageChunk", "title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}, "tool_call_id": {"title": "Tool Call Id", "type": "string"}, "artifact": {"default": null, "title": "Artifact"}, "status": {"default": "success", "enum": ["success", "error"], "title": "Status", "type": "string"}}, "required": ["content", "tool_call_id"], "title": "ToolMessageChunk", "type": "object"}, "UsageMetadata": {"description": "Usage metadata for a message, such as token counts.\\n\\nThis is a standard representation of token usage that is consistent across models.\\n\\nExample:\\n\\n .. code-block:: python\\n\\n {\\n \\"input_tokens\\": 350,\\n \\"output_tokens\\": 240,\\n \\"total_tokens\\": 590,\\n \\"input_token_details\\": {\\n \\"audio\\": 10,\\n \\"cache_creation\\": 200,\\n \\"cache_read\\": 100,\\n },\\n \\"output_token_details\\": {\\n \\"audio\\": 10,\\n \\"reasoning\\": 200,\\n }\\n }\\n\\n.. versionchanged:: 0.3.9\\n\\n Added ``input_token_details`` and ``output_token_details``.", "properties": {"input_tokens": {"title": "Input Tokens", "type": "integer"}, "output_tokens": {"title": "Output Tokens", "type": "integer"}, "total_tokens": {"title": "Total Tokens", "type": "integer"}, "input_token_details": {"$ref": "#/$defs/InputTokenDetails"}, "output_token_details": {"$ref": "#/$defs/OutputTokenDetails"}}, "required": ["input_tokens", "output_tokens", "total_tokens"], "title": "UsageMetadata", "type": "object"}}, "default": null, "items": {"oneOf": [{"$ref": "#/$defs/AIMessage"}, {"$ref": "#/$defs/HumanMessage"}, {"$ref": "#/$defs/ChatMessage"}, {"$ref": "#/$defs/SystemMessage"}, {"$ref": "#/$defs/FunctionMessage"}, {"$ref": "#/$defs/ToolMessage"}, {"$ref": "#/$defs/AIMessageChunk"}, {"$ref": "#/$defs/HumanMessageChunk"}, {"$ref": "#/$defs/ChatMessageChunk"}, {"$ref": "#/$defs/SystemMessageChunk"}, {"$ref": "#/$defs/FunctionMessageChunk"}, {"$ref": "#/$defs/ToolMessageChunk"}]}, "title": "LangGraphOutput", "type": "array"}' # --- # name: test_message_graph[memory].2 ''' @@ -276,10 +276,10 @@ ''' # --- # name: test_prebuilt_tool_chat - '{"$defs": {"BaseMessage": {"additionalProperties": true, "description": "Base abstract message class.\\n\\nMessages are the inputs and outputs of ChatModels.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"title": "Additional Kwargs", "type": "object"}, "response_metadata": {"title": "Response Metadata", "type": "object"}, "type": {"title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}}, "required": ["content", "type"], "title": "BaseMessage", "type": "object"}}, "properties": {"messages": {"items": {"$ref": "#/$defs/BaseMessage"}, "title": "Messages", "type": "array"}}, "required": ["messages"], "title": "LangGraphInput", "type": "object"}' + '{"$defs": {"BaseMessage": {"additionalProperties": true, "description": "Base abstract message class.\\n\\nMessages are the inputs and outputs of ChatModels.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"additionalProperties": true, "type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"additionalProperties": true, "title": "Additional Kwargs", "type": "object"}, "response_metadata": {"additionalProperties": true, "title": "Response Metadata", "type": "object"}, "type": {"title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}}, "required": ["content", "type"], "title": "BaseMessage", "type": "object"}}, "description": "The state of the agent.", "properties": {"messages": {"items": {"$ref": "#/$defs/BaseMessage"}, "title": "Messages", "type": "array"}, "is_last_step": {"title": "Is Last Step", "type": "boolean"}, "remaining_steps": {"title": "Remaining Steps", "type": "integer"}}, "required": ["messages", "is_last_step", "remaining_steps"], "title": "AgentState", "type": "object"}' # --- # name: test_prebuilt_tool_chat.1 - '{"$defs": {"BaseMessage": {"additionalProperties": true, "description": "Base abstract message class.\\n\\nMessages are the inputs and outputs of ChatModels.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"title": "Additional Kwargs", "type": "object"}, "response_metadata": {"title": "Response Metadata", "type": "object"}, "type": {"title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}}, "required": ["content", "type"], "title": "BaseMessage", "type": "object"}}, "properties": {"messages": {"items": {"$ref": "#/$defs/BaseMessage"}, "title": "Messages", "type": "array"}}, "required": ["messages"], "title": "LangGraphOutput", "type": "object"}' + '{"$defs": {"BaseMessage": {"additionalProperties": true, "description": "Base abstract message class.\\n\\nMessages are the inputs and outputs of ChatModels.", "properties": {"content": {"anyOf": [{"type": "string"}, {"items": {"anyOf": [{"type": "string"}, {"additionalProperties": true, "type": "object"}]}, "type": "array"}], "title": "Content"}, "additional_kwargs": {"additionalProperties": true, "title": "Additional Kwargs", "type": "object"}, "response_metadata": {"additionalProperties": true, "title": "Response Metadata", "type": "object"}, "type": {"title": "Type", "type": "string"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Name"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Id"}}, "required": ["content", "type"], "title": "BaseMessage", "type": "object"}}, "description": "The state of the agent.", "properties": {"messages": {"items": {"$ref": "#/$defs/BaseMessage"}, "title": "Messages", "type": "array"}, "is_last_step": {"title": "Is Last Step", "type": "boolean"}, "remaining_steps": {"title": "Remaining Steps", "type": "integer"}}, "required": ["messages", "is_last_step", "remaining_steps"], "title": "AgentState", "type": "object"}' # --- # name: test_prebuilt_tool_chat.2 ''' diff --git a/libs/langgraph/tests/__snapshots__/test_pregel.ambr b/libs/langgraph/tests/__snapshots__/test_pregel.ambr index a47c52178..0c7ffba54 100644 --- a/libs/langgraph/tests/__snapshots__/test_pregel.ambr +++ b/libs/langgraph/tests/__snapshots__/test_pregel.ambr @@ -89,10 +89,10 @@ ''' # --- # name: test_conditional_entrypoint_graph_state - '{"properties": {"input": {"default": null, "title": "Input", "type": "string"}, "output": {"default": null, "title": "Output", "type": "string"}, "steps": {"default": null, "items": {"type": "string"}, "title": "Steps", "type": "array"}}, "title": "LangGraphInput", "type": "object"}' + '{"properties": {"input": {"title": "Input", "type": "string"}, "output": {"title": "Output", "type": "string"}, "steps": {"items": {"type": "string"}, "title": "Steps", "type": "array"}}, "title": "AgentState", "type": "object"}' # --- # name: test_conditional_entrypoint_graph_state.1 - '{"properties": {"input": {"default": null, "title": "Input", "type": "string"}, "output": {"default": null, "title": "Output", "type": "string"}, "steps": {"default": null, "items": {"type": "string"}, "title": "Steps", "type": "array"}}, "title": "LangGraphOutput", "type": "object"}' + '{"properties": {"input": {"title": "Input", "type": "string"}, "output": {"title": "Output", "type": "string"}, "steps": {"items": {"type": "string"}, "title": "Steps", "type": "array"}}, "title": "AgentState", "type": "object"}' # --- # name: test_conditional_entrypoint_graph_state.2 ''' @@ -178,10 +178,10 @@ ''' # --- # name: test_conditional_entrypoint_to_multiple_state_graph - '{"properties": {"locations": {"items": {"type": "string"}, "title": "Locations", "type": "array"}, "results": {"items": {"type": "string"}, "title": "Results", "type": "array"}}, "required": ["locations", "results"], "title": "LangGraphInput", "type": "object"}' + '{"properties": {"locations": {"items": {"type": "string"}, "title": "Locations", "type": "array"}, "results": {"items": {"type": "string"}, "title": "Results", "type": "array"}}, "required": ["locations", "results"], "title": "OverallState", "type": "object"}' # --- # name: test_conditional_entrypoint_to_multiple_state_graph.1 - '{"properties": {"locations": {"items": {"type": "string"}, "title": "Locations", "type": "array"}, "results": {"items": {"type": "string"}, "title": "Results", "type": "array"}}, "required": ["locations", "results"], "title": "LangGraphOutput", "type": "object"}' + '{"properties": {"locations": {"items": {"type": "string"}, "title": "Locations", "type": "array"}, "results": {"items": {"type": "string"}, "title": "Results", "type": "array"}}, "required": ["locations", "results"], "title": "OverallState", "type": "object"}' # --- # name: test_conditional_entrypoint_to_multiple_state_graph.2 ''' @@ -917,10 +917,10 @@ '{"$defs": {"Config": {"properties": {"tools": {"items": {"type": "string"}, "title": "Tools", "type": "array"}}, "title": "Config", "type": "object"}}, "properties": {"configurable": {"$ref": "#/$defs/Config", "default": null}}, "title": "LangGraphConfig", "type": "object"}' # --- # name: test_state_graph_w_config_inherited_state_keys.1 - '{"$defs": {"AgentAction": {"description": "Represents a request to execute an action by an agent.\\n\\nThe action consists of the name of the tool to execute and the input to pass\\nto the tool. The log is used to pass along extra information about the action.", "properties": {"tool": {"title": "Tool", "type": "string"}, "tool_input": {"anyOf": [{"type": "string"}, {"type": "object"}], "title": "Tool Input"}, "log": {"title": "Log", "type": "string"}, "type": {"const": "AgentAction", "default": "AgentAction", "enum": ["AgentAction"], "title": "Type", "type": "string"}}, "required": ["tool", "tool_input", "log"], "title": "AgentAction", "type": "object"}, "AgentFinish": {"description": "Final return value of an ActionAgent.\\n\\nAgents return an AgentFinish when they have reached a stopping condition.", "properties": {"return_values": {"title": "Return Values", "type": "object"}, "log": {"title": "Log", "type": "string"}, "type": {"const": "AgentFinish", "default": "AgentFinish", "enum": ["AgentFinish"], "title": "Type", "type": "string"}}, "required": ["return_values", "log"], "title": "AgentFinish", "type": "object"}}, "properties": {"input": {"title": "Input", "type": "string"}, "agent_outcome": {"anyOf": [{"$ref": "#/$defs/AgentAction"}, {"$ref": "#/$defs/AgentFinish"}, {"type": "null"}], "default": null, "title": "Agent Outcome"}, "intermediate_steps": {"default": null, "items": {"maxItems": 2, "minItems": 2, "prefixItems": [{"$ref": "#/$defs/AgentAction"}, {"type": "string"}], "type": "array"}, "title": "Intermediate Steps", "type": "array"}}, "required": ["input"], "title": "LangGraphInput", "type": "object"}' + '{"$defs": {"AgentAction": {"description": "Represents a request to execute an action by an agent.\\n\\nThe action consists of the name of the tool to execute and the input to pass\\nto the tool. The log is used to pass along extra information about the action.", "properties": {"tool": {"title": "Tool", "type": "string"}, "tool_input": {"anyOf": [{"type": "string"}, {"additionalProperties": true, "type": "object"}], "title": "Tool Input"}, "log": {"title": "Log", "type": "string"}, "type": {"const": "AgentAction", "default": "AgentAction", "title": "Type", "type": "string"}}, "required": ["tool", "tool_input", "log"], "title": "AgentAction", "type": "object"}, "AgentFinish": {"description": "Final return value of an ActionAgent.\\n\\nAgents return an AgentFinish when they have reached a stopping condition.", "properties": {"return_values": {"additionalProperties": true, "title": "Return Values", "type": "object"}, "log": {"title": "Log", "type": "string"}, "type": {"const": "AgentFinish", "default": "AgentFinish", "title": "Type", "type": "string"}}, "required": ["return_values", "log"], "title": "AgentFinish", "type": "object"}}, "properties": {"input": {"title": "Input", "type": "string"}, "agent_outcome": {"anyOf": [{"$ref": "#/$defs/AgentAction"}, {"$ref": "#/$defs/AgentFinish"}, {"type": "null"}], "title": "Agent Outcome"}, "intermediate_steps": {"items": {"maxItems": 2, "minItems": 2, "prefixItems": [{"$ref": "#/$defs/AgentAction"}, {"type": "string"}], "type": "array"}, "title": "Intermediate Steps", "type": "array"}}, "required": ["input", "agent_outcome"], "title": "AgentState", "type": "object"}' # --- # name: test_state_graph_w_config_inherited_state_keys.2 - '{"$defs": {"AgentAction": {"description": "Represents a request to execute an action by an agent.\\n\\nThe action consists of the name of the tool to execute and the input to pass\\nto the tool. The log is used to pass along extra information about the action.", "properties": {"tool": {"title": "Tool", "type": "string"}, "tool_input": {"anyOf": [{"type": "string"}, {"type": "object"}], "title": "Tool Input"}, "log": {"title": "Log", "type": "string"}, "type": {"const": "AgentAction", "default": "AgentAction", "enum": ["AgentAction"], "title": "Type", "type": "string"}}, "required": ["tool", "tool_input", "log"], "title": "AgentAction", "type": "object"}, "AgentFinish": {"description": "Final return value of an ActionAgent.\\n\\nAgents return an AgentFinish when they have reached a stopping condition.", "properties": {"return_values": {"title": "Return Values", "type": "object"}, "log": {"title": "Log", "type": "string"}, "type": {"const": "AgentFinish", "default": "AgentFinish", "enum": ["AgentFinish"], "title": "Type", "type": "string"}}, "required": ["return_values", "log"], "title": "AgentFinish", "type": "object"}}, "properties": {"input": {"title": "Input", "type": "string"}, "agent_outcome": {"anyOf": [{"$ref": "#/$defs/AgentAction"}, {"$ref": "#/$defs/AgentFinish"}, {"type": "null"}], "default": null, "title": "Agent Outcome"}, "intermediate_steps": {"default": null, "items": {"maxItems": 2, "minItems": 2, "prefixItems": [{"$ref": "#/$defs/AgentAction"}, {"type": "string"}], "type": "array"}, "title": "Intermediate Steps", "type": "array"}}, "required": ["input"], "title": "LangGraphOutput", "type": "object"}' + '{"$defs": {"AgentAction": {"description": "Represents a request to execute an action by an agent.\\n\\nThe action consists of the name of the tool to execute and the input to pass\\nto the tool. The log is used to pass along extra information about the action.", "properties": {"tool": {"title": "Tool", "type": "string"}, "tool_input": {"anyOf": [{"type": "string"}, {"additionalProperties": true, "type": "object"}], "title": "Tool Input"}, "log": {"title": "Log", "type": "string"}, "type": {"const": "AgentAction", "default": "AgentAction", "title": "Type", "type": "string"}}, "required": ["tool", "tool_input", "log"], "title": "AgentAction", "type": "object"}, "AgentFinish": {"description": "Final return value of an ActionAgent.\\n\\nAgents return an AgentFinish when they have reached a stopping condition.", "properties": {"return_values": {"additionalProperties": true, "title": "Return Values", "type": "object"}, "log": {"title": "Log", "type": "string"}, "type": {"const": "AgentFinish", "default": "AgentFinish", "title": "Type", "type": "string"}}, "required": ["return_values", "log"], "title": "AgentFinish", "type": "object"}}, "properties": {"input": {"title": "Input", "type": "string"}, "agent_outcome": {"anyOf": [{"$ref": "#/$defs/AgentAction"}, {"$ref": "#/$defs/AgentFinish"}, {"type": "null"}], "title": "Agent Outcome"}, "intermediate_steps": {"items": {"maxItems": 2, "minItems": 2, "prefixItems": [{"$ref": "#/$defs/AgentAction"}, {"type": "string"}], "type": "array"}, "title": "Intermediate Steps", "type": "array"}}, "required": ["input", "agent_outcome"], "title": "AgentState", "type": "object"}' # --- # name: test_xray_bool ''' diff --git a/libs/langgraph/tests/test_large_cases.py b/libs/langgraph/tests/test_large_cases.py index e3108c105..81de033ba 100644 --- a/libs/langgraph/tests/test_large_cases.py +++ b/libs/langgraph/tests/test_large_cases.py @@ -569,8 +569,8 @@ def test_conditional_state_graph( app = workflow.compile() if isinstance(sync_checkpointer, InMemorySaver): - assert json.dumps(app.get_input_schema().model_json_schema()) == snapshot - assert json.dumps(app.get_output_schema().model_json_schema()) == snapshot + assert json.dumps(app.get_input_jsonschema()) == snapshot + assert json.dumps(app.get_output_jsonschema()) == snapshot assert json.dumps(app.get_graph().to_json(), indent=2) == snapshot assert app.get_graph().draw_mermaid(with_styles=False) == snapshot @@ -1302,8 +1302,8 @@ def test_prebuilt_tool_chat(snapshot: SnapshotAssertion) -> None: app = create_react_agent(model, tools) - assert json.dumps(app.get_input_schema().model_json_schema()) == snapshot - assert json.dumps(app.get_output_schema().model_json_schema()) == snapshot + assert json.dumps(app.get_input_jsonschema()) == snapshot + assert json.dumps(app.get_output_jsonschema()) == snapshot assert json.dumps(app.get_graph().to_json(), indent=2) == snapshot assert app.get_graph().draw_mermaid(with_styles=False) == snapshot @@ -2483,8 +2483,8 @@ def test_message_graph( app = workflow.compile() if isinstance(sync_checkpointer, InMemorySaver): - assert json.dumps(app.get_input_schema().model_json_schema()) == snapshot - assert json.dumps(app.get_output_schema().model_json_schema()) == snapshot + assert json.dumps(app.get_input_jsonschema()) == snapshot + assert json.dumps(app.get_output_jsonschema()) == snapshot assert json.dumps(app.get_graph().to_json(), indent=2) == snapshot assert app.get_graph().draw_mermaid(with_styles=False) == snapshot diff --git a/libs/langgraph/tests/test_pregel.py b/libs/langgraph/tests/test_pregel.py index dc732da91..9df854e0e 100644 --- a/libs/langgraph/tests/test_pregel.py +++ b/libs/langgraph/tests/test_pregel.py @@ -1723,8 +1723,8 @@ def test_conditional_entrypoint_to_multiple_state_graph( app = workflow.compile() - assert json.dumps(app.get_input_schema().model_json_schema()) == snapshot - assert json.dumps(app.get_output_schema().model_json_schema()) == snapshot + assert json.dumps(app.get_input_jsonschema()) == snapshot + assert json.dumps(app.get_output_jsonschema()) == snapshot assert json.dumps(app.get_graph().to_json(), indent=2) == snapshot assert app.get_graph().draw_mermaid(with_styles=False) == snapshot @@ -1848,8 +1848,8 @@ def test_state_graph_w_config_inherited_state_keys(snapshot: SnapshotAssertion) app = builder.compile() assert json.dumps(app.config_schema().model_json_schema()) == snapshot - assert json.dumps(app.get_input_schema().model_json_schema()) == snapshot - assert json.dumps(app.get_output_schema().model_json_schema()) == snapshot + assert json.dumps(app.get_input_jsonschema()) == snapshot + assert json.dumps(app.get_output_jsonschema()) == snapshot assert builder.channels.keys() == {"input", "agent_outcome", "intermediate_steps"} @@ -1912,8 +1912,8 @@ def test_conditional_entrypoint_graph_state(snapshot: SnapshotAssertion) -> None app = workflow.compile() - assert json.dumps(app.get_input_schema().model_json_schema()) == snapshot - assert json.dumps(app.get_output_schema().model_json_schema()) == snapshot + assert json.dumps(app.get_input_jsonschema()) == snapshot + assert json.dumps(app.get_output_jsonschema()) == snapshot assert json.dumps(app.get_graph().to_json(), indent=2) == snapshot assert app.get_graph().draw_mermaid(with_styles=False) == snapshot @@ -2507,8 +2507,8 @@ def test_in_one_fan_out_state_graph_waiting_edge_custom_state_class_pydantic2( if isinstance(sync_checkpointer, InMemorySaver): assert app.get_graph().draw_mermaid(with_styles=False) == snapshot - assert app.get_input_schema().model_json_schema() == snapshot - assert app.get_output_schema().model_json_schema() == snapshot + assert app.get_input_jsonschema() == snapshot + assert app.get_output_jsonschema() == snapshot with pytest.raises(ValidationError): app.invoke({"query": {}}) @@ -6549,7 +6549,7 @@ def test_entrypoint_output_schema_with_return_and_save() -> None: def foo2(inputs, *, previous: Any) -> entrypoint.final: return entrypoint.final(value="foo", save=1) - assert foo2.get_output_schema().model_json_schema() == { + assert foo2.get_output_jsonschema() == { "title": "LangGraphOutput", } @@ -6557,7 +6557,7 @@ def test_entrypoint_output_schema_with_return_and_save() -> None: def foo(inputs, *, previous: Any) -> entrypoint.final[str, int]: return entrypoint.final(value="foo", save=1) - assert foo.get_output_schema().model_json_schema() == { + assert foo.get_output_jsonschema() == { "title": "LangGraphOutput", "type": "string", } @@ -6584,7 +6584,7 @@ def test_entrypoint_with_return_and_save( previous = previous or [] return entrypoint.final(value=len(previous), save=previous + [msg]) - assert foo.get_output_schema().model_json_schema() == { + assert foo.get_output_jsonschema() == { "title": "LangGraphOutput", "type": "integer", } diff --git a/libs/langgraph/tests/test_pregel_async.py b/libs/langgraph/tests/test_pregel_async.py index 61d1ab5d7..76d650ce4 100644 --- a/libs/langgraph/tests/test_pregel_async.py +++ b/libs/langgraph/tests/test_pregel_async.py @@ -4493,8 +4493,8 @@ async def test_in_one_fan_out_state_graph_waiting_edge_custom_state_class_pydant if isinstance(async_checkpointer, InMemorySaver): assert app.get_graph().draw_mermaid(with_styles=False) == snapshot - assert app.get_input_schema().model_json_schema() == snapshot - assert app.get_output_schema().model_json_schema() == snapshot + assert app.get_input_jsonschema() == snapshot + assert app.get_output_jsonschema() == snapshot with pytest.raises(ValidationError): await app.ainvoke({"query": {}}) diff --git a/libs/langgraph/tests/test_state.py b/libs/langgraph/tests/test_state.py index 0ad70140d..82a3997de 100644 --- a/libs/langgraph/tests/test_state.py +++ b/libs/langgraph/tests/test_state.py @@ -163,13 +163,12 @@ def test_state_schema_optional_values(total_: bool): expected_required = set() expected_optional = {"val2", "val1"} else: - expected_required = {"val1"} - - expected_optional = {"val2"} + expected_required = {"val1", "val2"} + expected_optional = set() # The others should always have precedence based on the required annotation - expected_required |= {"val0a", "val3", "val5"} - expected_optional |= {"val0b", "val4", "val6"} + expected_required |= {"val0a", "val0b", "val3", "val5"} + expected_optional |= {"val4", "val6"} assert set(json_schema.get("required", set())) == expected_required assert ( @@ -182,11 +181,11 @@ def test_state_schema_optional_values(total_: bool): expected_required = set() expected_optional = {"out_val2", "out_val1"} else: - expected_required = {"out_val1"} - expected_optional = {"out_val2"} + expected_required = {"out_val1", "out_val2"} + expected_optional = set() - expected_required |= {"val0a", "out_val3", "out_val5"} - expected_optional |= {"val0b", "out_val4", "out_val6"} + expected_required |= {"val0a", "val0b", "out_val3", "out_val5"} + expected_optional |= {"out_val4", "out_val6"} assert set(output_schema.get("required", set())) == expected_required assert ( diff --git a/libs/langgraph/uv.lock b/libs/langgraph/uv.lock index db2d48375..7f9382daa 100644 --- a/libs/langgraph/uv.lock +++ b/libs/langgraph/uv.lock @@ -2166,103 +2166,126 @@ wheels = [ [[package]] name = "pydantic" -version = "2.9.2" +version = "2.11.7" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-types" }, { name = "pydantic-core" }, { name = "typing-extensions" }, + { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a9/b7/d9e3f12af310e1120c21603644a1cd86f59060e040ec5c3a80b8f05fae30/pydantic-2.9.2.tar.gz", hash = "sha256:d155cef71265d1e9807ed1c32b4c8deec042a44a50a4188b25ac67ecd81a9c0f", size = 769917, upload-time = "2024-09-17T15:59:54.273Z" } +sdist = { url = "https://files.pythonhosted.org/packages/00/dd/4325abf92c39ba8623b5af936ddb36ffcfe0beae70405d456ab1fb2f5b8c/pydantic-2.11.7.tar.gz", hash = "sha256:d989c3c6cb79469287b1569f7447a17848c998458d49ebe294e975b9baf0f0db", size = 788350, upload-time = "2025-06-14T08:33:17.137Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/df/e4/ba44652d562cbf0bf320e0f3810206149c8a4e99cdbf66da82e97ab53a15/pydantic-2.9.2-py3-none-any.whl", hash = "sha256:f048cec7b26778210e28a0459867920654d48e5e62db0958433636cde4254f12", size = 434928, upload-time = "2024-09-17T15:59:51.827Z" }, + { url = "https://files.pythonhosted.org/packages/6a/c0/ec2b1c8712ca690e5d61979dee872603e92b8a32f94cc1b72d53beab008a/pydantic-2.11.7-py3-none-any.whl", hash = "sha256:dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b", size = 444782, upload-time = "2025-06-14T08:33:14.905Z" }, ] [[package]] name = "pydantic-core" -version = "2.23.4" +version = "2.33.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e2/aa/6b6a9b9f8537b872f552ddd46dd3da230367754b6f707b8e1e963f515ea3/pydantic_core-2.23.4.tar.gz", hash = "sha256:2584f7cf844ac4d970fba483a717dbe10c1c1c96a969bf65d61ffe94df1b2863", size = 402156, upload-time = "2024-09-16T16:06:44.786Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ad/88/5f2260bdfae97aabf98f1778d43f69574390ad787afb646292a638c923d4/pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc", size = 435195, upload-time = "2025-04-23T18:33:52.104Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5c/8b/d3ae387f66277bd8104096d6ec0a145f4baa2966ebb2cad746c0920c9526/pydantic_core-2.23.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:b10bd51f823d891193d4717448fab065733958bdb6a6b351967bd349d48d5c9b", size = 1867835, upload-time = "2024-09-16T16:03:57.223Z" }, - { url = "https://files.pythonhosted.org/packages/46/76/f68272e4c3a7df8777798282c5e47d508274917f29992d84e1898f8908c7/pydantic_core-2.23.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4fc714bdbfb534f94034efaa6eadd74e5b93c8fa6315565a222f7b6f42ca1166", size = 1776689, upload-time = "2024-09-16T16:03:59.266Z" }, - { url = "https://files.pythonhosted.org/packages/cc/69/5f945b4416f42ea3f3bc9d2aaec66c76084a6ff4ff27555bf9415ab43189/pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63e46b3169866bd62849936de036f901a9356e36376079b05efa83caeaa02ceb", size = 1800748, upload-time = "2024-09-16T16:04:01.011Z" }, - { url = "https://files.pythonhosted.org/packages/50/ab/891a7b0054bcc297fb02d44d05c50e68154e31788f2d9d41d0b72c89fdf7/pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed1a53de42fbe34853ba90513cea21673481cd81ed1be739f7f2efb931b24916", size = 1806469, upload-time = "2024-09-16T16:04:02.323Z" }, - { url = "https://files.pythonhosted.org/packages/31/7c/6e3fa122075d78f277a8431c4c608f061881b76c2b7faca01d317ee39b5d/pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cfdd16ab5e59fc31b5e906d1a3f666571abc367598e3e02c83403acabc092e07", size = 2002246, upload-time = "2024-09-16T16:04:03.688Z" }, - { url = "https://files.pythonhosted.org/packages/ad/6f/22d5692b7ab63fc4acbc74de6ff61d185804a83160adba5e6cc6068e1128/pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:255a8ef062cbf6674450e668482456abac99a5583bbafb73f9ad469540a3a232", size = 2659404, upload-time = "2024-09-16T16:04:05.299Z" }, - { url = "https://files.pythonhosted.org/packages/11/ac/1e647dc1121c028b691028fa61a4e7477e6aeb5132628fde41dd34c1671f/pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a7cd62e831afe623fbb7aabbb4fe583212115b3ef38a9f6b71869ba644624a2", size = 2053940, upload-time = "2024-09-16T16:04:06.604Z" }, - { url = "https://files.pythonhosted.org/packages/91/75/984740c17f12c3ce18b5a2fcc4bdceb785cce7df1511a4ce89bca17c7e2d/pydantic_core-2.23.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f09e2ff1f17c2b51f2bc76d1cc33da96298f0a036a137f5440ab3ec5360b624f", size = 1921437, upload-time = "2024-09-16T16:04:08.071Z" }, - { url = "https://files.pythonhosted.org/packages/a0/74/13c5f606b64d93f0721e7768cd3e8b2102164866c207b8cd6f90bb15d24f/pydantic_core-2.23.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e38e63e6f3d1cec5a27e0afe90a085af8b6806ee208b33030e65b6516353f1a3", size = 1966129, upload-time = "2024-09-16T16:04:10.363Z" }, - { url = "https://files.pythonhosted.org/packages/18/03/9c4aa5919457c7b57a016c1ab513b1a926ed9b2bb7915bf8e506bf65c34b/pydantic_core-2.23.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0dbd8dbed2085ed23b5c04afa29d8fd2771674223135dc9bc937f3c09284d071", size = 2110908, upload-time = "2024-09-16T16:04:12.412Z" }, - { url = "https://files.pythonhosted.org/packages/92/2c/053d33f029c5dc65e5cf44ff03ceeefb7cce908f8f3cca9265e7f9b540c8/pydantic_core-2.23.4-cp310-none-win32.whl", hash = "sha256:6531b7ca5f951d663c339002e91aaebda765ec7d61b7d1e3991051906ddde119", size = 1735278, upload-time = "2024-09-16T16:04:13.732Z" }, - { url = "https://files.pythonhosted.org/packages/de/81/7dfe464eca78d76d31dd661b04b5f2036ec72ea8848dd87ab7375e185c23/pydantic_core-2.23.4-cp310-none-win_amd64.whl", hash = "sha256:7c9129eb40958b3d4500fa2467e6a83356b3b61bfff1b414c7361d9220f9ae8f", size = 1917453, upload-time = "2024-09-16T16:04:15.996Z" }, - { url = "https://files.pythonhosted.org/packages/5d/30/890a583cd3f2be27ecf32b479d5d615710bb926d92da03e3f7838ff3e58b/pydantic_core-2.23.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:77733e3892bb0a7fa797826361ce8a9184d25c8dffaec60b7ffe928153680ba8", size = 1865160, upload-time = "2024-09-16T16:04:18.628Z" }, - { url = "https://files.pythonhosted.org/packages/1d/9a/b634442e1253bc6889c87afe8bb59447f106ee042140bd57680b3b113ec7/pydantic_core-2.23.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b84d168f6c48fabd1f2027a3d1bdfe62f92cade1fb273a5d68e621da0e44e6d", size = 1776777, upload-time = "2024-09-16T16:04:20.038Z" }, - { url = "https://files.pythonhosted.org/packages/75/9a/7816295124a6b08c24c96f9ce73085032d8bcbaf7e5a781cd41aa910c891/pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df49e7a0861a8c36d089c1ed57d308623d60416dab2647a4a17fe050ba85de0e", size = 1799244, upload-time = "2024-09-16T16:04:21.799Z" }, - { url = "https://files.pythonhosted.org/packages/a9/8f/89c1405176903e567c5f99ec53387449e62f1121894aa9fc2c4fdc51a59b/pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ff02b6d461a6de369f07ec15e465a88895f3223eb75073ffea56b84d9331f607", size = 1805307, upload-time = "2024-09-16T16:04:23.324Z" }, - { url = "https://files.pythonhosted.org/packages/d5/a5/1a194447d0da1ef492e3470680c66048fef56fc1f1a25cafbea4bc1d1c48/pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:996a38a83508c54c78a5f41456b0103c30508fed9abcad0a59b876d7398f25fd", size = 2000663, upload-time = "2024-09-16T16:04:25.203Z" }, - { url = "https://files.pythonhosted.org/packages/13/a5/1df8541651de4455e7d587cf556201b4f7997191e110bca3b589218745a5/pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d97683ddee4723ae8c95d1eddac7c192e8c552da0c73a925a89fa8649bf13eea", size = 2655941, upload-time = "2024-09-16T16:04:27.211Z" }, - { url = "https://files.pythonhosted.org/packages/44/31/a3899b5ce02c4316865e390107f145089876dff7e1dfc770a231d836aed8/pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:216f9b2d7713eb98cb83c80b9c794de1f6b7e3145eef40400c62e86cee5f4e1e", size = 2052105, upload-time = "2024-09-16T16:04:28.611Z" }, - { url = "https://files.pythonhosted.org/packages/1b/aa/98e190f8745d5ec831f6d5449344c48c0627ac5fed4e5340a44b74878f8e/pydantic_core-2.23.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6f783e0ec4803c787bcea93e13e9932edab72068f68ecffdf86a99fd5918878b", size = 1919967, upload-time = "2024-09-16T16:04:30.045Z" }, - { url = "https://files.pythonhosted.org/packages/ae/35/b6e00b6abb2acfee3e8f85558c02a0822e9a8b2f2d812ea8b9079b118ba0/pydantic_core-2.23.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d0776dea117cf5272382634bd2a5c1b6eb16767c223c6a5317cd3e2a757c61a0", size = 1964291, upload-time = "2024-09-16T16:04:32.376Z" }, - { url = "https://files.pythonhosted.org/packages/13/46/7bee6d32b69191cd649bbbd2361af79c472d72cb29bb2024f0b6e350ba06/pydantic_core-2.23.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d5f7a395a8cf1621939692dba2a6b6a830efa6b3cee787d82c7de1ad2930de64", size = 2109666, upload-time = "2024-09-16T16:04:33.923Z" }, - { url = "https://files.pythonhosted.org/packages/39/ef/7b34f1b122a81b68ed0a7d0e564da9ccdc9a2924c8d6c6b5b11fa3a56970/pydantic_core-2.23.4-cp311-none-win32.whl", hash = "sha256:74b9127ffea03643e998e0c5ad9bd3811d3dac8c676e47db17b0ee7c3c3bf35f", size = 1732940, upload-time = "2024-09-16T16:04:35.467Z" }, - { url = "https://files.pythonhosted.org/packages/2f/76/37b7e76c645843ff46c1d73e046207311ef298d3f7b2f7d8f6ac60113071/pydantic_core-2.23.4-cp311-none-win_amd64.whl", hash = "sha256:98d134c954828488b153d88ba1f34e14259284f256180ce659e8d83e9c05eaa3", size = 1916804, upload-time = "2024-09-16T16:04:37.06Z" }, - { url = "https://files.pythonhosted.org/packages/74/7b/8e315f80666194b354966ec84b7d567da77ad927ed6323db4006cf915f3f/pydantic_core-2.23.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f3e0da4ebaef65158d4dfd7d3678aad692f7666877df0002b8a522cdf088f231", size = 1856459, upload-time = "2024-09-16T16:04:38.438Z" }, - { url = "https://files.pythonhosted.org/packages/14/de/866bdce10ed808323d437612aca1ec9971b981e1c52e5e42ad9b8e17a6f6/pydantic_core-2.23.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f69a8e0b033b747bb3e36a44e7732f0c99f7edd5cea723d45bc0d6e95377ffee", size = 1770007, upload-time = "2024-09-16T16:04:40.229Z" }, - { url = "https://files.pythonhosted.org/packages/dc/69/8edd5c3cd48bb833a3f7ef9b81d7666ccddd3c9a635225214e044b6e8281/pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:723314c1d51722ab28bfcd5240d858512ffd3116449c557a1336cbe3919beb87", size = 1790245, upload-time = "2024-09-16T16:04:41.794Z" }, - { url = "https://files.pythonhosted.org/packages/80/33/9c24334e3af796ce80d2274940aae38dd4e5676298b4398eff103a79e02d/pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb2802e667b7051a1bebbfe93684841cc9351004e2badbd6411bf357ab8d5ac8", size = 1801260, upload-time = "2024-09-16T16:04:43.991Z" }, - { url = "https://files.pythonhosted.org/packages/a5/6f/e9567fd90104b79b101ca9d120219644d3314962caa7948dd8b965e9f83e/pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d18ca8148bebe1b0a382a27a8ee60350091a6ddaf475fa05ef50dc35b5df6327", size = 1996872, upload-time = "2024-09-16T16:04:45.593Z" }, - { url = "https://files.pythonhosted.org/packages/2d/ad/b5f0fe9e6cfee915dd144edbd10b6e9c9c9c9d7a56b69256d124b8ac682e/pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33e3d65a85a2a4a0dc3b092b938a4062b1a05f3a9abde65ea93b233bca0e03f2", size = 2661617, upload-time = "2024-09-16T16:04:47.3Z" }, - { url = "https://files.pythonhosted.org/packages/06/c8/7d4b708f8d05a5cbfda3243aad468052c6e99de7d0937c9146c24d9f12e9/pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:128585782e5bfa515c590ccee4b727fb76925dd04a98864182b22e89a4e6ed36", size = 2071831, upload-time = "2024-09-16T16:04:48.893Z" }, - { url = "https://files.pythonhosted.org/packages/89/4d/3079d00c47f22c9a9a8220db088b309ad6e600a73d7a69473e3a8e5e3ea3/pydantic_core-2.23.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:68665f4c17edcceecc112dfed5dbe6f92261fb9d6054b47d01bf6371a6196126", size = 1917453, upload-time = "2024-09-16T16:04:51.099Z" }, - { url = "https://files.pythonhosted.org/packages/e9/88/9df5b7ce880a4703fcc2d76c8c2d8eb9f861f79d0c56f4b8f5f2607ccec8/pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:20152074317d9bed6b7a95ade3b7d6054845d70584216160860425f4fbd5ee9e", size = 1968793, upload-time = "2024-09-16T16:04:52.604Z" }, - { url = "https://files.pythonhosted.org/packages/e3/b9/41f7efe80f6ce2ed3ee3c2dcfe10ab7adc1172f778cc9659509a79518c43/pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9261d3ce84fa1d38ed649c3638feefeae23d32ba9182963e465d58d62203bd24", size = 2116872, upload-time = "2024-09-16T16:04:54.41Z" }, - { url = "https://files.pythonhosted.org/packages/63/08/b59b7a92e03dd25554b0436554bf23e7c29abae7cce4b1c459cd92746811/pydantic_core-2.23.4-cp312-none-win32.whl", hash = "sha256:4ba762ed58e8d68657fc1281e9bb72e1c3e79cc5d464be146e260c541ec12d84", size = 1738535, upload-time = "2024-09-16T16:04:55.828Z" }, - { url = "https://files.pythonhosted.org/packages/88/8d/479293e4d39ab409747926eec4329de5b7129beaedc3786eca070605d07f/pydantic_core-2.23.4-cp312-none-win_amd64.whl", hash = "sha256:97df63000f4fea395b2824da80e169731088656d1818a11b95f3b173747b6cd9", size = 1917992, upload-time = "2024-09-16T16:04:57.395Z" }, - { url = "https://files.pythonhosted.org/packages/ad/ef/16ee2df472bf0e419b6bc68c05bf0145c49247a1095e85cee1463c6a44a1/pydantic_core-2.23.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7530e201d10d7d14abce4fb54cfe5b94a0aefc87da539d0346a484ead376c3cc", size = 1856143, upload-time = "2024-09-16T16:04:59.062Z" }, - { url = "https://files.pythonhosted.org/packages/da/fa/bc3dbb83605669a34a93308e297ab22be82dfb9dcf88c6cf4b4f264e0a42/pydantic_core-2.23.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:df933278128ea1cd77772673c73954e53a1c95a4fdf41eef97c2b779271bd0bd", size = 1770063, upload-time = "2024-09-16T16:05:00.522Z" }, - { url = "https://files.pythonhosted.org/packages/4e/48/e813f3bbd257a712303ebdf55c8dc46f9589ec74b384c9f652597df3288d/pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cb3da3fd1b6a5d0279a01877713dbda118a2a4fc6f0d821a57da2e464793f05", size = 1790013, upload-time = "2024-09-16T16:05:02.619Z" }, - { url = "https://files.pythonhosted.org/packages/b4/e0/56eda3a37929a1d297fcab1966db8c339023bcca0b64c5a84896db3fcc5c/pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c6dcb030aefb668a2b7009c85b27f90e51e6a3b4d5c9bc4c57631292015b0d", size = 1801077, upload-time = "2024-09-16T16:05:04.154Z" }, - { url = "https://files.pythonhosted.org/packages/04/be/5e49376769bfbf82486da6c5c1683b891809365c20d7c7e52792ce4c71f3/pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:696dd8d674d6ce621ab9d45b205df149399e4bb9aa34102c970b721554828510", size = 1996782, upload-time = "2024-09-16T16:05:06.931Z" }, - { url = "https://files.pythonhosted.org/packages/bc/24/e3ee6c04f1d58cc15f37bcc62f32c7478ff55142b7b3e6d42ea374ea427c/pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2971bb5ffe72cc0f555c13e19b23c85b654dd2a8f7ab493c262071377bfce9f6", size = 2661375, upload-time = "2024-09-16T16:05:08.773Z" }, - { url = "https://files.pythonhosted.org/packages/c1/f8/11a9006de4e89d016b8de74ebb1db727dc100608bb1e6bbe9d56a3cbbcce/pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8394d940e5d400d04cad4f75c0598665cbb81aecefaca82ca85bd28264af7f9b", size = 2071635, upload-time = "2024-09-16T16:05:10.456Z" }, - { url = "https://files.pythonhosted.org/packages/7c/45/bdce5779b59f468bdf262a5bc9eecbae87f271c51aef628d8c073b4b4b4c/pydantic_core-2.23.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0dff76e0602ca7d4cdaacc1ac4c005e0ce0dcfe095d5b5259163a80d3a10d327", size = 1916994, upload-time = "2024-09-16T16:05:12.051Z" }, - { url = "https://files.pythonhosted.org/packages/d8/fa/c648308fe711ee1f88192cad6026ab4f925396d1293e8356de7e55be89b5/pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7d32706badfe136888bdea71c0def994644e09fff0bfe47441deaed8e96fdbc6", size = 1968877, upload-time = "2024-09-16T16:05:14.021Z" }, - { url = "https://files.pythonhosted.org/packages/16/16/b805c74b35607d24d37103007f899abc4880923b04929547ae68d478b7f4/pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ed541d70698978a20eb63d8c5d72f2cc6d7079d9d90f6b50bad07826f1320f5f", size = 2116814, upload-time = "2024-09-16T16:05:15.684Z" }, - { url = "https://files.pythonhosted.org/packages/d1/58/5305e723d9fcdf1c5a655e6a4cc2a07128bf644ff4b1d98daf7a9dbf57da/pydantic_core-2.23.4-cp313-none-win32.whl", hash = "sha256:3d5639516376dce1940ea36edf408c554475369f5da2abd45d44621cb616f769", size = 1738360, upload-time = "2024-09-16T16:05:17.258Z" }, - { url = "https://files.pythonhosted.org/packages/a5/ae/e14b0ff8b3f48e02394d8acd911376b7b66e164535687ef7dc24ea03072f/pydantic_core-2.23.4-cp313-none-win_amd64.whl", hash = "sha256:5a1504ad17ba4210df3a045132a7baeeba5a200e930f57512ee02909fc5c4cb5", size = 1919411, upload-time = "2024-09-16T16:05:18.934Z" }, - { url = "https://files.pythonhosted.org/packages/7a/04/2580b2deaae37b3e30fc30c54298be938b973990b23612d6b61c7bdd01c7/pydantic_core-2.23.4-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a4fa4fc04dff799089689f4fd502ce7d59de529fc2f40a2c8836886c03e0175a", size = 1868200, upload-time = "2024-09-16T16:05:48.043Z" }, - { url = "https://files.pythonhosted.org/packages/39/6e/e311bd0751505350f0cdcee3077841eb1f9253c5a1ddbad048cd9fbf7c6e/pydantic_core-2.23.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0a7df63886be5e270da67e0966cf4afbae86069501d35c8c1b3b6c168f42cb36", size = 1749316, upload-time = "2024-09-16T16:05:50.176Z" }, - { url = "https://files.pythonhosted.org/packages/d0/b4/95b5eb47c6dc8692508c3ca04a1f8d6f0884c9dacb34cf3357595cbe73be/pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcedcd19a557e182628afa1d553c3895a9f825b936415d0dbd3cd0bbcfd29b4b", size = 1800880, upload-time = "2024-09-16T16:05:52.58Z" }, - { url = "https://files.pythonhosted.org/packages/da/79/41c4f817acd7f42d94cd1e16526c062a7b089f66faed4bd30852314d9a66/pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f54b118ce5de9ac21c363d9b3caa6c800341e8c47a508787e5868c6b79c9323", size = 1807077, upload-time = "2024-09-16T16:05:54.313Z" }, - { url = "https://files.pythonhosted.org/packages/fb/53/d13d1eb0a97d5c06cf7a225935d471e9c241afd389a333f40c703f214973/pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86d2f57d3e1379a9525c5ab067b27dbb8a0642fb5d454e17a9ac434f9ce523e3", size = 2002859, upload-time = "2024-09-16T16:05:56.051Z" }, - { url = "https://files.pythonhosted.org/packages/53/7d/6b8a1eff453774b46cac8c849e99455b27167971a003212f668e94bc4c9c/pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:de6d1d1b9e5101508cb37ab0d972357cac5235f5c6533d1071964c47139257df", size = 2661437, upload-time = "2024-09-16T16:05:57.96Z" }, - { url = "https://files.pythonhosted.org/packages/6c/ea/8820f57f0b46e6148ee42d8216b15e8fe3b360944284bbc705bf34fac888/pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1278e0d324f6908e872730c9102b0112477a7f7cf88b308e4fc36ce1bdb6d58c", size = 2054404, upload-time = "2024-09-16T16:05:59.63Z" }, - { url = "https://files.pythonhosted.org/packages/0f/36/d4ae869e473c3c7868e1cd1e2a1b9e13bce5cd1a7d287f6ac755a0b1575e/pydantic_core-2.23.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9a6b5099eeec78827553827f4c6b8615978bb4b6a88e5d9b93eddf8bb6790f55", size = 1921680, upload-time = "2024-09-16T16:06:01.554Z" }, - { url = "https://files.pythonhosted.org/packages/0d/f8/eed5c65b80c4ac4494117e2101973b45fc655774ef647d17dde40a70f7d2/pydantic_core-2.23.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e55541f756f9b3ee346b840103f32779c695a19826a4c442b7954550a0972040", size = 1966093, upload-time = "2024-09-16T16:06:03.259Z" }, - { url = "https://files.pythonhosted.org/packages/e8/c8/1d42ce51d65e571ab53d466cae83434325a126811df7ce4861d9d97bee4b/pydantic_core-2.23.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a5c7ba8ffb6d6f8f2ab08743be203654bb1aaa8c9dcb09f82ddd34eadb695605", size = 2111437, upload-time = "2024-09-16T16:06:05.016Z" }, - { url = "https://files.pythonhosted.org/packages/aa/c9/7fea9d13383c2ec6865919e09cffe44ab77e911eb281b53a4deaafd4c8e8/pydantic_core-2.23.4-cp39-none-win32.whl", hash = "sha256:37b0fe330e4a58d3c58b24d91d1eb102aeec675a3db4c292ec3928ecd892a9a6", size = 1735049, upload-time = "2024-09-16T16:06:06.709Z" }, - { url = "https://files.pythonhosted.org/packages/98/95/dd7045c4caa2b73d0bf3b989d66b23cfbb7a0ef14ce99db15677a000a953/pydantic_core-2.23.4-cp39-none-win_amd64.whl", hash = "sha256:1498bec4c05c9c787bde9125cfdcc63a41004ff167f495063191b863399b1a29", size = 1920180, upload-time = "2024-09-16T16:06:08.528Z" }, - { url = "https://files.pythonhosted.org/packages/13/a9/5d582eb3204464284611f636b55c0a7410d748ff338756323cb1ce721b96/pydantic_core-2.23.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f455ee30a9d61d3e1a15abd5068827773d6e4dc513e795f380cdd59932c782d5", size = 1857135, upload-time = "2024-09-16T16:06:10.45Z" }, - { url = "https://files.pythonhosted.org/packages/2c/57/faf36290933fe16717f97829eabfb1868182ac495f99cf0eda9f59687c9d/pydantic_core-2.23.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1e90d2e3bd2c3863d48525d297cd143fe541be8bbf6f579504b9712cb6b643ec", size = 1740583, upload-time = "2024-09-16T16:06:12.298Z" }, - { url = "https://files.pythonhosted.org/packages/91/7c/d99e3513dc191c4fec363aef1bf4c8af9125d8fa53af7cb97e8babef4e40/pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e203fdf807ac7e12ab59ca2bfcabb38c7cf0b33c41efeb00f8e5da1d86af480", size = 1793637, upload-time = "2024-09-16T16:06:14.092Z" }, - { url = "https://files.pythonhosted.org/packages/29/18/812222b6d18c2d13eebbb0f7cdc170a408d9ced65794fdb86147c77e1982/pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e08277a400de01bc72436a0ccd02bdf596631411f592ad985dcee21445bd0068", size = 1941963, upload-time = "2024-09-16T16:06:16.757Z" }, - { url = "https://files.pythonhosted.org/packages/0f/36/c1f3642ac3f05e6bb4aec3ffc399fa3f84895d259cf5f0ce3054b7735c29/pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f220b0eea5965dec25480b6333c788fb72ce5f9129e8759ef876a1d805d00801", size = 1915332, upload-time = "2024-09-16T16:06:18.677Z" }, - { url = "https://files.pythonhosted.org/packages/f7/ca/9c0854829311fb446020ebb540ee22509731abad886d2859c855dd29b904/pydantic_core-2.23.4-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d06b0c8da4f16d1d1e352134427cb194a0a6e19ad5db9161bf32b2113409e728", size = 1957926, upload-time = "2024-09-16T16:06:20.591Z" }, - { url = "https://files.pythonhosted.org/packages/c0/1c/7836b67c42d0cd4441fcd9fafbf6a027ad4b79b6559f80cf11f89fd83648/pydantic_core-2.23.4-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ba1a0996f6c2773bd83e63f18914c1de3c9dd26d55f4ac302a7efe93fb8e7433", size = 2100342, upload-time = "2024-09-16T16:06:22.888Z" }, - { url = "https://files.pythonhosted.org/packages/a9/f9/b6bcaf874f410564a78908739c80861a171788ef4d4f76f5009656672dfe/pydantic_core-2.23.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:9a5bce9d23aac8f0cf0836ecfc033896aa8443b501c58d0602dbfd5bd5b37753", size = 1920344, upload-time = "2024-09-16T16:06:24.849Z" }, - { url = "https://files.pythonhosted.org/packages/32/fd/ac9cdfaaa7cf2d32590b807d900612b39acb25e5527c3c7e482f0553025b/pydantic_core-2.23.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:78ddaaa81421a29574a682b3179d4cf9e6d405a09b99d93ddcf7e5239c742e21", size = 1857850, upload-time = "2024-09-16T16:06:26.828Z" }, - { url = "https://files.pythonhosted.org/packages/08/fe/038f4b2bcae325ea643c8ad353191187a4c92a9c3b913b139289a6f2ef04/pydantic_core-2.23.4-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:883a91b5dd7d26492ff2f04f40fbb652de40fcc0afe07e8129e8ae779c2110eb", size = 1740265, upload-time = "2024-09-16T16:06:28.872Z" }, - { url = "https://files.pythonhosted.org/packages/51/14/b215c9c3cbd1edaaea23014d4b3304260823f712d3fdee52549b19b25d62/pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88ad334a15b32a791ea935af224b9de1bf99bcd62fabf745d5f3442199d86d59", size = 1793912, upload-time = "2024-09-16T16:06:30.925Z" }, - { url = "https://files.pythonhosted.org/packages/62/de/2c3ad79b63ba564878cbce325be725929ba50089cd5156f89ea5155cb9b3/pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:233710f069d251feb12a56da21e14cca67994eab08362207785cf8c598e74577", size = 1942870, upload-time = "2024-09-16T16:06:33.298Z" }, - { url = "https://files.pythonhosted.org/packages/cb/55/c222af19e4644c741b3f3fe4fd8bbb6b4cdca87d8a49258b61cf7826b19e/pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:19442362866a753485ba5e4be408964644dd6a09123d9416c54cd49171f50744", size = 1915610, upload-time = "2024-09-16T16:06:35.5Z" }, - { url = "https://files.pythonhosted.org/packages/c4/7a/9a8760692a6f76bb54bcd43f245ff3d8b603db695899bbc624099c00af80/pydantic_core-2.23.4-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:624e278a7d29b6445e4e813af92af37820fafb6dcc55c012c834f9e26f9aaaef", size = 1958403, upload-time = "2024-09-16T16:06:37.722Z" }, - { url = "https://files.pythonhosted.org/packages/4c/91/9b03166feb914bb5698e2f6499e07c2617e2eebf69f9374d0358d7eb2009/pydantic_core-2.23.4-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f5ef8f42bec47f21d07668a043f077d507e5bf4e668d5c6dfe6aaba89de1a5b8", size = 2101154, upload-time = "2024-09-16T16:06:40.376Z" }, - { url = "https://files.pythonhosted.org/packages/1d/d9/1d7ecb98318da4cb96986daaf0e20d66f1651d0aeb9e2d4435b916ce031d/pydantic_core-2.23.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:aea443fffa9fbe3af1a9ba721a87f926fe548d32cab71d188a6ede77d0ff244e", size = 1920855, upload-time = "2024-09-16T16:06:42.707Z" }, + { url = "https://files.pythonhosted.org/packages/e5/92/b31726561b5dae176c2d2c2dc43a9c5bfba5d32f96f8b4c0a600dd492447/pydantic_core-2.33.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2b3d326aaef0c0399d9afffeb6367d5e26ddc24d351dbc9c636840ac355dc5d8", size = 2028817, upload-time = "2025-04-23T18:30:43.919Z" }, + { url = "https://files.pythonhosted.org/packages/a3/44/3f0b95fafdaca04a483c4e685fe437c6891001bf3ce8b2fded82b9ea3aa1/pydantic_core-2.33.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e5b2671f05ba48b94cb90ce55d8bdcaaedb8ba00cc5359f6810fc918713983d", size = 1861357, upload-time = "2025-04-23T18:30:46.372Z" }, + { url = "https://files.pythonhosted.org/packages/30/97/e8f13b55766234caae05372826e8e4b3b96e7b248be3157f53237682e43c/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0069c9acc3f3981b9ff4cdfaf088e98d83440a4c7ea1bc07460af3d4dc22e72d", size = 1898011, upload-time = "2025-04-23T18:30:47.591Z" }, + { url = "https://files.pythonhosted.org/packages/9b/a3/99c48cf7bafc991cc3ee66fd544c0aae8dc907b752f1dad2d79b1b5a471f/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d53b22f2032c42eaaf025f7c40c2e3b94568ae077a606f006d206a463bc69572", size = 1982730, upload-time = "2025-04-23T18:30:49.328Z" }, + { url = "https://files.pythonhosted.org/packages/de/8e/a5b882ec4307010a840fb8b58bd9bf65d1840c92eae7534c7441709bf54b/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0405262705a123b7ce9f0b92f123334d67b70fd1f20a9372b907ce1080c7ba02", size = 2136178, upload-time = "2025-04-23T18:30:50.907Z" }, + { url = "https://files.pythonhosted.org/packages/e4/bb/71e35fc3ed05af6834e890edb75968e2802fe98778971ab5cba20a162315/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4b25d91e288e2c4e0662b8038a28c6a07eaac3e196cfc4ff69de4ea3db992a1b", size = 2736462, upload-time = "2025-04-23T18:30:52.083Z" }, + { url = "https://files.pythonhosted.org/packages/31/0d/c8f7593e6bc7066289bbc366f2235701dcbebcd1ff0ef8e64f6f239fb47d/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bdfe4b3789761f3bcb4b1ddf33355a71079858958e3a552f16d5af19768fef2", size = 2005652, upload-time = "2025-04-23T18:30:53.389Z" }, + { url = "https://files.pythonhosted.org/packages/d2/7a/996d8bd75f3eda405e3dd219ff5ff0a283cd8e34add39d8ef9157e722867/pydantic_core-2.33.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:efec8db3266b76ef9607c2c4c419bdb06bf335ae433b80816089ea7585816f6a", size = 2113306, upload-time = "2025-04-23T18:30:54.661Z" }, + { url = "https://files.pythonhosted.org/packages/ff/84/daf2a6fb2db40ffda6578a7e8c5a6e9c8affb251a05c233ae37098118788/pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:031c57d67ca86902726e0fae2214ce6770bbe2f710dc33063187a68744a5ecac", size = 2073720, upload-time = "2025-04-23T18:30:56.11Z" }, + { url = "https://files.pythonhosted.org/packages/77/fb/2258da019f4825128445ae79456a5499c032b55849dbd5bed78c95ccf163/pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:f8de619080e944347f5f20de29a975c2d815d9ddd8be9b9b7268e2e3ef68605a", size = 2244915, upload-time = "2025-04-23T18:30:57.501Z" }, + { url = "https://files.pythonhosted.org/packages/d8/7a/925ff73756031289468326e355b6fa8316960d0d65f8b5d6b3a3e7866de7/pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:73662edf539e72a9440129f231ed3757faab89630d291b784ca99237fb94db2b", size = 2241884, upload-time = "2025-04-23T18:30:58.867Z" }, + { url = "https://files.pythonhosted.org/packages/0b/b0/249ee6d2646f1cdadcb813805fe76265745c4010cf20a8eba7b0e639d9b2/pydantic_core-2.33.2-cp310-cp310-win32.whl", hash = "sha256:0a39979dcbb70998b0e505fb1556a1d550a0781463ce84ebf915ba293ccb7e22", size = 1910496, upload-time = "2025-04-23T18:31:00.078Z" }, + { url = "https://files.pythonhosted.org/packages/66/ff/172ba8f12a42d4b552917aa65d1f2328990d3ccfc01d5b7c943ec084299f/pydantic_core-2.33.2-cp310-cp310-win_amd64.whl", hash = "sha256:b0379a2b24882fef529ec3b4987cb5d003b9cda32256024e6fe1586ac45fc640", size = 1955019, upload-time = "2025-04-23T18:31:01.335Z" }, + { url = "https://files.pythonhosted.org/packages/3f/8d/71db63483d518cbbf290261a1fc2839d17ff89fce7089e08cad07ccfce67/pydantic_core-2.33.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:4c5b0a576fb381edd6d27f0a85915c6daf2f8138dc5c267a57c08a62900758c7", size = 2028584, upload-time = "2025-04-23T18:31:03.106Z" }, + { url = "https://files.pythonhosted.org/packages/24/2f/3cfa7244ae292dd850989f328722d2aef313f74ffc471184dc509e1e4e5a/pydantic_core-2.33.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e799c050df38a639db758c617ec771fd8fb7a5f8eaaa4b27b101f266b216a246", size = 1855071, upload-time = "2025-04-23T18:31:04.621Z" }, + { url = "https://files.pythonhosted.org/packages/b3/d3/4ae42d33f5e3f50dd467761304be2fa0a9417fbf09735bc2cce003480f2a/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc46a01bf8d62f227d5ecee74178ffc448ff4e5197c756331f71efcc66dc980f", size = 1897823, upload-time = "2025-04-23T18:31:06.377Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f3/aa5976e8352b7695ff808599794b1fba2a9ae2ee954a3426855935799488/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a144d4f717285c6d9234a66778059f33a89096dfb9b39117663fd8413d582dcc", size = 1983792, upload-time = "2025-04-23T18:31:07.93Z" }, + { url = "https://files.pythonhosted.org/packages/d5/7a/cda9b5a23c552037717f2b2a5257e9b2bfe45e687386df9591eff7b46d28/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73cf6373c21bc80b2e0dc88444f41ae60b2f070ed02095754eb5a01df12256de", size = 2136338, upload-time = "2025-04-23T18:31:09.283Z" }, + { url = "https://files.pythonhosted.org/packages/2b/9f/b8f9ec8dd1417eb9da784e91e1667d58a2a4a7b7b34cf4af765ef663a7e5/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dc625f4aa79713512d1976fe9f0bc99f706a9dee21dfd1810b4bbbf228d0e8a", size = 2730998, upload-time = "2025-04-23T18:31:11.7Z" }, + { url = "https://files.pythonhosted.org/packages/47/bc/cd720e078576bdb8255d5032c5d63ee5c0bf4b7173dd955185a1d658c456/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b21b5549499972441da4758d662aeea93f1923f953e9cbaff14b8b9565aef", size = 2003200, upload-time = "2025-04-23T18:31:13.536Z" }, + { url = "https://files.pythonhosted.org/packages/ca/22/3602b895ee2cd29d11a2b349372446ae9727c32e78a94b3d588a40fdf187/pydantic_core-2.33.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bdc25f3681f7b78572699569514036afe3c243bc3059d3942624e936ec93450e", size = 2113890, upload-time = "2025-04-23T18:31:15.011Z" }, + { url = "https://files.pythonhosted.org/packages/ff/e6/e3c5908c03cf00d629eb38393a98fccc38ee0ce8ecce32f69fc7d7b558a7/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fe5b32187cbc0c862ee201ad66c30cf218e5ed468ec8dc1cf49dec66e160cc4d", size = 2073359, upload-time = "2025-04-23T18:31:16.393Z" }, + { url = "https://files.pythonhosted.org/packages/12/e7/6a36a07c59ebefc8777d1ffdaf5ae71b06b21952582e4b07eba88a421c79/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:bc7aee6f634a6f4a95676fcb5d6559a2c2a390330098dba5e5a5f28a2e4ada30", size = 2245883, upload-time = "2025-04-23T18:31:17.892Z" }, + { url = "https://files.pythonhosted.org/packages/16/3f/59b3187aaa6cc0c1e6616e8045b284de2b6a87b027cce2ffcea073adf1d2/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:235f45e5dbcccf6bd99f9f472858849f73d11120d76ea8707115415f8e5ebebf", size = 2241074, upload-time = "2025-04-23T18:31:19.205Z" }, + { url = "https://files.pythonhosted.org/packages/e0/ed/55532bb88f674d5d8f67ab121a2a13c385df382de2a1677f30ad385f7438/pydantic_core-2.33.2-cp311-cp311-win32.whl", hash = "sha256:6368900c2d3ef09b69cb0b913f9f8263b03786e5b2a387706c5afb66800efd51", size = 1910538, upload-time = "2025-04-23T18:31:20.541Z" }, + { url = "https://files.pythonhosted.org/packages/fe/1b/25b7cccd4519c0b23c2dd636ad39d381abf113085ce4f7bec2b0dc755eb1/pydantic_core-2.33.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e063337ef9e9820c77acc768546325ebe04ee38b08703244c1309cccc4f1bab", size = 1952909, upload-time = "2025-04-23T18:31:22.371Z" }, + { url = "https://files.pythonhosted.org/packages/49/a9/d809358e49126438055884c4366a1f6227f0f84f635a9014e2deb9b9de54/pydantic_core-2.33.2-cp311-cp311-win_arm64.whl", hash = "sha256:6b99022f1d19bc32a4c2a0d544fc9a76e3be90f0b3f4af413f87d38749300e65", size = 1897786, upload-time = "2025-04-23T18:31:24.161Z" }, + { url = "https://files.pythonhosted.org/packages/18/8a/2b41c97f554ec8c71f2a8a5f85cb56a8b0956addfe8b0efb5b3d77e8bdc3/pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc", size = 2009000, upload-time = "2025-04-23T18:31:25.863Z" }, + { url = "https://files.pythonhosted.org/packages/a1/02/6224312aacb3c8ecbaa959897af57181fb6cf3a3d7917fd44d0f2917e6f2/pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7", size = 1847996, upload-time = "2025-04-23T18:31:27.341Z" }, + { url = "https://files.pythonhosted.org/packages/d6/46/6dcdf084a523dbe0a0be59d054734b86a981726f221f4562aed313dbcb49/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025", size = 1880957, upload-time = "2025-04-23T18:31:28.956Z" }, + { url = "https://files.pythonhosted.org/packages/ec/6b/1ec2c03837ac00886ba8160ce041ce4e325b41d06a034adbef11339ae422/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011", size = 1964199, upload-time = "2025-04-23T18:31:31.025Z" }, + { url = "https://files.pythonhosted.org/packages/2d/1d/6bf34d6adb9debd9136bd197ca72642203ce9aaaa85cfcbfcf20f9696e83/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f", size = 2120296, upload-time = "2025-04-23T18:31:32.514Z" }, + { url = "https://files.pythonhosted.org/packages/e0/94/2bd0aaf5a591e974b32a9f7123f16637776c304471a0ab33cf263cf5591a/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88", size = 2676109, upload-time = "2025-04-23T18:31:33.958Z" }, + { url = "https://files.pythonhosted.org/packages/f9/41/4b043778cf9c4285d59742281a769eac371b9e47e35f98ad321349cc5d61/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1", size = 2002028, upload-time = "2025-04-23T18:31:39.095Z" }, + { url = "https://files.pythonhosted.org/packages/cb/d5/7bb781bf2748ce3d03af04d5c969fa1308880e1dca35a9bd94e1a96a922e/pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b", size = 2100044, upload-time = "2025-04-23T18:31:41.034Z" }, + { url = "https://files.pythonhosted.org/packages/fe/36/def5e53e1eb0ad896785702a5bbfd25eed546cdcf4087ad285021a90ed53/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1", size = 2058881, upload-time = "2025-04-23T18:31:42.757Z" }, + { url = "https://files.pythonhosted.org/packages/01/6c/57f8d70b2ee57fc3dc8b9610315949837fa8c11d86927b9bb044f8705419/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6", size = 2227034, upload-time = "2025-04-23T18:31:44.304Z" }, + { url = "https://files.pythonhosted.org/packages/27/b9/9c17f0396a82b3d5cbea4c24d742083422639e7bb1d5bf600e12cb176a13/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea", size = 2234187, upload-time = "2025-04-23T18:31:45.891Z" }, + { url = "https://files.pythonhosted.org/packages/b0/6a/adf5734ffd52bf86d865093ad70b2ce543415e0e356f6cacabbc0d9ad910/pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290", size = 1892628, upload-time = "2025-04-23T18:31:47.819Z" }, + { url = "https://files.pythonhosted.org/packages/43/e4/5479fecb3606c1368d496a825d8411e126133c41224c1e7238be58b87d7e/pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2", size = 1955866, upload-time = "2025-04-23T18:31:49.635Z" }, + { url = "https://files.pythonhosted.org/packages/0d/24/8b11e8b3e2be9dd82df4b11408a67c61bb4dc4f8e11b5b0fc888b38118b5/pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab", size = 1888894, upload-time = "2025-04-23T18:31:51.609Z" }, + { url = "https://files.pythonhosted.org/packages/46/8c/99040727b41f56616573a28771b1bfa08a3d3fe74d3d513f01251f79f172/pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f", size = 2015688, upload-time = "2025-04-23T18:31:53.175Z" }, + { url = "https://files.pythonhosted.org/packages/3a/cc/5999d1eb705a6cefc31f0b4a90e9f7fc400539b1a1030529700cc1b51838/pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6", size = 1844808, upload-time = "2025-04-23T18:31:54.79Z" }, + { url = "https://files.pythonhosted.org/packages/6f/5e/a0a7b8885c98889a18b6e376f344da1ef323d270b44edf8174d6bce4d622/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef", size = 1885580, upload-time = "2025-04-23T18:31:57.393Z" }, + { url = "https://files.pythonhosted.org/packages/3b/2a/953581f343c7d11a304581156618c3f592435523dd9d79865903272c256a/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a", size = 1973859, upload-time = "2025-04-23T18:31:59.065Z" }, + { url = "https://files.pythonhosted.org/packages/e6/55/f1a813904771c03a3f97f676c62cca0c0a4138654107c1b61f19c644868b/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916", size = 2120810, upload-time = "2025-04-23T18:32:00.78Z" }, + { url = "https://files.pythonhosted.org/packages/aa/c3/053389835a996e18853ba107a63caae0b9deb4a276c6b472931ea9ae6e48/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a", size = 2676498, upload-time = "2025-04-23T18:32:02.418Z" }, + { url = "https://files.pythonhosted.org/packages/eb/3c/f4abd740877a35abade05e437245b192f9d0ffb48bbbbd708df33d3cda37/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d", size = 2000611, upload-time = "2025-04-23T18:32:04.152Z" }, + { url = "https://files.pythonhosted.org/packages/59/a7/63ef2fed1837d1121a894d0ce88439fe3e3b3e48c7543b2a4479eb99c2bd/pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56", size = 2107924, upload-time = "2025-04-23T18:32:06.129Z" }, + { url = "https://files.pythonhosted.org/packages/04/8f/2551964ef045669801675f1cfc3b0d74147f4901c3ffa42be2ddb1f0efc4/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5", size = 2063196, upload-time = "2025-04-23T18:32:08.178Z" }, + { url = "https://files.pythonhosted.org/packages/26/bd/d9602777e77fc6dbb0c7db9ad356e9a985825547dce5ad1d30ee04903918/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e", size = 2236389, upload-time = "2025-04-23T18:32:10.242Z" }, + { url = "https://files.pythonhosted.org/packages/42/db/0e950daa7e2230423ab342ae918a794964b053bec24ba8af013fc7c94846/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162", size = 2239223, upload-time = "2025-04-23T18:32:12.382Z" }, + { url = "https://files.pythonhosted.org/packages/58/4d/4f937099c545a8a17eb52cb67fe0447fd9a373b348ccfa9a87f141eeb00f/pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849", size = 1900473, upload-time = "2025-04-23T18:32:14.034Z" }, + { url = "https://files.pythonhosted.org/packages/a0/75/4a0a9bac998d78d889def5e4ef2b065acba8cae8c93696906c3a91f310ca/pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9", size = 1955269, upload-time = "2025-04-23T18:32:15.783Z" }, + { url = "https://files.pythonhosted.org/packages/f9/86/1beda0576969592f1497b4ce8e7bc8cbdf614c352426271b1b10d5f0aa64/pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9", size = 1893921, upload-time = "2025-04-23T18:32:18.473Z" }, + { url = "https://files.pythonhosted.org/packages/a4/7d/e09391c2eebeab681df2b74bfe6c43422fffede8dc74187b2b0bf6fd7571/pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac", size = 1806162, upload-time = "2025-04-23T18:32:20.188Z" }, + { url = "https://files.pythonhosted.org/packages/f1/3d/847b6b1fed9f8ed3bb95a9ad04fbd0b212e832d4f0f50ff4d9ee5a9f15cf/pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5", size = 1981560, upload-time = "2025-04-23T18:32:22.354Z" }, + { url = "https://files.pythonhosted.org/packages/6f/9a/e73262f6c6656262b5fdd723ad90f518f579b7bc8622e43a942eec53c938/pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", size = 1935777, upload-time = "2025-04-23T18:32:25.088Z" }, + { url = "https://files.pythonhosted.org/packages/53/ea/bbe9095cdd771987d13c82d104a9c8559ae9aec1e29f139e286fd2e9256e/pydantic_core-2.33.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a2b911a5b90e0374d03813674bf0a5fbbb7741570dcd4b4e85a2e48d17def29d", size = 2028677, upload-time = "2025-04-23T18:32:27.227Z" }, + { url = "https://files.pythonhosted.org/packages/49/1d/4ac5ed228078737d457a609013e8f7edc64adc37b91d619ea965758369e5/pydantic_core-2.33.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6fa6dfc3e4d1f734a34710f391ae822e0a8eb8559a85c6979e14e65ee6ba2954", size = 1864735, upload-time = "2025-04-23T18:32:29.019Z" }, + { url = "https://files.pythonhosted.org/packages/23/9a/2e70d6388d7cda488ae38f57bc2f7b03ee442fbcf0d75d848304ac7e405b/pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c54c939ee22dc8e2d545da79fc5381f1c020d6d3141d3bd747eab59164dc89fb", size = 1898467, upload-time = "2025-04-23T18:32:31.119Z" }, + { url = "https://files.pythonhosted.org/packages/ff/2e/1568934feb43370c1ffb78a77f0baaa5a8b6897513e7a91051af707ffdc4/pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53a57d2ed685940a504248187d5685e49eb5eef0f696853647bf37c418c538f7", size = 1983041, upload-time = "2025-04-23T18:32:33.655Z" }, + { url = "https://files.pythonhosted.org/packages/01/1a/1a1118f38ab64eac2f6269eb8c120ab915be30e387bb561e3af904b12499/pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09fb9dd6571aacd023fe6aaca316bd01cf60ab27240d7eb39ebd66a3a15293b4", size = 2136503, upload-time = "2025-04-23T18:32:35.519Z" }, + { url = "https://files.pythonhosted.org/packages/5c/da/44754d1d7ae0f22d6d3ce6c6b1486fc07ac2c524ed8f6eca636e2e1ee49b/pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0e6116757f7959a712db11f3e9c0a99ade00a5bbedae83cb801985aa154f071b", size = 2736079, upload-time = "2025-04-23T18:32:37.659Z" }, + { url = "https://files.pythonhosted.org/packages/4d/98/f43cd89172220ec5aa86654967b22d862146bc4d736b1350b4c41e7c9c03/pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d55ab81c57b8ff8548c3e4947f119551253f4e3787a7bbc0b6b3ca47498a9d3", size = 2006508, upload-time = "2025-04-23T18:32:39.637Z" }, + { url = "https://files.pythonhosted.org/packages/2b/cc/f77e8e242171d2158309f830f7d5d07e0531b756106f36bc18712dc439df/pydantic_core-2.33.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c20c462aa4434b33a2661701b861604913f912254e441ab8d78d30485736115a", size = 2113693, upload-time = "2025-04-23T18:32:41.818Z" }, + { url = "https://files.pythonhosted.org/packages/54/7a/7be6a7bd43e0a47c147ba7fbf124fe8aaf1200bc587da925509641113b2d/pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:44857c3227d3fb5e753d5fe4a3420d6376fa594b07b621e220cd93703fe21782", size = 2074224, upload-time = "2025-04-23T18:32:44.033Z" }, + { url = "https://files.pythonhosted.org/packages/2a/07/31cf8fadffbb03be1cb520850e00a8490c0927ec456e8293cafda0726184/pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:eb9b459ca4df0e5c87deb59d37377461a538852765293f9e6ee834f0435a93b9", size = 2245403, upload-time = "2025-04-23T18:32:45.836Z" }, + { url = "https://files.pythonhosted.org/packages/b6/8d/bbaf4c6721b668d44f01861f297eb01c9b35f612f6b8e14173cb204e6240/pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9fcd347d2cc5c23b06de6d3b7b8275be558a0c90549495c699e379a80bf8379e", size = 2242331, upload-time = "2025-04-23T18:32:47.618Z" }, + { url = "https://files.pythonhosted.org/packages/bb/93/3cc157026bca8f5006250e74515119fcaa6d6858aceee8f67ab6dc548c16/pydantic_core-2.33.2-cp39-cp39-win32.whl", hash = "sha256:83aa99b1285bc8f038941ddf598501a86f1536789740991d7d8756e34f1e74d9", size = 1910571, upload-time = "2025-04-23T18:32:49.401Z" }, + { url = "https://files.pythonhosted.org/packages/5b/90/7edc3b2a0d9f0dda8806c04e511a67b0b7a41d2187e2003673a996fb4310/pydantic_core-2.33.2-cp39-cp39-win_amd64.whl", hash = "sha256:f481959862f57f29601ccced557cc2e817bce7533ab8e01a797a48b49c9692b3", size = 1956504, upload-time = "2025-04-23T18:32:51.287Z" }, + { url = "https://files.pythonhosted.org/packages/30/68/373d55e58b7e83ce371691f6eaa7175e3a24b956c44628eb25d7da007917/pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5c4aa4e82353f65e548c476b37e64189783aa5384903bfea4f41580f255fddfa", size = 2023982, upload-time = "2025-04-23T18:32:53.14Z" }, + { url = "https://files.pythonhosted.org/packages/a4/16/145f54ac08c96a63d8ed6442f9dec17b2773d19920b627b18d4f10a061ea/pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d946c8bf0d5c24bf4fe333af284c59a19358aa3ec18cb3dc4370080da1e8ad29", size = 1858412, upload-time = "2025-04-23T18:32:55.52Z" }, + { url = "https://files.pythonhosted.org/packages/41/b1/c6dc6c3e2de4516c0bb2c46f6a373b91b5660312342a0cf5826e38ad82fa/pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87b31b6846e361ef83fedb187bb5b4372d0da3f7e28d85415efa92d6125d6e6d", size = 1892749, upload-time = "2025-04-23T18:32:57.546Z" }, + { url = "https://files.pythonhosted.org/packages/12/73/8cd57e20afba760b21b742106f9dbdfa6697f1570b189c7457a1af4cd8a0/pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa9d91b338f2df0508606f7009fde642391425189bba6d8c653afd80fd6bb64e", size = 2067527, upload-time = "2025-04-23T18:32:59.771Z" }, + { url = "https://files.pythonhosted.org/packages/e3/d5/0bb5d988cc019b3cba4a78f2d4b3854427fc47ee8ec8e9eaabf787da239c/pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2058a32994f1fde4ca0480ab9d1e75a0e8c87c22b53a3ae66554f9af78f2fe8c", size = 2108225, upload-time = "2025-04-23T18:33:04.51Z" }, + { url = "https://files.pythonhosted.org/packages/f1/c5/00c02d1571913d496aabf146106ad8239dc132485ee22efe08085084ff7c/pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:0e03262ab796d986f978f79c943fc5f620381be7287148b8010b4097f79a39ec", size = 2069490, upload-time = "2025-04-23T18:33:06.391Z" }, + { url = "https://files.pythonhosted.org/packages/22/a8/dccc38768274d3ed3a59b5d06f59ccb845778687652daa71df0cab4040d7/pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:1a8695a8d00c73e50bff9dfda4d540b7dee29ff9b8053e38380426a85ef10052", size = 2237525, upload-time = "2025-04-23T18:33:08.44Z" }, + { url = "https://files.pythonhosted.org/packages/d4/e7/4f98c0b125dda7cf7ccd14ba936218397b44f50a56dd8c16a3091df116c3/pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:fa754d1850735a0b0e03bcffd9d4b4343eb417e47196e4485d9cca326073a42c", size = 2238446, upload-time = "2025-04-23T18:33:10.313Z" }, + { url = "https://files.pythonhosted.org/packages/ce/91/2ec36480fdb0b783cd9ef6795753c1dea13882f2e68e73bce76ae8c21e6a/pydantic_core-2.33.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a11c8d26a50bfab49002947d3d237abe4d9e4b5bdc8846a63537b6488e197808", size = 2066678, upload-time = "2025-04-23T18:33:12.224Z" }, + { url = "https://files.pythonhosted.org/packages/7b/27/d4ae6487d73948d6f20dddcd94be4ea43e74349b56eba82e9bdee2d7494c/pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:dd14041875d09cc0f9308e37a6f8b65f5585cf2598a53aa0123df8b129d481f8", size = 2025200, upload-time = "2025-04-23T18:33:14.199Z" }, + { url = "https://files.pythonhosted.org/packages/f1/b8/b3cb95375f05d33801024079b9392a5ab45267a63400bf1866e7ce0f0de4/pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d87c561733f66531dced0da6e864f44ebf89a8fba55f31407b00c2f7f9449593", size = 1859123, upload-time = "2025-04-23T18:33:16.555Z" }, + { url = "https://files.pythonhosted.org/packages/05/bc/0d0b5adeda59a261cd30a1235a445bf55c7e46ae44aea28f7bd6ed46e091/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f82865531efd18d6e07a04a17331af02cb7a651583c418df8266f17a63c6612", size = 1892852, upload-time = "2025-04-23T18:33:18.513Z" }, + { url = "https://files.pythonhosted.org/packages/3e/11/d37bdebbda2e449cb3f519f6ce950927b56d62f0b84fd9cb9e372a26a3d5/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bfb5112df54209d820d7bf9317c7a6c9025ea52e49f46b6a2060104bba37de7", size = 2067484, upload-time = "2025-04-23T18:33:20.475Z" }, + { url = "https://files.pythonhosted.org/packages/8c/55/1f95f0a05ce72ecb02a8a8a1c3be0579bbc29b1d5ab68f1378b7bebc5057/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:64632ff9d614e5eecfb495796ad51b0ed98c453e447a76bcbeeb69615079fc7e", size = 2108896, upload-time = "2025-04-23T18:33:22.501Z" }, + { url = "https://files.pythonhosted.org/packages/53/89/2b2de6c81fa131f423246a9109d7b2a375e83968ad0800d6e57d0574629b/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f889f7a40498cc077332c7ab6b4608d296d852182211787d4f3ee377aaae66e8", size = 2069475, upload-time = "2025-04-23T18:33:24.528Z" }, + { url = "https://files.pythonhosted.org/packages/b8/e9/1f7efbe20d0b2b10f6718944b5d8ece9152390904f29a78e68d4e7961159/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:de4b83bb311557e439b9e186f733f6c645b9417c84e2eb8203f3f820a4b988bf", size = 2239013, upload-time = "2025-04-23T18:33:26.621Z" }, + { url = "https://files.pythonhosted.org/packages/3c/b2/5309c905a93811524a49b4e031e9851a6b00ff0fb668794472ea7746b448/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f68293f055f51b51ea42fafc74b6aad03e70e191799430b90c13d643059ebb", size = 2238715, upload-time = "2025-04-23T18:33:28.656Z" }, + { url = "https://files.pythonhosted.org/packages/32/56/8a7ca5d2cd2cda1d245d34b1c9a942920a718082ae8e54e5f3e5a58b7add/pydantic_core-2.33.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:329467cecfb529c925cf2bbd4d60d2c509bc2fb52a20c1045bf09bb70971a9c1", size = 2066757, upload-time = "2025-04-23T18:33:30.645Z" }, + { url = "https://files.pythonhosted.org/packages/08/98/dbf3fdfabaf81cda5622154fda78ea9965ac467e3239078e0dcd6df159e7/pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:87acbfcf8e90ca885206e98359d7dca4bcbb35abdc0ff66672a293e1d7a19101", size = 2024034, upload-time = "2025-04-23T18:33:32.843Z" }, + { url = "https://files.pythonhosted.org/packages/8d/99/7810aa9256e7f2ccd492590f86b79d370df1e9292f1f80b000b6a75bd2fb/pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7f92c15cd1e97d4b12acd1cc9004fa092578acfa57b67ad5e43a197175d01a64", size = 1858578, upload-time = "2025-04-23T18:33:34.912Z" }, + { url = "https://files.pythonhosted.org/packages/d8/60/bc06fa9027c7006cc6dd21e48dbf39076dc39d9abbaf718a1604973a9670/pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3f26877a748dc4251cfcfda9dfb5f13fcb034f5308388066bcfe9031b63ae7d", size = 1892858, upload-time = "2025-04-23T18:33:36.933Z" }, + { url = "https://files.pythonhosted.org/packages/f2/40/9d03997d9518816c68b4dfccb88969756b9146031b61cd37f781c74c9b6a/pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dac89aea9af8cd672fa7b510e7b8c33b0bba9a43186680550ccf23020f32d535", size = 2068498, upload-time = "2025-04-23T18:33:38.997Z" }, + { url = "https://files.pythonhosted.org/packages/d8/62/d490198d05d2d86672dc269f52579cad7261ced64c2df213d5c16e0aecb1/pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:970919794d126ba8645f3837ab6046fb4e72bbc057b3709144066204c19a455d", size = 2108428, upload-time = "2025-04-23T18:33:41.18Z" }, + { url = "https://files.pythonhosted.org/packages/9a/ec/4cd215534fd10b8549015f12ea650a1a973da20ce46430b68fc3185573e8/pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3eb3fe62804e8f859c49ed20a8451342de53ed764150cb14ca71357c765dc2a6", size = 2069854, upload-time = "2025-04-23T18:33:43.446Z" }, + { url = "https://files.pythonhosted.org/packages/1a/1a/abbd63d47e1d9b0d632fee6bb15785d0889c8a6e0a6c3b5a8e28ac1ec5d2/pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:3abcd9392a36025e3bd55f9bd38d908bd17962cc49bc6da8e7e96285336e2bca", size = 2237859, upload-time = "2025-04-23T18:33:45.56Z" }, + { url = "https://files.pythonhosted.org/packages/80/1c/fa883643429908b1c90598fd2642af8839efd1d835b65af1f75fba4d94fe/pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:3a1c81334778f9e3af2f8aeb7a960736e5cab1dfebfb26aabca09afd2906c039", size = 2239059, upload-time = "2025-04-23T18:33:47.735Z" }, + { url = "https://files.pythonhosted.org/packages/d4/29/3cade8a924a61f60ccfa10842f75eb12787e1440e2b8660ceffeb26685e7/pydantic_core-2.33.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2807668ba86cb38c6817ad9bc66215ab8584d1d304030ce4f0887336f28a5e27", size = 2066661, upload-time = "2025-04-23T18:33:49.995Z" }, ] [[package]] @@ -3073,6 +3096,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806, upload-time = "2025-04-10T14:19:03.967Z" }, ] +[[package]] +name = "typing-inspection" +version = "0.4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f8/b1/0c11f5058406b3af7609f121aaa6b609744687f1d158b3c3a5bf4cc94238/typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28", size = 75726, upload-time = "2025-05-21T18:55:23.885Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552, upload-time = "2025-05-21T18:55:22.152Z" }, +] + [[package]] name = "tzdata" version = "2025.2" From e28af0ffc3b50752d64e90eeaf690e611eb60e3a Mon Sep 17 00:00:00 2001 From: Eugene Yurtsev Date: Wed, 2 Jul 2025 17:02:17 -0400 Subject: [PATCH 012/129] ci: set explicit workflow permissions to read (should be a no-op) (#5318) * We're using restricted GITHUB_TOKENS by default. * This is expected to be a no-op operation for codeql. --- .github/workflows/_integration_test.yml | 3 +++ .github/workflows/_lint.yml | 3 +++ .github/workflows/_test.yml | 3 +++ .github/workflows/_test_langgraph.yml | 3 +++ .github/workflows/baseline.yml | 3 +++ .github/workflows/bench.yml | 3 +++ .github/workflows/ci.yml | 3 +++ .github/workflows/link_check.yml | 3 +++ .github/workflows/release.yml | 3 +++ .github/workflows/release_js.yml | 3 +++ .github/workflows/run_notebooks.yml | 3 +++ 11 files changed, 33 insertions(+) diff --git a/.github/workflows/_integration_test.yml b/.github/workflows/_integration_test.yml index e6452c637..5857609ec 100644 --- a/.github/workflows/_integration_test.yml +++ b/.github/workflows/_integration_test.yml @@ -3,6 +3,9 @@ name: CLI integration test on: workflow_call: +permissions: + contents: read + jobs: build: runs-on: ubuntu-latest diff --git a/.github/workflows/_lint.yml b/.github/workflows/_lint.yml index 585c232df..68c9a78f3 100644 --- a/.github/workflows/_lint.yml +++ b/.github/workflows/_lint.yml @@ -8,6 +8,9 @@ on: type: string description: "From which folder this pipeline executes" +permissions: + contents: read + env: # This env var allows us to get inline annotations when ruff has complaints. RUFF_OUTPUT_FORMAT: github diff --git a/.github/workflows/_test.yml b/.github/workflows/_test.yml index c572e96cb..6fb763003 100644 --- a/.github/workflows/_test.yml +++ b/.github/workflows/_test.yml @@ -8,6 +8,9 @@ on: type: string description: "From which folder this pipeline executes" +permissions: + contents: read + jobs: build: runs-on: ubuntu-latest diff --git a/.github/workflows/_test_langgraph.yml b/.github/workflows/_test_langgraph.yml index 0a8b515ea..df09511e7 100644 --- a/.github/workflows/_test_langgraph.yml +++ b/.github/workflows/_test_langgraph.yml @@ -3,6 +3,9 @@ name: test on: workflow_call: +permissions: + contents: read + jobs: build: runs-on: ubuntu-latest diff --git a/.github/workflows/baseline.yml b/.github/workflows/baseline.yml index a89bf8b3f..9b2c7cd71 100644 --- a/.github/workflows/baseline.yml +++ b/.github/workflows/baseline.yml @@ -7,6 +7,9 @@ on: paths: - "libs/**" +permissions: + contents: read + jobs: benchmark: runs-on: ubuntu-latest diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index e3eba31ac..f5484badb 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -5,6 +5,9 @@ on: paths: - "libs/**" +permissions: + contents: read + jobs: benchmark: runs-on: ubuntu-latest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 43752eddf..9ee07bc32 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,6 +6,9 @@ on: branches: [main] pull_request: +permissions: + contents: read + # If another push to the same PR or branch happens while this workflow is still running, # cancel the earlier run in favor of the next run. # diff --git a/.github/workflows/link_check.yml b/.github/workflows/link_check.yml index 05897c215..65e041e7b 100644 --- a/.github/workflows/link_check.yml +++ b/.github/workflows/link_check.yml @@ -11,6 +11,9 @@ on: - cron: "0 5 * * *" workflow_dispatch: +permissions: + contents: read + jobs: markdown-link-check: runs-on: ubuntu-latest diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e91f25804..78461653c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -8,6 +8,9 @@ on: type: string default: "libs/langgraph" +permissions: + contents: read + env: PYTHON_VERSION: "3.11" diff --git a/.github/workflows/release_js.yml b/.github/workflows/release_js.yml index 70617d6f1..bce535330 100644 --- a/.github/workflows/release_js.yml +++ b/.github/workflows/release_js.yml @@ -3,6 +3,9 @@ name: JS Release on: workflow_dispatch: +permissions: + contents: read + jobs: publish: # Disallow publishing from branches that aren't `main`. diff --git a/.github/workflows/run_notebooks.yml b/.github/workflows/run_notebooks.yml index da49980cd..975df0191 100644 --- a/.github/workflows/run_notebooks.yml +++ b/.github/workflows/run_notebooks.yml @@ -11,6 +11,9 @@ on: schedule: - cron: "0 13 * * *" +permissions: + contents: read + defaults: run: working-directory: docs From 813a1d6d0c5673acbf6774283cd8da44ea7a7fb1 Mon Sep 17 00:00:00 2001 From: Sydney Runkle <54324534+sydney-runkle@users.noreply.github.com> Date: Wed, 2 Jul 2025 17:06:05 -0400 Subject: [PATCH 013/129] langgraph: release v0.5.1 (#5323) * bump * lock --- libs/langgraph/pyproject.toml | 2 +- libs/langgraph/uv.lock | 2 +- libs/prebuilt/uv.lock | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/langgraph/pyproject.toml b/libs/langgraph/pyproject.toml index 1d5518052..a8dbae74b 100644 --- a/libs/langgraph/pyproject.toml +++ b/libs/langgraph/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "langgraph" -version = "0.5.0" +version = "0.5.1" description = "Building stateful, multi-actor applications with LLMs" authors = [] requires-python = ">=3.9" diff --git a/libs/langgraph/uv.lock b/libs/langgraph/uv.lock index 7f9382daa..897d89862 100644 --- a/libs/langgraph/uv.lock +++ b/libs/langgraph/uv.lock @@ -1201,7 +1201,7 @@ wheels = [ [[package]] name = "langgraph" -version = "0.5.0" +version = "0.5.1" source = { editable = "." } dependencies = [ { name = "langchain-core" }, diff --git a/libs/prebuilt/uv.lock b/libs/prebuilt/uv.lock index 3f4430eb8..7d399a39f 100644 --- a/libs/prebuilt/uv.lock +++ b/libs/prebuilt/uv.lock @@ -320,7 +320,7 @@ wheels = [ [[package]] name = "langgraph" -version = "0.5.0" +version = "0.5.1" source = { editable = "../langgraph" } dependencies = [ { name = "langchain-core" }, From 89451f4ea21819de806057cd94dd80a52dae97b4 Mon Sep 17 00:00:00 2001 From: Andrew Nguonly Date: Wed, 2 Jul 2025 14:30:00 -0700 Subject: [PATCH 014/129] docs: Add LGP control plane API docs page (#5319) Add control plane API docs page. --- docs/docs/cloud/reference/api/api_ref.md | 8 +- .../reference/api/api_ref_control_plane.md | 247 ++++++++++++++++++ docs/docs/concepts/langgraph_control_plane.md | 8 +- docs/mkdocs.yml | 1 + 4 files changed, 254 insertions(+), 10 deletions(-) create mode 100644 docs/docs/cloud/reference/api/api_ref_control_plane.md diff --git a/docs/docs/cloud/reference/api/api_ref.md b/docs/docs/cloud/reference/api/api_ref.md index 13b30acf2..c2d6a10a7 100644 --- a/docs/docs/cloud/reference/api/api_ref.md +++ b/docs/docs/cloud/reference/api/api_ref.md @@ -1,12 +1,12 @@ -# API Reference +# LangGraph Server API Reference -The LangGraph Platform API reference is available with each deployment at the `/docs` URL path (e.g. `http://localhost:8124/docs`). +The LangGraph Server API reference is available within each deployment at the `/docs` endpoint (e.g. `http://localhost:8124/docs`). Click here to view the API reference. ## Authentication -For deployments to LangGraph Platform, authentication is required. Pass the `X-Api-Key` header with each request to the LangGraph Platform API. The value of the header should be set to a valid LangSmith API key for the organization where the API is deployed. +For deployments to LangGraph Platform, authentication is required. Pass the `X-Api-Key` header with each request to the LangGraph Server. The value of the header should be set to a valid LangSmith API key for the organization where the LangGraph Server is deployed. Example `curl` command: ```shell @@ -18,5 +18,5 @@ curl --request POST \ "metadata": {}, "limit": 10, "offset": 0 -}' +}' ``` diff --git a/docs/docs/cloud/reference/api/api_ref_control_plane.md b/docs/docs/cloud/reference/api/api_ref_control_plane.md new file mode 100644 index 000000000..b6f3827ae --- /dev/null +++ b/docs/docs/cloud/reference/api/api_ref_control_plane.md @@ -0,0 +1,247 @@ +# LangGraph Control Plane API Reference + +The LangGraph Control Plane API is used to programmatically create and manage LangGraph Server deployments. For example, the APIs can be orchestrated to create custom CI/CD workflows. + +Click here to view the API reference. + +## Host + +LangGraph Control Plane hosts for Cloud SaaS data regions: + +| US | EU | +|----|----| +| `https://api.host.langchain.com` | `https://eu.api.host.langchain.com` | + +**Note**: Self-hosted deployments of LangGraph Platform will have a custom host for the LangGraph Control Plane. + +## Authentication + +To authenticate with the LangGraph Control Plane API, set the `X-Api-Key` header to a valid LangSmith API key. + +Example `curl` command: +```shell +curl --request GET \ + --url http://localhost:8124/v2/deployments \ + --header 'X-Api-Key: LANGSMITH_API_KEY' +``` + +## Versioning + +Each endpoint path is prefixed with a version (e.g. `v1`, `v2`). + +## Quick Start + +1. Call `POST /v2/deployments` to create a new Deployment. The response body contains the Deployment ID (`id`) and the ID of the latest (and first) revision (`latest_revision_id`). +1. Call `GET /v2/deployments/{deployment_id}` to retrieve the Deployment. Set `deployment_id` in the URL to the value of Deployment ID (`id`). +1. Poll for revision `status` until `status` is `DEPLOYED` by calling `GET /v2/deployments/{deployment_id}/revisions/{latest_revision_id}`. +1. Call `PATCH /v2/deployments/{deployment_id}` to update the deployment. + +## Example Code +Below is example Python code that demonstrates how to orchestrate the LangGraph Control Plane APIs to create a deployment, update the deployment, and delete the deployment. +```python +import os +import time + +import requests +from dotenv import load_dotenv + + +load_dotenv() + +# required environment variables +CONTROL_PLANE_HOST = os.getenv("CONTROL_PLANE_HOST") +LANGSMITH_API_KEY = os.getenv("LANGSMITH_API_KEY") +INTEGRATION_ID = os.getenv("INTEGRATION_ID") +MAX_WAIT_TIME = 1800 # 30 mins + + +def get_headers() -> dict: + """Return common headers for requests to LangGraph Control Plane API.""" + return { + "X-Api-Key": LANGSMITH_API_KEY, + } + + +def create_deployment() -> str: + """Create deployment. Return deployment ID.""" + headers = get_headers() + headers["Content-Type"] = "application/json" + + deployment_name = "my_deployment" + + request_body = { + "name": deployment_name, + "source": "github", + "source_config": { + "integration_id": INTEGRATION_ID, + "repo_url": "https://github.com/langchain-ai/langgraph-example", + "deployment_type": "dev", + "build_on_push": False, + "custom_url": None, + "resource_spec": None, + }, + "source_revision_config": { + "repo_ref": "main", + "langgraph_config_path": "langgraph.json", + "image_uri": None, + }, + "secrets": [ + { + "name": "OPENAI_API_KEY", + "value": "test_openai_api_key", + }, + { + "name": "ANTHROPIC_API_KEY", + "value": "test_anthropic_api_key", + }, + { + "name": "TAVILY_API_KEY", + "value": "test_tavily_api_key", + }, + ], + } + + response = requests.post( + url=f"{CONTROL_PLANE_HOST}/v2/deployments", + headers=headers, + json=request_body, + ) + + if response.status_code != 201: + raise Exception(f"Failed to create deployment: {response.text}") + + deployment_id = response.json()["id"] + print(f"Created deployment {deployment_name} ({deployment_id})") + return deployment_id + + +def get_deployment(deployment_id: str) -> dict: + """Get deployment.""" + response = requests.get( + url=f"{CONTROL_PLANE_HOST}/v2/deployments/{deployment_id}", + headers=get_headers(), + ) + + if response.status_code != 200: + raise Exception(f"Failed to get deployment ID {deployment_id}: {response.text}") + + return response.json() + + +def list_revisions(deployment_id: str) -> list[dict]: + """List revisions. + + Return list is sorted by created_at in descending order (latest first). + """ + response = requests.get( + url=f"{CONTROL_PLANE_HOST}/v2/deployments/{deployment_id}/revisions", + headers=get_headers(), + ) + + if response.status_code != 200: + raise Exception( + f"Failed to list revisions for deployment ID {deployment_id}: {response.text}" + ) + + return response.json() + + +def get_revision( + deployment_id: str, + revision_id: str, +) -> dict: + """Get revision.""" + response = requests.get( + url=f"{CONTROL_PLANE_HOST}/v2/deployments/{deployment_id}/revisions/{revision_id}", + headers=get_headers(), + ) + + if response.status_code != 200: + raise Exception(f"Failed to get revision ID {revision_id}: {response.text}") + + return response.json() + + +def patch_deployment(deployment_id: str) -> None: + """Patch deployment.""" + headers = get_headers() + headers["Content-Type"] = "application/json" + + response = requests.patch( + url=f"{CONTROL_PLANE_HOST}/v2/deployments/{deployment_id}", + headers=headers, + json={ + "source_config": { + "build_on_push": True, + }, + "source_revision_config": { + "repo_ref": "main", + "langgraph_config_path": "langgraph.json", + }, + }, + ) + + if response.status_code != 200: + raise Exception(f"Failed to patch deployment: {response.text}") + + print(f"Patched deployment ID {deployment_id}") + + +def wait_for_deployment(deployment_id: str, revision_id: str) -> None: + """Wait for revision status to be DEPLOYED.""" + start_time = time.time() + revision, status = None, None + while time.time() - start_time < MAX_WAIT_TIME: + revision = get_revision(deployment_id, revision_id) + status = revision["status"] + if status == "DEPLOYED": + break + elif "FAILED" in status: + raise Exception(f"Revision ID {revision_id} failed: {revision}") + + print(f"Waiting for revision ID {revision_id} to be DEPLOYED...") + time.sleep(60) + + if status != "DEPLOYED": + raise Exception( + f"Timeout waiting for revision ID {revision_id} to be DEPLOYED: {revision}" + ) + + +def delete_deployment(deployment_id: str) -> None: + """Delete deployment.""" + response = requests.delete( + url=f"{CONTROL_PLANE_HOST}/v2/deployments/{deployment_id}", + headers=get_headers(), + ) + + if response.status_code != 204: + raise Exception( + f"Failed to delete deployment ID {deployment_id}: {response.text}" + ) + + print(f"Deployment ID {deployment_id} deleted") + + +if __name__ == "__main__": + # create deployment and get the latest revision + deployment_id = create_deployment() + revisions = list_revisions(deployment_id) + latest_revision = revisions["resources"][0] + latest_revision_id = latest_revision["id"] + + # wait for latest revision to be DEPLOYED + wait_for_deployment(deployment_id, latest_revision_id) + + # patch the deployment and get the latest revision + patch_deployment(deployment_id) + revisions = list_revisions(deployment_id) + latest_revision = revisions["resources"][0] + latest_revision_id = latest_revision["id"] + + # wait for latest revision to be DEPLOYED + wait_for_deployment(deployment_id, latest_revision_id) + + # delete the deployment + delete_deployment(deployment_id) +``` \ No newline at end of file diff --git a/docs/docs/concepts/langgraph_control_plane.md b/docs/docs/concepts/langgraph_control_plane.md index 2e3ecc84d..f3562516c 100644 --- a/docs/docs/concepts/langgraph_control_plane.md +++ b/docs/docs/concepts/langgraph_control_plane.md @@ -26,7 +26,7 @@ The Control Plane UI is embedded in [LangSmith](https://docs.smith.langchain.com ## Control Plane API -This section describes data model of the control plane API. The API is used to create, update, and delete deployments. However, they are not publicly accessible. +This section describes the data model of the control plane API. The API is used to create, update, and delete deployments. See the [control plane API reference](../cloud/reference/api/api_ref_control_plane.md) for more details. ### Deployment @@ -34,11 +34,7 @@ A deployment is an instance of a LangGraph Server. A single deployment can have ### Revision -A revision is an iteration of a deployment. When a new deployment is created, an initial revision is automatically created. To deploy code changes or update environment variables for a deployment, a new revision must be created. - -### Environment Variable - -Environment variables are set for a deployment. All environment variables are stored as secrets (i.e. saved in a secrets store). +A revision is an iteration of a deployment. When a new deployment is created, an initial revision is automatically created. To deploy code changes or update secrets for a deployment, a new revision must be created. ## Control Plane Features diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 34a352fb0..69368662b 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -259,6 +259,7 @@ nav: - MCP Adapters: reference/mcp.md - LangGraph Platform: - Server API: cloud/reference/api/api_ref.md + - Control Plane API: cloud/reference/api/api_ref_control_plane.md - CLI: cloud/reference/cli.md - SDK (Python): cloud/reference/sdk/python_sdk_ref.md - SDK (JS/TS): cloud/reference/sdk/js_ts_sdk_ref.md From 22e09d27394ec856efe396b244aabdd10b713e01 Mon Sep 17 00:00:00 2001 From: Jake Broekhuizen Date: Wed, 2 Jul 2025 15:05:07 -0700 Subject: [PATCH 015/129] Create user_agent_auth.md (#5299) * Create user_agent_auth.md Adding documentation for agent authentication on behalf of a user * Update user_agent_auth.md * Rename user_agent_auth.md to user-agent-auth.md * break content out to separate guides * add links/overview * edits * fix sentence * Fix broken links * Fix: Change 'get_user_config' fn name to 'my_node' * Fix: Add reference to custom auth in MCP docs example --------- Co-authored-by: Lauren Hirata Singh --- docs/docs/agents/mcp.md | 11 +- docs/docs/agents/overview.md | 2 +- docs/docs/agents/ui.md | 4 +- docs/docs/concepts/auth.md | 48 +++++ docs/docs/concepts/mcp.md | 57 ++++++ docs/docs/concepts/server-mcp.md | 183 ++++++++++-------- docs/docs/how-tos/auth/custom_auth.md | 265 +++++++++++++------------- docs/mkdocs.yml | 1 + docs/uv.lock | 16 +- 9 files changed, 361 insertions(+), 226 deletions(-) create mode 100644 docs/docs/concepts/mcp.md diff --git a/docs/docs/agents/mcp.md b/docs/docs/agents/mcp.md index 9b654ffa5..f4bb1276d 100644 --- a/docs/docs/agents/mcp.md +++ b/docs/docs/agents/mcp.md @@ -9,21 +9,12 @@ hide: # Use MCP -[Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction) is an open protocol that standardizes how applications provide tools and context to language models. LangGraph agents can use tools defined on MCP servers through the `langchain-mcp-adapters` library. - -![MCP](./assets/mcp.png) - -Install the `langchain-mcp-adapters` library to use MCP tools in LangGraph: - -```bash -pip install langchain-mcp-adapters -``` +The Model Context Protocol (MCP) is an open protocol that standardizes how applications provide tools and context to language models. LangGraph agents can use tools defined on MCP servers through the `langchain-mcp-adapters` library. ## Use MCP tools The `langchain-mcp-adapters` package enables agents to use tools defined across one or more MCP servers. - === "In an agent" ```python title="Agent using tools defined on MCP servers" diff --git a/docs/docs/agents/overview.md b/docs/docs/agents/overview.md index 35426cc1d..d61b9d6ed 100644 --- a/docs/docs/agents/overview.md +++ b/docs/docs/agents/overview.md @@ -30,7 +30,7 @@ LangGraph includes several capabilities essential for building robust, productio - [**Memory integration**](../how-tos/memory/add-memory.md): Native support for *short-term* (session-based) and *long-term* (persistent across sessions) memory, enabling stateful behaviors in chatbots and assistants. - [**Human-in-the-loop control**](../concepts/human_in_the_loop.md): Execution can pause *indefinitely* to await human feedback—unlike websocket-based solutions limited to real-time interaction. This enables asynchronous approval, correction, or intervention at any point in the workflow. - [**Streaming support**](../how-tos/streaming.md): Real-time streaming of agent state, model tokens, tool outputs, or combined streams. -- [**Deployment tooling**](./deployment.md): Includes infrastructure-free deployment tools. [**LangGraph Platform**](https://langchain-ai.github.io/langgraph/concepts/langgraph_platform/) supports testing, debugging, and deployment. +- [**Deployment tooling**](../tutorials/langgraph-platform/local-server.md): Includes infrastructure-free deployment tools. [**LangGraph Platform**](https://langchain-ai.github.io/langgraph/concepts/langgraph_platform/) supports testing, debugging, and deployment. - **[Studio](https://langchain-ai.github.io/langgraph/concepts/langgraph_studio/)**: A visual IDE for inspecting and debugging workflows. - Supports multiple [**deployment options**](https://langchain-ai.github.io/langgraph/concepts/deployment_options.md) for production. diff --git a/docs/docs/agents/ui.md b/docs/docs/agents/ui.md index 64b321f60..41735d652 100644 --- a/docs/docs/agents/ui.md +++ b/docs/docs/agents/ui.md @@ -13,7 +13,7 @@ You can use a prebuilt chat UI for interacting with any LangGraph agent through ## Run agent in UI -First, set up LangGraph API server [locally](./deployment.md#launch-langgraph-server-locally) or deploy your agent on [LangGraph Platform](https://langchain-ai.github.io/langgraph/cloud/quick_start/). +First, set up LangGraph API server [locally](../tutorials/langgraph-platform/local-server.md) or deploy your agent on [LangGraph Platform](https://langchain-ai.github.io/langgraph/cloud/quick_start/). Then, navigate to [Agent Chat UI](https://agentchat.vercel.app), or clone the repository and [run the dev server locally](https://github.com/langchain-ai/agent-chat-ui?tab=readme-ov-file#setup): @@ -25,7 +25,7 @@ Then, navigate to [Agent Chat UI](https://agentchat.vercel.app), or clone the re ## Add human-in-the-loop -Agent Chat UI has full support for [human-in-the-loop](../concepts/human_in_the_loop.md) workflows. To try it out, replace the agent code in `src/agent/graph.py` (from the [deployment](./deployment.md) guide) with this [agent implementation](../how-tos/human_in_the_loop/add-human-in-the-loop.md#add-interrupts-to-any-tool): +Agent Chat UI has full support for [human-in-the-loop](../concepts/human_in_the_loop.md) workflows. To try it out, replace the agent code in `src/agent/graph.py` (from the [deployment](../tutorials/langgraph-platform/local-server.md) guide) with this [agent implementation](../how-tos/human_in_the_loop/add-human-in-the-loop.md#add-interrupts-to-any-tool): diff --git a/docs/docs/concepts/auth.md b/docs/docs/concepts/auth.md index 7788ce37f..204764ed3 100644 --- a/docs/docs/concepts/auth.md +++ b/docs/docs/concepts/auth.md @@ -143,6 +143,54 @@ The returned user information is available: In many of our tutorials, we will just show the "authorization" parameter to be concise, but you can opt to accept more information as needed to implement your custom authentication scheme. +### Agent authentication + +Custom authentication permits delegated access. The values you return in `@auth.authenticate` are added to the run context, giving agents user-scoped credentials lets them access resources on the user’s behalf. + +```mermaid +sequenceDiagram + %% Actors + participant ClientApp as Client + participant AuthProv as Auth Provider + participant LangGraph as LangGraph Backend + participant SecretStore as Secret Store + participant ExternalService as External Service + + %% Platform login / AuthN + ClientApp ->> AuthProv: 1. Login (username / password) + AuthProv -->> ClientApp: 2. Return token + ClientApp ->> LangGraph: 3. Request with token + + Note over LangGraph: 4. Validate token (@auth.authenticate) + LangGraph -->> AuthProv: 5. Fetch user info + AuthProv -->> LangGraph: 6. Confirm validity + + %% Fetch user tokens from secret store + LangGraph ->> SecretStore: 6a. Fetch user tokens + SecretStore -->> LangGraph: 6b. Return tokens + + Note over LangGraph: 7. Apply access control (@auth.on.*) + + %% External Service round-trip + LangGraph ->> ExternalService: 8. Call external service (with header) + Note over ExternalService: 9. External service validates header and executes action + ExternalService -->> LangGraph: 10. Service response + + %% Return to caller + LangGraph -->> ClientApp: 11. Return resources +``` + +After authentication, the platform creates a special configuration object that is passed to your graph and all nodes via the configurable context. +This object contains information about the current user, including any custom fields you return from your [`@auth.authenticate`](../cloud/reference/sdk/python_sdk_ref.md#langgraph_sdk.auth.Auth.authenticate) handler. + +To enable an agent to act on behalf of the user, use [custom authentication middleware](../how-tos/auth/custom_auth.md). This will allow the agent to interact with external systems like MCP servers, external databases, and even other agents on behalf of the user. + +For more information, see the [Use custom auth](../how-tos/auth/custom_auth.md#enable-agent-authentication) guide. + +### Agent authentication with MCP + +For information on how to authenticate an agent to an MCP server, see the [MCP conceptual guide](../concepts/mcp.md). + ## Authorization After authentication, LangGraph calls your [`@auth.on`](../cloud/reference/sdk/python_sdk_ref.md#langgraph_sdk.auth.Auth.on) handlers to control access to specific resources (e.g., threads, assistants, crons). These handlers can: diff --git a/docs/docs/concepts/mcp.md b/docs/docs/concepts/mcp.md new file mode 100644 index 000000000..a82356462 --- /dev/null +++ b/docs/docs/concepts/mcp.md @@ -0,0 +1,57 @@ +# MCP + +[Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction) is an open protocol that standardizes how applications provide tools and context to language models. LangGraph agents can use tools defined on MCP servers through the `langchain-mcp-adapters` library. + +![MCP](../agents/assets/mcp.png) + +Install the `langchain-mcp-adapters` library to use MCP tools in LangGraph: + +```bash +pip install langchain-mcp-adapters +``` + +## Authenticate to an MCP server + +You can set up [custom authentication middleware](../how-tos/auth/custom_auth.md) to authenticate a user with an MCP server to get access to user-scoped tools within your LangGraph Platform deployment. + +!!! note + Custom authentication is a LangGraph Platform feature. + +An example architecture for this flow: + +```mermaid +sequenceDiagram + %% Actors + participant ClientApp as Client + participant AuthProv as Auth Provider + participant LangGraph as LangGraph Backend + participant SecretStore as Secret Store + participant MCPServer as MCP Server + + %% Platform login / AuthN + ClientApp ->> AuthProv: 1. Login (username / password) + AuthProv -->> ClientApp: 2. Return token + ClientApp ->> LangGraph: 3. Request with token + + Note over LangGraph: 4. Validate token (@auth.authenticate) + LangGraph -->> AuthProv: 5. Fetch user info + AuthProv -->> LangGraph: 6. Confirm validity + + %% Fetch user tokens from secret store + LangGraph ->> SecretStore: 6a. Fetch user tokens + SecretStore -->> LangGraph: 6b. Return tokens + + Note over LangGraph: 7. Apply access control (@auth.on.*) + + %% MCP round-trip + Note over LangGraph: 8. Build MCP client with user token + LangGraph ->> MCPServer: 9. Call MCP tool (with header) + Note over MCPServer: 10. MCP validates header and runs tool + MCPServer -->> LangGraph: 11. Tool response + + %% Return to caller + LangGraph -->> ClientApp: 12. Return resources / tool output +``` + +For more information, see [MCP endpoint in LangGraph Server](../concepts/server-mcp.md#use-mcp-tools-in-your-deployment). + diff --git a/docs/docs/concepts/server-mcp.md b/docs/docs/concepts/server-mcp.md index 7f144e87f..ba1ebf49d 100644 --- a/docs/docs/concepts/server-mcp.md +++ b/docs/docs/concepts/server-mcp.md @@ -8,8 +8,7 @@ hide: # MCP endpoint in LangGraph Server -The **Model Context Protocol (MCP)** is an open protocol for describing tools and data sources in a model-agnostic format, enabling LLMs to discover -and use them via a structured API. +The [Model Context Protocol (MCP)](./mcp.md) is an open protocol for describing tools and data sources in a model-agnostic format, enabling LLMs to discover and use them via a structured API. [LangGraph Server](./langgraph_server.md) implements MCP using the [Streamable HTTP transport](https://spec.modelcontextprotocol.io/specification/2025-03-26/basic/transports/#streamable-http). This allows LangGraph **agents** to be exposed as **MCP tools**, making them usable with any MCP-compliant client supporting Streamable HTTP. @@ -28,79 +27,6 @@ Install them with: pip install "langgraph-api>=0.2.3" "langgraph-sdk>=0.1.61" ``` -## Exposing an agent as MCP tool - - -When deployed, your agent will appear as a tool in the MCP endpoint -with this configuration: - -- **Tool name**: The agent's name. -- **Tool description**: The agent's description. -- **Tool input schema**: The agent's input schema. - -### Setting name and description - -You can set the name and description of your agent in `langgraph.json`: - -```json -{ - "graphs": { - "my_agent": { - "path": "./my_agent/agent.py:graph", - "description": "A description of what the agent does" - } - }, - "env": ".env" -} -``` - -After deployment, you can update the name and description using the LangGraph SDK. - -### Schema - -Define clear, minimal input and output schemas to avoid exposing unnecessary internal complexity to the LLM. - -The default [MessagesState](./low_level.md#messagesstate) uses `AnyMessage`, which supports many message types but is too general for direct LLM exposure. - -Instead, define **custom agents or workflows** that use explicitly typed input and output structures. - -For example, a workflow answering documentation questions might look like this: - -```python -from langgraph.graph import StateGraph, START, END -from typing_extensions import TypedDict - -# Define input schema -class InputState(TypedDict): - question: str - -# Define output schema -class OutputState(TypedDict): - answer: str - -# Combine input and output -class OverallState(InputState, OutputState): - pass - -# Define the processing node -def answer_node(state: InputState): - # Replace with actual logic and do something useful - return {"answer": "bye", "question": state["question"]} - -# Build the graph with explicit schemas -builder = StateGraph(OverallState, input_schema=InputState, output_schema=OutputState) -builder.add_node(answer_node) -builder.add_edge(START, "answer_node") -builder.add_edge("answer_node", END) -graph = builder.compile() - -# Run the graph -print(graph.invoke({"question": "hi"})) -``` - -For more details, see the [low-level concepts guide](https://langchain-ai.github.io/langgraph/concepts/low_level/#state). - - ## Usage overview To enable MCP: @@ -201,6 +127,109 @@ Use an MCP-compliant client to connect to the LangGraph server. The following ex asyncio.run(main()) ``` +## Expose an agent as MCP tool + +When deployed, your agent will appear as a tool in the MCP endpoint +with this configuration: + +- **Tool name**: The agent's name. +- **Tool description**: The agent's description. +- **Tool input schema**: The agent's input schema. + +### Setting name and description + +You can set the name and description of your agent in `langgraph.json`: + +```json +{ + "graphs": { + "my_agent": { + "path": "./my_agent/agent.py:graph", + "description": "A description of what the agent does" + } + }, + "env": ".env" +} +``` + +After deployment, you can update the name and description using the LangGraph SDK. + +### Schema + +Define clear, minimal input and output schemas to avoid exposing unnecessary internal complexity to the LLM. + +The default [MessagesState](./low_level.md#messagesstate) uses `AnyMessage`, which supports many message types but is too general for direct LLM exposure. + +Instead, define **custom agents or workflows** that use explicitly typed input and output structures. + +For example, a workflow answering documentation questions might look like this: + +```python +from langgraph.graph import StateGraph, START, END +from typing_extensions import TypedDict + +# Define input schema +class InputState(TypedDict): + question: str + +# Define output schema +class OutputState(TypedDict): + answer: str + +# Combine input and output +class OverallState(InputState, OutputState): + pass + +# Define the processing node +def answer_node(state: InputState): + # Replace with actual logic and do something useful + return {"answer": "bye", "question": state["question"]} + +# Build the graph with explicit schemas +builder = StateGraph(OverallState, input_schema=InputState, output_schema=OutputState) +builder.add_node(answer_node) +builder.add_edge(START, "answer_node") +builder.add_edge("answer_node", END) +graph = builder.compile() + +# Run the graph +print(graph.invoke({"question": "hi"})) +``` + +For more details, see the [low-level concepts guide](https://langchain-ai.github.io/langgraph/concepts/low_level/#state). + +## Use User-Scoped MCP tools in your deployment + +!!! tip "Prerequisites" + + You have added your own [custom auth middleware](https://langchain-ai.github.io/langgraph/how-tos/auth/custom_auth/) that populates the `langgraph_auth_user` object, making it accessible through configurable context for every node in your graph. + +To make user-scoped tools available to your LangGraph Platform deployment, start with implementing a snippet like the following: + +```python +from langchain_mcp_adapters.client import MultiServerMCPClient + +def get_mcp_tools_node(state, config): + user = config["configurable"].get("langgraph_auth_user") + # e.g., user["github_token"], user["email"], etc. + + client = MultiServerMCPClient({ + "github": { + "transport": "streamable_http", # (1) + "url": "https://my-github-mcp-server/mcp", # (2) + "headers": { + "Authorization": f"Bearer {user['github_token']}" + } + } + }) + tools = await client.get_tools() # (3) + return {"tools": tools} + +``` + +1. MCP only supports adding headers to requests made to `streamable_http` and `sse` `transport` servers. +2. Your MCP server URL. +3. Get available tools from your MCP server. ## Session behavior @@ -210,7 +239,7 @@ The current LangGraph MCP implementation does not support sessions. Each `/mcp` The `/mcp` endpoint uses the same authentication as the rest of the LangGraph API. Refer to the [authentication guide](./auth.md) for setup details. -## Disabling MCP +## Disable MCP To disable the MCP endpoint, set `disable_mcp` to `true` in your `langgraph.json` configuration file: @@ -222,4 +251,4 @@ To disable the MCP endpoint, set `disable_mcp` to `true` in your `langgraph.json } ``` -This will prevent the server from exposing the `/mcp` endpoint. \ No newline at end of file +This will prevent the server from exposing the `/mcp` endpoint. diff --git a/docs/docs/how-tos/auth/custom_auth.md b/docs/docs/how-tos/auth/custom_auth.md index 64f95e1ef..03df45780 100644 --- a/docs/docs/how-tos/auth/custom_auth.md +++ b/docs/docs/how-tos/auth/custom_auth.md @@ -1,138 +1,147 @@ # Add custom authentication -!!! tip "Prerequisites" - - This guide assumes familiarity with the following concepts: - - * [**Authentication & Access Control**](../../concepts/auth.md) - * [**LangGraph Platform**](../../concepts/langgraph_platform.md) - - For a more guided walkthrough, see [**setting up custom authentication**](../../tutorials/auth/getting_started.md) tutorial. - -???+ note "Support by deployment type" - - Custom auth is supported for all deployments in the **managed LangGraph Platform**, as well as **Enterprise** self-hosted plans. It is not supported for **Lite** self-hosted plans. - This guide shows how to add custom authentication to your LangGraph Platform application. This guide applies to both LangGraph Platform and self-hosted deployments. It does not apply to isolated usage of the LangGraph open source library in your own custom server. -## 1. Implement authentication +!!! note + + Custom auth is supported for all **managed LangGraph Platform** deployments, as well as **Enterprise** self-hosted plans. It is not supported for **Lite** self-hosted plans. + +## Add custom authentication to your deployment + +To leverage custom authentication and access user-level metadata in your deployments, set up custom authentication to automatically populate the `config["configurable"]["langgraph_auth_user"]` object through a custom authentication handler. You can then access this object in your graph with the `langgraph_auth_user` key to [allow an agent to perform authenticated actions on behalf of the user](#enable-agent-authentication). + +1. Implement authentication: + + !!! note + + Without a custom `@auth.authenticate` handler, LangGraph sees only the API-key owner (usually the developer), so requests aren’t scoped to individual end-users. To propagate custom tokens, you must implement your own handler. + + ```python + from langgraph_sdk import Auth + import requests + + auth = Auth() + + def is_valid_key(api_key: str) -> bool: + is_valid = # your API key validation logic + return is_valid + + @auth.authenticate # (1)! + async def authenticate(headers: dict) -> Auth.types.MinimalUserDict: + api_key = headers.get("x-api-key") + if not api_key or not is_valid_key(api_key): + raise Auth.exceptions.HTTPException(status_code=401, detail="Invalid API key") + + # Fetch user-specific tokens from your secret store + user_tokens = await fetch_user_tokens(api_key) + + return { # (2)! + "identity": api_key, # fetch user ID from LangSmith + "github_token" : user_tokens.github_token + "jira_token" : user_tokens.jira_token + # ... custom fields/secrets here + } + ``` + + 1. This handler receives the request (headers, etc.), validates the user, and returns a dictionary with at least an identity field. + 2. You can add any custom fields you want (e.g., OAuth tokens, roles, org IDs, etc.). + +2. In your `langgraph.json`, add the path to your auth file: + + ```json hl_lines="7-9" + { + "dependencies": ["."], + "graphs": { + "agent": "./agent.py:graph" + }, + "env": ".env", + "auth": { + "path": "./auth.py:my_auth" + } + } + ``` + +3. Once you've set up authentication in your server, requests must include the required authorization information based on your chosen scheme. Assuming you are using JWT token authentication, you could access your deployments using any of the following methods: + + === "Python Client" + + ```python + from langgraph_sdk import get_client + + my_token = "your-token" # In practice, you would generate a signed token with your auth provider + client = get_client( + url="http://localhost:2024", + headers={"Authorization": f"Bearer {my_token}"} + ) + threads = await client.threads.search() + ``` + + === "Python RemoteGraph" + + ```python + from langgraph.pregel.remote import RemoteGraph + + my_token = "your-token" # In practice, you would generate a signed token with your auth provider + remote_graph = RemoteGraph( + "agent", + url="http://localhost:2024", + headers={"Authorization": f"Bearer {my_token}"} + ) + threads = await remote_graph.ainvoke(...) + ``` + + === "JavaScript Client" + + ```javascript + import { Client } from "@langchain/langgraph-sdk"; + + const my_token = "your-token"; // In practice, you would generate a signed token with your auth provider + const client = new Client({ + apiUrl: "http://localhost:2024", + defaultHeaders: { Authorization: `Bearer ${my_token}` }, + }); + const threads = await client.threads.search(); + ``` + + === "JavaScript RemoteGraph" + + ```javascript + import { RemoteGraph } from "@langchain/langgraph/remote"; + + const my_token = "your-token"; // In practice, you would generate a signed token with your auth provider + const remoteGraph = new RemoteGraph({ + graphId: "agent", + url: "http://localhost:2024", + headers: { Authorization: `Bearer ${my_token}` }, + }); + const threads = await remoteGraph.invoke(...); + ``` + + === "CURL" + + ```bash + curl -H "Authorization: Bearer ${your-token}" http://localhost:2024/threads + ``` + +## Enable agent authentication + +After [authentication](#add-custom-authentication-to-your-deployment), the platform creates a special configuration object (`config`) that is passed to LangGraph Platform deployment. This object contains information about the current user, including any custom fields you return from your `@auth.authenticate` handler. + +To allow an agent to perform authenticated actions on behalf of the user, access this object in your graph with the `langgraph_auth_user` key: ```python -from langgraph_sdk import Auth - -my_auth = Auth() - -@my_auth.authenticate -async def authenticate(authorization: str) -> str: - token = authorization.split(" ", 1)[-1] # "Bearer " - try: - # Verify token with your auth provider - user_id = await verify_token(token) - return user_id - except Exception: - raise Auth.exceptions.HTTPException( - status_code=401, - detail="Invalid token" - ) - -# Add authorization rules to actually control access to resources -@my_auth.on -async def add_owner( - ctx: Auth.types.AuthContext, - value: dict, -): - """Add owner to resource metadata and filter by owner.""" - filters = {"owner": ctx.user.identity} - metadata = value.setdefault("metadata", {}) - metadata.update(filters) - return filters - -# Assumes you organize information in store like (user_id, resource_type, resource_id) -@my_auth.on.store() -async def authorize_store(ctx: Auth.types.AuthContext, value: dict): - namespace: tuple = value["namespace"] - assert namespace[0] == ctx.user.identity, "Not authorized" - +def my_node(state, config): + user_config = config["configurable"].get("langgraph_auth_user") + # token was resolved during the @auth.authenticate function + token = user_config.get("github_token","") + ... ``` -## 2. Update configuration +!!! note + Fetch user credentials from a secure secret store. Storing secrets in graph state is not recommended. -In your `langgraph.json`, add the path to your auth file: +## Learn more -```json hl_lines="7-9" -{ - "dependencies": ["."], - "graphs": { - "agent": "./agent.py:graph" - }, - "env": ".env", - "auth": { - "path": "./auth.py:my_auth" - } -} -``` - -## 3. Connect from the client - -Once you've set up authentication in your server, requests must include the required authorization information based on your chosen scheme. -Assuming you are using JWT token authentication, you could access your deployments using any of the following methods: - -=== "Python Client" - - ```python - from langgraph_sdk import get_client - - my_token = "your-token" # In practice, you would generate a signed token with your auth provider - client = get_client( - url="http://localhost:2024", - headers={"Authorization": f"Bearer {my_token}"} - ) - threads = await client.threads.search() - ``` - -=== "Python RemoteGraph" - - ```python - from langgraph.pregel.remote import RemoteGraph - - my_token = "your-token" # In practice, you would generate a signed token with your auth provider - remote_graph = RemoteGraph( - "agent", - url="http://localhost:2024", - headers={"Authorization": f"Bearer {my_token}"} - ) - threads = await remote_graph.ainvoke(...) - ``` - -=== "JavaScript Client" - - ```javascript - import { Client } from "@langchain/langgraph-sdk"; - - const my_token = "your-token"; // In practice, you would generate a signed token with your auth provider - const client = new Client({ - apiUrl: "http://localhost:2024", - defaultHeaders: { Authorization: `Bearer ${my_token}` }, - }); - const threads = await client.threads.search(); - ``` - -=== "JavaScript RemoteGraph" - - ```javascript - import { RemoteGraph } from "@langchain/langgraph/remote"; - - const my_token = "your-token"; // In practice, you would generate a signed token with your auth provider - const remoteGraph = new RemoteGraph({ - graphId: "agent", - url: "http://localhost:2024", - headers: { Authorization: `Bearer ${my_token}` }, - }); - const threads = await remoteGraph.invoke(...); - ``` - -=== "CURL" - - ```bash - curl -H "Authorization: Bearer ${your-token}" http://localhost:2024/threads - ``` +* [Authentication & Access Control](../../concepts/auth.md) +* [LangGraph Platform](../../concepts/langgraph_platform.md) +* [Setting up custom authentication tutorial](../../tutorials/auth/getting_started.md) diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 69368662b..9fc53ac0d 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -156,6 +156,7 @@ nav: - Prebuilt implementation: agents/multi-agent.md - Custom implementation: how-tos/multi_agent.ipynb - MCP: + - Overview: concepts/mcp.md - Use MCP: agents/mcp.md - Server API: concepts/server-mcp.md - Evaluation: diff --git a/docs/uv.lock b/docs/uv.lock index 304d238f0..f838b6d3a 100644 --- a/docs/uv.lock +++ b/docs/uv.lock @@ -2448,7 +2448,7 @@ wheels = [ [[package]] name = "langchain-core" -version = "0.3.60" +version = "0.3.67" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jsonpatch" }, @@ -2459,9 +2459,9 @@ dependencies = [ { name = "tenacity" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5b/75/95129aaada92980a002a31e002610a80af3c8967ae7884710372e89cdde0/langchain_core-0.3.60.tar.gz", hash = "sha256:63dd1bdf7939816115399522661ca85a2f3686a61440f2f46ebd86d1b028595b", size = 557456, upload-time = "2025-05-15T15:23:23.642Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c2/40/875af0194024d0006874f061958fa417d3500bbfdc9a57e1bd1c2f4e6ed2/langchain_core-0.3.67.tar.gz", hash = "sha256:2c14aa44a0e78e014e96d7f2f8916ac109d0a0ba87ed67ee25bf7296bed7e7ba", size = 561952, upload-time = "2025-06-30T17:09:35.142Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2d/bc/344f5b11fdfe0e27f7064d2e829921a791461dc32e5ed285fe6325518c26/langchain_core-0.3.60-py3-none-any.whl", hash = "sha256:2ccdf06b12e699b1b0962bc02837056c075b4981c3d13f82a4d4c30bb22ea3dc", size = 437890, upload-time = "2025-05-15T15:23:22.278Z" }, + { url = "https://files.pythonhosted.org/packages/9f/2b/a0d283089c6d08c12d47dca39a55029ff714e939ec04f4560420426ab613/langchain_core-0.3.67-py3-none-any.whl", hash = "sha256:b699f1f24b24fa2747c05e2daa280aa64478a51e01a4e82c7f8e20b6167dfa99", size = 440237, upload-time = "2025-06-30T17:09:33.323Z" }, ] [[package]] @@ -2894,7 +2894,7 @@ test = [ [[package]] name = "langgraph-prebuilt" -version = "0.5.1" +version = "0.5.2" source = { editable = "../libs/prebuilt" } dependencies = [ { name = "langchain-core" }, @@ -2903,7 +2903,7 @@ dependencies = [ [package.metadata] requires-dist = [ - { name = "langchain-core", specifier = ">=0.3.22" }, + { name = "langchain-core", specifier = ">=0.3.67" }, { name = "langgraph-checkpoint", editable = "../libs/checkpoint" }, ] @@ -2989,7 +2989,7 @@ wheels = [ [[package]] name = "langsmith" -version = "0.3.42" +version = "0.3.45" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, @@ -3000,9 +3000,9 @@ dependencies = [ { name = "requests-toolbelt" }, { name = "zstandard" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3a/44/fe171c0b0fb0377b191aebf0b7779e0c7b2a53693c6a01ddad737212495d/langsmith-0.3.42.tar.gz", hash = "sha256:2b5cbc450ab808b992362aac6943bb1d285579aa68a3a8be901d30a393458f25", size = 345619, upload-time = "2025-05-03T03:07:17.873Z" } +sdist = { url = "https://files.pythonhosted.org/packages/be/86/b941012013260f95af2e90a3d9415af4a76a003a28412033fc4b09f35731/langsmith-0.3.45.tar.gz", hash = "sha256:1df3c6820c73ed210b2c7bc5cdb7bfa19ddc9126cd03fdf0da54e2e171e6094d", size = 348201, upload-time = "2025-06-05T05:10:28.948Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/89/8e/e8a58e0abaae3f3ac4702e9ca35d1fc6159711556b64ffd0e247771a3f12/langsmith-0.3.42-py3-none-any.whl", hash = "sha256:18114327f3364385dae4026ebfd57d1c1cb46d8f80931098f0f10abe533475ff", size = 360334, upload-time = "2025-05-03T03:07:15.491Z" }, + { url = "https://files.pythonhosted.org/packages/6a/f4/c206c0888f8a506404cb4f16ad89593bdc2f70cf00de26a1a0a7a76ad7a3/langsmith-0.3.45-py3-none-any.whl", hash = "sha256:5b55f0518601fa65f3bb6b1a3100379a96aa7b3ed5e9380581615ba9c65ed8ed", size = 363002, upload-time = "2025-06-05T05:10:27.228Z" }, ] [[package]] From 543e4c4e7e946f96962e4cc387021ff86253fbab Mon Sep 17 00:00:00 2001 From: Lauren Hirata Singh Date: Wed, 2 Jul 2025 19:28:42 -0400 Subject: [PATCH 016/129] docs: Convert notebooks (#5322) * docs: Convert subgraphs notebook * graph api conversion * fix examples * add * fixes * fix links * fix links * be gone! * multi-agent conversion * fix link * fix links * fix link --- docs/_scripts/notebook_hooks.py | 38 +- docs/docs/concepts/agentic_concepts.md | 4 +- docs/docs/concepts/low_level.md | 20 +- docs/docs/concepts/mcp.md | 2 +- docs/docs/concepts/multi_agent.md | 6 +- docs/docs/concepts/server-mcp.md | 2 +- docs/docs/concepts/subgraphs.md | 4 +- .../docs/how-tos/assets/graph_api_image_1.png | Bin 0 -> 3954 bytes .../how-tos/assets/graph_api_image_10.png | Bin 0 -> 150474 bytes .../docs/how-tos/assets/graph_api_image_2.png | Bin 0 -> 7129 bytes .../docs/how-tos/assets/graph_api_image_3.png | Bin 0 -> 9696 bytes .../docs/how-tos/assets/graph_api_image_4.png | Bin 0 -> 10101 bytes .../docs/how-tos/assets/graph_api_image_5.png | Bin 0 -> 7389 bytes .../docs/how-tos/assets/graph_api_image_6.png | Bin 0 -> 11541 bytes .../docs/how-tos/assets/graph_api_image_7.png | Bin 0 -> 7675 bytes .../docs/how-tos/assets/graph_api_image_8.png | Bin 0 -> 15601 bytes .../docs/how-tos/assets/graph_api_image_9.png | Bin 0 -> 7923 bytes docs/docs/how-tos/graph-api.ipynb | 3438 ----------------- docs/docs/how-tos/graph-api.md | 1877 +++++++++ docs/docs/how-tos/multi_agent.md | 580 +++ docs/docs/how-tos/subgraph.ipynb | 559 --- docs/docs/how-tos/subgraph.md | 453 +++ docs/mkdocs.yml | 6 +- docs/uv.lock | 2 +- extract_images.py | 70 + 25 files changed, 3022 insertions(+), 4039 deletions(-) create mode 100644 docs/docs/how-tos/assets/graph_api_image_1.png create mode 100644 docs/docs/how-tos/assets/graph_api_image_10.png create mode 100644 docs/docs/how-tos/assets/graph_api_image_2.png create mode 100644 docs/docs/how-tos/assets/graph_api_image_3.png create mode 100644 docs/docs/how-tos/assets/graph_api_image_4.png create mode 100644 docs/docs/how-tos/assets/graph_api_image_5.png create mode 100644 docs/docs/how-tos/assets/graph_api_image_6.png create mode 100644 docs/docs/how-tos/assets/graph_api_image_7.png create mode 100644 docs/docs/how-tos/assets/graph_api_image_8.png create mode 100644 docs/docs/how-tos/assets/graph_api_image_9.png delete mode 100644 docs/docs/how-tos/graph-api.ipynb create mode 100644 docs/docs/how-tos/graph-api.md create mode 100644 docs/docs/how-tos/multi_agent.md delete mode 100644 docs/docs/how-tos/subgraph.ipynb create mode 100644 docs/docs/how-tos/subgraph.md create mode 100644 extract_images.py diff --git a/docs/_scripts/notebook_hooks.py b/docs/_scripts/notebook_hooks.py index 34dceb064..7b7f049eb 100644 --- a/docs/_scripts/notebook_hooks.py +++ b/docs/_scripts/notebook_hooks.py @@ -34,20 +34,20 @@ REDIRECT_MAP = { "how-tos/streaming-from-final-node.ipynb": "how-tos/streaming-specific-nodes.ipynb", "how-tos/streaming-events-from-within-tools-without-langchain.ipynb": "how-tos/streaming-events-from-within-tools.ipynb#example-without-langchain", # graph-api - "how-tos/state-reducers.ipynb": "how-tos/graph-api#define-and-update-state", - "how-tos/sequence.ipynb": "how-tos/graph-api#create-a-sequence-of-steps", - "how-tos/branching.ipynb": "how-tos/graph-api#create-branches", - "how-tos/recursion-limit.ipynb": "how-tos/graph-api#create-and-control-loops", - "how-tos/visualization.ipynb": "how-tos/graph-api#visualize-your-graph", - "how-tos/input_output_schema.ipynb": "how-tos/graph-api#define-input-and-output-schemas", - "how-tos/pass_private_state.ipynb": "how-tos/graph-api#pass-private-state-between-nodes", - "how-tos/state-model.ipynb": "how-tos/graph-api#use-pydantic-models-for-graph-state", - "how-tos/map-reduce.ipynb": "how-tos/graph-api/#map-reduce-and-the-send-api", - "how-tos/command.ipynb": "how-tos/graph-api/#combine-control-flow-and-state-updates-with-command", - "how-tos/configuration.ipynb": "how-tos/graph-api/#add-runtime-configuration", - "how-tos/node-retries.ipynb": "how-tos/graph-api/#add-retry-policies", - "how-tos/return-when-recursion-limit-hits.ipynb": "how-tos/graph-api/#impose-a-recursion-limit", - "how-tos/async.ipynb": "how-tos/graph-api/#async", + "how-tos/state-reducers.ipynb": "how-tos/graph-api.md#define-and-update-state", + "how-tos/sequence.ipynb": "how-tos/graph-api.md#create-a-sequence-of-steps", + "how-tos/branching.ipynb": "how-tos/graph-api.md#create-branches", + "how-tos/recursion-limit.ipynb": "how-tos/graph-api.md#create-and-control-loops", + "how-tos/visualization.ipynb": "how-tos/graph-api.md#visualize-your-graph", + "how-tos/input_output_schema.ipynb": "how-tos/graph-api.md#define-input-and-output-schemas", + "how-tos/pass_private_state.ipynb": "how-tos/graph-api.md#pass-private-state-between-nodes", + "how-tos/state-model.ipynb": "how-tos/graph-api.md#use-pydantic-models-for-graph-state", + "how-tos/map-reduce.ipynb": "how-tos/graph-api.md#map-reduce-and-the-send-api", + "how-tos/command.ipynb": "how-tos/graph-api.md#combine-control-flow-and-state-updates-with-command", + "how-tos/configuration.ipynb": "how-tos/graph-api.md#add-runtime-configuration", + "how-tos/node-retries.ipynb": "how-tos/graph-api.md#add-retry-policies", + "how-tos/return-when-recursion-limit-hits.ipynb": "how-tos/graph-api.md#impose-a-recursion-limit", + "how-tos/async.ipynb": "how-tos/graph-api.md#async", # memory how-tos "how-tos/memory/manage-conversation-history.ipynb": "how-tos/memory/add-memory.md", "how-tos/memory/delete-messages.ipynb": "how-tos/memory/add-memory.md#delete-messages", @@ -55,8 +55,8 @@ REDIRECT_MAP = { "how-tos/memory.ipynb": "how-tos/memory/add-memory.md", "agents/memory.ipynb": "how-tos/memory/add-memory.md", # subgraph how-tos - "how-tos/subgraph-transform-state.ipynb": "how-tos/subgraph.ipynb#different-state-schemas", - "how-tos/subgraphs-manage-state.ipynb": "how-tos/subgraph.ipynb#add-persistence", + "how-tos/subgraph-transform-state.ipynb": "how-tos/subgraph.md#different-state-schemas", + "how-tos/subgraphs-manage-state.ipynb": "how-tos/subgraph.md#add-persistence", # persistence how-tos "how-tos/persistence_postgres.ipynb": "how-tos/memory/add-memory.md#use-in-production", "how-tos/persistence_mongodb.ipynb": "how-tos/memory/add-memory.md#use-in-production", @@ -73,9 +73,9 @@ REDIRECT_MAP = { "how-tos/pass-run-time-values-to-tools.ipynb": "how-tos/tool-calling.ipynb#read-state", "how-tos/update-state-from-tools.ipynb": "how-tos/tool-calling.ipynb#update-state", # multi-agent how-tos - "how-tos/agent-handoffs.ipynb": "how-tos/multi_agent.ipynb#handoffs", - "how-tos/multi-agent-network.ipynb": "how-tos/multi_agent.ipynb#use-in-a-multi-agent-system", - "how-tos/multi-agent-multi-turn-convo.ipynb": "how-tos/multi_agent.ipynb#multi-turn-conversation", + "how-tos/agent-handoffs.ipynb": "how-tos/multi_agent.md#handoffs", + "how-tos/multi-agent-network.ipynb": "how-tos/multi_agent.md#use-in-a-multi-agent-system", + "how-tos/multi-agent-multi-turn-convo.ipynb": "how-tos/multi_agent.md#multi-turn-conversation", # cloud redirects "cloud/index.md": "index.md", "cloud/how-tos/index.md": "concepts/langgraph_platform", diff --git a/docs/docs/concepts/agentic_concepts.md b/docs/docs/concepts/agentic_concepts.md index 5c18fce31..0dce56cd9 100644 --- a/docs/docs/concepts/agentic_concepts.md +++ b/docs/docs/concepts/agentic_concepts.md @@ -97,7 +97,7 @@ Parallel processing is vital for efficient multi-agent systems and complex tasks - Implementation of map-reduce-like operations - Efficient handling of independent subtasks -For practical implementation, see our [map-reduce tutorial](../how-tos/graph-api.ipynb#map-reduce-and-the-send-api) +For practical implementation, see our [map-reduce tutorial](../how-tos/graph-api.md#map-reduce-and-the-send-api) ### Subgraphs @@ -107,7 +107,7 @@ For practical implementation, see our [map-reduce tutorial](../how-tos/graph-api - Hierarchical organization of agent teams - Controlled communication between agents and the main system -Subgraphs communicate with the parent graph through overlapping keys in the state schema. This enables flexible, modular agent design. For implementation details, refer to our [subgraph how-to guide](../how-tos/subgraph.ipynb). +Subgraphs communicate with the parent graph through overlapping keys in the state schema. This enables flexible, modular agent design. For implementation details, refer to our [subgraph how-to guide](../how-tos/subgraph.md). ### Reflection diff --git a/docs/docs/concepts/low_level.md b/docs/docs/concepts/low_level.md index f277b742e..13c0fa0f7 100644 --- a/docs/docs/concepts/low_level.md +++ b/docs/docs/concepts/low_level.md @@ -45,9 +45,9 @@ The first thing you do when you define a graph is define the `State` of the grap ### Schema -The main documented way to specify the schema of a graph is by using `TypedDict`. However, we also support [using a Pydantic BaseModel](../how-tos/graph-api.ipynb#use-pydantic-models-for-graph-state) as your graph state to add **default values** and additional data validation. +The main documented way to specify the schema of a graph is by using `TypedDict`. However, we also support [using a Pydantic BaseModel](../how-tos/graph-api.md#use-pydantic-models-for-graph-state) as your graph state to add **default values** and additional data validation. -By default, the graph will have the same input and output schemas. If you want to change this, you can also specify explicit input and output schemas directly. This is useful when you have a lot of keys, and some are explicitly for input and others for output. See the [guide here](../how-tos/graph-api.ipynb#define-input-and-output-schemas) for how to use. +By default, the graph will have the same input and output schemas. If you want to change this, you can also specify explicit input and output schemas directly. This is useful when you have a lot of keys, and some are explicitly for input and others for output. See the [guide here](../how-tos/graph-api.md#define-input-and-output-schemas) for how to use. #### Multiple schemas @@ -56,9 +56,9 @@ Typically, all graph nodes communicate with a single schema. This means that the - Internal nodes can pass information that is not required in the graph's input / output. - We may also want to use different input / output schemas for the graph. The output might, for example, only contain a single relevant output key. -It is possible to have nodes write to private state channels inside the graph for internal node communication. We can simply define a private schema, `PrivateState`. See [this guide](../how-tos/graph-api.ipynb#pass-private-state-between-nodes) for more detail. +It is possible to have nodes write to private state channels inside the graph for internal node communication. We can simply define a private schema, `PrivateState`. See [this guide](../how-tos/graph-api.md#pass-private-state-between-nodes) for more detail. -It is also possible to define explicit input and output schemas for a graph. In these cases, we define an "internal" schema that contains _all_ keys relevant to graph operations. But, we also define `input` and `output` schemas that are sub-sets of the "internal" schema to constrain the input and output of the graph. See [this guide](../how-tos/graph-api.ipynb#define-input-and-output-schemas) for more detail. +It is also possible to define explicit input and output schemas for a graph. In these cases, we define an "internal" schema that contains _all_ keys relevant to graph operations. But, we also define `input` and `output` schemas that are sub-sets of the "internal" schema to constrain the input and output of the graph. See [this guide](../how-tos/graph-api.md#define-input-and-output-schemas) for more detail. Let's look at an example: @@ -406,7 +406,7 @@ def my_node(state: State) -> Command[Literal["my_other_node"]]: When returning `Command` in your node functions, you must add return type annotations with the list of node names the node is routing to, e.g. `Command[Literal["my_other_node"]]`. This is necessary for the graph rendering and tells LangGraph that `my_node` can navigate to `my_other_node`. -Check out this [how-to guide](../how-tos/graph-api.ipynb#combine-control-flow-and-state-updates-with-command) for an end-to-end example of how to use `Command`. +Check out this [how-to guide](../how-tos/graph-api.md#combine-control-flow-and-state-updates-with-command) for an end-to-end example of how to use `Command`. ### When should I use Command instead of conditional edges? @@ -433,17 +433,17 @@ def my_node(state: State) -> Command[Literal["other_subgraph"]]: !!! important "State updates with `Command.PARENT`" - When you send updates from a subgraph node to a parent graph node for a key that's shared by both parent and subgraph [state schemas](#schema), you **must** define a [reducer](#reducers) for the key you're updating in the parent graph state. See this [example](../how-tos/graph-api.ipynb#navigate-to-a-node-in-a-parent-graph). + When you send updates from a subgraph node to a parent graph node for a key that's shared by both parent and subgraph [state schemas](#schema), you **must** define a [reducer](#reducers) for the key you're updating in the parent graph state. See this [example](../how-tos/graph-api.md#navigate-to-a-node-in-a-parent-graph). This is particularly useful when implementing [multi-agent handoffs](./multi_agent.md#handoffs). -Check out [this guide](../how-tos/graph-api.ipynb#navigate-to-a-node-in-a-parent-graph) for detail. +Check out [this guide](../how-tos/graph-api.md#navigate-to-a-node-in-a-parent-graph) for detail. ### Using inside tools A common use case is updating graph state from inside a tool. For example, in a customer support application you might want to look up customer information based on their account number or ID in the beginning of the conversation. -Refer to [this guide](../how-tos/graph-api.ipynb#use-inside-tools) for detail. +Refer to [this guide](../how-tos/graph-api.md#use-inside-tools) for detail. ### Human-in-the-loop @@ -489,7 +489,7 @@ def node_a(state, config): ... ``` -See [this guide](../how-tos/graph-api.ipynb#add-runtime-configuration) for a full breakdown on configuration. +See [this guide](../how-tos/graph-api.md#add-runtime-configuration) for a full breakdown on configuration. ### Recursion Limit @@ -503,4 +503,4 @@ Read [this how-to](https://langchain-ai.github.io/langgraph/how-tos/recursion-li ## Visualization -It's often nice to be able to visualize graphs, especially as they get more complex. LangGraph comes with several built-in ways to visualize graphs. See [this how-to guide](../how-tos/graph-api.ipynb#visualize-your-graph) for more info. +It's often nice to be able to visualize graphs, especially as they get more complex. LangGraph comes with several built-in ways to visualize graphs. See [this how-to guide](../how-tos/graph-api.md#visualize-your-graph) for more info. diff --git a/docs/docs/concepts/mcp.md b/docs/docs/concepts/mcp.md index a82356462..4b05d008e 100644 --- a/docs/docs/concepts/mcp.md +++ b/docs/docs/concepts/mcp.md @@ -53,5 +53,5 @@ sequenceDiagram LangGraph -->> ClientApp: 12. Return resources / tool output ``` -For more information, see [MCP endpoint in LangGraph Server](../concepts/server-mcp.md#use-mcp-tools-in-your-deployment). +For more information, see [MCP endpoint in LangGraph Server](../concepts/server-mcp.md#use-user-scoped-mcp-tools-in-your-deployment). diff --git a/docs/docs/concepts/multi_agent.md b/docs/docs/concepts/multi_agent.md index 0cd4e7f61..81967f610 100644 --- a/docs/docs/concepts/multi_agent.md +++ b/docs/docs/concepts/multi_agent.md @@ -166,7 +166,7 @@ network = builder.compile() ### Supervisor -In this architecture, we define agents as nodes and add a supervisor node (LLM) that decides which agent nodes should be called next. We use [`Command`](./low_level.md#command) to route execution to the appropriate agent node based on supervisor's decision. This architecture also lends itself well to running multiple agents in parallel or using [map-reduce](../how-tos/graph-api.ipynb#map-reduce-and-the-send-api) pattern. +In this architecture, we define agents as nodes and add a supervisor node (LLM) that decides which agent nodes should be called next. We use [`Command`](./low_level.md#command) to route execution to the appropriate agent node based on supervisor's decision. This architecture also lends itself well to running multiple agents in parallel or using [map-reduce](../how-tos/graph-api.md#map-reduce-and-the-send-api) pattern. ```python from typing import Literal @@ -414,5 +414,5 @@ There are two high-level approaches to achieve that: An agent might need to have a different state schema from the rest of the agents. For example, a search agent might only need to keep track of queries and retrieved documents. There are two ways to achieve this in LangGraph: -- Define [subgraph](./subgraphs.md) agents with a separate state schema. If there are no shared state keys (channels) between the subgraph and the parent graph, it’s important to [add input / output transformations](../how-tos/subgraph.ipynb#different-state-schemas) so that the parent graph knows how to communicate with the subgraphs. -- Define agent node functions with a [private input state schema](../how-tos/graph-api.ipynb/#pass-private-state-between-nodes) that is distinct from the overall graph state schema. This allows passing information that is only needed for executing that particular agent. +- Define [subgraph](./subgraphs.md) agents with a separate state schema. If there are no shared state keys (channels) between the subgraph and the parent graph, it’s important to [add input / output transformations](../how-tos/subgraph.md#different-state-schemas) so that the parent graph knows how to communicate with the subgraphs. +- Define agent node functions with a [private input state schema](../how-tos/graph-api.md/#pass-private-state-between-nodes) that is distinct from the overall graph state schema. This allows passing information that is only needed for executing that particular agent. diff --git a/docs/docs/concepts/server-mcp.md b/docs/docs/concepts/server-mcp.md index ba1ebf49d..0d40bfb2e 100644 --- a/docs/docs/concepts/server-mcp.md +++ b/docs/docs/concepts/server-mcp.md @@ -198,7 +198,7 @@ print(graph.invoke({"question": "hi"})) For more details, see the [low-level concepts guide](https://langchain-ai.github.io/langgraph/concepts/low_level/#state). -## Use User-Scoped MCP tools in your deployment +## Use user-scoped MCP tools in your deployment !!! tip "Prerequisites" diff --git a/docs/docs/concepts/subgraphs.md b/docs/docs/concepts/subgraphs.md index 6a4aefb23..218bf8cac 100644 --- a/docs/docs/concepts/subgraphs.md +++ b/docs/docs/concepts/subgraphs.md @@ -12,7 +12,7 @@ Some reasons for using subgraphs are: The main question when adding subgraphs is how the parent graph and subgraph communicate, i.e. how they pass the [state](./low_level.md#state) between each other during the graph execution. There are two scenarios: -* parent and subgraph have **shared state keys** in their state [schemas](./low_level.md#state). In this case, you can [include the subgraph as a node in the parent graph](../how-tos/subgraph.ipynb#shared-state-schemas) +* parent and subgraph have **shared state keys** in their state [schemas](./low_level.md#state). In this case, you can [include the subgraph as a node in the parent graph](../how-tos/subgraph.md#shared-state-schemas) ```python from langgraph.graph import StateGraph, MessagesState, START @@ -40,7 +40,7 @@ The main question when adding subgraphs is how the parent graph and subgraph com graph.invoke({"messages": [{"role": "user", "content": "hi!"}]}) ``` -* parent graph and subgraph have **different schemas** (no shared state keys in their state [schemas](./low_level.md#state)). In this case, you have to [call the subgraph from inside a node in the parent graph](../how-tos/subgraph.ipynb#different-state-schemas): this is useful when the parent graph and the subgraph have different state schemas and you need to transform state before or after calling the subgraph +* parent graph and subgraph have **different schemas** (no shared state keys in their state [schemas](./low_level.md#state)). In this case, you have to [call the subgraph from inside a node in the parent graph](../how-tos/subgraph.md#different-state-schemas): this is useful when the parent graph and the subgraph have different state schemas and you need to transform state before or after calling the subgraph ```python from typing_extensions import TypedDict, Annotated diff --git a/docs/docs/how-tos/assets/graph_api_image_1.png b/docs/docs/how-tos/assets/graph_api_image_1.png new file mode 100644 index 0000000000000000000000000000000000000000..c1ac60da95c60406ff97447b87acbd758e64929f GIT binary patch literal 3954 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�CH!*m~zoRa|=@ZFtq>DII3ouqwsVT!*q( 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 R{X;yx!YP%LDJS&r{Xc~T+yDRo literal 0 HcmV?d00001 diff --git a/docs/docs/how-tos/assets/graph_api_image_2.png b/docs/docs/how-tos/assets/graph_api_image_2.png new file mode 100644 index 0000000000000000000000000000000000000000..4f890a3dd239d136a0ed78abd132d9e5a7e8a3cf GIT binary patch literal 7129 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 P7D!55UaU++FW|oc`O_57 literal 0 HcmV?d00001 diff --git a/docs/docs/how-tos/assets/graph_api_image_4.png b/docs/docs/how-tos/assets/graph_api_image_4.png new file mode 100644 index 0000000000000000000000000000000000000000..09bb71be2293d42dc254c007584e8ddb687746d7 GIT binary patch literal 10101 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 literal 0 HcmV?d00001 diff --git a/docs/docs/how-tos/assets/graph_api_image_5.png b/docs/docs/how-tos/assets/graph_api_image_5.png new file mode 100644 index 0000000000000000000000000000000000000000..c1ebb138c8189e77f94b0373c367ddbede184803 GIT binary patch literal 7389 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

C{N1F)yQv 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 bj67iE@{XhDnoREl_6AatQ5*S(DbpOE0s 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 BA6@_e literal 0 HcmV?d00001 diff --git a/docs/docs/how-tos/assets/graph_api_image_9.png b/docs/docs/how-tos/assets/graph_api_image_9.png new file mode 100644 index 0000000000000000000000000000000000000000..2eb23cc16856fb0f01d34dc0e3504fc91506ca84 GIT binary patch literal 7923 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 mQy>Gu{{OAvzn3s@i?#NXiq~+Y&\n", - "

\n", - "

\n", - " Sign up for LangSmith to quickly spot issues and improve the performance of your LangGraph projects. LangSmith lets you use trace data to debug, test, and monitor your LLM aps built with LangGraph — read more about how to get started in the docs. \n", - "

\n", - " " - ] - }, - { - "cell_type": "markdown", - "id": "b462f26d-8795-4dc2-9420-722d3e21656c", - "metadata": {}, - "source": [ - "## Define and update state\n", - "\n", - "Here we show how to define and update [state](../../concepts/low_level/#state) in LangGraph. We will demonstrate:\n", - "\n", - "1. How to use state to define a graph's [schema](../../concepts/low_level/#schema)\n", - "2. How to use [reducers](../../concepts/low_level/#reducers) to control how state updates are processed." - ] - }, - { - "cell_type": "markdown", - "id": "ca7ac66a-a3ae-43c6-bb9d-7ee2bd0030f0", - "metadata": {}, - "source": [ - "### Define state\n", - "\n", - "[State](../../concepts/low_level/#state) in LangGraph can be a `TypedDict`, `Pydantic` model, or dataclass. Below we will use `TypedDict`. See [this section](#use-pydantic-models-for-graph-state) for detail on using Pydantic.\n", - "\n", - "By default, graphs will have the same input and output schema, and the state determines that schema. See [this section](#define-input-and-output-schemas) for how to define distinct input and output schemas.\n", - "\n", - "Let's consider a simple example using [messages](../../concepts/low_level/#messagesstate). This represents a versatile formulation of state for many LLM applications. See our [concepts page](../../concepts/low_level/#working-with-messages-in-graph-state) for more detail." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "e7c3b392-50fb-4af3-bf2d-7b769f47efc6", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain_core.messages import AnyMessage\n", - "from typing_extensions import TypedDict\n", - "\n", - "\n", - "class State(TypedDict):\n", - " messages: list[AnyMessage]\n", - " extra_field: int" - ] - }, - { - "cell_type": "markdown", - "id": "c3555791-9dc9-4593-923e-9aa599d4c547", - "metadata": {}, - "source": [ - "This state tracks a list of [message](https://python.langchain.com/docs/concepts/messages/) objects, as well as an extra integer field.\n", - "\n", - "### Update state\n", - "\n", - "Let's build an example graph with a single node. Our [node](../../concepts/low_level/#nodes) is just a Python function that reads our graph's state and makes updates to it. The first argument to this function will always be the state:" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "f5db493b-c977-4f15-a06f-27b460cd7e4c", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain_core.messages import AIMessage\n", - "\n", - "\n", - "def node(state: State):\n", - " messages = state[\"messages\"]\n", - " new_message = AIMessage(\"Hello!\")\n", - "\n", - " return {\"messages\": messages + [new_message], \"extra_field\": 10}" - ] - }, - { - "cell_type": "markdown", - "id": "9f6cef5d-2635-45bc-a415-b422bb571685", - "metadata": {}, - "source": [ - "This node simply appends a message to our message list, and populates an extra field.\n", - "\n", - "!!! important\n", - "\n", - " Nodes should return updates to the state directly, instead of mutating the state.\n", - "\n", - "Let's next define a simple graph containing this node. We use [StateGraph](../../concepts/low_level/#stategraph) to define a graph that operates on this state. We then use [add_node](../../concepts/low_level/#nodes) populate our graph." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "92402ca2-9e46-4ad9-8378-83f98f597c00", - "metadata": {}, - "outputs": [], - "source": [ - "from langgraph.graph import StateGraph\n", - "\n", - "builder = StateGraph(State)\n", - "builder.add_node(node)\n", - "builder.set_entry_point(\"node\")\n", - "graph = builder.compile()" - ] - }, - { - "cell_type": "markdown", - "id": "f765d37d-3793-4ac9-90e5-fe28c6142202", - "metadata": {}, - "source": [ - "LangGraph provides built-in utilities for visualizing your graph. Let's inspect our graph. See [this section](#visualize-your-graph) for detail on visualization." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "263470d0-a9fa-48bc-86b1-c5a28b242aec", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "from IPython.display import Image, display\n", - "\n", - "display(Image(graph.get_graph().draw_mermaid_png()))" - ] - }, - { - "cell_type": "markdown", - "id": "ca3cd1a1-38b1-4cbb-9301-5aec62659e70", - "metadata": {}, - "source": [ - "In this case, our graph just executes a single node. Let's proceed with a simple invocation:" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "7d932703-932f-48cb-842c-c372f82510f9", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'messages': [HumanMessage(content='Hi', additional_kwargs={}, response_metadata={}),\n", - " AIMessage(content='Hello!', additional_kwargs={}, response_metadata={})],\n", - " 'extra_field': 10}" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from langchain_core.messages import HumanMessage\n", - "\n", - "result = graph.invoke({\"messages\": [HumanMessage(\"Hi\")]})\n", - "result" - ] - }, - { - "cell_type": "markdown", - "id": "e5918e84-49ac-4ab1-80bb-863a2e5461e2", - "metadata": {}, - "source": [ - "Note that:\n", - "\n", - "- We kicked off invocation by updating a single key of the state.\n", - "- We receive the entire state in the invocation result.\n", - "\n", - "For convenience, we frequently inspect the content of [message objects](https://python.langchain.com/docs/concepts/messages/) via pretty-print:" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "5009dbb2-77c3-47de-9d9d-3fc6e5b649b9", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "================================\u001b[1m Human Message \u001b[0m=================================\n", - "\n", - "Hi\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "\n", - "Hello!\n" - ] - } - ], - "source": [ - "for message in result[\"messages\"]:\n", - " message.pretty_print()" - ] - }, - { - "cell_type": "markdown", - "id": "4c4da6ff-a677-41bf-b51e-f2826fc51926", - "metadata": {}, - "source": [ - "### Process state updates with reducers\n", - "\n", - "Each key in the state can have its own independent [reducer](../../concepts/low_level/#reducers) function, which controls how updates from nodes are applied. If no reducer function is explicitly specified then it is assumed that all updates to the key should override it.\n", - "\n", - "For `TypedDict` state schemas, we can define reducers by annotating the corresponding field of the state with a reducer function.\n", - "\n", - "In the earlier example, our node updated the `\"messages\"` key in the state by appending a message to it. Below, we add a reducer to this key, such that updates are automatically appended:" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "35db8bfc-8747-423f-858a-b4f069d6199f", - "metadata": {}, - "outputs": [], - "source": [ - "from typing_extensions import Annotated\n", - "\n", - "\n", - "def add(left, right):\n", - " \"\"\"Can also import `add` from the `operator` built-in.\"\"\"\n", - " return left + right\n", - "\n", - "\n", - "class State(TypedDict):\n", - " # highlight-next-line\n", - " messages: Annotated[list[AnyMessage], add]\n", - " extra_field: int" - ] - }, - { - "cell_type": "markdown", - "id": "4979a906-fff3-48de-9215-8a12b9bc4acf", - "metadata": {}, - "source": [ - "Now our node can be simplified:" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "f24f8d3f-973f-468e-8895-8c4cf01951dd", - "metadata": {}, - "outputs": [], - "source": [ - "def node(state: State):\n", - " new_message = AIMessage(\"Hello!\")\n", - " # highlight-next-line\n", - " return {\"messages\": [new_message], \"extra_field\": 10}" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "6ef429ed-a0fa-4c00-a88c-bb61df59f578", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "================================\u001b[1m Human Message \u001b[0m=================================\n", - "\n", - "Hi\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "\n", - "Hello!\n" - ] - } - ], - "source": [ - "from langgraph.graph import START\n", - "\n", - "\n", - "graph = StateGraph(State).add_node(node).add_edge(START, \"node\").compile()\n", - "\n", - "result = graph.invoke({\"messages\": [HumanMessage(\"Hi\")]})\n", - "\n", - "for message in result[\"messages\"]:\n", - " message.pretty_print()" - ] - }, - { - "cell_type": "markdown", - "id": "7827723b-64aa-4d8b-b17a-5a3bcd8206f7", - "metadata": {}, - "source": [ - "#### MessagesState\n", - "\n", - "In practice, there are additional considerations for updating lists of messages:\n", - "\n", - "- We may wish to update an existing message in the state.\n", - "- We may want to accept short-hands for [message formats](../../concepts/low_level/#using-messages-in-your-graph), such as [OpenAI format](https://python.langchain.com/docs/concepts/messages/#openai-format).\n", - "\n", - "LangGraph includes a built-in reducer `add_messages` that handles these considerations:" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "89880b92-5d00-421f-83c3-46382c1d1c17", - "metadata": {}, - "outputs": [], - "source": [ - "from langgraph.graph.message import add_messages\n", - "\n", - "\n", - "class State(TypedDict):\n", - " # highlight-next-line\n", - " messages: Annotated[list[AnyMessage], add_messages]\n", - " extra_field: int\n", - "\n", - "\n", - "def node(state: State):\n", - " new_message = AIMessage(\"Hello!\")\n", - " return {\"messages\": [new_message], \"extra_field\": 10}\n", - "\n", - "\n", - "graph = StateGraph(State).add_node(node).set_entry_point(\"node\").compile()" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "51aeb731-e7f0-4d28-a096-436ef7fe004a", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "================================\u001b[1m Human Message \u001b[0m=================================\n", - "\n", - "Hi\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "\n", - "Hello!\n" - ] - } - ], - "source": [ - "# highlight-next-line\n", - "input_message = {\"role\": \"user\", \"content\": \"Hi\"}\n", - "\n", - "result = graph.invoke({\"messages\": [input_message]})\n", - "\n", - "for message in result[\"messages\"]:\n", - " message.pretty_print()" - ] - }, - { - "cell_type": "markdown", - "id": "17583dde-2520-464c-a962-eae511d0928e", - "metadata": {}, - "source": [ - "This is a versatile representation of state for applications involving [chat models](https://python.langchain.com/docs/concepts/chat_models/). LangGraph includes a pre-built `MessagesState` for convenience, so that we can have:" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "05956122-5ba0-4b4c-8b66-6362982227f2", - "metadata": {}, - "outputs": [], - "source": [ - "from langgraph.graph import MessagesState\n", - "\n", - "\n", - "class State(MessagesState):\n", - " extra_field: int" - ] - }, - { - "cell_type": "markdown", - "id": "f262985e-e973-4a27-9c9e-dbb3a06a35b7", - "metadata": {}, - "source": [ - "### Define input and output schemas\n", - "\n", - "By default, `StateGraph` operates with a single schema, and all nodes are expected to communicate using that schema. However, it's also possible to define distinct input and output schemas for a graph.\n", - "\n", - "When distinct schemas are specified, an internal schema will still be used for communication between nodes. The input schema ensures that the provided input matches the expected structure, while the output schema filters the internal data to return only the relevant information according to the defined output schema.\n", - "\n", - "Below, we'll see how to define distinct input and output schema." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6ec0eb77-874e-443e-8c73-93125b515106", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'answer': 'bye'}\n" - ] - } - ], - "source": [ - "from langgraph.graph import StateGraph, START, END\n", - "from typing_extensions import TypedDict\n", - "\n", - "\n", - "# Define the schema for the input\n", - "class InputState(TypedDict):\n", - " question: str\n", - "\n", - "\n", - "# Define the schema for the output\n", - "class OutputState(TypedDict):\n", - " answer: str\n", - "\n", - "\n", - "# Define the overall schema, combining both input and output\n", - "class OverallState(InputState, OutputState):\n", - " pass\n", - "\n", - "\n", - "# Define the node that processes the input and generates an answer\n", - "def answer_node(state: InputState):\n", - " # Example answer and an extra key\n", - " return {\"answer\": \"bye\", \"question\": state[\"question\"]}\n", - "\n", - "\n", - "# Build the graph with input and output schemas specified\n", - "builder = StateGraph(OverallState, input_schema=InputState, output_schema=OutputState)\n", - "builder.add_node(answer_node) # Add the answer node\n", - "builder.add_edge(START, \"answer_node\") # Define the starting edge\n", - "builder.add_edge(\"answer_node\", END) # Define the ending edge\n", - "graph = builder.compile() # Compile the graph\n", - "\n", - "# Invoke the graph with an input and print the result\n", - "print(graph.invoke({\"question\": \"hi\"}))" - ] - }, - { - "cell_type": "markdown", - "id": "6a68836f-98e1-4684-a8a6-c1473c73460c", - "metadata": {}, - "source": [ - "Notice that the output of invoke only includes the output schema." - ] - }, - { - "cell_type": "markdown", - "id": "47ed5db3-bda5-49e1-bf75-23e08c9a3af0", - "metadata": {}, - "source": [ - "### Pass private state between nodes\n", - "\n", - "In some cases, you may want nodes to exchange information that is crucial for intermediate logic but doesn’t need to be part of the main schema of the graph. This private data is not relevant to the overall input/output of the graph and should only be shared between certain nodes.\n", - "\n", - "Below, we'll create an example sequential graph consisting of three nodes (node_1, node_2 and node_3), where private data is passed between the first two steps (node_1 and node_2), while the third step (node_3) only has access to the public overall state." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "ce5b944d-4597-4af9-a7b5-15a00325f3e0", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Entered node `node_1`:\n", - "\tInput: {'a': 'set at start'}.\n", - "\tReturned: {'private_data': 'set by node_1'}\n", - "Entered node `node_2`:\n", - "\tInput: {'private_data': 'set by node_1'}.\n", - "\tReturned: {'a': 'set by node_2'}\n", - "Entered node `node_3`:\n", - "\tInput: {'a': 'set by node_2'}.\n", - "\tReturned: {'a': 'set by node_3'}\n", - "\n", - "Output of graph invocation: {'a': 'set by node_3'}\n" - ] - } - ], - "source": [ - "from langgraph.graph import StateGraph, START, END\n", - "from typing_extensions import TypedDict\n", - "\n", - "\n", - "# The overall state of the graph (this is the public state shared across nodes)\n", - "class OverallState(TypedDict):\n", - " a: str\n", - "\n", - "\n", - "# Output from node_1 contains private data that is not part of the overall state\n", - "class Node1Output(TypedDict):\n", - " private_data: str\n", - "\n", - "\n", - "# The private data is only shared between node_1 and node_2\n", - "def node_1(state: OverallState) -> Node1Output:\n", - " output = {\"private_data\": \"set by node_1\"}\n", - " print(f\"Entered node `node_1`:\\n\\tInput: {state}.\\n\\tReturned: {output}\")\n", - " return output\n", - "\n", - "\n", - "# Node 2 input only requests the private data available after node_1\n", - "class Node2Input(TypedDict):\n", - " private_data: str\n", - "\n", - "\n", - "def node_2(state: Node2Input) -> OverallState:\n", - " output = {\"a\": \"set by node_2\"}\n", - " print(f\"Entered node `node_2`:\\n\\tInput: {state}.\\n\\tReturned: {output}\")\n", - " return output\n", - "\n", - "\n", - "# Node 3 only has access to the overall state (no access to private data from node_1)\n", - "def node_3(state: OverallState) -> OverallState:\n", - " output = {\"a\": \"set by node_3\"}\n", - " print(f\"Entered node `node_3`:\\n\\tInput: {state}.\\n\\tReturned: {output}\")\n", - " return output\n", - "\n", - "\n", - "# Connect nodes in a sequence\n", - "# node_2 accepts private data from node_1, whereas\n", - "# node_3 does not see the private data.\n", - "builder = StateGraph(OverallState).add_sequence([node_1, node_2, node_3])\n", - "builder.add_edge(START, \"node_1\")\n", - "graph = builder.compile()\n", - "\n", - "# Invoke the graph with the initial state\n", - "response = graph.invoke(\n", - " {\n", - " \"a\": \"set at start\",\n", - " }\n", - ")\n", - "\n", - "print()\n", - "print(f\"Output of graph invocation: {response}\")" - ] - }, - { - "cell_type": "markdown", - "id": "51466c8d-8ce4-4b3d-be4e-18fdbeda5f53", - "metadata": {}, - "source": [ - "### Use Pydantic models for graph state\n", - "\n", - "A [StateGraph](https://langchain-ai.github.io/langgraph/reference/graphs/#langgraph.graph.StateGraph) accepts a `state_schema` argument on initialization that specifies the \"shape\" of the state that the nodes in the graph can access and update.\n", - "\n", - "In our examples, we typically use a python-native `TypedDict` for `state_schema`, but `state_schema` can be any [type](https://docs.python.org/3/library/stdtypes.html#type-objects).\n", - "\n", - "Here, we'll see how a [Pydantic BaseModel](https://docs.pydantic.dev/latest/api/base_model/). can be used for `state_schema` to add run time validation on **inputs**.\n", - "\n", - "\n", - "
\n", - "

Known Limitations

\n", - "

\n", - "

    \n", - "
  • \n", - " Currently, the output of the graph will NOT be an instance of a pydantic model.\n", - "
  • \n", - "
  • \n", - " Run-time validation only occurs on inputs into nodes, not on the outputs.\n", - "
  • \n", - "
  • \n", - " The validation error trace from pydantic does not show which node the error arises in.\n", - "
  • \n", - "
\n", - "

\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "efc46b36-425c-49c3-9f9e-d9785c70b034", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'a': 'goodbye'}" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from langgraph.graph import StateGraph, START, END\n", - "from typing_extensions import TypedDict\n", - "\n", - "from pydantic import BaseModel\n", - "\n", - "\n", - "# The overall state of the graph (this is the public state shared across nodes)\n", - "class OverallState(BaseModel):\n", - " a: str\n", - "\n", - "\n", - "def node(state: OverallState):\n", - " return {\"a\": \"goodbye\"}\n", - "\n", - "\n", - "# Build the state graph\n", - "builder = StateGraph(OverallState)\n", - "builder.add_node(node) # node_1 is the first node\n", - "builder.add_edge(START, \"node\") # Start the graph with node_1\n", - "builder.add_edge(\"node\", END) # End the graph after node_1\n", - "graph = builder.compile()\n", - "\n", - "# Test the graph with a valid input\n", - "graph.invoke({\"a\": \"hello\"})" - ] - }, - { - "cell_type": "markdown", - "id": "25b594c2-8198-4f76-9606-ea47151ff9d1", - "metadata": {}, - "source": [ - "Invoke the graph with an **invalid** input" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "05d7d43b-0b71-4e25-af6f-61d1560a46cb", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "An exception was raised because `a` is an integer rather than a string.\n", - "1 validation error for OverallState\n", - "a\n", - " Input should be a valid string [type=string_type, input_value=123, input_type=int]\n", - " For further information visit https://errors.pydantic.dev/2.9/v/string_type\n" - ] - } - ], - "source": [ - "try:\n", - " graph.invoke({\"a\": 123}) # Should be a string\n", - "except Exception as e:\n", - " print(\"An exception was raised because `a` is an integer rather than a string.\")\n", - " print(e)" - ] - }, - { - "cell_type": "markdown", - "id": "572ee9f1-45d2-428e-9b70-e7befaf2da80", - "metadata": {}, - "source": [ - "See below for additional features of Pydantic model state:\n", - "\n", - "
\n", - "Serialization Behavior\n", - "\n", - "When using Pydantic models as state schemas, it's important to understand how serialization works, especially when:\n", - "
    \n", - "
  • Passing Pydantic objects as inputs
  • \n", - "
  • Receiving outputs from the graph
  • \n", - "
  • Working with nested Pydantic models
  • \n", - "
\n", - "Let's see these behaviors in action.\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "0e919cdc", - "metadata": {}, - "outputs": [], - "source": [ - "from langgraph.graph import StateGraph, START, END\n", - "from pydantic import BaseModel\n", - "\n", - "\n", - "class NestedModel(BaseModel):\n", - " value: str\n", - "\n", - "\n", - "class ComplexState(BaseModel):\n", - " text: str\n", - " count: int\n", - " nested: NestedModel\n", - "\n", - "\n", - "def process_node(state: ComplexState):\n", - " # Node receives a validated Pydantic object\n", - " print(f\"Input state type: {type(state)}\")\n", - " print(f\"Nested type: {type(state.nested)}\")\n", - "\n", - " # Return a dictionary update\n", - " return {\"text\": state.text + \" processed\", \"count\": state.count + 1}\n", - "\n", - "\n", - "# Build the graph\n", - "builder = StateGraph(ComplexState)\n", - "builder.add_node(\"process\", process_node)\n", - "builder.add_edge(START, \"process\")\n", - "builder.add_edge(\"process\", END)\n", - "graph = builder.compile()\n", - "\n", - "# Create a Pydantic instance for input\n", - "input_state = ComplexState(text=\"hello\", count=0, nested=NestedModel(value=\"test\"))\n", - "print(f\"Input object type: {type(input_state)}\")\n", - "\n", - "# Invoke graph with a Pydantic instance\n", - "result = graph.invoke(input_state)\n", - "print(f\"Output type: {type(result)}\")\n", - "print(f\"Output content: {result}\")\n", - "\n", - "# Convert back to Pydantic model if needed\n", - "output_model = ComplexState(**result)\n", - "print(f\"Converted back to Pydantic: {type(output_model)}\")" - ] - }, - { - "cell_type": "markdown", - "id": "f13f28ce", - "metadata": {}, - "source": [ - "
\n", - "\n", - "
Runtime Type Coercion\n", - "\n", - "Pydantic performs runtime type coercion for certain data types. This can be helpful but also lead to unexpected behavior if you're not aware of it.\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "faf59316", - "metadata": {}, - "outputs": [], - "source": [ - "from langgraph.graph import StateGraph, START, END\n", - "from pydantic import BaseModel\n", - "\n", - "\n", - "class CoercionExample(BaseModel):\n", - " # Pydantic will coerce string numbers to integers\n", - " number: int\n", - " # Pydantic will parse string booleans to bool\n", - " flag: bool\n", - "\n", - "\n", - "def inspect_node(state: CoercionExample):\n", - " print(f\"number: {state.number} (type: {type(state.number)})\")\n", - " print(f\"flag: {state.flag} (type: {type(state.flag)})\")\n", - " return {}\n", - "\n", - "\n", - "builder = StateGraph(CoercionExample)\n", - "builder.add_node(\"inspect\", inspect_node)\n", - "builder.add_edge(START, \"inspect\")\n", - "builder.add_edge(\"inspect\", END)\n", - "graph = builder.compile()\n", - "\n", - "# Demonstrate coercion with string inputs that will be converted\n", - "result = graph.invoke({\"number\": \"42\", \"flag\": \"true\"})\n", - "\n", - "# This would fail with a validation error\n", - "try:\n", - " graph.invoke({\"number\": \"not-a-number\", \"flag\": \"true\"})\n", - "except Exception as e:\n", - " print(f\"\\nExpected validation error: {e}\")" - ] - }, - { - "cell_type": "markdown", - "id": "2844475b", - "metadata": {}, - "source": [ - "
\n", - "\n", - "
Working with Message Models\n", - "\n", - "When working with LangChain message types in your state schema, there are important considerations for serialization. You should use AnyMessage (rather than BaseMessage) for proper serialization/deserialization when using message objects over the wire.\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "bd0734b0", - "metadata": {}, - "outputs": [], - "source": [ - "from langgraph.graph import StateGraph, START, END\n", - "from pydantic import BaseModel\n", - "from langchain_core.messages import HumanMessage, AIMessage, AnyMessage\n", - "from typing import List\n", - "\n", - "\n", - "class ChatState(BaseModel):\n", - " messages: List[AnyMessage]\n", - " context: str\n", - "\n", - "\n", - "def add_message(state: ChatState):\n", - " return {\"messages\": state.messages + [AIMessage(content=\"Hello there!\")]}\n", - "\n", - "\n", - "builder = StateGraph(ChatState)\n", - "builder.add_node(\"add_message\", add_message)\n", - "builder.add_edge(START, \"add_message\")\n", - "builder.add_edge(\"add_message\", END)\n", - "graph = builder.compile()\n", - "\n", - "# Create input with a message\n", - "initial_state = ChatState(\n", - " messages=[HumanMessage(content=\"Hi\")], context=\"Customer support chat\"\n", - ")\n", - "\n", - "result = graph.invoke(initial_state)\n", - "print(f\"Output: {result}\")\n", - "\n", - "# Convert back to Pydantic model to see message types\n", - "output_model = ChatState(**result)\n", - "for i, msg in enumerate(output_model.messages):\n", - " print(f\"Message {i}: {type(msg).__name__} - {msg.content}\")" - ] - }, - { - "cell_type": "markdown", - "id": "c2e52e1f-c07a-4ebf-b28e-c370c8f50550", - "metadata": {}, - "source": [ - "
" - ] - }, - { - "cell_type": "markdown", - "id": "6e6a0a39-9a4c-47ae-a238-1a3a847eea5b", - "metadata": {}, - "source": [ - "## Add runtime configuration\n", - "\n", - "Sometimes you want to be able to configure your graph when calling it. For example, you might want to be able to specify what LLM or system prompt to use at runtime, *without polluting the graph state with these parameters*.\n", - "\n", - "To add runtime configuration:\n", - "\n", - "1. Specify a schema for your configuration\n", - "2. Add the configuration to the function signature for nodes or conditional edges\n", - "3. Pass the configuration into the graph.\n", - "\n", - "See below for a simple example:" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "97fc508b-1011-402e-8769-573ac3acb53a", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'my_state_value': 1}\n", - "{'my_state_value': 2}\n" - ] - } - ], - "source": [ - "from langchain_core.runnables import RunnableConfig\n", - "from langgraph.graph import END, StateGraph, START\n", - "from typing_extensions import TypedDict\n", - "\n", - "\n", - "# 1. Specify config schema\n", - "class ConfigSchema(TypedDict):\n", - " my_runtime_value: str\n", - "\n", - "\n", - "# 2. Define a graph that accesses the config in a node\n", - "class State(TypedDict):\n", - " my_state_value: str\n", - "\n", - "\n", - "# highlight-next-line\n", - "def node(state: State, config: RunnableConfig):\n", - " # highlight-next-line\n", - " if config[\"configurable\"][\"my_runtime_value\"] == \"a\":\n", - " return {\"my_state_value\": 1}\n", - " # highlight-next-line\n", - " elif config[\"configurable\"][\"my_runtime_value\"] == \"b\":\n", - " return {\"my_state_value\": 2}\n", - " else:\n", - " raise ValueError(\"Unknown values.\")\n", - "\n", - "\n", - "# highlight-next-line\n", - "builder = StateGraph(State, config_schema=ConfigSchema)\n", - "builder.add_node(node)\n", - "builder.add_edge(START, \"node\")\n", - "builder.add_edge(\"node\", END)\n", - "\n", - "graph = builder.compile()\n", - "\n", - "# 3. Pass in configuration at runtime:\n", - "# highlight-next-line\n", - "print(graph.invoke({}, {\"configurable\": {\"my_runtime_value\": \"a\"}}))\n", - "# highlight-next-line\n", - "print(graph.invoke({}, {\"configurable\": {\"my_runtime_value\": \"b\"}}))" - ] - }, - { - "cell_type": "markdown", - "id": "f080f50b-cec1-4dba-81e0-63cf40c990ee", - "metadata": {}, - "source": [ - "
Extended example: specifying LLM at runtime\n", - "\n", - "Below we demonstrate a practical example in which we configure what LLM to use at runtime. We will use both OpenAI and Anthropic models.\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ff4c1453-8cff-4679-9574-8602c530144e", - "metadata": {}, - "outputs": [], - "source": [ - "%%capture --no-stderr\n", - "%pip install -U langgraph \"langchain[anthropic,openai]\"" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "c031a059-7279-4e75-9164-58325d76242f", - "metadata": {}, - "outputs": [], - "source": [ - "import getpass\n", - "import os\n", - "\n", - "\n", - "def _set_env(var: str):\n", - " if not os.environ.get(var):\n", - " os.environ[var] = getpass.getpass(f\"{var}: \")\n", - "\n", - "\n", - "_set_env(\"ANTHROPIC_API_KEY\")\n", - "_set_env(\"OPENAI_API_KEY\")" - ] - }, - { - "cell_type": "markdown", - "id": "75ebea6f-e75f-42d4-9d32-68b37150bdde", - "metadata": {}, - "source": [ - "Build the graph:" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "a6033c2a-3b56-46f5-9c3f-79310e31e545", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "claude-3-5-haiku-20241022\n", - "gpt-4.1-mini-2025-04-14\n" - ] - } - ], - "source": [ - "from langchain.chat_models import init_chat_model\n", - "from langchain_core.runnables import RunnableConfig\n", - "from langgraph.graph import MessagesState\n", - "from langgraph.graph import END, StateGraph, START\n", - "from typing_extensions import TypedDict\n", - "\n", - "\n", - "class ConfigSchema(TypedDict):\n", - " model: str\n", - "\n", - "\n", - "MODELS = {\n", - " \"anthropic\": init_chat_model(\"anthropic:claude-3-5-haiku-latest\"),\n", - " \"openai\": init_chat_model(\"openai:gpt-4.1-mini\"),\n", - "}\n", - "\n", - "\n", - "def call_model(state: MessagesState, config: RunnableConfig):\n", - " model = config[\"configurable\"].get(\"model\", \"anthropic\")\n", - " model = MODELS[model]\n", - " response = model.invoke(state[\"messages\"])\n", - " return {\"messages\": [response]}\n", - "\n", - "\n", - "builder = StateGraph(MessagesState, config_schema=ConfigSchema)\n", - "builder.add_node(\"model\", call_model)\n", - "builder.add_edge(START, \"model\")\n", - "builder.add_edge(\"model\", END)\n", - "\n", - "graph = builder.compile()\n", - "\n", - "# Usage\n", - "input_message = {\"role\": \"user\", \"content\": \"hi\"}\n", - "# With no configuration, uses default (Anthropic)\n", - "response_1 = graph.invoke({\"messages\": [input_message]})[\"messages\"][-1]\n", - "# Or, can set OpenAI\n", - "config = {\"configurable\": {\"model\": \"openai\"}}\n", - "response_2 = graph.invoke({\"messages\": [input_message]}, config=config)[\"messages\"][-1]\n", - "\n", - "print(response_1.response_metadata[\"model_name\"])\n", - "print(response_2.response_metadata[\"model_name\"])" - ] - }, - { - "cell_type": "markdown", - "id": "bd1ac2bc-9e3e-42c4-a68f-238c841e58d1", - "metadata": {}, - "source": [ - "
\n", - "\n", - "
Extended example: specifying model and system message at runtime\n", - "\n", - "Below we demonstrate a practical example in which we configure two parameters: the LLM and system message to use at runtime.\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "367bcedd-047c-4150-a059-0a7630ab2663", - "metadata": {}, - "outputs": [], - "source": [ - "%%capture --no-stderr\n", - "%pip install -U langgraph \"langchain[anthropic,openai]\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e5d0dd7d-9564-4a5f-aa2e-2f7be20e1647", - "metadata": {}, - "outputs": [], - "source": [ - "import getpass\n", - "import os\n", - "\n", - "\n", - "def _set_env(var: str):\n", - " if not os.environ.get(var):\n", - " os.environ[var] = getpass.getpass(f\"{var}: \")\n", - "\n", - "\n", - "_set_env(\"ANTHROPIC_API_KEY\")\n", - "_set_env(\"OPENAI_API_KEY\")" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "04924627-9326-438b-aa52-91cea76f4477", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "================================\u001b[1m Human Message \u001b[0m=================================\n", - "\n", - "hi\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "\n", - "Ciao! Come posso aiutarti oggi?\n" - ] - } - ], - "source": [ - "from typing import Optional\n", - "\n", - "from langchain.chat_models import init_chat_model\n", - "from langchain_core.messages import SystemMessage\n", - "from langchain_core.runnables import RunnableConfig\n", - "from langgraph.graph import END, MessagesState, StateGraph, START\n", - "from typing_extensions import TypedDict\n", - "\n", - "\n", - "class ConfigSchema(TypedDict):\n", - " model: Optional[str]\n", - " system_message: Optional[str]\n", - "\n", - "\n", - "MODELS = {\n", - " \"anthropic\": init_chat_model(\"anthropic:claude-3-5-haiku-latest\"),\n", - " \"openai\": init_chat_model(\"openai:gpt-4.1-mini\"),\n", - "}\n", - "\n", - "\n", - "def call_model(state: MessagesState, config: RunnableConfig):\n", - " model = config[\"configurable\"].get(\"model\", \"anthropic\")\n", - " model = MODELS[model]\n", - " messages = state[\"messages\"]\n", - " if system_message := config[\"configurable\"].get(\"system_message\"):\n", - " messages = [SystemMessage(system_message)] + messages\n", - " response = model.invoke(messages)\n", - " return {\"messages\": [response]}\n", - "\n", - "\n", - "builder = StateGraph(MessagesState, config_schema=ConfigSchema)\n", - "builder.add_node(\"model\", call_model)\n", - "builder.add_edge(START, \"model\")\n", - "builder.add_edge(\"model\", END)\n", - "\n", - "graph = builder.compile()\n", - "\n", - "# Usage\n", - "input_message = {\"role\": \"user\", \"content\": \"hi\"}\n", - "config = {\"configurable\": {\"model\": \"openai\", \"system_message\": \"Respond in Italian.\"}}\n", - "response = graph.invoke({\"messages\": [input_message]}, config)\n", - "for message in response[\"messages\"]:\n", - " message.pretty_print()" - ] - }, - { - "cell_type": "markdown", - "id": "03eac38a-fca6-4baf-9ccf-94bf16321235", - "metadata": {}, - "source": [ - "
" - ] - }, - { - "cell_type": "markdown", - "id": "94715e3d-e98b-4be0-ae5f-1169cb795ce5", - "metadata": {}, - "source": [ - "## Add retry policies\n", - "\n", - "There are many use cases where you may wish for your node to have a custom retry policy, for example if you are calling an API, querying a database, or calling an LLM, etc. LangGraph lets you add retry policies to nodes.\n", - "\n", - "To configure a retry policy, pass the `retry_policy` parameter to the [add_node](https://langchain-ai.github.io/langgraph/reference/graphs/#langgraph.graph.state.StateGraph.add_node). The `retry_policy` parameter takes in a `RetryPolicy` named tuple object. Below we instantiate a `RetryPolicy` object with the default parameters and associate it with a node:\n", - "\n", - "```python\n", - "from langgraph.pregel import RetryPolicy\n", - "\n", - "builder.add_node(\n", - " \"node_name\",\n", - " node_function,\n", - " retry_policy=RetryPolicy(),\n", - ")\n", - "```" - ] - }, - { - "cell_type": "markdown", - "id": "af144b8f-761a-4456-a356-ce0812e92577", - "metadata": {}, - "source": [ - "By default, the `retry_on` parameter uses the `default_retry_on` function, which retries on any exception except for the following:\n", - "\n", - "* `ValueError`\n", - "* `TypeError`\n", - "* `ArithmeticError`\n", - "* `ImportError`\n", - "* `LookupError`\n", - "* `NameError`\n", - "* `SyntaxError`\n", - "* `RuntimeError`\n", - "* `ReferenceError`\n", - "* `StopIteration`\n", - "* `StopAsyncIteration`\n", - "* `OSError`\n", - "\n", - "In addition, for exceptions from popular http request libraries such as `requests` and `httpx` it only retries on 5xx status codes.\n", - "\n", - "
Extended example: customizing retry policies\n", - "\n", - "Consider an example in which we are reading from a SQL database. Below we pass two different retry policies to nodes:\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ad92598c-b688-42fa-aae0-9de36273d584", - "metadata": {}, - "outputs": [], - "source": [ - "import sqlite3\n", - "from typing_extensions import TypedDict\n", - "\n", - "from langchain.chat_models import init_chat_model\n", - "\n", - "from langgraph.graph import END, MessagesState, StateGraph, START\n", - "from langgraph.pregel import RetryPolicy\n", - "from langchain_community.utilities import SQLDatabase\n", - "from langchain_core.messages import AIMessage\n", - "\n", - "db = SQLDatabase.from_uri(\"sqlite:///:memory:\")\n", - "\n", - "model = init_chat_model(\"anthropic:claude-3-5-haiku-latest\")\n", - "\n", - "\n", - "def query_database(state: MessagesState):\n", - " query_result = db.run(\"SELECT * FROM Artist LIMIT 10;\")\n", - " return {\"messages\": [AIMessage(content=query_result)]}\n", - "\n", - "\n", - "def call_model(state: MessagesState):\n", - " response = model.invoke(state[\"messages\"])\n", - " return {\"messages\": [response]}\n", - "\n", - "\n", - "# Define a new graph\n", - "builder = StateGraph(MessagesState)\n", - "builder.add_node(\n", - " \"query_database\",\n", - " query_database,\n", - " retry_policy=RetryPolicy(retry_on=sqlite3.OperationalError),\n", - ")\n", - "builder.add_node(\"model\", call_model, retry_policy=RetryPolicy(max_attempts=5))\n", - "builder.add_edge(START, \"model\")\n", - "builder.add_edge(\"model\", \"query_database\")\n", - "builder.add_edge(\"query_database\", END)\n", - "\n", - "graph = builder.compile()" - ] - }, - { - "cell_type": "markdown", - "id": "068f806a", - "metadata": {}, - "source": [ - "
" - ] - }, - { - "cell_type": "markdown", - "id": "6d99d63c", - "metadata": {}, - "source": [ - "## Add node caching\n", - "\n", - "Node caching is useful in cases where you want to avoid repeating operations, like when doing something expensive (either in terms of time or cost). LangGraph lets you add individualized caching policies to nodes in a graph.\n", - "\n", - "To configure a cache policy, pass the `cache_policy` parameter to the [add_node](https://langchain-ai.github.io/langgraph/reference/graphs/#langgraph.graph.state.StateGraph.add_node) function. In the following example, a [`CachePolicy`](https://langchain-ai.github.io/langgraph/reference/types/?h=cachepolicy#langgraph.types.CachePolicy) object is instantiated with a time to live of 120 seconds and the default `key_func` generator. Then it is associated with a node:\n", - "\n", - "```python\n", - "from langgraph.types import CachePolicy\n", - "\n", - "builder.add_node(\n", - " \"node_name\",\n", - " node_function,\n", - " cache_policy=CachePolicy(ttl=120),\n", - ")\n", - "```\n", - "\n", - "Then, to enable node-level caching for a graph, set the `cache` argument when compiling the graph. The example below uses `InMemoryCache` to set up a graph with in-memory cache, but `SqliteCache` is also available.\n", - "\n", - "```python\n", - "from langgraph.cache.memory import InMemoryCache\n", - "\n", - "\n", - "graph = builder.compile(cache=InMemoryCache())\n", - "```" - ] - }, - { - "cell_type": "markdown", - "id": "e1a0213e-282f-4fad-b048-5f7465edfccb", - "metadata": {}, - "source": [ - "## Create a sequence of steps\n", - "\n", - "!!! info \"Prerequisites\"\n", - " This guide assumes familiarity with the above section on [state](#define-and-update-state).\n", - "\n", - "Here we demonstrate how to construct a simple sequence of steps. We will show:\n", - "\n", - "1. How to build a sequential graph\n", - "2. Built-in short-hand for constructing similar graphs.\n", - "\n", - "\n", - "To add a sequence of nodes, we use the `.add_node` and `.add_edge` methods of our [graph](../../concepts/low_level/#stategraph):\n", - "```python\n", - "from langgraph.graph import START, StateGraph\n", - "\n", - "builder = StateGraph(State)\n", - "\n", - "# Add nodes\n", - "builder.add_node(step_1)\n", - "builder.add_node(step_2)\n", - "builder.add_node(step_3)\n", - "\n", - "# Add edges\n", - "builder.add_edge(START, \"step_1\")\n", - "builder.add_edge(\"step_1\", \"step_2\")\n", - "builder.add_edge(\"step_2\", \"step_3\")\n", - "```\n", - "\n", - "We can also use the built-in shorthand `.add_sequence`:\n", - "```python\n", - "builder = StateGraph(State).add_sequence([step_1, step_2, step_3])\n", - "builder.add_edge(START, \"step_1\")\n", - "```\n", - "\n", - "\n", - "
\n", - "Why split application steps into a sequence with LangGraph?\n", - "\n", - "LangGraph makes it easy to add an underlying persistence layer to your application.\n", - "This allows state to be checkpointed in between the execution of nodes, so your LangGraph nodes govern:\n", - "\n", - "
    \n", - "
  • How state updates are [checkpointed](../../concepts/persistence/)
  • \n", - "
  • How interruptions are resumed in [human-in-the-loop](../../concepts/human_in_the_loop/) workflows
  • \n", - "
  • How we can \"rewind\" and branch-off executions using LangGraph's [time travel](../../concepts/time-travel/) features
  • \n", - "
\n", - "\n", - "They also determine how execution steps are [streamed](../../concepts/streaming/), and how your application is visualized\n", - "and debugged using [LangGraph Studio](../../concepts/langgraph_studio/).\n", - "\n", - "
" - ] - }, - { - "cell_type": "markdown", - "id": "518cb5d1-c60f-44d7-b348-e03b6e487098", - "metadata": {}, - "source": [ - "Let's demonstrate an end-to-end example. We will create a sequence of three steps:\n", - "\n", - "1. Populate a value in a key of the state\n", - "2. Update the same value\n", - "3. Populate a different value\n", - "\n", - "Let's first define our [state](../../concepts/low_level/#state). This governs the [schema of the graph](../../concepts/low_level/#schema), and can also specify how to apply updates. See [this section](#process-state-updates-with-reducers) for more detail.\n", - "\n", - "In our case, we will just keep track of two values:" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "aa1b04c6-2653-4ad4-a720-facc1f2906a7", - "metadata": {}, - "outputs": [], - "source": [ - "from typing_extensions import TypedDict\n", - "\n", - "\n", - "class State(TypedDict):\n", - " value_1: str\n", - " value_2: int" - ] - }, - { - "cell_type": "markdown", - "id": "6d4a8554-bc19-4bbe-a8c2-20adcfca8273", - "metadata": {}, - "source": [ - "Our [nodes](../../concepts/low_level/#nodes) are just Python functions that read our graph's state and make updates to it. The first argument to this function will always be the state:" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "c7db921a-dbfb-4039-a93b-8b2264143a3f", - "metadata": {}, - "outputs": [], - "source": [ - "def step_1(state: State):\n", - " return {\"value_1\": \"a\"}\n", - "\n", - "\n", - "def step_2(state: State):\n", - " current_value_1 = state[\"value_1\"]\n", - " return {\"value_1\": f\"{current_value_1} b\"}\n", - "\n", - "\n", - "def step_3(state: State):\n", - " return {\"value_2\": 10}" - ] - }, - { - "cell_type": "markdown", - "id": "2b454eb0-19c1-418e-a912-dc44c0c045e2", - "metadata": {}, - "source": [ - "!!! note\n", - "\n", - " Note that when issuing updates to the state, each node can just specify the value of the key it wishes to update.\n", - "\n", - "By default, this will **overwrite** the value of the corresponding key. You can also use [reducers](../../concepts/low_level/#reducers) to control how updates are processed— for example, you can append successive updates to a key instead. See [this section](#process-state-updates-with-reducers) for more detail.\n", - "\n", - "Finally, we define the graph. We use [StateGraph](../../concepts/low_level/#stategraph) to define a graph that operates on this state.\n", - "\n", - "We will then use [add_node](../../concepts/low_level/#messagesstate) and [add_edge](../../concepts/low_level/#edges) to populate our graph and define its control flow." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b02bdbcf-2bbb-4f08-b177-1a45b2a8bc6d", - "metadata": {}, - "outputs": [], - "source": [ - "from langgraph.graph import START, StateGraph\n", - "\n", - "builder = StateGraph(State)\n", - "\n", - "# Add nodes\n", - "builder.add_node(step_1)\n", - "builder.add_node(step_2)\n", - "builder.add_node(step_3)\n", - "\n", - "# Add edges\n", - "builder.add_edge(START, \"step_1\")\n", - "builder.add_edge(\"step_1\", \"step_2\")\n", - "builder.add_edge(\"step_2\", \"step_3\")" - ] - }, - { - "cell_type": "markdown", - "id": "79a696b2-ef9b-4f8d-ae83-ea674a16bab0", - "metadata": {}, - "source": [ - "!!! tip \"Specifying custom names\"\n", - "\n", - " You can specify custom names for nodes using `.add_node`:\n", - "\n", - " ```python\n", - " builder.add_node(\"my_node\", step_1)\n", - " ```" - ] - }, - { - "cell_type": "markdown", - "id": "7452c5ea-cf1b-47a5-8da0-32479c142dce", - "metadata": {}, - "source": [ - "Note that:\n", - "\n", - "- `.add_edge` takes the names of nodes, which for functions defaults to `node.__name__`.\n", - "- We must specify the entry point of the graph. For this we add an edge with the [START node](../../concepts/low_level/#start-node).\n", - "- The graph halts when there are no more nodes to execute.\n", - "\n", - "We next [compile](../../concepts/low_level/#compiling-your-graph) our graph. This provides a few basic checks on the structure of the graph (e.g., identifying orphaned nodes). If we were adding persistence to our application via a [checkpointer](../../concepts/persistence/), it would also be passed in here." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7aa2828c-0903-4775-b4ea-d62647f3bf0a", - "metadata": {}, - "outputs": [], - "source": [ - "graph = builder.compile()" - ] - }, - { - "cell_type": "markdown", - "id": "4c85772e-788c-49df-9327-11cb92f02c6a", - "metadata": {}, - "source": [ - "LangGraph provides built-in utilities for visualizing your graph. Let's inspect our sequence. See [this guide](../../how-tos/visualization) for detail on visualization." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "4162bc81-cbfd-49e3-b79f-8a97b9f417c2", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "from IPython.display import Image, display\n", - "\n", - "display(Image(graph.get_graph().draw_mermaid_png()))" - ] - }, - { - "cell_type": "markdown", - "id": "9406b427-c28c-4cd0-9f01-e5bc1f089f4c", - "metadata": {}, - "source": [ - "Let's proceed with a simple invocation:" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "3f7012ae-4f8f-4dd3-9f99-ebd179ff5fe9", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'value_1': 'a b', 'value_2': 10}" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "graph.invoke({\"value_1\": \"c\"})" - ] - }, - { - "cell_type": "markdown", - "id": "648421de-e43a-4242-8e62-afd84bc91b7e", - "metadata": {}, - "source": [ - "Note that:\n", - "\n", - "- We kicked off invocation by providing a value for a single state key. We must always provide a value for at least one key.\n", - "- The value we passed in was overwritten by the first node.\n", - "- The second node updated the value.\n", - "- The third node populated a different value." - ] - }, - { - "cell_type": "markdown", - "id": "1acdf7f1-d2f8-4863-a7f3-d5de4cc0ef28", - "metadata": {}, - "source": [ - "!!! tip \"Built-in shorthand\"\n", - "\n", - " `langgraph>=0.2.46` includes a built-in short-hand `add_sequence` for adding node sequences. You can compile the same graph as follows:\n", - "\n", - " ```python\n", - " # highlight-next-line\n", - " builder = StateGraph(State).add_sequence([step_1, step_2, step_3])\n", - " builder.add_edge(START, \"step_1\")\n", - " \n", - " graph = builder.compile()\n", - " \n", - " graph.invoke({\"value_1\": \"c\"}) \n", - " ```" - ] - }, - { - "attachments": { - "51f122de-b2ce-4c21-a5a7-c3be70c28a91.png": { - "image/png": "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LyI+CiAgICAgICAgIDxleGlmOlBpeGVsWURpbWVuc2lvbj41NDI8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+OTA0PC9leGlmOlBpeGVsWERpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6VXNlckNvbW1lbnQ+U2NyZWVuc2hvdDwvZXhpZjpVc2VyQ29tbWVudD4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+ClCweXwAAAAcaURPVAAAAAIAAAAAAAABDwAAACgAAAEPAAABDwAARV8dcCWfAABAAElEQVR4AezdB3wURfvA8UcgdAgdqaElNAEVFBSk96agf1REFJSiooAFRXxtiAooShHEBkhRULEjRTpIB0MTCC0JJEBooZcA/5mJt97mLqSQS+4uv30/8XZnd2dnvjcvnzyZ2ZmbrqlN2BBAAAEEEEAAAQQQQAABBDK9wE0EiJm+DQCAAAIIIIAAAggggAACCBgBAkQaAgIIIIAAAggggAACCCCAgBEgQKQhIIAAAggggAACCCCAAAIIGAECRBoCAggggAACCCCAAAIIIICAESBApCEggAACCCCAAAIIIIAAAggYAQJEGgICCCCAAAIIIIAAAggggIARIECkISCAAAIIIIAAAggggAACCBgBAkQaAgIIIIAAAggggAACCCCAgBEgQKQhIIAAAggggAACCCCAAAIIGAECRBoCAggggAACCCCAAAIIIICAESBApCEggAACCCCAAAIIIIAAAggYAQJEGgICCCCAAAIIIIAAAggggIARIECkISCAAAIIIIAAAggggAACCBgBAkQaAgIIIIAAAggggAACCCCAgBEgQKQhIIAAAggggAACCCCAAAIIGAECRBoCAggggAACCCCAAAIIIICAESBApCEggAACCCCAAAIIIIAAAggYAQJEGgICCCCAAAIIIIAAAggggIARIECkISCAAAIIIIAAAggggAACCBgBAkQaAgIIIIAAAggggAACCCCAgBEgQKQhIIAAAggggAACCCCAAAIIGAECRBoCAggggAACCCCAAAIIIICAESBApCEggAACCCCAAAIIIIAAAggYAQJEGgICCCCAAAIIIIAAAggggIARIECkISCAAAIIIIAAAggggAACCBgBAkQaAgIIIIAAAggggAACCCCAgBEgQKQhIIAAAggggAACCCCAAAIIGAECRBoCAggggAACCCCAAAIIIICAESBApCEggAACCCCAAAIIIIAAAggYAQJEGgICCCCAAAIIIIAAAggggIARIECkISCAAAIIIIAAAggggAACCBgBAkQaAgIIIIAAAggggAACCCCAgBEgQKQhIIAAAggggAACCCCAAAIIGAECRBoCAggggAACCCCAAAIIIICAESBApCEggAACCCCAAAIIIIAAAggYAQJEGgICCCCAAAIIIIAAAggggIARIECkISCAAAIIIIAAAggggAACCBgBAkQaAgIIIIAAAggggAACCCCAgBEgQKQhIIAAAggggAACCCCAAAIIGAECRBoCAggggAACCCCAAAIIIICAESBApCEggAACCCCAAAIIIIAAAggYAQJEGgICCCCAAAIIIIAAAggggIARIECkISCAAAIIIIAAAggggAACCBgBAkQaAgIIIIAAAggggAACCCCAgBEgQKQhIIAAAggggAACCCCAAAIIGAECRBoCAggggAACCCCAAAIIIICAESBApCEggAACCCCAAAIIIIAAAggYAQJEGgICCCCAAAIIIIAAAggggIARIECkISCAAAIIIIAAAggggAACCBgBAkQaAgIIIIAAAggggAACCCCAgBEgQKQhIIAAAggggAACCCCAAAIIGAECRBoCAggggAACCCCAAAIIIICAESBApCEggAACCCCAAAIIIIAAAggYAQJEGgICCCCAAAIIIIAAAggggIARIECkISCAAAIIIIAAAggggAACCBgBAkQaAgIIIIAAAggggAACCCCAgBEgQKQhIIAAAggggAACCCCAAAIIGAECRBoCAggggAACCCCAAAIIIICAESBApCEggAACCCCAAAIIIIAAAggYAQJEGgICCCCAAAIIIIAAAggggIARIECkISCAAAIIIIAAAggggAACCBgBAkQaAgIIIIAAAggggAACCCCAgBEgQKQhIIAAAggggAACCCCAAAIIGAECRBoCAggggAACCCCAAAIIIICAESBApCEggAACCCCAAAIIIIAAAggYAQJEGgICCCCAAAIIIIAAAggggIARIECkISCAAAIIIIAAAggggAACCBgBAkQaAgIIIIAAAggggAACCCCAgBEgQKQhIIAAAggggAACCCCAAAIIGAECRBoCAggggAACCCCAAAIIIICAESBApCEggAACCCCAAAIIIIAAAggYAQJEGgICCCCAAAIIIIAAAggggIARIECkISCAAAIIIIAAAggggAACCBgBAkQaAgIIIIAAAggggAACCCCAgBEgQKQhIIAAAggggAACCCCAAAIIGAECRBoCAggggAACCCCAAAIIIICAESBApCEggAACCCCAAAIIIIAAAggYAQJEGgICCCCAAAIIIIAAAggggIARIECkISCAAAIIIIAAAggggAACCBgBAkQaAgIIIIAAAggggAACCCCAgBEgQKQhIIAAAggggAACCCCAAAIIGAECRBoCAggggAACCCCAAAIIIICAESBApCEggAACCCCAAAIIIIAAAggYAQJEGgICCCCAAAIIIIAAAggggIARIECkISCAAAIIIIAAAggggAACCBgBAkQaAgIIIIAAAggggAACCCCAgBEgQKQhIIAAAggggAACCCCAAAIIGAECRBoCAggggAACCCCAAAIIIICAESBApCEggAACCCCAAAIIIIAAAggYAQJEGgICCCCAAAIIIIAAAggggIARIECkISCAAAIIIIAAAggggAACCBgBAkQaAgIIIIAAAggggAACCCCAgBEgQKQhIIAAAggggAACCCCAAAIIGAECRBoCAggggAACCCCAAAIIIICAESBApCEggAACCCCAAAIIIIAAAggYAQJEGgICCCCAAAIIIIAAAggggIARIECkISCAAAIIIIAAAggggAACCBgBAkQaAgIIIIAAAggggAACCCCAgBEgQKQhIIAAAggggAACCCCAAAIIGAECRBoCAggggAACCCCAAAIIIICAESBApCEggAACCCCAAAIIIIAAAggYAQJEGgICCCCAAAIIIIAAAggggIARIECkISCAAAIIIIAAAggggAACCBgBAkQaAgIIIIAAAggggAACCCCAgBEgQKQhIIAAAggggAACCCCAAAIIGAECRBoCAggggAACCCCAAAIIIICAESBApCEggAACCCCAAAIIIIAAAggYAQJEGgICCCCAAAIIIIAAAggggIARIECkISCAAAIIIIAAAggggAACCBgBAkQaAgIIIICARwXOnDkjW7ZssT2jWrVqEhgYaEvjAAEEEEAAAQQyXoAAMeO/A0qAAAII+LVA+/btXQJEXeHy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Ujl++pycOH1eTkSfl7PnzsvFC+cl5qL5MZ8XL56TwsUjpFSZslK2TBkpXz5C8uUQyZczixTKncV82llyggACCCCAAAIuCxAgugxOcQgggAACCCCAAAIIIICAVwUIEL36ZqgXAggggAACCCCAAAIIIOCyAAGiy+AUhwACCCCAAAIIIIAAAgh4VYAA0atvhnohgAACCCCAAAIIIIAAAi4LECC6DE5xCCCAAAIIIIAAAggggIBXBQgQvfpmqBcCCCCAAAIIIIAAAggg4LIAAaLL4BSHAAIIIIAAAggggAACCHhVgADRq2+GeiGAAAIIIIAAAggggAACLgsQILoMTnEIIIAAAggggAACCCCAgFcFCBC9+maoFwIIIIAAAggggAACCCDgsgABosvgFIcAAggggAACCCCAAAIIeFWAANGrb4Z6IYAAAggggAACCCCAAAIuCxAgugxOcQgggAACCCCAAAIIIICAVwUIEL36ZqgXAggggAACCCCAAAIIIOCyAAGiy+AUhwACCCCAAAIIIIAAAgh4VYAA0atvhnohgAACCCCAAAIIIIAAAi4LECC6DE5xCCCAAAIIIIAAAggggIBXBQgQvfpmqBcCCCCAAAIIIIAAAggg4LIAAaLL4BSHAAIIIIAAAggggAACCHhVgADRq2+GeiGAAAIIIIAAAggggAACLgsQILoMTnEIIIAAAggggAACCCCAgFcFCBC9+maoFwIIIIAAAggggAACCCDgsgABosvgFIcAAggggAACCCCAAAIIeFWAANGrb4Z6IYAAAggggAACCCCAAAIuCxAgugxOcQgggAACCCCAAAIIIICAVwUIEL36ZqgXAggggAACCCCAAAIIIOCyAAGiy+AUhwACCCCAAAIIIIAAAgh4VYAA0atvhnohgAACCCCAAAIIIIAAAi4LECC6DE5xCCCAAAIIIIAAAggggIBXBQgQvfpmqBcCCCCAAAIIIIAAAggg4LIAAaLL4BSHAAIIIIAAAggggAACCHhVgADRq2+GeiGAAAIIIIAAAggggAACLgsQILoMTnEIIIAAAggggAACCCCAgFcFCBC9+maoFwIIIIAAAggggAACCCDgsgABosvgFIcAAggggAACCCCAAAIIeFWAANGrb4Z6IYAAAggggAACCCCAAAIuCxAgugxOcQgggAACCCCAAAIIIICAVwUIEL36ZqgXAggggAACCCCAAAIIIOCyAAGiy+AUhwACCCCAAAIIIIAAAgh4VYAA0atvhnohgAACCCCAAAIIIIAAAi4LECC6DE5xCCCAAAIIIIAAAggggIBXBQgQvfpmqBcCCCCAAAIIIIAAAggg4LIAAaLL4BSHAAIIIIAAAggggAACCHhVgADRq2+GeiGAAAIIIIAAAggggAACLgsQILoMTnEIIIAAAggggAACCCCAgFcFCBC9+maoFwIIIIAAApaKqg4AAAVzSURBVAgggAACCCDgsgABosvgFIcAAggggAACCCCAAAIIeFWAANGrb4Z6IYAAAggggAACCCCAAAIuCxAgugxOcQgggAACCCCAAAIIIICAVwUIEL36ZqgXAggggAACCCCAAAIIIOCyAAGiy+AUhwACCCCAAAIIIIAAAgh4VYAA0atvhnohgAACCCCAAAIIIIAAAi4LECC6DE5xCCCAAAIIIIAAAggggIBXBQgQvfpmqBcCCCCAAAIIIIAAAggg4LIAAaLL4BSHAAIIIIAAAggggAACCHhVgADRq2+GeiGAAAIIIIAAAggggAACLgsQILoMTnEIIIAAAggggAACCCCAgFcFCBC9+maoFwIIIIAAAggggAACCCDgsgABosvgFIcAAggggAACCCCAAAIIeFWAANGrb4Z6IYAAAggggAACCCCAAAIuCxAgugxOcQgggAACCCCAAAIIIICAVwUIEL36ZqgXAggggAACCCCAAAIIIOCyAAGiy+AUhwACCCCAAAIIIIAAAgh4VYAA0atvhnohgAACCCCAAAIIIIAAAi4LECC6DE5xCCCAAAIIIIAAAggggIBXBQgQvfpmqBcCCCCAAAIIIIAAAggg4LIAAaLL4BSHAAIIIIAAAggggAACCHhVgADRq2+GeiGAAAIIIIAAAggggAACLgsQILoMTnEIIIAAAggggAACCCCAgFcFCBC9+maoFwIIIIAAAggggAACCCDgsgABosvgFIcAAggggAACCCCAAAIIeFWAANGrb4Z6IYAAAggggAACCCCAAAIuCxAgugxOcQgggAACCCCAAAIIIICAVwUIEL36ZqgXAggggAACCCCAAAIIIOCyAAGiy+AUhwACCCCAAAIIIIAAAgh4VYAA0atvhnohgAACCCCAAAIIIIAAAi4LECC6DE5xCCCAAAIIIIAAAggggIBXBQgQvfpmqBcCCCCAAAIIIIAAAggg4LIAAaLL4BSHAAIIIIAAAggggAACCHhVgADRq2+GeiGAAAIIIIAAAggggAACLgsQILoMTnEIIIAAAggggAACCCCAgFcFCBC9+maoFwIIIIAAAggggAACCCDgsgABosvgFIcAAggggAACCCCAAAIIeFWAANGrb4Z6IYAAAggggAACCCCAAAIuCxAgugxOcQgggAACCCCAAAIIIICAVwUIEL36ZqgXAggggAACCCCAAAIIIOCyAAGiy+AUhwACCCCAAAIIIIAAAgh4VYAA0atvhnohgAACCCCAAAIIIIAAAi4LECC6DE5xCCCAAAIIIIAAAggggIBXBQgQvfpmqBcCCCCAAAIIIIAAAggg4LIAAaLL4BSHAAIIIIAAAggggAACCHhVgADRq2+GeiGAAAIIIIAAAggggAACLgsQILoMTnEIIIAAAggggAACCCCAgFcFCBC9+maoFwIIIIAAAggggAACCCDgsgABosvgFIcAAggggAACCCCAAAIIeFWAANGrb4Z6IYAAAggggAACCCCAAAIuCxAgugxOcQgggAACCCCAAAIIIICAVwUIEL36ZqgXAggggAACCCCAAAIIIOCyAAGiy+AUhwACCCCAAAIIIIAAAgh4VYAA0atvhnohgAACCCCAAAIIIIAAAi4LECC6DE5xCCCAAAIIIIAAAggggIBXBQgQvfpmqBcCCCCAAAIIIIAAAggg4LIAAaLL4BSHAAIIIIAAAggggAACCHhVgADRq2+GeiGAAAIIIIAAAggggAACLgsQILoMTnEIIIAAAggggAACCCCAgFcFCBC9+maoFwIIIIAAAggggAACCCDgsgABosvgFIcAAggggAACCCCAAAIIeFWAANGrb4Z6IYAAAggggAACCCCAAAIuC/w/OsDdHSiHP+MAAAAASUVORK5CYII=" - } - }, - "cell_type": "markdown", - "id": "710dc4f0-1c88-4386-9e9d-fec3de6bb774", - "metadata": {}, - "source": [ - "## Create branches\n", - "\n", - "Parallel execution of nodes is essential to speed up overall graph operation. LangGraph offers native support for parallel execution of nodes, which can significantly enhance the performance of graph-based workflows. This parallelization is achieved through fan-out and fan-in mechanisms, utilizing both standard edges and [conditional_edges](https://langchain-ai.github.io/langgraph/reference/graphs/#langgraph.graph.MessageGraph.add_conditional_edges). Below are some examples showing how to add create branching dataflows that work for you. \n", - "\n", - "![Screenshot 2024-07-09 at 2.55.56 PM.png](attachment:51f122de-b2ce-4c21-a5a7-c3be70c28a91.png)" - ] - }, - { - "cell_type": "markdown", - "id": "d6c05fc4-ecd8-483f-a9fd-b1a055f922d9", - "metadata": {}, - "source": [ - "### Run graph nodes in parallel\n", - "\n", - "In this example, we fan out from `Node A` to `B and C` and then fan in to `D`. With our state, [we specify the reducer add operation](https://langchain-ai.github.io/langgraph/concepts/low_level/#reducers). This will combine or accumulate values for the specific key in the State, rather than simply overwriting the existing value. For lists, this means concatenating the new list with the existing list. See the above section on [state reducers](#process-state-updates-with-reducers) for more detail on updating state with reducers." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "09372b8b-edea-4b9d-9ec3-3d93ce1ba819", - "metadata": {}, - "outputs": [], - "source": [ - "import operator\n", - "from typing import Annotated, Any\n", - "\n", - "from typing_extensions import TypedDict\n", - "\n", - "from langgraph.graph import StateGraph, START, END\n", - "\n", - "\n", - "class State(TypedDict):\n", - " # The operator.add reducer fn makes this append-only\n", - " aggregate: Annotated[list, operator.add]\n", - "\n", - "\n", - "def a(state: State):\n", - " print(f'Adding \"A\" to {state[\"aggregate\"]}')\n", - " return {\"aggregate\": [\"A\"]}\n", - "\n", - "\n", - "def b(state: State):\n", - " print(f'Adding \"B\" to {state[\"aggregate\"]}')\n", - " return {\"aggregate\": [\"B\"]}\n", - "\n", - "\n", - "def c(state: State):\n", - " print(f'Adding \"C\" to {state[\"aggregate\"]}')\n", - " return {\"aggregate\": [\"C\"]}\n", - "\n", - "\n", - "def d(state: State):\n", - " print(f'Adding \"D\" to {state[\"aggregate\"]}')\n", - " return {\"aggregate\": [\"D\"]}\n", - "\n", - "\n", - "builder = StateGraph(State)\n", - "builder.add_node(a)\n", - "builder.add_node(b)\n", - "builder.add_node(c)\n", - "builder.add_node(d)\n", - "builder.add_edge(START, \"a\")\n", - "builder.add_edge(\"a\", \"b\")\n", - "builder.add_edge(\"a\", \"c\")\n", - "builder.add_edge(\"b\", \"d\")\n", - "builder.add_edge(\"c\", \"d\")\n", - "builder.add_edge(\"d\", END)\n", - "graph = builder.compile()" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "66f52a20", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "from IPython.display import Image, display\n", - "\n", - "display(Image(graph.get_graph().draw_mermaid_png()))" - ] - }, - { - "cell_type": "markdown", - "id": "74dd577b-0474-44c4-b4bc-9113090e3121", - "metadata": {}, - "source": [ - "With the reducer, you can see that the values added in each node are accumulated." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "81646784-5e7d-4096-980d-9fdfafd6e7a3", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Adding \"A\" to []\n", - "Adding \"B\" to ['A']\n", - "Adding \"C\" to ['A']\n", - "Adding \"D\" to ['A', 'B', 'C']\n" - ] - }, - { - "data": { - "text/plain": [ - "{'aggregate': ['A', 'B', 'C', 'D']}" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "graph.invoke({\"aggregate\": []}, {\"configurable\": {\"thread_id\": \"foo\"}})" - ] - }, - { - "cell_type": "markdown", - "id": "ea5495cf-9564-40c6-bc2d-0b2a8f72a5df", - "metadata": {}, - "source": [ - "!!! note\n", - "\n", - " In the above example, nodes `\"b\"` and `\"c\"` are executed concurrently in the same [superstep](../../concepts/low_level/#graphs). Because they are in the same step, node `\"d\"` executes after both `\"b\"` and `\"c\"` are finished.\n", - "\n", - " Importantly, updates from a parallel superstep may not be ordered consistently. If you need a consistent, predetermined ordering of updates from a parallel superstep, you should write the outputs to a separate field in the state together with a value with which to order them." - ] - }, - { - "cell_type": "markdown", - "id": "c392b3d2", - "metadata": {}, - "source": [ - "
Exception handling?\n", - "

LangGraph executes nodes within \"supersteps\", meaning that while parallel branches are executed in parallel, the entire superstep is transactional. If any of these branches raises an exception, none of the updates are applied to the state (the entire superstep errors).

\n", - "

Importantly, when using a checkpointer, results from successful nodes within a superstep are saved, and don't repeat when resumed.

\n", - " If you have error-prone (perhaps want to handle flakey API calls), LangGraph provides two ways to address this:
\n", - "
    \n", - "
  1. You can write regular python code within your node to catch and handle exceptions.
  2. \n", - "
  3. You can set a retry_policy to direct the graph to retry nodes that raise certain types of exceptions. Only failing branches are retried, so you needn't worry about performing redundant work.
  4. \n", - "

\n", - "Together, these let you perform parallel execution and fully control exception handling.\n", - "
" - ] - }, - { - "cell_type": "markdown", - "id": "48731230", - "metadata": {}, - "source": [ - "### Defer node execution\n", - "\n", - "Deferring node execution is useful when you want to delay the execution of a node until all other pending tasks are completed. This is particularly relevant when branches have different lengths, which is common in workflows like map-reduce flows.\n", - "\n", - "The above example showed how to fan-out and fan-in when each path was only one step. But what if one branch had more than one step? Let's add a node `\"b_2\"` in the `\"b\"` branch:" - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "id": "3890af2f-fb14-4569-b48d-a91db2d3f026", - "metadata": {}, - "outputs": [], - "source": [ - "import operator\n", - "from typing import Annotated, Any\n", - "\n", - "from typing_extensions import TypedDict\n", - "\n", - "from langgraph.graph import StateGraph, START, END\n", - "\n", - "\n", - "class State(TypedDict):\n", - " # The operator.add reducer fn makes this append-only\n", - " aggregate: Annotated[list, operator.add]\n", - "\n", - "\n", - "def a(state: State):\n", - " print(f'Adding \"A\" to {state[\"aggregate\"]}')\n", - " return {\"aggregate\": [\"A\"]}\n", - "\n", - "\n", - "def b(state: State):\n", - " print(f'Adding \"B\" to {state[\"aggregate\"]}')\n", - " return {\"aggregate\": [\"B\"]}\n", - "\n", - "\n", - "def b_2(state: State):\n", - " print(f'Adding \"B_2\" to {state[\"aggregate\"]}')\n", - " return {\"aggregate\": [\"B_2\"]}\n", - "\n", - "\n", - "def c(state: State):\n", - " print(f'Adding \"C\" to {state[\"aggregate\"]}')\n", - " return {\"aggregate\": [\"C\"]}\n", - "\n", - "\n", - "def d(state: State):\n", - " print(f'Adding \"D\" to {state[\"aggregate\"]}')\n", - " return {\"aggregate\": [\"D\"]}\n", - "\n", - "\n", - "builder = StateGraph(State)\n", - "builder.add_node(a)\n", - "builder.add_node(b)\n", - "builder.add_node(b_2)\n", - "builder.add_node(c)\n", - "# highlight-next-line\n", - "builder.add_node(d, defer=True)\n", - "builder.add_edge(START, \"a\")\n", - "builder.add_edge(\"a\", \"b\")\n", - "builder.add_edge(\"a\", \"c\")\n", - "builder.add_edge(\"b\", \"b_2\")\n", - "builder.add_edge(\"b_2\", \"d\")\n", - "builder.add_edge(\"c\", \"d\")\n", - "builder.add_edge(\"d\", END)\n", - "graph = builder.compile()" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "1a3508e6-bcaf-448e-bdc8-bf5701589d42", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "from IPython.display import Image, display\n", - "\n", - "display(Image(graph.get_graph().draw_mermaid_png()))" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "b510379a-b82a-4658-973e-df56caf5cd01", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Adding \"A\" to []\n", - "Adding \"B\" to ['A']\n", - "Adding \"C\" to ['A']\n", - "Adding \"B_2\" to ['A', 'B', 'C']\n", - "Adding \"D\" to ['A', 'B', 'C', 'B_2']\n" - ] - }, - { - "data": { - "text/plain": [ - "{'aggregate': ['A', 'B', 'C', 'B_2', 'D']}" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "graph.invoke({\"aggregate\": []})" - ] - }, - { - "cell_type": "markdown", - "id": "70e67ced", - "metadata": {}, - "source": [ - "In the above example, nodes `\"b\"` and `\"c\"` are executed concurrently in the same superstep. We set `defer=True` on node `d` so it will not execute until all pending tasks are finished. In this case, this means that `\"d\"` waits to execute until the entire `\"b\"` branch is finished." - ] - }, - { - "cell_type": "markdown", - "id": "1a940eec-f36f-4236-9cc8-8d5dfd5cc860", - "metadata": {}, - "source": [ - "### Conditional branching\n", - "\n", - "If your fan-out should vary at runtime based on the state, you can use [add_conditional_edges](https://langchain-ai.github.io/langgraph/reference/graphs/#langgraph.graph.StateGraph.add_conditional_edges) to select one or more paths using the graph state. See example below, where node `a` generates a state update that determines the following node." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "8b270199-f07d-4831-9674-f18715fa26de", - "metadata": {}, - "outputs": [], - "source": [ - "import operator\n", - "from typing import Annotated, Literal, Sequence\n", - "\n", - "from typing_extensions import TypedDict\n", - "\n", - "from langgraph.graph import StateGraph, START, END\n", - "\n", - "\n", - "class State(TypedDict):\n", - " aggregate: Annotated[list, operator.add]\n", - " # Add a key to the state. We will set this key to determine\n", - " # how we branch.\n", - " which: str\n", - "\n", - "\n", - "def a(state: State):\n", - " print(f'Adding \"A\" to {state[\"aggregate\"]}')\n", - " # highlight-next-line\n", - " return {\"aggregate\": [\"A\"], \"which\": \"c\"}\n", - "\n", - "\n", - "def b(state: State):\n", - " print(f'Adding \"B\" to {state[\"aggregate\"]}')\n", - " return {\"aggregate\": [\"B\"]}\n", - "\n", - "\n", - "def c(state: State):\n", - " print(f'Adding \"C\" to {state[\"aggregate\"]}')\n", - " return {\"aggregate\": [\"C\"]}\n", - "\n", - "\n", - "builder = StateGraph(State)\n", - "builder.add_node(a)\n", - "builder.add_node(b)\n", - "builder.add_node(c)\n", - "builder.add_edge(START, \"a\")\n", - "builder.add_edge(\"b\", END)\n", - "builder.add_edge(\"c\", END)\n", - "\n", - "\n", - "def conditional_edge(state: State) -> Literal[\"b\", \"c\"]:\n", - " # Fill in arbitrary logic here that uses the state\n", - " # to determine the next node\n", - " return state[\"which\"]\n", - "\n", - "\n", - "# highlight-next-line\n", - "builder.add_conditional_edges(\"a\", conditional_edge)\n", - "\n", - "graph = builder.compile()" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "43999312-0198-49e4-86a9-4f71e343ed64", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "from IPython.display import Image, display\n", - "\n", - "display(Image(graph.get_graph().draw_mermaid_png()))" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "c6e92bf6-5ee8-4a5a-8693-a0e028b73e3b", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Adding \"A\" to []\n", - "Adding \"C\" to ['A']\n", - "{'aggregate': ['A', 'C'], 'which': 'c'}\n" - ] - } - ], - "source": [ - "result = graph.invoke({\"aggregate\": []})\n", - "print(result)" - ] - }, - { - "cell_type": "markdown", - "id": "b1c54e61-393d-4359-88e2-6117a6022ce3", - "metadata": {}, - "source": [ - "!!! tip\n", - "\n", - " Your conditional edges can route to multiple destination nodes. For example:\n", - "\n", - " ```python\n", - " def route_bc_or_cd(state: State) -> Sequence[str]:\n", - " if state[\"which\"] == \"cd\":\n", - " return [\"c\", \"d\"]\n", - " return [\"b\", \"c\"]\n", - " ```" - ] - }, - { - "attachments": { - "f0038a5c-08d9-4eff-a1cb-d1ee4dde4fe5.png": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAABXIAAAExCAYAAADRMVpJAAABXWlDQ1BJQ0MgUHJvZmlsZQAAKJF1kD1Lw3AQxp9oS0EDFnUQ6hDoJFQpbcRBCtZaXyBDaC21gkOa1lboy98kIm7i4hcQv4BQ3B3q4ODkLAgKguDqLARBS7x/o6ZVvON4fjzcHccBA6LGWM0HoN6wjMzKorRR2JQCL/BTBillTTdZUlUVasG39od9D4Hr3TTfpa2ehd4ux+ZCN+JTdjd89Le/L4ZKZVMn/aCSdWZYgBAlVvctxvmQeNygo4hPOFdcPudcdPmq27OeSRHfEgf1qlYifiaOFHv8Sg/Xa3v61w38erHcyGVJJ6gmsYQ0FEoJOcQhI4ZZ5JH+Z0buzqTQBMMBDOyggiosmk6Sw1BDmXgNDeiYQYQ4hijfyX/9+4eed0yayBMseJ5SAC6awGjL88JbwMg8cL3MNEP7+axg+8zteMzl4TbgP3WcV9oXmAI6D47z3nacTgsYfKRZ+xN5zGEwOHUGjgAAAFZlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA5KGAAcAAAASAAAARKACAAQAAAABAAAFcqADAAQAAAABAAABMQAAAABBU0NJSQAAAFNjcmVlbnNob3S9u+miAAAB12lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNi4wLjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczpleGlmPSJodHRwOi8vbnMuYWRvYmUuY29tL2V4aWYvMS4wLyI+CiAgICAgICAgIDxleGlmOlBpeGVsWURpbWVuc2lvbj4zMDU8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+MTM5NDwvZXhpZjpQaXhlbFhEaW1lbnNpb24+CiAgICAgICAgIDxleGlmOlVzZXJDb21tZW50PlNjcmVlbnNob3Q8L2V4aWY6VXNlckNvbW1lbnQ+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgqn9EX7AABAAElEQVR4AeydB4BVxfnFz/beCyxLWXqXJihYwB4xdqNGjcYaY0xMYokaW9QY/zExRZMYE02MGrvYS1CkSJPey9J3l+299//55vGWB1IWWHB3OQO77+0tc2d+d+69M+d+831+zUxQEgEREAEREAEREAEREAEREAEREAEREAEREAEREAERaLcE/NttyVQwERABERABERABERABERABERABERABERABERABERABR0BCrhqCCIiACIiACIiACIiACIiACIiACIiACIiACIiACLRzAhJy2/kJUvFEQAREQAREQAREQAREQAREQAREQAREQAREQAREQEKu2oAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAItHMCEnLb+QlS8URABERABERABERABERABERABERABERABERABERAQq7agAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAi0cwISctv5CVLxREAEREAEREAEREAEREAEREAEREAEREAEREAEREBCrtqACIiACIiACIiACIiACIiACIiACIiACIiACIiACLRzAhJy2/kJUvFEQAREQAREQAREQAREQAREQAREQAREQAREQAREQEKu2oAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAItHMCEnLb+QlS8URABERABERABERABERABERABERABERABERABERAQq7agAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAi0cwISctv5CVLxREAEREAEREAEREAEREAEREAEREAEREAEREAEREBCrtqACIiACIiACIiACIiACIiACIiACIiACIiACIiACLRzAhJy2/kJUvFEQAREQAREQAREQAREQAREQAREQAREQAREQAREQEKu2oAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAItHMCEnLb+QlS8URABERABERABERABERABERABERABERABERABERAQq7agAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAi0cwISctv5CVLxREAEREAEREAEREAEREAEREAEREAEREAEREAEREBCrtqACIiACIiACIiACIiACIiACIiACIiACIiACIiACLRzAhJy2/kJUvFEQAREQAREQAREQAREQAREQAREQAREQAREQAREQEKu2oAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAItHMCEnLb+QlS8URABERABERABERABERABERABERABERABERABERAQq7agAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAi0cwISctv5CVLxREAEREAEREAEREAEREAEREAEREAEREAEREAEREBCrtqACIiACIiACIiACIiACIiACIiACIiACIiACIiACLRzAhJy2/kJUvFEQAREQAREQAREQAREQAREQAREQAREQAREQAREQEKu2oAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAItHMCEnLb+QlS8URABERABERABERABERABERABERABERABERABERAQq7agAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAi0cwISctv5CVLxREAEREAEREAEREAEREAEREAEREAEREAEREAEREBCrtqACIiACIiACIiACIiACIiACIiACIiACIiACIiACLRzAhJy2/kJUvFEQAREQAREQAREQAREQAREQAREQAREQAREQAREQEKu2oAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAItHMCEnLb+QlS8URABERABERABERABERABERABERABERABERABERAQq7agAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAi0cwISctv5CVLxREAEREAEREAEREAEREAEREAEREAEREAEREAEREBCrtqACIiACIiACIiACIiACIiACIiACIiACIiACIiACLRzAhJy2/kJUvFEQAREQAREQAREQAREQAREQAREQAREQAREQAREQEKu2oAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAItHMCEnLb+QlS8URABERABERABERABERABERABERABERABERABERAQq7agAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAi0cwISctv5CVLxREAEREAEREAEREAEREAEREAEREAEREAEREAEREBCrtqACIiACIiACIiACIiACIiACIiACIiACIiACIiACLRzAhJy2/kJUvFEQAREQAQOH4H60lKULFqA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iIAIiEDHJCAht2OeN5VaBERABNoPAYq5jbQu3fz0H1G1KR3D//ws/IJswkdrLFbbTzUOa0nIyKyXze1EU00N+QQxIFrQfl0zHNYyKXMREAEREAEREAEREAEREAEREIEORUBCboc6XSqsCIiACLRfAs1NTQxO1kCB0gKYKYmACIiACIiACIhAxyOwOacSm7IrMXZgPKLD5Ymw451BlVgEREAEOjcBzXvt3OdXtRMBERCBI0bAz99fIu4Ro60DiYAIiIAIiIAItDWB+oYm/OXtdXjw74vdZyODliqJgAiIgAiIQHsiICG3PZ0NlUUEREAEREAEREAEREAEREAEROAbIWBCbnpGORobGcw1qwIScr+R06CDioAIiIAI7IOAhNx9wNEqERABERABERABERABERABERCBzk/AbG9NuC0uqYV9r6OoqyQCIiACIiAC7Y2AhNz2dkZUHhEQAREQAREQAREQAREQAREQgSNLgOrt1rxqirkeAbemttFilCqJgAiIgAiIQLsiICG3XZ0OFUYEREAEREAEREAEREAEREAEROBIE2imHe6MFfnOGteOXVldTyFXSu6RPg86ngiIgAiIwL4JSMjdNx+tFQEREAEREAEREAEREAEREAER6OwEqNl+tbqgRbwNCPSHn19nr7TqJwIiIAIi0NEISMjtaGdM5RUBERABERABERABERABERABEWhzArl5VS3uFCLDguDHf0oiIAIiIAIi0J4IBLanwqgsIiACIiACIiACIiACIiACIiACRzcB82hgrg48Mirl1COgp5oThaqaBgfejhcbSSH3CBz36D7Tqr0IiIAIiMCBEpCQe6DEtL0IiIAIiIAIiIAIiIAIiIAIiECbEzABt7a+EQs2lGBrbiWC6d6gb0oEhvaMRkhQwF6FVa/w2+LglgKsWdMeqBDb2OAJdGYV6xoXCn//tlNyD7aMB7tfm58cZSgCIiACItAuCEjIbRenQYUQAREQAREQAREQAREQAREQgaObwLrMctz796XIzqvYBURMdAiuO6cfzhyXgtiIoF3WNVHpXLy+GG/NysTaraVmyothfWJx1tgUTBiasFcxtoaCcRN127DgnQJxU7NHyPWjAty/RzT8dyjBJqbmldQghNvGhB+4pW5VbSP97xbikwXZWLK+CMFB/hjUKwbfP6s3BqftPM4uFeMf9RSWV20pw9tf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" - } - }, - "cell_type": "markdown", - "id": "931a0f15-b8d2-4ff6-8772-fd99f708a099", - "metadata": {}, - "source": [ - "### Map-reduce and the `Send` API\n", - "\n", - "By default, `Nodes` and `Edges` are defined ahead of time and operate on the same shared state. However, there can be cases where the exact edges are not known ahead of time and/or you may want different versions of state to exist at the same time. A common example of this is with map-reduce design patterns. In this design pattern, a first node may generate a list of objects, and you may want to apply some other node to all those objects. The number of objects may be unknown ahead of time (meaning the number of edges may not be known) and the input state to the downstream `Node` should be different (one for each generated object).\n", - "\n", - "To support this design pattern, LangGraph supports returning [Send](/langgraph/reference/types/#langgraph.types.Send) objects from conditional edges. `Send` takes two arguments: first is the name of the node, and second is the state to pass to that node.\n", - "\n", - "```python\n", - "def continue_to_jokes(state: OverallState):\n", - " return [Send(\"generate_joke\", {\"subject\": s}) for s in state['subjects']]\n", - "\n", - "graph.add_conditional_edges(\"node_a\", continue_to_jokes)\n", - "```\n", - "\n", - "Below we implement a simple example, where we simulate using LLMs to (1) generate a list of subjects (the length of which is unknown ahead of time), (2) generate jokes in parallel, and (3) select a \"best\" joke. Importantly, the input state to the fan-out nodes is different than the graph's overall state.\n", - "\n", - "![Screenshot 2025-05-05 at 4.21.35 PM.png](attachment:f0038a5c-08d9-4eff-a1cb-d1ee4dde4fe5.png)" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "8b971a9c-337a-4899-bcf7-080193832935", - "metadata": {}, - "outputs": [], - "source": [ - "import operator\n", - "from typing import Annotated\n", - "from typing_extensions import TypedDict\n", - "\n", - "from langgraph.types import Send\n", - "from langgraph.graph import END, StateGraph, START\n", - "\n", - "\n", - "# This will be the overall state of the main graph.\n", - "# It will contain a topic (which we expect the user to provide)\n", - "# and then will generate a list of subjects, and then a joke for\n", - "# each subject\n", - "class OverallState(TypedDict):\n", - " topic: str\n", - " subjects: list\n", - " # Notice here we use the operator.add\n", - " # This is because we want combine all the jokes we generate\n", - " # from individual nodes back into one list - this is essentially\n", - " # the \"reduce\" part\n", - " jokes: Annotated[list, operator.add]\n", - " best_selected_joke: str\n", - "\n", - "\n", - "# This will be the state of the node that we will \"map\" all\n", - "# subjects to in order to generate a joke\n", - "class JokeState(TypedDict):\n", - " subject: str\n", - "\n", - "\n", - "# This is the function we will use to generate the subjects of the jokes.\n", - "# In general the length of the list generated by this node could vary each run.\n", - "def generate_topics(state: OverallState):\n", - " # Simulate a LLM.\n", - " return {\"subjects\": [\"lions\", \"elephants\", \"penguins\"]}\n", - "\n", - "\n", - "# Here we generate a joke, given a subject\n", - "def generate_joke(state: JokeState):\n", - " # Simulate a LLM.\n", - " joke_map = {\n", - " \"lions\": \"Why don't lions like fast food? Because they can't catch it!\",\n", - " \"elephants\": \"Why don't elephants use computers? They're afraid of the mouse!\",\n", - " \"penguins\": (\n", - " \"Why don’t penguins like talking to strangers at parties? \"\n", - " \"Because they find it hard to break the ice.\"\n", - " ),\n", - " }\n", - " return {\"jokes\": [joke_map[state[\"subject\"]]]}\n", - "\n", - "\n", - "# Here we define the logic to map out over the generated subjects\n", - "# We will use this as an edge in the graph\n", - "def continue_to_jokes(state: OverallState):\n", - " # We will return a list of `Send` objects\n", - " # Each `Send` object consists of the name of a node in the graph\n", - " # as well as the state to send to that node\n", - " return [Send(\"generate_joke\", {\"subject\": s}) for s in state[\"subjects\"]]\n", - "\n", - "\n", - "# Here we will judge the best joke\n", - "def best_joke(state: OverallState):\n", - " return {\"best_selected_joke\": \"penguins\"}\n", - "\n", - "\n", - "# Construct the graph: here we put everything together to construct our graph\n", - "builder = StateGraph(OverallState)\n", - "builder.add_node(\"generate_topics\", generate_topics)\n", - "builder.add_node(\"generate_joke\", generate_joke)\n", - "builder.add_node(\"best_joke\", best_joke)\n", - "builder.add_edge(START, \"generate_topics\")\n", - "builder.add_conditional_edges(\"generate_topics\", continue_to_jokes, [\"generate_joke\"])\n", - "builder.add_edge(\"generate_joke\", \"best_joke\")\n", - "builder.add_edge(\"best_joke\", END)\n", - "graph = builder.compile()" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "2760846f-a297-455c-a07c-155743f5e55f", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "from IPython.display import Image, display\n", - "\n", - "display(Image(graph.get_graph().draw_mermaid_png()))" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "cd91131a-b640-4604-9b48-b6cb5207be31", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'generate_topics': {'subjects': ['lions', 'elephants', 'penguins']}}\n", - "{'generate_joke': {'jokes': [\"Why don't lions like fast food? Because they can't catch it!\"]}}\n", - "{'generate_joke': {'jokes': [\"Why don't elephants use computers? They're afraid of the mouse!\"]}}\n", - "{'generate_joke': {'jokes': ['Why don’t penguins like talking to strangers at parties? Because they find it hard to break the ice.']}}\n", - "{'best_joke': {'best_selected_joke': 'penguins'}}\n" - ] - } - ], - "source": [ - "# Call the graph: here we call it to generate a list of jokes\n", - "for step in graph.stream({\"topic\": \"animals\"}):\n", - " print(step)" - ] - }, - { - "cell_type": "markdown", - "id": "4c505843-5449-4e9b-8ad4-27b88a987cc4", - "metadata": {}, - "source": [ - "## Create and control loops\n", - "\n", - "When creating a graph with a loop, we require a mechanism for terminating execution. This is most commonly done by adding a [conditional edge](../../concepts/low_level/#conditional-edges) that routes to the [END](../../concepts/low_level/#end-node) node once we reach some termination condition.\n", - "\n", - "You can also set the graph recursion limit when invoking or streaming the graph. The recursion limit sets the number of [supersteps](../../concepts/low_level/#graphs) that the graph is allowed to execute before it raises an error. Read more about the concept of recursion limits [here](../../concepts/low_level/#recursion-limit). \n", - "\n", - "Let's consider a simple graph with a loop to better understand how these mechanisms work.\n", - "\n", - "!!! tip\n", - "\n", - " To return the last value of your state instead of receiving a recursion limit error, see the [next section](#impose-a-recursion-limit).\n", - "\n", - "When creating a loop, you can include a conditional edge that specifies a termination condition:\n", - "```python\n", - "builder = StateGraph(State)\n", - "builder.add_node(a)\n", - "builder.add_node(b)\n", - "\n", - "def route(state: State) -> Literal[\"b\", END]:\n", - " if termination_condition(state):\n", - " return END\n", - " else:\n", - " return \"b\"\n", - "\n", - "builder.add_edge(START, \"a\")\n", - "builder.add_conditional_edges(\"a\", route)\n", - "builder.add_edge(\"b\", \"a\")\n", - "graph = builder.compile()\n", - "```\n", - "\n", - "To control the recursion limit, specify `\"recursion_limit\"` in the config. This will raise a `GraphRecursionError`, which you can catch and handle:\n", - "```python\n", - "from langgraph.errors import GraphRecursionError\n", - "\n", - "try:\n", - " graph.invoke(inputs, {\"recursion_limit\": 3})\n", - "except GraphRecursionError:\n", - " print(\"Recursion Error\")\n", - "```" - ] - }, - { - "cell_type": "markdown", - "id": "2de7cdff-3811-4d19-b93b-7b8dfbbdb4f1", - "metadata": {}, - "source": [ - "Let's define a graph with a simple loop. Note that we use a conditional edge to implement a termination condition." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "f087c028-b115-42a0-a85d-f53d96223720", - "metadata": {}, - "outputs": [], - "source": [ - "import operator\n", - "from typing import Annotated, Literal\n", - "\n", - "from typing_extensions import TypedDict\n", - "\n", - "from langgraph.graph import StateGraph, START, END\n", - "\n", - "\n", - "class State(TypedDict):\n", - " # The operator.add reducer fn makes this append-only\n", - " aggregate: Annotated[list, operator.add]\n", - "\n", - "\n", - "def a(state: State):\n", - " print(f'Node A sees {state[\"aggregate\"]}')\n", - " return {\"aggregate\": [\"A\"]}\n", - "\n", - "\n", - "def b(state: State):\n", - " print(f'Node B sees {state[\"aggregate\"]}')\n", - " return {\"aggregate\": [\"B\"]}\n", - "\n", - "\n", - "# Define nodes\n", - "builder = StateGraph(State)\n", - "builder.add_node(a)\n", - "builder.add_node(b)\n", - "\n", - "\n", - "# Define edges\n", - "def route(state: State) -> Literal[\"b\", END]:\n", - " if len(state[\"aggregate\"]) < 7:\n", - " return \"b\"\n", - " else:\n", - " return END\n", - "\n", - "\n", - "builder.add_edge(START, \"a\")\n", - "builder.add_conditional_edges(\"a\", route)\n", - "builder.add_edge(\"b\", \"a\")\n", - "graph = builder.compile()" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "c468e5b2-a1dd-4fac-84a9-9eb212a09752", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "from IPython.display import Image, display\n", - "\n", - "display(Image(graph.get_graph().draw_mermaid_png()))" - ] - }, - { - "cell_type": "markdown", - "id": "255d288a-6e17-4f34-babe-0c6cf1e09a6f", - "metadata": {}, - "source": [ - "This architecture is similar to a [ReAct agent](../../agents/overview) in which node `\"a\"` is a tool-calling model, and node `\"b\"` represents the tools.\n", - "\n", - "In our `route` conditional edge, we specify that we should end after the `\"aggregate\"` list in the state passes a threshold length.\n", - "\n", - "Invoking the graph, we see that we alternate between nodes `\"a\"` and `\"b\"` before terminating once we reach the termination condition." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "83c759be-9bb7-4f96-8b79-028fe1ebb45f", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Node A sees []\n", - "Node B sees ['A']\n", - "Node A sees ['A', 'B']\n", - "Node B sees ['A', 'B', 'A']\n", - "Node A sees ['A', 'B', 'A', 'B']\n", - "Node B sees ['A', 'B', 'A', 'B', 'A']\n", - "Node A sees ['A', 'B', 'A', 'B', 'A', 'B']\n" - ] - }, - { - "data": { - "text/plain": [ - "{'aggregate': ['A', 'B', 'A', 'B', 'A', 'B', 'A']}" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "graph.invoke({\"aggregate\": []})" - ] - }, - { - "cell_type": "markdown", - "id": "8c596264-9a36-4c52-ba7d-9fa5dcb3467d", - "metadata": {}, - "source": [ - "### Impose a recursion limit\n", - "\n", - "In some applications, we may not have a guarantee that we will reach a given termination condition. In these cases, we can set the graph's [recursion limit](../../concepts/low_level/#recursion-limit). This will raise a `GraphRecursionError` after a given number of [supersteps](../../concepts/low_level/#graphs). We can then catch and handle this exception:" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "f7526e3c-357c-4eba-b101-751418523672", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Node A sees []\n", - "Node B sees ['A']\n", - "Node A sees ['A', 'B']\n", - "Node B sees ['A', 'B', 'A']\n", - "Recursion Error\n" - ] - } - ], - "source": [ - "from langgraph.errors import GraphRecursionError\n", - "\n", - "try:\n", - " graph.invoke({\"aggregate\": []}, {\"recursion_limit\": 4})\n", - "except GraphRecursionError:\n", - " print(\"Recursion Error\")" - ] - }, - { - "cell_type": "markdown", - "id": "0793b71a-fd92-4284-8d58-cc10f49872f6", - "metadata": {}, - "source": [ - "Note that this time we terminate after the fourth step. The default recursion limit is 25.\n", - "\n", - "
Extended example: return state on hitting recursion limit\n", - "\n", - "Instead of raising GraphRecursionError, we can introduce a new key to the state that keeps track of the number of steps remaining until reaching the recursion limit. We can then use this key to determine if we should end the run.\n", - "\n", - "LangGraph implements a special RemainingSteps annotation. Under the hood, it creates a ManagedValue channel -- a state channel that will exist for the duration of our graph run and no longer.\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "7fe57f1a-ab55-45ed-b229-8f29fc3da05b", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Node A sees []\n", - "Node B sees ['A']\n", - "Node A sees ['A', 'B']\n", - "{'aggregate': ['A', 'B', 'A']}\n" - ] - } - ], - "source": [ - "import operator\n", - "from typing import Annotated, Literal\n", - "\n", - "from typing_extensions import TypedDict\n", - "\n", - "from langgraph.graph import StateGraph, START, END\n", - "\n", - "# highlight-next-line\n", - "from langgraph.managed.is_last_step import RemainingSteps\n", - "\n", - "\n", - "class State(TypedDict):\n", - " # The operator.add reducer fn makes this append-only\n", - " aggregate: Annotated[list, operator.add]\n", - " # highlight-next-line\n", - " remaining_steps: RemainingSteps\n", - "\n", - "\n", - "def a(state: State):\n", - " print(f'Node A sees {state[\"aggregate\"]}')\n", - " return {\"aggregate\": [\"A\"]}\n", - "\n", - "\n", - "def b(state: State):\n", - " print(f'Node B sees {state[\"aggregate\"]}')\n", - " return {\"aggregate\": [\"B\"]}\n", - "\n", - "\n", - "# Define nodes\n", - "builder = StateGraph(State)\n", - "builder.add_node(a)\n", - "builder.add_node(b)\n", - "\n", - "\n", - "# Define edges\n", - "def route(state: State) -> Literal[\"b\", END]:\n", - " # highlight-next-line\n", - " if state[\"remaining_steps\"] <= 2:\n", - " return END\n", - " else:\n", - " return \"b\"\n", - "\n", - "\n", - "builder.add_edge(START, \"a\")\n", - "builder.add_conditional_edges(\"a\", route)\n", - "builder.add_edge(\"b\", \"a\")\n", - "graph = builder.compile()\n", - "\n", - "# Test it out\n", - "result = graph.invoke({\"aggregate\": []}, {\"recursion_limit\": 4})\n", - "print(result)" - ] - }, - { - "cell_type": "markdown", - "id": "6c9e1818-079a-41bb-aed0-2bf993ca943f", - "metadata": {}, - "source": [ - "
" - ] - }, - { - "cell_type": "markdown", - "id": "308d93f4-6e78-411d-82de-78eac230e44d", - "metadata": {}, - "source": [ - "
Extended example: loops with branches\n", - "\n", - "To better understand how the recursion limit works, let's consider a more complex example. Below we implement a loop, but one step fans out into two nodes:\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "258d8613-8572-407a-941a-2ac50b8f1c3e", - "metadata": {}, - "outputs": [], - "source": [ - "import operator\n", - "from typing import Annotated, Literal\n", - "\n", - "from typing_extensions import TypedDict\n", - "\n", - "from langgraph.graph import StateGraph, START, END\n", - "\n", - "\n", - "class State(TypedDict):\n", - " aggregate: Annotated[list, operator.add]\n", - "\n", - "\n", - "def a(state: State):\n", - " print(f'Node A sees {state[\"aggregate\"]}')\n", - " return {\"aggregate\": [\"A\"]}\n", - "\n", - "\n", - "def b(state: State):\n", - " print(f'Node B sees {state[\"aggregate\"]}')\n", - " return {\"aggregate\": [\"B\"]}\n", - "\n", - "\n", - "def c(state: State):\n", - " print(f'Node C sees {state[\"aggregate\"]}')\n", - " return {\"aggregate\": [\"C\"]}\n", - "\n", - "\n", - "def d(state: State):\n", - " print(f'Node D sees {state[\"aggregate\"]}')\n", - " return {\"aggregate\": [\"D\"]}\n", - "\n", - "\n", - "# Define nodes\n", - "builder = StateGraph(State)\n", - "builder.add_node(a)\n", - "builder.add_node(b)\n", - "builder.add_node(c)\n", - "builder.add_node(d)\n", - "\n", - "\n", - "# Define edges\n", - "def route(state: State) -> Literal[\"b\", END]:\n", - " if len(state[\"aggregate\"]) < 7:\n", - " return \"b\"\n", - " else:\n", - " return END\n", - "\n", - "\n", - "builder.add_edge(START, \"a\")\n", - "builder.add_conditional_edges(\"a\", route)\n", - "builder.add_edge(\"b\", \"c\")\n", - "builder.add_edge(\"b\", \"d\")\n", - "builder.add_edge([\"c\", \"d\"], \"a\")\n", - "graph = builder.compile()" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "bdb2a545-3f1f-408b-8aa3-3702d37eedf8", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "from IPython.display import Image, display\n", - "\n", - "display(Image(graph.get_graph().draw_mermaid_png()))" - ] - }, - { - "cell_type": "markdown", - "id": "a1d4cc42-590c-4de9-9e51-0bb8a79db86f", - "metadata": {}, - "source": [ - "This graph looks complex, but can be conceptualized as loop of [supersteps](../../concepts/low_level/#graphs):\n", - "\n", - "1. Node A\n", - "2. Node B\n", - "3. Nodes C and D\n", - "4. Node A\n", - "5. ...\n", - "\n", - "We have a loop of four supersteps, where nodes C and D are executed concurrently.\n", - "\n", - "Invoking the graph as before, we see that we complete two full \"laps\" before hitting the termination condition:" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "d5c692d0-9a69-4743-bd47-e462adab8700", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Node A sees []\n", - "Node B sees ['A']\n", - "Node D sees ['A', 'B']\n", - "Node C sees ['A', 'B']\n", - "Node A sees ['A', 'B', 'C', 'D']\n", - "Node B sees ['A', 'B', 'C', 'D', 'A']\n", - "Node D sees ['A', 'B', 'C', 'D', 'A', 'B']\n", - "Node C sees ['A', 'B', 'C', 'D', 'A', 'B']\n", - "Node A sees ['A', 'B', 'C', 'D', 'A', 'B', 'C', 'D']\n" - ] - } - ], - "source": [ - "result = graph.invoke({\"aggregate\": []})" - ] - }, - { - "cell_type": "markdown", - "id": "42cb9253-93a9-4a33-b4fb-a235aa41d655", - "metadata": {}, - "source": [ - "However, if we set the recursion limit to four, we only complete one lap because each lap is four supersteps:" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "d0ff64b3-eb78-48a4-aab5-bb78499f92df", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Node A sees []\n", - "Node B sees ['A']\n", - "Node C sees ['A', 'B']\n", - "Node D sees ['A', 'B']\n", - "Node A sees ['A', 'B', 'C', 'D']\n", - "Recursion Error\n" - ] - } - ], - "source": [ - "from langgraph.errors import GraphRecursionError\n", - "\n", - "try:\n", - " result = graph.invoke({\"aggregate\": []}, {\"recursion_limit\": 4})\n", - "except GraphRecursionError:\n", - " print(\"Recursion Error\")" - ] - }, - { - "cell_type": "markdown", - "id": "13579366-69fb-4aa4-9d95-a9865c1d5799", - "metadata": {}, - "source": [ - "
" - ] - }, - { - "cell_type": "markdown", - "id": "5a2d23ae-ea3f-478b-8db6-791cd29cfb6c", - "metadata": {}, - "source": [ - "## Async\n", - "\n", - "Using the [async](https://docs.python.org/3/library/asyncio.html) programming paradigm can produce significant performance improvements when running [IO-bound](https://en.wikipedia.org/wiki/I/O_bound) code concurrently (e.g., making concurrent API requests to a chat model provider).\n", - "\n", - "To convert a `sync` implementation of the graph to an `async` implementation, you will need to:\n", - "\n", - "1. Update `nodes` use `async def` instead of `def`.\n", - "2. Update the code inside to use `await` appropriately.\n", - "3. Invoke the graph with `.ainvoke` or `.astream` as desired.\n", - "\n", - "Because many LangChain objects implement the [Runnable Protocol](https://python.langchain.com/docs/expression_language/interface/) which has `async` variants of all the `sync` methods it's typically fairly quick to upgrade a `sync` graph to an `async` graph.\n", - "\n", - "See example below. To demonstrate async invocations of underlying LLMs, we will include a chat model:\n", - "\n", - "{!snippets/chat_model_tabs.md!}\n", - "\n", - "```python\n", - "from langchain.chat_models import init_chat_model\n", - "from langgraph.graph import MessagesState, StateGraph\n", - "\n", - "\n", - "# highlight-next-line\n", - "async def node(state: MessagesState): # (1)!\n", - " # highlight-next-line\n", - " new_message = await llm.ainvoke(state[\"messages\"]) # (2)!\n", - " return {\"messages\": [new_message]}\n", - "\n", - "\n", - "builder = StateGraph(MessagesState).add_node(node).set_entry_point(\"node\")\n", - "graph = builder.compile()\n", - "\n", - "input_message = {\"role\": \"user\", \"content\": \"Hello\"}\n", - "# highlight-next-line\n", - "result = await graph.ainvoke({\"messages\": [input_message]}) # (3)!\n", - "```\n", - "\n", - "1. Declare nodes to be async functions.\n", - "2. Use async invocations when available within the node.\n", - "3. Use async invocations on the graph object itself.\n", - "\n", - "!!! tip \"Async streaming\"\n", - " See the [streaming guide](../../how-tos/streaming) for examples of streaming with async." - ] - }, - { - "cell_type": "markdown", - "id": "d33ecddc-6818-41a3-9d0d-b1b1cbcd286d", - "metadata": {}, - "source": [ - "## Combine control flow and state updates with `Command`" - ] - }, - { - "cell_type": "markdown", - "id": "7c0a8d03-80b4-47fd-9b17-e26aa9b081f3", - "metadata": {}, - "source": [ - "It can be useful to combine control flow (edges) and state updates (nodes). For example, you might want to BOTH perform state updates AND decide which node to go to next in the SAME node. LangGraph provides a way to do so by returning a [Command](/langgraph/reference/types/#langgraph.types.Command) object from node functions:\n", - "\n", - "```python\n", - "def my_node(state: State) -> Command[Literal[\"my_other_node\"]]:\n", - " return Command(\n", - " # state update\n", - " update={\"foo\": \"bar\"},\n", - " # control flow\n", - " goto=\"my_other_node\"\n", - " )\n", - "```\n", - "\n", - "We show an end-to-end example below. Let's create a simple graph with 3 nodes: A, B and C. We will first execute node A, and then decide whether to go to Node B or Node C next based on the output of node A." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "4539b81b-09e9-4660-ac55-1b1775e13892", - "metadata": {}, - "outputs": [], - "source": [ - "import random\n", - "from typing_extensions import TypedDict, Literal\n", - "\n", - "from langgraph.graph import StateGraph, START\n", - "from langgraph.types import Command\n", - "\n", - "\n", - "# Define graph state\n", - "class State(TypedDict):\n", - " foo: str\n", - "\n", - "\n", - "# Define the nodes\n", - "\n", - "\n", - "def node_a(state: State) -> Command[Literal[\"node_b\", \"node_c\"]]:\n", - " print(\"Called A\")\n", - " value = random.choice([\"a\", \"b\"])\n", - " # this is a replacement for a conditional edge function\n", - " if value == \"a\":\n", - " goto = \"node_b\"\n", - " else:\n", - " goto = \"node_c\"\n", - "\n", - " # note how Command allows you to BOTH update the graph state AND route to the next node\n", - " return Command(\n", - " # this is the state update\n", - " update={\"foo\": value},\n", - " # this is a replacement for an edge\n", - " goto=goto,\n", - " )\n", - "\n", - "\n", - "def node_b(state: State):\n", - " print(\"Called B\")\n", - " return {\"foo\": state[\"foo\"] + \"b\"}\n", - "\n", - "\n", - "def node_c(state: State):\n", - " print(\"Called C\")\n", - " return {\"foo\": state[\"foo\"] + \"c\"}" - ] - }, - { - "cell_type": "markdown", - "id": "badc25eb-4876-482e-bb10-d763023cdaad", - "metadata": {}, - "source": [ - "We can now create the `StateGraph` with the above nodes. Notice that the graph doesn't have [conditional edges](../../concepts/low_level#conditional-edges) for routing! This is because control flow is defined with `Command` inside `node_a`." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "d6711650-4380-4551-a007-2805f49ab2d8", - "metadata": {}, - "outputs": [], - "source": [ - "builder = StateGraph(State)\n", - "builder.add_edge(START, \"node_a\")\n", - "builder.add_node(node_a)\n", - "builder.add_node(node_b)\n", - "builder.add_node(node_c)\n", - "# NOTE: there are no edges between nodes A, B and C!\n", - "\n", - "graph = builder.compile()" - ] - }, - { - "cell_type": "markdown", - "id": "0ab344c5-d634-4d7d-b3b4-edf4fa875311", - "metadata": {}, - "source": [ - "!!! important\n", - "\n", - " You might have noticed that we used `Command` as a return type annotation, e.g. `Command[Literal[\"node_b\", \"node_c\"]]`. This is necessary for the graph rendering and tells LangGraph that `node_a` can navigate to `node_b` and `node_c`." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "eeb810e5-8822-4c09-8d53-c55cd0f5d42e", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "from IPython.display import display, Image\n", - "\n", - "display(Image(graph.get_graph().draw_mermaid_png()))" - ] - }, - { - "cell_type": "markdown", - "id": "58fb6c32-e6fb-4c94-8182-e351ed52a45d", - "metadata": {}, - "source": [ - "If we run the graph multiple times, we'd see it take different paths (A -> B or A -> C) based on the random choice in node A." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "d88a5d9b-ee08-4ed4-9c65-6e868210bfac", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Called A\n", - "Called C\n" - ] - }, - { - "data": { - "text/plain": [ - "{'foo': 'bc'}" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "graph.invoke({\"foo\": \"\"})" - ] - }, - { - "cell_type": "markdown", - "id": "68986cc4-97ec-43a1-b95d-5273d7ffc25a", - "metadata": {}, - "source": [ - "### Navigate to a node in a parent graph\n", - "\n", - "If you are using [subgraphs](../../concepts/subgraphs), you might want to navigate from a node within a subgraph to a different subgraph (i.e. a different node in the parent graph). To do so, you can specify `graph=Command.PARENT` in `Command`:\n", - "\n", - "```python\n", - "def my_node(state: State) -> Command[Literal[\"my_other_node\"]]:\n", - " return Command(\n", - " update={\"foo\": \"bar\"},\n", - " goto=\"other_subgraph\", # where `other_subgraph` is a node in the parent graph\n", - " graph=Command.PARENT\n", - " )\n", - "```" - ] - }, - { - "cell_type": "markdown", - "id": "02ccddf2-978c-41bf-b2eb-2d0c4b3f5d81", - "metadata": {}, - "source": [ - "Let's demonstrate this using the above example. We'll do so by changing `node_a` in the above example into a single-node graph that we'll add as a subgraph to our parent graph.\n", - "\n", - "!!! important \"State updates with `Command.PARENT`\"\n", - "\n", - " When you send updates from a subgraph node to a parent graph node for a key that's shared by both parent and subgraph [state schemas](../../concepts/low_level#schema), you **must** define a [reducer](../../concepts/low_level#reducers) for the key you're updating in the parent graph state. See the example below." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "91351541-67af-4c73-9437-426599dcf81e", - "metadata": {}, - "outputs": [], - "source": [ - "import operator\n", - "from typing_extensions import Annotated\n", - "\n", - "\n", - "class State(TypedDict):\n", - " # NOTE: we define a reducer here\n", - " # highlight-next-line\n", - " foo: Annotated[str, operator.add]\n", - "\n", - "\n", - "def node_a(state: State):\n", - " print(\"Called A\")\n", - " value = random.choice([\"a\", \"b\"])\n", - " # this is a replacement for a conditional edge function\n", - " if value == \"a\":\n", - " goto = \"node_b\"\n", - " else:\n", - " goto = \"node_c\"\n", - "\n", - " # note how Command allows you to BOTH update the graph state AND route to the next node\n", - " return Command(\n", - " update={\"foo\": value},\n", - " goto=goto,\n", - " # this tells LangGraph to navigate to node_b or node_c in the parent graph\n", - " # NOTE: this will navigate to the closest parent graph relative to the subgraph\n", - " # highlight-next-line\n", - " graph=Command.PARENT,\n", - " )\n", - "\n", - "\n", - "subgraph = StateGraph(State).add_node(node_a).add_edge(START, \"node_a\").compile()\n", - "\n", - "\n", - "def node_b(state: State):\n", - " print(\"Called B\")\n", - " # NOTE: since we've defined a reducer, we don't need to manually append\n", - " # new characters to existing 'foo' value. instead, reducer will append these\n", - " # automatically (via operator.add)\n", - " # highlight-next-line\n", - " return {\"foo\": \"b\"}\n", - "\n", - "\n", - "def node_c(state: State):\n", - " print(\"Called C\")\n", - " # highlight-next-line\n", - " return {\"foo\": \"c\"}" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "beb61d02-c868-4c2b-b83f-1dfd280f1c8e", - "metadata": {}, - "outputs": [], - "source": [ - "builder = StateGraph(State)\n", - "builder.add_edge(START, \"subgraph\")\n", - "builder.add_node(\"subgraph\", subgraph)\n", - "builder.add_node(node_b)\n", - "builder.add_node(node_c)\n", - "\n", - "graph = builder.compile()" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "3f07b704-1fe2-48a3-ad40-c9bc7698cb1c", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Called A\n", - "Called C\n" - ] - }, - { - "data": { - "text/plain": [ - "{'foo': 'bc'}" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "graph.invoke({\"foo\": \"\"})" - ] - }, - { - "cell_type": "markdown", - "id": "bcd31ceb-f96f-4325-878d-ae1dea8cde8a", - "metadata": {}, - "source": [ - "### Use inside tools\n", - "\n", - "A common use case is updating graph state from inside a tool. For example, in a customer support application you might want to look up customer information based on their account number or ID in the beginning of the conversation. To update the graph state from the tool, you can return `Command(update={\"my_custom_key\": \"foo\", \"messages\": [...]})` from the tool:\n", - "\n", - "```python\n", - "@tool\n", - "def lookup_user_info(tool_call_id: Annotated[str, InjectedToolCallId], config: RunnableConfig):\n", - " \"\"\"Use this to look up user information to better assist them with their questions.\"\"\"\n", - " user_info = get_user_info(config.get(\"configurable\", {}).get(\"user_id\"))\n", - " return Command(\n", - " update={\n", - " # update the state keys\n", - " \"user_info\": user_info,\n", - " # update the message history\n", - " \"messages\": [ToolMessage(\"Successfully looked up user information\", tool_call_id=tool_call_id)]\n", - " }\n", - " )\n", - "```\n", - "\n", - "!!! important\n", - " You MUST include `messages` (or any state key used for the message history) in `Command.update` when returning `Command` from a tool and the list of messages in `messages` MUST contain a `ToolMessage`. This is necessary for the resulting message history to be valid (LLM providers require AI messages with tool calls to be followed by the tool result messages).\n", - "\n", - "If you are using tools that update state via `Command`, we recommend using prebuilt [`ToolNode`][langgraph.prebuilt.tool_node.ToolNode] which automatically handles tools returning `Command` objects and propagates them to the graph state. If you're writing a custom node that calls tools, you would need to manually propagate `Command` objects returned by the tools as the update from the node." - ] - }, - { - "cell_type": "markdown", - "id": "8bcd1a3d-7c50-4f58-be4e-1ed654aa33be", - "metadata": {}, - "source": [ - "## Visualize your graph\n", - "\n", - "Here we demonstrate how to visualize the graphs you create." - ] - }, - { - "cell_type": "markdown", - "id": "e130cf70-a30e-47d7-8fd5-464f1a92e374", - "metadata": {}, - "source": [ - "You can visualize any arbitrary [Graph](https://langchain-ai.github.io/langgraph/reference/graphs/), including [StateGraph](https://langchain-ai.github.io/langgraph/reference/graphs/#langgraph.graph.state.StateGraph). Let's have some fun by drawing fractals :)." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "6d604311", - "metadata": {}, - "outputs": [], - "source": [ - "import random\n", - "from typing import Annotated, Literal\n", - "\n", - "from typing_extensions import TypedDict\n", - "\n", - "from langgraph.graph import StateGraph, START, END\n", - "from langgraph.graph.message import add_messages\n", - "\n", - "\n", - "class State(TypedDict):\n", - " messages: Annotated[list, add_messages]\n", - "\n", - "\n", - "class MyNode:\n", - " def __init__(self, name: str):\n", - " self.name = name\n", - "\n", - " def __call__(self, state: State):\n", - " return {\"messages\": [(\"assistant\", f\"Called node {self.name}\")]}\n", - "\n", - "\n", - "def route(state) -> Literal[\"entry_node\", \"__end__\"]:\n", - " if len(state[\"messages\"]) > 10:\n", - " return \"__end__\"\n", - " return \"entry_node\"\n", - "\n", - "\n", - "def add_fractal_nodes(builder, current_node, level, max_level):\n", - " if level > max_level:\n", - " return\n", - "\n", - " # Number of nodes to create at this level\n", - " num_nodes = random.randint(1, 3) # Adjust randomness as needed\n", - " for i in range(num_nodes):\n", - " nm = [\"A\", \"B\", \"C\"][i]\n", - " node_name = f\"node_{current_node}_{nm}\"\n", - " builder.add_node(node_name, MyNode(node_name))\n", - " builder.add_edge(current_node, node_name)\n", - "\n", - " # Recursively add more nodes\n", - " r = random.random()\n", - " if r > 0.2 and level + 1 < max_level:\n", - " add_fractal_nodes(builder, node_name, level + 1, max_level)\n", - " elif r > 0.05:\n", - " builder.add_conditional_edges(node_name, route, node_name)\n", - " else:\n", - " # End\n", - " builder.add_edge(node_name, \"__end__\")\n", - "\n", - "\n", - "def build_fractal_graph(max_level: int):\n", - " builder = StateGraph(State)\n", - " entry_point = \"entry_node\"\n", - " builder.add_node(entry_point, MyNode(entry_point))\n", - " builder.add_edge(START, entry_point)\n", - "\n", - " add_fractal_nodes(builder, entry_point, 1, max_level)\n", - "\n", - " # Optional: set a finish point if required\n", - " builder.add_edge(entry_point, END) # or any specific node\n", - "\n", - " return builder.compile()\n", - "\n", - "\n", - "app = build_fractal_graph(3)" - ] - }, - { - "cell_type": "markdown", - "id": "edcd9ad2", - "metadata": { - "ExecuteTime": { - "end_time": "2024-04-18T12:18:30.629307Z", - "start_time": "2024-04-18T12:18:30.609323Z" - } - }, - "source": [ - "### Mermaid\n", - "\n", - "We can also convert a graph class into Mermaid syntax." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "66007b2d", - "metadata": { - "ExecuteTime": { - "end_time": "2024-04-19T11:25:38.733126Z", - "start_time": "2024-04-19T11:25:38.726838Z" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "%%{init: {'flowchart': {'curve': 'linear'}}}%%\n", - "graph TD;\n", - "\t__start__([

__start__

]):::first\n", - "\tentry_node(entry_node)\n", - "\tnode_entry_node_A(node_entry_node_A)\n", - "\tnode_entry_node_B(node_entry_node_B)\n", - "\tnode_node_entry_node_B_A(node_node_entry_node_B_A)\n", - "\tnode_node_entry_node_B_B(node_node_entry_node_B_B)\n", - "\tnode_node_entry_node_B_C(node_node_entry_node_B_C)\n", - "\t__end__([

__end__

]):::last\n", - "\t__start__ --> entry_node;\n", - "\tentry_node --> __end__;\n", - "\tentry_node --> node_entry_node_A;\n", - "\tentry_node --> node_entry_node_B;\n", - "\tnode_entry_node_B --> node_node_entry_node_B_A;\n", - "\tnode_entry_node_B --> node_node_entry_node_B_B;\n", - "\tnode_entry_node_B --> node_node_entry_node_B_C;\n", - "\tnode_entry_node_A -.-> entry_node;\n", - "\tnode_entry_node_A -.-> __end__;\n", - "\tnode_node_entry_node_B_A -.-> entry_node;\n", - "\tnode_node_entry_node_B_A -.-> __end__;\n", - "\tnode_node_entry_node_B_B -.-> entry_node;\n", - "\tnode_node_entry_node_B_B -.-> __end__;\n", - "\tnode_node_entry_node_B_C -.-> entry_node;\n", - "\tnode_node_entry_node_B_C -.-> __end__;\n", - "\tclassDef default fill:#f2f0ff,line-height:1.2\n", - "\tclassDef first fill-opacity:0\n", - "\tclassDef last fill:#bfb6fc\n", - "\n" - ] - } - ], - "source": [ - "print(app.get_graph().draw_mermaid())" - ] - }, - { - "cell_type": "markdown", - "id": "8f77ad75", - "metadata": {}, - "source": [ - "### PNG\n", - "\n", - "If preferred, we could render the Graph into a `.png`. Here we could use three options:\n", - "\n", - "- Using Mermaid.ink API (does not require additional packages)\n", - "- Using Mermaid + Pyppeteer (requires `pip install pyppeteer`)\n", - "- Using graphviz (which requires `pip install graphviz`)\n", - "\n", - "\n", - "**Using Mermaid.Ink**\n", - "\n", - "By default, `draw_mermaid_png()` uses Mermaid.Ink's API to generate the diagram." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "967f116d", - "metadata": {}, - "outputs": [ - { - "data": { - "image/jpeg": "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IgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiIC17waINTV+xJ/958l3/8Aa/nWwlr3g1v5Jq/fb+s+S7tv879CDYSIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiIC15wZG1TWHUH/3oyXcP/nLYa15wZ28k1ht7UZLw2/tkGw0REBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEUzmdU3GZGbH4alDcs1w3yma1M6KGEkAhm4a4ufykO2AAAI3I3G+O8+6w/0DB+9zfVrqp6NXVF+yPWYWy3RRHn3WH+gYP3ub6tPPusP9Awfvc31a1utecawWW6KI8+6w/0DB+9zfVp591h/oGD97m+rTda841gs+3GHXd3hhwz1BqvH4N+pLGJr+VOxsc/YOlja4dq4P5XbcrOd/cd+Xbx3XmD4G3wvbXGbX+X0tR0LJSq2rd3OXMm7JB7abJHbtZyCFvOS8tbvuO8nw2XpafLasswyQzYzAyxSNLHxvsyua5pGxBBi6grU3wfeA1r4OsOpWafp4id2avutOkntS80MI37KAHs+rWczuvjum615xrBZ6TRRHn3WH+gYP3ub6tPPusP9Awfvc31abrXnGsFluiiPPusP9Awfvc31aefdYf6Bg/e5vq03WvONYLLdFEefdYf6Bg/e5vq1+2ai1VBvJPicXZjb1MVW69sjht+LzxhpPqBIHXqQm615xrBZaIupicpWzeOgvVHl9eZvM0uaWuHgQQeoIIIIPUEELtrkmJpm0oIiKAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIggNPnfNasJ7/Ox6/8A+vAs4sHp/wD6a1Z+lj/w8Kzi+vicY9I+kLPEREXmgi6NzOY/H5HH0LN2CC9kHPZUrSSASTljC9/I3vdytBJ27gu8gIiICIiAi6uVylbCYu5kbsvY06cL7E8vKXckbGlzjsASdgD0A3X4weap6kwuPy+Om8ox9+vHarTcrm9pE9ocx2zgCNwQdiAfWoO6iIqOtwxO+mJ/oyuSAAHcBenVYpLhh/Vix+lsn/x06rVy9J+PX6z9WquMiIi5mRERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEX5kkbExz3uDGNG5c47ABRuZ408P9PTdjktbafp2CdhXlycIlcfUGc3MT9ACC0Ra6dx60vO0nG19Q5vpuHYzTt6aI/8AfdiIh+t4UXmvhb4bHWvJIsDYbcPyYchl8bXkd+aFtl8//wBpBdaf/wCmtWfpY/8ADwrOKF4Salm1hjc5mJ6Xm6W1lHuNbeQ8m0UQHWSON3UAHqwd/TcbE3S+vicY9I+kLPF5d1bPr7ihxk1/hcNYsw0tMGpVqQU9VS4V0RmrNl7d7I6svb8znOA5zygR7cu+5PfxWB1dq7izR0prLVuXp2a2haVu/HprJy1IZr3ldiN07XMDXAkAEgcodsA4ENaBtjW/A3RHEXMsy2ewgs5JsPkzrVe1PWfLDvv2chie3tGdT6L9x1PRZ6lofCY7Uoz9aiIcsMdHiRO2R+wqxvc9kYZvyjZznHfbfrtvsufZm/ajyphq1ji5N8G/I6jzOY85XoMtVsW8fk56UkjoYJAJAYnt5Xu5PSc3YuG4O46LZun9PXdccfuJ1bI6o1FFh8JLifIcXQy09aFj31Gve48jgSCQN278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1J98f3FpEez2Dxe3drfEhLOsXw+WCHT+auOrW2VC2Ku1na83fKwyPaHRt8Xb/mBVEiCctaky7BeFbSeQmdXtMgiMlmqxtqM/KmYRKSGN9Tw158GnvXNrJ6m5rramAov7O1HHXdayZibNAflynlheWub12Zseb1tVEiCdnk1ZIbIhr4aANusEDpJ5Zeer+O54DG8svqaC5vrKS09VymcMy2IrDy9r4j5tlkIpj5UTvv4++n/OD0R+QVRIgnZMHnp+231M6EHINsR+T0YgWVh/1Y8/Nzb+MnR3q2XEmlL0/bCTVWZIfkBdYGCtH2UY/wCqtLYQTF6+bmkP5fgqNEE7LoitY7cT5TNSCW+3IANyc0XI4d0TTG5p7L1x9WnxBXE3D/CWRYE8Fmy2e83JPbPenkAnb8ktDnnkaPyG7M/1VRognpeHel7BtGfT2Ms+U3W5Gbt6jJOe035Mx5gfTHg7vHgsjHp7FRPsPZjKbH2JhYmc2uwGSUd0junV30nqsgiDgADuGy5REBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERBhtaaVqa70dndNZB80VDM0J8dYfXcGytjmjdG4sJBAds47EgjfwK0Fjvgd8KeBWkMnnMHp039QY6tJPUy2WlNieKYDeORoOzGua7YhzWgghellitVYUak0zlcUXBnltWWuHn8UuaQD+ondeuDNNOJTNfC8XWOLzXBC2tBHEwbMjaGNH0AbBftfKrJJJCBMwxWGExzRHvjkaS17T9IcCP1LCag1Rdwl1kFbS+YzbHRh5sY81hG07kcp7WZjt+m/QbdR179v6jVVFMXliVAoHizxJm0HHhqdGFs2Vy9h8MDpa09iOFrGF75HRwNdI/YAANaB1duSACV3PjAym39QNTfm5qH2pY7O4C1xOioXW1MtonOYS15Rj712OvMd3MLXgsjleHMc0kOBLT3bFc+JXNVExhcfSf1427hJt41aobhJ98RWfkY8xQx0FuxRt0qltll/Ju1kzRIxzDuD8sDoeu+yyd/i9mdGs1hU1DUo5HJ4aGnNTOMa+GO2bT3RxRlr3PLCJG7E7kbHfbpsqDIcO8xn8HQqZvUzchcq5mrlRZZj2ws5YZGPELWB/QHlPpFziC4942C+WquD9XV+S1RYuZCWOLN0KlRrIY+V9aSvI+RkrX79TzOadth8nvO65tjpEReme39Mp9e+3/AFxNYIapHHvD/dQ7EPsnTdt0fmlkrWNHlFfma7tCSdunpDbf1BbmWsaeidRac1LDq7L5qfWV2njpMdHQx2NhqySNklicXgumDdxybncgEd222xzrdfZRx2OgdSt6E7l1D1d3/Ol7YM9XeK4ntm+f0uLFFKUNbZK7dggk0TqGlHK8MdYsOpdnECflO5bLnbD6AT9Cq3ODWlziAANyT4LrpqirgjRvwg/gza8494dmQ0jSwt9uBlkp9hKeyyMgftYIbI70DGDO7ZhIIJceu422p/7P7hbrnRnArVOGzT8porIzZx7q0NvGtbNBtFBzzM7VpbI14HKDsWgscQSe70NwUwz8ZooWpWlkuUsPv8p/IcGsjP642MP61fL+cdPmmrpWJNPC/wD9/d6TxTmR0peyPnhp1Vmasd9sLYWVhWZ5Bybcxhd2JcTJt6XaF+2/o8iZLRFfLeeG2MpmhFk2wtfHWyc1fsBHtt2DonNdEXbekWkF3j06KjRcCJzJcP8ACZjzyLsFm0zLiEW4pL05jcItuQMZz8sfd15A3mPV26/WR4d6XzDswchp7GZAZnsPOLblRkzbfY7dj2jXAh3JsC3fuI3CoUQY52ncS+e7M7GU3TXTG61Ia7OacsGzC87ekWgADffbwWQAAJ2AG/U/SuUQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREGsOJHDCfJW5M1gmB9143s0C4NFggdHsJ2DX+B3IDum5BG51BcvRYyya2QLsbaHfBeaYX/qDttx9I3C9XL5z1orUZjmiZMw/iyNDh/4FfoOifxfE6PRGHiU7URw7bT917J4vKfneiP8Artf/ABW/xXHnej/ptf8AxW/xXp/7msR81Uvd2fwT7msR81Uvd2fwX0fx3D/xzr/pLQ8wed6P+m1/8Vv8U870f9Nr/wCK3+K9P/c1iPmql7uz+Cfc1iPmql7uz+CfjuH/AI51/wBFoeYPO9H/AE2v/it/innej/ptf/Fb/Fen/uaxHzVS93Z/BPuaxHzVS93Z/BPx3D/xzr/otDy/55omRsbLUUsrzs2KJ3O9x9Qa3cn9QWwtDcLruoLEdzOVJMfiWEObUnHLNa+h7e9jPWDs49xAHfuirj6tEEVq0NcHv7KMN/3LsLj6T/Gq8SmaMGnZv33vP6cLHZHBwAGgADYDuAXKIvzQIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiICIiAiIgIiIP/Z", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "from IPython.display import Image, display\n", - "from langchain_core.runnables.graph import CurveStyle, MermaidDrawMethod, NodeStyles\n", - "\n", - "display(Image(app.get_graph().draw_mermaid_png()))" - ] - }, - { - "cell_type": "markdown", - "id": "b9e767fc", - "metadata": { - "ExecuteTime": { - "end_time": "2024-04-18T12:18:30.873950Z", - "start_time": "2024-04-18T12:18:30.871750Z" - } - }, - "source": [ - "**Using Mermaid + Pyppeteer**" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d403e1e7", - "metadata": { - "ExecuteTime": { - "end_time": "2024-04-19T11:25:44.798703Z", - "start_time": "2024-04-19T11:25:44.793438Z" - } - }, - "outputs": [], - "source": [ - "%%capture --no-stderr\n", - "%pip install --quiet pyppeteer\n", - "%pip install --quiet nest_asyncio" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "058546ee", - "metadata": { - "ExecuteTime": { - "end_time": "2024-04-19T11:25:47.412695Z", - "start_time": "2024-04-19T11:25:45.405158Z" - } - }, - "outputs": [ - { - "data": { - "image/png": "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AAAAJpWJUwAAwEHt2zUw+nHjDG8hflVPT0++8IW/O2C9tbUt5557YXbs2J5HH30k3d37kiSXXnplqqurR89bsuS4XHDBpdm1a0ceffSRMde44IJLD7ju3Lnzxxy3t8/JZZe9Kffcc9eY9cbGpixbdnx27hyZCvWrPve5/5WPf/xPDutz/OY37xj9eNGipTn99Feno2NLfvrTH+f6629MfX19Zs5sG817//33jnn+2Wefd0BZ7MQTTzmse5dRY0ttsqk3e5/32gMAAAAAYOL5rgcAAHBQfb1DSZLaegNrx/OLX6wYLUXt9/GP/0kuvfSNo8c9PT25/fYv5J/+6dM5//xfG3PueeddlPPOuygbNz6T97//raPrS5celz/8wz87rAzvfOfNo8WpD3/4Y7nkkjfmmGNmjj6+efOz+Yu/+OMsX/6T0bV77/123vKWd+bUU1912J/r7/7u7+Xqq68fPV6z5qm0t89JkixYsGg07zve8cYxW/197GN/lLa2WYd9n7KrrRt5re1/7QEAAAAAMDkUpwAAgIPq/2V5o6ZWcWo8u3fvOmDt4ovfMOa4oaEhN974m3nTm64bU2iaKMuWHZ+PfeyTOeusc0eLTM83f/7C/NEf/WXe+95rxxSaVq1aedjFqf/0n/4gb3rTm8esHXfciS8vOOPaX1LsV5wCAAAAAJhUvvMBAAAc1P6pN3UmTo1rzpx5B6z94hc/H/fc9vbZqa2tnZQcr3/9VeOWpvZraGjI2972njFr423hN57jjjsxV1xxzcvKx+GrrR/ZytHEKQAAAACAyeU7HwAAwEH19/1yq766SsFJpqalS487YO2P/uijWbHi4QLSjLVz54488cRjeeCB+7J27dNZvHjpmMcPtzh13XW/kerq6smIyDj2b9W3/7UHAAAAAMDksFUfAABwUJXKSGFquOAcU1Vz84zcfPPv5B/+4W9H13bs6MpHP/rbueKKa3L99Tce0S3tHn74gXzxi/+YVatWprt730HP3bz58IpTS5YcOxHROEy/fMll2IsOAAAAAGBSKU4BAAAHtX/S1GC/FscLeetbb8zTT6/K97//nTHrd9/99dx999dz3nkX5eabPzSpBapVq1bm7/7uf2bFip8e9nMGBwcP67x58xa81Fi8BM9NeTMkGgAAAABgMvkqLAAAcFC19bYNO5S6urr83u/9t9x002+N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DgAAAAAAAABA76NVHwAAAIBeUVS0QTfccHnA0FQgL7/8rG644XLV1m7qcu2zzz6km266xi801dGiRR/rgQfu7NbzH6gVK/4dMDTV5txzLzUqZbX57LOPujxvXd1WU2hKkk444bT92+Q+euWVv+ruu//LLzTVUVHRBs2Y8Qs1NDQEXbNu3Wpdd91FAUNTHXm9bt1887WaPfsF+Xy+oOv27Nmjp5/+n4Chqf21bVud7rrr5oChqUA++2yerrrqPK1c+W2P7QEAAAAAAAAAEBpUnAIAAAAQcjt31uvuu/9LXq/bNG+12pWfP1oWS4y8XrfWrPnO9HhFRZmefPJ+3XffUwoLCwt6/u++W2oaH3bYWGVlOVVZ6TJVA5Kk5cu/0YYNa02VnYYOTdRPfrK3fds33ywxrZ8w4WhZLDGmueHDR3RxxXurLrVJSEjU+PFHS5IWL16gww4bq7y8kWppaTZVP1q06GNdd93vZLFYgp63Y9BowoSjZbMld7mfnuD1uk2fw/T0LB1++Hht3bpZ3377lWltY2ODPv74PV144RV+59m82aubb77Wbz4ry6lx446SxWJRQcGPWr16henx11//X2VlOXX88acG3N/99//R7/Mn7f06Gz36CEnSmjXf+bVj7MwTT9znd20xMbEaPfoIJSQMU339DhUUrDWds7GxQffcc5teffWfGjo0oeMpAQAAAAAAAAD9BMEpAAAAACE3a9ZzfqGpGTNu05lnnq9BgwYZc9u21em55x7V4sULjLnvvluqzz6bp9NPP7vL57nggst16aVXa8iQocbcqlXLdffdtxjt5iTp3Xff0J13/qcqUWpquu6662FJ0iWXnG4Kwdx22z1KTBy2D1drNmXKuZox4w9Gy8HrrvudsZeRI8coK8upiooySXsDN//+97900klnBD3f4sWfmMannDJ1v/e2v8aOnajf//5OpaVlGHObNlXrvvtuV1HRBmNu9uwXdN55lyoiwvyj5+uv/6/fOW+88Vadc87FprnS0iLdcceNps/Hyy8/o2OOOcGvheOyZV/7haYSEhJ1992PatSow405n8+n1157Xm+++XKX1/nll4v8znnOORfrqqt+bWr32NzcrHfeeU2zZj1nzDU2NuiFF57ULbfc1eXzAAAAAAAAAAD6Bq36AAAAAITU2rWr9MEHfzfNPfXULJ199kWm0JQkDR2a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379qGHV1dZo7d67mzp0rr9drzFssFk2bNk2XXXYZbfyAQ1Rtba2ee+45I1xVX1+vCy+8ULfffrtp3RNPPKHZs2cbY7vdrvvvv1/jxo3r7S0DPaKpqUlut9sIWG3ZskU///nPTWvWrFmj6dOnm+YuueQS3Xrrraa5++67T++//74kKS4uTna7XY888oiysrJM69avXy+bzSar1RqCKwIAAAAAdIbgFABgwNu9e7epelTbv5WVlWppaQl6XHx8vF/1qJycHKWkpAzYKkjbt283wlEbNmxQQUGBysvL1draGnC9xWLR8OHDTa328vLyTH/JC+DAtLb4tPKLzfp2oVe7mwL/twjg0JNgjdSE45OUP3aIYuIOvMpcc3OzFi1apDlz5uiHH34wPTZp0iRdeumlOu644wbsayBgIPB6vWppaVFysrnl50033aQvv/zSNPf2228rNzfXNDdt2jRZrVZlZ2fL4XAoPz9fP/3pT0O+byBUtmzZIrfbrc2bN6umpkY5OTkaP368aU37tn9tFixYYApI7dixQyeddJIxttvtOvHEE3XbbbeZjnO73WpoaFBKSgo/MwMAAABADyI4BQAYMNraUZSVlamkpMQISVVVVamzb4eJiYnKyckxhaOcTueA/0vQmpoaUxWpgoIC1dTUBF0/ZMgQo3pU283hcCg8PLwXdw0MXL+dcZMifamKDx+ulj2RptZbnfH5fEYQov39uLg45efnh2y/OHBbt2412swkJSUpOzu7j3eEUBocP0hDk6I0NClKw+xRSs8ZHLLnKigo0BtvvKFPP/3UVIUzIyNDF110kc477zwNHhy65wfQvzQ2Npra/pWWlv5/9u48Lup6+x/4i0U2kU1AcB3WGTZFBMR9QyX1uqQVopZL3TYzu9atzG5a3ntb7GplV7uZ4m5qRaWlaLngQkKKMOwgg4DADCAgwoAIvz/88vn5ccByYT4sr+fjMQ+d9+eM94A3kJnXnIN//vOforVkV69exfjx40WP8/DwwO7du0Vnly5dQnJysrD2jytBqSPIz88XVgNqNBrMnTtXdD0rKwvh4eGis7CwMKxevVp09t///hebN28GAFhYWMDR0RFvv/02BgwYIKrLyMiAtbW1TsiRiIiIiIiImsfgFBERdTharVY0OaopJFVQUHDXgJSDg4MoGOXq6go3NzdYWVnpsfu2p76+HtnZ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4OnpKTpLT0/HsmXLUFRUJJw98sgjeO+990R1O3bswLp164Q1gzKZDHPnzoVCodBL70REREQPisEpIhLJz8+HUqlEYmIikpKSWgzrGBsbw8PDA35+fujfvz9X7j2g6upqJCYmCpOklEolysvLdeoMDQ3h6uoqCqe5urrC0NBQgq6JiKi2thZbt27F1q1b0adPH+zevRsGBgZSt0VERG1QSUkJtmzZgu+++w51dXUAbq3RnDdvHmbNmgUzMzOJOyQiIildunQJubm56NKlC4YPHy669uGHH2Lv3r3CfVNTU7z11luYNGmSvtskok4qNTUVly9fRvfu3REYGCi69v7772P//v2is40bN+rUrVixAqampnB0dISjoyNkMhkGDhzY6r0TERER/REGp4g6sbq6OqSkpCAxMRGJiYm4ePEirl692mytg4MD/Pz8hJu3tzdMTEz03HHH0NjYCJVKJYTTEhMTkZOTg+a+HNvZ2cHPzw++vr7Cr3xBhYiobYiOjsbatWuh0WgAAGZmZoiMjOTUKSIiuqvS0lJs374d+/fvh1arBXBreu+cOXPw+OOPo2vXrhJ3SEREbc2ePXsQHR2NtLQ0IXzbXChh/fr16NKlC7y9vdG/f39YW1tL0S4RdTLp6elIT0+HRqOBWq2GRqPB8uXLYW9vL9Rcv34do0aNEj0uMDAQGzduFJ0lJSUhLy8Pffv2hbu7O58LJyIiIr1gcIqoEykpKcHFixeFkFRaWlqz06RMTEygUCiEkJSvry/3kz+AqqoqKJVKISSVlJSEqqoqnTpjY2MoFAohJOXn54eePXtK0DEREf0ZixYtwsWLFwEAU6ZMwZIlS7gqldqcL774AgAwduxYrnQhamMqKiqwfft27N27F9XV1QCAbt26ITw8HHPmzOHacyIialZaWhpSU1MxceJEWFhYiK6NHDlS+J4CAD179sQPP/yg7xaJiHRcvXoVn332GXJycpCTk4Oqqio8+uijWL58uahuzZo12LNnj3DfwcEBq1atQnBwsL5bJiIiok6EwSmiDurmzZvIzMwUTZMqLCxsttbe3h4DBgxA//79MWDAACgUChgbG+u5444jJydHCEglJSXh0qVLzU6TcnJyEk3xUigU6NKliwQdExHR/VCpVFi5ciVeffVV+Pr6St0OkQ6tViuseVm1ahUmT54scUdE1Jyqqirs3LkTu3fvFt5g0bVrV0RERDBARUREf9q1a9ewatUqxMfHC99PPD09sWvXLlFdUlISjh49iqCgIAQGBnKaCxFJoqSkBPX19Tpv2F66dClOnTolOouMjNR53uXRRx+FpaUl+vXrB5lMBrlcrrPmlIiIiOjPYnCKqIPQarVISkpCQkICEhISkJiYiJqaGp06Q0NDeHp6on///kJQytnZWYKOO4ba2loolUrRJK9r167p1JmYmMDLywt+fn7o378//P39OZWEiKidqK6uxpYtW7Bw4UKYm5tL3Q7Rn8bgFFH7cv36dXz99dfYtWsXysvLAdyaQDVv3jyEh4frTBUhIiJqiVKpRHx8PLp06YI5c+aIrm3atEm0GisgIACvvPIKvLy89N0mEZEOrVaLS5cuQaVS4fLly8jJycHy5ctFq0erq6sxcuRI0eOaC4qmp6cjMzMTrq6ucHFx4XM6RERE1CKOlCFqpyoqKnD+/HkhKJWWloabN2/q1HXr1k0UkvL19eU7yR5ASUmJKJyWnp7e7Oe9R48eQkiqf//+nOJFRNROHTp0COvWrUNJSQnMzc2xcOFCqVsiIqIOqmvXrli4cCEiIiKwe/dubN++HZWVlfjvf/+LXbt24cknn8Tjjz/On+eIiOgP+fr6tjgVt6KiQnT//PnzzU5AP3DgAIYNGwZbW9tW6ZGIqDlmZmbw9vaGt7d3izWGhoZ49913oVKpkJOTA5VKBU9PT526Y8eOYdOmTcJ9R0dHfPzxxwyKEhERkQ6+ik/UTuTn5yMhIQEXLlxAQkICcnNzm62TyWSioJSLi4ueO+04GhsbkZ2dLQSlWlp3aGRkBE9PTwwYMAADBgyAv78/HBwcJOiYiIgelpKSErz55pu4cOGCcKZUKiXsiIiIOgszMzMsWLAAjz32GHbv3o2dO3eivLwcn376KXbs2IEFCxZg5syZMDExkbpVIiJqh5YtW4bFixcjNTUVSUlJSE1Nhbu7u6gmMTERK1euBADI5XIEBQVh6tSpcHV1laJlIiIRMzMzTJo06Q/ramtrYW5uLmzmUKvVzW6BGDt2LPr27QuZTCas/RsyZMhD75uIiIjaLq7qI2qDGhoakJGRIQR2EhISUFJSolNnbGwMhUIBf39/+Pv7IyAgAFZWVhJ03DHU1dUJ6w6bVu9VVVXp1HXr1g1+fn5CUIpTvIiIOp66ujrMmDEDxcXFcHV1xeLFi3XGwBMREenDtWvXsGPHDuzevRvV1dUAAAcHByxatAjTp0/nZFsiInroDhw4IASnmrz77rs6QYX8/Hz07t1bn60REd2z4uJiYTJVeHi46FpeXh5mzJghOvP29sa2bdtEZ1lZWVCpVPD19YWTk1Or90xERET6xeAUURtw8+ZNpKSk4PfffxfW7zU9IX47c3Nz+Pn5YeDAgfD390f//v1hamoqQccdw/Xr14UJXufPn0dKSgrq6+t16nr27ClMkhowYADc3NxgYGAgQcdERKRPp06dwtWrV/GXv/xF6laIiIhQUVGBbdu24euvv4ZWqwVw62eVF154ARMnTuTPKERE9FBVV1fj3LlzOHv2LGJjY7F582Z0795duF5fX4/Ro0fDwsICwcHBCA4OxpAhQziFnYjalfz8fGzatAkqlQoqlQpVVVWYNGkS3n33XVHdV199hQ0bNgAAunfvDh8fHzz77LOQy+VStE1EREQPGYNTRBKor6+HUqnE+fPnhaBU0xPft7O1tRWmSQ0cOBByuRxGRkYSdNwxVFRUCOG0CxcuICMjA3d+CTQ0NISnp6cQkho4cCDs7e0l6piIiFpbcXExtm3bhsrKSrz33ntSt0NERPSHysvLsWXLFuzfvx+1tbUAbq1ReumllxASEiJxd0RE1FlcvHgRixYtEp15eXlh+/btEnVERPTgSkpKUF9frzNVasWKFTh06JDoLDIyEr6+vqKz1157TVj55+LiAldXV26rICIiagcYnCLSgxs3biAxMRHnz5/H77//jqSkJOEJ7tvZ29tj0KBBCAgIwKBBgyCTySTotuNQqVRISEhAYmIiLl68iNzcXJ2apqBUYGAgAgMDERAQAAsLCwm6JSIifcrLy8OWLVvw008/CdMGd+zYAYVCIXFnREREf45Go8HGjRvx448/oqGhAQAQEBCAZcuW8Z3vRESkFwkJCTh37hx+++03XLx4EfPnz8fixYtFNd9//z3UajUGDx6M/v37S9QpEdGD0Wq1UKlUyMnJEdb+vffee6KNILm5uZg5c6bocWFhYVi9erW+2yUiIqJ7xOAUUSuor69HcnIy4uLiEB8fj8TERNTV1enU9ejRQwhJBQQEoG/fvhJ023E0Te9KTExEQkICqqqqmq2Ty+UICAhAUFAQAgICYGlpqedOiYhIap988onwTmgTExOE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y5cvV3BwsObNm6e0tDQ5OzurY8eOWrp0qT7++GN17NiRoikHVatWLbVr106StGjRIh05csRwIgBAUTp8+LD+/e9/W4umJCk7O9tgIgAAgBtTp04dSdLvv/9uOAkAAI4lLS1NY8aM0Z49e/Too48qKirKdCQAwF/k10Hmvffe0759+/TCCy+ob9+++v777w0kAwD8GStOlXBZWVkKCwvTwoULlZiYaB3v1KmTRo4cqZo1axpMh+KUmJiohx56SBcvXpSfn5+WLl0qT09P07EAADfphx9+UKNGjfJcGdq3b19JUo8ePdSzZ0/atAIAALs0b948LViwQBUrVlR4eLjpOAAAOJStW7fqpZdeksVikYuLi5599ln169fPdCwAwFXs2bNHy5cv17fffmsdmzdvnlq2bGkwFQCUbq6mAyB/OTk52rhxo+bNm6fjx49bx4OCgjRq1CjVrVvXYDqYULVqVT3//POaPn26YmNjNWnSJM2ePdt0LADADTh16pRWr16tr776SqdPn9bYsWP1z3/+0+aYDz74QFWrVjWUEICjmDdvniSpQ4cOqlevnuE0AEqj3At+LBaL4SQAADieDh06yM/PT88++6wSEhIUHR1tOhIA4BoCAgIUEBCgw4cP64033tDly5cpmgIAw1hxqgT69ttv9cEHH9i0Y2vRooXGjh2rxo0bG0yGkuC1117Tl19+KUnq3r27pk6dajgRAOB67Ny5UyNHjrQZa9Omjd5//31DiQA4KovFoqCgIEnStGnT1K1bN8OJAJRGoaGhmjFjhiQpMjLScBoAABxTamqqlixZkud8AwCg5EtJScnTbeDgwYO69dZb83QpAAAUDVacKkGioqL01ltv6eDBg9axxo0b66mnnlKbNm0MJkNJMmnSJMXFxSkyMlJr166Vt7e3xo4dazoWAKCAWrRoIQ8PD126dEn33nuvevbsqbvvvtt0LAAAgCLx5xbzFotF7u7uBtMAAOCYvLy8KJoCADv116IpSZo4caLOnTunESNG6NFHHzWQCgBKF2fTASBFR0dr5MiRGjJkiLVoqnbt2po5c6aWLl1K0RTyeOedd9SgQQNJ0ieffELLPgAoYY4cOaKFCxeqX79++vXXX232lS1bVq+//rq+/vprzZw5U0FBQXJxcTGUFAAAoGi5ublZb1+8eNFgEgAASpecnByNHz+eFR8BwM78+uuvSkhIUGpqqmbOnKmuXbtq06ZNpmMBgENjxSmDYmNjNWfOHG3bts065uvrq+HDh6tLly5ydqauDfnz8PDQnDlzNGTIEMXGxmr58uUqV66chg4dajoaAJRqu3bt0muvvab4+Hjr2Pr169W0aVOb43JbZwEAAAAAABSFhQsXatu2bdq2bZtmz57NuQgAsBNNmzbV2rVr9frrr+v777/XmTNndP78edOxAMChUThlQEZGhubOnatPP/1Uly9fliRVqVJFTz75pHr16iVXV14WXFvFihW1YMECPf7444qPj9e8efPk7u6uQYMGmY4GAKVWlSpVbIqmgoKC1KpVK4OJAJRm7u7umjt3riTJ39/fcBoAAAAAxalq1arW2+PGjdPbb7+ttm3bGkwEACioW2+9Ve+++662b9+ulStX6qGHHjIdCQAcmlNOTk6O6RClSUREhF577TUlJiZKulL8MnjwYD3yyCM2y9cDBZWUlKQhQ4ZYP6gfP348/Y4BoIjt2LFDmzdv1tixY1WuXDmbfTNnzlTTpk113333ydPT01BCAACAkiE8PFwTJ06UJG3ZskUVKlQwnAgAgNIjLCxM06dPlySVLVtW69evl7e3t+FUAICbdeHCBcXGxubpdAAAuDEsbVRM/vjjD7355psKDw+3jvXu3VujR4+Wl5eXwWSwd5UrV9bChQv1+OOP6+TJk5o5c6bc3NyoPgeAQnb06FGtWLFC27Zt04ULFyRJLVq0UI8ePWyOGz9+vIl4AAAAAAAANoKDg+Xj46Pnn39er776KkVTAOAg3nnnHYWFhalv374aNWoUnzUDwE1yNh3A0eXk5Cg0NFS9e/e2Fk35+fnp448/1qRJk/hFhkKRWzyVu/zyq6++qnXr1hlOBQCOJTExUWFhYdaiqQoVKujixYuGUwEAAAAAAPy9e+65R+vXr9f9999vOgoAoBCcP39e27ZtkySFhoaqT58++uabbwynAgD7RuFUETp27Jgef/xxzZgxQ6mpqXJzc1NISIhWrlzJ0okodNWqVbMpnpo6dao2bdpkOBUA2KfNmzfnGbv77rvl5+envn37au7cudqyZYv69u1rIB0AAAAAAEDBlS9f3nQEAEAh8fb21pdffqnBgwdLkpKTk/k8EABuEq36ikBmZqYWLFigZcuWKSsrS5IUGBioyZMnq0aNGobTwZHddttt1rZ9ycnJmjx5stzc3NSuXTvT0QCgxDt48KDCwsK0ceNGnT9/Xh4eHgoKCrI5JjQ01FA6ALh+FovF+nNs2rRp6tatm+FEAAAAAEqCEydOaNKkSXrllVf4zAIA7FClSpU0atQo3XvvvXrnnXf0wgsvmI4EAHaNFacKWWRkpB5++GF9/PHHysrKUoUKFTR16lTNnTuXCQiKRW7xlI+Pjy5fvqznn39eERERpmMBQIk2f/58DRo0SF988YXOnz8vSdq1a5fhVAAAAAAAAIXvySef1L59+xQSEqIzZ86YjgMAuEHNmzfX4sWL5eXlZToKANg1CqcKSVZWlmbNmqWQkBAlJCRIkrp166ZVq1ape/fuhtOhtKlZs6YWLlyoihUrKjs7W+PGjdPOnTtNxwKAEiG/E4Jt2rSRJHl4eKhnz576+OOPNXbs2OKOBgAAAAAAUORefPFFOTs769SpU3r22WetnTMAAI5h+fLleuONN/j5DgAFROFUIThx4oQGDRqklStXSpJ8fX01d+5cTZs2TRUrVjScDqVVbvGUt7e3srKy9Oyzz2rPnj2mYwGAEadPn9bixYs1YMAAde3aVWfPnrXZ36xZM73++uvavHmzXnzxRTVt2tRQUgAAAAAAgKLVtm1bTZgwQZIUHR2tDz74wHAiAEBh2b9/v2bPnq0vvvhCQ4YMUVJSkulIAFDiUTh1k7Zv365HH31UMTExkqQePXro888/V2BgoOFkgOTn56f58+fL29tbmZmZGj16tH799VfTsQCgWK1evVrdunXT+++/r0OHDkmSNm3alOe4zp07y93dvbjjAQAAAAAAFLu+ffuqY8eOatKkiQYNGmQ6DgCgkDRq1EiDBw+WJO3bt0/9+vWb84Z1AAAgAElEQVTTwYMHDacCgJLNKScnJ8d0CHuUmZmpt99+W6GhoZIkd3d3TZkyRZ07dzacDMjryJEjGjJkiFJTU+Xh4aH58+erUaNGV73Pn4v/IiMjizoiABSZ+Ph49erVSy4uLmrVqpUeeOABdejQgb7vAAAAxSA8PFwTJ06UJG3ZskUVKlQwnAgAAOTKyMiQh4eH6RgAgCLw57nYm2++qQ4dOhhOBAAlF4VTN+DEiRMaM2aMfvvtN0lS7dq19fbbb6tGjRqGkwF/Lzo6WiEhIUpNTZWXl5cWLFigevXq5XtsYGCgcnJy5OTkJEkaNWqUtTodAEqi48ePa/Xq1dq1a5eWLVuWZ394eLjuuusueXt7G0gHAADguHLnjzfLycmJi3YAAAAAoBAdOnRI+/btU58+fUxHAYASjcKp67R9+3a9+OKLysjIkCT16dNHzz33nNzc3AwnA64tOjpaQ4cOVUZGhry9vbVo0SL5+/vbHPPXk95OTk5q0aKFFi5cWNxxAeCawsPD9emnn2rv3r3Wsfnz5ysgIMBgKgAAgNKjb9++io2Ntbn45nrl3pfCKQAAzIuMjLTpRgAAAAA4OmfTAexFZmamXnnlFY0bN866fO2sWbP0wgsvUDQFu9GwYUN9+OGHcnd31/nz5zV06FDFxcVZ9/+5aCr3hHdOTo6ioqKUnJxsJDMAXE1UVJRN0dSDDz6oihUrGkwEAABQuowaNeqm7p87B3V1dS2MOAAA4AZlZ2dr9uzZCgkJ0aeffmo6DgCgiJw9e1bDhw/ncz8A+BMKpwogPj5eAwcO1OrVqyVJ9erV02effaZ27doZTgZcvyZNmuj999+Xu7u7UlJSNGzYMCUkJNhcRZRbNPXnq4W3bdtW7FkBQJIyMjIUHh6uV199Nc++Ll26qHHjxpo4caK2b9+u6dOnq3bt2gZSAkDJFBkZqcjISE6GASgy999/v+rWrSsnJ6cbatnn5OQkJycnde/evQjSAQCAgrp8+bIiIiIkSe+9955iY2MNJwIAFIXnnntOu3fv1pNPPqmkpCTTcQCgRKBV3zVERUVp9OjRSk9PlyT169dPY8aM4UpI2L2oqCg99dRTyszMlKQ8K03lym2ZEBAQoPnz5xd7TgCl18aNG/X111/r+++/t47NmzdPLVu2NJgKAOyHxWJRUFCQJGnatGnq1q2b4UQAHNXWrVs1YcKEv51XXk1OTo48PDz01VdfqVKlSkUVEQAAFMD+/fs1ePBg5eTkqH79+lq2bJlcXFxMxwIAFJKsrCxNmDBB3377rSSpRo0aWrhwoSpXrmw4GQCYxYpTV/Hdd99pxIgRSk9Pl5eXl2bPnq1x48ZRNAWH0KJFC7377rs2Y/md3M4di4qKUkpKSrFkAwBJ2rRpk03RVMWKFXX+/HmDiQAAAJCf9u3bq3bt2tdVMCX9/4U6AwYMoGgKAIAS4I477tCIESMkSYcPH9bBgwcNJwIAFCZXV1e9/fbb1q5K8fHxev311w2nAgDzKJz6G2vXrtXYsWN16dIlVatWTcuWLbNerQ04ihEjRhToiuCcnBxdvnxZP/zwQ3FFA1CKHDlyJN+fL+3bt5d0pR3ff/7zH4WHh1vHAAAAUHI4OTlp6NCh1u3rWdzc09NTAwcOLIpYAADgBjzxxBMaNGiQ1qxZoyZNmpiOAwAoAm+++aaCg4NVo0YNvfDCC6bjAIBxLJ2UjyVLlui9996TxBKFcFyBgYHWq3sL6ttvv9WDDz5YhKkAlBanT5/W559/ri1btig+Pl4+Pj7auHGjzTEdOnRQhw4d5OnpaSglAAAACqpjx466/fbb9fvvvxeocCp3PvrII4+ofPnyxZAQAAAU1DPPPGM6AgCgCDk7O+ull17SuXPnVKFCBdNxAMA4Vpz6izfffNNaNNWgQQMtXryYoik4nMDAQElXX2UqP999950sFktRRAJQynz66adasmSJ4uPjJUnJyck6cuSIzTGenp4UTQHATXB3d9fQoUM1dOhQ1a9f33QcAA7O2dm5wKtO5RZNlS1bltWmAAAAAMAQiqYA4AoKp/7n8uXLmjp1qj7//HNJUvPmzbVw4UJVrFjRcDKgcOWuNHU9nJyclJOTo4sXLyoiIqKIkgFwRGlpadq+fXue8S5dulj///rrr+u7775T3bp1izseADi84cOHa/jw4apXr57pKABKgQceeEC1atWSk5NTgS7UeeSRRzjvAgCAHbhw4YLpCACAYrB+/XqNHz9e2dnZpqMAQLGicEpSZmamxo4dq7Vr10qS2rRpow8//FAeHh6GkwGF60aKpv4qPDy8kNIAcGSRkZGaMmWKOnfurHHjxikxMdFmf8OGDbVp0ya98sor6ty5M79zAQAAHICzs7MGDx4s6cqqUvnNP3PHypYtq0GDBhVrPgAAcH1ycnIUFham3r17a926dabjAACKUEREhF588UVt27ZNr7/+uuk4AFCsSn3hVFpamkaMGGFdReeBBx7Q7Nmz5ebmZjgZULhyi6autz3fX0VERNCuD8BVvfbaawoJCdG6deuUmZkpSdq9e3ee42655ZbijgYAAIAi1q1bN/n5+V117unk5KSHHnqIvwcBACjhLl++rIULF+rs2bOaM2eOsrKyTEcCABSRe+65R+3atZMkrV69WqGhoYYTAUDxKdWFU1lZWRo1apT27t0rSerVq5deffVVubq6Gk4GFL7IyEjrievc1nt/dwVwfnLva7FYaNcHwCo5OTnPWKtWrSRdKYwaOHCgQkND1bVr1+KOBgAAAANcXFz03HPP5bsvd/7p5uZmXZkKAACUXC4uLho9erQkKTExUV9++aXhRACAouLk5KRZs2apQYMGkqQZM2boxIkThlMBQPEo1YVTU6dO1a+//ipJGjp0qCZPnnzTq/EAJVlkZKT69u2rqlWrysnJyfrf9RZRUTgFlG5paWn6/PPP9dhjj6lPnz559t9333168803tWnTJo0ZM0Z+fn4GUgIAJGnYsGEaNmyYduzYYToKgFLk7rvvVuPGja3zzT9zcnJSz549VblyZUPpAADA9ejUqZMaNmwoSVq0aJEuXrxoOBEAoCjNnDlT5cuX13PPPafbbrvNdBwAKBZOOQWtlHAwCxcu1Ny5cyVJAwcO1JgxYwwnAorXL7/8olWrVmnbtm1KT0+XpHxPaP9Z7v5bbrlFmzZtotAQKIXmz5+vxYsXW1vwSdKsWbOsS/gCAEoOi8WioKAgSdK0adPUrVs3w4kAlCYRERE251pyW8e7uLgoLCxM1apVM5gOAABcj71792rmzJl64okn1KFDB9NxAABFLDU1VV5eXqZjAECxKZU96bZs2WItmmrdurV1qVmgNGnWrJmaNWuml156SVFRUVq7dq02bNigS5cu2RyXWyyVuzqVJJ09e1Z79uxRy5Ytiz03ALOcnZ2tRVPNmzdXcHCw2rRpYzgVAAAASpqgoCA1btxYBw4csLlIp2fPnhRNAQBgZ5o3b67ly5ebjgEAKCYUTQEobUpd4dSBAwc0efJkSVLNmjU1a9YsOTuX6o6FKOVcXFzUsmVLtWzZUhMmTNCuXbu0fft2bdy4UZmZmTat/HI5OTlp8+bNFE4BDioiIkLh4eE6efKk5s2bZ7Ova9euSktLU8+ePWnBBwAAgKt68skn9dxzz1m3XVxc9MQTTxhMBAAAAAC4EefOnVOFChVMxwCAIlGqCqdOnDih0aNH69KlSypfvrzmzJkjDw8P07FKtMR4i1KSLyr9QrYy0rOkUtnYsXRxUyM90KaR7r/zCf3++++Ki4tTXNxxZWVl2RwXt89NP2w4Tbs+wIHs2rVL+/cf+N/Kc2Uk1dL6zw6rYsWKfzqqjO5q2F8nD0mnYhLlWc5Vnt5lVKW6uyr4lDGUHACAkuVUXIbO/ZGp9AtZsqRnm44DGFMmp6HaBQxRcnKyJKlx40Y6ttdZx/YmGk4GGOIklfPKnUOVVQUfN9OJAAAAgKs6duyYpk2bpjJlymjBggWm4wBAkXDK+fMyMg4sNTVVgwYN0vHjx+Xs7KyFCxeqWbNmpmOVSKkpl/TTtiQdjjqv9FRO8gMACsanmpvq3+mtlvdVVpmyrOYIACVBZGSkJMnf318+Pj6G0zi2lKRMRW5LUsze87JkXDYdBwBgB26p6qb6LbwV2I45FAD7cuTIEZUtW1Y1a9Y0HQUAUMS++OILvfHGG5KkyZMnq1evXoYTAUDhKxWFU9nZ2RoxYoT27NkjSXrppZcUHBxsOFXJk5WZo+83nNaeb/4wHQUAYMfcPZ0V1K2amrapZDoKAABFLtNyWd9+dUq/7kgxHQUAYKeYQwGwJ08//bR+/PFHPfzww3r++edNxwEAFIPBgwdr37598vLy0qpVq7g4D4DDKRWFUy+//LLWrFkjSerXr5/GjRtnOFHJk5GapS/nxykxwWIdq9WgvKr7e8rnVg95eZeRu1ep6uwIACiAtHOXlHb+khLj03XiWJpOxaZb9zVq6a0u/6xhMB0AAEUrNeWSQufG6uyZS5IkZxenK/MoP0/dUs1dXhXKqKwn8ygAwP/LnUOdSUhXwm+2c6gGd3rrwYHMoQCUbJMnT9aGDRvk7u6urVu3ys2NtqMA4OhiY2PVt29fSVJwcLBeeuklw4kAoHA5fOFUWFiYpk+fLkkKCAjQhx9+KBcXF8OpSpZzyZf0+ZxjSj2XJUm6vWF5tepUTZ7eZQwnAwDYm6SEdO3afFpJJ64U4vr6e6j3MD+5ujkZTgYAQOFKPnVRn79/zNqWr06zCmrZvqrcy1EoBQAouOSTGdq16ZTO/O9ixtv8PNR7uJ/KMIcCUELt3r1bw4cPlyRNnz5dDz74oOFEAIDiMHfuXF24cEEjRoyQl5eX6TgAUKgcunDq5MmT6tu3ry5evKhatWppyZIlKl++vOlYJYolLVufvPubziVfkksZJ7XtVl3+jSuYjgUAsHN7tidq3w/JkiS/RuX00JDbDScCAKDwpJ27pOVv/6b01GyVKeuse3vephp1mWsCAG7cn+dQtzcop97DmEMBKLm6d++uU6dOqU2bNnr//fdNxwEAAABuisvUqVOnmg5RVObMmaNff/1VkjRt2jTVq1fPcKKS56slx3X6uEVykjo9Wks163GyHwBw86r7lZOzi5NOxaYrJemSnF2kGrXLmY4FAKWKxWJRmzZtNH/+fPn6+qp+/fqmIzmEnBzpvwvi9Edippydpa6P3a5qtfgdBwC4OdX9ysm1jJNOHkvXueRLcnLOUY06/H4BUDJ5eXmpadOmeuyxx+Tt7W06DgAAAHBTHLaHwMGDBxUaGipJ6tSpk4KCggwnKnmO7L+g2Og0SVJAuyqq7sfJGABA4WnatrLOJGQoPiZVP6w/o8YtK6p8JdrAAgDs24GfzupEbIYkqXWXW3XLrR6GEwEAHMUdbSorMSFDxw+l6scNSbojsBJzKAAlUnBwsOkIAAAAQKFxNh2gKGRnZyt3IS0vLy+98MILhhOVTBFfnZIkVfBxU5M2lQ2nAQA4oru7VJeLq5MkaefmM4bTAABwc3IuSz9suPL7rPJt7qrXopLhRAAAR9O26//PoX7cxBwKAAAAJc+5c+c0Y8YMLV++3HQUACgUDlk4tWLFCh09elSSNH78eFWoUMFwopLn1O/pOnvmkiQpoENVyclwIACAQ/Io76qGra58qHxgzznDaQAAuDmxh1OVei5LkhTYsZrhNAAAR1TW01WNW/tIkvbvSlHWpRzDiQAAAABbEydOVGhoqJYuXWo6CgAUCocrnDp9+rTmzZsnSWrVqpW6detmOFHJFHs4VZLk4uok39q06AMAFB2/ht6SpOxLOYo9lGo4DQCUHu7u7goICFBAQIB8fHxMx3EIv//v95ibu7Oq1vQ0nAYA4Khub1jeejv+tzSDSQCgYJKTk01HAAAUo4cffliS9Mcff2j16tWG0wDAzXO4wqmXX35ZFy9elIeHh6ZNm2Y6TomVmGCRJFWr5SlnF4d7GwAAShCf6h4q63Hld82ZhAzDaQCgdJk/f77mz5+vNm3amI7iEM78bx7lW8fLcBIAgCO7pZq73NyZQwEo+d59913df//9+vDDD01HAQAUo/bt28vX11fSlU5QAGDvHKpi5qefftKOHTskSY899piqVq1qOFHJlZpypb1EOW9Xw0kAAKVB7u+b3PZGAADYowspV9qdl6tQxnASAICj8/rf75oLKcyhAJRcZ8+eVVpamvVzGQBA6eDk5KTHHntMkpSTk6M//vjDcCIAuDkOVTXz0UcfSZI8PDw0YMAAw2lKtrTzV066uJfjhD8AoOiV9SwjKVOp5znpDwCwX2kXrvwe8yjnYjgJAMDRuZdzlXRRqecvmY4CAH+rTZs2Wrt2rU6dOqXff/9dt99+u+lIAIBi0qdPH/n4+Khdu3amowDATXOYFaeio6P1008/SZIGDhwoT09Pw4lKtuysHEmSk8O8AwAAJZmzi5MkKSvzsuEkAADcOOs8ysnJcBIAgKNzcc2dQ+UYTgIAf++ee+6x3t69e7fBJAAAEyiaAuAoHGbFqQULFki6strUP//5T8NpAAAAAMC8efPmSZI6dOigevXqGU4DAAAAwJGUL19ezZo1U5kyZeTt7W06DgAAAHBDHKJwKi4uTt98840kacCAASpfvrzhRAAAAABglsVisV5gUqNGDQqnAAAAABS6jz76yHQEAAAA4KY4RKO2+fPnS7qy2tSAAQMMpwEAAAAAAAAAAAAAwLGlpaVpwYIF6tevnw4ePGg6DgDcELsvnDp58qQ2btwoSerfvz+rTQEAAAAAAAAAAAAAUMTc3Ny0ePFiHTlyRJs3bzYdBwBuiN0XTn3xxRfKycmRh4eHBg0aZDoOAAAAAAAAAAAAAAAOr0yZMmrXrp0kafv27YbTAMCNcTUd4Gbk5ORow4YNkqQuXbqw2hQAAAAA/I+7u7vmzp0rSfL39zecBgAAAICjCg8PV0REhCpWrKgxY8aYjgMAKGbt27fXxo0bFRcXp/j4eNWoUcN0JAC4Lna94tTPP/+sxMRESdI//vEPw2kAAAAAoGQJDAxUYGCgfHx8TEcBAAAA4KB+//13rV27VmFhYaajAAAMaNu2raQrbftiYmIMpwGA62fXK06tX79eklSpUiW1bNnScBoAAAAAAAAAAIDSpX79+pKk8+fPKykpSZUrVzacCABQnDw9PRUaGio/Pz/TUQDghtjtilNZWVkKDw+XJD344INycnIynAgAAAAAAAAAAKB0qV27tvX20aNHDSYBAJhC0RQAe2a3hVPff/+9Lly4IIk2fQAAAAAAAAAAACb4+vqqTJkykqRjx44ZTgMAAABcH7tt1bdhwwZJV/4gb9y4seE0AAAAAFCyWCwWBQUFSZKmTZumbt26GU4EAAAAwFEtWbJEFSpUULVq1UxHAQAAAK6LXRZOpaen65tvvpEkde3a1XAaAAAAAAAAAACA0qt+/fqmIwAADLt48aL279+v5ORkde7c2XQcACgwuyycioyMVGZmpiRZr6AGAAAAAAAAAAAAAADFb9GiRfroo4/k5eVF4RQAu+JsOsCN2Lt3ryTJzc2NNn0AAAAAAAAAAAAAABh0xx13SJJSU1P1+++/G04DAAVnl4VTUVFRkqSAgAA5O9vllwAAAAAAAAAAAOAwUlJSFBMTo7S0NNNRAAAGNGnSxHo7OjraYBIAuD52V3WUlZWlffv2SZLuvPNOw2kAAAAAoGRyd3dXZGSkIiMj1a1bN9NxAAAAADiw48ePq1OnTurfv79+/fVX03EAAAb4+PiocuXKkqSYmBjDaQCg4FxNB7he+/fvV3Z2tqQrK04BAAAAAAAAAADAnOrVq1tvnz592mASAIBJY8aM0aVLl9SoUSPTUQCgwOyucGrv3r2SJBcXFzVt2tRwGgAAAAAAAAAAgNLN1dVV3t7eOn/+vM6cOWM6DgDAkC5dupiOAADXze5a9eUWTjVr1kyurnZX9wUAAAAAAAAAAOBwqlSpIklKSkoynAQAAAAoOLurPIqKipJEmz4AAAAAuJbIyEhJkr+/v3x8fAynAQAAAODIgoKC1KhRI7Vo0cJ0FAAAAKDA7Kpw6tSpUzp37pwkqXnz5obTAAAAAEDJZbFYFBISIkmaNm2aunXrZjgRAAAAAEf29NNPm44AAAAAXDe7atUXFxdnvV2rVi2DSQAAAAAAAAAAAAAAwJ8NGzZMnTt31vLly01HAYACsavCqePHj0uSnJ2dVb16dcNpAAAAAAAAAAAAAABAruTkZJ09e1YnT540HQUACsQuC6d8fX3l4uJiOA0AAAAAAAAAAAAAAMh16623SpJOnz5tOAkAFIyr6QDXIz4+XpJUs2ZNw0kAAAAAoGRzd3fX0KFDJUn169c3nAYAAACAozt27JhWrlypM2fOaOrUqfL29jYdCQBgQJUqVSRJZ86cMZwEAArGrgqncleconAKAAAAAK5t+PDhpiMAAAAAKCVOnz6tVatWSZLOnTtH4RQAlFK33nqrfHx8VLlyZdNRAKBA7KpwKnc5v2rVqhlOAgAAAAAAAAAAgFxeXl7W26mpqQaTAABMCgkJUUhIiOkYAFBgzqYDFFRWVpb1D+1KlSoZTgMAAAAAAAAAAIBc5cqVs95OS0szmAQAAAAoOLspnDp79qz1NoVTAAAAAAAAAAAAJYeHh4f1tsViMZgEAAAAKDi7adX3xx9/WG9XrFjRYBIAAAAAsA/z5s2TJHXo0EH16tUznAYAAACAI7v11ls1d+5cSVLdunUNpwEAAAAKxm4Kp1hxCgAAAAAKzmKxaMGCBZKkGjVqUDgFAAAAoMgFBgaajgAAKAEiIyMlSfXq1VOFChUMpwGAq7ObVn0pKSnW27fccovBJAAAAAAAAAAAAAAA4K9SUlIUEhKikJAQawEVAJRkdlM4lbvilKurq02fbAAAAAAAAAAAAAAAYJ6np6f1dnp6usEkAFAwdlM4deHCBUlSxYoVDScBAAAAAAAAAAAAAAB/5ebmJhcXF0kUTgGwD66mAxRURkaGJMnd3d1wEgAAAAAo+dzd3TV37lxJkr+/v+E0AAAAAEqDLl26KCkpSUOHDtXw4cNNxwEAGOLu7q60tDRdvHjRdBQAuCa7K5yiTR8AAAAAFExgYKDpCAAAAABKEVfXKx87ZWVlGU4CADBpyJAhSk9PV5MmTUxHAYBrspvCKYvFIonCKdi3qVPH6fz5FEmSi4urXn55NquoAYVgxYqF2r17h3U7JOQ51a/fyGCionHuXIoOHdqvBg3uUIUKtK4FAACOLzHxlGbMmGzd9vevp6efft5gIsBxONo8KjMzUxcvWpSZeVGXLl1Sdna2srOz5OHhqUqVfKwf5AMAihaFUwAASRo0aJDpCABQYHZzxoAVp+AIoqJ+UkbG//fyzc5m8ggUhtjYo9q/f691OyXlD4Npis6qVcv12WdLNHjwCPXv/4TpOAAAAEUuLS3V5u+8zEyW+AcKi6PMo/7znxlat27VNY+rXLmq6tSpr27d+uiuu+6Rk5NTMaQDgNKHwikAAADYG2fTAQqKwikANyszM9N0BOCGZWZmKizsC0nSxo1hysnJMZwIAAAApQHzKJR0BS2oTEpK1M6dEXrppWf19NOPKTp6XxEnA4DSqXnz5goICJCvr6/pKAAAAECB2F3hFG3NAFyP7Oxs7dmzUzNmvKgePe7RuXMppiMBN2THjm+tK9adPJlgc2U4AAD5sVgsCgwMVGBgoNatW2c6DgA7kpGRoa1b12v8+BCNHv0v03GAQhcTE62JE0fqzJnTpqMAgMN58cUXNX/+fPXr1890FAAAAKBAaNUHwKGNHDlQx44dsW5fvnzZYBrgxq1fv9pme+vWDWrSpIWhNAAAAHBUZ86c1sCB3a3btWr5G0wDXL877miue+/tqLJl3eXq6qrz51N04kRCnnZ+GRnpeuWViZo9+yPa9gEAAACFbNasWTp8+LDatGmjJ554wnQcALgquymcslgskiicAnB9zp5NNh0BuGkJCce1Z89Om7F161Zp2LAxrMQIAACAQkVrPti7O+9spYce6p9n/PHHn9LMmVO0c2eEdSw6ep9OnkzQbbfVKM6IAAAAgMM7dOiQfv75Z1WpUsV0FAC4Jrtp1Xfp0iVJkpubm+EkAAAUr40b1+Q7vmPHt8WcBAAAAADsU/ny3ho/flqe8djYI/kcDQAAAOBmuLi4SKITDAD7YDeFU9nZ2ZLE0tkAgFIlMzNTYWFf5LsvPHxdMacBANgTd3d3BQQEKCAgQD4+PqbjAABgXPny3nlanh87RuEUABSm6OhoRUZGKjY21nQUAIBBuZ/pUzgFwB7YTau+3B+qudWpcFwxMdH68cftkqRGjZqpVau2kqQTJ+K1b9/POnTogPbvj9KFC+dVr14j1a5dV3ff3U716jUs8HMkJydp//4oHTkSrZiYaP3222H5+tZSnToN5OdXW/Xr33FdjyddKW7YufM7RURs1e+//6azZ5NVpUo1Va9eQ3Xq1Fe3bn2u6/EkKScnRz//vEsxMQd15MghxcQclLOzi/z96+r22/1Vo8btat36XpUr53Xdj12Yfvst5n//nod06NB+XbhwXv7+dVWrlr9q1vRTixatVL2679/e/8KF8/rvfz+RJN1yS2V1797XOr53b6QOHdqvAwd+UXz877r99jqqU6e+mjUL0N1335/v4yUnJ2ndulBJUkrKWZt9n376kby8bP+9GjZsqrvuusdmbMeOb3X48AHrdvv2XVSzpp+Sk5O0YcNqRUVF6sSJ49bMNWrUsvkaa9b0V/v2/7jqv1uu8PB11seSpHvv7SR//7oFuu/1Cg1dpvT0NEnSo48+rrJlyyorK0u//LJbhw7t18GDv+rQof2qWrW66tRpoHr1Gqhz5x4FXu0vJydH+/ZF6ejRQzpy5JAOHPhFly9nq06dBqpdu578/OqoeYyj2t0AACAASURBVPNAeXmVv67c+/ZFadu2jTpyJFqnTiXIw8NTtWrVVq1afvrHP4Kv+99BkpKSEvXzz7v0228xOnRovxIS4lSjxu3y86urmjVvV8OGTdSwYZMbeuzCtGPHt8rISM93308//aCkpERVrly1mFMBAOzF/PnzTUdAMbHXedS5cyn67rtw7dr1veLj45SWdkG+vrV022011axZgPz9613X40mlZx5V2K/5wYO/6qefvldycpLNeFzcMS1dOjfP8blzpD/7738/1YUL5yRdOUn+8MP/kru7u377LUbr16/W4cMHrH/PV6lyq5o0aaE/Xx9XEudRhT1fzY/FYtHevZE6evSQYmKidfjwAXl6llODBnfIz6+Oateup+bNA6/7nFhpnkddj+udnwIArm7mzJnau3evunbtqpdfftl0HACAIaw4BcCe2F3hlLOz3SyShRt0+PB+rVixSJJUuXJVLVmyRr/8slsvvDAqz7FJSYn68cdvtGLFIg0dOlq9ew+45nskImKrZs2alqcQISXlrPbv32vd7tnzUT3xxCi5u7tfM3Ny8hlNnz5B0dH78jxmTEy0vv02XCtXLv7b4of8JCae0uzZr2r37h159iUkxCki4srtihUr6ZlnJqlt23YFfuzCYrFYtGTJh/ryy0/y7EtKStRPP/1g3X7iiZHq3XuAypQpk+fY5OQz1tdcku68s7XKlCmjCRNCdPJkgs2xKSmR2rs3Ul9++Yk6dnxQI0eOz/OBx5kzp2we78/WrPksz1hw8CN5CqciIrZp8+a11u3atesrIeG4pkwZm+/XWqmSj81zenh46u6777/m+8disWjmzKk2Y3fdFXTV+9yM5csXWt+Ht91WU/fe20mvvvqCdu78zua4lJSzOnz4gNavl9avX62JE19VjRq1rvrY58+f09tvv6wff/wmz76TJxMUEbFV0pXv60mTXtMddzS/Zt7MzEx98MEsrV//3zz5Tp5M0M6d3+mLL5Zd83H+LCcnRxs3humdd17Jsy8l5az27Yuybnfu3F1DhoxWxYqVrus5CtPatatstjt37m7z3ty+fZP69h1Y3LEAAEAJY4/zqP3792r69PF5LnbIfcw//81TUKVpHlXYr/n+/VF/O4/Kb/xKoYxt4dTKlR/bvJ4PPthHoaHLtGyZbRFn7t/zTZu2KPHzqMKer/7VsWNH9PLLzyshIS7Pvri4Y9bbzZq11IQJ01SlSrVrZmYe9fcsFouOHj1sM1anTgNDaQAAAADH9dxzz6ls2bK67bbbTEcBgGuymyqk3FZ9FE6VLklJiXr77ZfzPfH7VwsW/Edffrnib/dfvHhRc+bM1MsvP1+gAqY1az7T008/ZnOiMj/R0fv01FMD8hRN/dX1FE1t27ZRw4Y9mu/J/r9KSTmradPGa9q08crKyirwc9ysmJhoPfXUgHxP9ufno4/m6KmnBuj06ZPXPHbOnDf17LNP5jkJ/Vdbtnyt11//d4Ge/2ZFRv6Yb9FUroEDh9pcDZ6Rka5duyKu+bhRUbtstqtX91WDBnfceNDr8PHHH2jq1OfyFE39VUxMtEaNGqT09L9/D+/fv1dDhz6cb9HUXyUlJWrs2CFavnyBcnJy/va45OQkTZz4VJ6T/Tfj3LkUTZkyNt+T/fnZvHmtBg/upT17dhZahusRHx+nvXsjrdvNmrVUz56P2hzz9deF9+8DAAAcgz3Mo9avX62xY4fkKZq6GaV5HlWYr3lhWrZsfp6iqVweHp565JHBdjePKsz56vr1qxUS0j/foqm/+uWX3Ro69JFrzrmYR13dokXv2fwsa9KkhRo3bmYwEQAAAOCY/P39KZoCYDfspgqJVn2l15YtX9tst259rzp37q5atfzzHLt8+cK/Le5YsWKBwsI+txnz8PBU69b3asCAJ9W5c/c8bRDi4o7p5Zef/9sT6dHR+/TMM4/ne7L/jjuaq0uXnte9RH1MTLRmzJic50OJWrX81b59F7Vr94Dq12+c534//LBdoaHXd8XojUpLS9XUqc/lOblbuXJVtW3bTh06dFWzZi3z3C8u7pjeffe1qxbLSNLu3TuUlJRo3b7jjubq2rWXmjRpkefYn376IU/RWoUKldS2bbt8rx4PCGht3Zf7X9261766dP361dbbFStWUvv2XdS+fRdrvvr1G1lbNuTasGHNNR93+/bNNttduvS09n0uaklJiTYnsn19a6lLl55q3TrvldoZGen6+usv832c5OSkfD/0qlXLX8HBj+iRRx5T8+aBee63bNl8fffdlnwfMy0tVaNH/8tm9YI/P27nzt2trUiux+zZr2rnTtsPYjw8PNWyZRt17PigWre+N89V0RkZ6Zo+fYLOnUu57ue7WZs2hdlsd+zYVXXrNrBpzZeQEKdDh/YXdzQAAFDCleR51OrVKzV79qt5xj08PNWqVVt17txdvr5XX+30r5hH3fxrXrOmv9q2bZfvvOuvc6i2bdupatVbr5pHkk3xTu58o2XLNpKkPn0GyN3d3e7mUTc7X821a9f3+X4fNGnSQo888piCgx/J857NyEjX1KnjlJh4Kt/HZB51RVZWlvX7JScnRykpZ/Xzz7v0wgujbH6eeXh4auzYl7hIEwAAAACAUs5uWvWx4hTGjZui++7rrLJly0q6cvJrzZrP9OGHb1mPychI15Yt69Sjx8M29z1xIl6ffbbEZszfv65effU/8vGpYh3LysrSRx+9r1Wr/v/q27i4Y9q6db0eeKCHzf0vX76sOXNm5skZHPyIhgwZbc0pSQkJxzVhQojNydX8ZGVl6a23ptmMVa/uq2eemaQ777zLZvzYsSN6661piomJto59/PEHuvvu+3X77bWv+jw3a/HiD/N8LaNGTdCDD/a2KW48dy5FH374lrZt22Ad2717hzZvXpvn3zM/ffoMUL9+j8vbu4J1LCrqJ02dOs7mA5FVq1bo3/9+3bpdvbqvpky58to8+ugDNgU9EyZMV6VKt1zHV2urS5eeGjXqeWurjKFDn7Fmad++ixYseNd67O7dO5SYeOpvP1DIyMiw+beRpPvu63zD2W5U8+aBGjPm37rtthrWsZMnE/TqqxNt3l/Lly9Qr1795Opq+6sjvyvIR44cr+DgR2zGfvstRi+8MNLm9fjoo/d1993352k98tlni/O8x5o0aaFJk16z+Z7NyMjQyy9PKNCqAt99t0U//LDdZiw4+BENHjzCpn1GVlaWvvhiqRYv/vBPz5OuBQve1bhxU675PIUlMzNTYWFf2Iy1bdtOTk5O6tChiz7/fKl1fOvWDcV2hT0AwL5ERl5ZudDf318+Pj6G08CEkjaPSk5OsnnuXM8+O1n/+EewTfHLjh3fXXXV1z8/P/Oo/3ejr3nr1kFq3TpICQnH9cQTva3jtWr5W+dXN2r06Inq1q2PdfvYsSPW95C9zqNudL4qXXnPzp37ts2Yh4enXnnl3TwFWNu2bdSMGZNtxpYunZfv3IR51BUrVy7WypWLr3pMvXoN9eKLb6paterFlAoASo/g4GDdddddql+/vukoAAAAQIHYTRUSK06VXh4ennrrrQXq3Lm7TTGSk5OTevXqp4CA1jbHHz0ak+cxPv54js22r28tvfXWApsTh5Lk6uqqYcPGqFevfjbjixa9J4vFYjO2fftGHT58wGbsuede0siR421yXnm+mnrnnUXX+EqlL75YqmPHjli3K1euqvfeW5rnZL905QOLt99elOfq4b9+sFHY9u2LynPF+X/+s1g9ejyc5/uzQoWKmjjxZXXt+pDN+KJF713zeZ56apyGDRtjcxJaklq0aKX+/R+3GTtw4Jfr+RJuWMeOD+rZZyfbFPn4+FRWjRq1rLeDgjrY3Gfr1vV/+3iRkT/YbN9xR3Ob4qXi0KFDV73yyrt5nrd6dV+NGDHOZiwjI11//JFkM3b06OE8LSDGjPl3nqIpSapdu57ef9/2av6TJxO0YcNqm7GEhON53sdduz6kN974MM/3rIeHh6ZMmaV69Rpe5auUzp8/p7femm4zFhIyViNHjrc52S9d+TnQv/8Tev75l23GN29eq/j4a7fQKCw7dnxr84HL3Xffb/1++Otqahs3hikzM7PYsgEA7IPFYlFISIhCQkK0Y8e1PxyHYymp86hly+blyfnee0vzXTGoTZt7NXnyjGt8pcyjchXGa14Unn12sk3RlHTldcj929Ye51E3O19dv/6/eVYemz37o3xXrWrf/h968cU3bMY2b16r336zff2YR12f3r3/KW/viqZjAIBD6tmzp4YPH6727dubjgIAAAAUiN0VTrHiVOnTvXuffE8e5vrHP4JtthMTT9psnzgRr2+/DbcZ69//8Twn+f7sryf8U1LOKipql3XbYrFo3rx3bI65775OV736t2rVW+Xh4fm3+y0Wi82VmZI0adJrKl/e+2/v4+bmpqefnmgzFhPzf+zdeVid9Z3//xdw2EmAhJAQ9n1fsplEq6bG2Fij1Wqt1lrHperYdrpo/fb7q9N2Wmem029rp5d2GuvSxWVqjTa2UaPGNDqxJlUTOOxLCAkQSCBsgUDCcn5/MNxycyBAWO7D4fm4Lq6c+z6fc/M+wCF87vO635/SMcdPh9/9bqtp+447vjJup5s77/yq6bm3tbWOurzhkOTkNH3mM58f8/6NGz9t2m5uPmF0pZtJd9zxlXHHjPx53LnzFeP310gjfy43bdpy/sWdp/vue0A+Pj6j3peZmeu07EpT03HT9iuvvGDaDgsLP+fzWLJkqa688lrTvldfNS8B+PTTj5m2Q0JCde+933LqdDXE19dXERHnfqPkL3950RRCWrVqndPrfKRPfvJTTksMHj1afc7HTKcdO14ybV922WbjdkpKhmkpjO7u005vIAEAgPnNFedRg6F7c2j+zju/qpSU9DGPGRUVO+Z9EvOo4ab6PZ8J8fFJE5rnzKV51HTMV5999gnT9qZNWxQXlzjmMdevv9RpbrZr16umbeZRk/Mf//E93XzzZr3//jtWlwIAAAC4pW984xtavXq1vvGNb1hdCgCMa86kkAhOzV8jrzoeaeTJw2PHak3bdXVHTNshIaG69NIrxj3m2rWfGHHcOuP2oUPlTiesb7vtH895zPGMrDsyMkaZmbnjPm7kmKNHD6u3t3dKtYzF4XA4vaFw+eVXjfu4BQsWKidnpWlfbW3NedcRFhbutK+treW8jzcRGzd+etTPO9LKlWtNgZaGhnoVFeU7jevq6nQ64T/yKuvZMN7ra+SV+CdPNpm2h1/ZL0k33fQPY56YHzIyOHX4cJUcDoekweUd9u7dbbr/rrv+SX5+fuc85niqqspN26N1NBjJw8NDF1xwkWlfTc2hKdUxUbW1NSoo+NC0b82aj2vx8vLShg2fMt3/5ps7ZqU2AAAwN7jiPGpk0DsiIlKbN5v/Npws5lEfm+r3fCZce+1NE+ocPtfmUecy3ny1q6vT6XzCZz/7hXMe08vLS1u23GDaN7yLE/Mosw0brtB//Md/6ZFHntRPf/prffe7/6577/2WPvnJzaZx3d2n9YMfPKAXX/z9GEcCAAAAAADzwbnf3XYhQ2+qD/0LDAkODjVtjzwB2dBQZ9pOTc0as8POcHFxidq/f++w49Qbt0e21M/JWWUs13a+jhwxX4FZX39UDz309fM6VmNjvaKj46ZUz2iam0+YrjaVpJ///OEJPfaDD8xvktTVHVF29orzriUsLFzNzSeM7VOnOpyWH5hOsbHx4w/S4PIEW7Zcr2effdLYt2vXq05veAz/2ZIGO5ad66p4q4SGLjZtnzrVbtx2OBxOy1WOd9W8NHrXgJaWk1q8OEzHjztf9T4yIHQ+Dh82L2Px/PNP6c03/zLu40a+wXX06PkH/iZjZG2bNm2Rv7+/ad+FF16q7dv/YGy///47amk5qUWLzN8zAACA0Vgxj6qtNYexNm3aYloG+3wwj5q48b7nM2GiX093m0eda746PEw4JD4+adxjjryoZXi4kXmUWVRUjPLy1ox632233atHH/2xPvro4yVsn3zyUa1bd8mMvP4BAAAAAIDrmzPBKWAs51oqQjJfhSlJS5dGTOi4I0M4w8NSI6/yHXkC83zU1h522jfyJPlEeXjMTGe20a5uPt8ap9o9LjR0kelE9ExbunT5hMdu3HiV6YT/G2/8Wffc803Tz+qePW+aHjN8GTZXcq43IVpaTjrtW7x4/K5co71mT5xo0OLFYU6dDSIiIqf8ZlpPT4/pDTtpsMvVyG5ZEzEbXQ/PnDmjv/xlm2nfpZduchqXmZknf/8A05twe/e+rWuuuXHGawQAzA1+fn768pe/LElKSUmxuBq4GivmUTU15r+/IiOndvGJxDxqMsb7ns+Eif7cSO41jzrXfHVkKDEyMmbcLk6DxzRfIFFff1R9fX2y2WzMoyYhIiJS/+f//Eh3332jKTz43HNP6Tvf+ZGFlQGA+/jpT3+qiooKrV27VnfeeafV5QAAAADjcp0zF8B5Gu8EY0dHm2l7ZNeWsSxcGGLabmw8ZtweeVXzyCUPzsfhw9PXun4iS8qdj6ksrzfSZE6gu4Lxlp8bbvnyKK1cuda07733/mrc7uho1/79/2Ns+/sHaNWq9VMvcgac6/U1vPvUkNDQRRM67sjXTFPTcUkzE0oc2SFuKqbjtT6e/fv/xxSG8vcP0IoVFziNs9lsTleRv/ban2a8PgDA3HLPPffonnvuUXJystWlwMXM9jyqv79flZVlpvuYR03eVOZREwnnTDdPz/GX6RviTvOoczl1qsO0PdFAW3BwiNO+9vbB4A/zqMkJDg7RDTd80bRv3753LaoGANxPeXm5Dhw4oMOHnQPuAID5IykpSStXruScFIA5gY5TcHteXrYR2xM7cXv6dKdpOyTk42UNOjtPme5zOAbOs7qPjQzmrFy5Vp/73K2TPo6Pj6/8/PymXM9oRn7t/P0D9L3v/WTSx/Hw8FBaWvZ0leWSPvWpa3TgwH5je+fOV3TFFVdLcj4hu2nTlgkte+JqRnstnTlzZkJvqo1cFiQoaIEk59fdwMDUX1ujXd38/e//P/n5TezNv+FiYxOnXM94Rnab2rRpi7y8vEZdqvbCCy/V669/HJY6fLhK1dWVSkhgIgIAAKZmuudRvb29TmPP52+9kV2hmEe5l/k4j5poN6bTp7uc9gUGMo86XzExCabt7u7TOnWqwyWXfgQAAADmoq9+9atWlwAAE0ZwCm5v+fIo03ZT08SWdxvZVn/58mjT7eLiAmO7sbFhChUOio01n7QLClrgdLWt1aKj45z2uVqNrmLduktMy6gVFxeotrZG0dFxTstLbNhwhRUlTll4uPPV7q2tJ+XvHzXK6I91d3ebOipJ0rJlkaZ/h4xccuJ8DH/tDv98rhguqq2tkd3+kWnfn//8R/35z3+c8DF2737dJZ8bAACYW6Z7HuXn56eQkFBTgP748Qalp08uCDTyohXmUe5lPsyjRnZfamysH2Ok2cmTTabtkJBQI+w33+dR52O0Tl/NzScITgHANLKi2yUAAABwPliqD25v5EnJEycaJ/S4ujpzW/rIyOHBKfObCMeO1Z5ndR8becL/0KGKKR9zukVFmU/4d3ef1smTzRZVc376+pyvdJ8Jfn5+uvLKa037du9+XS0tJ/XRR/uMfRERkcrIyJmVmqabr6+v03ImLS3j/zwcP37MaV94+DJJUkSE+bXV0FCvvr6+KVQ5WGdkZIxp33QuOzGd3nzzL1M+xo4dL035awYAADAT86iRXWcmGhg5F+ZRM6+39+ysfa75MI9aunS5abutrXVCf7+PfL0Mfz3N93nU+WhoqHPaN9FlEwEAE0NwCgAAAHMFwSm4vZFXXhYUfDjuSerW1ha9++4u077hJyJHXnl54MB+1dbWTKnOmJh403Z9/VEVFeVP6ZjTbfHiMPn7B5j2vfnmny2q5vyMXCJuJm3atMW0/dprf9J77+12GjOXTyKMfKPqvff+Ou5jdu161bQdERFpLLEy8g06afCNkqlKTk4zbb/22p9GXfrOSmfOnHFapu98dHefNi1vAgCY3+6++27dfffd2rdv3/iDgWFmYh41svPSzp2vjLqE32Qwj5p5DQ1TD7hNhrvPo0ZefCJJf//73nEf9/rr203bw19P83kedb5KS4tM2/7+AcYFPQCAqXniiSf04Ycf6oc//KHVpQAAAAATQnAKbi8+PtnpJPUbb7xyzse8/vqfnPYNX0JitNb0v//94+dZ4aDly6MVEhJq2vfIIz/S2bOzd3XvRKxZc6Fp+7e//ZXTVeWuZOHCENP2dCxZMFEJCcmmE81tba167LGfmMZs2PCpWatnJqxceYFp++WXn9fp011jju/q6tSLLz5j2rdq1Xrj9qJFYU6vg6eeelQ9PT1TqjM7e4Vp+8CB/dPyRsJ0ev/9d5yWMHz44V/oV796ftyPkW8YvvXWjtksHQDgorq7u3XgwAEdOHBAra2zFx6He5iJeVRSUqrpvoaGeu3cuX3kQyaFedT0CwgIdNrX1HR81j6/u8+jbDab08/D9u0vnPMxhYUHVVlZZtqXm7vKuD2f51Hno6DgI7366kumfTk5q8YYDQAAAOB87Ny5U48//rh27txpdSkAMC6CU3B7AQEBuuOOr5j2/fGPv1dBwYejjt+373/0u99tNe274YYvaunSCGM7JiZeGzd+2jTm3Xd36de//s8xT0xWVpY5hSKG8/b21je+8V3Tvvr6o/rZz/5F7e1tYz7u739/T9/61l1qbj4x5pjp9OUvf91p38MP/x/V1Bwa8zFHjx7WD37wgPbvH/8q2uk2MuT2l7+8qIGBgVn7/Js3f2bM+9LSskxLl8xFW7Z8zukE/S9+8W+jvg5Onz6tf//37zrt/8IX7jBue3p66vbbza/XtrZW/fCH3x5zeZiOjnZVVpaes87Nm691ulr60Uf/Q/v2/c+Yj+noaNevfvUzPfPMr8957Ony6qsvm7aTk9O0Zs2FSkhIHvfjsss2mx777ru71NHRPit1AwAA9zQT86jLLrvSqdvOY4/9RDt3vjJmF5vCwgPnrJN51PQLDV3kFJp77bWXxxg9M9x9HjVyzlNQ8KFefvn5UcfW1R3Vj3/8kGlfcnKaPvGJy4zt+TyPmoyenh69+urL+v73v+V034YNmyyoCAAAAHBfO3fu1BNPPEFwCsCcYLO6AGA2bN58rV544XfGSfHu7tN68MF/1O2336e8vDVavjxax47V6sMP33c6uefvH6DPf/4fnI5522336u23XzPte+ml5/S3v+3RtdfepOjoOIWHL9OxY3X6+9/f044d4y/BtX79pbrssitNV3Du2fOm9u/fqy9+8ctKSkrVkiXL1Np6UnV1R/S3v+0xTqI//fQv9eCD/zLpr81khYcv0ze+8V3953/+q7Hv8OEq3XPPTbrhhi8qO3ulIiOj1dPTo7q6Iyoqyjeee01NlfLy1sjX13fG6xySnJyuPXveNLaLiwv0ve99UzfeeJtCQkJ16FCFioryFRsbr2uuuXHaP/8ll2zSo4/+x6j3XXHFllH3zyV+fn66446v6pFHfmTs27PnTTU2HtPnP3+bEhJS5OnpqYqKEr3wwu9UUVFievytt96txYuXmPZdfvlVeuml53T06GFj30cf7dOtt16tW2+9WwkJyYqIiFJXV6fy8z/Qtm3PnjOUKA1e1X3//d/XvffebOzr7j6t73//W/rEJy7TxRdvVExMvLy8vHTsWK2qqyv14ovPGMe99NJNTl2dplNtbY3s9o9M+y677MoJP/7CCzfot7/9lWnf3r279elPXzct9QEA5qbhQZS5uqQVrDXd8yhfX1/dc8839a//+n9N+3/+84f1zjtv6ZJLLldUVKyCg0NUWVmqd97Zpf37xw5oDGEeNf1yclaaAlvPP/+0zp49q0sv3SQPD09VVBSrsDBfn/70dcrJWTntn9/d51GJiSnauPHTpnMKjz/+c1VXV2rjxisVG5uoU6faVVJi1+OP/9xpvvPlL39dnp7mayHn4zxqLPv371VfX58WLFio/v5+tbSc1IkTjTp48O+jPuerrrp+UvMvAAAAAADgXghOYV7w8fHR17/+/+mf//kbpv2/+c1/jfvY++57QAsXBjvtX7o0Qrfffp/TMRoa6vWrX/3svGu9995v6cCBfWpr+3g5le7u03riiV+c83Fvv/2arr3280pJyTjvzz1Rmzd/Ru+//47Tlc/btj2rbdueHfNxDQ312rFjm66//paZLtFw1VXX609/+m/TleQffPA3ffDB30zjVq1aNyPBqYULg3XJJZfr3Xd3Od33iU9snPbPZ4XBE/6vm7oPlJUV6V/+5dvnfFxMTLw++1nnnwWbzaavfvVBPfjgPzrdN5WrluPjk3TXXV/Tk08+atq/d+9u7d27+5yPffLJR/XDHz5y3p97PG+88WenfcOvIB9PbGyCIiNjVF//8XIvr7++neAUAMxzY3XwASZqJuZRF1+8UatWrdNHH+0z7T9wYL8OHNh/3rUyj5pet932jxOqMyEhaUaCU/NhHnXbbffqo4/eN/3MvvXWjnGX3f7Up65Rbu5qp/3zcR41lsrKMqelDceSmZmre+917kAFAAAAAADmD5bqw7xxwQUXaevW/1ZkZMyExoeEhOpnP3tCV1xx9Zhjbrrpdn3nOw9PV4mSpODgED3xxIvatGlyV9FmZeU5de6ZKR4eHvre9/6f7rzzq5N6XFhYuFJTM2eoqtH5+/vrW9/653HHHTpUPmM15OU5n9S+8MINCg4OmbHPOZtsNpv+7d8e1Re/eNeEH7Nlyw169NHfKyAgYNT7c3NX67HHnlFEROR0lSlJ+tznvqR/+ZefOS0vOJ716y+Z1jqGO3PmjHbseMm0LydnlcLDl03qOCOX66uoKFFra8uU6wMAzF2BgYHaunWrtm7dqgsuuMDqcjBH4T/BkAAAIABJREFUTfc8ysPDQz/84c91441fms4ymUdNs8TEFH3pS/eMO66mpnrGanD3edTSpRF64okXtX79pRN+zD/903f0zW8+NOb982keNVVhYeG6//7v6Sc/2SofHx+rywEAt3L77bdr9erV+sEPfmB1KQAAAMCE0HEKLsdm8zZte3t7jzFykKenl2n7XMsXxMcn6Ze/fFbPPPO4Pvjgb6YW9kMiIiK1cuU6/cM//OOoV0iP9MlPfkpJSal66qnHlJ//waht3y+8cIPuueeb+vrX/8F0NenI2ocsXBisBx74vi6+eKOef/4plZUVjTouJSVDCQnJ2rjx0zNyle+52Gw23XjjbVq//tJzPveYmHglJCTrggsu0qWXXiGbzfnXzsjvuZfX+L+afHzM3+eRxxhu1ap1evzxP+jHP35Ihw9XjTrG3z9APT098vPzG/V45zr+eGJjE532bdxozTIAvr6+pu/TyOUdRhr5+hvr62Cz2XTrrfcoJ2eV/vCH36q0tHDUn4esrDx99rNf0EUXfXLcWpOT0/TLXz6rp5/+pT766H01NNSPOubee+/Xzp2vmK7MPteJ73XrLtGTT27T73//uP72tz2mbmRDwsLClZiYqszMHF1xxTUKDV00br3nq7TU7vS1GhmCmogLL9zgdCV5ff3RGa0dAOD6Vq92Dh7APc2leZTNZtOdd35NWVkr9Mc//k5FRfmjjrvxxi/p4osv19e+9nHIyt8/cMzjzvd51HR+zyXpllvuUnx8kn7yk++PuaRbf3/fOWvy8hp9zjsRrjKPmsn56sKFwfr+9/+fduzYpl27Xhv1ZzYkJFTp6Tm67bZ7FR+fNO7nni/zqOEmMl+PiIhUVFSsoqJiFR+fpA0bPjWry18CwHwy1Pl2vPOOAAD3tnnzZqWnpys2NtbqUgBgXB6OObJ+w/r169Xb26v7779fN998s9XlzHlbv1eu7q5+5VwcpryLZ+fqWlfU09Oj2toaNTTUacmSpYqNTVBAwNgn4ifixIlG1dQcks1mU0RElJYsWTrqSe7J6OvrU2PjMdXWHpaPj6+iomK1ZMlSl5t8Njef0JEj1Tp79owiI2MUERE17sn72dbcfELV1ZXq7+/T4sXhWrx4iUJDF83o17K9vU033rjJ2Pb3D9Af/vCGEdJyV01Nx3X06GH19vYqJiZey5Ytn9LX+dSpDlVXV6qnp1vLli3X0qXLp+VreOpUh44cqVZr60ktXbpcUVExU/49AGdv/7FW9VWdiksL1HVfZqIEAJib/vPbJXIMSBdcsVRpq+dvOHm651F9fX1qaKhTXd0RLVgQrIiIKC1atFgeHh5TqpN51PTo7+/XsWO1Onp08OsYFhausLBwLViwcEY/73ycRw29Fmpra+TvH6DY2EQtWrR4SsdkHjV3/XVbrWorOhWbGqjP3s0cCsDcceutt6q0tFTXXnutHnpo7E6JAAAAgKug4xTmNT8/PyUnpyk5OW3ajhkevmzSS2yNx2azKSoqRlFRE1seQ5La2lo1nblIPz9/+fv7n3PM0Al0V2ZFjSdONJq2L7vsynOeqO7sPKXe3t5p+/w2m23G39QYzZIlS7VkydJpO96CBQuVm7tq2o43/LhZWXkTHt/T0zPmFffni65QAABgLpnueZTNZlN0dJyio+Om5XjDj8s8auq8vLxm5Psznvk4j5qJ14KrzKPc4fsDAJgYOk4BAABgriE4Bbihkyeb9IUvfHpaj/nJT27Wd77zo2k95nxw+nSXtm79mWnfeMuw/dM//YPq649OWw3+/gHavv2daTvefPfUU4/qz3/+47Qe88knX5z1N6IAAABgxjzKdTCPcj98fwBg/khLS1NAQIDi4+OtLgUAAACYEIJTgBuaiRU4HY6BaT+mO+vt7dXevbv1/PNP6ejRw8b+iIhIZWTknPOxAwP9M10epmBgYPpfCzNxTAAA2tradPnll0uSfvKTn+iyyy6zuCLAtTGPsh7zKPfF9wcA5g+W5wMAAMBcQ3AKcEO+vn5auXKt+vun78RkQkLytB3LnX3wwd/0q1/9bMwrab/ylQfHbVOdm7ta4eER01ZTcHDItB0LUmxsvHJzV0/rMYOCFkzr8QAAkMzBXJbJAMbHPMo6zKPcH98fAAAAYH557LHHZLfblZeXp/vuu8/qcgDgnAhOAW5owYKF+vd/f8zqMualjo62MU/233ffA1qz5sJxj/HNb3JVliu75pobdc01N1pdBgAA4yI4BUwO8yjrMI9yf3x/AAAAgPmloqJCBw4c0IIFXDgOwPURnAKAGZaSkqF77/2WMjNzrS4FAADMIwSnAMxlzKMAAAAAAAAwGwhOAcA0Cg1drOTkNC1dulzLl0fpkks2KTk5zeqyAADAPGSz2bRy5UpJUkgISxoBcF3MowAAcB/PP/+8Tp06pZUrV2rNmjVWlwMAsIjD4ZAkeXh4WFwJAIyP4BQATKOVK9dq5cq1VpcBAACgRYsW6de//rXVZQDAuJhHAQDgPp555hk1NTXprrvuIjgFAPPYUHAKAOYCglMAAAAAAAAAAACYst7eXkmSt7e3xZUAAKz02GOPWV0CAEyYp9UFAAAAAAAAAAAAYO7r6+uTRHAKAAAAcwfBKQAAAAAAAAAAAEwZHacAAAAw17BUHwAAAAC4oZMnT2rbtm2SpOuuu07h4eEWVwQAAADA3T366KMaGBhQbGys1aUAAAAAE0JwCgAAAADc0IkTJ/TEE09Iki655BKCUwAAAABm3MqVK60uAQDgAiorK9Xe3q7Q0FAlJiZaXQ4AnBNL9QEAAACAG+rr6zNu22xcMwMAAAAAAIDZ8Ytf/EL33nuvtm7danUpADAuglMAAAAA4IYITgEAAAAAAMAKDodDkuTh4WFxJQAwPoJTAAAAAOCGCE4BAAAAAADACgSnAMwlnD0HAAAAADeUmppqtEMPDw+3uBoAAAAA7u7o0aP67Gc/K0naunWrVq9ebXFFAACrEJwCMJcQnAIAAAAAN7Rw4ULeqAAAAAAwa06fPm3c9vf3t7ASAIDVrrrqKuXl5SkxMdHqUgBgXASnAAAAAAAAAAAAMCXd3d3G7YCAAAsrAQBYbcuWLVaXAAAT5ml1AQAAAAAAAAAAAJjb6DgFAACAuYjgFAAAAAAAAAAAAKbEz89PcXFxCggIIDgFAACAOYOl+gAAAADADe3Zs0fPP/+8bDab/uu//svqcgAAAAC4uVWrVmnbtm1WlwEAAABMCsEpAAAAAHBDtbW1OnDggAIDA60uBQAAAAAAAPPIX/7yFx07dkzJycm67LLLrC4HAM6JpfoAAAAAwA319PRIGlwuAwAAAAAAAJgtr7zyip544gnt3r3b6lIAYFwEpwAAAADADRGcml5FRUVyOBxWlwEAAAAAAODyhs6heHoSRwDg+liqDwAAAADcEMGp89PT06Py8nKVlZWprKxMpaWlOnz4sPr7+3XTxU/Ly5NpNAAAADCavXv3qrm5WUlJScrKyrK6HACAhQYGBiQRnAIwN3DGFwAAAADc0Le//W19+9vftroMl9bV1aXS0lIjJFVeXq7Dhw+POd7Dw2MWqwMAAADmlu3bt2vPnj1au3atfvnLX1pdDgDAQnTtBjCXEJwCAAAAALi99vZ2U0iqrKxMdXV1Y44PCQlRWlqa0tPTlZaWprS0NL34n+1yDMxi0QAAAMAc0t7eLkkKDg62uBIAgNW+853vqLOzU2FhYVaXAgDjIjgFAAAAAHArLS0tKikpMYWkGhsbxxy/ZMkSIxw19LF06dJRRrbPXNEAAADAHDcUnAoJCbG4EgCA1dLS0qwuAQAmjOAUAAAAAGDOamxsNAWkysrK1NzcPOb4iIgIIxyVnp6u9PR0hYaGzmLFAAAAgHvq6OiQRMcpAAAAzC0EpwAAAADADVVVVSkoKEjLli2zupRpU1dXZ4SjSktLVV5erra2tjHHx8TEOHWSWrhw4SxWDADA1DQ3N6upKUBLliyxuhQAGNeNN96o3t5eXXjhhVaXAgAAAEwYwSkAAAAAcEMPPvigjh49qptvvln333+/1eVMysDAgI4cOWLqIlVeXq7Ozs5Rx3t6eiouLs4pJBUQEDDLlQMAML0qKip05ZX3aOnSpcrJyVFubq6ys7OVmpoqm41TuwBcyx133GF1CQAAAMCkMbsGAAAAADc0FDIKCgqyuJJz6+/vV3V1tVNIqqenZ9TxNptNiYmJpoBUcnKy/Pz8ZrlyAABmz/Hjx/XWW2/prbfekiT5+voqIyNDubm5ysnJUU5OjkJCQiyuEgAAABj08MMP6+jRo7r00kt1yy23WF0OAJwTwSkAAAAAcEOuGJzq7e1VZWWlKSRVVVWls2fPjjrex8dHycnJppBUUlKSvL29Z7lyAACskZGRoZQL75bdbldRUZHx//uZM2d08OBBHTx40BgbHR1tClIlJibKw8PDqtIBAAAwjxUVFamqqkoJCQlWlwIA4yI4BQAAAABuZmBgwAgjLViwwJIaenp6VFFRYQpJVVdXq6+vb9Tx/v7+SklJUXp6uhGSio+Pl5eX1yxXDgCA6wgJCdFn775bkuRwOFRTUyO73a7CwkIVFhaqurpaDodDklRbW6va2lrt2LFD0mB4OisrywhSZWdnKzAw0LLnAgAAgPlj6G9UT09PiysBgPERnAIAAAAAN3P27FnddNNNampqUmRk5Ix/vq6uLpWXl6u0tNQISR05ckQDAwOjjg8KCjJ1kUpLS1NsbCxdMQAAOAcPDw/Fx8crPj5en/nMZyQNdpgsKioyglSFhYU6deqUcd++ffu0b98+4/GJiYmmrlTR0dGWPR8A7mXXrl16++23FR0drfvuu8/qcgAAFuvv75dEcArA3EBwCgAAAADcjJ+fnx544IEZOXZHR4cpIFVWVqba2toxx4eEhDiFpKKiomakNgAA5pugoCCtW7dO69atM/aN7Ep16NAhORwOORwOVVVVqaqqSi+99JIkKTQ01AhR5ebmKiMjQz4+PlY9HQBzWFFRkd566y0tX76c4BQAgI5TAOYUglMAAAAAgFG1tLQYIamhfxsbG8ccHxYW5hSSWrZs2SxWDAAA4uLiFBcXp2uuuUbSYGfIkV2pOjo6JEmtra1655139M4770iSbDabUlNTjSBVbm6ulixZYtlzATB3HD9+XJIUHh5ucSUAAFcwFNQHgLmA4NQ8ZYR7HZaWAQCYJxwDQ1eXsAQTALiqxsZGp+X2mpubxxy/bNkyU0AqIyNDixYtmsWKZ5+np4f6BxxiIgUAmGmO/13tdjou0A8MDNTatWu1du1aY19NTY2Kiopkt9tlt9uNrlR9fX0qLi5WcXGx/vu//1vS4P/5Q12pcnJylJqaKi8vr6kXBsCtDF1gwYUTAAAAmGsITs1T/oFe6jrVrzPdfVaXAgCYB86cHvz/JiCIPz0AwGoOh0N1dXUqKytTeXm5EZJqa2sb8zHR0dGmkFR6eroWLlw4i1W7Br8AT3V19Kvn9IDVpQAA3FzPDM+hhrpSbdmyRZJ0+vRpFRcXm5b4a29vlzQYhmhsbNSbb74paXBJ4IyMDNMSf8HBwTNSJ4C5o6GhQZK0fPlyiysBAAAAJod3L+cp/wU2qfGserr6rS4FADAPdP/v/zcBC7kqGQBmw65du/T2228rKipKmzdvNgWkKioq1NnZOerjPD09FRsb67TcXmBg4Cw/A9cUuMBbXR396u7stboUAICb6+763+DUwtk5fRsQEKA1a9ZozZo1xr6jR4+aglRVVVUaGBhQT0+PDhw4oAMHDhhjY2JijBBVTk6OEhIS5OFBx2FgPtm+fbsaGxsVEBBgdSkAAADApBCcmqfCI/1UW3lazQ3dVpcCAHBzPZ19On1q8KR/eKS/xdUAgPvq6+tTVVWVysrK9OKLL6q8vFyS9Jvf/GbU8TabTQkJCaaAVEpKivz8/Gaz7DllSaSfTtT36GRDj9WlAADc2JnufnW1D82hrPt/OSYmRjExMUZXqp6eHmN5v6Ew1VDHyqNHj+ro0aPasWOHJCkoKEhZWVlGkCo7O5swBeDm/Pz8FBcXZ3UZAAAXUVhYqDNnzmj58uV0IwTg8ghOzVMJGQv00Z4WdbX3qaWxW4uW8UY2AGBmHCnvMG7HpS6wsBIAcB89PT2qrKw0ukiVl5erqqpKfX2Db7I6HA55eHgY//r6+io5OVlpaWlKTU1VWlqakpKS5O3tbfEzmVviMxao+O9tajl+Rl3tvQoM5usHAJh+R8rajdvxaa6zNK6fn59Wr16t1atXG/tqa2tNQarKykoNDAyos7NT+/bt0759+yRJHh4eSkpKMi3vFxUVZdVTAQAAwAz79re/rebmZt1111269957rS4HAM6J4NQ8FRkfKJuPh/rOOpT/brMuuzHa6pIAAG5ooH9A9r3NkqTIhAB5+7JUAwBMVldXlxGOGgpK1dTUaGBgYNTxAQEBstls6ujoUHJysh5++GHFx8fLy4vlUqcqLjVIHh6SwyHl/88JXbQl0uqSAABuZqDfocL3TkqSlsf7u/wcKjo6WtHR0brqqqskfdyVaihIZbfb1dbWJofDocrKSlVWVuqll16SJIWEhCgvL0/Z2dnKzMxUWlqagoKCrHw6AAAAmCb9/f2SxPkoAHMCwal5ysNTWnHxIn3w9knVVXWqruqUopLoAgIAmF4H321Sd9fgBGnVJxdbXA0AuL7Ozk6VlJSotLTUCEnV1taOOT44ONjoIDXUTSomJka33nqrOjo6jM5SmB7ePh7KXhcq+/utOmTvUEpeqJZEsewQAGD6FOxtVlfHYAfJVRvCLK5m8kbrSlVXV2eEqIa6UvX396utrU179uzRnj17JA12pUpISFB2drZyc3OVnZ3Nsl/AHLF3717ZbDZlZ2crMDDQ6nIAAC5g6II/glMA5gKCU/PYusvDVfz3Np0+1a89L9XryltjtXg5S/YBAKbHocJWFb/fIkmKSwtUYgYBXQAYrr29XSUlJUZAqrS0VMeOHRtzfFhYmGmpvbS0NEVERIw69tlnn1Vtba08PT1nqvx56xNXLVVFQbt6Tg9o1wu1uvJLsQpZ4md1WQAAN3CosFWF7w127I1KDFBSlnvMoaKiohQVFaUrr7xS0mBXqpKSEtMSfy0tLXI4HDp06JAOHTqk7du3S5IWLlyo7OxsY4m/zMxMBQQQWgZczdNPPy273a4NGzbopz/9qdXlAABcwFDHKc5NAZgLCE7NYzYfD33mjhj98Zc16u9z6I3nj+iyz0VrWSxXhAAApqb8QIv27zwuSVq4yFtXfiHK4ooAwFotLS2mkFRZWZkaGxvHHL906VKlp6cbAamMjAwtWrRoUp8zOprluGeCr7/n4Dzqv2rUe2ZAbzx7RBs/H6MwLkIBAExBlb1Vf9sx+LdBULBNV93qvnMoPz8/rVy5UitXrjT2tbS0yG63Gx+lpaU6c+aMOjo69N577+m9996TNPjGW2JiotGRKjc3V1FR7vu1AuaKiooKSVJ8fLzFlQAAXMWPf/xj1dfXKzk52epSAGBcHg6Hw2F1EROxfv169fb26v7779fNN99sdTlu5XBpp7Y/edTYXrMpXMm5IbL50DoRADA5pzt6Zf9bsyoOtEmS/AO9dNM/xSskzMfiygBg9pw4ccK01F5paamam5vHHB8ZGWkEpIZCUsHBwbNYMc5HeUG7Xvt9vSTJ08tDF1wRrsTsEHnZuJISADBxpzt6Vfh+s8o/+ngO9fmvxSt0yfyeQ/X19am8vFyFhYUqKChQYWHhmKHzkJAQoyNVTk6OMjIy5OdHN0hgtjQ3N2vz5s2SpB/96EdGdzkAAABgriA4BUnSscOn9acnj+psz/+uN2vzUFzGQiXnBis8mg5UAIBzO1LWocqCNh071GXsWxTuo8/eHasFod4WVgYAM6uhocEUkCorK1NLS8uY42NiYpSWlmZ0k0pPT1dQUNAsVozpdLisU3/5ba36ewen1TYfDyVkBSspO1hhkSwjBAAY2+hzKG9d9+U4LVzEHGo0zc3NKigoMLpSlZWVqbe312mcl5eXkpOTTV2pxlreGMDU7d+/X1/5ylckSc8//7xSUlIsrggAAACYHIJTMLQ2ndVrz9TpRH2Pab+nzUOBC2zyD2JlRwDAxxwDDp0+1aeujj6n+1JXLNDlN0TKx4+uGwDcx7Fjx1RaWmrqJtXW1jbqWE9PT8XGxpqW20tLS1NAwMyHaVpbW9Xa2qrw8HBCWbOg6dgZvf5srU4eP2va7+XtoaCFNvkGMI8CAAxyOBw63cEcarr09vaqtLRUdrtdhYWFstvtampqGnVsWFiYEaLKyclRWlqafHzmd1cvYLo0NTXpzTffVHFxsf7t3/7N6nIAAACASSM4BSfl+e36+1tNam48O/5gAACGiU4K0Cc+Ha5lsXTZADC31dfXGwGpoX/b29tHHevl5aWEhARTQCo1NdWyJWK2bdumH//4x5Kkffv2yWYjuDMbSj5s0743m9R+0rnzBQAAY4lMCNDFV4UrIo451HRobGw0OlLZ7XZVVFSor885qGaz2ZSWlmYEqXJzcxUWFmZBxQAAAAAAq3EGHU5S84KVmhesU629qrR3qK35rDpP9aqna8Dq0gDLlZaWqru7W4sXL1ZsbKzV5QCW8vSU/AO9FLjQW4uX+So5J1h+AVwdDWDuqaurMwJSQyGpjo6OUcfabDYlJiaalttLTU2Vt7frLKlz7NgxSdKyZcsITc2ijNUhylgdopONZ1RT1qm25rPqOtWrntPMozC/tba26vDhw5KknJwcfi9hXvPwkAKCBudQi5b6KCUnWH6BXlaX5VaWLVumZcuW6YorrpAknT17ViUlJaYwVUtLi/r6+lRUVKSioiI999xzxmNzcnKMj5SUFH5nAQAAnKe7775bkvSlL31Jn/jEJyyuBgDOjZkfxrQg1FsrL11sdRmAS7nllu+qvLxc1113nW78yqVWlwMAACaprq7OCEgNhaROnTo16libzaakpCRTSColJcWlQlKjGQpORUREWFzJ/LR4ma8WL/O1ugzAZezaVaUntg8u2/N/H3lbwcHBFlcEYD7x8fFRXl6e8vLyjH11dXUqLCxUQUGB7Ha7qqqqNDAwoMbGRjU2NurNN9+UJPn6+iojI8MIUuXm5iokJMSqpwIAADBn9Pb26sCBA5Kkq6++2uJqAGB8BKcAAAAAuB2Hw6Ha2lqnTlKdnZ2jjh8KSaWnpxsfSUlJLh+SGk1DQ4MkKTIy0uJKAAAAXE9UVJSioqJ05ZVXSpJ6enpUVFRkBKkKCwvV0dGhM2fO6ODBgzp48KDpscOX90tISJCnJ52XAQAAhuvv7zdue3nRYRWA6yM4BQAAAGDOq62tdeokNVZIytvbe9SQlLssxbJhwwZFRUVp1apVVpcCAADg8vz8/LR69WqtXr3a2FdTU2Na3q+6ulrSYLequro6vfrqq5KkwMBAZWVlGUGqrKwsBQUFWfI8ACts27ZNL7zwgnJycvTP//zPVpcDAHARfX19xm2CUwDmAvd4ZwAAZslDDz2krq4uLVmyxOpSAACYt0Yut1daWjpmSMrHx0fJycmm5fbcKSQ1mttvv93qEgAAAOa0uLg4xcXF6ZprrpEkdXZ2Gsv7FRYWqqioSF1dXerq6tL+/fu1f/9+SZKHh4cSExOVnZ1tdKaKiYmx8qkAMyo/P1+HDx/mTXEAgAkdpwDMNe77bgEAzID09HSrSwAAYF6pr683OkiVlJSotLRUp06dGnWst7e3kpOTnTpJcYIGAAAAUxEUFKT169dr/fr1kqSBgQFVV1crPz/f6EpVV1cnh8OhqqoqVVVV6U9/+pMkKSQkRDk5OUZXqoyMDPn6+lr5dIBpU1BQIEnKycmxuBIAgCsJDg7W1q1bJUlJSUkWVwMA4yM4BQAAAMAlNDQ0GOGosrIylZaWqr29fdSxNpvNWG4vIyPD7ZbbAwAAgOvy9PRUUlKSkpKSdMMNN0iSWltbVVBQYASpSkpKdPbsWbW1tendd9/Vu+++K2nw79iUlBQjSJWXl0dnc8xJbW1tamhokCTl5uZaXA0AwNUMXwYZAFwd7yoAAAAAmHVNTU0qKSkxPkpLS9XW1jbqWJvNpsTERKOLVEZGhpKSkuTt7T3LVQMAAACjCw0N1YYNG7RhwwZJUl9fn8rKyowwVUFBgZqbm9XX12f8DfyHP/xBkhQeHm50pcrJyVFaWhoXBMDl1dbWKiAgQKdPn9bKlSutLgcAAAA4b8y+AAAAAMyotrY2FRcXm0JSzc3No4718vJSQkKC0UUqPT1dKSkphKQm6Le//a0OHTqkvLw8XX/99VaXAwAAMG/ZbDZlZWUpKytLt9xyi6TBDqvDu1JVVFRoYGBAJ06c0K5du7Rr1y5Jko+Pj9LT05WdnW2EqcLCwqx8OoCT7Oxsvfvuuzp06JAiIiKsLgcAAAA4bwSnAGASbrnlFpWXl+u6667Td7/7XavLAQDA5XR2dqq4uFilpaXGv42NjaOO9fLyUnx8vGm5vZSUFPn4+Mxy1e5jz549KioqkoeHB8EpAAAAFxMREaGIiAht3rxZktTT06PCwkIVFBQoPz9fhYWF6urq0tmzZ1VQUKCCggLTY3NycowwVUpKCl2p4BISExOtLgEAAACYEmZWAAAAAM5Ld3e30UFqKCRVV1c36lgPDw/FxsYqIyPD+EhNTZWvr+8sV+3eqqqqJEkJCQkWVwIAg7y8vIzbAwMDFlYCAK7Hz89Pa9as0Zo1ayQN/p6srq5Wfn6+8vPzVVBQoIaGBkmD3aoaGhr0xhtvSJJ8fX2VkZFhWuIvNDTUsucCAAAwpLKyUjfffLOkwe7oWVlZFlcEAOdGcAoAAADAuM6cOaOysjKVlpYaS+4dOXJEDodj1PFRUVFGJ6mhD39//1muen5pbGxUT0+PJK76BuA6hgen+vv7LawEAFyfp6enkpKatoSGAAAgAElEQVSSlJSUpBtuuEGS1NzcbHSfOnDggMrKyiQN/n1+8OBBHTx40Hj8okWLlJOTo9zcXOXm5iotLY1urgAAYNb19vYat+mQCWAu4DcVAAAAAJO+vj5VVVWpuLhYJSUlKi4uVnV19ZidQpYuXar09HRlZmYqPT1dWVlZCgoKmuWqcejQIeN2cnKyhZUAwMeGB6f6+vosrAQA5qawsDBt3LhRGzdulDS4vF9RUZERprLb7ers7JQktbS0aM+ePdqzZ48kydvbW+np6UaYKi8vj65UmBZPP/20QkJCtHHjRgUHB1tdDgDAxQwPTnl7e1tYCQBMDMEpAJiE9PR0BQYGKjY21upSAACYFg6HQ4cPHza6SJWUlKi8vNx0gmO4RYsWmbpIZWZm8uaLi7jooou0c+dONTU1admyZVaXAwCS6DgFANPNz89Pq1ev1urVq419lZWVys/P16FDh5Sfn28s39zb2yu73S673a5nn31WkrR8+XJlZ2drxYoVysnJUUpKiiXPA3NXf3+/nnrqKZ05c0bV1dV64IEHrC4JAOBi6DgFYK7hNxUATMJDDz1kdQkAAExJfX290UWqtLRUpaWlOn369Khjg4KCjE5SQ0EpAjmuLSwsTGFhYVaXAQCG4SfJCU4BwMxITk42dRzt6upSYWGhEZoqLCxUV1eXJOnYsWM6duyY3njjDUlSYGCgsrOzja5UWVlZCgwMtOR5YG748MMPdebMGUnSJZdcYnE1AABXFBAQoPj4eDU1NdFxCsCcQHAKAAAAcFOtra0qLCw0BaXa2tpGHevn56fU1FSji1R6ejodFgEAU+bp6WncJjgFALMjMDBQ69at07p16yRJAwMDqq6uNpb2KygoUF1dnaTBkNW+ffu0b98+SZKHh4eSkpKUm5ur3Nxc5eTkKDIy0rLnAtfz17/+VZK0YMECrVq1yuJqAACuKCMjQy+++KLVZQDAhBGcAgAAANxAd3e3iouLVVRUpOLiYpWUlOj48eOjjrXZbEpKSjItt5eQkGBaTgkAgOnAUn0AYD1PT08lJSUpKSlJ119/vaTBiywKCgqUn58vu92u0tJS9fb2yuFwqLKyUpWVldq2bZskafHixUaIKi8vT6mpqXSPmMfy8/MlSRs3bmQOCQAAALdAcAoAAACYY/r6+lRRUaHi4mLjo6amRg6Hw2msh4eH4uLiTCEp3uhwP21tbfLw8FBwcLDVpQCAia+vr3G7p6fHwkoAAMOFhoZqw4YN2rBhgyTp7NmzKi0tNXWlam1tlSSdPHlSu3fv1u7duyVJPj4+ysjIMLpS5ebm8nfoPPKHP/xBH330kUJCQqwuBQAAAJgWBKcAYBJeeuklNTc3KyMjQxdffLHV5QAA5gGHw6EjR44YXaSKi4tVXl6u3t7eUccvX77cCEgNhaX8/f1nuWrMttdee02PPPKIIiMj9corr1hdDgAYgoKCjNtdXV0WVgIAOBcfHx8jBDWktrZWBQUFxkd1dbWkwZBVfn6+0XlIkuLi4kxBKpb9dm8s0QcAAAB3QnAKACbh5ZdfVnl5ua677jqCUwCAGdHS0iK73W50kiopKVFnZ+eoY0NCQpSZmWl8ZGdna+HChbNcMVyB3W6XJC1YsMDiSgDAbHhwaqz/zwAArik6OlrR0dHasmWLpMHf40MhKrvdrqKiIqObYE1NjWpqaowQf0hIiLG8X25urjIyMuTj42PZcwEAALOntLRU7777riTpnnvusbgaABgfwSkAAADAIj09PSouLlZRUZHx74kTJ0Yd6+fnp7S0NFNQKjIycpYrhqs6ePCgJCkrK8viSgDAbHigl45TADC3BQUF6aKLLtJFF10kServ71d5ebmpK1VTU5OkwaWk33nnHb3zzjuSJG9vb6WnpxsdqfLy8ljqDQAAN2W32/XEE0/IZrMRnAIwJxCcAgAAAGbBwMCAqqurVVRUZHxUV1drYGDAaaynp6cSExOVmZmprKwsZWZmKjExUZ6enhZUDldXX1+vkydPSpJWrFhhcTUAYObp6SkfHx+dPXuW4BQAuBkvLy9jefCbb75ZktTQ0GAKUlVWVsrhcKi3t1d2u112u13PPPOMpMGOVkMhqtzcXMXHx1v5dDCOxx9/XEuWLNHll19Op2MAwDmdPXtWkug2CWDOIDgFAAAAzIDjx4+bOkmVlpaqu7t71LHLly83ukhlZWUpPT1dvr6+s1wx5qqgoCA98MADKioq0po1a6wuBwCcBAYGEpwCgHkiIiJCERER2rx5syTp9OnTKiwsNIJUhYWFOn36tCSptrZWtbW12rFjh6TBLoVDS/vl5uYqMzOTeZGLaGtr05NPPimHw6H29nbdfvvtVpcEAHBhBKcAzDUEpwBgEh566CF1dXVpyZIlVpcCAHAh3d3dRkBq6KO5uXnUsQsWLDACUllZWcrJyeFqXUxJcHCwbrrpJqvLAIAxBQYGqrW1VW1tbVaXAgCYZQEBAVq7dq3Wrl0rabATb1VVlRGkys/PV2NjoySpo6NDe/fu1d69eyVJNptNaWlpRpBqxYoVCg0Ntey5zGfbt2+Xw+GQh4eHrrvuOqvLAQC4OIJTAOYaglMAMAnp6elWlwAAsJjD4dChQ4dMIalDhw7J4XA4jbXZbEpOTjZCUpmZmYqLi7OgagAArBMSEqK6uroxQ8UAgPnD09NTKSkpSklJ0ec+9zlJUlNTkxGiKigoUEVFhfr7+9XX12fMuZ577jlJUlRUlLG039Dyfh4eHlY+pXlh27ZtkqQNGzYoJCTE4moAAK7u6quv1po1a+Tn52d1KQAwIQSnAAAAgHNob283lpQoKipSSUnJmEsNRUZGmrpJpaeny9vbe5YrBgDAtQx17G1pabG4EgCAK1qyZIkuv/xyXX755ZKknp4eFRUVKT8/X/n5+SosLDTmYHV1daqrqzOW91uwYIERosrNzVVWVhbdLaZZdXW10RVsKOwGAMC5REVFKSoqyuoyAGDCCE4BAAAA/6uvr09lZWUqKioyglL19fWjjh255F52draCg4NnuWIAAFxfWFiYJOnkyZMWVwIAmAv8/Py0evVqrV69WtLg8n6HDh0yulINX97v1KlToy7vl5eXpxUrVigvL4952hQlJCRoz549+utf/6oLLrjA6nIAAACAaUdwCgAAAPPWsWPHjIBUYWGhysvL1dvb6zTO09NTSUlJys7OVnZ2trKyslhyDy7hhz/8oaqqqnTllVfq5ptvtrocABjVUMcpglMAgPPh6emp5ORkJScn64YbbpA0uLzfUIhqaHm/gYEB0/J+zz77rCQpLi5OeXl5xgcdMCYvKChIV199tdVlAAAAADOC4BQATMLDDz+so0eP6pJLLtEXv/hFq8sBAEzCmTNnVFpaKrvdLrvdrsLCwjHfwF28eLERkMrOzlZmZqb8/PxmuWJgfO+8847a29uNq/EBwBUNdZzq7OxUb28vy9gCAKZsyZIl2rRpkzZt2iRpcHm/goICoytVYWGhuru7JUk1NTWqqanR9u3bJUmLFi0yBalSU1Pl5eVl2XMBAAAAYC2CUwAwCaWlpSovL1dsbKzVpQAAxtHQ0GAEpOx2uyoqKtTX1+c0ztvbW6mpqUY3qezsbEVERFhQMTA5RUVFam9vlyRdeOGFFlcDAGMb6jglDXYIWb58uYXVAADckZ+fn9auXau1a9dKkvr7+1VZWWl0pcrPz1dzc7MkqaWlRbt379bu3buNx2ZlZRlBqpycHAUEBFj2XAAAmOvuv/9+lZeX61Of+pS+9rWvWV0OAIyL4BQAAADmvLNnz6q0tNQISdntduOk+Ejh4eHKyclRdna2cnJylJaWRucLzEl79uyRJPn6+mrFihUWVwMAYxseSG5oaCA4BQCYcV5eXkpLS1NaWppuuukmSVJ9fb1peb/q6mpJg92qPvzwQ3344YeSPl4aMC8vT7m5uVq5cqXRPXE+eeSRR3Tq1Cndcccdio6OtrocAMAccurUKTU2NurYsWNWlwIAE0JwCgAAAHNOY2OjEZIqLCxUWVnZqN2kbDab0tLSjJBUTk6Oli5dakHFwPTz9/fXggULdMEFF7C0CACXNvzN1traWq1atcrCagAA81VkZKQiIyN11VVXSRpcQvbgwYNGmKqkpES9vb0aGBhQeXm5ysvL9cILL0gaDAEPX94vISFBHh4eVj6dGdXc3Kw//vGP6uvrk7+/vx588EGrSwIAzCE9PT2SBrs6AsBcQHAKAAAALq2/v18VFRUqKCgwPk6cODHq2LCwMCMglZ2drfT0dPn4+MxyxcDsuPPOO3XnnXeO2V0NAFyFl5eXli9frmPHjuno0aNWlwMAgCQpKChIF198sS6++GJJg52MS0pKTF2pTp06JWmwY2JDQ4Nef/11SdLChQuVk5NjBKkyMzPdqpPx1q1b1dfXJx8fH91xxx1WlwMAmGMITgGYawhOAcAkPPfcc1aXAABur7OzUwUFBbLb7SooKFBRUZEx2R7OZrMpJSXFCErl5ORo2bJlFlQMWGs+LhsCYO6JiYkhOAUAcGk+Pj5GEEqSHA6HqqurjSBVfn6+GhoaJEkdHR3au3ev9u7dK0ny9vZWZmamVqxYoRUrVig3N1eBgYGWPZepqK+v15///GdJ0k033cR8AwAwaTExMero6Jiz/xcCmH8ITgEAAMBSdXV1xtW8drtdhw4dGnVccHCwsrOzlZeXp5ycHGVlZdFNCgCAOSI6Olr79u0jOAUAmDM8PDyUmJioxMREXX/99ZIGl7A7cOCAEaSqrKyUw+FQb2+vse83v/mNPDw8lJycbASpVq5cqUWLFln8jCamu7tbF1xwgUpKSnTnnXdaXQ4AYA766U9/anUJADApBKcAAAAwa4aW3Rt+xe7JkydHHRsbG6vc3Fxj+YO4uLhZrhYAAEyXmJgYSdKRI0fU19cnm41TUgCAuScsLExXXHGFrrjiCklSV1eX7Ha7Mb8tLi5WT0+PHA6HKioqVFFRoRdeeEGSFBUVpby8PK1YsUJ5eXmKjY218qmMKSkpSY899phaW1vpFAIAAIB5gbNUAAAAmDFnzpwxnUS22+3q7u52Gufj46OMjAzl5uYaH8HBwRZUDLi+X//61yooKNDVV1+tzZs3W10OAExIUlKSpMEQdWVlpdLT0y2uCACAqQsMDNT69eu1fv16SVJfX5/Kysp08OBBHTx4UAUFBWpvb5c02G25rq5OO3bskCSFhoYaIaoVK1YoNTVVnp6elj2XkUJDQ60uAQAAAJgVBKcAYBJKS0vV1dWlJUuWuOxVYQBgpfb2duMEcX5+vsrLy9XX1+c0Ljg4WLm5ucrLy1NeXp4yMjLoPAFMgMPh0Msvv6zm5mYtWLCA4BSAOWN4UKq0tJTgFADALdlsNmVlZSkrK0u33nqrJKm6utqYIx88eFCNjY2SpNbWVu3evVu7d++WJAUEBBgdl1esWKHs7GyWpwcAAABmAe9OAcAkPPzwwyovL9d1112n7373u1aXAwCWa2pq0ocffvj/s3fnYVXW+f/HnwdBQBAQcfu6m6kgbiwKKi5JZoappRVao1M25XeysbTJvjmlaZs61a/JtKYyGyvHNNcUE02SFAUFzVxyQ8XcCAFZDuv5/cFwJkenRIEPy+txXXNdeJ8bep5rrktv7vO+Px/27NlDYmIiycnJ1zyvefPm9iGp7t2707Zt20ouFakZEhISSE1NBWDYsGGGa0RErp+7uzstW7bk9OnTHDx40HSOiIhIpWnXrh3t2rXj3nvvBUp+j969e7f9oaPjx48DkJOTQ1xcHHFxcUDJEJafnx89evSwr0zl7u5eIY3nz5/nyy+/ZOLEiRXy80VEpPbIyclh5cqVNG7cmODgYLy8vEwniYj8Jg1OiYiIiMh1S05OJikpyT4odfbs2avOcXBwoEOHDvYhqYCAALy9vQ3UitQ8q1evBqBhw4b27UBERKqLzp07a3BKRERqvUaNGjFkyBD76rGZmZlXrNx88OBBioqKKCwsZN++fezbt4/FixdjsVho3749PXr0ICAggMDAwHLbTu/ll19m+/btbNy4kVWrVpXLzxQRkdrp0qVLvPnmmwC88847hISEGC4SEfltGpwSERERkWuy2WwcOXLEPiSVmJhIWlraVec5OTnRuXNn+1OwAQEBuLi4GCgWqflsNht169Zl1KhRODg4mM4RESkTX19foqKiOHLkCIWFhdqmV0REBPDw8KB///70798fAKvVyvfff2//Pfz777/HarXaf0c/cuQIy5YtA6BFixYEBAQQEBBAjx49aN68eZn/+19//TXbt28HYOjQoeX3xkREpFbKycmxf12vXj2DJSIi1093qEREREQE+Peg1O7du+3b712+fPmq81xcXOjatSsBAQF0796drl27UrduXQPFIrXPyy+/TG5uLkVFRaZTRETKzM/PD4CioiL2799P9+7dDReJiIhUPS4uLgQHBxMcHAyU/Lt58OBBEhMT2bNnD0lJSfbf1VNSUkhJSWHNmjUANG7c+IqHmtq1a/er/62MjAxee+01ANq2bcvDDz9cge9MRERqg+zsbPvXbm5uBktERK6fBqdERMrgnnvuITU11X7DX0SkOrPZbBw7doyEhAQSEhJITEwkIyPjqvPc3d3tW+716NEDPz8/6tSpY6BYRABcXV1NJ4iI3JDOnTvj5OREQUEBcXFxGpwSERG5DnXq1MHf3x9/f38eeugh++/ye/bssQ9SpaamAnDhwgU2btzIxo0bAfDy8rIPUQUEBNChQwcsFov9Z1+8eBEPDw8yMzOZNWuWVoMUEZGb9ssVpzQ4JSLVhcVms9lMR1yP0NBQCgoKmDJlCpGRkaZzRERERKql48ePk5CQwO7du9m9ezfp6elXnePt7W1/QrVHjx5X3VgVERERuVGTJk1ix44d+Pv78/HHH5vOERERqRFOnz5tX5EqMTGRM2fOXPO80gejAgMDCQgIoFOnTtSpU4edO3fSq1evSq4WEZGaKDk52T7AO27cOFxcXAwXiYj8Nj0+ICIiIlKDnT9/nri4OOLj49m1axdpaWlXnePl5UVAQABBQUEEBQX95lL+IlL5fv75Zxo2bGg6Q0TkpvXu3ZsdO3awf/9+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Z4mIiFRJsbGx/N///R/z58+nS5cupnOMadSoEXfffTd33303NpuNH3/8kbi4OHbu3ElSUhL5+fmcOXOG5cuXs3z5chwdHenatat9kKpjx45YLBbTb0NEpEa4dOkSAD4+Pvq7VUSqFQ1OiYiUga+vL25ubrRu3dp0iohUkOPHj7NkyRKioqLIz8+3Hw8KCuKBBx6gX79+ODg4GCwUkZrkk08+ISwsjLZt21dsP9kAACAASURBVJpOERExrnHjxrz++us8/vjjJCcn88ILLzBnzhzTWSIiIlXOihUrePXVVwF46qmnWLdunYaNAYvFQseOHenYsSPjxo0jLy+P3bt3ExcXx44dOzhx4gSFhYXs2bOHPXv2MH/+fLy8vAgJCSE0NJTevXvToEED029DRKTaKl1xSqupi0h1Y7HZbDbTEdcjNDSUgoICpkyZQmRkpOkcERERqWGOHj3KO++8Q2xsrP2Yi4sLd911F5GRkbRp08ZgnYjURLGxsUyePBmAhQsXEhQUZLhIRKRqeO+99/j73/8OwNNPP82YMWMMF4mIiFQdn332GW+88QYAjo6OzJ49m/DwcMNV1UNqaiqxsbH2FakuX7581TmdOnWiT58+9OnTB39/fz08JyJSBlFRUcTFxeHj48MTTzxhOkdE5LppcEpERERqteTkZBYsWMDmzZvtxzw8PHjggQeIjIykfv36ButEpKY6d+4cY8eOJSMjg44dO/Lpp5+aThIRqTJsNhuPP/44u3fvpk6dOvz973+na9euprNERESqhPnz57No0SIaNmzIG2+8QefOnU0nVUvFxcX88MMP7Nixgx07dvDDDz9QXFx8xTmenp6EhobSp08fevfujaenp6FaEREREalIGpwSERGRWikrK4t3332X5cuX22+MNWzYkDFjxnDffffh6upquFBEaiqr1cr48eM5evQozs7OfPbZZ9oGWETkP6SnpxMZGcnFixfx9PTko48+0t+VIiIi/7Jw4UJGjx5Nw4YNTafUGFlZWezYsYPvvvuO7du327ebKmWxWOjcuTN9+vShb9++dOrUCYvFYqhWRERERMqTBqdERESk1lm7di1vv/02ly5dAqBp06Y89NBDjBw5krp16xquE5GarqCggFmzZrF+/XpmzJhBRESE6SQRkSrp2LFjPPLII2RlZeHj48MHH3xAixYtTGeJiIhIDWez2Th06BDfffcd33333TVXo/L29qZv376EhYUREhKiB/BEREREqjENTomIlMGKFStITU3Fz8+PsLAw0zkiUkZHjhzh1VdfZd++fQC4uLjwyCOP8NBDD+Ho6Gi4TkRqm/j4eIKDg01niIhUaT/88AN/+MMfyMvLo0mTJnz88cc0atTIdJaIiEiliI6OJioqijlz5uDg4GA6p9bKzMy8YjWq9PT0K153dHQkKCiIvn37MmDAAJo2bWqoVERERERuhAanRETKYOzYsRw+fJiRI0fy/PPPm84RkTL49NNPefvttykqKgIgPDycqVOn4uPjY7hMRERERH7N7t27+eMf/0hhYSGtWrXigw8+wNvb23SWiIhIhcnNzeVvf/sby5YtA+DRRx/lscceM1wlULIa1Q8//MC2bdvYtm0bP/7441Xn3HLLLfTv35/+/fvj5+enLf1EpFY4e/Ys8+bNo1GjRowfP15DpCJSrWhpBREREanRcnNzef755/n2228BaNmyJS+++CLdu3c3XCYitUlGRgaenp6mM0REqqXAwEDmzp3L008/zalTp/j973/PwoULadasmek0ERGRcnfo0CGmTp3KuXPnAAgKCuL+++83XCWlLBYL/v7++Pv7M3HiRFJTU9m6dSuxsbHEx8eTl5fHsWPHOHbsGB999BE+Pj6EhYXRv39/evXqhZOTk+m3ICJSIc6cOUNMTAwADzzwgOEaEZGy0dquIiIiUmOdOnWKMWPG2Iemhg4dyrJlyzQ0JSKV6vLlyzz88MM8++yz5OXlmc4REamWwsLCeOGFF4CSG/IPPfQQBw4cMFwlIiJS/ho1akRWVhYAEyZMYOHChXh5eRmukv/Gx8eHUaNG8dZbb7F582b++te/cvfdd9OgQQMAUlNTWblyJZMnT2bgwIFMnTqVdevWkZGRYbhcRKR8Xbhwwf61VpsSkepGK06JiIhIjXT27FnGjRvH5cuXqVOnDk8//bSe0BQRIyZPnszJkyc5efIkQ4cOpX///qaTRESqpWHDhmGxWJg5cybp6ek8+uijzJkzhz59+phOExERKTcNGzZk1qxZODo6EhoaajpHysDFxcW+RZ/NZuP7778nJiaGmJgYkpOTsVqtbN26la1bt2KxWOjevTsDBgxg4MCB/M///I/pfBGRm1I6OFWvXj1cXFwM14iIlI0Gp0REyuCee+4hNTUVPz8/0yki8isyMzOZOHEily9fxmKx8MorrzBo0CDTWSJSyxQVFTFlyhT27t0LwMSJEzU0JSJykyIiIvD09OTPf/4zeXl5TJ48menTpzN8+HDTaSIiIjfku+++u2oIOCwszFCNlBeLxULXrl3p2rUrkyZN4syZM3zzzTfExMSwd+9eiouLSUxMJDExkTfffJNbb72VgQMHMnDgQG699VbT+SIiZXbx4kUAGjdubLhERKTsLDabzWY64nqEhoZSUFDAlClTiIyMNJ0jIiIiVdjEiROJj48H4LnnnuPee+81XCQitdGZM2cYO3YsWVlZREREMGPGDNNJIiI1RlJSEpMnT7ZvZTR+/HieeOIJw1UiIiLX7+jRo8yYMYNDhw4xf/58evXqZTpJKklGRgYxMTFs2bKF2NjYq15v1qwZ4eHhDBo0CH9/fwOFIiI35uzZs+Tk5HDLLbeYThERKRMNTomIiEiNkpSUxIQJEwB49NFHeeyxxwwXiUhtduzYMd58803eeustHB214K+ISHk6evQoEydO5NKlSwCEhITw6quvUr9+fcNlIiIiv+6f//wnc+fOtf85PDyc1157zWCRmJKTk8N3333HN998Q2xsLDk5OVe8XjpENXjwYHx9fQ1VioiIiNRsGpwSERGRGmXKlCnExMTg4eHB119/rUEFERERkRrsp59+4n//939JSUkBSj5cnDdvHh07djRcJiIicm3JycmMGjUKAFdXV5588klGjx5tuEqqitjYWL755huio6PJzs6+4rUmTZowZMgQwsPDNUQlIiIiUo40OCUiIiI1St++fbFarYwdO5annnrKdI6I1DJZWVm4u7ubzhARqVWysrKYPn26fasbJycnZs6cyeDBgw2XiYiIXNubb77Jrl27mDt3Li1atDCdI1VQYWEhO3fuZNOmTWzdutW+PXGpli1bMmTIEIYOHUrLli0NVYqIiIjUDBqcEhEpg9mzZ3Pq1Cn69evHgw8+aDpHRP5DYWEhISEhAEybNs3+BKeISGXYunUrs2fPZuHChbRv3950johIrfPRRx+xYMECSm913X333fz5z3/GxcXFcJmIiNRmGRkZeHp6XnHMarXq3ye5boWFhezYsYOvv/6ab7/99qqVqPz8/Ljzzju544478Pb2NlQpIrVZTk4OKSkpNG7cGC8vL9M5IiJl5mA6QESkOjl48CB79uzh5MmTplNE5Bq0LZ+ImBIbG8vUqVNJT0/XanciIoY8/PDDvPvuu/aV/9asWcP999/PwYMHDZeJiEhtlJOTw5w5c7jrrrs4f/78Fa9paErKwtHRkbCwMGbNmkV0dDTz5s3jjjvuwNXVFYADBw7w17/+lSFDhvDHP/6RdevWkZOTY7haRGqTH374gTFjxhAeHk5ycrLpHBGRMtPglIiIiNQofn5+AMTHxxsuEZHaIj4+nqlTpwLg6urKnDlzDBeJiNRewcHBLF26lG7dugFw5swZfv/737N48WKqyaLrIiJSA0RFRTFixAiWLVuG1WplwYIFppOkhnBycmLAgAG8/PLLREdH88orr9C3b1/q1KlDcXExO3fuZMaMGYSHhzNt2jS2bt1KQUGB6WwRqeHOnDlj/7pp06YGS0REbowGp0RERKRG6dChA1CyZdbFixcN14hIbbBs2TIKCwtxcXHh3XffxdfX13SSiEit1rRpU/7+978zceJE6tSpQ2FhIX/729/4wx/+wNmzZ03niYhIDRcbG8v06dNJS0sDYNSoUfYHLUTKk7OzM4MHD+att97i66+/5tlnn6VLly4A5OfnEx0dzdSpU7njjjt4/fXXOXDggOFiEampfvrpJwAaNGigVRVFpFrS4JSIiIjUKPfccw8ARUVFLFq0yHCNiNQGs2bNonfv3rz77rv2m9QiImKWg4MDjzzyCB9//DHNmjUDIDExkfvvv59Vq1YZrhMRkZqsd+/etG/fniZNmrBo0SKmTZtm30ZWpKJ4enoyevRoFi1axOrVq3n88cdp1aoVAJmZmXzxxRf87ne/Y/To0XzyySf2wT4RkfJQOjhV+ruXiEh1Y7FVk3XKQ0NDKSgoYMqUKURGRprOERERkSrstddeY/ny5QC8/vrrDBo0yHCRiIiIiJiSk5PDG2+8ccXAVGhoKC+++CI+Pj4Gy0REpCZIT0/Hy8vrimOHDh2iRYsWGpgS4/bv38+6devYuHEjly9fth93cHAgJCSEiIgIBgwYQN26dQ1Wikh1t2zZMqKiomjZsiUzZ840nSMiUmYanBIREZEax2q18uCDD5KcnIyjoyMLFy6ke/fuprNEpIbYuXMnvXr1Mp0hIiJltH37dmbOnMnPP/8MgIeHB9OmTWPw4MGGy0REpDpKTk7mtddeIz09nc8//xyLxWI6SeS/KigoICYmhnXr1rF9+3aKi4vtr7m7uzN48GCGDRumVZRFRESkVtLglIiIiNRIycnJPPzww2RmZuLq6sqiRYto37696SwRqcaKioqYOXMm69ev1+8lIiLV1OXLl3nppZf45ptv7Mf69OnDiy++iLe3t8EyERGpLpKTk1m0aBFfffWV/dicOXO47bbbDFaJXL/09HTWrVvHunXrOHr06BWvtWnThuHDhzNs2LCrVlITERERqak0OCUiIiI11pEjR5gwYQLZ2dm4uroyZ84cQkNDTWeJSDWUlZXF1KlTSUhIAMDf35+PP/7YcJWIiNyojRs38tprr9m3rKlfvz5TpkwhIiLCcJmIiFR1f/3rX/n8888BaNCgAZMmTWLYsGFacUqqpUOHDrFu3TqioqJIT0+3H69Tpw5hYWGMGDGC0NBQ6tSpY7BSREREpGJpcEpEpAwOHjxIdnY2jRo1onXr1qZzROQ6HDp0iD/96U/2LVkmT57Mgw8+aLhKRKqbxx9/3D40dfvtt/Pqq68aLhIRkZv1888/M3PmTLZv324/FhgYyEsvvUSTJk0MlomISFWWnp7OsGHDGDFiBI8//jhubm6mk0RuWmFhITExMaxatYq4uDh++dGhj48PERERjBgxghYtWhisFBEREakYGpwSESmDsWPHcvjwYUaOHMnzzz9vOkdErtOlS5d45plnSEpKAuC2227jpZdewsXFxXCZiFQX33//PRMmTOD2229n1qxZeppcRKQGiYqKYu7cuWRkZADg6urKE088wX333ae/70VEarGcnBw++eQThg8fTrNmza54LTMzEw8PD0NlIhXrwoULrF69mtWrV3Pu3LkrXgsICGD48OEMGjRI99VEBIDo6Gg2b95Mq1atmDhxoukcEZEb4mA6QERERKSiNWjQgA8++IDbb78dgC1btjBu3DiSk5MNl4lIddGlSxfef/99Zs+erQ/RRURqmCFDhrB8+XIGDhwIQG5uLnPnzuWRRx7h1KlThutERKSyWa1WPvnkE4YNG8YHH3xwzS26NTQlNVnjxo159NFHWbduHW+//TaDBg2yv7Znzx5efPFF+0NF+/fvN1gqIlVBQkICmzZtYsuWLaZTRERumAanREREpNZ45ZVXGDFiBADHjh3jwQcfZNu2bYarRKQqunz58lXHunXrZqBEREQqQ4MGDZg7dy6vvfYaXl5eAOzbt4/7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IlLzZGVlXXVs6NChdOrUiaeeeooNGzbwpz/9iUaNGhmoE5GyaNasGZMmTWL9+vW8/vrrhISEYLFYKCoqIiYmhsmTJzNs2DDef/99Lly4YDpXRP7l2LFj9q+12pSIVHcanBIRERH5FR06dOCzzz4jKCgIgCNHjhAZGcmOHTsMl4lIWUVERDB//nz+8pe/ULduXdM5IiJSw3h4eDBjxgwWLlxI06ZNAdi/fz/3338/H330EUVFRYYLRUSqv5SUFObOncudd95JVFTUVa8vWbKEsWPHamVZkWrI0dGRQYMG8c4777B27VoeeeQRfHx8ADh//jzvv/8+ERERTJ48mZiYGF1biRh29OhRAFxcXOy//4iIVFcWWzVZMzw0NJSCggKmTJlCZGSk6RwRERGpZYqLi5k/fz6LFy8GwGKx8NhjjzFhwoQy/ZygoCASEhIqIlFEfuGLL77A19cXf39/0ykiIlILWa1W3nvvPT799FP71jK33HILL730Eh07djRcJyJS/Rw/fpx33nmHb7/91n6sW7du9q24RaRmKioqYtu2baxatYrvvvvuim2QfXx8GD58OCNHjtTQhogBGzZsYOXKlTg5OTF//nzTOSIiN0WDUyIiIiJlsGXLFl544QWsVisAffv2Zfbs2bi7u//m95auWuXk5KQVq0QqyE8//cT06dPZt28fLVu2ZOnSpTg7O5vOEhGRWurw4cO88MIL9m0sHBwcePDBB3n88cdvaPVDDeGLSG118uRJ7r33XqBkhb8777yTkSNHamsgkVrkwoULrFq1itWrV3P+/Hn7cYvFQq9evbjnnnvo168fjo6OBitFRESkOqozY8aMGaYjrseHH35IcXExvXv3pkuXLqZzREREpJZq27Ytt912Gzt37iQjI4NTp06xadMmQkND8fLy+q/fFxQUZH8qrri4mIKCAnr27FlZ2SK1wubNm3nyySdJSUkBoEmTJvTr14/69esbLhMRkdrKx8eHe+65B1dXV/bu3UthYSF79+4lKioKf39/mjRpct0/q3QI//3338fb2xs/P7+KyhYRMSouLg53d3dcXFzsx7y8vCgqKuLee+9l1qxZ9OnTB29vb4OVIlLZ3NzcCAwMJDIyks6dO5Obm0tKSgrFxcWkpKSwadMmvvzySzIyMmjZsqXuBYiIiMh104pTIiIiIjcgNzeX5557jtjYWKBk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Wrvh5FwyhnTmRK7hmuvnaDpARKQ6+fTTT00n1Chp5/MBcPN0sm99IyIiIlJVOdRxoElLN84mZ5N2Ps90jlSAtAv//v+1eTs3gyUiIiIiv635LfU5kpRBUYGNrPQC6jfQ/bWa5tK/fu9o0d7dcImIiIjIb7M4WGjaxo3Thy9Xq/unWnFKRESMycoseZrf3VM3dURERKR6qO9V8vxRdmah4RKpCKXXp6BrVBEREan63Dz+/Wx89i+uY6TmyPrX7x31dG0qIiIi1YS7Z+n90+pzfarBKRERMcaaXQSAs2sdwyUiIiIi16duvZJf/HOyigyXSEUovT4FcK6nRbpFRESkaqvn/u9hmpxsXZ/WRNacYgBc6+n+qYiIyP9n787Doqr+P4C/URQGFwbFBdlBFMXEfd9x18wtK5fU0qTUXHL7luWeS2mWmZpL5ZZbpua+b6louIUKoqAoYgiCKIsywO8PfozcubMBs13m/XqenriHO3c+cmfOvefczzmHpKFMudx71HQJ3Z8ycYqIiMwmJyf3/yV4NSIiIiKJKFHSBgCQk51j5kjIGPLuT2Fj1jCIiIiI9GKTr08tWzrPpUhf+ZscNrxBJSIiIon4/9uW7GzzhlEQHD5JRFQAt27dQmpqKipVqgRPT09zh0NERERERERERERERERERESFxDk+iIgKYO7cuQgODsbGjRvNHQoREREREREREREREREREREVAROniIiIiIiIiIiIiIiIiIiIiIjI6jBxioiIiIiIiIiIiIiIiIiIiIiIrA4Tp4iIiIiIiIiIiIiIiIiIiIiIyOrYmjsAIiIp6du3LxISElC7dm1zh0JERERERERERERERERERERFwMQpIqIC6Nevn7lDICIiIiIiIiIiIiIiIiIiIgPgUn1ERERERERERERERERERERERGR1mDhFRERERERERERERERERERERERWh4lTRERERERERERERERERERERERkdWzNHQARkZTMnTsXMTExaNOmDQYPHmzucIiIiIiIiIiIiIiIiIiIiKiQmDhFRFQAt27dQkREBDw9Pc0dChERERERERERERERERERERUBl+ojIiIiIiIiIiIiIiIiIiIiIiKrw8QpIiIiIiIiIiIiIiIiIiIiIiKyOkycIiIiIiIiIiIiIiIiIiIiIiIiq2Nr7gCIiKRk+vTpSE1NRaVKlcwdChERERERERERERERERERERUBE6eIiAqgVq1a5g6BiIiIiIiIiIiIiIiIiIiIDIBL9RERERERERERERERERERERERkdVh4hQREREREREREREREREREREREVkdJk4REREREREREREREREREREREZHVsTV3AEREUjJ37lzExMSgTZs2GDx4sLnDISIiIiIiIiIiIiIiIiIiokJi4hQRUQHcunULERER8PT0NHcoREREREREREREREREREREVARcqo+IiIiIiIiIiIiIiIiIiIiIiKwOE6eIiIiIiIiIiIiIiIiIiIiIiMjqMHGKiIiIiIiIiIiIiIiIiIiIiIisjq25AyAikpJNmzaZOwQiIiIiIiIiIiIiIiIiIiIyAM44RUREREREREREREREREREREREVoeJU0REREREREREREREREREREREZHWYOEVERERERERERERERERERERERFbH1twBEBFJya1bt5CamopKlSrB09PT3OEQERERERERERERERERERFRIXHGKSKiApg7dy6Cg4OxceNGc4dCRERERERERERERERERERERcDEKSIiIiIiIiIiIiIiIiIiIiIisjpMnCIiIiIiIiIiIiIiIiIiIiIiIqvDxCkiIiIiIiIiIiIiIiIiIiIiIrI6tuYOgIhISvr27YuEhATUrl3b3KEQERERERERERERERERERFRETBxioioAPr162fuEIiIiIiIiIiIiIiIiIiIiMgAmDhFRERkZWbOnISUlGQAQMmStpgzZyns7e3NHBXl2bRpDUJDLyi3g4M/Q40atcwYEVHxEBJyFlu3/qrc7tz5TXTt+pYZIyoahUKBly8zkJGRAYUiEwqFAtnZWShZ0hYVK1aCnZ2duUPUKisrC6GhF1Ctmjvc3DzMHQ4RmVlxq6OLG54fIuMpTu3znJwcvHz5Ei9fZiAz8xUyMzOhUGQiOzsbMpkDKlashJIlS5o7TGRlZeHVq1d4+TIDr169hEKhQFaWAjk5OShfXg653MncIRKRmcXHP8aCBdOV297efhg7dqoZIyJVxen6SWRJituzifz3fJmZmcjKykJWlgIymQOcnCrC1tayU2UePXqIhIR4PH2agOzsLDg6OkEurwC53AmOjk4WH7/U8K9JRERkZa5evYT09DTldlaWwozRkKp79+7ixo1ryu3k5KdmjIao+Hjy5LHguxUQEGjG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c4dFRMWYZBKn7OzsAHDGKSIyryVLlpg7BCIiKgZmz+b1hIiIiIgsx8CBH2LgwA/NHQYRERERERo0aIoGDZqaOwwisiIlzB2AvjjjFBERERERERERERERERERERERGQoTp4iIiIiIiIiIiIiIiIiIiIiIyOpIJnEqb6m+9PR0M0dCRERERERERERERERERERERERSZ2vuAPQlk8kAAKmpqWaOhIisWUxMDOLj41GmTBnUqlXL3OEQERERERERERERERERERFRIUkmcapMmTIAgLS0NDNHQkTWbOvWrdi6dSt8fHywbds2c4dDREREREREREREREREREREhSSZpfqYOEVElqB06dIAgMzMTDNHQkREREREREREREREREREREUhmcQpBwcH5c/p6elmjISIrBkTp4iIiIiIiIiIiIiIiIiIiIoHySROlS1bVvlzamqqGSMhImuWlzj16tUrM0dCRERERERERERERERERERERWFr7gD0Vb58eeXPKSkpcHZ2NmM0RGStGjVqhJEjR8Le3t7coRAREREREREREREREREREVERSCZxqkKFCsqfExIS4OPjY8ZoiMhaBQYGIjAw0NxhEBERERERERERERERERERURFJZqm+/DNMPX361IyREBERERERERERERERERERERGR1Ekmcaps2bKwtc2dICshIcHM0RARERERERERERERERERERERkZRJJnEKeD3rVGJiopkjISIiIiIiIiIiIiIiIiIiIiIiKZNk4hSX6iMic4mLi8OCBQvw2Wef4fHjx+YOh4iIiIiIiIiIiIiIiIiIiApJUolTFSpUAMAZp4jIfJ4+fYodO3bg1KlTSE5ONnc4REREREREREREREREREREVEiSSpyqWLEiACZOEZH5lClTRvlzamqqGSMhIiIiIiIiIiIiIiIiIiKiopBk4lRcXJyZIyEia5U/cSotLc2MkRAREREREREREREREREREVFRSCpxqmrVqgCAFy9e4NmzZ2aOhoiskYODg/JnzjhFREREREREREREREREREQkXbbmDqAgPDw8lD8/fPgQjo6OZoyGiP6PvTuPrqo82z9+hYRAJgiQSQYzAgHCaBgUEApRVKJSRKUOVBGLUxUp/gSHNq0T+mrFVl5wZBBb8aWCGgQlzKCAAYIkJDGQQUjICAmZTubfH+hpt6GtIMmTk3w/a53l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xXQMAAAAAAAAAAAAwK6srMx0BABocZxjYmJiTIdoau7u7vLy8tKXX36poqIi2Ww2XX755aZjAWiF7r33Xr3xxhs6c+aMfdodAKD5bdu2TZ9//rlOnDih8PBw03EAAADQhr344ot64403VFJSoqFDh5qOAwAAgDZs6dKlevLJJ1VdXa1hw4aZjgMALUKbmDglSbfeeqvGjBkjSXr//fe1d+9ew4kAtEYDBw6UJO3cuZPpdgBg0LZt2/TWW29p3bp1pqMAAACgjfvqq6+UnJysrKws01EAAADQhhUVFWn16tUqLi7W8ePHTccBgBajzTROSdKf/vQndevWTZL05JNPqri42HAiAK3NxIkTJUlVVVXatGmT4TQAAAAAAMCknJwcnThxQpIUGRlpOA0AAADaqoaGBj355JOqqqqSi4uLHnzwQdORAKDFaFONU506ddILL7wgSSouLtYTTzyhhoYGw6kAtCYDBgxQz549JUlbtmwxnAYAAAAAAJj0w7WBdu3a6corrzScBgAAAG3V4cOHFR8fL0m699575efnZzgRALQcbapxSpKGDRumO++8U5K0b98+rVy50nAiAK3NPffco2eeeUYvv/yy6SgAAAAAAMAgFxcXde7cWcOHD1enTp1MxwEAAEAbNWjQIC1ZskSXX3657r77btNxAKBFcWpogyOXamtr9etf/1qpqalq166d/vKXv2jUqFGmYwEAAAAAAABohQoKCuTr62s6BgAAAAAA+JE22TglSdnZ2br11ltls9nUsWNHLVu2TL179zYdCwAAAAAAAAAAAAAAAEAzaHNb9f2gR48eWrhwoZycnGSz2fTQQw8pLy/PdCwAAAAAAAAAAAAAAC7YkSNHNGvWLJWWlpqOAgAtXpttnJKkMWPGaMGCBZKkoqIiPfjggyorKzOcCkBrkpCQoMWLF5uOAQAAAAAAmtGOHTtMRwAAAEAbFRsbqxkzZighIUFz5841HQcAWrw23TglSVOnTtXMmTMlSZmZmZo7d65qa2sNpwLQGqxfv16zZs3SsmXLlJycbDoOAAAAAABoBtu3b9fcuXN11113KTc313QcAAAAtCEPP/ywYmJiJEne3t767W9/azgRALR8bb5xSpIeeOABRUdHS5IOHDhg/8cEAH6O8ePHq2PHjpKk5cuXG04DAG1LTEyMIiMjddddd5mOAgAAgDaksrJS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XJxqa2u1ceNGbdy4UWFhYZo8ebImT57MFCqglXFxcdH8+fPVv39//elPf1Jtba327NlD4xQAAAAAwCEUFRWpW7dullppaan9eVBQkKKiolRXV9fc0QAAANqU3NxcdejQQV26dLHUY2JiFBcXZ6ldf/31lsapjh076oYbbpC3t7eCg4MVEhKikJCQRr8Hk6UAAC0ZE6dakVOnTmnNmjX66KOPVFhYaK87OTlp5MiRmjx5sn7xi1+oY8eOBlMCuNiOHj2q559/XosWLVKnTp1MxwGAFoGJUwAAAC3P9u3btWnTJu3YsUPXXnutFixYYDn+xRdf6Pjx45o4caKCgoIMpQQAAGjdCgoKtHjxYqWnpysjI0OVlZV69NFHdfvtt1vWvfnmm3rzzTfl6uqq0NBQ9erVS7/61a80cOBAQ8kBAGgaNE61QrW1tfryyy+1fv167dixQzU1NfZjbm5umjhxoqKjo3XZZZfJycnJYFIATc1ms9EsCaBNWrFihXbv3q2QkBDNnz/fdBwAAIA27cyZM7ruuutks9nstUsuuUSffvqpwVQAAACtT0pKig4cOKDMzExlZWUpPT1db731lqUp/fTp07rqqqss75syZYqeeuopS62wsFC1tbUKCAholuwAAJhC41QrV1ZWps8//1yxsbE6fPiw5Zi/v7+uvfZaXX/99QoMDDSUEEBTWbx4sTZs2KCYmBhFRkaajgMAAAAAaOXKy8u1d+9e9e/fv9EXbNOnT9fRo0fl6empyMhIjRgxQrfccouhpAAAAI7JZrPp2LFjOn78uPz9/TV06FDL8ZdfflkffPCBpbZo0SKNGTPGUluwYIF69uyp4OBg+4ObsAEAbRWNU21Idna2Pv30U61fv14nT560HAsLC1NUVJSuvvpqXXrppYYSArhYsrOzdeONN9pfX3PNNZo3b568vb0NpgIAAAAAtDa5ubn65JNP9NVXX9lv2ps/f76mTZtmWbd371517NhRgwcPNhETAADAYaSlpal3796W2r59+/SHP/xBBQUF9toNN9yg3//+95Z1H3zwgV5++WV16NBBQUFBCgoK0m233aYBAwY0S3YAABwRjVNtUENDgw4ePKj169crLi5O5eXlluPBwcGaOHGioqKiFBYWZiglgJ/ryy+/1DPPPGP/QWrs2LF69dVXDacCAAAAALQm33zzjWbOnGmpRUVF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AAAAms6HH36ojRs36ptvvrHXhg8fbpmK3bdvX/n5+alPnz6KiIhQREQEW9UAAACdOXNGBQUF6tatW6MtfJ988knt379fhYWF9lp8fLxlTUVFhdasWWOp5eXlNfp9RowYoW7dutkbovz8/NShQ4dG637c6A0AANBW0EUCh+Ph4WG5q6G6ulpJSUk6ePCgDhw4oG+++UYVFRUqKyvT7t27tXv3bkmSq6urwsPDNXDgQPvD39/f5KkArYKvr68eeughPfTQQ8rNzW10fNu2bZo3b56uuuoq3XjjjRo1apSBlAAAAABw/mw2m44dO6asrCz17NlTgwYNshzPzMy0NE1J0rfffmtpnJKkzz77rMmzAgCAliMnJ0dVVVUKDg621P/xj39o5cqVKigosE/JjomJUXR0tGVdUVGRpWlKOrudno+Pj/21n5+frrzySsu2eT+eSiVJd91118U6LQAAgFaJxik4PFdXV/tUqZkzZ6q+vl7ffvutfWu/hIQEnTp1StXV1frmm28sFzR9fHw0aNAgeyNVv379znmnBYCfJiAgoFHtk08+kSRt2rRJmzZtkp+fn55//nkNGTKkueMBaEOCg4M1bNgwhYSEmI4CAAAc0K5du/Tss89avrCcMmVKo8apyy+/XBUVFQoKClJISIgCAwPPua0NAABwbGVlZSovL1dFRYXKy8sVGBjYaML+jBkzlJOTo+LiYknSwIEDtWzZMssam82m7OxsS62oqKjR7zd8+HD5+fnJz8/PPiXK09PTsqZz587685//fDFODwAAoE1zamhoaDAdAmhq6enpSkpKUlJSkhISEnT06NF/uzY8PFzh4eHq37+/+vfvf847NAD8dMePH9fatWsVGxurU6dOSZI2bNggX19fw8kAAAAAtEU2m03p6enKyMhQRkaGsrKy9D//8z+WNd98841mzpxpqU2aNEnPPfdcc0YFAABNrKSkRAUFBSosLFReXp68vLw0YcIEy5q33npLb7zxhqX26quvauzYsZbaddddp/z8fPvrgIAAxcbGWtbs2bNHa9eula+vr/0xcOBA9erV6yKfGQAAAH4qGqfQJtlsNiUmJioxMVGHDx/W4cOH7Q0dP+bq6qq+fftqwIAB9maqwMBAOTk5NXNqwPFt3bpVqampuu+++yz13Nxcvffee5o4caKGDRtmKB0AAACAtuDpp5/Whg0bLLV169apZ8+e9tdlZWV64YUX1L9/fw0YMEDh4eHq2LFjc0cFAAAXKCUlRTk5OaqoqFBZWZkqKioaNUWfPHlS119/vaU2fPhwLVmyxFJbs2aNFi5caKk98cQTmjp1qqX2ySefqF27dgoICJCPj48CAgL4/AAAAOAAaJwCvpeTk2NvokpMTFRKSopqa2vPudbDw0P9+vWzN1MNGDDgnFuUAfhpli9frtdff13S2S00x48fr9tvv507rQAAAACclw0bNigzM1MZGRnKzMxUaGioXnjhBcuaFStW6K9//askydvbW4MGDdIjjzzCFnsAADiA0tJS7d27V/n5+fYpUSNHjtQNN9xgWTdnzhzt2rXLUtu6datle72qqiqNHj3asiY0NFSrV6+21I4dO6b9+/fLz89Pvr6+9v8CAACgdXAxHQBoKbp3767u3btr0qRJkqSamhqlpaXpyJEj9kdGRobq6upUXl6u+Ph4xcfH29/v7e1t3+bvh0ePHj2YTAX8RJ6eniorK1NhYaHWrFmjyZMn0zgFAAAAoJGjR4/qyJEjGjdunDp37mw59vTTT1te22y2Ru8fO3asevTooYiICG6CAgCgBVmzZo0yMjJUXl6u8vJyVVZW2m+2/EFOTo7mz59vqXl6ejZqnOratav9uZeXl/z8/FRRUWFpnOrQoYPmzJkjHx8f+7Z5fn5+jXKFhoYqNDT0YpwiAAAAWiAmTgHnoaqqSqmpqZZmqqysLP27v0aenp7q06ePpZkqKChI7dq1a+bkgGPYs2ePNm3apNTUVK1atcpy7MyZM/rrX/+qqKgojRw50lBCAI4iMzNThYWF8vT0VHh4uOk4AADgZ4qNjdXHH3+s5ORkezPU0qVLFRkZaVl39913q6qqSsHBwQoODlZQUJCioqJMRAYAAN87ePCg1q9fr4KCAuXn56ugoEAPP/xwo2an2bNna//+/Zba5s2bLY3SBQUFuvbaa+2vAwICdN111+mBBx6wvC87O1v19fXcmAkAAID/iolTwHno0KGDBg0apEGDBtlrlZWVSk1NVUpKiv3xw2SqsrIyHThwQAcOHLCv79ixo3r37m1vpOrbt6/CwsLk4sJfR2DUqFEaNWrUOY9t2bJFa9eu1dq1a+Xl5aVx48Zp+vTpNEQAOKfly5crNjZWERERWr58uek4AADgP8jNzVVGRob9MXjwYEVHR1vWZGZm6uDBg5Zaenp6o8apZcuWNXleAADampKSEhUUFMjf398ysUmSZs6cqdLSUpWXl6uiokJ9+vTRm2++aVmTmZmpdevWWWqnT59u9Pt069ZN/v7+8vPzs0+B+jFfX1+tWrVKvr6+6tat27/N3KNHj/M5RQAAALRhdGoAP5Obm5uGDBmiIUOG2GvV1dVKS0tTSkqKkpOTlZKSomPHjqmmpkY2m02HDx/W4cOH7etdXFwUHBysvn37qnfv3urbt6/Cw8Pl6elp4pSAFqm+vl5du3bVqVOnVFpaqtjYWI0YMYLGKQAAAMBBnDx5Ul26dFHHjh3ttdzc3EZNUhUVFY1qkZGRKigoUFBQkEJDQ9WrVy8FBwc3S24AAFqbHxqhCgsLlZ+fLw8PD02cONGyZt26dVq2bJkKCgpUXV0tSXrttdc0evRoy7rjx49bmqCKiooa/X6BgYG64oor5O7uLg8PD7m7u5/zmt7zzz//k/JzPRAAAAAXE41TQBNwdXXVgAEDNGDAAHuttrZW6enp9kaqlJQUpaWlyWazqba2VmlpaUpLS7P8On5+furTp4/l0atXLzk5OTX3KQHGTZ06VVOnTlVCQoK2bNmiHTt2aNy4cY3WPffccxozZsw5jwEAAABoPkePHtW2bduUlJSkw4cPq7i4WO+8844GDx5sXxMQECA3NzdVVlZKOvvz9Ln8p+m0AADgrCNHjig3N1cVFRX2CVB33323Zc2pU6d09dVXW2qRkZGNGqeqqqqUnZ3d6L0/Nn78eNXV1cnPz0++vr7n3Bpv2LBhGjZs2IWeFgAAANCknBoaGhpMhwDaqvr6en333Xf69ttvLY/CwsJ/+54ftvr712aq3r17W+7YBdqq/fv3a/bs2ZLO/l0ZM2aMbr75Zl122WWGkwFobjExMWzVBwBAM8jIyFBmZqbq6+sbfeG6cuVK/eUvf7HUnn76ad14442WWmxsrLy9vRUUFKSePXs2eWYAABzNiRMntGbNGnszVHl5ua666ipNnjzZsu6+++5TfHy8pRYbG6uAgABL7cdb3YaGhmr16tWW2tGjR3Xw4EH5+vram6LOtXUeAAAA4OiYOAUY1K5dOwUFBSkoKMhyl8+ZM2d05MgRSzNVVlaW6urqzrnVn5OTk3r06KHevXtbHj169GA6FdqUyspK9ejRQ9nZ2bLZbIqLi1NYWBiNU0AbNH78eF1yySXy9/c3HQUAgFbppptuUlZWlv11UFBQo8ap0NBQ+fr6Kjg4WCEhIQoMDDzntIkfb8sHAEBrU1ZWpvz8fHXu3FndunWzHHv//feVnJysgoIC5efnq6SkRFu2bLGsKSkp0apVqyy1nj17Nmqc6tKli/25p6en/Pz8VFVV1SjPsmXL5ObmJnd3d7m7u8vb27vRmrCwMIWFhZ33uQIAAACOholTgIOoqanR0aNHlZqaqrS0NKWmpuro0aMqKyv7t+9xc3NTaGhoo4YqT0/PZkwONL+0tDRt3rxZmzdv1sKFCxUaGmo5fu+996pXr16aOHGiRo8ebSglAAAA0PKkpqZq//79yszM1HfffaeMjAy9+uqr6t+/v2XdDTfcoJycHPvrkJAQffjhh80dFwAAI6qqqizTn5ydnRs1GW3dulV/+ctfVFBQIJvNJkmaP3++pk2bZln3m9/8RgcOHLDUdu3aZdlhIDs7W7fffrt8fHwUEBAgHx8fjR49WldddZXlfcePH5eTkxMTHAEAAIDzwMQpwEG0b99e/fr1U79+/Sz1nJwcpaWlKS0tTUePHlVaWpqOHz+u+vp6VVZWKjExUYmJiZb3+Pv7q3fv3goLC7M3UwUGBsrZ2bk5TwloMj/8f33fffc1OlZYWKiDBw/q4MGD+uSTT+Tu7q6pU6dqzpw5BpICAAAAzS8jI0MZGRlydnbWuHHjLMc+/fRTffDBB5ZaZmZmo8aphx56SK6urvYpygAAtAZZWVnKyMiwNEVFR0fLx8fHvqayslJjx461vG/AgAFasWKFpVZVVaXjx49basXFxY1+z8suu0yenp5yd3e3/7eurs6ypkePHtq2bdt/zd+rV6//ugYAAACAFY1TgIPr3r27unfvbrnYXV1drWPHjtkbqn5oqvrhB/O8vDzl5eVp165d9ve0b99eQUFBCgsLU2hoqH0Uc0BAQLOfE9CUSkpKFBkZqfj4eElSRUXFOSe3FRYWWi6KAQAAAI7u5ptvVkZGhv314MGDGzVOhYSE2J+Hh4erZ8+e8vPza/Rr/et28wAAtHQ2m01ffvml8vPzVVhYqPz8fAUHB+vuu++2rPv444+1cuVKS23g/2fv3uObqu//gb/Spm2apPckvbdJy02BgrTc7wjqFLziVLygzAsiilO2oc7BvME23NiGtymKTh0iIk4R5YugyKW6cpGLFNsm6Y22SS8pTdL0mt8f/eXYDyfcSy/09Xw8eDR553NOPmcjtTSvvN+DBwu/IwoNDUVwcDAaGxulWlVVlew5k5KSMGXKFOj1eunP4MGDZeseeOCB8708IiIiIiI6DxzVR9SLVFZWCmGqvLw8WK1WNDc3n/QYjUaDtLQ0IUzVt29fREREdOLOiTqex+PBvn37kJ2djQkTJiAzM1N4fNGiRfjuu+8wefJkjvQjIiIiom7ParXCYrGgsLAQZrMZN954I4YOHSqsue6661BaWirdj4yMxJYtW4Q1DocDLpcLiYmJnbJvIiKiM1FfX4+KigpoNBro9XrhsQ0bNmDv3r2w2+2w2+2w2Wz473//i8jISGlNVVUVrrzySuG40aNH45///KdQe/vtt6VaaGgoDAYDnnrqKQwbNkxYt3btWmi1WhgMBml8XvvRekRERERE1HMwOEXUyzU3N6OwsBD5+fkoKCiQvrb/Zbo/0dHRSE9PFwJV6enpCA0N7aSdE11YkyZNEjpRaTQabN68GSEhIV24KyI6U2+//TZ27tyJtLQ0LFq0qKu3Q0RE1CHq6+tRXl4Ok8kk1D/99FP88Y9/FGoLFizAnXfeKdRefvlluN1umEwmpKWlwWg0Iioq6oLvm4iI6EQNDQ2oqKiQgk7Hjx/HLbfcIqzZs2cPXnjhBdhsNtTX1wNoGxV79913C+t++9vfYuvWrULto48+QmpqqlDLyspCeHi4NBIvIyMDTz75pLCmsrISTqcTsbGx/D0nEREREVEvwVF9RL2cUqmUAlDteTweWZgqPz8f1dXVAIDq6mpUV1fjf//7n3BcfHw80tPTkZaWhrS0NPTp0wcmk4lhE+pxHnjgAXz33XfIycmBx+NB3759ZX+Pi4qKcOzYMYwaNaqLdklEJ2OxWLB3715hdAIREVFP9Nprr+HAgQOwWCyw2WzQarX4+uuvhTXtx+sZjUYYjUYkJSXJzjVv3rwLvl8iIurdqqqqkJOTA7vdjsrKSlRUVODKK6/EpEmThHW/+tWvkJubK9RODE55vV4UFhYKNYfDIXvOjIwMNDU1QaPRQK1WQ6PR+A095eTknHb/Op1OGMtHREREREQXPwaniMgvlUqFQYMGYdCgQUK9trYWeXl5yM/PlwJVBQUFcLvdAICysjKUlZVhx44d0jEKhQKJiYlCmMr36ebg4OBOvS6iM3XbbbfhtttuAwDs27cPLS0tsjUbN27EqlWroNVqMWnSJOkPEREREdGZKCwshNVqlcbsTZ06FePGjRPW7NmzB3v37pXuO51OVFZWCm/qDhw4EB9++KGsExUREVFH+ve//42ysjK4XC64XC4olUosW7ZMWHPkyBE89dRTQi09PV32+xJ/HQ/dbjfUarV032g0Yv78+UIgymg0yo674447cMcdd5zPpRERERERUS/G4BQRnZWIiAhkZWUhKytLqJeXlyM/Px9msxlmsxn5+fmwWq3weDzwer0oKSlBSUkJtm/fLh0TEBCApKQkIUzlC1Qplfz2RN3HZZdd5rd+5MgRAG1vXn322Wf47LPPsHz5coaniIiIiEhysvF6W7ZskY2TjY6OlgWnJk+eLP07yWQyITU11W8nDIamiIjIn4aGBrhcLrjdbrhcLgQGBqJPnz7Cmi1btuCtt94S1j399NO46qqrhHUbN25Efn7+KZ8vIiJCuJ+QkACNRiNb99hjj6GhoQFarRZqtRpqtRoqlUpYo9PpZGP5iIiIiIiIOhqTCUTUIeLi4hAXFyf8kt/r9aK0tBQFBQUwm81Sdyqr1Yqmpia0traiqKgIRUVFwqiJwMBAJCcnS0EqBqqou/rHP/6B3NxcbN26Fdu2bYPFYvE7tu+5557D+PHjMXHixC7YJRERERF1tpdeegmHDx+G1Wo96Xi99kGn5ORkmEwmYeSej68LKhERUXv5+fkoKSkRwk433ngjwsPDhXVjx44V7g8aNAirV68WavX19Th69KhQq6mpkT2nTqeD0+lEbGws9Hq93yBveno63n//fRgMBkRGRp50/wz8EhERERFRd6Hwer3ert4EEfUuLS0tKC4uFsJUBQUFKC4uRnNz80mP8wWqTCYT0tPTpa+pqakICgrqxCsg8s9ms8FgMAi1vXv34v777wfQNgJz3LhxuOGGGzBy5Miu2CLRRSMrKwterxcKhUL4CkBW8/e1vZycnK64BCIi6qEsFgusVisKCwthsVhw7bXXIjMzU1hz991349ChQ0Jt06ZN0Ov1Qs1sNvsNSxERUe9lsVjwySefwO12w+12w+l04vLLL8eMGTOEdb///e/xxRdfCLV3330XAwYMEGrjxo2Dx+OR7icmJuKTTz4R1uzfvx//+c9/oNfrodfrYTAYMHjwYCQlJXXw1REREREREXU/bN1CRJ0uMDAQRqMRRqMRU6ZMkerNzc2wWq3CuD+z2YySkhK0traipaUFVqsVVqsV27Ztk44LCAg4aaAqODi4Ky6ReqkTQ1MA4PF4kJSUhJKSEng8HmzZsgUJCQkMThF1IF8Qqn0g6sSavzX+QlRERERA2yjmqqoqpKamCvV169Zh2bJlQs1oNMqCU1OmTMGAAQOk8XpGo1EWmgLA0BQR0UXE6XQK3Z9SUlJk3Z/mz58Pu90Ol8sFl8uFqKgorF+/Xlhjs9nw7rvvCrW4uDhZcCoqKkq6rdVqodfr0draKtvXggULoNFoYDAYoNfrERsbK1szdOhQDB069KyvmYiIiIiI6GLA4BQRdRtKpRJ9+vRBnz59hHpjYyMKCwthNpthsVikYFVxcTFaWlrQ2tqKwsJCFBYWCuMvAgICkJSU5HfkHwNV1FnGjBmDDRs2wGKx4KuvvsLWrVsxfvx42bp58+ZBpVJh9OjRGDVqFJKTk7tgt0Q9R2pqKgoLC885/OTrTqXVajt6a0RE1EMtXbpU+qBGVVUVjEYj1q1bJ6xpP1bI92EQfz+33XXXXRd8v0RE1Dl2794tBZ1cLhdiYmJw5ZVXCmtef/11vPbaa0Ltr3/9KyZMmCDUCgoKYLfbpfstLS2y54uIiEBYWJjU+Umn02HYsGGydbNmzcLMmTMRGxsLlUp10v3ffPPNZ3SdREREREREvRVH9RFRj9Xc3IyioiIhUGWxWFBYWIimpqaTHqdQKJCQkACTyYS0tDSYTCbptlqt7sQrIGpTXV2NK664QqhlZmbKfulKRD/78ssv8dRTT51XcEqhUOD222/Hr3/96wuwQyIi6k5yc3NRUFAAi8WCvLw8LFiwQNbt6eqrr4bNZhNqJ45z9Xg8KC8vh9FovOB7JiKiCysvLw9Hjx6F3W6HzWaD3W7HwoULERcXJ61pamrC6NGjheOGDBmCVatWCbW1a9fiz3/+s1BbvHixrEvUsmXL0NjYKAWiDAaDLFxFREREREREnYsdp4iox1IqlVIXqfZaW1tRUlIiC1RZrVZ4PB54vU93u9UAACAASURBVF6UlpaitLQUO3bsEI41GAxSmKr91xNbqxN1pICAAMyZMwdbt26F1WoFANlYGACoqKjw21KfqDeaNm0aXnvtNRQVFZ1zeCooKAh33nnnBdgdERF1hePHj6O2tlbWAerll1/Gm2++KdSuuOIKv8Epj8cjdZLyF45SqVQMTRERdRPl5eWorKzEoEGDhLrNZsPq1aulMJTdbseUKVOwcOFCYd3atWvx8ccfC7XZs2cLwamgoCCoVCp4PB6pVltbK9vLZZddhkceeQRqtRparRZqtRoDBgyQrVu0aNE5XSsRERERERFdOAxOEdFFJyAgACkpKUhJScGkSZOEx0pKSmRj/ywWC1wuF4C2X67ZbDZkZ2cLx0VFRcm6U5lMJuh0uk67Lrp4RUZGYt68eZg3bx7y8vLw9ddfY8iQIbJ1Tz31FHJzc5GVlYWRI0di5MiRsjf8iHqLgIAA3HvvvfjDH/5w1sf6glbXXXcdv48TEfVgHo8Hy5cvl8brORwODB06FG+88YawzvfzkkqlQt++fZGWlia8Ke4zf/78Ttk3ERH5V1lZKQWdbDYbBg0aJAsfLVmyBNnZ2aisrJRqJ3YHdLvdWLt2rezcJ4qJiYFarYZarYZGo4FGo/H7gYxXX30VISEh0Gg0UKvViIyMlK3p27cv+vbte1bXS0RERERERN0DR/UREQGw2+1SiKp9oMrhcJzyuLCwML+BKn9vxBCdD4fDgalTpwq1iIgIbNmy5Zw67RBdDFpaWnDTTTehpKTkjLtO+dYFBgbik08+4fdrIqJuLC8vD1arVfrgw9y5c5GSkiKsmTBhAtxut3Rfq9Xi66+/FtbU1dWhrq4OCQkJnbJvIiISbd++Xej+FBISgt/97nfCmnXr1mHZsmVCbcGCBbIOsfPnz5d92O2LL74QPhBRV1eHJ554QgpD+bo/TZ8+vYOvjIiIiIiIiC4G7DhFRARAr9dDr9dj5MiRQr2mpsZvoMr3ScW6ujr88MMP+OGHH4TjQkNDpSCV0WiURgomJCQgICCg066LLh6RkZF499138d1332H37t3IycnBpEmTZEGR/Px8VFRUIDMzEyqVqot2S9Q5AgMDMWfOHDzzzDNnfex1113H0BQRUTdQV1cHh8MhG6/30ksv4a233hJqU6ZMkQWnrr32WgQEBMBoNMJkMvkdoxcWFoawsLCO3zwRUS9RXFwMhUKBpKQkof7f//4XH330EZxOJ1wuF5xOJ1566SVZB+VFixahsbFRuh8XFycLTvkLt/obiXfDDTdg9OjR0Gg00Gq1CA8Ph1arFdaEhYVh5cqVZ32dRERERERE1DsxOEVEdApRUVHIzMxEZmamUHc6nSgoKBDCVBaLBeXl5QCA+vp6/Pjjj/jxxx+F44KDg5GamirrUpWcnAylkt+S6dQGDBiAAQMGYPbs2fB4PHA6nbI169evl0YSZGVlYdSoUbjhhhsQERHR2dsl6hRXX301/vWvf6G8vPyMu06p1Wo8+OCDnbA7IiLy54UXXoDVaoXFYkFNTQ0yMjLw5ptvCmvajyPu27cvUlNT/Y5GWrhw4QXfLxHRxaakpEToAHXHHXfIHn/88cdht9tx/PhxAG0/d5/4gYWioiIcPnxYqPkLOyUkJKCqqkrq/hQbGytbk5GRgdWrV0uj87RarSwQBQCXX375WV8vERERERER0anwXXoionOg1WoxZMgQ2aco6+vrpSBV+0BVaWkpvF4vGhsbkZeXh7y8POE4pVKJ5ORkYdyf7xPzwcHBnXlp1EOoVCq/HaXa/93KyclBTk4Obrzxxs7cGlGnUiqVmDNnDl544YXTrvUFq2bNmoWoqKhO2B0RUe+Tn58Pq9Uq/Zk9ezb69u0rrNm+fbvUwRUAzGaz7Dzjxo3Dhg0bZN1NiIjIP5vNhn379klhKJvNhl/84heYMGGCsO7uu+/GoUOHhNr1118vhJSUSiUKCgqENTU1NbLn7N+/P0aNGiWFnDQaDeLj42Xr1q1bd9r9a7VaDBo06LTriIiIiIiIiDoag1NERB0oNDQUAwcOxMCBA4V6Q0OD9Kn69oGq4uJitLS0oLm5Wapt3bpVOk6hUCAxMVHWocpkMiE0NLSzL496gNdffx1WqxXZ2dnIzs5Gc3MzwsPDhTV79+7Fiy++iMmTJ2PKlClCRweinmjGjBl44403YLPZTrtWrVbj9ttv74RdERFdvGpra1FXVycLNa1cuRKrV68WaiNGjJAFp66++mo0NjZKP9umpqbKnoPj9Yiot3E4HLDb7YiPj5d1WlqxYgUqKiqkUFRkZCTefvttYc2ePXvw9NNPC7X+/fvLglP+PkBQW1srPGdcXBweeughqNVqaDSakwaipk2bhmnTpp31tRIRERERERF1Jwqv1+vt6k0QEfVWzc3NKCwslAJVZrMZVqsVhYWFaGpqOuWxcXFxsjBVenq631b2RO298sorWLVqlXQ/KSkJCxcuxLhx47pwV0Tn58MPP8Sf/vSnk47r89XnzJmDefPmdcEOiYh6LpfLhb/97W/SBwFqa2sxcuRIvPTSS8K6zz77DEuWLAEA9OnTB6mpqbjhhhswatSortg2EVGXOn78OGw2GyorK2Gz2RAREYGJEycKa9asWYP//Oc/sNvtaGxsBAC8+uqryMrKEtZdfvnlwgg8nU6HL774QliTnZ2Nxx9/XBqHp9FocOONN+Kmm24S1lmtVng8HmGdv27GRERERERERL0FO04REXUhpVKJ9PR0pKenC/WWlhaUlJTIAlW+X3ACQHl5OcrLy7F7927h2JiYGNnIv7S0NERHR3fadVH3FhkZCaPRCKvVCgAoKSnxOxLSbrdDr9d39vaIzsl1112HVatWCaOffHyhqZCQEMyaNasLdkdE1L3l5eXBYrFIwaj58+cjMTFRelyj0WDDhg3CMSeOcAKACRMmcLweEV30cnNzkZeXB5vNJnWAevrppxEZGSmtsdlsuPrqq4Xjxo4dKwtOuVwulJaWCjWHwyF7zvHjx8PpdErdn/z9+37UqFHYuXPnafdvNBpPu4aIiIiIiIioN2HHKSKiHsTr9eLYsWOyQJXZbIbb7T7lsREREbIOVSaTCbGxsZ20e+pu7HY7srOz8d133+G5554THqupqcG0adPQv39/TJ48GdOmTfM7RoeoO1m3bh2WLVsm6zrluz979mw8/PDDXbhDIqKu43Q6UV1djZSUFKH+z3/+Uzbu6a9//atstNPSpUuhUqlgNBqlnyMjIiIu+L6JiDqa3W5HVVUVBgwYINQrKyvx5ptvSoEom82GadOm4bHHHhPWPf3009i0aZNQW7t2rTACvbm5WdZtb9CgQbJxpocPH8bevXuFkXiXXHIJdDpdR1wqEREREREREZ0BdpwiIupBFAoFEhMTkZiYKBurVlFRIQSqLBYLLBYLjh8/DgCora3F/v37sX//fuE4jUYDk8kEo9GItLQ0pKWlwWg0IjEx0e+4K7p46PV6zJgxAzNmzJA99u233wIAjh49iqNHj+LVV1/FnXfeiQULFnT2NonO2A033IA1a9bAarVKYSnfZwRCQkJw5513dvEOiYg61x/+8AfYbDZYLBZUVVXhkksuwb///W9hTfs3+vv164fU1FS/gagnnnjigu+XiOhc2Gw2YSTeqFGjZCHR3/zmNzh48KDQnTQnJ0dYU19fj7Vr1wq16upq2fPFxMRArVZDrVZDq9VCrVajtbVVWKNUKvHmm29K6zQajd/vrQMHDsTAgQPP+pqJiIiIiIiIqOMwOEVEdJGIjY1FbGys7FOtVVVVfgNVvl8Au1wuHDp0CIcOHRKOCwkJEToK+LpUJScnIzAwsNOui7rGFVdcgdDQUGzduhXbt29HQ0MD+vfvL1u3a9cuhIeHY9CgQV2wSyJRYGAg5s6di0WLFknBT9/XmTNnCuNTiIh6up9++glWqxWFhYWwWCy4//77ZeOXDhw4gJKSEum+xWKRnWf8+PEcr0dE3Y7H48Hu3buFcXipqamYM2eOsO7VV1/FG2+8IdSee+45WXCqoqJCNtK5trZWCDNFRUVh1KhRUucntVqNSy+9VLa3Rx99FI8++uhpryEjI+O0a4iIiIiIiIio6zE4RUR0kYuJiUFMTAyysrKE+vHjx6UwVftAlc1mAwA0NDRI3YbaUyqVSElJEcb9paWlITU1FUFBQZ12XXRhqVQqTJs2DdOmTUNDQwN2796NzMxM2bqlS5eirKwMYWFhGDFiBCZMmIBrrrmmC3ZM1Obyyy+H0WiUuk4B7DZFRD1XTU0N6uvrkZCQINSXL1+ONWvWCLWJEyfKglNTp06Fx+ORwvAnPg4A4eHhCA8P7/jNE1Gv5vF4UF5eDrVaDYPBIDz28ccfY//+/cJIvM8//xxarVZa43A48Jvf/EY4buTIkbLgVFRUlOy5HQ6HrDZr1ixUVVUJoagTO0BptVqsXLnyrK+ViIiIiIiIiHo2BqeIiHqp8PBwDB06FEOHDhXqLpdL1qHKbDajrKwMANDc3Cw91l5AQAASExOlQFX7YJVKpeq066KOFxISgkmTJsnqFRUVUueyuro6fPXVV7Db7QxOUZdSKBS477778NRTT0ndpm688UbodLou3hkR0enV1dVhxYoVsFqt0sjliRMn4sUXXxTWmUwm6faAAQOQlJSEmJgY2fnmz59/wfdMRL2Dx+MRuj85nU7MnDlTWLN//34899xzsNvtcLlcAIC5c+fi3nvvFdbt2LED33zzjVBzOBxCcCouLg4AEBERIQWdTgyRAm2h+UGDBklrfMGoE1111VXnduFEREREREREdNFTeH0fxSciIjoFj8cDq9UqC1SVlpaitbX1lMfGx8cLYSrf1/a/GKeeqaGhATt37sSWLVuwfft2zJ49G/fdd5+w5vPPP0dhYSFGjBjht2sVXTiNnlZUlXtQZWtAdUXbH7ezBY2eFjQ2tKKxwYumhlO/fqn7CgpWICgkAMEhAQhRBUKlDkR0XAii9cGIjg1BTGwIQrX8nARRd1FYWIiDBw9K3VVsNhsee+wxJCYmCutO7BKalJSEDRs2CDWHwwGXyyU7lojobFVWVmLv3r1C96drrrkG48aNE9bNnDkTVqtVuq9SqbBjxw5hzb59+2T/Frj11luxcOFCofbvf/8b+/btg1qthlarhVqtxqxZsxh0JyIiIiIiIqIuweAUERGdl8bGRhQVFckCVcXFxWhubj7lsTqdTjbyz2Qy+R23QD2Dw+FAZGSkULv33nuxf/9+AG3dqzIzM/Hkk09KnyKnjuFtBWyl9SgvqscxqxvHrG4crz71a5AufpqwQMQbQ5Fg1CA+NRSxyaEIVCq6eltEFy2r1YqSkhLU1tbKOjC+8847+Mc//iHUXnzxRUycOFGoPffcc9BqtTAajTAajUhLS+MoPSI6qbq6OtjtdkRGRiI6Olp47P3338ePP/4oBaKam5vx6aefCmu2bt2K3/72t0JtwYIFsjHH9913H/bt2yfUdu/eLYxrr6qqwqeffip0f/J9LyMiIiIiIiIi6q74EXQiIjovwcHB6NOnD/r06SPUm5ubUVJSIgtUFRYWorGxEUDbp5srKyvx/fffC8dGRkbKxv2lpaVBr9d32nXRuTkxNOWrBQcHo7GxEQ0NDdi1a5ffdXRuCn9yIndvLfIO1J2ye1SwKgBqrRKhWiWU/79LkTIoAMEqJRTM0fQ4Xi/Q1NiCpoZWNDa0ormxFY2eZjgdzWiob5HWuepakH/QifyDTqnWd0gYBlwWCdMALQKD+H8+0flqaGjAbbfdhqKiIqmm0+lkwamUlBTpdt++fZGamur3v4e///3vL9xmiajbczqdUle6yspKBAcH44orrhDWbN68Ga+88grsdjs8Hg+Atu8d119/vbBu69at0gcYTiYqKgohISHCmLuwsDDZuieeeAJNTU1CKKp9aAoAYmJicPfdd5/LZRMRERERERERdRkGp4iI6IJQKpXSp4unTJki1VtbW3Hs2DFZoMpqtaK+vh5AW9eiffv2yT7R7Ou+kJaWhrS0NOl2fHw8FEx+dFvLly+Hx+PBzp07sW3bNng8HqhUKmHNhx9+iE8++QQjRozAiBEjMHToUNka+lltVRP2fF2Jo/tq4amXh6U0EUok9w1DYroW2shgRMQEd8EuqSvV1TTCdbwJx8wulOTVwVHZKD2W90Md8n6ogzJYgb6DwzBsgg6GJL7eiPypr6/H4cOHcfjwYRw8eBBHjhzBK6+8IoSgQkJCcPz4ceG4yspKOJ1OYSxxVlYWPv74YyQnJ3fa/omo+8jPz0dubq7U/clut+Pxxx9HfHy8tKa5uRmTJk0Sjhs4cKAsONXQ0IDi4mKh5nA4ZM+ZlZWFiIgIKezkb1T6ZZddhp07d552/2lpaaddQ0RERERERETUE3FUHxERdRvl5eWyQJXFYoHT6TzlcSqVCkajUdalKikpCYGBgZ20ezof8+fPR3Z2tlBbunQppk2b1ml7yMrKAgDcf//9uP/++zvtec9GVXkDvttiw9F9dbLHYlPUSOmvRUJaGINSJFNf14SivDqU5DlRZnWjtUX8J4DxEg1GTdUj3qjuoh0SdZ28vDxYrVaEhYVh1KhRwmNLlizBZ599JtRWrFiBcePGCbXly5dDqVQiKSlJCo7rdLoLvnci6jyVlZWw2+245JJLhHpdXR1ee+01qUuU3W7H8OHDsWTJEmHdn/70J3z44YdC7c0330RGRoZQGzdunNRFCgCSkpKwYcMGYY3VasU333wjdYhSq9Xo06cPEhMTO+JSiYiIiIiIiIh6FXacIiKibiMuLg5xcXEYM2aMULfb7UKQyvfV96lqj8eD3Nxc5ObmCscFBQUhNTVV6FJlMpmQmpoKpZL/CexOrrvuOuj1euzevRuVlZUAgEsvvVS2btOmTRg/frzfT8ufL1+W/F//+hfsdjueeOIJBAQEdPjznIsaeyO+3ViOgoNiiDClfxiS+2mR0i8MQSEMCdLJhYYFof+waPQfFo2W5lYcs7hQfLQOliPH0dLkhfWIC9YjLiSYQjFheiwDVHTRczqduOOOO1BSUiLVxo8fLwtOGY1GAG0hbd/PFP7G6y1cuPDCbpiIOpwvCOXrADVw4EBZKOrZZ59FdnY2KioqpNq2bduEUXatra1Ys2aNcFx1dbXs+WJiYhAaGiqEnfz9rPnaa68hODhYGofn73uOL6BJRERERERERETnjx2niIiox6qpqfEbqPIFb04mMDAQSUlJUmcqX6DKaDRyPFw3YLVaceDAAVx77bVCfc+ePXjggQcAAKNHj8bkyZMxadIkREdHn/dzZmVlof2PRAqFAmPGjMFf/vIXhISEnPf5z1VLkxe7/8+GPV9XobWlrRYQAKRnRGDoeD1Cw4K6bG90cWiob8Hh7CocyalGS9PPr4FBIyMx/ppYqDQM5FHPU1xcjOzsbFitVlitVpjNZjz11FOyLlEndnVJTU3FRx99JKyprq5GY2Mj4uLiOmXvRHT+srOzUVpaKoWiAgMD8eSTTwprPvvsM1lHqEceeQR33XWXUFuwYIFsjJ2/kZvz58+Xgk4ajQZ9+vTB9ddf34FXRUREREREREREFwqDU0REdNFxOp1+R/6Vl5ef9tiEhARh3J/vtkaj6YSd06msXLkSq1evFmrXXXcdnn766fM+d2ZmJoC2wJTX64VCoQAAjBo1CitWrOiSDmX5h+qwbX0ZnLXNUi09IxxDxhmgjWRgijpWY30z9u+oRO7/aqRaSGgAxl1jQMbo8w8nEnW03NxclJSUQKVSyQJR69evxwsvvCDUFi5ciFtvvVWoLVu2TBr3azQakZ6eLnSRIaKuUVpaiubmZqSmpgr1ffv2YePGjUKXqEWLFmHq1KnCuquvvho2m026HxMTgy+//FJYs3PnTixYsECozZ49Gw8//LBQ27ZtG0pLS6HVaqFWq6FWqzFs2DCo1ezMSERERERERER0seCcIiIiuuhotVpkZGQgIyNDqNfX10shqvaBqtLSUqnb0LFjx3Ds2DHs2LFDONZgMMjCVOnp6QgPD++06+rt5syZg4yMDHz//ffIyclBfn4+Jk6cKFu3cuVKjBkzBsOGDTur8/vCUr7wFNDWsWDRokV44YUXEBwcfP4XcQaaG1uxeW0pju6rk2ox8SEYdVUcYuL5Jh1dGMGhSoyYFodLh0dj96YylFncaKhvxVfrypG7txYzZicjVMt/OlDXKi0txYMPPohjx45JtREjRsiCU+07wfhG9CYmJsrOt2jRogu3WSKStO/+ZLPZcNNNNwldXmtqavDggw+isrJSGsU9cuRIvPTSS8J5zGYzNmzYINR869vT6XRwu91S2Mlfd9IhQ4Zg9erV0sg8jUbjdxT05MmTz+maiYiIiIiIiIio52DHKSIi6vUaGxulMFX7QFVxcTFaWlpOeWxUVJTfDlU6na6Tdt97VVdXQ6PRCKP0zGYzfvnLXwJoC9CNGTMGN9xwA4YPH37S8/jG9PmCUz7ta0OHDsWKFSv8vqHWkWrsDfhkVRFq7E0AgGBVADIvN6BvRhSgOM3BRB2oJL8O331RDtfxto5nam0gZtydhAQTu+/RhfHjjz9i3759sFgssFqtsFgs+OijjxAZGSmtcbvdmDBhgnBcbGwsNm7cKNTcbjfsdrusWw0RdRyn04ns7GwpDGW32zFixAjZqOXHHnsM27dvF2r//e9/kZCQIN1vbm7GqFGjhDX9+/fHe++9J9T27NmDd955Rwg7TZ48GUOHDu3gqyMiIiIiIiIiot6EHxsnIqJeLzg4GP3790f//v2FenNzMwoLC2WBqsLCQjQ1tQVbampqsGfPHuzZs0c4VqvVygJVaWlpiIuL67Trutj56x5QVVWFyMhIOBwOOJ1ObN68GXFxcacMTp1M+85T+/fvx+zZs/Hyyy8jNjb2vPfuz08HjuPL/5SiubHtOWNT1Jh0YyJC1PxxjTpfUp8wxD2gxq6NZbD+WAe3swVrXy7E+GtikTkppqu3Rz1UYWEhrFYrmpqaZKO1Nm7ciA8++EColZSUCMEptVqNK6+8EnFxcUhOTobRaESfPn1kz6NWqxmaIjqNuro62O12REVFISoqSnhszZo1OHz4MOx2OyorK2Gz2fD5558LAfJjx47JurZpNBpZcOrEcwNAbW2tEJxSKpWYP38+VCqVFIoyGAyy4zIzM6XxykRERERERERERB2F78QRERGdhFKpRHp6OtLT04V6S0sLSkpKZIEqq9UKj8cDoO1T+AcOHMCBAweEY0NDQ2E0GmWhqsTERAQEBHTatV2shg8fji1btuDAgQPYsWMHvv32W1l3EgB46KGHEBQUhJEjR/rtNuXjC095vV4UFhbirrvuwssvvyz7O3G+9nxdie2f2v7/cwJDJuiQMUbPLlPUpZRBgZhwfRIS02uQvakCLc1ebP+0AvZj9bjytsSTvm6ITjR//nxkZ2dL9/v06SMLTqWkpAAAVCoVjEYjjEajMMrL5/nnn7+wmyXqoZxOp9D9KSgoCFdeeaWw5ssvv8Srr74Ku90u/cy6ePFizJgxQ1i3detW7N27V6jV1tYKwSlfgD0yMlIKO/nruHrPPffg5ptvhlqthlqthlar9fvavvvuu8/twomIiIiIiIiIiM4TR/URERF1EK/Xi2PHjskCVRaLBS6X65THBgcHIyUlRepM5QtXpaSkQKlkzrkj1dTUYNq0aWd1jO/HJYVCgbCwMLz++ut+u5yci/ahqRB1ICbflAhDMsehUffiqGzA1+uKcby6rdveJZnhDE8RSktLsXv3blitVmm83uOPP44pU6YI6x544AFZZ8acnBzhvsPhQH19PeLj4y/4vol6kpKSEhw8eFAKRNlsNtx3333o27evtMbr9cq6aw4YMADvvvuuUNuwYQOee+45ofbII4/grrvuEmqvvfYafvrpJ2kcnlqtxqxZsziKmoiIiIiIiIiILkp8J5aIiKiDKBQKJCYmIjExEePGjRMeq6iokAWqzGYzjh8/DgBobGxEfn4+8vPzheMCAwORnJwsdabydakymUwIDg7utGu7mCgUCvzqV7/Ctm3bYDabz/gYoO2Nybq6Ojz44IN47bXXkJaWdl572bmpAt9vqQIAhEUF4ao7UxGqDTqvcxJdCJG6EEyfY8JXa0tQUeTGkT3H0dLixS9uT0JAAMNTF7Pi4mIUFRXBbrfj+uuvFx47cOAAli1bJlt/ovHjx6NPnz5ITU2VwsEnioyMFMbyEV0sfKPuLr30UqFeXV2NVatWSWGoyspKDB48GEuXLhXWbdu2DX//+9+F2vTp04XglC/YXVdXJ9UcDodsLykpKZg6dSp0Oh0MBgP0ej0GDx4sW/fAAw+c07USERERERERERH1ROw4RURE1IWqqqpk3anMZjOqq6tPeZwvpNV+3J/vtlqt7qTd93yZmZkAcFZdc3yj/bRaLVasWIGhQ4ee03N/t8WOXZvsAAB9ogpTb01BUEjgOZ2LqDN983EJCo+0vTk/YFg4fnF7UhfviC6Eu+++G4cOHZLuh4aG4ttvvxXWHDp0SBqv5RuvN336dEyaNKlT90rUmdxuN9xuN5xOJ9xutxRCau/ZZ5/F7t27YbPZpNrOnTsREhIi3S8rK5ONyLvsssvw+uuvC7XPPvsMS5YsAdD2OjQYDFi4cCFGjx4trFu3bh3UajUMBgN0Oh3i4uL8jsQjIiIiIiIiIiIiEYNTRERE3dDx48dhNptlgar2b8CdTGxsrCxMlZ6ejrCwsE7Yec+SmZl5zqPGvF4vgoODsXTp0rMOCRzMrsGWD8sAAMn9tJg8M/mc9kDUVb7fXI7cnBoAwLAJ0Zh4XVwX74jOVFlZGXbt2gWLxYLCwkJYLBbMnTsX06dPF9bdfvvtOHr0qFD7/PPPhYCIx+NBeXm53w5SRD1NTk4OSkpKhA5Qf/vb34Q1xEc8HQAAIABJREFUu3btwiOPPCLU5s2bhzlz5gi1+fPnIzs7W6ht3LgRsbGx0n2Xy4Vf/OIX0Ov10p9LL70Ut912m3BcTU0NampqYDAYoNVqO+JSiYiIiIiIiIiIqB2O6iMiIuqGwsPDMXToUFk3o9raWuTl5cFiscBqtSIvLw9ms1kYx1JRUYGKigrZG3aRkZFIS0vDZZddBqPRCJPJBKPR2Gu7EWRlZZ33OZqamrBw4UIsWrQIM2fOPKNjDn33c2gqNkWNiTeyWw/1PCOuiENzYwvyDxzH3u3V8AKYxPBUt1FSUgKLxYK6ujpcffXVwmOHDh2SjQLzN15v8uTJGDZsGJKSkpCWloaUlBRZVx2VSsXQFHV72dnZ2LVrF9xuN1wuF9xuN+677z4MGjRIWPfnP/9ZNsLX6XQKYaWIiAjZ+f11Cc3MzERMTIwUiDIYDLJjNRoNtm/fftr9R0VFISoq6rTriIiIiIiIiIiI6NwwOEVERNSDREREICsrSxb6qa2tRX5+PsxmMwoKCmCxWFBQUCAEqhwOB/bu3Yu9e/cKx8bFxUmdqXxhKpPJhMjIyE65pq7SEU03fWP7li1bdkbBKUtuHf7v/4emovTBuPyWJAQEnFvHK6KuNvqaBHjcLSjJd2Hf9mpExwYjY1R0V2+rV/vtb3+LrVu3Svejo6NlwamUlBTpdmpqKoxGI9LS0mTnuvfeey/cRonOgNPphMvlksJOaWlpwjhip9OJ+fPnC2uysrKwfPly4TyHDh3C+++/L9SuvPJKWXCqfTgpMjISOp0ODQ0NQnAqMTERjz/+uBSGMhgMiIuTh0bvueee87p2IiIiIiIiIiIi6jwMThEREV0EIiIikJmZiczMTKHucDiQn58vBanMZjO8Xi/MZjNqa2sBAOXl5SgvL8fu3btl52zfmcp3OzExsdOu60I60xF9/gJWvmPPZsyfrcSDT98qAbxAWFQQrrg9FcqgwDM+nqi7USgUmHhTEja/Vwh7iQdfrStHqEaJvoPDu3prF53y8nLs3LlT6jZotVqxYMECTJs2TVjX1NQk3K+urpZ1zOnfvz8+/PBDmEymTtk7UXu1tbU4ePAg3G433G43nE4n0tLSMGbMGGHdypUrsXr1aqH2xhtvCJ04NRoNDh06JKzx1/0pMjIS0dHRwki85GT5iNwnnngCQUFBp/w5JzIyUjZKj4iIiIiIiIiIiHo2BqeIiIguYpGRkX47VAFAVVWV1KHKbDZLt+vq6gC0vbn5ww8/4IcffhCOU6lUUpeS9qGq1NRUBAUFdcp1na9TjenzdZHyBaZODEcpFAooFApceumlSE1NRXJy8mk7szR6WvHx64VoafZCGaTAtNtSEKLmj2HU8wUGBuDyXybj0zcscB1vxqZ3S6H/jQqRuuCu3lqPU1xcDKvVitraWkyfPl147MiRI7LxekVFRbJzjB07FgaDAUajEenp6TAajUJoyoehKboQ/vOf/6CkpETqABUQEIA//elPwhqz2YxHH31UqF199dWy4JS/rpc1NTXCfYVCgalTpyIsLAwGgwF6vd7v6MiZM2eeUVdIjp0kIiIiIiIiIiLqnfiOHRERUS8VExODmJgYDB8+XKhXVlaioKBAClT5Rv85nU4AgMfjwdGjR3H06FHhuICAACQmJgrj/ny3/b1x39VO1knqxG5SKSkp6NOnD5KSkpCQkICkpCQMHjwYGo3mjJ/ryw9K4Ha2AADGX58IbSRDJXTxCFYpMfnmJGx8y4qWZi82vlOCWY+aoOjgMZRFRUX43e9+h7y8PABATk5Oh56/qzz44IP43//+J93XarWy4JS/8XonC4gQnY2Ghga43W5p1F1LSwsuueQSYU1ubi5eeOEFKRDlcrkwb948WeeljRs3Ijc3V6j5wsg+7cfhAW3jgqOj5SM+s7KysGjRImkknl6vh06nk61btmzZWV8zERERERERERERUXsMThEREZFAp9NBp9Nh5MiRQr28vFzqTJWfny/d9ng8AIDW1lYUFxejuLgY27dvF46NiYkRulOlpaUhLS3N75ugncXfmD1fmGrw4MG45ZZbMGTIECQkJJzX8xzZ40D+gbbQ2SUjopDcN+y8zkfUHUXHhmLklbHI3lQBW6kHuzfbMeYqQ4ecu7m5GatXr8Ybb7whG0XXnfnG6/lG61ksFsydO1cWijrxmpxOJ6qrq4UwSXp6OtauXYu0tLRO2Tv1fGazGRaLBcePH0dQUBAcDgeuueYaIbjk9XoxduxY4TidTocvvvhCdr4ff/xRuO9vJJ5Op0NcXBwMBoMUdjrxv7Xx8fF47733oNfr/QamfAYMGIABAwac0bUSERERERERERERnQ8Gp4iIiOiMxMXFIS4uTjZOp6ysTBj3l5+fD6vVKgWqgLaxgFVVVbIOMVqtVgpR+QJVJpMJ8fHxF/RacnJycO+99yIzMxOvv/668MauQqHAoUOH4Ha7sWLFivN6nob6FmxdXw4A0CWokDkl9rzOR9Sd9bssGscsbhTl1uH7LZUYcFkEomNDzuuc+fn5WLRoEaxWawftsmOVlZWhsLAQxcXFuPnmm4XHDh48eEbj9SZOnIj+/fsjJSVFCpj6C5QwNEU+K1euFLo/9evXDw888ICwZv369VizZo1Qy8jIEIJTCoUCkZGRcDgcUq2yslL2fDqdDpMmTYJer0dsbCz0ej0GDhwoW3cm/80MCQlB//79T7uOiIiIiIiIiIiIqLMwOEVERETnJT4+HvHx8Rg3bpxU83q9KC0tlcJUvmCVxWJBY2OjtM7pdOLAgQM4cOCAcE6VSgWTySQFqXx/kpKSEBAQ0CH7fuONN6Sv7YNTvq5TZrMZN998Mx5++GHceuut5/Qc2z+tQKOnFQGBwMQbEhHQwaPLiLqbsdfEo9zqQqOnFZs/OIZbHzGd87m2bNmCxYsXo6GhQXpd+l6r/kZtdqbFixdjy5YtaGhokGpXXXUVwsJ+7iiXnJws3faN10tPT5ed684777ywm6VuwTcOzzcSz2AwyLouLl++HHv27JHWOBwOfPLJJ0hMTBTWrV27Fm63W7pfV1cne77IyEjptsFgQEREhN9Oi/PmzUNISAj0er3050Q6nQ7Lly8/62smIiIiIiIiIiIi6gkYnCIiIqIOp1AokJSUhKSkJEyYMEGqt7a24tixY1Kgymq1SoGq+vp6aZ3H48GRI0dw5MgR4bxBQUFITU2VBapSU1OhVHbMjzUKhQJerxderxcNDQ1Yvnw5cnJy8OyzzyI0NPSMz1N5zIND37V18Rg4KgaaiOAO2R9RdxYUEojh02Kx89MylBXW4+j+WvQfGnFW56ipqcHzzz+Pr7/+GgBkoSmfrKwsWRe78+VwOPDNN9/AYrGgsLAQFosF11xzDe677z7Z2vahqbi4OFRVVQnBqQEDBuDDDz+EyXTu4THq/nJzc1FWViaFohoaGnDXXXcJa7766iv87ne/E2oLFiyQheaOHTuGvLw8oVZTUyMLThkMBjQ3N5+y+9OMGTMwYcIEREREIDb25N0Ob7zxxjO6TiIiIiIiIiIiIqKLFYNTRERE1GkCAgL8BqoAoLy8HBaLRQpS+W6376TR1NSE/Px85OfnC8cGBgYiOTlZGvfnG/1nMpkQEnLyUWFZWVl+6+272igUCnz99df45S9/icWLF5/0mBN9+cExAIA6TImMsbrTrCa6eKQPjkTu/6pRVd6Arz8uR9qlYQgKPrNOcYcPH8bjjz+OmpqakwamTlY7U77vNUVFRbjllluEx8rKyvDss88KtYKCAtk5rr32WowePRpGoxFGoxEqlcrvczE01XNlZ2dj9+7dQpeo2bNnY9iwYcK6l156Cbt37xZqs2bNEsK8ERHy8GB1dbWsdtlll0Gj0cBgMECv10On0yElJUW2bt26dafdf2xs7CkDU0RERERERERERETUhsEpIiIi6hbi4uIQFxeH0aNHC/Wqqiq/gar2bzq3tLTAarXCarVKXWqAtnBFQkKC1JmqfacqjUZz2j35uk8BbYGKuXPnYvbs2XjooYdOOTIw72AdbCUeAMDwK+IQqOyY8YJEPcWYa+Lx6Sor3M4W7N9RheFT5OO/2mtqasKqVauwevVqNDc3nzI0BfwcajwbzzzzDDZv3gyPxyPVrrjiCkRFRUn3TSYTwsLCpOClyWTCoEGDZOfKzMw8q+emzuN0OqWgk8vlQkJCAqKjo4U1d999t7AmMzMTL774orDm8OHDeO+994TaxIkTZcGp9n9/IiIioNfr4Xa7ER4eLtVTU1OxcOFCaRSewWBAXFycbO8c20hERERERERERETU+RicIiIiom4tJiYGMTExsk5PdXV1KCgoEMJUFosFFRUV0hqv14vS0lKUlpZix44dwvEGg+GMnr999ykAePvtt3H48GEsXrwY8fHxfo/5fou9be9xIUjtH+Z3DdHFLCo2FMZLw2D9sQ57vq7GsAk6BCr9B50qKirw6KOPwmw2o6Wl5bShKd9jvnUOhwPbt2+HxWKB1WqFxWLBVVddhblz58qOaR+a8o3Xax98UalU2LZt2zlfN10YtbW1OHjwoBB2uuSSS2QBtmeffRaffPKJUPvDH/6Aa6+9Vqjl5+cLfxeqqqpkzxkREYGoqCip+5Ner/fbQez+++/H/fffj6SkpJPuX6/X49Zbbz2jayUiIiIiIiIiIiKizsXgFBEREfVIYWFhGDp0KIYOHSrU3W633w5VpaWlwjqbzXZWXWt8QQ2v14ucnBzMnDkTTzzxBKZPny6sKylwSd2mBo7hiD7qvQaPjoH1xzrUu1rw4x4HBo+Mkq3ZvHkz/vznP8PhcAA4t05SdrsdzzzzjFA7cZwnAMyYMQPDhw8/7Xg96lxbtmzB/v37pUCUy+XC8uXLhf9/zGYzHn30UeG4W2+9VRacOtOReJdffjmCgoJgMBhgMBiQmpoqWzNz5kzMnDnztPs/VWCKiIiIiIiIiIiIiLo/BqeIiIjooqJWqzFw4EAMHDhQqDc2NsJqtcJsNktfv/rqq7M6d/tAR0NDA5YsWYIjR47g4Ycflt7k/9/WSgCAJlzJblPUq0XFhiLOqEa51Y2crZUYNCJSeg25XC4sXrxYGq15Jl2mfHzhKt/avn37Ijw8HKmpqdKIvRNf/wBkIUs6Pw6HQwo7tba2on///sLjmzdvxjvvvCN0iVq4cCGuv/56YV12djY2bNgg1Kqrq5GQkCDdb98VDADi4+MRGRkp29OECROQkJAgdYjy/TnRH//4x7O+XiIiIiIiIiIiIiK6ODE4RURERL1CcHAw+vXrh379+km1E8f/nQ1f0OODDz7AN998g88++wxORxOsuS4AwOCxurPunEN0sRk8OgblVjcclU0oKXAjuY8GeXl5WLRoEQoLCwGcWZep0wWrtm7d2rEb76Vqampw+PBhqfOT2+1GRkYGMjIyhHUPPPAA9uzZI91PSkqShZ9cLhdyc3Nl5z9RVFQU9Hq9NBLPYDAgODhYWBMfH4/33nsPBoNBFqJqz18XQiIiIiIiIiIiIiKiU2FwioiIiHqlrKyscxoLBvwc9PCN7isvLwcA5O6rBQAEKhVIGxTeofsl6oniTVqow5Rw1zUjd28tkvtoMGvWLOm1A5y6y5RvjW9d+9eeQqFAVlYWcnJyLvh1XAzefvttVFRUSN2fgoOD8fzzzwtrDh8+LBuJd88998iCUyeOxPMXiEpJScHUqVOh0+mkUNSgQYNk6x566CE89NBDp9x7SEiIrKMVEREREREREREREVFHYHCKiIiIeq0zDU21D2/4jvMdGxgYKHWuyt3bFpxK6quFMiiwA3dK3ZXNVo5ly34v3TeZ+uLhh3/XhTvqftIGReDQ7irkHTiOKTfFy15PwKk7SrUPKfY2DQ0Nwqg7pVKJ9PR0Yc2mTZvw3nvvCV2i/vjHP+Lyyy8X1m3YsAHFxcXSfaVSKQtOnTj+LiEhAeHh8hDotddei7FjxyI2NhYGgwHx8fGyNZmZmcjMzDzrayYiIiIiIiIiIiIi6kwMThEREVGvdbqOUyd2u/FJSkrC6NGjMWLECIwYMQIajQa1VY2wH2sAABgvYbep3sLlcuLw4R+k+42NDV24m+7JeGk4Du2uQkN9K6xHnfj73/+OXbt24fvvv4fFYpFeW77XW2trq/B68/c6bd91qicym80oKiqSAlEulwvXX3+9EFyqr6/H+PHjheOGDBmCVatWCbUzHYmn0+nQ0tICvV4vjcQ7UVpaGt5//30YDAZZiKq9cePGndF1EhERERERERERERF1dwxOERERUa/kL3Thr7OUT3h4OKZMmYKbb77Z78io/IN1ANrG9CX31V6AHRP1TNGxKmgjg+B0NMFyuA5Tbx6LsWPHAgDKysqwefNmrF+/HqWlpT06DAUANpsNa9asEbo/jRw5Erfccouw7v3338eGDRuEWlZWlhBWCg0NhVKpRHNzs1Srrq6WPWdqaiqmTp0qhaH0ej2GDBkiW/f666+fdv9qtRr9+vU77ToiIiIiIiIiIiIioosFg1NERETUq52sq5RSqcTQoUMxatQojBgxApdccskpAx3F+U4AQFyqGgGBARduw0Q9UEo/LX78vgYlBS6hHh8fj9mzZ2P8+PF4+umncfTo0ZO+Jv3pqPF97Ts/uVwuKYDU3tKlS/HDDz9Ia2tra5GTkyOscblceOedd4SaSqWSBafaB6S0Wq3suXx+/etfIzw8XOoSFRsbK1szfPhwDB8+/Kyul4iIiIiIiIiIiIiI2jA4RURERL1e+3DGqFGjcNNNN2H06NFQqVRndLy31YuSAjeAtuAUEYkMyRr8+H0NauxNqHe1IFQTCADweDx49dVX8f7778Pr9UpBqI7qOpWTk4Pa2lqp+1NQUBBuuukmYc0XX3yB3//+90LtkUcewV133SXUSktLkZ+fL9QqKyuh0+mk++Hh4dBoNEL3p8zMTNm+br75ZsyYMQOxsbGn/D5zYuCKiIiIiIiIiIiIiIg6FoNTRERE1OtkZWVJwYzo6GiMGzcOw4cPx+jRoxEVFXXW56ssa0BTY1vgQ5/I4BTRiWKTQ6XbxQUu9MsIx5YtW7B8+XJUVVWhtbVVevxsQlMKhQKZmZkYO3Ys5s6di0svvVR4/IknnkBNTY10PyYmRhacioiIkJ3X30i8zMxMxMTESN2fDAYDtFpxLGdMTAy++eab0+7bX+coIiIiIiIiIiIiIiLqfAxOERERUa9z4nit81Vibhs/FhCogC4x9DSriXqfELUSYVFBqKtpwk8H7PjHv55Edna29Pj5dJhSKBTYtWsXrrnmGllwKioqSgpORUdH+x2JZzKZsHDhQqFLVFxcnGzdPffcc857JCIiIiIiIiIiIiKi7onBKSIiIqLzZC/1AAAidcEICOiYEWNEF5voOBXqapqw+5tDyN6XLY3lA84tOKVQKNC/f38p8JSUlCRbs3TpUmg0Gr9BKJ+4uDjceuutZ/38RERERERERERERETU8zE4RURERHSeHFVNAABtVHAX76TnqK+vx549u2E2/4SffjqCvLwj0OtjkZKShtRUE4zGPsjKGo3AwMCTnmPdun/D7W7r9nXLLfcgJCQEzc3NOHBgD44ePYwjRw7i6NHDMBjikZ7eH3379se0aTMQHHzm/z/V1jrw7bdb8P33O1FSUgSXqw6JiSlISEhGRsYwmEx9z/t/i94i7P+/PtTBMR1yPq/Xi6NHj+K999476Zr09PQOeS4iIiIiIiIiIiIiIro4MThFREREdJ5qqxoBAGGRQV28k57h8OEf8Je/LEZZWalQdzhqkJeXK90fMGAQFix4Emlp/sNJ7777Burr3QCAhIRkjB8/Fc8//wS+++5b2Xl/+ulHbNoEbNq0AYsWPY+kpJQz2uczz/wGDkeN7HyHD/+A//u/z87oeqmN7/WhVkVh5k03Y/P/fYnjx48DaAtBKRQK6SsREREREREREREREVFnCOjqDRARERH1ZK2tXjhrmwH83FGH/GtpacGbb67EY4/dKwtN+ZObewgPPjgLa9e+fdq1b731MpYseVwWmjpRXl4u5s+/E263+5TrNm3agMceu1cWmqJz9/PrQ4H75/waX3zxBZYsWYJ+/foJYSmv1yuM8SMiIiIiIiIiIiIiIrpQGJwiIiIiOg/1dc3SbXUYm3meysaNH+GDD+QhqIEDh2DSpCswadIVSEyUd4JatWolDh3af8pzV1basHfvd9L9xMQUXHXVdRg5cpxsbX29G59/vv6k59qwYQ1WrHheVg8NVWP48DGYNm26333SqYVqfn59uJ1NCA4OxvTp0/H+++/jrbfewlVXXYWgoCAoFAqp+xRDVEREREREREREREREdCHx3T0iIiKi89Dg+TnUERTMTPrJlJWV4qWX/iLUhgzJwoIFTyIxMVmo79r1Nf7858XSGD4AWL58CV59dQ1UKtUpn2fIkCw8+uhTSEhIEp77+ecXCWMA3333dVx//a1QKsUfh6uqKvHKKy/KzvvrX/8eV155rdAZKTv7Wyxe/Ngp90M/Cw75+fXR2NAqPDZ48GAMHjwYCxcuxPr167F+/XqUl5dLj/vCUxzjR0REREREREREREREHYnv7hERERGdh6aGFum2Mog/Wvnj9Xrxz38uE2pjxkzCn/70siw09f/au9fgOu86P+DfIx3dJVvyNYotX+JLnE1MwE5I2GwuTTCENJBlyLLpsk23SVvKTnlBNy/olu50tmyZ3RdkOrDTMLOZ6V5muiTQjQtTTMwGvEAG52ICueDYBN8j3y3ZsmRdT18Y7BxiO3Ek+cg+n88r/Z/znOf52tKZkeZ8z+//q8f+8i//ruxYd/eebNjw5Dnvc/vtH8rnP/8/ykpTSdLZOS+f+tRDZccGBvpz+PDBN13jb//2K2XrpqbmfOlLf5M777znTaWdG2+8OZ/7XPm/i7OrKytOjZ7xnPb29jzwwANZu3ZtvvCFL+S6665LElOoAAAAAACASeHdPQCAcRgaOj05p1hfW8EkU9eLL/44zz//o1Pr9vaOfOYznzvn9KB587py//2fLDu2fftr57zPH/7hQ6mvrz/jY1dffW06O+eVHTtwYF/Z+rXXtuRb33qi7NiDD/6HLF9+1VnvOX/+wnNm4rQ3vj6GB89dfKqtrc2aNWvyyCOP5PHHH8+9996bpqamUwUqk6cAAAAAAICJoDgFADAOb9xy7I1bkXHa9u0/L1vfcsuaTJs2/S2fd9117ytbv/balnOe/1ZlmgULFpetDx06ULZ+7rmny9adnfNy552//VYxOQ/F+pPfo6ETY29x5mmLFy/OZz/72axbty4PPfRQVqxYkSSpqfF6AwAAAAAAxqdY6QAAAJcMu4ed0fbtvyhbr1//zXR3737L5x07drRsvWXLK+PK0dEx89eu31u23rVrR9l6zZq7U1dXN657Uu5kue2dbbXX0tKS++67L/fdd9/EBwMAAAAAAKqS4hQAwDi8ccrU8PBYmiqYZar69YlTAwP9efbZp89y9tk1NDSMK0db27RzPv7rOefNWzCu+/Fmw7+c0FZnOhsAAAAAADAFeMcCAGAc6upObw83Mvz2tx+rJi+//JMJuc54i0zn2spvdHQ0W7duLjvW2TlvXPej3OgbXh+KUwAAAAAAwFRg4hQAwDjUNdSe+npkSHHqTJqamjMw0H9qfe+9v5/Vq2887+vMnDl7ImOVGR4eftOxsbHz/34WCgpBZ/PGYmH9G143AAAAAAAAlaI4BQAwDnX1p4syoyOKU2eyZMnyvPTSC6fWl112eVatuqGCid6ssbEx7e0d6ek5curYvn3dueqqled1nVLJz8DZDA+VTn1db+IUAAAAAAAwBXjHAgBgHJpbT0/O6e8bqWCSqWvJkivL1rt27ahQknNbuHBJ2Xrv3j0VSnJpGug7PdWrudXnNwAAAAAAgMpTnAIAGIdifU1app0sTx09PFThNFPTwoVXlK2ffPIbOXq0t0Jpzq6ra1HZet26tWfcwo935uiR06+Pjtn1FUwCAAAAAABwkuIUAMA4tc88WQI5ekhx6kx+fbu7gYH+PProlyqU5uyWLi2fjNXdvSfr1j1RoTSXnt5fvj5aptWmtliocBoAAAAAAADFKQCAcWuf3ZAkOXZ4sMJJpqYrrliWj33sE2XH1q1bm8ce++uMjJx5e8ORkZGsXfvV/Mmf/MeMjo5eiJi5/fYPZdasOWXHvvzlv8i6dWtTKpXO+JwXX9x0IaJdEn41ke1XRUMAAAAAAIBKK1Y6AADAxa59Vl2S5MiBoYyOjKa2WFvhRFPP/ff/+zz99PfS3b3n1LFHH/1ynnpqXT760X+RBQsWp61tevbv786uXduzdu1j2bNnZ5Jk/fpv5s4775n0jA0NDfnkJz+TP/uz/1R2/OGHP58NG9bnllven/nzF2b69PZs3fqzbNjwnWzc+P1Jz3WpOLx3IMnpoiEAAAAAAEClKU4BAIzT3K6mJEmplBx8/UTmLmipcKKpp7GxMQ899F/zR3/0b8uOb9v283zxi//tnM995JEv5rbbPpjGxsbJjJgkufnmO7J69Y15/vkflR3ftGljNm3aOOn3v1QN9A2nr+fkdLG58yf/+wgAAAAAAPB22KoPAGCc5i1uTuGXv1V17+ivbJgp7Jpr3p2vfOXvs3z5b5zX8+64464Uixem718oFPKnf/pwPv7x+y/I/apF947jp77uWqpYCAAAAAAATA0mTgEAjFOxriadC5ry+vaB7N+pOHUuixYtycMPP5onnvj7fPvb/zc7d2570zlNTc1Zvvw3smzZiqxZc3cWLVpyxms1NDRkYOD0/3dNzbk/E1BXV1e2LhbrznhesVjMgw9+Otdc85489thf56WXXjjjeR//+P25+eb359OfPl2yampSCjqT/TtPbtPX1FKbGXNt1QcAAAAAAEwNhVKpVKp0CACAi93T6/Zn4/oW+9D4AAAKuUlEQVSDqalJfvczy1PXUFvpSBeFEydOZNeu7dm7d086OmZm3rwF6eiYUelYZUZGRtLdvTu7d+9IW9v0dHbOz4wZM1MoFCod7aLxtS9tTf+xkVz5nrbc9ftdlY4DAAAAAACQxMQpAIAJseTqtmxcfzBjY8nOLceyZGX7pN9zaGgox4/3Tdj1RkdHUls7sb8evlUJqrGxMcuWrciyZSsm9L4TqVgspqtrUbq6Fp3X83p6jmQiP6MwMjIyoVsWNjQ0prm5ecKudzb7d/Wn/9hIkmTJ1dMm/X4AAAAAAABvl+IUAMAEmNvVlOkz69J7aDjbXzl6QYpTP/jBU/nzP/8vE3a92trajI6OTtj1kuSv/urx8y4cXQoOHTqQ3/u9uyb0mk1NzWVbE47XrbeuyR//8X+fsOudzfaf9SZJaouFLLmmbdLvBwAAAAAA8HbVVDoAAMCl4qrV05Mkr//ieAYHRib9fhO/U9zEbz03NjY24de8GEzGbtgX4w7bpVIp2145liRZ9q62FOv8+QEAAAAAAEwdJk4BAEyQFaum50dPHkyplOzYfCzL39MxqfebMWNWrr32ugm7Xl/fsbS2TuxEoIm+3sWioaExq1bdMKETvAYG+tPUNHFb612I7RH37ezPYP/J/4MVqyd/ChsAAAAAAMD5KJQuxo+uAwBMUV/7n9uz6+f9mT6zPh/5d1ekMPFjoeCi8b2v78rOV/vS1l7Mg/95WQo1Xg8AAAAAAMDUYa8MAIAJdP0ds5IkvYeGsmtrX4XTQOX0HDiRna+efA1cf/sspSkAAAAAAGDKUZwCAJhAC5e3ZtZl9UmSH393fwz3pFq98P2DSZKGpppcc8PkblsJAAAAAADwTihOAQBMsPd+YHaSk1Ontr3cW+E0cOEdfL0/OzcfS5KsunVGaoumTQEAAAAAAFOP4hQAwARbvnJa2jqKSZJnntyX4cHRCieCC6dUKuXpb3YnSWrrCnn3TTMrnAgAAAAAAODMFKcAACZYoaaQW+/pTJIMnRjLC98/UOFEcOFsfeFIeg4OJUlueP+sNDbXVjgRAAAAAADAmSlOAQBMgmUr27LwypYkyeZnj6T34GCFE8HkGzoxkuefOlkUnD6zLtf/s1kVTgQAAAAAAHB2ilMAAJNkze90praukFIp+acndmdsrFTpSDCpfvCN7gwPjiVJPvSJeampLVQ4EQAAAAAAwNkpTgEATJK2jvrcdOecJMmR/UN5/ql9FU4Ek+fV5w9n99a+JMnKG9vTubC5wokAAAAAAADOTXEKAGASrbplRuZfcbJA8rNnjmTPa8cqnAgm3uF9A3lm/cli4LQZxdzykcsqnAgAAAAAAOCtKU4BAEyiQk0hd/9BV5paapMk//TE6+k/OlzhVDBxhgdH893Hd6c0lhTrCvnov1mY+gZ/ZgAAAAAAAFOfdzQAACZZU0ttPvLA/BRqkuHBsXznqzszMjRa6VgwbqVSKd/9+u4cPzqSJLnzE/MyY25DhVMBAAAAAAC8PYpTAAAXwOWLWvLB+y5PkvQcGMpTX9udUqlU4VQwPs+u35u92/uTJNffMTPLVk6rcCIAAAAAAIC3T3EKAOACuWp1e2784Kwkyd7t/Xl2/d4KJ4J37tVNh7P5uZ4kydJ3tea37ppb4UQAAAAAAADnR3EKAOACet8H5uTq97YnSTY/15NXNh6qcCI4fztePZaN6/YlSRYsa86H/9WCCicCAAAAAAA4f4pTAAAX2Pt/pzMLr2xJkjz3j/vz/FP7KpwI3r5fvNSTDV/fnSSZObc+H/nXSlMAAAAAAMDFqVAqlUqVDgEAUG1GR0r5xv/amW0/O54kWbJyWn7z7stTKBQqnAzO7qc/PJAXNhxMkszurM+9n1qcxpbaCqcCAAAAAAB4ZxSnAAAqpDRWypNf3ZNXnjuaJJm3pCW3fWx+aouGgjK1lEqlbFzXnS0/7k2SdC1tzj0PLkhdvZ9VAAAAAADg4qU4BQBQYT/81r48851DSZKO2fW57d6utHXUVzgVnDTYP5Lv/Z892bezP0my9F2t+ef/sis1NaajAQAAAAAAFzfFKQCAKWDzpp48+Vh3RodLqS0WctOHO7PoqumVjkWV27ujLxv+4fUM9o+mUEh+80Oz8947Zlc6FgAAAAAAwIRQnAIAmCIO7RvM2kd3pvfQcJKka3lrbvjAZWmeVlfhZFSb4cHRPPeP+7L1hZNb8zU21+SeB7py+eKWCicDAAAAAACYOIpTAABTyPDgWNb97935+Yt9SZJifSGrbpudK1fPTMHOaFwA217pzTPf3pfBgdEkSefCpnz4D+anRYEPAAAAAAC4xChOAQBMQVt+0pvv/cPeHD92srzSMac+N919eWZc1lThZFyq+nqG8sNvdmffzv4kSV1DTX7rrjm59qYZSnsAAAAAAMAlSXEKAGCKGh4s5Qf/b29+8sMjKZWSFJL5S1tzzY0zM6erudLxuET0HDiRl390KNteOZqxkz29LLu2Lbf/dmeapxUrGw4AAAAAAGASKU4BAExxB14fzPqv7sm+3SdOHeuYU58V18/I4qump1hfU8F0XKy2vdyTLT/uPTVhKkna2otZ87uXZ+Hy1gomAwAAAAAAuDAUpwAALgal5Beb+7Jpw8Hs2nq66FJTLKRrWWuWXduezkUtKdTYU42zKCX7d/fntZ/2ZPvmYxkeHDv10Jx5jVl164xc+e721NRWMCMAAAAAAMAFpDgFAHCRObR3MD95+nBe3dSbEwOnyy/F+kJmz2vO3AVNmTO/ObPnNaW2aBpVNTuwuz8H9gxk787+7N/Vn6ET5T8vy1a25V3vm5HLF9v6EQAAAAAAqD6KUwAAF7EdW/qyeVNvtv60fILQr7S216VjTkOmz2rIjDkNaWotViAlF8LgibH0HDiRI/sGc/TQYI4cGDrjeUtXtuaq1R1ZvKI1tXUmlAEAAAAAANVLcQoA4BIwNpa8vu14tr/alx2bj2f/nhOVjsQU0TG7LguvbM2iFW3pWtqSorIUAAAAAABAEsUpAIBL0onjo+neNZC+nuEc6xlOX+9I+nqHc7x3OMd6RzI48ObpVFyc6htr0jqtNi3T69I6rZjW9rq0Ta9LS3td5l7emLaOukpHBAAAAAAAmJIUpwAAqlTvoeEcPzqcsTG/Dl5sCoVCmtuKaWuvM0EKAAAAAADgHVKcAgAAAAAAAAAAqk5NpQMAAAAAAAAAAABcaIpTAAAAAAAAAABA1VGcAgAAAAAAAAAAqo7iFAAAAAAAAAAAUHUUpwAAAAAAAAAAgKqjOAUAAAAAAAAAAFQdxSkAAAAAAAAAAKDqKE4BAAAAAAAAAABVR3EKAAAAAAAAAACoOopTAAAAAAAAAABA1VGcAgAAAAAAAAAAqo7iFAAAAAAAAAAAUHUUpwAAAAAAAAAAgKqjOAUAAAAAAAAAAFQdxSkAAAAAAAAAAKDqKE4BAAAAAAAAAABVR3EKAAAAAAAAAACoOopTAAAAAAAAAABA1VGcAgAAAAAAAAAAqo7iFAAAAAAAAAAAUHUUpwAAAAAAAAAAgKqjOAUAAAAAAAAAAFQdxSkAAAAAAAAAAKDqKE4BAAAAAAAAAABVR3EKAAAAAAAAAACoOopTAAAAAAAAAABA1VGcAgAAAAAAAAAAqo7iFAAAAAAAAAAAUHX+P1UgAwEKp2doAAAAAElFTkSuQmCC", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "import nest_asyncio\n", - "\n", - "nest_asyncio.apply() # Required for Jupyter Notebook to run async functions\n", - "\n", - "display(\n", - " Image(\n", - " app.get_graph().draw_mermaid_png(\n", - " curve_style=CurveStyle.LINEAR,\n", - " node_colors=NodeStyles(first=\"#ffdfba\", last=\"#baffc9\", default=\"#fad7de\"),\n", - " wrap_label_n_words=9,\n", - " output_file_path=None,\n", - " draw_method=MermaidDrawMethod.PYPPETEER,\n", - " background_color=\"white\",\n", - " padding=10,\n", - " )\n", - " )\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "d821b2f6", - "metadata": { - "ExecuteTime": { - "end_time": "2024-04-18T12:18:30.629629Z", - "start_time": "2024-04-18T12:18:30.620092Z" - } - }, - "source": [ - "**Using Graphviz**" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d4234400-75cd-4b13-aeff-828f7fb68ab1", - "metadata": { - "ExecuteTime": { - "end_time": "2024-04-19T11:25:42.057704Z", - "start_time": "2024-04-19T11:25:42.019017Z" - } - }, - "outputs": [], - "source": [ - "%%capture --no-stderr\n", - "%pip install pygraphviz" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "ee026342-f560-4ce0-ab43-1718bd19a366", - "metadata": { - "ExecuteTime": { - "end_time": "2024-04-19T11:25:42.631675Z", - "start_time": "2024-04-19T11:25:42.452377Z" - } - }, - "outputs": [ - { - "data": { - "image/png": "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P87s2bNZt24dDz/8MP/85z8xGAxahyWEEGesrKyMPXv2OBWn0tLSUBSlSXHq/PPPJzQ0VOuQRQdw8OBBbDYb/fr10zoUIYToSFq3EFVYWMiQIUOYOHEiq1ataq3ZCKGJJUuWoNPpmDdvntahCCGEaCNJSUksWrSItWvXMmLECObNm8f1118vB2mFEC5FURRefPFFEhMTGTFiBKtWrSIqKkrrsIQQ4pyVlpayd+9ep+LU/v37AZoUpy644AK5zbJo4u6772bFihVccsklrF69msDAQK1DEkKIjqB1C1EA33zzDVOnTuXVV1/lr3/9a2vOSgghhBCixdlsNr766iueeOIJkpOTiYuLIzExkWnTpmkdmhBCtKrU1FSuu+46fv/9d15++WWuu+46rUMSQogWV1JSwr59+9iyZQtJSUmkpKSQm5sLNC1OxcfHExwcrHHEQks2m401a9bwzTff8Morr2gdjhBCdBStX4gCeOihh3jhhRf46aefiI2Nbe3ZCSGEEEKcs5qaGv7zn//wr3/9i0OHDjFlyhQeffRRRo8erXVoQgjRZsxmM4mJiSxbtowbbriBFStW4Ofnp3VYQgjRqnJycpyumtq+fTt5eXkYDAb69+/vVJwaMWIEPj4+WocshBBCtGdtU4iyWq1MnjyZw4cPk5ycLJetCiGEEKLdKisr46233uLZZ5+lsLCQa665hkceeUTuAy+EcGv//e9/ue222/D392fVqlWMHTtW65CEEKJNnVic2rZtG/n5+RiNRvr16+dUnBo5ciTe3t5ahyw0lJubS5cuXeQW3kIIoWqbQhRAXl4esbGxxMfH89FHH7XFLIUQQgghTlteXh4vv/wyS5cuxWq1csstt5CYmEh4eLjWoQkhRLuQl5fHLbfcwvr163n44Yd59NFH0ev1WoclhBCaObE49fPPP1NYWNhscWr06NF4enpqHbJoIwkJCWRnZ3PnnXdy7733ah2OEEJore0KUQA//PADF198MUuXLuXOO+9sq9kKIYQQ7daRI0dQFIXu3btrHYrbyszMZOnSpaxcuZKAgAD+/ve/M3/+fIKCgrQOTQgh2h1FUXjxxRe5//77iYuL47333iMiIkLrsIQQot04sTi1ZcsWiouLMZlM9O3b16k4dd555+Hh4aF1yKIV/Prrr6xYsYK8vDw++OADrcMRQgittW0hCuCJJ57g6aef5ocffpDbOQghhHB7c+bM4eDBg/zvf//TOhS3s2vXLp5//nk++OADevbsydy5c7n99tvlNipCCHEaUlJSmDlzJsePH+eVV17h2muv1TqkDmPr1q1s3bqV+fPnax2KEKINWK1W0tPTnYpTO3fupKqqqqE4FR8fT1xcHCNHjmTgwIFytakQQghX0/aFKJvNxowZM/jll1/Ytm0bPXv2bMvZCyGEEO3KFVdcgYeHB6tXr9Y6FLeRlJTEokWLWLt2LcOGDWPBggXMnDkTo9GodWhCCNGhVFdX88ADD/Diiy9y44038vLLL+Pr66t1WO3e/fffz3fffceuXbu0DkUIoZHmilM7duyguroaPz8/hg0b5nTllBSnXJfFYpH9ECGEO2j7QhRARUUFcXFxWCwWfvrpJwIDA9s6BCHOWUpKCgUFBUyePFnrUIQQHdjq1avx9PTk8ssv1zoUl2az2fjqq6946qmn2LZtG3FxcSQmJjJ16lR0Op3W4QkhRIf2+eefc9tttxEaGsoHH3xAbGys1iG1axdeeCHR0dG8/vrrWocihGhHLBYLGRkZTsWplJQUzGYz/v7+DB061Kk4FRMTI/3YDs5mszFkyBBGjRrF3LlzGTlypNYhCSFEa9GmEAVw+PBhxowZw4gRI1izZg0Gg0GLMIQ4a3feeSepqan8+OOPWocihBDiJGpra1m9ejXPPPMMBw4cYMqUKTz88MOcf/75WocmhBAuJTs7m5tuuoktW7bw0EMP8eijj8rZ+ydRVFREVVUVkZGRWocihGjn6urqOHDggFNhavv27dTW1hIYGMjgwYOlONWBWSwW3n77bV566SXGjBnDq6++qnVIQgjRWrQrRAH89NNPXHjhhcybN49FixZpFYYQZ2XBggX8/PPP/Pzzz1qHIoQQ4gQVFRW88cYbLF68mOPHj3Pttdfy4IMPMnDgQK1DE0IIl6UoCi+++CL3338/48aN49133yU8PFzrsIQQwqU0Lk5t2bKFpKQkMjIysFqtBAUFMWjQoIbCVHx8PNHR0VqHLE5DdXW1PKtWCOHKtC1EAbz33nvcfPPNvPnmm8yaNUvLUIQ4I3v27KGsrIz4+HitQxFCCFEvPz+f5cuXs2zZMmpra5k9ezb33XefnHUuhBBtKDk5mZkzZ1JSUsLrr7/O9OnTtQ5JCCFcWkVFBbt27XK6cio9PR2bzUZYWJjTVVOjR4+mW7duWocshBDCvWhfiAJ46KGHeO6551izZg2XXHKJ1uEIIYQQooP57bffeOGFF3j99dfx9fXljjvuYO7cuXTq1Enr0IQQwi2Vl5dz7733snLlSm688UZeeeUVfHx8tA5LCCHcRnl5Obt373YqTqWlpaEoSpPi1JgxY+jSpYvWIYuTqKysZNq0adx4441cd911eHl5aR2SEEKcqfZRiFIUhVtvvZX//Oc/rF+/ngsuuEDrkIQQQgjRAezdu5d///vffPjhh0RGRjJ//nxuu+02OdgphBDtxKeffsrtt99O165d+eCDDxg+fLjWIQkhhNsqKytjz549p1WcGjt2LJ07d9Y6ZAHk5uZy77338sknn/D444/z4IMPah2SEEKcqfZRiAKwWq1cffXVbNq0ic2bN8szHIQQQghxUklJSSxatIivvvqKwYMHc++99zJz5kyMRqPWoQkhhDjB77//zo033sgvv/zC448/zn333Yder9c6LCGEEEBJSQn79u1zKk7t378foElxKi4uTu44oKFjx47h6elJcHCw1qEIIcSZaj+FKFAfzHfJJZeQlZXFli1b6Nmzp9YhCSGEEKKdUBSFtWvXsnDhQn766Sfi4uJITExk6tSp6HQ6rcMTQghxClarlcWLF/PPf/6TCRMm8M477xAWFqZ1WEIIIZqRm5tLcnJyQ2EqOTmZY8eOAY7iVHx8PHFxccTGxuLr66txxEIIIdq59lWIAigtLWX8+PFUVVWRlJQk96gVQgjhsr7//ntSUlK47777tA6lXaurq+PDDz/k2WefZf/+/Vx22WU88MADxMXFaR2aEEKIM/TLL79w/fXXU1payptvvsnUqVObHc9qtfLxxx/zl7/8pY0jbD0lJSX4+/tjMBi0DkUIIc5YTk6O01VTv/zyC8ePH8dgMNC/f3+nK6dGjhyJt7e31iG7naNHj7J8+XLuvPNOIiIitA5HCCEaa3+FKFA3nHFxcYSFhfHdd9/h7++vdUhCCCFEi3vkkUdYs2YNu3fv1jqUdqmyspLXX3+d559/niNHjnDllVfy2GOPMWjQIK1DE0IIcQ7Kysq46667eP/997ntttt44YUXmjzb78knn+Txxx/nxx9/ZNy4cRpF2rJuu+02fv/9d9atW6d1KEII0SJOLE5t3bqVgoICjEYj/fr1cypMjRo1Ci8vL61Ddmk//PAD119/PQUFBXz77bdceOGFWockhBB27bMQBZCRkcH48ePp27cv33zzDX5+flqHJIQQQrSoOXPmcOjQITZs2KB1KK2uoqLitHN5WVkZb731FgsXLqS4uJhrrrmGRx99lD59+rRylEIIIdrSxx9/zJw5cwgPD+eDDz5g6NChAPz888/Ex8ejKArh4eGkpqYSGBiocbTnLiYmhhkzZvD0009rHYoQQrSaE4tTP/30E0VFRc0Wp0aPHo2np6fWIbuU2tpaPvnkE6644gop/Akh2pP2W4gCtRg1ceJEoqOj+fbbb6UYJdoVm83Gn//8Z+6//36XOUtTCNG2SktLqaqqcvlnZCxdupTvv/+eL7744pTjHTt2jFdeeYUlS5agKAqzZs3igQcecPnfRwgh3Nnhw4e54YYbSE5OZuHChcyePZuhQ4dy5MgRLBYLJpOJa665hvfff1/rUM+JoigkJiYyffp04uPjtQ5HCCHalL04tWXLFpKSkti1axeVlZWYTCb69u3rVJw677zz8PDw0DpkIYQQLat9F6IA0tPTmThxIn369JEro0S7ExgYyHPPPcdf//pXrUMRQoh2afHixdx3333odDr27dtHTExMk3EOHjzIsmXLWLlyJUFBQcyZM4d//OMfLnH2uxBCiD9msVh44oknePrpp+nWrRvHjx+nrq7OaZwPP/zQpZ4XJYQQ7sxqtZKenu505dTOnTupqqrC19eX4cOHOxWnBg4ciF6v1zpsl3Ho0CGqq6sZPHiw1qEIIdxH+y9EgaMY1bdvX77++mspRol2IyYmhr///e/cfffdWocihBDtzrPPPktiYiIAJpOJv/zlL7z77rsNn+/YsYMlS5bwwQcf0KtXL+6++27mzJkjt5AQQgg39cQTT/DYY481Ga7T6fD19SU1NZUePXpoEJkQQojWZrFYyMjIcCpOpaSkYDab8ff3Z+jQoVKcaiH3338/ixcvZtKkSaxevZqQkBCtQxJCuL6OUYgC2LNnD5MmTSImJoavv/4aX19frUMSQgghxEksWrSIBx54wGmYwWDg0KFDZGdns2jRItauXUtsbCzz58/n+uuvx2AwaBStEEIIrWVlZTFkyBCqqqpobhfVZDJx3nnnsWnTJjnwKIQQbqK54lRycjI1NTUEBAQwZMgQp+JUTEwMOp1O67DbPUVRWLduHZ999hmv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5BNcvHgR0dHReOqppzB9+nS4ubkJHe+OKC0thbe3t9AxiIiI6BYYDAacOXMGiYmJcHFxwfPPPy90JCKyAnq9Hrm5ufD29oajo2Or44YPH47y8nIMGDAAH3/8sRkTEhEREVEHUCEWOgFRR+Tp6Ym//e1vuHDhAk6ePIl7770XL730Evz8/DB16lTs378fHbnHe+LECchkMmzatEnoKERERHSLxo4di1WrVqGoqEjoKERkBb744gs4Ojqia9euSElJaXPsgQMHcPr0aTahiIiIiOiGeEUU0R2iUCiwdetWrF+/vvGmun/5y1/wl7/8pcMtfaPX67Fo0SIsX74cJ06cQExMjNCRiIiI6CZyc3MRFBQEkUgkdBQislAGgwFr1qxBZmYmgoKCsHDhwlbHZmRk4OjRo+jWrRt69erF++MSERER0R/FpfmI2kNaWho2b96MDRs2QKlUYvz48Zg5cyYefPBB2NjYCB3vlqWmpvL+V0RERAJSKBRISEjADz/8gEcffRTjxo0TOhIRWSiNRoPs7GyEhoZCIpG0Oq5nz55wdnbGgw8+iNdff92MCYmIiIiok+LSfETtISoqCkuXLkV+fj6++OILVFRUYPz48ejatSv+8Y9/ICcnR+iIt4RNKKI7LzExEatWrRI6BhF1EEVFRZg9ezYKCws71GQWIjKv9957D46OjoiIiMDly5fbHHv+/HkcPXqUTSgiIiIiMhteEUVkJunp6di4cSM2btyIa9euYdiwYXj66acxYcIESKVSoeMRkZksXrwYiYmJSE1NFToKEXUQSqWSS2IRdUJKpRLr1q2DXC7HgAED8OSTT7Y69vTp08jIyEB4eDh69uwJOzs78wUlIiIiImobr4giMpeIiAgsXboUV69exZYtWwAAjz76KLp27YpXX331pjMXiYiIyHqcP38eixYtQnR0NPLz89scyyYUkfWpra3FxYsX2xxjY2ODDz74ABcuXEBdXV2bY/v27Ytp06YhJiaGTSgiIiIisji8IopIQHl5efjyyy+xdu1a5OTkICYmBjNnzsTMmTPh6ekpdLw2ffvtt7j33nsRHBwsdBSiDqW2thYajQaurq5CRyEiAf3vf//De++9hzFjxuDll19mPSXqRObNm4f169cDAFQqFRwcHARORERERETUrirYiCKyAHq9HklJSdi0aRN27twJvV6P+Ph4zJw5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IiIiItLgaWk+EZG64HQ62bFjB6tWrSIpKYlvvvkGX19frr/+ehITE7n55puJjo42OqbUk61bt3LNNdeccd5qtfL0008zY8YMA1LJxcrNzWXChAls3LiRJ554glmzZhkdSS7QnDlz+O677zCZTCxatKjWcXa7na1btxIVFUX79u0xmUz1mFJERERERETkkqRClIhIXSovLycuLo4hQ4YQFRXF1q1bSUpKori4mMjISBITE2v2lvL19TU6rtShyMhIcnJyzjj/448/0rlzZwMSycWqrKzk/vvvZ/DgwQwePJjg4GCjI8kp3G43ubm5ZGZm0qNHD1q3bl3r2D/84Q8UFBQQGxvLzJkz6zGliIiIiIiISKOnQpSISF0qKSnhpZdeYsGCBUyaNImnn34ah8PBxo0b+eqrr1i2bBnp6ekEBgZy4403MmLECIYPH06HDh2Mji5eNnPmTP7617/WLM9nMpno2bMn27dvNziZnI3b7Wb79u3ExMSoSHyJWrhwIXfddRcAixYt4tZbbzU4kYiIiIiIiMhlSYUoEZH64HK5qKioICAg4Ixr+fn5rFixgi+//JIVK1ZQWlpa0y2VmJjI8OHDCQwMNCC1eNPu3btPW47RYrEwe/ZsHnnkEQNTydksXryYBx54gPz8fFauXEliYqLRkeQUjz/+OBkZGYSHh/PGG2/UOi4/P5/MzEw6d+5MSEhIPSYUERERERERkVOoECUi0lAUFhYSFBTEhg0bWL58OStWrCA9PR1/f38GDBjA0KFDGTZsGF27djU6qlyg7t27k56ejtvtxmQykZubS7t27YyOJf8jPT2dpKQkhg0bRs+ePbUPUD1wOBzs27ePrKws+vfvf9ai/c9uu+02bDYb/fr148EHH6zHlCIiIiIiIiJyAVSIEhFpCH766SfCw8OJj4/n8ccfZ+TIkYDnX/SvX7+epKQkli5dytGjRwkNDWXw4MGMGjWKxMREWrRoYXB6OVezZ89m+vTpuFwubrjhBtauXWt0pMtOQUEBKSkpDBs2zOgocornnnuOGTNmALBlyxb69OljcCIRERERERER8RIVokREGoKqqipWrFjBhx9+yMiRI7nzzjvPGON0OtmxYwerVq1i1apVrFu3DpfLRa9evWqW8Rs4cCAWi8WAGci5yM3NpWPHjrjdbubNm8ekSZOMjnRZeeCBB3j77bcJCAigoKAAf39/oyM1asePH2fatGlkZWXRr18/nn766VrHHjhwgIKCAqKiomjevHk9phQRERERERGROqZClIjIpaqoqIhVq1axYsUKVqxYQV5eHq1bt2bw4MEMHTqUxMRELfvWAPXr14+tW7eSn5+vbrZ69vXXX1NeXk5CQgJNmjQxOs4lq6KigszMTLKyshg9enSt41wuF4MHD6Zjx44MHTqUsWPH1mNKEREREREREWkgVIgSEbnUzJw5k4EDB9K/f398fHxqzu/cubOmKLVx40YqKyuJjo4+rVuqadOmBiYXgLfeeovly5ezZMkSo6M0CAUFBYSEhFzUMxwOB5s2baKqqoohQ4Z4KZnUZvLkycybNw/w7G3XunVrgxOJiIiIiIiISAOmQpSIyKWkqKiIhIQEdu7cyf3338/cuXPPOu7EiRNs2rSpZhm/7du3YzKZTlvG74YbbsDX17eeZ9D4lZeXY7fbsdvtNefsdjsOhwOA0tJSUlJSGDhwYM31UzujfH19CQoKavRFw8rKSmbMmMFXX31FWlraBT/H5XLRoUMH8vLyGDNmDP/+97+9mPLycejQIWbOnElmZibjxo1j8uTJtY7du3cvFRUVREVFaXlDEREREREREfk1KkSJiFyK9u7di9vtpkuXLuc0/siRI6xZs6amMJWdnU1AQAB9+/atKUz17t0bs9nslXwul8trzzJSUVEReXl5HD58mPz8fAoLC8nPz/ccFxzm2NEjlJWVUlZWRklJGaX2cpxOl9e+v1nTJgQFNiEoMJDAoEBatGxNcEgYwcHBtGnThtDQ0Jrjtm3bEhYWhslk8tr315X09HTGjh1LRkYGbrebAwcO0KFDhwt+3tKlS4mOjiYyMtKLKRuH0tJSMjMzyc/PZ/jw4bWOKygoYPz48URFRTFmzBgGDx5cjylFREREREREpBFTIUpEpLHasmULXbt2PWtnTXZ2Nhs3bmTTpk18+eWX5OXlERwczMCBA0lMTGTIkCFERERc0PdmZWVx1113MX/+fLp27XqRs6hbTqeT7Oxsdu3aRU5OjueVncW+nL3s259LaVl5zVirxUxIcwshTU2ENq0mJMhJiyYQ5A+BftA8AIL8PMdB/p7jn/nbwM969gzVTiirOPn5RBXYKzznisuh7ITns70SjtqhsMxMod3C4RIT+ceqKa901tzra7PSMbwtEZ2uIKJTFBEREXTq1IkuXboQHR1tePeK2+1m3rx5PPzwwzidTqqrq7FYLMydO5dJkyadMT4rK4vly5dz3XXXERcXZ0DiS9/QoUNJTk4mKCiIkpKSS6JQKSIiIiIiIiKNigpRIiKNkdvtpn379hQVFXHffffx5ptv/uL47Ozsmm6p5cuXU1ZWRmRkZE231I033kjLli3P6bvfffddJk2ahM1m49lnn2XKlCmn7WVllP3797Nt2zZ27dpFWtoP7M7Yya7dmVRWeZbMC21pI6I1RLSqolMwRARDp2Bo3xJCmkGrQIMnUIvjlXC4GH4qhpxCyCmAfUdgX5GVnEITB484qHa6MZtNdOrYjpjYXnSLiaVbt2707NmTmJiYevnzyc/PZ8KECaxcuRKX62TXmI+PD6NGjWLx4sWnjd++fTtXXXUVTZs25e9//zsTJ06s84yXirS0NF544QUyMzOZPn06o0aNqnVseno6VquViIgIbDZbPaYUEREREREREQFUiBIRabyOHTtGUlISTqeTe++995zvq66uJjU1taYwtW7dOpxOJ717964pTF1//fX4+flRWVmJ1Wo9bRm+8ePH8+mnn1JdXY3ZbKZXr168//77dOvWrS6meValpaXs3LmTbdu2sWnjetavW0t+4VEAwlpaiWnnpFtbFzHtoVs76NXR08nUGFU74UARpB+EjEOQfshExk82dh2sprzCSZMAP3r17EFcH0/XUVxcHN26dfNq58znn3/OfffdR3l5ec1eWacKCAiguLgYq/Vk25jL5WLDhg307dv3tPON2ZEjR8jMzKS8vJyEhIRax6WmpjJ9+nSioqK46667uPrqq+sxpYiIiIiIiIjIeVEhSkTkcpednU3z5s1r7Xiy2+189913NYWplJQU/Pz86NevH6GhoezYsYOPP/6YmJgYAEJCQigsLKy532Kx4Ha7efTRR5k1a1addGWUlJSwfv16vv76a9Z8vYIf0vfgdrvpFGrjmk4O+kS6ueYKuCoCmvh6/esvSdVOSD8EW7NgcxZs3Wcj/YCne6p92xASEoeSkHAjCQkJF7x/U1lZGVOmTOGdd97BbDaf1gn1v9atW0f//v0vdDqNQteuXdmzZw+xsbH88MMPRscREREREREREfEGFaJERC53Y8aMISkpiX79+pGcnPyrhaLc3NyaotSSJUsoL/fsoxQbG8uYMWOYNWvW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4MTxEh64sZo/DoXQ5kYnk4tR4YB/roc5X1k5cMTNw398hBkzZtCsWTOjo4mIiIiIiIiISP3SHlEiImK8srIyXn/9dV59+SWOHSvm7hvcTB3h4sowo5PJ+Th2HOaugleTLRSXw90TJvD443/iiiuuMDqaiIiIiIiIiIgYQ4UoERFpOKqqqvj444/52/Oz2LUni7hIHyYPcjKuLwT6GZ1Ozsblhm9+hPc3mflgkwkfqy/33DuJxx57TEvwiYiIiIiIiIiIClEiItLwuFwuli9fzvx33yEpKQlfK9x+jYs7r3dxw5Xgox0ODZdxCD79DhZstLK/wEH8tVdz78TJ3HHHHQQFBRkdT0REREREREREGgYVokREpGE7cuQIH3zwAQvmz2PHznRaNbUyqlc1t1ztZkh38LcZnfDy4HLD5kxY8j0s2W7jx0NVhLVpzZ1338u9995LdHS00RFFRERERERERKThUSFKREQuHZmZmSxevJglny/iuy3f42czk9ANEro5SYiBHh3AZDI6ZeORWwSrM2B1uonkNAuHjzmIigznljG3c8sttxAfH4/ZrPY0ERERERERERGplQpRIiJyaTp8+DBffPEFyckrWLvma4qOltC6mZVB0U4GdnUR3xliO4DVx+ikl47MfNiSBet2wZrdVvbmOfDztRJ/3bUkDhnOzTffTGxsrNExRURERERERETk0qFClIiIXPpcLhepqamsWbOG1V+vZP36dZTZT+Dv60OvCDPXdHLQJxKujoSoNtpjCuDQMUjJga3ZsDXHhy1ZJo6WVWO1+HB1XG8SEoeSkJBAfHw8/v7+RscVEREREREREZFLkwpRIiLS+LhcLnbv3s2WLVvYunUrW77bSOrOdBzVTnytZqLbW4kOqyK2vZtu7SCmPXRsDTaL0cm9y+32FJx250H6Qcg4BGmHrGQcclNsr8ZkMtH5inD6XNuPa665lj59+tC7d2/8/PyMji4iIiIiIiIiIo2DClEiInJ5qKys5IcffiA9PZ2MjAzS03aSkf4D+w7k4Xa7MZtNtG1pJSLYTadWDiKCISIY2reE0GYQ0hSCmzasbqqjdsgvgcIyOHgU9hX+91VkYd8RHw4UOqh0uABo3bIZsbGxRMf0oHv37kRHR9OrVy+aN29u8CxERERERERERKQRUyFKREQub3a7nT179pCTk8O+ffs8r5wscrL3sm//QcpPVNaMNZtNBDezEtzURGgzFy38HTQLgEBfCPSDIH9oHgBBfmDx8exPFXhKc5G/DfysnmOnC0pPnLxW6YDyKs/xseNgr/C8yio840rKwV7lw+ESC4dL3BSWVFP13yITgNXiQ/t2oUREdCIisjMRERF06tSJiIgIunbtSnBwcF3+GEVERERERERERM5GhSgREZFfcuzYMQ4fPkxhYSGHDx8mPz+/5ri4uJiS4iLsZaWUlZVSVlZGSUkZpfZynE7Xrz+8Fs2aNiEosAmBTZoQ1DSIZs1a0KxFKwIDgwgJCSEsLIzg4GDatGlDaGgowcHBhISEYDY3oHYtERERERERERERFaJERETqTkVFBSdOnGx7stvtOByOms8tWrSoObZYL2SkjgAAAF9JREFULAQFBdVrPhERERERERERkTqmQpSIiIiIiIiIiIiIiIjUiWNaw0dERERERERERERERETqhApRIiIiIiIiIiIiIiIiUicswDajQ4iIiIiIiIiIiIiIiEijU/r/ARN5/xGPrsbJAAAAAElFTkSuQmCC", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "try:\n", - " display(Image(app.get_graph().draw_png()))\n", - "except ImportError:\n", - " print(\n", - " \"You likely need to install dependencies for pygraphviz, see more here https://github.com/pygraphviz/pygraphviz/blob/main/INSTALL.txt\"\n", - " )" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": ".venv", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.6" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/docs/docs/how-tos/graph-api.md b/docs/docs/how-tos/graph-api.md new file mode 100644 index 000000000..2e15cacb1 --- /dev/null +++ b/docs/docs/how-tos/graph-api.md @@ -0,0 +1,1877 @@ +# How to use the graph API + +This guide demonstrates the basics of LangGraph's Graph API. It walks through [state](#define-and-update-state), as well as composing common graph structures such as [sequences](#create-a-sequence-of-steps), [branches](#create-branches), and [loops](#create-and-control-loops). It also covers LangGraph's control features, including the [Send API](#map-reduce-and-the-send-api) for map-reduce workflows and the [Command API](#combine-control-flow-and-state-updates-with-command) for combining state updates with "hops" across nodes. + +## Setup + +Install `langgraph`: + +```bash +pip install -U langgraph +``` + +!!! tip "Set up LangSmith for better debugging" + Sign up for [LangSmith](https://smith.langchain.com) to quickly spot issues and improve the performance of your LangGraph projects. LangSmith lets you use trace data to debug, test, and monitor your LLM apps built with LangGraph — read more about how to get started in the [docs](https://docs.smith.langchain.com). + +## Define and update state + +Here we show how to define and update [state](../concepts/low_level.md#state) in LangGraph. We will demonstrate: + +1. How to use state to define a graph's [schema](../concepts/low_level.md#schema) +2. How to use [reducers](../concepts/low_level.md#reducers) to control how state updates are processed. + +### Define state + +[State](../concepts/low_level.md#state) in LangGraph can be a `TypedDict`, `Pydantic` model, or dataclass. Below we will use `TypedDict`. See [this section](#use-pydantic-models-for-graph-state) for detail on using Pydantic. + +By default, graphs will have the same input and output schema, and the state determines that schema. See [this section](#define-input-and-output-schemas) for how to define distinct input and output schemas. + +Let's consider a simple example using [messages](../concepts/low_level.md#messagesstate). This represents a versatile formulation of state for many LLM applications. See our [concepts page](../concepts/low_level.md#working-with-messages-in-graph-state) for more detail. + +```python +from langchain_core.messages import AnyMessage +from typing_extensions import TypedDict + +class State(TypedDict): + messages: list[AnyMessage] + extra_field: int +``` + +This state tracks a list of [message](https://python.langchain.com/docs/concepts/messages/) objects, as well as an extra integer field. + +### Update state + +Let's build an example graph with a single node. Our [node](../concepts/low_level.md#nodes) is just a Python function that reads our graph's state and makes updates to it. The first argument to this function will always be the state: + +```python +from langchain_core.messages import AIMessage + +def node(state: State): + messages = state["messages"] + new_message = AIMessage("Hello!") + return {"messages": messages + [new_message], "extra_field": 10} +``` + +This node simply appends a message to our message list, and populates an extra field. + +!!! important + Nodes should return updates to the state directly, instead of mutating the state. + +Let's next define a simple graph containing this node. We use [StateGraph](../concepts/low_level.md#stategraph) to define a graph that operates on this state. We then use [add_node](../concepts/low_level.md#nodes) populate our graph. + +```python +from langgraph.graph import StateGraph + +builder = StateGraph(State) +builder.add_node(node) +builder.set_entry_point("node") +graph = builder.compile() +``` + +LangGraph provides built-in utilities for visualizing your graph. Let's inspect our graph. See [this section](#visualize-your-graph) for detail on visualization. + +```python +from IPython.display import Image, display + +display(Image(graph.get_graph().draw_mermaid_png())) +``` + +![Simple graph with single node](assets/graph_api_image_1.png) + +In this case, our graph just executes a single node. Let's proceed with a simple invocation: + +```python +from langchain_core.messages import HumanMessage + +result = graph.invoke({"messages": [HumanMessage("Hi")]}) +result +``` +``` +{'messages': [HumanMessage(content='Hi'), AIMessage(content='Hello!')], 'extra_field': 10} +``` + +Note that: + +- We kicked off invocation by updating a single key of the state. +- We receive the entire state in the invocation result. + +For convenience, we frequently inspect the content of [message objects](https://python.langchain.com/docs/concepts/messages/) via pretty-print: + +```python +for message in result["messages"]: + message.pretty_print() +``` +``` +================================ Human Message ================================ + +Hi +================================== Ai Message ================================== + +Hello! +``` + +### Process state updates with reducers + +Each key in the state can have its own independent [reducer](../concepts/low_level.md#reducers) function, which controls how updates from nodes are applied. If no reducer function is explicitly specified then it is assumed that all updates to the key should override it. + +For `TypedDict` state schemas, we can define reducers by annotating the corresponding field of the state with a reducer function. + +In the earlier example, our node updated the `"messages"` key in the state by appending a message to it. Below, we add a reducer to this key, such that updates are automatically appended: + +```python +from typing_extensions import Annotated + +def add(left, right): + """Can also import `add` from the `operator` built-in.""" + return left + right + +class State(TypedDict): + # highlight-next-line + messages: Annotated[list[AnyMessage], add] + extra_field: int +``` + +Now our node can be simplified: + +```python +def node(state: State): + new_message = AIMessage("Hello!") + # highlight-next-line + return {"messages": [new_message], "extra_field": 10} +``` +```python +from langgraph.graph import START + +graph = StateGraph(State).add_node(node).add_edge(START, "node").compile() + +result = graph.invoke({"messages": [HumanMessage("Hi")]}) + +for message in result["messages"]: + message.pretty_print() +``` +``` +================================ Human Message ================================ + +Hi +================================== Ai Message ================================== + +Hello! +``` + +#### MessagesState + +In practice, there are additional considerations for updating lists of messages: + +- We may wish to update an existing message in the state. +- We may want to accept short-hands for [message formats](../concepts/low_level.md#using-messages-in-your-graph), such as [OpenAI format](https://python.langchain.com/docs/concepts/messages.md#openai-format). + +LangGraph includes a built-in reducer `add_messages` that handles these considerations: + +```python +from langgraph.graph.message import add_messages + +class State(TypedDict): + # highlight-next-line + messages: Annotated[list[AnyMessage], add_messages] + extra_field: int + +def node(state: State): + new_message = AIMessage("Hello!") + return {"messages": [new_message], "extra_field": 10} + +graph = StateGraph(State).add_node(node).set_entry_point("node").compile() +``` + +```python +# highlight-next-line +input_message = {"role": "user", "content": "Hi"} + +result = graph.invoke({"messages": [input_message]}) + +for message in result["messages"]: + message.pretty_print() +``` +``` +================================ Human Message ================================ + +Hi +================================== Ai Message ================================== + +Hello! +``` + +This is a versatile representation of state for applications involving [chat models](https://python.langchain.com/docs/concepts/chat_models/). LangGraph includes a pre-built `MessagesState` for convenience, so that we can have: + +```python +from langgraph.graph import MessagesState + +class State(MessagesState): + extra_field: int +``` + +### Define input and output schemas + +By default, `StateGraph` operates with a single schema, and all nodes are expected to communicate using that schema. However, it's also possible to define distinct input and output schemas for a graph. + +When distinct schemas are specified, an internal schema will still be used for communication between nodes. The input schema ensures that the provided input matches the expected structure, while the output schema filters the internal data to return only the relevant information according to the defined output schema. + +Below, we'll see how to define distinct input and output schema. + +```python +from langgraph.graph import StateGraph, START, END +from typing_extensions import TypedDict + +# Define the schema for the input +class InputState(TypedDict): + question: str + +# Define the schema for the output +class OutputState(TypedDict): + answer: str + +# Define the overall schema, combining both input and output +class OverallState(InputState, OutputState): + pass + +# Define the node that processes the input and generates an answer +def answer_node(state: InputState): + # Example answer and an extra key + return {"answer": "bye", "question": state["question"]} + +# Build the graph with input and output schemas specified +builder = StateGraph(OverallState, input_schema=InputState, output_schema=OutputState) +builder.add_node(answer_node) # Add the answer node +builder.add_edge(START, "answer_node") # Define the starting edge +builder.add_edge("answer_node", END) # Define the ending edge +graph = builder.compile() # Compile the graph + +# Invoke the graph with an input and print the result +print(graph.invoke({"question": "hi"})) +``` +``` +{'answer': 'bye'} +``` + +Notice that the output of invoke only includes the output schema. + +### Pass private state between nodes + +In some cases, you may want nodes to exchange information that is crucial for intermediate logic but doesn't need to be part of the main schema of the graph. This private data is not relevant to the overall input/output of the graph and should only be shared between certain nodes. + +Below, we'll create an example sequential graph consisting of three nodes (node_1, node_2 and node_3), where private data is passed between the first two steps (node_1 and node_2), while the third step (node_3) only has access to the public overall state. + +```python +from langgraph.graph import StateGraph, START, END +from typing_extensions import TypedDict + +# The overall state of the graph (this is the public state shared across nodes) +class OverallState(TypedDict): + a: str + +# Output from node_1 contains private data that is not part of the overall state +class Node1Output(TypedDict): + private_data: str + +# The private data is only shared between node_1 and node_2 +def node_1(state: OverallState) -> Node1Output: + output = {"private_data": "set by node_1"} + print(f"Entered node `node_1`:\n\tInput: {state}.\n\tReturned: {output}") + return output + +# Node 2 input only requests the private data available after node_1 +class Node2Input(TypedDict): + private_data: str + +def node_2(state: Node2Input) -> OverallState: + output = {"a": "set by node_2"} + print(f"Entered node `node_2`:\n\tInput: {state}.\n\tReturned: {output}") + return output + +# Node 3 only has access to the overall state (no access to private data from node_1) +def node_3(state: OverallState) -> OverallState: + output = {"a": "set by node_3"} + print(f"Entered node `node_3`:\n\tInput: {state}.\n\tReturned: {output}") + return output + +# Connect nodes in a sequence +# node_2 accepts private data from node_1, whereas +# node_3 does not see the private data. +builder = StateGraph(OverallState).add_sequence([node_1, node_2, node_3]) +builder.add_edge(START, "node_1") +graph = builder.compile() + +# Invoke the graph with the initial state +response = graph.invoke( + { + "a": "set at start", + } +) + +print() +print(f"Output of graph invocation: {response}") +``` +``` +Entered node `node_1`: + Input: {'a': 'set at start'}. + Returned: {'private_data': 'set by node_1'} +Entered node `node_2`: + Input: {'private_data': 'set by node_1'}. + Returned: {'a': 'set by node_2'} +Entered node `node_3`: + Input: {'a': 'set by node_2'}. + Returned: {'a': 'set by node_3'} + +Output of graph invocation: {'a': 'set by node_3'} +``` + +### Use Pydantic models for graph state + +A [StateGraph](https://langchain-ai.github.io/langgraph/reference/graphs.md#langgraph.graph.StateGraph) accepts a `state_schema` argument on initialization that specifies the "shape" of the state that the nodes in the graph can access and update. + +In our examples, we typically use a python-native `TypedDict` for `state_schema`, but `state_schema` can be any [type](https://docs.python.org/3/library/stdtypes.html#type-objects). + +Here, we'll see how a [Pydantic BaseModel](https://docs.pydantic.dev/latest/api/base_model/). can be used for `state_schema` to add run time validation on **inputs**. + +!!! note "Known Limitations" + - Currently, the output of the graph will **NOT** be an instance of a pydantic model. + - Run-time validation only occurs on inputs into nodes, not on the outputs. + - The validation error trace from pydantic does not show which node the error arises in. + +```python +from langgraph.graph import StateGraph, START, END +from typing_extensions import TypedDict +from pydantic import BaseModel + +# The overall state of the graph (this is the public state shared across nodes) +class OverallState(BaseModel): + a: str + +def node(state: OverallState): + return {"a": "goodbye"} + +# Build the state graph +builder = StateGraph(OverallState) +builder.add_node(node) # node_1 is the first node +builder.add_edge(START, "node") # Start the graph with node_1 +builder.add_edge("node", END) # End the graph after node_1 +graph = builder.compile() + +# Test the graph with a valid input +graph.invoke({"a": "hello"}) +``` + +Invoke the graph with an **invalid** input + +```python +try: + graph.invoke({"a": 123}) # Should be a string +except Exception as e: + print("An exception was raised because `a` is an integer rather than a string.") + print(e) +``` +``` +An exception was raised because `a` is an integer rather than a string. +1 validation error for OverallState +a + Input should be a valid string [type=string_type, input_value=123, input_type=int] + For further information visit https://errors.pydantic.dev/2.9/v/string_type +``` + +See below for additional features of Pydantic model state: + +??? example "Serialization Behavior" + + When using Pydantic models as state schemas, it's important to understand how serialization works, especially when: + - Passing Pydantic objects as inputs + - Receiving outputs from the graph + - Working with nested Pydantic models + + Let's see these behaviors in action. + + ```python + from langgraph.graph import StateGraph, START, END + from pydantic import BaseModel + + class NestedModel(BaseModel): + value: str + + class ComplexState(BaseModel): + text: str + count: int + nested: NestedModel + + def process_node(state: ComplexState): + # Node receives a validated Pydantic object + print(f"Input state type: {type(state)}") + print(f"Nested type: {type(state.nested)}") + # Return a dictionary update + return {"text": state.text + " processed", "count": state.count + 1} + + # Build the graph + builder = StateGraph(ComplexState) + builder.add_node("process", process_node) + builder.add_edge(START, "process") + builder.add_edge("process", END) + graph = builder.compile() + + # Create a Pydantic instance for input + input_state = ComplexState(text="hello", count=0, nested=NestedModel(value="test")) + print(f"Input object type: {type(input_state)}") + + # Invoke graph with a Pydantic instance + result = graph.invoke(input_state) + print(f"Output type: {type(result)}") + print(f"Output content: {result}") + + # Convert back to Pydantic model if needed + output_model = ComplexState(**result) + print(f"Converted back to Pydantic: {type(output_model)}") + ``` + +??? example "Runtime Type Coercion" + + Pydantic performs runtime type coercion for certain data types. This can be helpful but also lead to unexpected behavior if you're not aware of it. + + ```python + from langgraph.graph import StateGraph, START, END + from pydantic import BaseModel + + class CoercionExample(BaseModel): + # Pydantic will coerce string numbers to integers + number: int + # Pydantic will parse string booleans to bool + flag: bool + + def inspect_node(state: CoercionExample): + print(f"number: {state.number} (type: {type(state.number)})") + print(f"flag: {state.flag} (type: {type(state.flag)})") + return {} + + builder = StateGraph(CoercionExample) + builder.add_node("inspect", inspect_node) + builder.add_edge(START, "inspect") + builder.add_edge("inspect", END) + graph = builder.compile() + + # Demonstrate coercion with string inputs that will be converted + result = graph.invoke({"number": "42", "flag": "true"}) + + # This would fail with a validation error + try: + graph.invoke({"number": "not-a-number", "flag": "true"}) + except Exception as e: + print(f"\nExpected validation error: {e}") + ``` + +??? example "Working with Message Models" + + When working with LangChain message types in your state schema, there are important considerations for serialization. You should use `AnyMessage` (rather than `BaseMessage`) for proper serialization/deserialization when using message objects over the wire. + + ```python + from langgraph.graph import StateGraph, START, END + from pydantic import BaseModel + from langchain_core.messages import HumanMessage, AIMessage, AnyMessage + from typing import List + + class ChatState(BaseModel): + messages: List[AnyMessage] + context: str + + def add_message(state: ChatState): + return {"messages": state.messages + [AIMessage(content="Hello there!")]} + + builder = StateGraph(ChatState) + builder.add_node("add_message", add_message) + builder.add_edge(START, "add_message") + builder.add_edge("add_message", END) + graph = builder.compile() + + # Create input with a message + initial_state = ChatState( + messages=[HumanMessage(content="Hi")], context="Customer support chat" + ) + + result = graph.invoke(initial_state) + print(f"Output: {result}") + + # Convert back to Pydantic model to see message types + output_model = ChatState(**result) + for i, msg in enumerate(output_model.messages): + print(f"Message {i}: {type(msg).__name__} - {msg.content}") + ``` + +## Add runtime configuration + +Sometimes you want to be able to configure your graph when calling it. For example, you might want to be able to specify what LLM or system prompt to use at runtime, *without polluting the graph state with these parameters*. + +To add runtime configuration: + +1. Specify a schema for your configuration +2. Add the configuration to the function signature for nodes or conditional edges +3. Pass the configuration into the graph. + +See below for a simple example: + +```python +from langchain_core.runnables import RunnableConfig +from langgraph.graph import END, StateGraph, START +from typing_extensions import TypedDict + +# 1. Specify config schema +class ConfigSchema(TypedDict): + my_runtime_value: str + +# 2. Define a graph that accesses the config in a node +class State(TypedDict): + my_state_value: str + +# highlight-next-line +def node(state: State, config: RunnableConfig): + # highlight-next-line + if config["configurable"]["my_runtime_value"] == "a": + return {"my_state_value": 1} + # highlight-next-line + elif config["configurable"]["my_runtime_value"] == "b": + return {"my_state_value": 2} + else: + raise ValueError("Unknown values.") + +# highlight-next-line +builder = StateGraph(State, config_schema=ConfigSchema) +builder.add_node(node) +builder.add_edge(START, "node") +builder.add_edge("node", END) + +graph = builder.compile() + +# 3. Pass in configuration at runtime: +# highlight-next-line +print(graph.invoke({}, {"configurable": {"my_runtime_value": "a"}})) +# highlight-next-line +print(graph.invoke({}, {"configurable": {"my_runtime_value": "b"}})) +``` +``` +{'my_state_value': 1} +{'my_state_value': 2} +``` + +??? example "Extended example: specifying LLM at runtime" + Below we demonstrate a practical example in which we configure what LLM to use at runtime. We will use both OpenAI and Anthropic models. + + ```python + from langchain.chat_models import init_chat_model + from langchain_core.runnables import RunnableConfig + from langgraph.graph import MessagesState + from langgraph.graph import END, StateGraph, START + from typing_extensions import TypedDict + + class ConfigSchema(TypedDict): + model: str + + MODELS = { + "anthropic": init_chat_model("anthropic:claude-3-5-haiku-latest"), + "openai": init_chat_model("openai:gpt-4.1-mini"), + } + + def call_model(state: MessagesState, config: RunnableConfig): + model = config["configurable"].get("model", "anthropic") + model = MODELS[model] + response = model.invoke(state["messages"]) + return {"messages": [response]} + + builder = StateGraph(MessagesState, config_schema=ConfigSchema) + builder.add_node("model", call_model) + builder.add_edge(START, "model") + builder.add_edge("model", END) + + graph = builder.compile() + + # Usage + input_message = {"role": "user", "content": "hi"} + # With no configuration, uses default (Anthropic) + response_1 = graph.invoke({"messages": [input_message]})["messages"][-1] + # Or, can set OpenAI + config = {"configurable": {"model": "openai"}} + response_2 = graph.invoke({"messages": [input_message]}, config=config)["messages"][-1] + + print(response_1.response_metadata["model_name"]) + print(response_2.response_metadata["model_name"]) + ``` + ``` + claude-3-5-haiku-20241022 + gpt-4.1-mini-2025-04-14 + ``` + +??? example "Extended example: specifying model and system message at runtime" + Below we demonstrate a practical example in which we configure two parameters: the LLM and system message to use at runtime. + + ```python + from typing import Optional + from langchain.chat_models import init_chat_model + from langchain_core.messages import SystemMessage + from langchain_core.runnables import RunnableConfig + from langgraph.graph import END, MessagesState, StateGraph, START + from typing_extensions import TypedDict + + class ConfigSchema(TypedDict): + model: Optional[str] + system_message: Optional[str] + + MODELS = { + "anthropic": init_chat_model("anthropic:claude-3-5-haiku-latest"), + "openai": init_chat_model("openai:gpt-4.1-mini"), + } + + def call_model(state: MessagesState, config: RunnableConfig): + model = config["configurable"].get("model", "anthropic") + model = MODELS[model] + messages = state["messages"] + if system_message := config["configurable"].get("system_message"): + messages = [SystemMessage(system_message)] + messages + response = model.invoke(messages) + return {"messages": [response]} + + builder = StateGraph(MessagesState, config_schema=ConfigSchema) + builder.add_node("model", call_model) + builder.add_edge(START, "model") + builder.add_edge("model", END) + + graph = builder.compile() + + # Usage + input_message = {"role": "user", "content": "hi"} + config = {"configurable": {"model": "openai", "system_message": "Respond in Italian."}} + response = graph.invoke({"messages": [input_message]}, config) + for message in response["messages"]: + message.pretty_print() + ``` + ``` + ================================ Human Message ================================ + + hi + ================================== Ai Message ================================== + + Ciao! Come posso aiutarti oggi? + ``` + +## Add retry policies + +There are many use cases where you may wish for your node to have a custom retry policy, for example if you are calling an API, querying a database, or calling an LLM, etc. LangGraph lets you add retry policies to nodes. + +To configure a retry policy, pass the `retry_policy` parameter to the [add_node](https://langchain-ai.github.io/langgraph/reference/graphs.md#langgraph.graph.state.StateGraph.add_node). The `retry_policy` parameter takes in a `RetryPolicy` named tuple object. Below we instantiate a `RetryPolicy` object with the default parameters and associate it with a node: + +```python +from langgraph.pregel import RetryPolicy + +builder.add_node( + "node_name", + node_function, + retry_policy=RetryPolicy(), +) +``` + +By default, the `retry_on` parameter uses the `default_retry_on` function, which retries on any exception except for the following: + +* `ValueError` +* `TypeError` +* `ArithmeticError` +* `ImportError` +* `LookupError` +* `NameError` +* `SyntaxError` +* `RuntimeError` +* `ReferenceError` +* `StopIteration` +* `StopAsyncIteration` +* `OSError` + +In addition, for exceptions from popular http request libraries such as `requests` and `httpx` it only retries on 5xx status codes. + +??? example "Extended example: customizing retry policies" + Consider an example in which we are reading from a SQL database. Below we pass two different retry policies to nodes: + + ```python + import sqlite3 + from typing_extensions import TypedDict + from langchain.chat_models import init_chat_model + from langgraph.graph import END, MessagesState, StateGraph, START + from langgraph.pregel import RetryPolicy + from langchain_community.utilities import SQLDatabase + from langchain_core.messages import AIMessage + + db = SQLDatabase.from_uri("sqlite:///:memory:") + model = init_chat_model("anthropic:claude-3-5-haiku-latest") + + def query_database(state: MessagesState): + query_result = db.run("SELECT * FROM Artist LIMIT 10;") + return {"messages": [AIMessage(content=query_result)]} + + def call_model(state: MessagesState): + response = model.invoke(state["messages"]) + return {"messages": [response]} + + # Define a new graph + builder = StateGraph(MessagesState) + builder.add_node( + "query_database", + query_database, + retry_policy=RetryPolicy(retry_on=sqlite3.OperationalError), + ) + builder.add_node("model", call_model, retry_policy=RetryPolicy(max_attempts=5)) + builder.add_edge(START, "model") + builder.add_edge("model", "query_database") + builder.add_edge("query_database", END) + graph = builder.compile() + ``` + +## Add node caching + +Node caching is useful in cases where you want to avoid repeating operations, like when doing something expensive (either in terms of time or cost). LangGraph lets you add individualized caching policies to nodes in a graph. + +To configure a cache policy, pass the `cache_policy` parameter to the [add_node](https://langchain-ai.github.io/langgraph/reference/graphs.md#langgraph.graph.state.StateGraph.add_node) function. In the following example, a [`CachePolicy`](https://langchain-ai.github.io/langgraph/reference/types/?h=cachepolicy#langgraph.types.CachePolicy) object is instantiated with a time to live of 120 seconds and the default `key_func` generator. Then it is associated with a node: + +```python +from langgraph.types import CachePolicy + +builder.add_node( + "node_name", + node_function, + cache_policy=CachePolicy(ttl=120), +) +``` + +Then, to enable node-level caching for a graph, set the `cache` argument when compiling the graph. The example below uses `InMemoryCache` to set up a graph with in-memory cache, but `SqliteCache` is also available. + +```python +from langgraph.cache.memory import InMemoryCache + +graph = builder.compile(cache=InMemoryCache()) +``` + +## Create a sequence of steps + +!!! info "Prerequisites" + This guide assumes familiarity with the above section on [state](#define-and-update-state). + +Here we demonstrate how to construct a simple sequence of steps. We will show: + +1. How to build a sequential graph +2. Built-in short-hand for constructing similar graphs. + +To add a sequence of nodes, we use the `.add_node` and `.add_edge` methods of our [graph](../concepts/low_level.md#stategraph): + +```python +from langgraph.graph import START, StateGraph + +builder = StateGraph(State) + +# Add nodes +builder.add_node(step_1) +builder.add_node(step_2) +builder.add_node(step_3) + +# Add edges +builder.add_edge(START, "step_1") +builder.add_edge("step_1", "step_2") +builder.add_edge("step_2", "step_3") +``` + +We can also use the built-in shorthand `.add_sequence`: + +```python +builder = StateGraph(State).add_sequence([step_1, step_2, step_3]) +builder.add_edge(START, "step_1") +``` + +??? info "Why split application steps into a sequence with LangGraph?" + LangGraph makes it easy to add an underlying persistence layer to your application. + This allows state to be checkpointed in between the execution of nodes, so your LangGraph nodes govern: + + - How state updates are [checkpointed](../concepts/persistence.md) + - How interruptions are resumed in [human-in-the-loop](../concepts/human_in_the_loop.md) workflows + - How we can "rewind" and branch-off executions using LangGraph's [time travel](../concepts/time-travel.md) features + + They also determine how execution steps are [streamed](../concepts/streaming.md), and how your application is visualized + and debugged using [LangGraph Studio](../concepts/langgraph_studio.md). + +Let's demonstrate an end-to-end example. We will create a sequence of three steps: + +1. Populate a value in a key of the state +2. Update the same value +3. Populate a different value + +Let's first define our [state](../concepts/low_level.md#state). This governs the [schema of the graph](../concepts/low_level.md#schema), and can also specify how to apply updates. See [this section](#process-state-updates-with-reducers) for more detail. + +In our case, we will just keep track of two values: + +```python +from typing_extensions import TypedDict + +class State(TypedDict): + value_1: str + value_2: int +``` + +Our [nodes](../concepts/low_level.md#nodes) are just Python functions that read our graph's state and make updates to it. The first argument to this function will always be the state: + +```python +def step_1(state: State): + return {"value_1": "a"} + +def step_2(state: State): + current_value_1 = state["value_1"] + return {"value_1": f"{current_value_1} b"} + +def step_3(state: State): + return {"value_2": 10} +``` + +!!! note + Note that when issuing updates to the state, each node can just specify the value of the key it wishes to update. + + By default, this will **overwrite** the value of the corresponding key. You can also use [reducers](../concepts/low_level.md#reducers) to control how updates are processed— for example, you can append successive updates to a key instead. See [this section](#process-state-updates-with-reducers) for more detail. + +Finally, we define the graph. We use [StateGraph](../concepts/low_level.md#stategraph) to define a graph that operates on this state. + +We will then use [add_node](../concepts/low_level.md#messagesstate) and [add_edge](../concepts/low_level.md#edges) to populate our graph and define its control flow. + +```python +from langgraph.graph import START, StateGraph + +builder = StateGraph(State) + +# Add nodes +builder.add_node(step_1) +builder.add_node(step_2) +builder.add_node(step_3) + +# Add edges +builder.add_edge(START, "step_1") +builder.add_edge("step_1", "step_2") +builder.add_edge("step_2", "step_3") +``` + +!!! tip "Specifying custom names" + You can specify custom names for nodes using `.add_node`: + + ```python + builder.add_node("my_node", step_1) + ``` + +Note that: + +- `.add_edge` takes the names of nodes, which for functions defaults to `node.__name__`. +- We must specify the entry point of the graph. For this we add an edge with the [START node](../concepts/low_level.md#start-node). +- The graph halts when there are no more nodes to execute. + +We next [compile](../concepts/low_level.md#compiling-your-graph) our graph. This provides a few basic checks on the structure of the graph (e.g., identifying orphaned nodes). If we were adding persistence to our application via a [checkpointer](../concepts/persistence.md), it would also be passed in here. + +```python +graph = builder.compile() +``` + +LangGraph provides built-in utilities for visualizing your graph. Let's inspect our sequence. See [this guide](#visualize-your-graph) for detail on visualization. + +```python +from IPython.display import Image, display + +display(Image(graph.get_graph().draw_mermaid_png())) +``` + +![Sequence of steps graph](assets/graph_api_image_2.png) + +Let's proceed with a simple invocation: + +```python +graph.invoke({"value_1": "c"}) +``` +``` +{'value_1': 'a b', 'value_2': 10} +``` + +Note that: + +- We kicked off invocation by providing a value for a single state key. We must always provide a value for at least one key. +- The value we passed in was overwritten by the first node. +- The second node updated the value. +- The third node populated a different value. + +!!! tip "Built-in shorthand" + `langgraph>=0.2.46` includes a built-in short-hand `add_sequence` for adding node sequences. You can compile the same graph as follows: + + ```python + # highlight-next-line + builder = StateGraph(State).add_sequence([step_1, step_2, step_3]) + builder.add_edge(START, "step_1") + + graph = builder.compile() + + graph.invoke({"value_1": "c"}) + ``` + +## Create branches + +Parallel execution of nodes is essential to speed up overall graph operation. LangGraph offers native support for parallel execution of nodes, which can significantly enhance the performance of graph-based workflows. This parallelization is achieved through fan-out and fan-in mechanisms, utilizing both standard edges and [conditional_edges](https://langchain-ai.github.io/langgraph/reference/graphs.md#langgraph.graph.MessageGraph.add_conditional_edges). Below are some examples showing how to add create branching dataflows that work for you. + +### Run graph nodes in parallel + +In this example, we fan out from `Node A` to `B and C` and then fan in to `D`. With our state, [we specify the reducer add operation](https://langchain-ai.github.io/langgraph/concepts/low_level.md#reducers). This will combine or accumulate values for the specific key in the State, rather than simply overwriting the existing value. For lists, this means concatenating the new list with the existing list. See the above section on [state reducers](#process-state-updates-with-reducers) for more detail on updating state with reducers. + +```python +import operator +from typing import Annotated, Any +from typing_extensions import TypedDict +from langgraph.graph import StateGraph, START, END + +class State(TypedDict): + # The operator.add reducer fn makes this append-only + aggregate: Annotated[list, operator.add] + +def a(state: State): + print(f'Adding "A" to {state["aggregate"]}') + return {"aggregate": ["A"]} + +def b(state: State): + print(f'Adding "B" to {state["aggregate"]}') + return {"aggregate": ["B"]} + +def c(state: State): + print(f'Adding "C" to {state["aggregate"]}') + return {"aggregate": ["C"]} + +def d(state: State): + print(f'Adding "D" to {state["aggregate"]}') + return {"aggregate": ["D"]} + +builder = StateGraph(State) +builder.add_node(a) +builder.add_node(b) +builder.add_node(c) +builder.add_node(d) +builder.add_edge(START, "a") +builder.add_edge("a", "b") +builder.add_edge("a", "c") +builder.add_edge("b", "d") +builder.add_edge("c", "d") +builder.add_edge("d", END) +graph = builder.compile() +``` + +```python +from IPython.display import Image, display + +display(Image(graph.get_graph().draw_mermaid_png())) +``` + +![Parallel execution graph](assets/graph_api_image_3.png) + +With the reducer, you can see that the values added in each node are accumulated. + +```python +graph.invoke({"aggregate": []}, {"configurable": {"thread_id": "foo"}}) +``` +``` +Adding "A" to [] +Adding "B" to ['A'] +Adding "C" to ['A'] +Adding "D" to ['A', 'B', 'C'] +``` + +!!! note + In the above example, nodes `"b"` and `"c"` are executed concurrently in the same [superstep](../concepts/low_level.md#graphs). Because they are in the same step, node `"d"` executes after both `"b"` and `"c"` are finished. + + Importantly, updates from a parallel superstep may not be ordered consistently. If you need a consistent, predetermined ordering of updates from a parallel superstep, you should write the outputs to a separate field in the state together with a value with which to order them. + +??? note "Exception handling?" + LangGraph executes nodes within [supersteps](../concepts/low_level.md#graphs), meaning that while parallel branches are executed in parallel, the entire superstep is **transactional**. If any of these branches raises an exception, **none** of the updates are applied to the state (the entire superstep errors). + + Importantly, when using a [checkpointer](../concepts/persistence.md), results from successful nodes within a superstep are saved, and don't repeat when resumed. + + If you have error-prone (perhaps want to handle flakey API calls), LangGraph provides two ways to address this: + + 1. You can write regular python code within your node to catch and handle exceptions. + 2. You can set a **[retry_policy](../reference/types.md#langgraph.types.RetryPolicy)** to direct the graph to retry nodes that raise certain types of exceptions. Only failing branches are retried, so you needn't worry about performing redundant work. + + Together, these let you perform parallel execution and fully control exception handling. + +### Defer node execution + +Deferring node execution is useful when you want to delay the execution of a node until all other pending tasks are completed. This is particularly relevant when branches have different lengths, which is common in workflows like map-reduce flows. + +The above example showed how to fan-out and fan-in when each path was only one step. But what if one branch had more than one step? Let's add a node `"b_2"` in the `"b"` branch: + +```python +import operator +from typing import Annotated, Any +from typing_extensions import TypedDict +from langgraph.graph import StateGraph, START, END + +class State(TypedDict): + # The operator.add reducer fn makes this append-only + aggregate: Annotated[list, operator.add] + +def a(state: State): + print(f'Adding "A" to {state["aggregate"]}') + return {"aggregate": ["A"]} + +def b(state: State): + print(f'Adding "B" to {state["aggregate"]}') + return {"aggregate": ["B"]} + +def b_2(state: State): + print(f'Adding "B_2" to {state["aggregate"]}') + return {"aggregate": ["B_2"]} + +def c(state: State): + print(f'Adding "C" to {state["aggregate"]}') + return {"aggregate": ["C"]} + +def d(state: State): + print(f'Adding "D" to {state["aggregate"]}') + return {"aggregate": ["D"]} + +builder = StateGraph(State) +builder.add_node(a) +builder.add_node(b) +builder.add_node(b_2) +builder.add_node(c) +# highlight-next-line +builder.add_node(d, defer=True) +builder.add_edge(START, "a") +builder.add_edge("a", "b") +builder.add_edge("a", "c") +builder.add_edge("b", "b_2") +builder.add_edge("b_2", "d") +builder.add_edge("c", "d") +builder.add_edge("d", END) +graph = builder.compile() +``` + +```python +from IPython.display import Image, display + +display(Image(graph.get_graph().draw_mermaid_png())) +``` + +![Deferred execution graph](assets/graph_api_image_4.png) + +```python +graph.invoke({"aggregate": []}) +``` +``` +Adding "A" to [] +Adding "B" to ['A'] +Adding "C" to ['A'] +Adding "B_2" to ['A', 'B', 'C'] +Adding "D" to ['A', 'B', 'C', 'B_2'] +``` + +In the above example, nodes `"b"` and `"c"` are executed concurrently in the same superstep. We set `defer=True` on node `d` so it will not execute until all pending tasks are finished. In this case, this means that `"d"` waits to execute until the entire `"b"` branch is finished. + +### Conditional branching + +If your fan-out should vary at runtime based on the state, you can use [add_conditional_edges](https://langchain-ai.github.io/langgraph/reference/graphs.md#langgraph.graph.StateGraph.add_conditional_edges) to select one or more paths using the graph state. See example below, where node `a` generates a state update that determines the following node. + +```python +import operator +from typing import Annotated, Literal, Sequence +from typing_extensions import TypedDict +from langgraph.graph import StateGraph, START, END + +class State(TypedDict): + aggregate: Annotated[list, operator.add] + # Add a key to the state. We will set this key to determine + # how we branch. + which: str + +def a(state: State): + print(f'Adding "A" to {state["aggregate"]}') + # highlight-next-line + return {"aggregate": ["A"], "which": "c"} + +def b(state: State): + print(f'Adding "B" to {state["aggregate"]}') + return {"aggregate": ["B"]} + +def c(state: State): + print(f'Adding "C" to {state["aggregate"]}') + return {"aggregate": ["C"]} + +builder = StateGraph(State) +builder.add_node(a) +builder.add_node(b) +builder.add_node(c) +builder.add_edge(START, "a") +builder.add_edge("b", END) +builder.add_edge("c", END) + +def conditional_edge(state: State) -> Literal["b", "c"]: + # Fill in arbitrary logic here that uses the state + # to determine the next node + return state["which"] + +# highlight-next-line +builder.add_conditional_edges("a", conditional_edge) + +graph = builder.compile() +``` + +```python +from IPython.display import Image, display + +display(Image(graph.get_graph().draw_mermaid_png())) +``` + +![Conditional branching graph](assets/graph_api_image_5.png) + +```python +result = graph.invoke({"aggregate": []}) +print(result) +``` +``` +Adding "A" to [] +Adding "C" to ['A'] +{'aggregate': ['A', 'C'], 'which': 'c'} +``` + +!!! tip + Your conditional edges can route to multiple destination nodes. For example: + + ```python + def route_bc_or_cd(state: State) -> Sequence[str]: + if state["which"] == "cd": + return ["c", "d"] + return ["b", "c"] + ``` + +## Map-Reduce and the Send API + +LangGraph supports map-reduce and other advanced branching patterns using the Send API. Here is an example of how to use it: + +```python +from langgraph.graph import StateGraph, START, END, Send +from typing_extensions import TypedDict + +class OverallState(TypedDict): + topic: str + subjects: list[str] + jokes: list[str] + best_selected_joke: str + +def generate_topics(state: OverallState): + return {"subjects": ["lions", "elephants", "penguins"]} + +def generate_joke(state: OverallState): + joke_map = { + "lions": "Why don't lions like fast food? Because they can't catch it!", + "elephants": "Why don't elephants use computers? They're afraid of the mouse!", + "penguins": "Why don't penguins like talking to strangers at parties? Because they find it hard to break the ice." + } + return {"jokes": [joke_map[state["subject"]]]} + +def continue_to_jokes(state: OverallState): + return [Send("generate_joke", {"subject": s}) for s in state["subjects"]] + +def best_joke(state: OverallState): + return {"best_selected_joke": "penguins"} + +builder = StateGraph(OverallState) +builder.add_node("generate_topics", generate_topics) +builder.add_node("generate_joke", generate_joke) +builder.add_node("best_joke", best_joke) +builder.add_edge(START, "generate_topics") +builder.add_conditional_edges("generate_topics", continue_to_jokes, ["generate_joke"]) +builder.add_edge("generate_joke", "best_joke") +builder.add_edge("best_joke", END) +builder.add_edge("generate_topics", END) +graph = builder.compile() +``` + +```python +from IPython.display import Image, display + +display(Image(graph.get_graph().draw_mermaid_png())) +``` + +![Map-reduce graph with fanout](assets/graph_api_image_2.png) + +```python +# Call the graph: here we call it to generate a list of jokes +for step in graph.stream({"topic": "animals"}): + print(step) +``` +``` +{'generate_topics': {'subjects': ['lions', 'elephants', 'penguins']}} +{'generate_joke': {'jokes': ["Why don't lions like fast food? Because they can't catch it!"]}} +{'generate_joke': {'jokes': ["Why don't elephants use computers? They're afraid of the mouse!"]}} +{'generate_joke': {'jokes': ['Why don't penguins like talking to strangers at parties? Because they find it hard to break the ice.']}} +{'best_joke': {'best_selected_joke': 'penguins'}} +``` + +## Create and control loops + +When creating a graph with a loop, we require a mechanism for terminating execution. This is most commonly done by adding a [conditional edge](../concepts/low_level.md#conditional-edges) that routes to the [END](../concepts/low_level.md#end-node) node once we reach some termination condition. + +You can also set the graph recursion limit when invoking or streaming the graph. The recursion limit sets the number of [supersteps](../concepts/low_level.md#graphs) that the graph is allowed to execute before it raises an error. Read more about the concept of recursion limits [here](../concepts/low_level.md#recursion-limit). + +Let's consider a simple graph with a loop to better understand how these mechanisms work. + +!!! tip + To return the last value of your state instead of receiving a recursion limit error, see the [next section](#impose-a-recursion-limit). + +When creating a loop, you can include a conditional edge that specifies a termination condition: + +```python +builder = StateGraph(State) +builder.add_node(a) +builder.add_node(b) + +def route(state: State) -> Literal["b", END]: + if termination_condition(state): + return END + else: + return "b" + +builder.add_edge(START, "a") +builder.add_conditional_edges("a", route) +builder.add_edge("b", "a") +graph = builder.compile() +``` + +To control the recursion limit, specify `"recursion_limit"` in the config. This will raise a `GraphRecursionError`, which you can catch and handle: + +```python +from langgraph.errors import GraphRecursionError + +try: + graph.invoke(inputs, {"recursion_limit": 3}) +except GraphRecursionError: + print("Recursion Error") +``` + +Let's define a graph with a simple loop. Note that we use a conditional edge to implement a termination condition. + +```python +import operator +from typing import Annotated, Literal +from typing_extensions import TypedDict +from langgraph.graph import StateGraph, START, END + +class State(TypedDict): + # The operator.add reducer fn makes this append-only + aggregate: Annotated[list, operator.add] + +def a(state: State): + print(f'Node A sees {state["aggregate"]}') + return {"aggregate": ["A"]} + +def b(state: State): + print(f'Node B sees {state["aggregate"]}') + return {"aggregate": ["B"]} + +# Define nodes +builder = StateGraph(State) +builder.add_node(a) +builder.add_node(b) + +# Define edges +def route(state: State) -> Literal["b", END]: + if len(state["aggregate"]) < 7: + return "b" + else: + return END + +builder.add_edge(START, "a") +builder.add_conditional_edges("a", route) +builder.add_edge("b", "a") +graph = builder.compile() +``` + +```python +from IPython.display import Image, display + +display(Image(graph.get_graph().draw_mermaid_png())) +``` + +![Simple loop graph](assets/graph_api_image_3.png) + +This architecture is similar to a [ReAct agent](../agents/overview.md) in which node `"a"` is a tool-calling model, and node `"b"` represents the tools. + +In our `route` conditional edge, we specify that we should end after the `"aggregate"` list in the state passes a threshold length. + +Invoking the graph, we see that we alternate between nodes `"a"` and `"b"` before terminating once we reach the termination condition. + +```python +graph.invoke({"aggregate": []}) +``` +``` +Node A sees [] +Node B sees ['A'] +Node A sees ['A', 'B'] +Node B sees ['A', 'B', 'A'] +Node A sees ['A', 'B', 'A', 'B'] +Node B sees ['A', 'B', 'A', 'B', 'A'] +Node A sees ['A', 'B', 'A', 'B', 'A', 'B'] +``` + +### Impose a recursion limit + +In some applications, we may not have a guarantee that we will reach a given termination condition. In these cases, we can set the graph's [recursion limit](../concepts/low_level.md#recursion-limit). This will raise a `GraphRecursionError` after a given number of [supersteps](../concepts/low_level.md#graphs). We can then catch and handle this exception: + +```python +from langgraph.errors import GraphRecursionError + +try: + graph.invoke({"aggregate": []}, {"recursion_limit": 4}) +except GraphRecursionError: + print("Recursion Error") +``` +``` +Node A sees [] +Node B sees ['A'] +Node C sees ['A', 'B'] +Node D sees ['A', 'B'] +Node A sees ['A', 'B', 'C', 'D'] +Recursion Error +``` + +??? example "Extended example: return state on hitting recursion limit" + + Instead of raising `GraphRecursionError`, we can introduce a new key to the state that keeps track of the number of steps remaining until reaching the recursion limit. We can then use this key to determine if we should end the run. + + LangGraph implements a special `RemainingSteps` annotation. Under the hood, it creates a `ManagedValue` channel -- a state channel that will exist for the duration of our graph run and no longer. + + ```python + import operator + from typing import Annotated, Literal + from typing_extensions import TypedDict + from langgraph.graph import StateGraph, START, END + from langgraph.managed.is_last_step import RemainingSteps + + class State(TypedDict): + aggregate: Annotated[list, operator.add] + remaining_steps: RemainingSteps + + def a(state: State): + print(f'Node A sees {state["aggregate"]}') + return {"aggregate": ["A"]} + + def b(state: State): + print(f'Node B sees {state["aggregate"]}') + return {"aggregate": ["B"]} + + # Define nodes + builder = StateGraph(State) + builder.add_node(a) + builder.add_node(b) + + # Define edges + def route(state: State) -> Literal["b", END]: + if state["remaining_steps"] <= 2: + return END + else: + return "b" + + builder.add_edge(START, "a") + builder.add_conditional_edges("a", route) + builder.add_edge("b", "a") + graph = builder.compile() + + # Test it out + result = graph.invoke({"aggregate": []}, {"recursion_limit": 4}) + print(result) + ``` + ``` + Node A sees [] + Node B sees ['A'] + Node A sees ['A', 'B'] + {'aggregate': ['A', 'B', 'A']} + ``` + +??? example "Extended example: loops with branches" + + To better understand how the recursion limit works, let's consider a more complex example. Below we implement a loop, but one step fans out into two nodes: + + ```python + import operator + from typing import Annotated, Literal + from typing_extensions import TypedDict + from langgraph.graph import StateGraph, START, END + + class State(TypedDict): + aggregate: Annotated[list, operator.add] + + def a(state: State): + print(f'Node A sees {state["aggregate"]}') + return {"aggregate": ["A"]} + + def b(state: State): + print(f'Node B sees {state["aggregate"]}') + return {"aggregate": ["B"]} + + def c(state: State): + print(f'Node C sees {state["aggregate"]}') + return {"aggregate": ["C"]} + + def d(state: State): + print(f'Node D sees {state["aggregate"]}') + return {"aggregate": ["D"]} + + # Define nodes + builder = StateGraph(State) + builder.add_node(a) + builder.add_node(b) + builder.add_node(c) + builder.add_node(d) + + # Define edges + def route(state: State) -> Literal["b", END]: + if len(state["aggregate"]) < 7: + return "b" + else: + return END + + builder.add_edge(START, "a") + builder.add_conditional_edges("a", route) + builder.add_edge("b", "c") + builder.add_edge("b", "d") + builder.add_edge(["c", "d"], "a") + graph = builder.compile() + ``` + + ```python + from IPython.display import Image, display + + display(Image(graph.get_graph().draw_mermaid_png())) + ``` + + ![Complex loop graph with branches](assets/graph_api_image_4.png) + + This graph looks complex, but can be conceptualized as loop of [supersteps](../concepts/low_level.md#graphs): + + 1. Node A + 2. Node B + 3. Nodes C and D + 4. Node A + 5. ... + + We have a loop of four supersteps, where nodes C and D are executed concurrently. + + Invoking the graph as before, we see that we complete two full "laps" before hitting the termination condition: + + ```python + result = graph.invoke({"aggregate": []}) + ``` + ``` + Node A sees [] + Node B sees ['A'] + Node D sees ['A', 'B'] + Node C sees ['A', 'B'] + Node A sees ['A', 'B', 'C', 'D'] + Node B sees ['A', 'B', 'C', 'D', 'A'] + Node D sees ['A', 'B', 'C', 'D', 'A', 'B'] + Node C sees ['A', 'B', 'C', 'D', 'A', 'B'] + Node A sees ['A', 'B', 'C', 'D', 'A', 'B', 'C', 'D'] + ``` + + However, if we set the recursion limit to four, we only complete one lap because each lap is four supersteps: + + ```python + from langgraph.errors import GraphRecursionError + + try: + result = graph.invoke({"aggregate": []}, {"recursion_limit": 4}) + except GraphRecursionError: + print("Recursion Error") + ``` + ``` + Node A sees [] + Node B sees ['A'] + Node C sees ['A', 'B'] + Node D sees ['A', 'B'] + Node A sees ['A', 'B', 'C', 'D'] + Recursion Error + ``` + +## Async + +Using the [async](https://docs.python.org/3/library/asyncio.html) programming paradigm can produce significant performance improvements when running [IO-bound](https://en.wikipedia.org/wiki/I/O_bound) code concurrently (e.g., making concurrent API requests to a chat model provider). + +To convert a `sync` implementation of the graph to an `async` implementation, you will need to: + +1. Update `nodes` use `async def` instead of `def`. +2. Update the code inside to use `await` appropriately. +3. Invoke the graph with `.ainvoke` or `.astream` as desired. + +Because many LangChain objects implement the [Runnable Protocol](https://python.langchain.com/docs/expression_language/interface/) which has `async` variants of all the `sync` methods it's typically fairly quick to upgrade a `sync` graph to an `async` graph. + +See example below. To demonstrate async invocations of underlying LLMs, we will include a chat model: + +{!snippets/chat_model_tabs.md!} + +```python +from langchain.chat_models import init_chat_model +from langgraph.graph import MessagesState, StateGraph + +# highlight-next-line +async def node(state: MessagesState): # (1)! + # highlight-next-line + new_message = await llm.ainvoke(state["messages"]) # (2)! + return {"messages": [new_message]} + +builder = StateGraph(MessagesState).add_node(node).set_entry_point("node") +graph = builder.compile() + +input_message = {"role": "user", "content": "Hello"} +# highlight-next-line +result = await graph.ainvoke({"messages": [input_message]}) # (3)! +``` + +1. Declare nodes to be async functions. +2. Use async invocations when available within the node. +3. Use async invocations on the graph object itself. + +!!! tip "Async streaming" + See the [streaming guide](./streaming.md) for examples of streaming with async. + +## Combine control flow and state updates with `Command` + +It can be useful to combine control flow (edges) and state updates (nodes). For example, you might want to BOTH perform state updates AND decide which node to go to next in the SAME node. LangGraph provides a way to do so by returning a [Command](../reference/types.md#langgraph.types.Command) object from node functions: + +```python +def my_node(state: State) -> Command[Literal["my_other_node"]]: + return Command( + # state update + update={"foo": "bar"}, + # control flow + goto="my_other_node" + ) +``` + +We show an end-to-end example below. Let's create a simple graph with 3 nodes: A, B and C. We will first execute node A, and then decide whether to go to Node B or Node C next based on the output of node A. + +```python +import random +from typing_extensions import TypedDict, Literal +from langgraph.graph import StateGraph, START +from langgraph.types import Command + +# Define graph state +class State(TypedDict): + foo: str + +# Define the nodes + +def node_a(state: State) -> Command[Literal["node_b", "node_c"]]: + print("Called A") + value = random.choice(["a", "b"]) + # this is a replacement for a conditional edge function + if value == "a": + goto = "node_b" + else: + goto = "node_c" + + # note how Command allows you to BOTH update the graph state AND route to the next node + return Command( + # this is the state update + update={"foo": value}, + # this is a replacement for an edge + goto=goto, + ) + +def node_b(state: State): + print("Called B") + return {"foo": state["foo"] + "b"} + +def node_c(state: State): + print("Called C") + return {"foo": state["foo"] + "c"} +``` + +We can now create the `StateGraph` with the above nodes. Notice that the graph doesn't have [conditional edges](../concepts/low_level.md#conditional-edges) for routing! This is because control flow is defined with `Command` inside `node_a`. + +```python +builder = StateGraph(State) +builder.add_edge(START, "node_a") +builder.add_node(node_a) +builder.add_node(node_b) +builder.add_node(node_c) +# NOTE: there are no edges between nodes A, B and C! + +graph = builder.compile() +``` + +!!! important + You might have noticed that we used `Command` as a return type annotation, e.g. `Command[Literal["node_b", "node_c"]]`. This is necessary for the graph rendering and tells LangGraph that `node_a` can navigate to `node_b` and `node_c`. + +```python +from IPython.display import display, Image + +display(Image(graph.get_graph().draw_mermaid_png())) +``` + +![Command-based graph navigation](assets/graph_api_image_6.png) + +If we run the graph multiple times, we'd see it take different paths (A -> B or A -> C) based on the random choice in node A. + +```python +graph.invoke({"foo": ""}) +``` +``` +Called A +Called C +``` + +### Navigate to a node in a parent graph + +If you are using [subgraphs](../concepts/subgraphs.md), you might want to navigate from a node within a subgraph to a different subgraph (i.e. a different node in the parent graph). To do so, you can specify `graph=Command.PARENT` in `Command`: + +```python +def my_node(state: State) -> Command[Literal["my_other_node"]]: + return Command( + update={"foo": "bar"}, + goto="other_subgraph", # where `other_subgraph` is a node in the parent graph + graph=Command.PARENT + ) +``` + +Let's demonstrate this using the above example. We'll do so by changing `node_a` in the above example into a single-node graph that we'll add as a subgraph to our parent graph. + +!!! important "State updates with `Command.PARENT`" + When you send updates from a subgraph node to a parent graph node for a key that's shared by both parent and subgraph [state schemas](../concepts/low_level.md#schema), you **must** define a [reducer](../concepts/low_level.md#reducers) for the key you're updating in the parent graph state. See the example below. + +```python +import operator +from typing_extensions import Annotated + +class State(TypedDict): + # NOTE: we define a reducer here + # highlight-next-line + foo: Annotated[str, operator.add] + +def node_a(state: State): + print("Called A") + value = random.choice(["a", "b"]) + # this is a replacement for a conditional edge function + if value == "a": + goto = "node_b" + else: + goto = "node_c" + + # note how Command allows you to BOTH update the graph state AND route to the next node + return Command( + update={"foo": value}, + goto=goto, + # this tells LangGraph to navigate to node_b or node_c in the parent graph + # NOTE: this will navigate to the closest parent graph relative to the subgraph + # highlight-next-line + graph=Command.PARENT, + ) + +subgraph = StateGraph(State).add_node(node_a).add_edge(START, "node_a").compile() + +def node_b(state: State): + print("Called B") + # NOTE: since we've defined a reducer, we don't need to manually append + # new characters to existing 'foo' value. instead, reducer will append these + # automatically (via operator.add) + # highlight-next-line + return {"foo": "b"} + +def node_c(state: State): + print("Called C") + # highlight-next-line + return {"foo": "c"} + +builder = StateGraph(State) +builder.add_edge(START, "subgraph") +builder.add_node("subgraph", subgraph) +builder.add_node(node_b) +builder.add_node(node_c) + +graph = builder.compile() +``` + +```python +graph.invoke({"foo": ""}) +``` +``` +Called A +Called C +``` + +### Use inside tools + +A common use case is updating graph state from inside a tool. For example, in a customer support application you might want to look up customer information based on their account number or ID in the beginning of the conversation. To update the graph state from the tool, you can return `Command(update={"my_custom_key": "foo", "messages": [...]})` from the tool: + +```python +@tool +def lookup_user_info(tool_call_id: Annotated[str, InjectedToolCallId], config: RunnableConfig): + """Use this to look up user information to better assist them with their questions.""" + user_info = get_user_info(config.get("configurable", {}).get("user_id")) + return Command( + update={ + # update the state keys + "user_info": user_info, + # update the message history + "messages": [ToolMessage("Successfully looked up user information", tool_call_id=tool_call_id)] + } + ) +``` + +!!! important + You MUST include `messages` (or any state key used for the message history) in `Command.update` when returning `Command` from a tool and the list of messages in `messages` MUST contain a `ToolMessage`. This is necessary for the resulting message history to be valid (LLM providers require AI messages with tool calls to be followed by the tool result messages). + +If you are using tools that update state via `Command`, we recommend using prebuilt [`ToolNode`](../reference/agents.md#langgraph.prebuilt.tool_node.ToolNode) which automatically handles tools returning `Command` objects and propagates them to the graph state. If you're writing a custom node that calls tools, you would need to manually propagate `Command` objects returned by the tools as the update from the node. + +## Visualize your graph + +Here we demonstrate how to visualize the graphs you create. + +You can visualize any arbitrary [Graph](https://langchain-ai.github.io/langgraph/reference/graphs/), including [StateGraph](https://langchain-ai.github.io/langgraph/reference/graphs.md#langgraph.graph.state.StateGraph). Let's have some fun by drawing fractals :). + +```python +import random +from typing import Annotated, Literal +from typing_extensions import TypedDict +from langgraph.graph import StateGraph, START, END +from langgraph.graph.message import add_messages + +class State(TypedDict): + messages: Annotated[list, add_messages] + +class MyNode: + def __init__(self, name: str): + self.name = name + def __call__(self, state: State): + return {"messages": [("assistant", f"Called node {self.name}")]} + +def route(state) -> Literal["entry_node", "__end__"]: + if len(state["messages"]) > 10: + return "__end__" + return "entry_node" + +def add_fractal_nodes(builder, current_node, level, max_level): + if level > max_level: + return + # Number of nodes to create at this level + num_nodes = random.randint(1, 3) # Adjust randomness as needed + for i in range(num_nodes): + nm = ["A", "B", "C"][i] + node_name = f"node_{current_node}_{nm}" + builder.add_node(node_name, MyNode(node_name)) + builder.add_edge(current_node, node_name) + # Recursively add more nodes + r = random.random() + if r > 0.2 and level + 1 < max_level: + add_fractal_nodes(builder, node_name, level + 1, max_level) + elif r > 0.05: + builder.add_conditional_edges(node_name, route, node_name) + else: + # End + builder.add_edge(node_name, "__end__") + +def build_fractal_graph(max_level: int): + builder = StateGraph(State) + entry_point = "entry_node" + builder.add_node(entry_point, MyNode(entry_point)) + builder.add_edge(START, entry_point) + add_fractal_nodes(builder, entry_point, 1, max_level) + # Optional: set a finish point if required + builder.add_edge(entry_point, END) # or any specific node + return builder.compile() + +app = build_fractal_graph(3) +``` + +### Mermaid + +We can also convert a graph class into Mermaid syntax. + +```python +print(app.get_graph().draw_mermaid()) +``` +``` +%%{init: {'flowchart': {'curve': 'linear'}}}%% +graph TD; + __start__([

__start__

]):::first + entry_node(entry_node) + node_entry_node_A(node_entry_node_A) + node_entry_node_B(node_entry_node_B) + node_node_entry_node_B_A(node_node_entry_node_B_A) + node_node_entry_node_B_B(node_node_entry_node_B_B) + node_node_entry_node_B_C(node_node_entry_node_B_C) + __end__([

__end__

]):::last + __start__ --> entry_node; + entry_node --> __end__; + entry_node --> node_entry_node_A; + entry_node --> node_entry_node_B; + node_entry_node_B --> node_node_entry_node_B_A; + node_entry_node_B --> node_node_entry_node_B_B; + node_entry_node_B --> node_node_entry_node_B_C; + node_entry_node_A -.-> entry_node; + node_entry_node_A -.-> __end__; + node_node_entry_node_B_A -.-> entry_node; + node_node_entry_node_B_A -.-> __end__; + node_node_entry_node_B_B -.-> entry_node; + node_node_entry_node_B_B -.-> __end__; + node_node_entry_node_B_C -.-> entry_node; + node_node_entry_node_B_C -.-> __end__; + classDef default fill:#f2f0ff,line-height:1.2 + classDef first fill-opacity:0 + classDef last fill:#bfb6fc +``` + +### PNG + +If preferred, we could render the Graph into a `.png`. Here we could use three options: + +- Using Mermaid.ink API (does not require additional packages) +- Using Mermaid + Pyppeteer (requires `pip install pyppeteer`) +- Using graphviz (which requires `pip install graphviz`) + +**Using Mermaid.Ink** + +By default, `draw_mermaid_png()` uses Mermaid.Ink's API to generate the diagram. + +```python +from IPython.display import Image, display +from langchain_core.runnables.graph import CurveStyle, MermaidDrawMethod, NodeStyles + +display(Image(app.get_graph().draw_mermaid_png())) +``` + +![Fractal graph visualization](assets/graph_api_image_5.png) + +**Using Mermaid + Pyppeteer** + +```python +import nest_asyncio + +nest_asyncio.apply() # Required for Jupyter Notebook to run async functions + +display( + Image( + app.get_graph().draw_mermaid_png( + curve_style=CurveStyle.LINEAR, + node_colors=NodeStyles(first="#ffdfba", last="#baffc9", default="#fad7de"), + wrap_label_n_words=9, + output_file_path=None, + draw_method=MermaidDrawMethod.PYPPETEER, + background_color="white", + padding=10, + ) + ) +) +``` + +**Using Graphviz** + +```python +try: + display(Image(app.get_graph().draw_png())) +except ImportError: + print( + "You likely need to install dependencies for pygraphviz, see more here https://github.com/pygraphviz/pygraphviz/blob/main/INSTALL.txt" + ) +``` \ No newline at end of file diff --git a/docs/docs/how-tos/multi_agent.md b/docs/docs/how-tos/multi_agent.md new file mode 100644 index 000000000..5aead8b95 --- /dev/null +++ b/docs/docs/how-tos/multi_agent.md @@ -0,0 +1,580 @@ +# Build multi-agent systems + +A single agent might struggle if it needs to specialize in multiple domains or manage many tools. To tackle this, you can break your agent into smaller, independent agents and composing them into a [multi-agent system](../concepts/multi_agent.md). + +In multi-agent systems, agents need to communicate between each other. They do so via [handoffs](#handoffs) — a primitive that describes which agent to hand control to and the payload to send to that agent. + +This guide covers the following: + +* implementing [handoffs](#handoffs) between agents +* using handoffs and the prebuilt [agent](../agents/agents.md) to [build a custom multi-agent system](#build-a-multi-agent-system) + +To get started with building multi-agent systems, check out LangGraph [prebuilt implementations](#prebuilt-implementations) of two of the most popular multi-agent architectures — [supervisor](../agents/multi-agent.md#supervisor) and [swarm](../agents/multi-agent.md#swarm). + +## Handoffs + +To set up communication between the agents in a multi-agent system you can use [**handoffs**](../concepts/multi_agent.md#handoffs) — a pattern where one agent *hands off* control to another. Handoffs allow you to specify: + +- **destination**: target agent to navigate to (e.g., name of the LangGraph node to go to) +- **payload**: information to pass to that agent (e.g., state update) + +### Create handoffs + +To implement handoffs, you can return `Command` objects from your agent nodes or tools: + +```python +from typing import Annotated +from langchain_core.tools import tool, InjectedToolCallId +from langgraph.prebuilt import create_react_agent, InjectedState +from langgraph.graph import StateGraph, START, MessagesState +from langgraph.types import Command + +def create_handoff_tool(*, agent_name: str, description: str | None = None): + name = f"transfer_to_{agent_name}" + description = description or f"Transfer to {agent_name}" + + @tool(name, description=description) + def handoff_tool( + # highlight-next-line + state: Annotated[MessagesState, InjectedState], # (1)! + # highlight-next-line + tool_call_id: Annotated[str, InjectedToolCallId], + ) -> Command: + tool_message = { + "role": "tool", + "content": f"Successfully transferred to {agent_name}", + "name": name, + "tool_call_id": tool_call_id, + } + return Command( # (2)! + # highlight-next-line + goto=agent_name, # (3)! + # highlight-next-line + update={"messages": state["messages"] + [tool_message]}, # (4)! + # highlight-next-line + graph=Command.PARENT, # (5)! + ) + return handoff_tool +``` + +1. Access the [state](../concepts/low_level.md#state) of the agent that is calling the handoff tool using the [InjectedState][langgraph.prebuilt.InjectedState] annotation. +2. The `Command` primitive allows specifying a state update and a node transition as a single operation, making it useful for implementing handoffs. +3. Name of the agent or node to hand off to. +4. Take the agent's messages and **add** them to the parent's **state** as part of the handoff. The next agent will see the parent state. +5. Indicate to LangGraph that we need to navigate to agent node in a **parent** multi-agent graph. + +!!! tip + + If you want to use tools that return `Command`, you can either use prebuilt [`create_react_agent`][langgraph.prebuilt.chat_agent_executor.create_react_agent] / [`ToolNode`][langgraph.prebuilt.tool_node.ToolNode] components, or implement your own tool-executing node that collects `Command` objects returned by the tools and returns a list of them, e.g.: + + ```python + def call_tools(state): + ... + commands = [tools_by_name[tool_call["name"]].invoke(tool_call) for tool_call in tool_calls] + return commands + ``` + +!!! Important + + This handoff implementation assumes that: + + - each agent receives overall message history (across all agents) in the multi-agent system as its input. If you want more control over agent inputs, see [this section](#control-agent-inputs) + - each agent outputs its internal messages history to the overall message history of the multi-agent system. If you want more control over **how agent outputs are added**, wrap the agent in a separate node function: + + ```python + def call_hotel_assistant(state): + # return agent's final response, + # excluding inner monologue + response = hotel_assistant.invoke(state) + # highlight-next-line + return {"messages": response["messages"][-1]} + ``` + +### Control agent inputs + +You can use the [`Send()`][langgraph.types.Send] primitive to directly send data to the worker agents during the handoff. For example, you can request that the calling agent populate a task description for the next agent: + +```python + +from typing import Annotated +from langchain_core.tools import tool, InjectedToolCallId +from langgraph.prebuilt import InjectedState +from langgraph.graph import StateGraph, START, MessagesState +# highlight-next-line +from langgraph.types import Command, Send + +def create_task_description_handoff_tool( + *, agent_name: str, description: str | None = None +): + name = f"transfer_to_{agent_name}" + description = description or f"Ask {agent_name} for help." + + @tool(name, description=description) + def handoff_tool( + # this is populated by the calling agent + task_description: Annotated[ + str, + "Description of what the next agent should do, including all of the relevant context.", + ], + # these parameters are ignored by the LLM + state: Annotated[MessagesState, InjectedState], + ) -> Command: + task_description_message = {"role": "user", "content": task_description} + agent_input = {**state, "messages": [task_description_message]} + return Command( + # highlight-next-line + goto=[Send(agent_name, agent_input)], + graph=Command.PARENT, + ) + + return handoff_tool +``` + +See the multi-agent [supervisor](../tutorials/multi_agent/agent_supervisor.ipynb#4-create-delegation-tasks) example for a full example of using [`Send()`][langgraph.types.Send] in handoffs. + +## Build a multi-agent system + +You can use handoffs in any agents built with LangGraph. We recommend using the prebuilt [agent](../agents/overview.md) or [`ToolNode`](./tool-calling.md#toolnode), as they natively support handoffs tools returning `Command`. Below is an example of how you can implement a multi-agent system for booking travel using handoffs: + +```python +from langgraph.prebuilt import create_react_agent +from langgraph.graph import StateGraph, START, MessagesState + +def create_handoff_tool(*, agent_name: str, description: str | None = None): + # same implementation as above + ... + return Command(...) + +# Handoffs +transfer_to_hotel_assistant = create_handoff_tool(agent_name="hotel_assistant") +transfer_to_flight_assistant = create_handoff_tool(agent_name="flight_assistant") + +# Define agents +flight_assistant = create_react_agent( + model="anthropic:claude-3-5-sonnet-latest", + # highlight-next-line + tools=[..., transfer_to_hotel_assistant], + # highlight-next-line + name="flight_assistant" +) +hotel_assistant = create_react_agent( + model="anthropic:claude-3-5-sonnet-latest", + # highlight-next-line + tools=[..., transfer_to_flight_assistant], + # highlight-next-line + name="hotel_assistant" +) + +# Define multi-agent graph +multi_agent_graph = ( + StateGraph(MessagesState) + # highlight-next-line + .add_node(flight_assistant) + # highlight-next-line + .add_node(hotel_assistant) + .add_edge(START, "flight_assistant") + .compile() +) +``` + +??? example "Full example: Multi-agent system for booking travel" + + ```python + from typing import Annotated + from langchain_core.messages import convert_to_messages + from langchain_core.tools import tool, InjectedToolCallId + from langgraph.prebuilt import create_react_agent, InjectedState + from langgraph.graph import StateGraph, START, MessagesState + from langgraph.types import Command + + # We'll use `pretty_print_messages` helper to render the streamed agent outputs nicely + + def pretty_print_message(message, indent=False): + pretty_message = message.pretty_repr(html=True) + if not indent: + print(pretty_message) + return + + indented = "\n".join("\t" + c for c in pretty_message.split("\n")) + print(indented) + + + def pretty_print_messages(update, last_message=False): + is_subgraph = False + if isinstance(update, tuple): + ns, update = update + # skip parent graph updates in the printouts + if len(ns) == 0: + return + + graph_id = ns[-1].split(":")[0] + print(f"Update from subgraph {graph_id}:") + print("\n") + is_subgraph = True + + for node_name, node_update in update.items(): + update_label = f"Update from node {node_name}:" + if is_subgraph: + update_label = "\t" + update_label + + print(update_label) + print("\n") + + messages = convert_to_messages(node_update["messages"]) + if last_message: + messages = messages[-1:] + + for m in messages: + pretty_print_message(m, indent=is_subgraph) + print("\n") + + + def create_handoff_tool(*, agent_name: str, description: str | None = None): + name = f"transfer_to_{agent_name}" + description = description or f"Transfer to {agent_name}" + + @tool(name, description=description) + def handoff_tool( + # highlight-next-line + state: Annotated[MessagesState, InjectedState], # (1)! + # highlight-next-line + tool_call_id: Annotated[str, InjectedToolCallId], + ) -> Command: + tool_message = { + "role": "tool", + "content": f"Successfully transferred to {agent_name}", + "name": name, + "tool_call_id": tool_call_id, + } + return Command( # (2)! + # highlight-next-line + goto=agent_name, # (3)! + # highlight-next-line + update={"messages": state["messages"] + [tool_message]}, # (4)! + # highlight-next-line + graph=Command.PARENT, # (5)! + ) + return handoff_tool + + # Handoffs + transfer_to_hotel_assistant = create_handoff_tool( + agent_name="hotel_assistant", + description="Transfer user to the hotel-booking assistant.", + ) + transfer_to_flight_assistant = create_handoff_tool( + agent_name="flight_assistant", + description="Transfer user to the flight-booking assistant.", + ) + + # Simple agent tools + def book_hotel(hotel_name: str): + """Book a hotel""" + return f"Successfully booked a stay at {hotel_name}." + + def book_flight(from_airport: str, to_airport: str): + """Book a flight""" + return f"Successfully booked a flight from {from_airport} to {to_airport}." + + # Define agents + flight_assistant = create_react_agent( + model="anthropic:claude-3-5-sonnet-latest", + # highlight-next-line + tools=[book_flight, transfer_to_hotel_assistant], + prompt="You are a flight booking assistant", + # highlight-next-line + name="flight_assistant" + ) + hotel_assistant = create_react_agent( + model="anthropic:claude-3-5-sonnet-latest", + # highlight-next-line + tools=[book_hotel, transfer_to_flight_assistant], + prompt="You are a hotel booking assistant", + # highlight-next-line + name="hotel_assistant" + ) + + # Define multi-agent graph + multi_agent_graph = ( + StateGraph(MessagesState) + .add_node(flight_assistant) + .add_node(hotel_assistant) + .add_edge(START, "flight_assistant") + .compile() + ) + + # Run the multi-agent graph + for chunk in multi_agent_graph.stream( + { + "messages": [ + { + "role": "user", + "content": "book a flight from BOS to JFK and a stay at McKittrick Hotel" + } + ] + }, + # highlight-next-line + subgraphs=True + ): + pretty_print_messages(chunk) + ``` + + 1. Access agent's state + 2. The `Command` primitive allows specifying a state update and a node transition as a single operation, making it useful for implementing handoffs. + 3. Name of the agent or node to hand off to. + 4. Take the agent's messages and **add** them to the parent's **state** as part of the handoff. The next agent will see the parent state. + 5. Indicate to LangGraph that we need to navigate to agent node in a **parent** multi-agent graph. + +## Multi-turn conversation + +Users might want to engage in a *multi-turn conversation* with one or more agents. To build a system that can handle this, you can create a node that uses an [`interrupt`][langgraph.types.interrupt] to collect user input and routes back to the **active** agent. + +The agents can then be implemented as nodes in a graph that executes agent steps and determines the next action: + +1. **Wait for user input** to continue the conversation, or +2. **Route to another agent** (or back to itself, such as in a loop) via a [handoff](#handoffs) + +```python +def human(state) -> Command[Literal["agent", "another_agent"]]: + """A node for collecting user input.""" + user_input = interrupt(value="Ready for user input.") + + # Determine the active agent. + active_agent = ... + + ... + return Command( + update={ + "messages": [{ + "role": "human", + "content": user_input, + }] + }, + goto=active_agent + ) + +def agent(state) -> Command[Literal["agent", "another_agent", "human"]]: + # The condition for routing/halting can be anything, e.g. LLM tool call / structured output, etc. + goto = get_next_agent(...) # 'agent' / 'another_agent' + if goto: + return Command(goto=goto, update={"my_state_key": "my_state_value"}) + else: + return Command(goto="human") # Go to human node +``` + +??? example "Full example: multi-agent system for travel recommendations" + + In this example, we will build a team of travel assistant agents that can communicate with each other via handoffs. + + We will create 2 agents: + + * travel_advisor: can help with travel destination recommendations. Can ask hotel_advisor for help. + * hotel_advisor: can help with hotel recommendations. Can ask travel_advisor for help. + + ```python + from langchain_anthropic import ChatAnthropic + from langgraph.graph import MessagesState, StateGraph, START + from langgraph.prebuilt import create_react_agent, InjectedState + from langgraph.types import Command, interrupt + from langgraph.checkpoint.memory import MemorySaver + + + model = ChatAnthropic(model="claude-3-5-sonnet-latest") + + class MultiAgentState(MessagesState): + last_active_agent: str + + + # Define travel advisor tools and ReAct agent + travel_advisor_tools = [ + get_travel_recommendations, + make_handoff_tool(agent_name="hotel_advisor"), + ] + travel_advisor = create_react_agent( + model, + travel_advisor_tools, + prompt=( + "You are a general travel expert that can recommend travel destinations (e.g. countries, cities, etc). " + "If you need hotel recommendations, ask 'hotel_advisor' for help. " + "You MUST include human-readable response before transferring to another agent." + ), + ) + + + def call_travel_advisor( + state: MultiAgentState, + ) -> Command[Literal["hotel_advisor", "human"]]: + # You can also add additional logic like changing the input to the agent / output from the agent, etc. + # NOTE: we're invoking the ReAct agent with the full history of messages in the state + response = travel_advisor.invoke(state) + update = {**response, "last_active_agent": "travel_advisor"} + return Command(update=update, goto="human") + + + # Define hotel advisor tools and ReAct agent + hotel_advisor_tools = [ + get_hotel_recommendations, + make_handoff_tool(agent_name="travel_advisor"), + ] + hotel_advisor = create_react_agent( + model, + hotel_advisor_tools, + prompt=( + "You are a hotel expert that can provide hotel recommendations for a given destination. " + "If you need help picking travel destinations, ask 'travel_advisor' for help." + "You MUST include human-readable response before transferring to another agent." + ), + ) + + + def call_hotel_advisor( + state: MultiAgentState, + ) -> Command[Literal["travel_advisor", "human"]]: + response = hotel_advisor.invoke(state) + update = {**response, "last_active_agent": "hotel_advisor"} + return Command(update=update, goto="human") + + + def human_node( + state: MultiAgentState, config + ) -> Command[Literal["hotel_advisor", "travel_advisor", "human"]]: + """A node for collecting user input.""" + + user_input = interrupt(value="Ready for user input.") + active_agent = state["last_active_agent"] + + return Command( + update={ + "messages": [ + { + "role": "human", + "content": user_input, + } + ] + }, + goto=active_agent, + ) + + + builder = StateGraph(MultiAgentState) + builder.add_node("travel_advisor", call_travel_advisor) + builder.add_node("hotel_advisor", call_hotel_advisor) + + # This adds a node to collect human input, which will route + # back to the active agent. + builder.add_node("human", human_node) + + # We'll always start with a general travel advisor. + builder.add_edge(START, "travel_advisor") + + + checkpointer = MemorySaver() + graph = builder.compile(checkpointer=checkpointer) + ``` + + Let's test a multi turn conversation with this application. + + ```python + import uuid + + thread_config = {"configurable": {"thread_id": str(uuid.uuid4())}} + + inputs = [ + # 1st round of conversation, + { + "messages": [ + {"role": "user", "content": "i wanna go somewhere warm in the caribbean"} + ] + }, + # Since we're using `interrupt`, we'll need to resume using the Command primitive. + # 2nd round of conversation, + Command( + resume="could you recommend a nice hotel in one of the areas and tell me which area it is." + ), + # 3rd round of conversation, + Command( + resume="i like the first one. could you recommend something to do near the hotel?" + ), + ] + + for idx, user_input in enumerate(inputs): + print() + print(f"--- Conversation Turn {idx + 1} ---") + print() + print(f"User: {user_input}") + print() + for update in graph.stream( + user_input, + config=thread_config, + stream_mode="updates", + ): + for node_id, value in update.items(): + if isinstance(value, dict) and value.get("messages", []): + last_message = value["messages"][-1] + if isinstance(last_message, dict) or last_message.type != "ai": + continue + print(f"{node_id}: {last_message.content}") + ``` + + ``` + --- Conversation Turn 1 --- + + User: {'messages': [{'role': 'user', 'content': 'i wanna go somewhere warm in the caribbean'}]} + + travel_advisor: Based on the recommendations, Aruba would be an excellent choice for your Caribbean getaway! Aruba is known as "One Happy Island" and offers: + - Year-round warm weather with consistent temperatures around 82°F (28°C) + - Beautiful white sand beaches like Eagle Beach and Palm Beach + - Clear turquoise waters perfect for swimming and snorkeling + - Minimal rainfall and location outside the hurricane belt + - A blend of Caribbean and Dutch culture + - Great dining options and nightlife + - Various water sports and activities + + Would you like me to get some specific hotel recommendations in Aruba for your stay? I can transfer you to our hotel advisor who can help with accommodations. + + --- Conversation Turn 2 --- + + User: Command(resume='could you recommend a nice hotel in one of the areas and tell me which area it is.') + + hotel_advisor: Based on the recommendations, I can suggest two excellent options: + + 1. The Ritz-Carlton, Aruba - Located in Palm Beach + - This luxury resort is situated in the vibrant Palm Beach area + - Known for its exceptional service and amenities + - Perfect if you want to be close to dining, shopping, and entertainment + - Features multiple restaurants, a casino, and a world-class spa + - Located on a pristine stretch of Palm Beach + + 2. Bucuti & Tara Beach Resort - Located in Eagle Beach + - An adults-only boutique resort on Eagle Beach + - Known for being more intimate and peaceful + - Award-winning for its sustainability practices + - Perfect for a romantic getaway or peaceful vacation + - Located on one of the most beautiful beaches in the Caribbean + + Would you like more specific information about either of these properties or their locations? + + --- Conversation Turn 3 --- + + User: Command(resume='i like the first one. could you recommend something to do near the hotel?') + + travel_advisor: Near the Ritz-Carlton in Palm Beach, here are some highly recommended activities: + + 1. Visit the Palm Beach Plaza Mall - Just a short walk from the hotel, featuring shopping, dining, and entertainment + 2. Try your luck at the Stellaris Casino - It's right in the Ritz-Carlton + 3. Take a sunset sailing cruise - Many depart from the nearby pier + 4. Visit the California Lighthouse - A scenic landmark just north of Palm Beach + 5. Enjoy water sports at Palm Beach: + - Jet skiing + - Parasailing + - Snorkeling + - Stand-up paddleboarding + + Would you like more specific information about any of these activities or would you like to know about other options in the area? + ``` + +## Prebuilt implementations + +LangGraph comes with prebuilt implementations of two of the most popular multi-agent architectures: + +- [supervisor](../agents/multi-agent.md#supervisor) — individual agents are coordinated by a central supervisor agent. The supervisor controls all communication flow and task delegation, making decisions about which agent to invoke based on the current context and task requirements. You can use [`langgraph-supervisor`](https://github.com/langchain-ai/langgraph-supervisor-py) library to create a supervisor multi-agent systems. +- [swarm](../agents/multi-agent.md#supervisor) — agents dynamically hand off control to one another based on their specializations. The system remembers which agent was last active, ensuring that on subsequent interactions, the conversation resumes with that agent. You can use [`langgraph-swarm`](https://github.com/langchain-ai/langgraph-swarm-py) library to create a swarm multi-agent systems. \ No newline at end of file diff --git a/docs/docs/how-tos/subgraph.ipynb b/docs/docs/how-tos/subgraph.ipynb deleted file mode 100644 index a16d99216..000000000 --- a/docs/docs/how-tos/subgraph.ipynb +++ /dev/null @@ -1,559 +0,0 @@ -{ - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Use subgraphs\n", - "\n", - "This guide explains the mechanics of using [subgraphs](../../concepts/subgraphs). A common application of subgraphs is to build [multi-agent](../../concepts/multi_agent) systems.\n", - "\n", - "When adding subgraphs, you need to define how the parent graph and the subgraph communicate:\n", - "\n", - "* [Shared state schemas](#shared-state-schemas) — parent and subgraph have **shared state keys** in their state [schemas](../../concepts/low_level#state)\n", - "* [Different state schemas](#different-state-schemas) — **no shared state keys** in parent and subgraph [schemas](../../concepts/low_level#state)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Setup" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "%%capture --no-stderr\n", - "%pip install -U langgraph" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "

Set up LangSmith for LangGraph development

\n", - "

\n", - " Sign up for LangSmith to quickly spot issues and improve the performance of your LangGraph projects. LangSmith lets you use trace data to debug, test, and monitor your LLM apps built with LangGraph — read more about how to get started here. \n", - "

\n", - "
" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Shared state schemas\n", - "\n", - "A common case is for the parent graph and subgraph to communicate over a shared state key (channel) in the [schema](../../concepts/low_level#state). For example, in [multi-agent](../../concepts/multi_agent) systems, the agents often communicate over a shared [messages](https://langchain-ai.github.io/langgraph/concepts/low_level/#why-use-messages) key.\n", - "\n", - "If your subgraph shares state keys with the parent graph, you can follow these steps to add it to your graph:\n", - "\n", - "1. Define the subgraph workflow (`subgraph_builder` in the example below) and compile it\n", - "2. Pass compiled subgraph to the `.add_node` method when defining the parent graph workflow\n", - "\n", - "```python\n", - "from typing_extensions import TypedDict\n", - "from langgraph.graph.state import StateGraph, START\n", - "\n", - "class State(TypedDict):\n", - " foo: str\n", - "\n", - "# Subgraph\n", - "\n", - "def subgraph_node_1(state: State):\n", - " return {\"foo\": \"hi! \" + state[\"foo\"]}\n", - "\n", - "subgraph_builder = StateGraph(State)\n", - "subgraph_builder.add_node(subgraph_node_1)\n", - "subgraph_builder.add_edge(START, \"subgraph_node_1\")\n", - "# highlight-next-line\n", - "subgraph = subgraph_builder.compile()\n", - "\n", - "# Parent graph\n", - "\n", - "builder = StateGraph(State)\n", - "# highlight-next-line\n", - "builder.add_node(\"node_1\", subgraph)\n", - "builder.add_edge(START, \"node_1\")\n", - "graph = builder.compile()\n", - "```\n", - "\n", - "??? example \"Full example: shared state schemas\"\n", - "\n", - " ```python\n", - " from typing_extensions import TypedDict\n", - " from langgraph.graph.state import StateGraph, START\n", - "\n", - " # Define subgraph\n", - " class SubgraphState(TypedDict):\n", - " foo: str # (1)! \n", - " bar: str # (2)!\n", - " \n", - " def subgraph_node_1(state: SubgraphState):\n", - " return {\"bar\": \"bar\"}\n", - " \n", - " def subgraph_node_2(state: SubgraphState):\n", - " # note that this node is using a state key ('bar') that is only available in the subgraph\n", - " # and is sending update on the shared state key ('foo')\n", - " return {\"foo\": state[\"foo\"] + state[\"bar\"]}\n", - " \n", - " subgraph_builder = StateGraph(SubgraphState)\n", - " subgraph_builder.add_node(subgraph_node_1)\n", - " subgraph_builder.add_node(subgraph_node_2)\n", - " subgraph_builder.add_edge(START, \"subgraph_node_1\")\n", - " subgraph_builder.add_edge(\"subgraph_node_1\", \"subgraph_node_2\")\n", - " subgraph = subgraph_builder.compile()\n", - " \n", - " # Define parent graph\n", - " class ParentState(TypedDict):\n", - " foo: str\n", - " \n", - " def node_1(state: ParentState):\n", - " return {\"foo\": \"hi! \" + state[\"foo\"]}\n", - " \n", - " builder = StateGraph(ParentState)\n", - " builder.add_node(\"node_1\", node_1)\n", - " # highlight-next-line\n", - " builder.add_node(\"node_2\", subgraph)\n", - " builder.add_edge(START, \"node_1\")\n", - " builder.add_edge(\"node_1\", \"node_2\")\n", - " graph = builder.compile()\n", - " \n", - " for chunk in graph.stream({\"foo\": \"foo\"}):\n", - " print(chunk)\n", - " ```\n", - "\n", - " 1. This key is shared with the parent graph state\n", - " 2. This key is private to the `SubgraphState` and is not visible to the parent graph\n", - " \n", - " ```\n", - " {'node_1': {'foo': 'hi! foo'}}\n", - " {'node_2': {'foo': 'hi! foobar'}}\n", - " ```\n", - "\n", - " ```" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Different state schemas\n", - "\n", - "For more complex systems you might want to define subgraphs that have a **completely different schema** from the parent graph (no shared keys). For example, you might want to keep a private message history for each of the agents in a [multi-agent](../concepts/multi_agent.md) system.\n", - "\n", - "If that's the case for your application, you need to define a node **function that invokes the subgraph**. This function needs to transform the input (parent) state to the subgraph state before invoking the subgraph, and transform the results back to the parent state before returning the state update from the node.\n", - "\n", - "```python\n", - "from typing_extensions import TypedDict\n", - "from langgraph.graph.state import StateGraph, START\n", - "\n", - "class SubgraphState(TypedDict):\n", - " bar: str\n", - "\n", - "# Subgraph\n", - "\n", - "def subgraph_node_1(state: SubgraphState):\n", - " return {\"bar\": \"hi! \" + state[\"bar\"]}\n", - "\n", - "subgraph_builder = StateGraph(SubgraphState)\n", - "subgraph_builder.add_node(subgraph_node_1)\n", - "subgraph_builder.add_edge(START, \"subgraph_node_1\")\n", - "# highlight-next-line\n", - "subgraph = subgraph_builder.compile()\n", - "\n", - "# Parent graph\n", - "\n", - "class State(TypedDict):\n", - " foo: str\n", - "\n", - "def call_subgraph(state: State):\n", - " # highlight-next-line\n", - " subgraph_output = subgraph.invoke({\"bar\": state[\"foo\"]}) # (1)!\n", - " # highlight-next-line\n", - " return {\"foo\": subgraph_output[\"bar\"]} # (2)!\n", - "\n", - "builder = StateGraph(State)\n", - "# highlight-next-line\n", - "builder.add_node(\"node_1\", call_subgraph)\n", - "builder.add_edge(START, \"node_1\")\n", - "graph = builder.compile()\n", - "```\n", - "\n", - "1. Transform the state to the subgraph state\n", - "2. Transform response back to the parent state\n", - "\n", - "??? example \"Full example: different state schemas\"\n", - "\n", - " ```python\n", - " from typing_extensions import TypedDict\n", - " from langgraph.graph.state import StateGraph, START\n", - "\n", - " # Define subgraph\n", - " class SubgraphState(TypedDict):\n", - " # note that none of these keys are shared with the parent graph state\n", - " bar: str\n", - " baz: str\n", - " \n", - " def subgraph_node_1(state: SubgraphState):\n", - " return {\"baz\": \"baz\"}\n", - " \n", - " def subgraph_node_2(state: SubgraphState):\n", - " return {\"bar\": state[\"bar\"] + state[\"baz\"]}\n", - " \n", - " subgraph_builder = StateGraph(SubgraphState)\n", - " subgraph_builder.add_node(subgraph_node_1)\n", - " subgraph_builder.add_node(subgraph_node_2)\n", - " subgraph_builder.add_edge(START, \"subgraph_node_1\")\n", - " subgraph_builder.add_edge(\"subgraph_node_1\", \"subgraph_node_2\")\n", - " subgraph = subgraph_builder.compile()\n", - " \n", - " # Define parent graph\n", - " class ParentState(TypedDict):\n", - " foo: str\n", - " \n", - " def node_1(state: ParentState):\n", - " return {\"foo\": \"hi! \" + state[\"foo\"]}\n", - " \n", - " def node_2(state: ParentState):\n", - " # highlight-next-line\n", - " response = subgraph.invoke({\"bar\": state[\"foo\"]}) # (1)!\n", - " # highlight-next-line\n", - " return {\"foo\": response[\"bar\"]} # (2)!\n", - " \n", - " \n", - " builder = StateGraph(ParentState)\n", - " builder.add_node(\"node_1\", node_1)\n", - " # highlight-next-line\n", - " builder.add_node(\"node_2\", node_2)\n", - " builder.add_edge(START, \"node_1\")\n", - " builder.add_edge(\"node_1\", \"node_2\")\n", - " graph = builder.compile()\n", - " \n", - " for chunk in graph.stream({\"foo\": \"foo\"}, subgraphs=True):\n", - " print(chunk)\n", - " ```\n", - "\n", - " 1. Transform the state to the subgraph state\n", - " 2. Transform response back to the parent state\n", - "\n", - " ```\n", - " ((), {'node_1': {'foo': 'hi! foo'}})\n", - " (('node_2:9c36dd0f-151a-cb42-cbad-fa2f851f9ab7',), {'subgraph_node_1': {'baz': 'baz'}})\n", - " (('node_2:9c36dd0f-151a-cb42-cbad-fa2f851f9ab7',), {'subgraph_node_2': {'bar': 'hi! foobaz'}})\n", - " ((), {'node_2': {'foo': 'hi! foobaz'}})\n", - " ```\n", - "\n", - "??? example \"Full example: different state schemas (two levels of subgraphs)\"\n", - "\n", - " This is an example with two levels of subgraphs: parent -> child -> grandchild.\n", - "\n", - " ```python\n", - " # Grandchild graph\n", - " from typing_extensions import TypedDict\n", - " from langgraph.graph.state import StateGraph, START, END\n", - " \n", - " class GrandChildState(TypedDict):\n", - " my_grandchild_key: str\n", - " \n", - " def grandchild_1(state: GrandChildState) -> GrandChildState:\n", - " # NOTE: child or parent keys will not be accessible here\n", - " return {\"my_grandchild_key\": state[\"my_grandchild_key\"] + \", how are you\"}\n", - " \n", - " \n", - " grandchild = StateGraph(GrandChildState)\n", - " grandchild.add_node(\"grandchild_1\", grandchild_1)\n", - " \n", - " grandchild.add_edge(START, \"grandchild_1\")\n", - " grandchild.add_edge(\"grandchild_1\", END)\n", - " \n", - " grandchild_graph = grandchild.compile()\n", - " \n", - " # Child graph\n", - " class ChildState(TypedDict):\n", - " my_child_key: str\n", - " \n", - " def call_grandchild_graph(state: ChildState) -> ChildState:\n", - " # NOTE: parent or grandchild keys won't be accessible here\n", - " grandchild_graph_input = {\"my_grandchild_key\": state[\"my_child_key\"]} # (1)!\n", - " # highlight-next-line\n", - " grandchild_graph_output = grandchild_graph.invoke(grandchild_graph_input)\n", - " return {\"my_child_key\": grandchild_graph_output[\"my_grandchild_key\"] + \" today?\"} # (2)!\n", - " \n", - " child = StateGraph(ChildState)\n", - " # highlight-next-line\n", - " child.add_node(\"child_1\", call_grandchild_graph) # (3)!\n", - " child.add_edge(START, \"child_1\")\n", - " child.add_edge(\"child_1\", END)\n", - " child_graph = child.compile()\n", - " \n", - " # Parent graph\n", - " class ParentState(TypedDict):\n", - " my_key: str\n", - " \n", - " def parent_1(state: ParentState) -> ParentState:\n", - " # NOTE: child or grandchild keys won't be accessible here\n", - " return {\"my_key\": \"hi \" + state[\"my_key\"]}\n", - " \n", - " def parent_2(state: ParentState) -> ParentState:\n", - " return {\"my_key\": state[\"my_key\"] + \" bye!\"}\n", - " \n", - " def call_child_graph(state: ParentState) -> ParentState:\n", - " child_graph_input = {\"my_child_key\": state[\"my_key\"]} # (4)!\n", - " # highlight-next-line\n", - " child_graph_output = child_graph.invoke(child_graph_input)\n", - " return {\"my_key\": child_graph_output[\"my_child_key\"]} # (5)!\n", - " \n", - " parent = StateGraph(ParentState)\n", - " parent.add_node(\"parent_1\", parent_1)\n", - " # highlight-next-line\n", - " parent.add_node(\"child\", call_child_graph) # (6)!\n", - " parent.add_node(\"parent_2\", parent_2)\n", - " \n", - " parent.add_edge(START, \"parent_1\")\n", - " parent.add_edge(\"parent_1\", \"child\")\n", - " parent.add_edge(\"child\", \"parent_2\")\n", - " parent.add_edge(\"parent_2\", END)\n", - " \n", - " parent_graph = parent.compile()\n", - " \n", - " for chunk in parent_graph.stream({\"my_key\": \"Bob\"}, subgraphs=True):\n", - " print(chunk)\n", - " ```\n", - "\n", - " 1. We're transforming the state from the child state channels (`my_child_key`) to the child state channels (`my_grandchild_key`)\n", - " 2. We're transforming the state from the grandchild state channels (`my_grandchild_key`) back to the child state channels (`my_child_key`)\n", - " 3. We're passing a function here instead of just compiled graph (`grandchild_graph`)\n", - " 4. We're transforming the state from the parent state channels (`my_key`) to the child state channels (`my_child_key`)\n", - " 5. We're transforming the state from the child state channels (`my_child_key`) back to the parent state channels (`my_key`)\n", - " 6. We're passing a function here instead of just a compiled graph (`child_graph`)\n", - "\n", - " ```\n", - " ((), {'parent_1': {'my_key': 'hi Bob'}})\n", - " (('child:2e26e9ce-602f-862c-aa66-1ea5a4655e3b', 'child_1:781bb3b1-3971-84ce-810b-acf819a03f9c'), {'grandchild_1': {'my_grandchild_key': 'hi Bob, how are you'}})\n", - " (('child:2e26e9ce-602f-862c-aa66-1ea5a4655e3b',), {'child_1': {'my_child_key': 'hi Bob, how are you today?'}})\n", - " ((), {'child': {'my_key': 'hi Bob, how are you today?'}})\n", - " ((), {'parent_2': {'my_key': 'hi Bob, how are you today? bye!'}})\n", - " ```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Add persistence \n", - "\n", - "You only need to **provide the checkpointer when compiling the parent graph**. LangGraph will automatically propagate the checkpointer to the child subgraphs.\n", - "\n", - "```python\n", - "from langgraph.graph import START, StateGraph\n", - "from langgraph.checkpoint.memory import InMemorySaver\n", - "from typing_extensions import TypedDict\n", - "\n", - "class State(TypedDict):\n", - " foo: str\n", - "\n", - "# Subgraph\n", - "\n", - "def subgraph_node_1(state: State):\n", - " return {\"foo\": state[\"foo\"] + \"bar\"}\n", - "\n", - "subgraph_builder = StateGraph(State)\n", - "subgraph_builder.add_node(subgraph_node_1)\n", - "subgraph_builder.add_edge(START, \"subgraph_node_1\")\n", - "# highlight-next-line\n", - "subgraph = subgraph_builder.compile()\n", - "\n", - "# Parent graph\n", - "\n", - "builder = StateGraph(State)\n", - "# highlight-next-line\n", - "builder.add_node(\"node_1\", subgraph)\n", - "builder.add_edge(START, \"node_1\")\n", - "\n", - "checkpointer = InMemorySaver()\n", - "# highlight-next-line\n", - "graph = builder.compile(checkpointer=checkpointer)\n", - "``` \n", - "\n", - "If you want the subgraph to **have its own memory**, you can compile it `with checkpointer=True`. This is useful in [multi-agent](../../concepts/multi_agent) systems, if you want agents to keep track of their internal message histories:\n", - "\n", - "```python\n", - "subgraph_builder = StateGraph(...)\n", - "# highlight-next-line\n", - "subgraph = subgraph_builder.compile(checkpointer=True)\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## View subgraph state\n", - "\n", - "When you enable [persistence](../persistence), you can [inspect the graph state](../persistence#manage-checkpoints) (checkpoint) via `graph.get_state(config)`. To view the subgraph state, you can use `graph.get_state(config, subgraphs=True)`.\n", - "\n", - "!!! important \"Available **only** when interrupted\"\n", - "\n", - " Subgraph state can only be viewed **when the subgraph is interrupted**. Once you resume the graph, you won't be able to access the subgraph state.\n", - "\n", - "??? example \"View interrupted subgraph state\"\n", - "\n", - " ```python\n", - " from langgraph.graph import START, StateGraph\n", - " from langgraph.checkpoint.memory import InMemorySaver\n", - " from langgraph.types import interrupt, Command\n", - " from typing_extensions import TypedDict\n", - " \n", - " class State(TypedDict):\n", - " foo: str\n", - " \n", - " # Subgraph\n", - " \n", - " def subgraph_node_1(state: State):\n", - " # highlight-next-line\n", - " value = interrupt(\"Provide value:\")\n", - " return {\"foo\": state[\"foo\"] + value}\n", - " \n", - " subgraph_builder = StateGraph(State)\n", - " subgraph_builder.add_node(subgraph_node_1)\n", - " subgraph_builder.add_edge(START, \"subgraph_node_1\")\n", - " \n", - " subgraph = subgraph_builder.compile()\n", - " \n", - " # Parent graph\n", - " \n", - " builder = StateGraph(State)\n", - " # highlight-next-line\n", - " builder.add_node(\"node_1\", subgraph)\n", - " builder.add_edge(START, \"node_1\")\n", - " \n", - " checkpointer = InMemorySaver()\n", - " # highlight-next-line\n", - " graph = builder.compile(checkpointer=checkpointer)\n", - " \n", - " config = {\"configurable\": {\"thread_id\": \"1\"}}\n", - " \n", - " graph.invoke({\"foo\": \"\"}, config)\n", - " parent_state = graph.get_state(config)\n", - " # highlight-next-line\n", - " subgraph_state = graph.get_state(config, subgraphs=True).tasks[0].state # (1)!\n", - " \n", - " # resume the subgraph\n", - " graph.invoke(Command(resume=\"bar\"), config)\n", - " ```\n", - " \n", - " 1. This will be available only when the subgraph is interrupted. Once you resume the graph, you won't be able to access the subgraph state." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Stream subgraph outputs\n", - "\n", - "To include outputs from [subgraphs](../concepts/low_level.md#subgraphs) in the streamed outputs, you can set `subgraphs=True` in the `.stream()` method of the parent graph. This will stream outputs from both the parent graph and any subgraphs.\n", - "\n", - "```python\n", - "for chunk in graph.stream(\n", - " {\"foo\": \"foo\"},\n", - " # highlight-next-line\n", - " subgraphs=True, # (1)!\n", - " stream_mode=\"updates\",\n", - "):\n", - " print(chunk)\n", - "```\n", - "\n", - "1. Set `subgraphs=True` to stream outputs from subgraphs.\n", - "\n", - "??? example \"Stream from subgraphs\"\n", - "\n", - " ```python\n", - " from typing_extensions import TypedDict\n", - " from langgraph.graph.state import StateGraph, START\n", - "\n", - " # Define subgraph\n", - " class SubgraphState(TypedDict):\n", - " foo: str\n", - " bar: str\n", - " \n", - " def subgraph_node_1(state: SubgraphState):\n", - " return {\"bar\": \"bar\"}\n", - " \n", - " def subgraph_node_2(state: SubgraphState):\n", - " # note that this node is using a state key ('bar') that is only available in the subgraph\n", - " # and is sending update on the shared state key ('foo')\n", - " return {\"foo\": state[\"foo\"] + state[\"bar\"]}\n", - " \n", - " subgraph_builder = StateGraph(SubgraphState)\n", - " subgraph_builder.add_node(subgraph_node_1)\n", - " subgraph_builder.add_node(subgraph_node_2)\n", - " subgraph_builder.add_edge(START, \"subgraph_node_1\")\n", - " subgraph_builder.add_edge(\"subgraph_node_1\", \"subgraph_node_2\")\n", - " subgraph = subgraph_builder.compile()\n", - " \n", - " # Define parent graph\n", - " class ParentState(TypedDict):\n", - " foo: str\n", - " \n", - " def node_1(state: ParentState):\n", - " return {\"foo\": \"hi! \" + state[\"foo\"]}\n", - " \n", - " builder = StateGraph(ParentState)\n", - " builder.add_node(\"node_1\", node_1)\n", - " # highlight-next-line\n", - " builder.add_node(\"node_2\", subgraph)\n", - " builder.add_edge(START, \"node_1\")\n", - " builder.add_edge(\"node_1\", \"node_2\")\n", - " graph = builder.compile()\n", - "\n", - " for chunk in graph.stream(\n", - " {\"foo\": \"foo\"},\n", - " stream_mode=\"updates\",\n", - " # highlight-next-line\n", - " subgraphs=True, # (1)!\n", - " ):\n", - " print(chunk)\n", - " ```\n", - " \n", - " 1. Set `subgraphs=True` to stream outputs from subgraphs.\n", - "\n", - " ```\n", - " ((), {'node_1': {'foo': 'hi! foo'}})\n", - " (('node_2:e58e5673-a661-ebb0-70d4-e298a7fc28b7',), {'subgraph_node_1': {'bar': 'bar'}})\n", - " (('node_2:e58e5673-a661-ebb0-70d4-e298a7fc28b7',), {'subgraph_node_2': {'foo': 'hi! foobar'}})\n", - " ((), {'node_2': {'foo': 'hi! foobar'}})\n", - " ```" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.3" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/docs/docs/how-tos/subgraph.md b/docs/docs/how-tos/subgraph.md new file mode 100644 index 000000000..9ad820f73 --- /dev/null +++ b/docs/docs/how-tos/subgraph.md @@ -0,0 +1,453 @@ +# Use subgraphs + +This guide explains the mechanics of using [subgraphs](../concepts/subgraphs.md). A common application of subgraphs is to build [multi-agent](../concepts/multi_agent.md) systems. + +When adding subgraphs, you need to define how the parent graph and the subgraph communicate: + +* [Shared state schemas](#shared-state-schemas) — parent and subgraph have **shared state keys** in their state [schemas](../concepts/low_level.md#state) +* [Different state schemas](#different-state-schemas) — **no shared state keys** in parent and subgraph [schemas](../concepts/low_level.md#state) + +## Setup + +```bash +pip install -U langgraph +``` + +!!! tip "Set up LangSmith for LangGraph development" + Sign up for [LangSmith](https://smith.langchain.com) to quickly spot issues and improve the performance of your LangGraph projects. LangSmith lets you use trace data to debug, test, and monitor your LLM apps built with LangGraph — read more about how to get started [here](https://docs.smith.langchain.com). + +## Shared state schemas + +A common case is for the parent graph and subgraph to communicate over a shared state key (channel) in the [schema](../concepts/low_level.md#state). For example, in [multi-agent](../concepts/multi_agent.md) systems, the agents often communicate over a shared [messages](https://langchain-ai.github.io/langgraph/concepts/low_level.md#why-use-messages) key. + +If your subgraph shares state keys with the parent graph, you can follow these steps to add it to your graph: + +1. Define the subgraph workflow (`subgraph_builder` in the example below) and compile it +2. Pass compiled subgraph to the `.add_node` method when defining the parent graph workflow + +```python +from typing_extensions import TypedDict +from langgraph.graph.state import StateGraph, START + +class State(TypedDict): + foo: str + +# Subgraph + +def subgraph_node_1(state: State): + return {"foo": "hi! " + state["foo"]} + +subgraph_builder = StateGraph(State) +subgraph_builder.add_node(subgraph_node_1) +subgraph_builder.add_edge(START, "subgraph_node_1") +subgraph = subgraph_builder.compile() + +# Parent graph + +builder = StateGraph(State) +builder.add_node("node_1", subgraph) +builder.add_edge(START, "node_1") +graph = builder.compile() +``` + +??? example "Full example: shared state schemas" + + ```python + from typing_extensions import TypedDict + from langgraph.graph.state import StateGraph, START + + # Define subgraph + class SubgraphState(TypedDict): + foo: str # (1)! + bar: str # (2)! + + def subgraph_node_1(state: SubgraphState): + return {"bar": "bar"} + + def subgraph_node_2(state: SubgraphState): + # note that this node is using a state key ('bar') that is only available in the subgraph + # and is sending update on the shared state key ('foo') + return {"foo": state["foo"] + state["bar"]} + + subgraph_builder = StateGraph(SubgraphState) + subgraph_builder.add_node(subgraph_node_1) + subgraph_builder.add_node(subgraph_node_2) + subgraph_builder.add_edge(START, "subgraph_node_1") + subgraph_builder.add_edge("subgraph_node_1", "subgraph_node_2") + subgraph = subgraph_builder.compile() + + # Define parent graph + class ParentState(TypedDict): + foo: str + + def node_1(state: ParentState): + return {"foo": "hi! " + state["foo"]} + + builder = StateGraph(ParentState) + builder.add_node("node_1", node_1) + builder.add_node("node_2", subgraph) + builder.add_edge(START, "node_1") + builder.add_edge("node_1", "node_2") + graph = builder.compile() + + for chunk in graph.stream({"foo": "foo"}): + print(chunk) + ``` + + 1. This key is shared with the parent graph state + 2. This key is private to the `SubgraphState` and is not visible to the parent graph + + ``` + {'node_1': {'foo': 'hi! foo'}} + {'node_2': {'foo': 'hi! foobar'}} + ``` + +## Different state schemas + +For more complex systems you might want to define subgraphs that have a **completely different schema** from the parent graph (no shared keys). For example, you might want to keep a private message history for each of the agents in a [multi-agent](../concepts/multi_agent.md) system. + +If that's the case for your application, you need to define a node **function that invokes the subgraph**. This function needs to transform the input (parent) state to the subgraph state before invoking the subgraph, and transform the results back to the parent state before returning the state update from the node. + +```python +from typing_extensions import TypedDict +from langgraph.graph.state import StateGraph, START + +class SubgraphState(TypedDict): + bar: str + +# Subgraph + +def subgraph_node_1(state: SubgraphState): + return {"bar": "hi! " + state["bar"]} + +subgraph_builder = StateGraph(SubgraphState) +subgraph_builder.add_node(subgraph_node_1) +subgraph_builder.add_edge(START, "subgraph_node_1") +subgraph = subgraph_builder.compile() + +# Parent graph + +class State(TypedDict): + foo: str + +def call_subgraph(state: State): + subgraph_output = subgraph.invoke({"bar": state["foo"]}) # (1)! + return {"foo": subgraph_output["bar"]} # (2)! + +builder = StateGraph(State) +builder.add_node("node_1", call_subgraph) +builder.add_edge(START, "node_1") +graph = builder.compile() +``` + +1. Transform the state to the subgraph state +2. Transform response back to the parent state + +??? example "Full example: different state schemas" + + ```python + from typing_extensions import TypedDict + from langgraph.graph.state import StateGraph, START + + # Define subgraph + class SubgraphState(TypedDict): + # note that none of these keys are shared with the parent graph state + bar: str + baz: str + + def subgraph_node_1(state: SubgraphState): + return {"baz": "baz"} + + def subgraph_node_2(state: SubgraphState): + return {"bar": state["bar"] + state["baz"]} + + subgraph_builder = StateGraph(SubgraphState) + subgraph_builder.add_node(subgraph_node_1) + subgraph_builder.add_node(subgraph_node_2) + subgraph_builder.add_edge(START, "subgraph_node_1") + subgraph_builder.add_edge("subgraph_node_1", "subgraph_node_2") + subgraph = subgraph_builder.compile() + + # Define parent graph + class ParentState(TypedDict): + foo: str + + def node_1(state: ParentState): + return {"foo": "hi! " + state["foo"]} + + def node_2(state: ParentState): + response = subgraph.invoke({"bar": state["foo"]}) # (1)! + return {"foo": response["bar"]} # (2)! + + + builder = StateGraph(ParentState) + builder.add_node("node_1", node_1) + builder.add_node("node_2", node_2) + builder.add_edge(START, "node_1") + builder.add_edge("node_1", "node_2") + graph = builder.compile() + + for chunk in graph.stream({"foo": "foo"}, subgraphs=True): + print(chunk) + ``` + + 1. Transform the state to the subgraph state + 2. Transform response back to the parent state + + ``` + ((), {'node_1': {'foo': 'hi! foo'}}) + (('node_2:9c36dd0f-151a-cb42-cbad-fa2f851f9ab7',), {'grandchild_1': {'my_grandchild_key': 'hi Bob, how are you'}}) + (('node_2:9c36dd0f-151a-cb42-cbad-fa2f851f9ab7',), {'grandchild_2': {'bar': 'hi! foobaz'}}) + ((), {'node_2': {'foo': 'hi! foobaz'}}) + ``` + +??? example "Full example: different state schemas (two levels of subgraphs)" + + This is an example with two levels of subgraphs: parent -> child -> grandchild. + + ```python + # Grandchild graph + from typing_extensions import TypedDict + from langgraph.graph.state import StateGraph, START, END + + class GrandChildState(TypedDict): + my_grandchild_key: str + + def grandchild_1(state: GrandChildState) -> GrandChildState: + # NOTE: child or parent keys will not be accessible here + return {"my_grandchild_key": state["my_grandchild_key"] + ", how are you"} + + + grandchild = StateGraph(GrandChildState) + grandchild.add_node("grandchild_1", grandchild_1) + + grandchild.add_edge(START, "grandchild_1") + grandchild.add_edge("grandchild_1", END) + + grandchild_graph = grandchild.compile() + + # Child graph + class ChildState(TypedDict): + my_child_key: str + + def call_grandchild_graph(state: ChildState) -> ChildState: + # NOTE: parent or grandchild keys won't be accessible here + grandchild_graph_input = {"my_grandchild_key": state["my_child_key"]} # (1)! + grandchild_graph_output = grandchild_graph.invoke(grandchild_graph_input) + return {"my_child_key": grandchild_graph_output["my_grandchild_key"] + " today?"} # (2)! + + child = StateGraph(ChildState) + child.add_node("child_1", call_grandchild_graph) # (3)! + child.add_edge(START, "child_1") + child.add_edge("child_1", END) + child_graph = child.compile() + + # Parent graph + class ParentState(TypedDict): + my_key: str + + def parent_1(state: ParentState) -> ParentState: + # NOTE: child or grandchild keys won't be accessible here + return {"my_key": "hi " + state["my_key"]} + + def parent_2(state: ParentState) -> ParentState: + return {"my_key": state["my_key"] + " bye!"} + + def call_child_graph(state: ParentState) -> ParentState: + child_graph_input = {"my_child_key": state["my_key"]} # (4)! + child_graph_output = child_graph.invoke(child_graph_input) + return {"my_key": child_graph_output["my_child_key"]} # (5)! + + parent = StateGraph(ParentState) + parent.add_node("parent_1", parent_1) + parent.add_node("child", call_child_graph) # (6)! + parent.add_node("parent_2", parent_2) + + parent.add_edge(START, "parent_1") + parent.add_edge("parent_1", "child") + parent.add_edge("child", "parent_2") + parent.add_edge("parent_2", END) + + parent_graph = parent.compile() + + for chunk in parent_graph.stream({"my_key": "Bob"}, subgraphs=True): + print(chunk) + ``` + + 1. We're transforming the state from the child state channels (`my_child_key`) to the child state channels (`my_grandchild_key`) + 2. We're transforming the state from the grandchild state channels (`my_grandchild_key`) back to the child state channels (`my_child_key`) + 3. We're passing a function here instead of just compiled graph (`grandchild_graph`) + 4. We're transforming the state from the parent state channels (`my_key`) to the child state channels (`my_child_key`) + 5. We're transforming the state from the child state channels (`my_child_key`) back to the parent state channels (`my_key`) + 6. We're passing a function here instead of just a compiled graph (`child_graph`) + + ``` + ((), {'parent_1': {'my_key': 'hi Bob'}}) + (('child:2e26e9ce-602f-862c-aa66-1ea5a4655e3b', 'child_1:781bb3b1-3971-84ce-810b-acf819a03f9c'), {'grandchild_1': {'my_grandchild_key': 'hi Bob, how are you'}}) + (('child:2e26e9ce-602f-862c-aa66-1ea5a4655e3b',), {'child_1': {'my_child_key': 'hi Bob, how are you today?'}}) + ((), {'child': {'my_key': 'hi Bob, how are you today?'}}) + ((), {'parent_2': {'my_key': 'hi Bob, how are you today? bye!'}}) + ``` + +## Add persistence + +You only need to **provide the checkpointer when compiling the parent graph**. LangGraph will automatically propagate the checkpointer to the child subgraphs. + +```python +from langgraph.graph import START, StateGraph +from langgraph.checkpoint.memory import InMemorySaver +from typing_extensions import TypedDict + +class State(TypedDict): + foo: str + +# Subgraph + +def subgraph_node_1(state: State): + return {"foo": state["foo"] + "bar"} + +subgraph_builder = StateGraph(State) +subgraph_builder.add_node(subgraph_node_1) +subgraph_builder.add_edge(START, "subgraph_node_1") +subgraph = subgraph_builder.compile() + +# Parent graph + +builder = StateGraph(State) +builder.add_node("node_1", subgraph) +builder.add_edge(START, "node_1") + +checkpointer = InMemorySaver() +graph = builder.compile(checkpointer=checkpointer) +``` + +If you want the subgraph to **have its own memory**, you can compile it `with checkpointer=True`. This is useful in [multi-agent](../concepts/multi_agent.md) systems, if you want agents to keep track of their internal message histories: + +```python +subgraph_builder = StateGraph(...) +subgraph = subgraph_builder.compile(checkpointer=True) +``` + +## View subgraph state + +When you enable [persistence](../concepts/persistence.md), you can [inspect the graph state](../concepts/persistence.md#checkpoints) (checkpoint) via `graph.get_state(config)`. To view the subgraph state, you can use `graph.get_state(config, subgraphs=True)`. + +!!! important "Available **only** when interrupted" + + Subgraph state can only be viewed **when the subgraph is interrupted**. Once you resume the graph, you won't be able to access the subgraph state. + +??? example "View interrupted subgraph state" + + ```python + from langgraph.graph import START, StateGraph + from langgraph.checkpoint.memory import InMemorySaver + from langgraph.types import interrupt, Command + from typing_extensions import TypedDict + + class State(TypedDict): + foo: str + + # Subgraph + + def subgraph_node_1(state: State): + value = interrupt("Provide value:") + return {"foo": state["foo"] + value} + + subgraph_builder = StateGraph(State) + subgraph_builder.add_node(subgraph_node_1) + subgraph_builder.add_edge(START, "subgraph_node_1") + + subgraph = subgraph_builder.compile() + + # Parent graph + + builder = StateGraph(State) + builder.add_node("node_1", subgraph) + builder.add_edge(START, "node_1") + + checkpointer = InMemorySaver() + graph = builder.compile(checkpointer=checkpointer) + + config = {"configurable": {"thread_id": "1"}} + + graph.invoke({"foo": ""}, config) + parent_state = graph.get_state(config) + subgraph_state = graph.get_state(config, subgraphs=True).tasks[0].state # (1)! + + # resume the subgraph + graph.invoke(Command(resume="bar"), config) + ``` + + 1. This will be available only when the subgraph is interrupted. Once you resume the graph, you won't be able to access the subgraph state. + +## Stream subgraph outputs + +To include outputs from subgraphs in the streamed outputs, you can set `subgraphs=True` in the `.stream()` method of the parent graph. This will stream outputs from both the parent graph and any subgraphs. + +```python +for chunk in graph.stream( + {"foo": "foo"}, + subgraphs=True, # (1)! + stream_mode="updates", +): + print(chunk) +``` + +1. Set `subgraphs=True` to stream outputs from subgraphs. + +??? example "Stream from subgraphs" + + ```python + from typing_extensions import TypedDict + from langgraph.graph.state import StateGraph, START + + # Define subgraph + class SubgraphState(TypedDict): + foo: str + bar: str + + def subgraph_node_1(state: SubgraphState): + return {"bar": "bar"} + + def subgraph_node_2(state: SubgraphState): + # note that this node is using a state key ('bar') that is only available in the subgraph + # and is sending update on the shared state key ('foo') + return {"foo": state["foo"] + state["bar"]} + + subgraph_builder = StateGraph(SubgraphState) + subgraph_builder.add_node(subgraph_node_1) + subgraph_builder.add_node(subgraph_node_2) + subgraph_builder.add_edge(START, "subgraph_node_1") + subgraph_builder.add_edge("subgraph_node_1", "subgraph_node_2") + subgraph = subgraph_builder.compile() + + # Define parent graph + class ParentState(TypedDict): + foo: str + + def node_1(state: ParentState): + return {"foo": "hi! " + state["foo"]} + + builder = StateGraph(ParentState) + builder.add_node("node_1", node_1) + builder.add_node("node_2", subgraph) + builder.add_edge(START, "node_1") + builder.add_edge("node_1", "node_2") + graph = builder.compile() + + for chunk in graph.stream( + {"foo": "foo"}, + stream_mode="updates", + subgraphs=True, # (1)! + ): + print(chunk) + ``` + + 1. Set `subgraphs=True` to stream outputs from subgraphs. + + ``` + ((), {'node_1': {'foo': 'hi! foo'}}) + (('node_2:e58e5673-a661-ebb0-70d4-e298a7fc28b7',), {'subgraph_node_1': {'bar': 'bar'}}) + (('node_2:e58e5673-a661-ebb0-70d4-e298a7fc28b7',), {'subgraph_node_2': {'foo': 'hi! foobar'}}) + ((), {'node_2': {'foo': 'hi! foobar'}}) + \ No newline at end of file diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 9fc53ac0d..a59c835dd 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -112,7 +112,7 @@ nav: - LangGraph APIs: - Graph API: - Overview: concepts/low_level.md - - Use the Graph API: how-tos/graph-api.ipynb + - Use the Graph API: how-tos/graph-api.md - Functional API: - Overview: concepts/functional_api.md - Use the Functional API: how-tos/use-functional-api.md @@ -150,11 +150,11 @@ nav: - Use Server API: cloud/how-tos/human_in_the_loop_time_travel.md - Subgraphs: - Overview: concepts/subgraphs.md - - Use subgraphs: how-tos/subgraph.ipynb + - Use subgraphs: how-tos/subgraph.md - Multi-agent: - Overview: concepts/multi_agent.md - Prebuilt implementation: agents/multi-agent.md - - Custom implementation: how-tos/multi_agent.ipynb + - Custom implementation: how-tos/multi_agent.md - MCP: - Overview: concepts/mcp.md - Use MCP: agents/mcp.md diff --git a/docs/uv.lock b/docs/uv.lock index f838b6d3a..0f4527769 100644 --- a/docs/uv.lock +++ b/docs/uv.lock @@ -2590,7 +2590,7 @@ wheels = [ [[package]] name = "langgraph" -version = "0.5.0" +version = "0.5.1" source = { editable = "../libs/langgraph" } dependencies = [ { name = "langchain-core" }, diff --git a/extract_images.py b/extract_images.py new file mode 100644 index 000000000..781ba0a22 --- /dev/null +++ b/extract_images.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 +""" +Script to extract images from the graph-api.ipynb notebook and save them to assets folder. +""" + +import json +import base64 +import os +from pathlib import Path + +def extract_images_from_notebook(notebook_path, assets_dir): + """Extract images from notebook and save them to assets directory.""" + + # Read the notebook + with open(notebook_path, 'r') as f: + notebook = json.load(f) + + # Create assets directory if it doesn't exist + os.makedirs(assets_dir, exist_ok=True) + + image_count = 0 + + # Process each cell + for cell_idx, cell in enumerate(notebook['cells']): + if cell['cell_type'] == 'code': + # Check if this cell contains draw_mermaid_png + source = ''.join(cell.get('source', [])) + if 'draw_mermaid_png' in source: + print(f"Found draw_mermaid_png in cell {cell_idx}") + + # Check for outputs with images + if 'outputs' in cell: + for output_idx, output in enumerate(cell['outputs']): + if output.get('output_type') == 'display_data': + data = output.get('data', {}) + + # Check for PNG data + if 'image/png' in data: + png_data = data['image/png'] + + # Decode base64 data + try: + image_bytes = base64.b64decode(png_data) + + # Generate filename + image_count += 1 + filename = f"graph_api_image_{image_count}.png" + filepath = os.path.join(assets_dir, filename) + + # Save the image + with open(filepath, 'wb') as img_file: + img_file.write(image_bytes) + + print(f"Saved image: {filepath}") + + except Exception as e: + print(f"Error decoding image {image_count}: {e}") + + print(f"Extracted {image_count} images to {assets_dir}") + return image_count + +if __name__ == "__main__": + notebook_path = "docs/docs/how-tos/graph-api.ipynb" + assets_dir = "docs/docs/how-tos/assets" + + if os.path.exists(notebook_path): + count = extract_images_from_notebook(notebook_path, assets_dir) + print(f"Successfully extracted {count} images") + else: + print(f"Notebook not found: {notebook_path}") \ No newline at end of file From ecfabdf73af570461b91d64d2ada5704598a4760 Mon Sep 17 00:00:00 2001 From: Josh Rogers Date: Wed, 2 Jul 2025 22:14:01 -0400 Subject: [PATCH 017/129] Adding disable_webhook to cli docs (#5320) * Adding disable_webhook to cli docs * Adding disable_webhook config --- docs/docs/cloud/reference/cli.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/cloud/reference/cli.md b/docs/docs/cloud/reference/cli.md index 84e5f3f66..b43be5485 100644 --- a/docs/docs/cloud/reference/cli.md +++ b/docs/docs/cloud/reference/cli.md @@ -53,7 +53,7 @@ The LangGraph CLI requires a JSON configuration file that follows this [schema]( | `pip_installer` | _(Added in v0.3)_ Optional. Python package installer selector. It can be set to `"auto"`, `"pip"`, or `"uv"`. From version 0.3 onward the default strategy is to run `uv pip`, which typically delivers faster builds while remaining a drop-in replacement. In the uncommon situation where `uv` cannot handle your dependency graph or the structure of your `pyproject.toml`, specify `"pip"` here to revert to the earlier behaviour. | | `dockerfile_lines` | Array of additional lines to add to Dockerfile following the import from parent image. | | `checkpointer` | Configuration for the checkpointer. Contains a `ttl` field which is an object with the following keys:
  • `strategy`: How to handle expired checkpoints (e.g., `"delete"`).
  • `sweep_interval_minutes`: How often to check for expired checkpoints (integer).
  • `default_ttl`: Default time-to-live for checkpoints in **minutes** (integer). Defines how long checkpoints are kept before the specified strategy is applied.
| - | `http` | HTTP server configuration with the following fields:
  • `app`: Path to custom Starlette/FastAPI app (e.g., `"./src/agent/webapp.py:app"`). See [custom routes guide](../../how-tos/http/custom_routes.md).
  • `disable_assistants`: Disable `/assistants` routes
  • `disable_threads`: Disable `/threads` routes
  • `disable_runs`: Disable `/runs` routes
  • `disable_store`: Disable `/store` routes
  • `disable_meta`: Disable `/ok`, `/info`, `/metrics`, and `/docs` routes
  • `disable_mcp`: Disable `/mcp` routes
  • `cors`: CORS configuration with fields for `allow_origins`, `allow_methods`, `allow_headers`, etc.
  • `configurable_headers`: Define which request headers to exclude or include as a run's configurable values.
| + | `http` | HTTP server configuration with the following fields:
  • `app`: Path to custom Starlette/FastAPI app (e.g., `"./src/agent/webapp.py:app"`). See [custom routes guide](../../how-tos/http/custom_routes.md).
  • `cors`: CORS configuration with fields for `allow_origins`, `allow_methods`, `allow_headers`, etc.
  • `configurable_headers`: Define which request headers to exclude or include as a run's configurable values.
  • `disable_assistants`: Disable `/assistants` routes
  • `disable_mcp`: Disable `/mcp` routes
  • `disable_meta`: Disable `/ok`, `/info`, `/metrics`, and `/docs` routes
  • `disable_runs`: Disable `/runs` routes
  • `disable_store`: Disable `/store` routes
  • `disable_threads`: Disable `/threads` routes
  • `disable_ui`: Disable `/ui` routes
  • `disable_webhooks`: Disable webhooks calls on run completion in all routes
  • `mount_prefix`: Prefix for mounted routes (e.g., "/my-deployment/api")
| === "JS" From 37d1ac1dce9b9e1248063e1874a89620207cca9d Mon Sep 17 00:00:00 2001 From: Eugene Yurtsev Date: Wed, 2 Jul 2025 22:26:32 -0400 Subject: [PATCH 018/129] ci: one more workflow without explicit permissions (#5326) --- .github/workflows/_test_release.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/_test_release.yml b/.github/workflows/_test_release.yml index ea0c352aa..2a2324c6f 100644 --- a/.github/workflows/_test_release.yml +++ b/.github/workflows/_test_release.yml @@ -11,6 +11,9 @@ on: env: PYTHON_VERSION: "3.10" +permissions: + contents: read + jobs: build: if: github.ref == 'refs/heads/main' From 042e8ef31576b852bd2a24395a5c9a2bbb30e4f5 Mon Sep 17 00:00:00 2001 From: Tat Dat Duong Date: Thu, 3 Jul 2025 16:50:51 +0200 Subject: [PATCH 019/129] chore: remove sdk-js `sdk-js` has been moved here: https://github.com/langchain-ai/langgraphjs/tree/main/libs/sdk --- .github/workflows/ci.yml | 55 - .github/workflows/release_js.yml | 41 - docs/.gitignore | 1 - docs/Makefile | 12 +- .../docs/cloud/reference/sdk/js_ts_sdk_ref.md | 3403 +++++++++++ docs/mkdocs.yml | 2 +- libs/sdk-js/.gitignore | 28 - libs/sdk-js/.prettierrc | 1 - libs/sdk-js/LICENSE | 21 - libs/sdk-js/README.md | 64 - libs/sdk-js/jest.config.js | 17 - libs/sdk-js/langchain.config.js | 27 - libs/sdk-js/package.json | 147 - libs/sdk-js/src/auth/error.ts | 80 - libs/sdk-js/src/auth/index.ts | 46 - libs/sdk-js/src/auth/types.ts | 411 -- libs/sdk-js/src/client.ts | 1699 ------ libs/sdk-js/src/index.ts | 56 - libs/sdk-js/src/react-ui/client.tsx | 279 - libs/sdk-js/src/react-ui/index.ts | 15 - libs/sdk-js/src/react-ui/server/index.ts | 6 - libs/sdk-js/src/react-ui/server/server.ts | 99 - libs/sdk-js/src/react-ui/types.ts | 66 - libs/sdk-js/src/react/debug.tsx | 102 - libs/sdk-js/src/react/index.ts | 6 - libs/sdk-js/src/react/stream.tsx | 1264 ---- libs/sdk-js/src/schema.ts | 334 -- libs/sdk-js/src/singletons/fetch.ts | 29 - libs/sdk-js/src/tests/fetch.test.ts | 201 - libs/sdk-js/src/tests/sse.test.ts | 183 - libs/sdk-js/src/tests/stream.test.tsx | 450 -- libs/sdk-js/src/types.messages.ts | 101 - libs/sdk-js/src/types.stream.ts | 231 - libs/sdk-js/src/types.ts | 209 - libs/sdk-js/src/utils/async_caller.ts | 216 - libs/sdk-js/src/utils/env.ts | 11 - libs/sdk-js/src/utils/signals.ts | 22 - libs/sdk-js/src/utils/sse.ts | 175 - libs/sdk-js/src/utils/stream.ts | 115 - libs/sdk-js/tsconfig.cjs.json | 9 - libs/sdk-js/tsconfig.json | 33 - libs/sdk-js/typedoc.auth.json | 5 - libs/sdk-js/typedoc.react.json | 5 - libs/sdk-js/vitest.config.ts | 11 - libs/sdk-js/yarn.lock | 5259 ----------------- 45 files changed, 3407 insertions(+), 12140 deletions(-) delete mode 100644 .github/workflows/release_js.yml create mode 100644 docs/docs/cloud/reference/sdk/js_ts_sdk_ref.md delete mode 100644 libs/sdk-js/.gitignore delete mode 100644 libs/sdk-js/.prettierrc delete mode 100644 libs/sdk-js/LICENSE delete mode 100644 libs/sdk-js/README.md delete mode 100644 libs/sdk-js/jest.config.js delete mode 100644 libs/sdk-js/langchain.config.js delete mode 100644 libs/sdk-js/package.json delete mode 100644 libs/sdk-js/src/auth/error.ts delete mode 100644 libs/sdk-js/src/auth/index.ts delete mode 100644 libs/sdk-js/src/auth/types.ts delete mode 100644 libs/sdk-js/src/client.ts delete mode 100644 libs/sdk-js/src/index.ts delete mode 100644 libs/sdk-js/src/react-ui/client.tsx delete mode 100644 libs/sdk-js/src/react-ui/index.ts delete mode 100644 libs/sdk-js/src/react-ui/server/index.ts delete mode 100644 libs/sdk-js/src/react-ui/server/server.ts delete mode 100644 libs/sdk-js/src/react-ui/types.ts delete mode 100644 libs/sdk-js/src/react/debug.tsx delete mode 100644 libs/sdk-js/src/react/index.ts delete mode 100644 libs/sdk-js/src/react/stream.tsx delete mode 100644 libs/sdk-js/src/schema.ts delete mode 100644 libs/sdk-js/src/singletons/fetch.ts delete mode 100644 libs/sdk-js/src/tests/fetch.test.ts delete mode 100644 libs/sdk-js/src/tests/sse.test.ts delete mode 100644 libs/sdk-js/src/tests/stream.test.tsx delete mode 100644 libs/sdk-js/src/types.messages.ts delete mode 100644 libs/sdk-js/src/types.stream.ts delete mode 100644 libs/sdk-js/src/types.ts delete mode 100644 libs/sdk-js/src/utils/async_caller.ts delete mode 100644 libs/sdk-js/src/utils/env.ts delete mode 100644 libs/sdk-js/src/utils/signals.ts delete mode 100644 libs/sdk-js/src/utils/sse.ts delete mode 100644 libs/sdk-js/src/utils/stream.ts delete mode 100644 libs/sdk-js/tsconfig.cjs.json delete mode 100644 libs/sdk-js/tsconfig.json delete mode 100644 libs/sdk-js/typedoc.auth.json delete mode 100644 libs/sdk-js/typedoc.react.json delete mode 100644 libs/sdk-js/vitest.config.ts delete mode 100644 libs/sdk-js/yarn.lock diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9ee07bc32..050daa704 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,6 @@ jobs: runs-on: ubuntu-latest outputs: python: ${{ steps.filter.outputs.python }} - sdk-js: ${{ steps.filter.outputs.sdk-js }} deps: ${{ steps.filter.outputs.deps }} steps: - uses: actions/checkout@v4 @@ -40,8 +39,6 @@ jobs: - 'libs/checkpoint-sqlite/**' - 'libs/checkpoint-postgres/**' - 'libs/prebuilt/**' - sdk-js: - - 'libs/sdk-js/**' deps: - '**/pyproject.toml' - '**/uv.lock' @@ -152,68 +149,16 @@ jobs: uses: ./.github/workflows/_integration_test.yml secrets: inherit - lint-js: - needs: changes - if: needs.changes.outputs.sdk-js == 'true' - runs-on: ubuntu-latest - strategy: - matrix: - working-directory: - - "libs/sdk-js" - defaults: - run: - working-directory: ${{ matrix.working-directory }} - steps: - - uses: actions/checkout@v4 - - name: Setup Node.js (LTS) - uses: actions/setup-node@v4 - with: - node-version: "20" - cache: "yarn" - cache-dependency-path: ${{ matrix.working-directory }}/yarn.lock - - name: Install dependencies - run: yarn install - - name: Run lint - run: yarn lint - - name: Build - run: yarn build - - test-js: - needs: changes - if: needs.changes.outputs.sdk-js == 'true' - runs-on: ubuntu-latest - strategy: - matrix: - working-directory: - - "libs/sdk-js" - defaults: - run: - working-directory: ${{ matrix.working-directory }} - steps: - - uses: actions/checkout@v4 - - name: Setup Node.js (LTS) - uses: actions/setup-node@v4 - with: - node-version: "20" - cache: "yarn" - cache-dependency-path: ${{ matrix.working-directory }}/yarn.lock - - name: Install dependencies - run: yarn install - - name: Run tests - run: yarn test - ci_success: name: "CI Success" needs: [ lint, - lint-js, test, test-langgraph, check-sdk-methods, check-schema, integration-test, - test-js, ] if: | always() diff --git a/.github/workflows/release_js.yml b/.github/workflows/release_js.yml deleted file mode 100644 index bce535330..000000000 --- a/.github/workflows/release_js.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: JS Release - -on: - workflow_dispatch: - -permissions: - contents: read - -jobs: - publish: - # Disallow publishing from branches that aren't `main`. - if: github.ref == 'refs/heads/main' - runs-on: ubuntu-latest - - strategy: - matrix: - working-directory: - - "libs/sdk-js" - - defaults: - run: - working-directory: ${{ matrix.working-directory }} - - steps: - - uses: actions/checkout@v4 - # JS Build - - name: Use Node.js - uses: actions/setup-node@v4 - with: - node-version: "20" - cache: "yarn" - cache-dependency-path: ${{ matrix.working-directory }}/yarn.lock - - - name: Install dependencies - run: yarn install - - name: Build - run: yarn build - - name: Publish package to NPM - run: | - echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > .npmrc - npm publish \ No newline at end of file diff --git a/docs/.gitignore b/docs/.gitignore index f4d716881..540583df2 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -1,4 +1,3 @@ site/ -docs/cloud/reference/sdk/js_ts_sdk_ref.md .vercel diff --git a/docs/Makefile b/docs/Makefile index 5696fbc6f..95d256241 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -1,10 +1,4 @@ -.PHONY: lint-docs format-docs build-docs serve-docs serve-clean-docs clean-docs codespell build-typedoc llms-text build-prebuilt tests - -build-typedoc: - cd ../libs/sdk-js && yarn install --include-dev && yarn typedoc - cd ../libs/sdk-js && yarn --silent concat-md --decrease-title-levels --ignore=js_ts_sdk_ref.md --start-title-level-at 2 docs > ../../docs/docs/cloud/reference/sdk/js_ts_sdk_ref.md 2>/dev/null - # Add links to the monorepo - sed -e '1,10s|@langchain/langgraph-sdk|[@langchain/langgraph-sdk](https://github.com/langchain-ai/langgraph/tree/main/libs/sdk-js)|g' docs/cloud/reference/sdk/js_ts_sdk_ref.md > temp_file && mv temp_file docs/cloud/reference/sdk/js_ts_sdk_ref.md +.PHONY: lint-docs format-docs build-docs serve-docs serve-clean-docs clean-docs codespell llms-text build-prebuilt tests build-prebuilt: # Use to create an update to date prebuilt page. @@ -21,7 +15,7 @@ build-prebuilt: fi uv run python -m _scripts.third_party_page.create_third_party_page stats.yml docs/agents/prebuilt.md --language python -build-docs: build-typedoc build-prebuilt +build-docs: build-prebuilt uv run python -m mkdocs build --clean -f mkdocs.yml --strict llms-text: @@ -45,7 +39,7 @@ vercel-build-docs: install-vercel-deps serve-clean-docs: clean-docs uv run python -m mkdocs serve -c -f mkdocs.yml --strict -w ../libs/langgraph -serve-docs: build-typedoc +serve-docs: uv run python -m mkdocs serve -f mkdocs.yml -w ../libs/langgraph -w ../libs/checkpoint -w ../libs/sdk-py --dirty clean-docs: diff --git a/docs/docs/cloud/reference/sdk/js_ts_sdk_ref.md b/docs/docs/cloud/reference/sdk/js_ts_sdk_ref.md new file mode 100644 index 000000000..e90a54cad --- /dev/null +++ b/docs/docs/cloud/reference/sdk/js_ts_sdk_ref.md @@ -0,0 +1,3403 @@ + + + +**[@langchain/langgraph-sdk](https://github.com/langchain-ai/langgraph/tree/main/libs/sdk-js)** + +*** + +## [@langchain/langgraph-sdk](https://github.com/langchain-ai/langgraph/tree/main/libs/sdk-js) + +### Classes + +- [AssistantsClient](#classesassistantsclientmd) +- [Client](#classesclientmd) +- [CronsClient](#classescronsclientmd) +- [RunsClient](#classesrunsclientmd) +- [StoreClient](#classesstoreclientmd) +- [ThreadsClient](#classesthreadsclientmd) + +### Interfaces + +- [ClientConfig](#interfacesclientconfigmd) + +### Functions + +- [getApiKey](#functionsgetapikeymd) + + + + +**@langchain/langgraph-sdk** + +*** + +## @langchain/langgraph-sdk/auth + +### Classes + +- [Auth](#authclassesauthmd) +- [HTTPException](#authclasseshttpexceptionmd) + +### Interfaces + +- [AuthEventValueMap](#authinterfacesautheventvaluemapmd) + +### Type Aliases + +- [AuthFilters](#authtype-aliasesauthfiltersmd) + + + + +[**@langchain/langgraph-sdk**](#authreadmemd) + +*** + +[@langchain/langgraph-sdk](#authreadmemd) / Auth + +## Class: Auth\ + +Defined in: [src/auth/index.ts:11](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/auth/index.ts#L11) + +### Type Parameters + +• **TExtra** = \{\} + +• **TAuthReturn** *extends* `BaseAuthReturn` = `BaseAuthReturn` + +• **TUser** *extends* `BaseUser` = `ToUserLike`\<`TAuthReturn`\> + +### Constructors + +#### new Auth() + +> **new Auth**\<`TExtra`, `TAuthReturn`, `TUser`\>(): [`Auth`](#authclassesauthmd)\<`TExtra`, `TAuthReturn`, `TUser`\> + +##### Returns + +[`Auth`](#authclassesauthmd)\<`TExtra`, `TAuthReturn`, `TUser`\> + +### Methods + +#### authenticate() + +> **authenticate**\<`T`\>(`cb`): [`Auth`](#authclassesauthmd)\<`TExtra`, `T`\> + +Defined in: [src/auth/index.ts:25](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/auth/index.ts#L25) + +##### Type Parameters + +• **T** *extends* `BaseAuthReturn` + +##### Parameters + +###### cb + +`AuthenticateCallback`\<`T`\> + +##### Returns + +[`Auth`](#authclassesauthmd)\<`TExtra`, `T`\> + +*** + +#### on() + +> **on**\<`T`\>(`event`, `callback`): `this` + +Defined in: [src/auth/index.ts:32](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/auth/index.ts#L32) + +##### Type Parameters + +• **T** *extends* `CallbackEvent` + +##### Parameters + +###### event + +`T` + +###### callback + +`OnCallback`\<`T`, `TUser`\> + +##### Returns + +`this` + + + + +[**@langchain/langgraph-sdk**](#authreadmemd) + +*** + +[@langchain/langgraph-sdk](#authreadmemd) / HTTPException + +## Class: HTTPException + +Defined in: [src/auth/error.ts:66](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/auth/error.ts#L66) + +### Extends + +- `Error` + +### Constructors + +#### new HTTPException() + +> **new HTTPException**(`status`, `options`?): [`HTTPException`](#authclasseshttpexceptionmd) + +Defined in: [src/auth/error.ts:70](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/auth/error.ts#L70) + +##### Parameters + +###### status + +`number` + +###### options? + +####### cause? + +`unknown` + +####### headers? + +`HeadersInit` + +####### message? + +`string` + +##### Returns + +[`HTTPException`](#authclasseshttpexceptionmd) + +##### Overrides + +`Error.constructor` + +### Properties + +#### cause? + +> `optional` **cause**: `unknown` + +Defined in: node\_modules/typescript/lib/lib.es2022.error.d.ts:24 + +##### Inherited from + +`Error.cause` + +*** + +#### headers + +> **headers**: `HeadersInit` + +Defined in: [src/auth/error.ts:68](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/auth/error.ts#L68) + +*** + +#### message + +> **message**: `string` + +Defined in: node\_modules/typescript/lib/lib.es5.d.ts:1077 + +##### Inherited from + +`Error.message` + +*** + +#### name + +> **name**: `string` + +Defined in: node\_modules/typescript/lib/lib.es5.d.ts:1076 + +##### Inherited from + +`Error.name` + +*** + +#### stack? + +> `optional` **stack**: `string` + +Defined in: node\_modules/typescript/lib/lib.es5.d.ts:1078 + +##### Inherited from + +`Error.stack` + +*** + +#### status + +> **status**: `number` + +Defined in: [src/auth/error.ts:67](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/auth/error.ts#L67) + +*** + +#### prepareStackTrace()? + +> `static` `optional` **prepareStackTrace**: (`err`, `stackTraces`) => `any` + +Defined in: node\_modules/@types/node/globals.d.ts:28 + +Optional override for formatting stack traces + +##### Parameters + +###### err + +`Error` + +###### stackTraces + +`CallSite`[] + +##### Returns + +`any` + +##### See + +https://v8.dev/docs/stack-trace-api#customizing-stack-traces + +##### Inherited from + +`Error.prepareStackTrace` + +*** + +#### stackTraceLimit + +> `static` **stackTraceLimit**: `number` + +Defined in: node\_modules/@types/node/globals.d.ts:30 + +##### Inherited from + +`Error.stackTraceLimit` + +### Methods + +#### captureStackTrace() + +> `static` **captureStackTrace**(`targetObject`, `constructorOpt`?): `void` + +Defined in: node\_modules/@types/node/globals.d.ts:21 + +Create .stack property on a target object + +##### Parameters + +###### targetObject + +`object` + +###### constructorOpt? + +`Function` + +##### Returns + +`void` + +##### Inherited from + +`Error.captureStackTrace` + + + + +[**@langchain/langgraph-sdk**](#authreadmemd) + +*** + +[@langchain/langgraph-sdk](#authreadmemd) / AuthEventValueMap + +## Interface: AuthEventValueMap + +Defined in: [src/auth/types.ts:218](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/auth/types.ts#L218) + +### Properties + +#### assistants:create + +> **assistants:create**: `object` + +Defined in: [src/auth/types.ts:226](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/auth/types.ts#L226) + +##### assistant\_id? + +> `optional` **assistant\_id**: `Maybe`\<`string`\> + +##### config? + +> `optional` **config**: `Maybe`\<`AssistantConfig`\> + +##### graph\_id + +> **graph\_id**: `string` + +##### if\_exists? + +> `optional` **if\_exists**: `Maybe`\<`"raise"` \| `"do_nothing"`\> + +##### metadata? + +> `optional` **metadata**: `Maybe`\<`Record`\<`string`, `unknown`\>\> + +##### name? + +> `optional` **name**: `Maybe`\<`string`\> + +*** + +#### assistants:delete + +> **assistants:delete**: `object` + +Defined in: [src/auth/types.ts:229](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/auth/types.ts#L229) + +##### assistant\_id + +> **assistant\_id**: `string` + +*** + +#### assistants:read + +> **assistants:read**: `object` + +Defined in: [src/auth/types.ts:227](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/auth/types.ts#L227) + +##### assistant\_id + +> **assistant\_id**: `string` + +##### metadata? + +> `optional` **metadata**: `Maybe`\<`Record`\<`string`, `unknown`\>\> + +*** + +#### assistants:search + +> **assistants:search**: `object` + +Defined in: [src/auth/types.ts:230](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/auth/types.ts#L230) + +##### graph\_id? + +> `optional` **graph\_id**: `Maybe`\<`string`\> + +##### limit? + +> `optional` **limit**: `Maybe`\<`number`\> + +##### metadata? + +> `optional` **metadata**: `Maybe`\<`Record`\<`string`, `unknown`\>\> + +##### offset? + +> `optional` **offset**: `Maybe`\<`number`\> + +*** + +#### assistants:update + +> **assistants:update**: `object` + +Defined in: [src/auth/types.ts:228](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/auth/types.ts#L228) + +##### assistant\_id + +> **assistant\_id**: `string` + +##### config? + +> `optional` **config**: `Maybe`\<`AssistantConfig`\> + +##### graph\_id? + +> `optional` **graph\_id**: `Maybe`\<`string`\> + +##### metadata? + +> `optional` **metadata**: `Maybe`\<`Record`\<`string`, `unknown`\>\> + +##### name? + +> `optional` **name**: `Maybe`\<`string`\> + +##### version? + +> `optional` **version**: `Maybe`\<`number`\> + +*** + +#### crons:create + +> **crons:create**: `object` + +Defined in: [src/auth/types.ts:232](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/auth/types.ts#L232) + +##### cron\_id? + +> `optional` **cron\_id**: `Maybe`\<`string`\> + +##### end\_time? + +> `optional` **end\_time**: `Maybe`\<`string`\> + +##### payload? + +> `optional` **payload**: `Maybe`\<`Record`\<`string`, `unknown`\>\> + +##### schedule + +> **schedule**: `string` + +##### thread\_id? + +> `optional` **thread\_id**: `Maybe`\<`string`\> + +##### user\_id? + +> `optional` **user\_id**: `Maybe`\<`string`\> + +*** + +#### crons:delete + +> **crons:delete**: `object` + +Defined in: [src/auth/types.ts:235](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/auth/types.ts#L235) + +##### cron\_id + +> **cron\_id**: `string` + +*** + +#### crons:read + +> **crons:read**: `object` + +Defined in: [src/auth/types.ts:233](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/auth/types.ts#L233) + +##### cron\_id + +> **cron\_id**: `string` + +*** + +#### crons:search + +> **crons:search**: `object` + +Defined in: [src/auth/types.ts:236](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/auth/types.ts#L236) + +##### assistant\_id? + +> `optional` **assistant\_id**: `Maybe`\<`string`\> + +##### limit? + +> `optional` **limit**: `Maybe`\<`number`\> + +##### offset? + +> `optional` **offset**: `Maybe`\<`number`\> + +##### thread\_id? + +> `optional` **thread\_id**: `Maybe`\<`string`\> + +*** + +#### crons:update + +> **crons:update**: `object` + +Defined in: [src/auth/types.ts:234](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/auth/types.ts#L234) + +##### cron\_id + +> **cron\_id**: `string` + +##### payload? + +> `optional` **payload**: `Maybe`\<`Record`\<`string`, `unknown`\>\> + +##### schedule? + +> `optional` **schedule**: `Maybe`\<`string`\> + +*** + +#### store:delete + +> **store:delete**: `object` + +Defined in: [src/auth/types.ts:242](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/auth/types.ts#L242) + +##### key + +> **key**: `string` + +##### namespace? + +> `optional` **namespace**: `Maybe`\<`string`[]\> + +*** + +#### store:get + +> **store:get**: `object` + +Defined in: [src/auth/types.ts:239](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/auth/types.ts#L239) + +##### key + +> **key**: `string` + +##### namespace + +> **namespace**: `Maybe`\<`string`[]\> + +*** + +#### store:list\_namespaces + +> **store:list\_namespaces**: `object` + +Defined in: [src/auth/types.ts:241](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/auth/types.ts#L241) + +##### limit? + +> `optional` **limit**: `Maybe`\<`number`\> + +##### max\_depth? + +> `optional` **max\_depth**: `Maybe`\<`number`\> + +##### namespace? + +> `optional` **namespace**: `Maybe`\<`string`[]\> + +##### offset? + +> `optional` **offset**: `Maybe`\<`number`\> + +##### suffix? + +> `optional` **suffix**: `Maybe`\<`string`[]\> + +*** + +#### store:put + +> **store:put**: `object` + +Defined in: [src/auth/types.ts:238](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/auth/types.ts#L238) + +##### key + +> **key**: `string` + +##### namespace + +> **namespace**: `string`[] + +##### value + +> **value**: `Record`\<`string`, `unknown`\> + +*** + +#### store:search + +> **store:search**: `object` + +Defined in: [src/auth/types.ts:240](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/auth/types.ts#L240) + +##### filter? + +> `optional` **filter**: `Maybe`\<`Record`\<`string`, `unknown`\>\> + +##### limit? + +> `optional` **limit**: `Maybe`\<`number`\> + +##### namespace? + +> `optional` **namespace**: `Maybe`\<`string`[]\> + +##### offset? + +> `optional` **offset**: `Maybe`\<`number`\> + +##### query? + +> `optional` **query**: `Maybe`\<`string`\> + +*** + +#### threads:create + +> **threads:create**: `object` + +Defined in: [src/auth/types.ts:219](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/auth/types.ts#L219) + +##### if\_exists? + +> `optional` **if\_exists**: `Maybe`\<`"raise"` \| `"do_nothing"`\> + +##### metadata? + +> `optional` **metadata**: `Maybe`\<`Record`\<`string`, `unknown`\>\> + +##### thread\_id? + +> `optional` **thread\_id**: `Maybe`\<`string`\> + +*** + +#### threads:create\_run + +> **threads:create\_run**: `object` + +Defined in: [src/auth/types.ts:224](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/auth/types.ts#L224) + +##### after\_seconds? + +> `optional` **after\_seconds**: `Maybe`\<`number`\> + +##### assistant\_id + +> **assistant\_id**: `string` + +##### if\_not\_exists? + +> `optional` **if\_not\_exists**: `Maybe`\<`"reject"` \| `"create"`\> + +##### kwargs + +> **kwargs**: `Record`\<`string`, `unknown`\> + +##### metadata? + +> `optional` **metadata**: `Maybe`\<`Record`\<`string`, `unknown`\>\> + +##### multitask\_strategy? + +> `optional` **multitask\_strategy**: `Maybe`\<`"reject"` \| `"interrupt"` \| `"rollback"` \| `"enqueue"`\> + +##### prevent\_insert\_if\_inflight? + +> `optional` **prevent\_insert\_if\_inflight**: `Maybe`\<`boolean`\> + +##### run\_id + +> **run\_id**: `string` + +##### status + +> **status**: `Maybe`\<`"pending"` \| `"running"` \| `"error"` \| `"success"` \| `"timeout"` \| `"interrupted"`\> + +##### thread\_id? + +> `optional` **thread\_id**: `Maybe`\<`string`\> + +*** + +#### threads:delete + +> **threads:delete**: `object` + +Defined in: [src/auth/types.ts:222](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/auth/types.ts#L222) + +##### run\_id? + +> `optional` **run\_id**: `Maybe`\<`string`\> + +##### thread\_id? + +> `optional` **thread\_id**: `Maybe`\<`string`\> + +*** + +#### threads:read + +> **threads:read**: `object` + +Defined in: [src/auth/types.ts:220](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/auth/types.ts#L220) + +##### thread\_id? + +> `optional` **thread\_id**: `Maybe`\<`string`\> + +*** + +#### threads:search + +> **threads:search**: `object` + +Defined in: [src/auth/types.ts:223](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/auth/types.ts#L223) + +##### limit? + +> `optional` **limit**: `Maybe`\<`number`\> + +##### metadata? + +> `optional` **metadata**: `Maybe`\<`Record`\<`string`, `unknown`\>\> + +##### offset? + +> `optional` **offset**: `Maybe`\<`number`\> + +##### status? + +> `optional` **status**: `Maybe`\<`"error"` \| `"interrupted"` \| `"idle"` \| `"busy"` \| `string` & `object`\> + +##### thread\_id? + +> `optional` **thread\_id**: `Maybe`\<`string`\> + +##### values? + +> `optional` **values**: `Maybe`\<`Record`\<`string`, `unknown`\>\> + +*** + +#### threads:update + +> **threads:update**: `object` + +Defined in: [src/auth/types.ts:221](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/auth/types.ts#L221) + +##### action? + +> `optional` **action**: `Maybe`\<`"interrupt"` \| `"rollback"`\> + +##### metadata? + +> `optional` **metadata**: `Maybe`\<`Record`\<`string`, `unknown`\>\> + +##### thread\_id? + +> `optional` **thread\_id**: `Maybe`\<`string`\> + + + + +[**@langchain/langgraph-sdk**](#authreadmemd) + +*** + +[@langchain/langgraph-sdk](#authreadmemd) / AuthFilters + +## Type Alias: AuthFilters\ + +> **AuthFilters**\<`TKey`\>: \{ \[key in TKey\]: string \| \{ \[op in "$contains" \| "$eq"\]?: string \} \} + +Defined in: [src/auth/types.ts:367](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/auth/types.ts#L367) + +### Type Parameters + +• **TKey** *extends* `string` \| `number` \| `symbol` + + + + +[**@langchain/langgraph-sdk**](#readmemd) + +*** + +[@langchain/langgraph-sdk](#readmemd) / AssistantsClient + +## Class: AssistantsClient + +Defined in: [client.ts:294](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L294) + +### Extends + +- `BaseClient` + +### Constructors + +#### new AssistantsClient() + +> **new AssistantsClient**(`config`?): [`AssistantsClient`](#classesassistantsclientmd) + +Defined in: [client.ts:88](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L88) + +##### Parameters + +###### config? + +[`ClientConfig`](#interfacesclientconfigmd) + +##### Returns + +[`AssistantsClient`](#classesassistantsclientmd) + +##### Inherited from + +`BaseClient.constructor` + +### Methods + +#### create() + +> **create**(`payload`): `Promise`\<`Assistant`\> + +Defined in: [client.ts:359](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L359) + +Create a new assistant. + +##### Parameters + +###### payload + +Payload for creating an assistant. + +####### assistantId? + +`string` + +####### config? + +`Config` + +####### description? + +`string` + +####### graphId + +`string` + +####### ifExists? + +`OnConflictBehavior` + +####### metadata? + +`Metadata` + +####### name? + +`string` + +##### Returns + +`Promise`\<`Assistant`\> + +The created assistant. + +*** + +#### delete() + +> **delete**(`assistantId`): `Promise`\<`void`\> + +Defined in: [client.ts:415](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L415) + +Delete an assistant. + +##### Parameters + +###### assistantId + +`string` + +ID of the assistant. + +##### Returns + +`Promise`\<`void`\> + +*** + +#### get() + +> **get**(`assistantId`): `Promise`\<`Assistant`\> + +Defined in: [client.ts:301](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L301) + +Get an assistant by ID. + +##### Parameters + +###### assistantId + +`string` + +The ID of the assistant. + +##### Returns + +`Promise`\<`Assistant`\> + +Assistant + +*** + +#### getGraph() + +> **getGraph**(`assistantId`, `options`?): `Promise`\<`AssistantGraph`\> + +Defined in: [client.ts:311](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L311) + +Get the JSON representation of the graph assigned to a runnable + +##### Parameters + +###### assistantId + +`string` + +The ID of the assistant. + +###### options? + +####### xray? + +`number` \| `boolean` + +Whether to include subgraphs in the serialized graph representation. If an integer value is provided, only subgraphs with a depth less than or equal to the value will be included. + +##### Returns + +`Promise`\<`AssistantGraph`\> + +Serialized graph + +*** + +#### getSchemas() + +> **getSchemas**(`assistantId`): `Promise`\<`GraphSchema`\> + +Defined in: [client.ts:325](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L325) + +Get the state and config schema of the graph assigned to a runnable + +##### Parameters + +###### assistantId + +`string` + +The ID of the assistant. + +##### Returns + +`Promise`\<`GraphSchema`\> + +Graph schema + +*** + +#### getSubgraphs() + +> **getSubgraphs**(`assistantId`, `options`?): `Promise`\<`Subgraphs`\> + +Defined in: [client.ts:336](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L336) + +Get the schemas of an assistant by ID. + +##### Parameters + +###### assistantId + +`string` + +The ID of the assistant to get the schema of. + +###### options? + +Additional options for getting subgraphs, such as namespace or recursion extraction. + +####### namespace? + +`string` + +####### recurse? + +`boolean` + +##### Returns + +`Promise`\<`Subgraphs`\> + +The subgraphs of the assistant. + +*** + +#### getVersions() + +> **getVersions**(`assistantId`, `payload`?): `Promise`\<`AssistantVersion`[]\> + +Defined in: [client.ts:453](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L453) + +List all versions of an assistant. + +##### Parameters + +###### assistantId + +`string` + +ID of the assistant. + +###### payload? + +####### limit? + +`number` + +####### metadata? + +`Metadata` + +####### offset? + +`number` + +##### Returns + +`Promise`\<`AssistantVersion`[]\> + +List of assistant versions. + +*** + +#### search() + +> **search**(`query`?): `Promise`\<`Assistant`[]\> + +Defined in: [client.ts:426](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L426) + +List assistants. + +##### Parameters + +###### query? + +Query options. + +####### graphId? + +`string` + +####### limit? + +`number` + +####### metadata? + +`Metadata` + +####### offset? + +`number` + +####### sortBy? + +`AssistantSortBy` + +####### sortOrder? + +`SortOrder` + +##### Returns + +`Promise`\<`Assistant`[]\> + +List of assistants. + +*** + +#### setLatest() + +> **setLatest**(`assistantId`, `version`): `Promise`\<`Assistant`\> + +Defined in: [client.ts:481](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L481) + +Change the version of an assistant. + +##### Parameters + +###### assistantId + +`string` + +ID of the assistant. + +###### version + +`number` + +The version to change to. + +##### Returns + +`Promise`\<`Assistant`\> + +The updated assistant. + +*** + +#### update() + +> **update**(`assistantId`, `payload`): `Promise`\<`Assistant`\> + +Defined in: [client.ts:388](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L388) + +Update an assistant. + +##### Parameters + +###### assistantId + +`string` + +ID of the assistant. + +###### payload + +Payload for updating the assistant. + +####### config? + +`Config` + +####### description? + +`string` + +####### graphId? + +`string` + +####### metadata? + +`Metadata` + +####### name? + +`string` + +##### Returns + +`Promise`\<`Assistant`\> + +The updated assistant. + + + + +[**@langchain/langgraph-sdk**](#readmemd) + +*** + +[@langchain/langgraph-sdk](#readmemd) / Client + +## Class: Client\ + +Defined in: [client.ts:1448](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L1448) + +### Type Parameters + +• **TStateType** = `DefaultValues` + +• **TUpdateType** = `TStateType` + +• **TCustomEventType** = `unknown` + +### Constructors + +#### new Client() + +> **new Client**\<`TStateType`, `TUpdateType`, `TCustomEventType`\>(`config`?): [`Client`](#classesclientmd)\<`TStateType`, `TUpdateType`, `TCustomEventType`\> + +Defined in: [client.ts:1484](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L1484) + +##### Parameters + +###### config? + +[`ClientConfig`](#interfacesclientconfigmd) + +##### Returns + +[`Client`](#classesclientmd)\<`TStateType`, `TUpdateType`, `TCustomEventType`\> + +### Properties + +#### ~ui + +> **~ui**: `UiClient` + +Defined in: [client.ts:1482](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L1482) + +**`Internal`** + +The client for interacting with the UI. + Used by LoadExternalComponent and the API might change in the future. + +*** + +#### assistants + +> **assistants**: [`AssistantsClient`](#classesassistantsclientmd) + +Defined in: [client.ts:1456](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L1456) + +The client for interacting with assistants. + +*** + +#### crons + +> **crons**: [`CronsClient`](#classescronsclientmd) + +Defined in: [client.ts:1471](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L1471) + +The client for interacting with cron runs. + +*** + +#### runs + +> **runs**: [`RunsClient`](#classesrunsclientmd)\<`TStateType`, `TUpdateType`, `TCustomEventType`\> + +Defined in: [client.ts:1466](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L1466) + +The client for interacting with runs. + +*** + +#### store + +> **store**: [`StoreClient`](#classesstoreclientmd) + +Defined in: [client.ts:1476](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L1476) + +The client for interacting with the KV store. + +*** + +#### threads + +> **threads**: [`ThreadsClient`](#classesthreadsclientmd)\<`TStateType`, `TUpdateType`\> + +Defined in: [client.ts:1461](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L1461) + +The client for interacting with threads. + + + + +[**@langchain/langgraph-sdk**](#readmemd) + +*** + +[@langchain/langgraph-sdk](#readmemd) / CronsClient + +## Class: CronsClient + +Defined in: [client.ts:197](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L197) + +### Extends + +- `BaseClient` + +### Constructors + +#### new CronsClient() + +> **new CronsClient**(`config`?): [`CronsClient`](#classescronsclientmd) + +Defined in: [client.ts:88](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L88) + +##### Parameters + +###### config? + +[`ClientConfig`](#interfacesclientconfigmd) + +##### Returns + +[`CronsClient`](#classescronsclientmd) + +##### Inherited from + +`BaseClient.constructor` + +### Methods + +#### create() + +> **create**(`assistantId`, `payload`?): `Promise`\<`CronCreateResponse`\> + +Defined in: [client.ts:238](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L238) + +##### Parameters + +###### assistantId + +`string` + +Assistant ID to use for this cron job. + +###### payload? + +`CronsCreatePayload` + +Payload for creating a cron job. + +##### Returns + +`Promise`\<`CronCreateResponse`\> + +*** + +#### createForThread() + +> **createForThread**(`threadId`, `assistantId`, `payload`?): `Promise`\<`CronCreateForThreadResponse`\> + +Defined in: [client.ts:205](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L205) + +##### Parameters + +###### threadId + +`string` + +The ID of the thread. + +###### assistantId + +`string` + +Assistant ID to use for this cron job. + +###### payload? + +`CronsCreatePayload` + +Payload for creating a cron job. + +##### Returns + +`Promise`\<`CronCreateForThreadResponse`\> + +The created background run. + +*** + +#### delete() + +> **delete**(`cronId`): `Promise`\<`void`\> + +Defined in: [client.ts:265](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L265) + +##### Parameters + +###### cronId + +`string` + +Cron ID of Cron job to delete. + +##### Returns + +`Promise`\<`void`\> + +*** + +#### search() + +> **search**(`query`?): `Promise`\<`Cron`[]\> + +Defined in: [client.ts:276](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L276) + +##### Parameters + +###### query? + +Query options. + +####### assistantId? + +`string` + +####### limit? + +`number` + +####### offset? + +`number` + +####### threadId? + +`string` + +##### Returns + +`Promise`\<`Cron`[]\> + +List of crons. + + + + +[**@langchain/langgraph-sdk**](#readmemd) + +*** + +[@langchain/langgraph-sdk](#readmemd) / RunsClient + +## Class: RunsClient\ + +Defined in: [client.ts:776](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L776) + +### Extends + +- `BaseClient` + +### Type Parameters + +• **TStateType** = `DefaultValues` + +• **TUpdateType** = `TStateType` + +• **TCustomEventType** = `unknown` + +### Constructors + +#### new RunsClient() + +> **new RunsClient**\<`TStateType`, `TUpdateType`, `TCustomEventType`\>(`config`?): [`RunsClient`](#classesrunsclientmd)\<`TStateType`, `TUpdateType`, `TCustomEventType`\> + +Defined in: [client.ts:88](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L88) + +##### Parameters + +###### config? + +[`ClientConfig`](#interfacesclientconfigmd) + +##### Returns + +[`RunsClient`](#classesrunsclientmd)\<`TStateType`, `TUpdateType`, `TCustomEventType`\> + +##### Inherited from + +`BaseClient.constructor` + +### Methods + +#### cancel() + +> **cancel**(`threadId`, `runId`, `wait`, `action`): `Promise`\<`void`\> + +Defined in: [client.ts:1063](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L1063) + +Cancel a run. + +##### Parameters + +###### threadId + +`string` + +The ID of the thread. + +###### runId + +`string` + +The ID of the run. + +###### wait + +`boolean` = `false` + +Whether to block when canceling + +###### action + +`CancelAction` = `"interrupt"` + +Action to take when cancelling the run. Possible values are `interrupt` or `rollback`. Default is `interrupt`. + +##### Returns + +`Promise`\<`void`\> + +*** + +#### create() + +> **create**(`threadId`, `assistantId`, `payload`?): `Promise`\<`Run`\> + +Defined in: [client.ts:885](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L885) + +Create a run. + +##### Parameters + +###### threadId + +`string` + +The ID of the thread. + +###### assistantId + +`string` + +Assistant ID to use for this run. + +###### payload? + +`RunsCreatePayload` + +Payload for creating a run. + +##### Returns + +`Promise`\<`Run`\> + +The created run. + +*** + +#### createBatch() + +> **createBatch**(`payloads`): `Promise`\<`Run`[]\> + +Defined in: [client.ts:921](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L921) + +Create a batch of stateless background runs. + +##### Parameters + +###### payloads + +`RunsCreatePayload` & `object`[] + +An array of payloads for creating runs. + +##### Returns + +`Promise`\<`Run`[]\> + +An array of created runs. + +*** + +#### delete() + +> **delete**(`threadId`, `runId`): `Promise`\<`void`\> + +Defined in: [client.ts:1157](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L1157) + +Delete a run. + +##### Parameters + +###### threadId + +`string` + +The ID of the thread. + +###### runId + +`string` + +The ID of the run. + +##### Returns + +`Promise`\<`void`\> + +*** + +#### get() + +> **get**(`threadId`, `runId`): `Promise`\<`Run`\> + +Defined in: [client.ts:1050](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L1050) + +Get a run by ID. + +##### Parameters + +###### threadId + +`string` + +The ID of the thread. + +###### runId + +`string` + +The ID of the run. + +##### Returns + +`Promise`\<`Run`\> + +The run. + +*** + +#### join() + +> **join**(`threadId`, `runId`, `options`?): `Promise`\<`void`\> + +Defined in: [client.ts:1085](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L1085) + +Block until a run is done. + +##### Parameters + +###### threadId + +`string` + +The ID of the thread. + +###### runId + +`string` + +The ID of the run. + +###### options? + +####### signal? + +`AbortSignal` + +##### Returns + +`Promise`\<`void`\> + +*** + +#### joinStream() + +> **joinStream**(`threadId`, `runId`, `options`?): `AsyncGenerator`\<\{ `data`: `any`; `event`: `StreamEvent`; \}\> + +Defined in: [client.ts:1111](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L1111) + +Stream output from a run in real-time, until the run is done. +Output is not buffered, so any output produced before this call will +not be received here. + +##### Parameters + +###### threadId + +`string` + +The ID of the thread. + +###### runId + +`string` + +The ID of the run. + +###### options? + +Additional options for controlling the stream behavior: + - signal: An AbortSignal that can be used to cancel the stream request + - cancelOnDisconnect: When true, automatically cancels the run if the client disconnects from the stream + - streamMode: Controls what types of events to receive from the stream (can be a single mode or array of modes) + Must be a subset of the stream modes passed when creating the run. Background runs default to having the union of all + stream modes enabled. + +`AbortSignal` | \{ `cancelOnDisconnect`: `boolean`; `signal`: `AbortSignal`; `streamMode`: `StreamMode` \| `StreamMode`[]; \} + +##### Returns + +`AsyncGenerator`\<\{ `data`: `any`; `event`: `StreamEvent`; \}\> + +An async generator yielding stream parts. + +*** + +#### list() + +> **list**(`threadId`, `options`?): `Promise`\<`Run`[]\> + +Defined in: [client.ts:1013](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L1013) + +List all runs for a thread. + +##### Parameters + +###### threadId + +`string` + +The ID of the thread. + +###### options? + +Filtering and pagination options. + +####### limit? + +`number` + +Maximum number of runs to return. +Defaults to 10 + +####### offset? + +`number` + +Offset to start from. +Defaults to 0. + +####### status? + +`RunStatus` + +Status of the run to filter by. + +##### Returns + +`Promise`\<`Run`[]\> + +List of runs. + +*** + +#### stream() + +Create a run and stream the results. + +##### Param + +The ID of the thread. + +##### Param + +Assistant ID to use for this run. + +##### Param + +Payload for creating a run. + +##### Call Signature + +> **stream**\<`TStreamMode`, `TSubgraphs`\>(`threadId`, `assistantId`, `payload`?): `TypedAsyncGenerator`\<`TStreamMode`, `TSubgraphs`, `TStateType`, `TUpdateType`, `TCustomEventType`\> + +Defined in: [client.ts:781](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L781) + +###### Type Parameters + +• **TStreamMode** *extends* `StreamMode` \| `StreamMode`[] = `StreamMode` + +• **TSubgraphs** *extends* `boolean` = `false` + +###### Parameters + +####### threadId + +`null` + +####### assistantId + +`string` + +####### payload? + +`Omit`\<`RunsStreamPayload`\<`TStreamMode`, `TSubgraphs`\>, `"multitaskStrategy"` \| `"onCompletion"`\> + +###### Returns + +`TypedAsyncGenerator`\<`TStreamMode`, `TSubgraphs`, `TStateType`, `TUpdateType`, `TCustomEventType`\> + +##### Call Signature + +> **stream**\<`TStreamMode`, `TSubgraphs`\>(`threadId`, `assistantId`, `payload`?): `TypedAsyncGenerator`\<`TStreamMode`, `TSubgraphs`, `TStateType`, `TUpdateType`, `TCustomEventType`\> + +Defined in: [client.ts:799](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L799) + +###### Type Parameters + +• **TStreamMode** *extends* `StreamMode` \| `StreamMode`[] = `StreamMode` + +• **TSubgraphs** *extends* `boolean` = `false` + +###### Parameters + +####### threadId + +`string` + +####### assistantId + +`string` + +####### payload? + +`RunsStreamPayload`\<`TStreamMode`, `TSubgraphs`\> + +###### Returns + +`TypedAsyncGenerator`\<`TStreamMode`, `TSubgraphs`, `TStateType`, `TUpdateType`, `TCustomEventType`\> + +*** + +#### wait() + +Create a run and wait for it to complete. + +##### Param + +The ID of the thread. + +##### Param + +Assistant ID to use for this run. + +##### Param + +Payload for creating a run. + +##### Call Signature + +> **wait**(`threadId`, `assistantId`, `payload`?): `Promise`\<`DefaultValues`\> + +Defined in: [client.ts:938](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L938) + +###### Parameters + +####### threadId + +`null` + +####### assistantId + +`string` + +####### payload? + +`Omit`\<`RunsWaitPayload`, `"multitaskStrategy"` \| `"onCompletion"`\> + +###### Returns + +`Promise`\<`DefaultValues`\> + +##### Call Signature + +> **wait**(`threadId`, `assistantId`, `payload`?): `Promise`\<`DefaultValues`\> + +Defined in: [client.ts:944](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L944) + +###### Parameters + +####### threadId + +`string` + +####### assistantId + +`string` + +####### payload? + +`RunsWaitPayload` + +###### Returns + +`Promise`\<`DefaultValues`\> + + + + +[**@langchain/langgraph-sdk**](#readmemd) + +*** + +[@langchain/langgraph-sdk](#readmemd) / StoreClient + +## Class: StoreClient + +Defined in: [client.ts:1175](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L1175) + +### Extends + +- `BaseClient` + +### Constructors + +#### new StoreClient() + +> **new StoreClient**(`config`?): [`StoreClient`](#classesstoreclientmd) + +Defined in: [client.ts:88](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L88) + +##### Parameters + +###### config? + +[`ClientConfig`](#interfacesclientconfigmd) + +##### Returns + +[`StoreClient`](#classesstoreclientmd) + +##### Inherited from + +`BaseClient.constructor` + +### Methods + +#### deleteItem() + +> **deleteItem**(`namespace`, `key`): `Promise`\<`void`\> + +Defined in: [client.ts:1296](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L1296) + +Delete an item. + +##### Parameters + +###### namespace + +`string`[] + +A list of strings representing the namespace path. + +###### key + +`string` + +The unique identifier for the item. + +##### Returns + +`Promise`\<`void`\> + +Promise + +*** + +#### getItem() + +> **getItem**(`namespace`, `key`, `options`?): `Promise`\<`null` \| `Item`\> + +Defined in: [client.ts:1252](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L1252) + +Retrieve a single item. + +##### Parameters + +###### namespace + +`string`[] + +A list of strings representing the namespace path. + +###### key + +`string` + +The unique identifier for the item. + +###### options? + +####### refreshTtl? + +`null` \| `boolean` + +Whether to refresh the TTL on this read operation. If null, uses the store's default behavior. + +##### Returns + +`Promise`\<`null` \| `Item`\> + +Promise + +##### Example + +```typescript +const item = await client.store.getItem( + ["documents", "user123"], + "item456", + { refreshTtl: true } +); +console.log(item); +// { +// namespace: ["documents", "user123"], +// key: "item456", +// value: { title: "My Document", content: "Hello World" }, +// createdAt: "2024-07-30T12:00:00Z", +// updatedAt: "2024-07-30T12:00:00Z" +// } +``` + +*** + +#### listNamespaces() + +> **listNamespaces**(`options`?): `Promise`\<`ListNamespaceResponse`\> + +Defined in: [client.ts:1392](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L1392) + +List namespaces with optional match conditions. + +##### Parameters + +###### options? + +####### limit? + +`number` + +Maximum number of namespaces to return (default is 100). + +####### maxDepth? + +`number` + +Optional integer specifying the maximum depth of namespaces to return. + +####### offset? + +`number` + +Number of namespaces to skip before returning results (default is 0). + +####### prefix? + +`string`[] + +Optional list of strings representing the prefix to filter namespaces. + +####### suffix? + +`string`[] + +Optional list of strings representing the suffix to filter namespaces. + +##### Returns + +`Promise`\<`ListNamespaceResponse`\> + +Promise + +*** + +#### putItem() + +> **putItem**(`namespace`, `key`, `value`, `options`?): `Promise`\<`void`\> + +Defined in: [client.ts:1196](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L1196) + +Store or update an item. + +##### Parameters + +###### namespace + +`string`[] + +A list of strings representing the namespace path. + +###### key + +`string` + +The unique identifier for the item within the namespace. + +###### value + +`Record`\<`string`, `any`\> + +A dictionary containing the item's data. + +###### options? + +####### index? + +`null` \| `false` \| `string`[] + +Controls search indexing - null (use defaults), false (disable), or list of field paths to index. + +####### ttl? + +`null` \| `number` + +Optional time-to-live in minutes for the item, or null for no expiration. + +##### Returns + +`Promise`\<`void`\> + +Promise + +##### Example + +```typescript +await client.store.putItem( + ["documents", "user123"], + "item456", + { title: "My Document", content: "Hello World" }, + { ttl: 60 } // expires in 60 minutes +); +``` + +*** + +#### searchItems() + +> **searchItems**(`namespacePrefix`, `options`?): `Promise`\<`SearchItemsResponse`\> + +Defined in: [client.ts:1347](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L1347) + +Search for items within a namespace prefix. + +##### Parameters + +###### namespacePrefix + +`string`[] + +List of strings representing the namespace prefix. + +###### options? + +####### filter? + +`Record`\<`string`, `any`\> + +Optional dictionary of key-value pairs to filter results. + +####### limit? + +`number` + +Maximum number of items to return (default is 10). + +####### offset? + +`number` + +Number of items to skip before returning results (default is 0). + +####### query? + +`string` + +Optional search query. + +####### refreshTtl? + +`null` \| `boolean` + +Whether to refresh the TTL on items returned by this search. If null, uses the store's default behavior. + +##### Returns + +`Promise`\<`SearchItemsResponse`\> + +Promise + +##### Example + +```typescript +const results = await client.store.searchItems( + ["documents"], + { + filter: { author: "John Doe" }, + limit: 5, + refreshTtl: true + } +); +console.log(results); +// { +// items: [ +// { +// namespace: ["documents", "user123"], +// key: "item789", +// value: { title: "Another Document", author: "John Doe" }, +// createdAt: "2024-07-30T12:00:00Z", +// updatedAt: "2024-07-30T12:00:00Z" +// }, +// // ... additional items ... +// ] +// } +``` + + + + +[**@langchain/langgraph-sdk**](#readmemd) + +*** + +[@langchain/langgraph-sdk](#readmemd) / ThreadsClient + +## Class: ThreadsClient\ + +Defined in: [client.ts:489](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L489) + +### Extends + +- `BaseClient` + +### Type Parameters + +• **TStateType** = `DefaultValues` + +• **TUpdateType** = `TStateType` + +### Constructors + +#### new ThreadsClient() + +> **new ThreadsClient**\<`TStateType`, `TUpdateType`\>(`config`?): [`ThreadsClient`](#classesthreadsclientmd)\<`TStateType`, `TUpdateType`\> + +Defined in: [client.ts:88](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L88) + +##### Parameters + +###### config? + +[`ClientConfig`](#interfacesclientconfigmd) + +##### Returns + +[`ThreadsClient`](#classesthreadsclientmd)\<`TStateType`, `TUpdateType`\> + +##### Inherited from + +`BaseClient.constructor` + +### Methods + +#### copy() + +> **copy**(`threadId`): `Promise`\<`Thread`\<`TStateType`\>\> + +Defined in: [client.ts:566](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L566) + +Copy an existing thread + +##### Parameters + +###### threadId + +`string` + +ID of the thread to be copied + +##### Returns + +`Promise`\<`Thread`\<`TStateType`\>\> + +Newly copied thread + +*** + +#### create() + +> **create**(`payload`?): `Promise`\<`Thread`\<`TStateType`\>\> + +Defined in: [client.ts:511](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L511) + +Create a new thread. + +##### Parameters + +###### payload? + +Payload for creating a thread. + +####### graphId? + +`string` + +Graph ID to associate with the thread. + +####### ifExists? + +`OnConflictBehavior` + +How to handle duplicate creation. + +**Default** + +```ts +"raise" +``` + +####### metadata? + +`Metadata` + +Metadata for the thread. + +####### supersteps? + +`object`[] + +Apply a list of supersteps when creating a thread, each containing a sequence of updates. + +Used for copying a thread between deployments. + +####### threadId? + +`string` + +ID of the thread to create. + +If not provided, a random UUID will be generated. + +##### Returns + +`Promise`\<`Thread`\<`TStateType`\>\> + +The created thread. + +*** + +#### delete() + +> **delete**(`threadId`): `Promise`\<`void`\> + +Defined in: [client.ts:599](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L599) + +Delete a thread. + +##### Parameters + +###### threadId + +`string` + +ID of the thread. + +##### Returns + +`Promise`\<`void`\> + +*** + +#### get() + +> **get**\<`ValuesType`\>(`threadId`): `Promise`\<`Thread`\<`ValuesType`\>\> + +Defined in: [client.ts:499](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L499) + +Get a thread by ID. + +##### Type Parameters + +• **ValuesType** = `TStateType` + +##### Parameters + +###### threadId + +`string` + +ID of the thread. + +##### Returns + +`Promise`\<`Thread`\<`ValuesType`\>\> + +The thread. + +*** + +#### getHistory() + +> **getHistory**\<`ValuesType`\>(`threadId`, `options`?): `Promise`\<`ThreadState`\<`ValuesType`\>[]\> + +Defined in: [client.ts:752](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L752) + +Get all past states for a thread. + +##### Type Parameters + +• **ValuesType** = `TStateType` + +##### Parameters + +###### threadId + +`string` + +ID of the thread. + +###### options? + +Additional options. + +####### before? + +`Config` + +####### checkpoint? + +`Partial`\<`Omit`\<`Checkpoint`, `"thread_id"`\>\> + +####### limit? + +`number` + +####### metadata? + +`Metadata` + +##### Returns + +`Promise`\<`ThreadState`\<`ValuesType`\>[]\> + +List of thread states. + +*** + +#### getState() + +> **getState**\<`ValuesType`\>(`threadId`, `checkpoint`?, `options`?): `Promise`\<`ThreadState`\<`ValuesType`\>\> + +Defined in: [client.ts:659](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L659) + +Get state for a thread. + +##### Type Parameters + +• **ValuesType** = `TStateType` + +##### Parameters + +###### threadId + +`string` + +ID of the thread. + +###### checkpoint? + +`string` | `Checkpoint` + +###### options? + +####### subgraphs? + +`boolean` + +##### Returns + +`Promise`\<`ThreadState`\<`ValuesType`\>\> + +Thread state. + +*** + +#### patchState() + +> **patchState**(`threadIdOrConfig`, `metadata`): `Promise`\<`void`\> + +Defined in: [client.ts:722](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L722) + +Patch the metadata of a thread. + +##### Parameters + +###### threadIdOrConfig + +Thread ID or config to patch the state of. + +`string` | `Config` + +###### metadata + +`Metadata` + +Metadata to patch the state with. + +##### Returns + +`Promise`\<`void`\> + +*** + +#### search() + +> **search**\<`ValuesType`\>(`query`?): `Promise`\<`Thread`\<`ValuesType`\>[]\> + +Defined in: [client.ts:611](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L611) + +List threads + +##### Type Parameters + +• **ValuesType** = `TStateType` + +##### Parameters + +###### query? + +Query options + +####### limit? + +`number` + +Maximum number of threads to return. +Defaults to 10 + +####### metadata? + +`Metadata` + +Metadata to filter threads by. + +####### offset? + +`number` + +Offset to start from. + +####### sortBy? + +`ThreadSortBy` + +Sort by. + +####### sortOrder? + +`SortOrder` + +Sort order. +Must be one of 'asc' or 'desc'. + +####### status? + +`ThreadStatus` + +Thread status to filter on. +Must be one of 'idle', 'busy', 'interrupted' or 'error'. + +##### Returns + +`Promise`\<`Thread`\<`ValuesType`\>[]\> + +List of threads + +*** + +#### update() + +> **update**(`threadId`, `payload`?): `Promise`\<`Thread`\<`DefaultValues`\>\> + +Defined in: [client.ts:579](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L579) + +Update a thread. + +##### Parameters + +###### threadId + +`string` + +ID of the thread. + +###### payload? + +Payload for updating the thread. + +####### metadata? + +`Metadata` + +Metadata for the thread. + +##### Returns + +`Promise`\<`Thread`\<`DefaultValues`\>\> + +The updated thread. + +*** + +#### updateState() + +> **updateState**\<`ValuesType`\>(`threadId`, `options`): `Promise`\<`Pick`\<`Config`, `"configurable"`\>\> + +Defined in: [client.ts:693](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L693) + +Add state to a thread. + +##### Type Parameters + +• **ValuesType** = `TUpdateType` + +##### Parameters + +###### threadId + +`string` + +The ID of the thread. + +###### options + +####### asNode? + +`string` + +####### checkpoint? + +`Checkpoint` + +####### checkpointId? + +`string` + +####### values + +`ValuesType` + +##### Returns + +`Promise`\<`Pick`\<`Config`, `"configurable"`\>\> + + + + +[**@langchain/langgraph-sdk**](#readmemd) + +*** + +[@langchain/langgraph-sdk](#readmemd) / getApiKey + +## Function: getApiKey() + +> **getApiKey**(`apiKey`?): `undefined` \| `string` + +Defined in: [client.ts:53](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L53) + +Get the API key from the environment. +Precedence: + 1. explicit argument + 2. LANGGRAPH_API_KEY + 3. LANGSMITH_API_KEY + 4. LANGCHAIN_API_KEY + +### Parameters + +#### apiKey? + +`string` + +Optional API key provided as an argument + +### Returns + +`undefined` \| `string` + +The API key if found, otherwise undefined + + + + +[**@langchain/langgraph-sdk**](#readmemd) + +*** + +[@langchain/langgraph-sdk](#readmemd) / ClientConfig + +## Interface: ClientConfig + +Defined in: [client.ts:71](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L71) + +### Properties + +#### apiKey? + +> `optional` **apiKey**: `string` + +Defined in: [client.ts:73](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L73) + +*** + +#### apiUrl? + +> `optional` **apiUrl**: `string` + +Defined in: [client.ts:72](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L72) + +*** + +#### callerOptions? + +> `optional` **callerOptions**: `AsyncCallerParams` + +Defined in: [client.ts:74](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L74) + +*** + +#### defaultHeaders? + +> `optional` **defaultHeaders**: `Record`\<`string`, `undefined` \| `null` \| `string`\> + +Defined in: [client.ts:76](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L76) + +*** + +#### timeoutMs? + +> `optional` **timeoutMs**: `number` + +Defined in: [client.ts:75](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/client.ts#L75) + + + + +**@langchain/langgraph-sdk** + +*** + +## @langchain/langgraph-sdk/react + +### Interfaces + +- [UseStream](#reactinterfacesusestreammd) +- [UseStreamOptions](#reactinterfacesusestreamoptionsmd) + +### Type Aliases + +- [MessageMetadata](#reacttype-aliasesmessagemetadatamd) + +### Functions + +- [useStream](#reactfunctionsusestreammd) + + + + +[**@langchain/langgraph-sdk**](#reactreadmemd) + +*** + +[@langchain/langgraph-sdk](#reactreadmemd) / useStream + +## Function: useStream() + +> **useStream**\<`StateType`, `Bag`\>(`options`): [`UseStream`](#reactinterfacesusestreammd)\<`StateType`, `Bag`\> + +Defined in: [react/stream.tsx:618](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L618) + +### Type Parameters + +• **StateType** *extends* `Record`\<`string`, `unknown`\> = `Record`\<`string`, `unknown`\> + +• **Bag** *extends* `object` = `BagTemplate` + +### Parameters + +#### options + +[`UseStreamOptions`](#reactinterfacesusestreamoptionsmd)\<`StateType`, `Bag`\> + +### Returns + +[`UseStream`](#reactinterfacesusestreammd)\<`StateType`, `Bag`\> + + + + +[**@langchain/langgraph-sdk**](#reactreadmemd) + +*** + +[@langchain/langgraph-sdk](#reactreadmemd) / UseStream + +## Interface: UseStream\ + +Defined in: [react/stream.tsx:507](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L507) + +### Type Parameters + +• **StateType** *extends* `Record`\<`string`, `unknown`\> = `Record`\<`string`, `unknown`\> + +• **Bag** *extends* `BagTemplate` = `BagTemplate` + +### Properties + +#### assistantId + +> **assistantId**: `string` + +Defined in: [react/stream.tsx:592](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L592) + +The ID of the assistant to use. + +*** + +#### branch + +> **branch**: `string` + +Defined in: [react/stream.tsx:542](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L542) + +The current branch of the thread. + +*** + +#### client + +> **client**: `Client` + +Defined in: [react/stream.tsx:587](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L587) + +LangGraph SDK client used to send request and receive responses. + +*** + +#### error + +> **error**: `unknown` + +Defined in: [react/stream.tsx:519](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L519) + +Last seen error from the thread or during streaming. + +*** + +#### experimental\_branchTree + +> **experimental\_branchTree**: `Sequence`\<`StateType`\> + +Defined in: [react/stream.tsx:558](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L558) + +**`Experimental`** + +Tree of all branches for the thread. + +*** + +#### getMessagesMetadata() + +> **getMessagesMetadata**: (`message`, `index`?) => `undefined` \| [`MessageMetadata`](#reacttype-aliasesmessagemetadatamd)\<`StateType`\> + +Defined in: [react/stream.tsx:579](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L579) + +Get the metadata for a message, such as first thread state the message +was seen in and branch information. + +##### Parameters + +###### message + +`Message` + +The message to get the metadata for. + +###### index? + +`number` + +The index of the message in the thread. + +##### Returns + +`undefined` \| [`MessageMetadata`](#reacttype-aliasesmessagemetadatamd)\<`StateType`\> + +The metadata for the message. + +*** + +#### history + +> **history**: `ThreadState`\<`StateType`\>[] + +Defined in: [react/stream.tsx:552](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L552) + +Flattened history of thread states of a thread. + +*** + +#### interrupt + +> **interrupt**: `undefined` \| `Interrupt`\<`GetInterruptType`\<`Bag`\>\> + +Defined in: [react/stream.tsx:563](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L563) + +Get the interrupt value for the stream if interrupted. + +*** + +#### isLoading + +> **isLoading**: `boolean` + +Defined in: [react/stream.tsx:524](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L524) + +Whether the stream is currently running. + +*** + +#### messages + +> **messages**: `Message`[] + +Defined in: [react/stream.tsx:569](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L569) + +Messages inferred from the thread. +Will automatically update with incoming message chunks. + +*** + +#### setBranch() + +> **setBranch**: (`branch`) => `void` + +Defined in: [react/stream.tsx:547](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L547) + +Set the branch of the thread. + +##### Parameters + +###### branch + +`string` + +##### Returns + +`void` + +*** + +#### stop() + +> **stop**: () => `void` + +Defined in: [react/stream.tsx:529](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L529) + +Stops the stream. + +##### Returns + +`void` + +*** + +#### submit() + +> **submit**: (`values`, `options`?) => `void` + +Defined in: [react/stream.tsx:534](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L534) + +Create and stream a run to the thread. + +##### Parameters + +###### values + +`undefined` | `null` | `GetUpdateType`\<`Bag`, `StateType`\> + +###### options? + +`SubmitOptions`\<`StateType`, `GetConfigurableType`\<`Bag`\>\> + +##### Returns + +`void` + +*** + +#### values + +> **values**: `StateType` + +Defined in: [react/stream.tsx:514](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L514) + +The current values of the thread. + + + + +[**@langchain/langgraph-sdk**](#reactreadmemd) + +*** + +[@langchain/langgraph-sdk](#reactreadmemd) / UseStreamOptions + +## Interface: UseStreamOptions\ + +Defined in: [react/stream.tsx:408](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L408) + +### Type Parameters + +• **StateType** *extends* `Record`\<`string`, `unknown`\> = `Record`\<`string`, `unknown`\> + +• **Bag** *extends* `BagTemplate` = `BagTemplate` + +### Properties + +#### apiKey? + +> `optional` **apiKey**: `string` + +Defined in: [react/stream.tsx:430](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L430) + +The API key to use. + +*** + +#### apiUrl? + +> `optional` **apiUrl**: `string` + +Defined in: [react/stream.tsx:425](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L425) + +The URL of the API to use. + +*** + +#### assistantId + +> **assistantId**: `string` + +Defined in: [react/stream.tsx:415](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L415) + +The ID of the assistant to use. + +*** + +#### callerOptions? + +> `optional` **callerOptions**: `AsyncCallerParams` + +Defined in: [react/stream.tsx:435](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L435) + +Custom call options, such as custom fetch implementation. + +*** + +#### client? + +> `optional` **client**: `Client`\<`DefaultValues`, `DefaultValues`, `unknown`\> + +Defined in: [react/stream.tsx:420](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L420) + +Client used to send requests. + +*** + +#### defaultHeaders? + +> `optional` **defaultHeaders**: `Record`\<`string`, `undefined` \| `null` \| `string`\> + +Defined in: [react/stream.tsx:440](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L440) + +Default headers to send with requests. + +*** + +#### messagesKey? + +> `optional` **messagesKey**: `string` + +Defined in: [react/stream.tsx:448](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L448) + +Specify the key within the state that contains messages. +Defaults to "messages". + +##### Default + +```ts +"messages" +``` + +*** + +#### onCustomEvent()? + +> `optional` **onCustomEvent**: (`data`, `options`) => `void` + +Defined in: [react/stream.tsx:470](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L470) + +Callback that is called when a custom event is received. + +##### Parameters + +###### data + +`GetCustomEventType`\<`Bag`\> + +###### options + +####### mutate + +(`update`) => `void` + +##### Returns + +`void` + +*** + +#### onDebugEvent()? + +> `optional` **onDebugEvent**: (`data`) => `void` + +Defined in: [react/stream.tsx:494](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L494) + +**`Internal`** + +Callback that is called when a debug event is received. + This API is experimental and subject to change. + +##### Parameters + +###### data + +`unknown` + +##### Returns + +`void` + +*** + +#### onError()? + +> `optional` **onError**: (`error`) => `void` + +Defined in: [react/stream.tsx:453](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L453) + +Callback that is called when an error occurs. + +##### Parameters + +###### error + +`unknown` + +##### Returns + +`void` + +*** + +#### onFinish()? + +> `optional` **onFinish**: (`state`) => `void` + +Defined in: [react/stream.tsx:458](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L458) + +Callback that is called when the stream is finished. + +##### Parameters + +###### state + +`ThreadState`\<`StateType`\> + +##### Returns + +`void` + +*** + +#### onLangChainEvent()? + +> `optional` **onLangChainEvent**: (`data`) => `void` + +Defined in: [react/stream.tsx:488](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L488) + +Callback that is called when a LangChain event is received. + +##### Parameters + +###### data + +####### data + +`unknown` + +####### event + +`string` & `object` \| `"on_tool_start"` \| `"on_tool_stream"` \| `"on_tool_end"` \| `"on_chat_model_start"` \| `"on_chat_model_stream"` \| `"on_chat_model_end"` \| `"on_llm_start"` \| `"on_llm_stream"` \| `"on_llm_end"` \| `"on_chain_start"` \| `"on_chain_stream"` \| `"on_chain_end"` \| `"on_retriever_start"` \| `"on_retriever_stream"` \| `"on_retriever_end"` \| `"on_prompt_start"` \| `"on_prompt_stream"` \| `"on_prompt_end"` + +####### metadata + +`Record`\<`string`, `unknown`\> + +####### name + +`string` + +####### parent_ids + +`string`[] + +####### run_id + +`string` + +####### tags + +`string`[] + +##### Returns + +`void` + +##### See + +https://langchain-ai.github.io/langgraph/cloud/how-tos/stream_events/#stream-graph-in-events-mode for more details. + +*** + +#### onMetadataEvent()? + +> `optional` **onMetadataEvent**: (`data`) => `void` + +Defined in: [react/stream.tsx:482](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L482) + +Callback that is called when a metadata event is received. + +##### Parameters + +###### data + +####### run_id + +`string` + +####### thread_id + +`string` + +##### Returns + +`void` + +*** + +#### onThreadId()? + +> `optional` **onThreadId**: (`threadId`) => `void` + +Defined in: [react/stream.tsx:504](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L504) + +Callback that is called when the thread ID is updated (ie when a new thread is created). + +##### Parameters + +###### threadId + +`string` + +##### Returns + +`void` + +*** + +#### onUpdateEvent()? + +> `optional` **onUpdateEvent**: (`data`) => `void` + +Defined in: [react/stream.tsx:463](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L463) + +Callback that is called when an update event is received. + +##### Parameters + +###### data + +##### Returns + +`void` + +*** + +#### threadId? + +> `optional` **threadId**: `null` \| `string` + +Defined in: [react/stream.tsx:499](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L499) + +The ID of the thread to fetch history and current values from. + + + + +[**@langchain/langgraph-sdk**](#reactreadmemd) + +*** + +[@langchain/langgraph-sdk](#reactreadmemd) / MessageMetadata + +## Type Alias: MessageMetadata\ + +> **MessageMetadata**\<`StateType`\>: `object` + +Defined in: [react/stream.tsx:169](https://github.com/langchain-ai/langgraph/blob/d4f644877db6264bd46d0b00fc4c37f174e502d5/libs/sdk-js/src/react/stream.tsx#L169) + +### Type Parameters + +• **StateType** *extends* `Record`\<`string`, `unknown`\> + +### Type declaration + +#### branch + +> **branch**: `string` \| `undefined` + +The branch of the message. + +#### branchOptions + +> **branchOptions**: `string`[] \| `undefined` + +The list of branches this message is part of. +This is useful for displaying branching controls. + +#### firstSeenState + +> **firstSeenState**: `ThreadState`\<`StateType`\> \| `undefined` + +The first thread state the message was seen in. + +#### messageId + +> **messageId**: `string` + +The ID of the message used. diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index a59c835dd..7cfbb246f 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -263,7 +263,7 @@ nav: - Control Plane API: cloud/reference/api/api_ref_control_plane.md - CLI: cloud/reference/cli.md - SDK (Python): cloud/reference/sdk/python_sdk_ref.md - - SDK (JS/TS): cloud/reference/sdk/js_ts_sdk_ref.md + - SDK (JS/TS): https://langchain-ai.github.io/langgraphjs/reference/modules/sdk.html - RemoteGraph: reference/remote_graph.md - Environment variables: cloud/reference/env_var.md diff --git a/libs/sdk-js/.gitignore b/libs/sdk-js/.gitignore deleted file mode 100644 index db1a582d0..000000000 --- a/libs/sdk-js/.gitignore +++ /dev/null @@ -1,28 +0,0 @@ -index.cjs -index.js -index.d.ts -index.d.cts -client.cjs -client.js -client.d.ts -client.d.cts -auth.cjs -auth.js -auth.d.ts -auth.d.cts -react.cjs -react.js -react.d.ts -react.d.cts -react-ui.cjs -react-ui.js -react-ui.d.ts -react-ui.d.cts -react-ui/server.cjs -react-ui/server.js -react-ui/server.d.ts -react-ui/server.d.cts -node_modules -dist -.yarn -docs diff --git a/libs/sdk-js/.prettierrc b/libs/sdk-js/.prettierrc deleted file mode 100644 index 0967ef424..000000000 --- a/libs/sdk-js/.prettierrc +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/libs/sdk-js/LICENSE b/libs/sdk-js/LICENSE deleted file mode 100644 index fc0602fee..000000000 --- a/libs/sdk-js/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2024 LangChain, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/libs/sdk-js/README.md b/libs/sdk-js/README.md deleted file mode 100644 index fb47ef3cb..000000000 --- a/libs/sdk-js/README.md +++ /dev/null @@ -1,64 +0,0 @@ -# LangGraph JS/TS SDK - -This repository contains the JS/TS SDK for interacting with the LangGraph REST API. - -## Quick Start - -To get started with the JS/TS SDK, [install the package](https://www.npmjs.com/package/@langchain/langgraph-sdk) - -```bash -yarn add @langchain/langgraph-sdk -``` - -You will need a running LangGraph API server. If you're running a server locally using `langgraph-cli`, SDK will automatically point at `http://localhost:8123`, otherwise -you would need to specify the server URL when creating a client. - -```js -import { Client } from "@langchain/langgraph-sdk"; - -const client = new Client(); - -// List all assistants -const assistants = await client.assistants.search({ - metadata: null, - offset: 0, - limit: 10, -}); - -// We auto-create an assistant for each graph you register in config. -const agent = assistants[0]; - -// Start a new thread -const thread = await client.threads.create(); - -// Start a streaming run -const messages = [{ role: "human", content: "what's the weather in la" }]; - -const streamResponse = client.runs.stream( - thread["thread_id"], - agent["assistant_id"], - { - input: { messages }, - } -); - -for await (const chunk of streamResponse) { - console.log(chunk); -} -``` - -## Documentation - -To generate documentation, run the following commands: - -1. Generate docs. - - yarn typedoc - -1. Consolidate doc files into one markdown file. - - npx concat-md --decrease-title-levels --ignore=js_ts_sdk_ref.md --start-title-level-at 2 docs > docs/js_ts_sdk_ref.md - -1. Copy `js_ts_sdk_ref.md` to MkDocs directory. - - cp docs/js_ts_sdk_ref.md ../../docs/docs/cloud/reference/sdk/js_ts_sdk_ref.md diff --git a/libs/sdk-js/jest.config.js b/libs/sdk-js/jest.config.js deleted file mode 100644 index 10218cfab..000000000 --- a/libs/sdk-js/jest.config.js +++ /dev/null @@ -1,17 +0,0 @@ -/** @type {import('jest').Config} */ -export default { - preset: 'ts-jest', - testEnvironment: 'node', - extensionsToTreatAsEsm: ['.ts'], - moduleNameMapper: { - '^(\\.{1,2}/.*)\\.js$': '$1', - }, - transform: { - '^.+\\.tsx?$': [ - 'ts-jest', - { - useESM: true, - }, - ], - }, -}; diff --git a/libs/sdk-js/langchain.config.js b/libs/sdk-js/langchain.config.js deleted file mode 100644 index 0c8a691cd..000000000 --- a/libs/sdk-js/langchain.config.js +++ /dev/null @@ -1,27 +0,0 @@ -import { resolve, dirname } from "node:path"; -import { fileURLToPath } from "node:url"; - -/** - * @param {string} relativePath - * @returns {string} - */ -function abs(relativePath) { - return resolve(dirname(fileURLToPath(import.meta.url)), relativePath); -} - -export const config = { - internals: [/react/], - entrypoints: { - index: "index", - client: "client", - auth: "auth/index", - react: "react/index", - "react-ui": "react-ui/index", - "react-ui/server": "react-ui/server/index", - }, - tsConfigPath: resolve("./tsconfig.json"), - cjsSource: "./dist-cjs", - cjsDestination: "./dist", - additionalGitignorePaths: ["docs"], - abs, -}; diff --git a/libs/sdk-js/package.json b/libs/sdk-js/package.json deleted file mode 100644 index bc2b2fa5d..000000000 --- a/libs/sdk-js/package.json +++ /dev/null @@ -1,147 +0,0 @@ -{ - "name": "@langchain/langgraph-sdk", - "version": "0.0.89", - "description": "Client library for interacting with the LangGraph API", - "type": "module", - "packageManager": "yarn@1.22.19", - "scripts": { - "clean": "rm -rf dist/ dist-cjs/", - "build": "yarn clean && yarn lc_build --create-entrypoints --pre --tree-shaking", - "prepack": "yarn run build", - "format": "prettier --write src", - "lint": "prettier --check src && tsc --noEmit", - "test": "vitest", - "typedoc": "typedoc && typedoc src/react/index.ts --out docs/react --options typedoc.react.json && typedoc src/auth/index.ts --out docs/auth --options typedoc.auth.json" - }, - "main": "index.js", - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.15", - "p-queue": "^6.6.2", - "p-retry": "4", - "uuid": "^9.0.0" - }, - "devDependencies": { - "@langchain/langgraph-api": "~0.0.41", - "@langchain/core": "^0.3.61", - "@langchain/langgraph": "^0.3.5", - "@langchain/scripts": "^0.1.4", - "@testing-library/dom": "^10.4.0", - "@testing-library/jest-dom": "^6.6.3", - "@testing-library/react": "^16.3.0", - "@testing-library/user-event": "^14.6.1", - "@tsconfig/recommended": "^1.0.2", - "@types/node": "^20.12.12", - "@types/react": "^19.0.8", - "@types/react-dom": "^19.0.3", - "@types/uuid": "^9.0.1", - "@vitejs/plugin-react": "^4.4.1", - "concat-md": "^0.5.1", - "hono": "^4.8.2", - "jsdom": "^26.1.0", - "msw": "^2.8.2", - "prettier": "^3.2.5", - "react": "^19.0.0", - "react-dom": "^19.0.0", - "typedoc": "^0.27.7", - "typedoc-plugin-markdown": "^4.4.2", - "typescript": "^5.4.5", - "vitest": "^3.1.3" - }, - "peerDependencies": { - "@langchain/core": ">=0.2.31 <0.4.0", - "react": "^18 || ^19" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "@langchain/core": { - "optional": true - } - }, - "exports": { - ".": { - "types": { - "import": "./index.d.ts", - "require": "./index.d.cts", - "default": "./index.d.ts" - }, - "import": "./index.js", - "require": "./index.cjs" - }, - "./client": { - "types": { - "import": "./client.d.ts", - "require": "./client.d.cts", - "default": "./client.d.ts" - }, - "import": "./client.js", - "require": "./client.cjs" - }, - "./auth": { - "types": { - "import": "./auth.d.ts", - "require": "./auth.d.cts", - "default": "./auth.d.ts" - }, - "import": "./auth.js", - "require": "./auth.cjs" - }, - "./react": { - "types": { - "import": "./react.d.ts", - "require": "./react.d.cts", - "default": "./react.d.ts" - }, - "import": "./react.js", - "require": "./react.cjs" - }, - "./react-ui": { - "types": { - "import": "./react-ui.d.ts", - "require": "./react-ui.d.cts", - "default": "./react-ui.d.ts" - }, - "import": "./react-ui.js", - "require": "./react-ui.cjs" - }, - "./react-ui/server": { - "types": { - "import": "./react-ui/server.d.ts", - "require": "./react-ui/server.d.cts", - "default": "./react-ui/server.d.ts" - }, - "import": "./react-ui/server.js", - "require": "./react-ui/server.cjs" - }, - "./package.json": "./package.json" - }, - "files": [ - "dist/", - "index.cjs", - "index.js", - "index.d.ts", - "index.d.cts", - "client.cjs", - "client.js", - "client.d.ts", - "client.d.cts", - "auth.cjs", - "auth.js", - "auth.d.ts", - "auth.d.cts", - "react.cjs", - "react.js", - "react.d.ts", - "react.d.cts", - "react-ui.cjs", - "react-ui.js", - "react-ui.d.ts", - "react-ui.d.cts", - "react-ui/server.cjs", - "react-ui/server.js", - "react-ui/server.d.ts", - "react-ui/server.d.cts" - ] -} diff --git a/libs/sdk-js/src/auth/error.ts b/libs/sdk-js/src/auth/error.ts deleted file mode 100644 index ace6df54c..000000000 --- a/libs/sdk-js/src/auth/error.ts +++ /dev/null @@ -1,80 +0,0 @@ -const HTTP_STATUS_MAPPING: { [key: number]: string } = { - 100: "Continue", - 101: "Switching Protocols", - 102: "Processing", - 103: "Early Hints", - 200: "OK", - 201: "Created", - 202: "Accepted", - 203: "Non-Authoritative Information", - 204: "No Content", - 205: "Reset Content", - 206: "Partial Content", - 207: "Multi-Status", - 208: "Already Reported", - 226: "IM Used", - 300: "Multiple Choices", - 301: "Moved Permanently", - 302: "Found", - 303: "See Other", - 304: "Not Modified", - 305: "Use Proxy", - 307: "Temporary Redirect", - 308: "Permanent Redirect", - 400: "Bad Request", - 401: "Unauthorized", - 402: "Payment Required", - 403: "Forbidden", - 404: "Not Found", - 405: "Method Not Allowed", - 406: "Not Acceptable", - 407: "Proxy Authentication Required", - 408: "Request Timeout", - 409: "Conflict", - 410: "Gone", - 411: "Length Required", - 412: "Precondition Failed", - 413: "Request Entity Too Large", - 414: "Request-URI Too Long", - 415: "Unsupported Media Type", - 416: "Requested Range Not Satisfiable", - 417: "Expectation Failed", - 418: "I'm a Teapot", - 421: "Misdirected Request", - 422: "Unprocessable Entity", - 423: "Locked", - 424: "Failed Dependency", - 425: "Too Early", - 426: "Upgrade Required", - 428: "Precondition Required", - 429: "Too Many Requests", - 431: "Request Header Fields Too Large", - 451: "Unavailable For Legal Reasons", - 500: "Internal Server Error", - 501: "Not Implemented", - 502: "Bad Gateway", - 503: "Service Unavailable", - 504: "Gateway Timeout", - 505: "HTTP Version Not Supported", - 506: "Variant Also Negotiates", - 507: "Insufficient Storage", - 508: "Loop Detected", - 510: "Not Extended", - 511: "Network Authentication Required", -}; - -export class HTTPException extends Error { - status: number; - headers: HeadersInit; - - constructor( - status: number, - options?: { message?: string; headers?: HeadersInit; cause?: unknown }, - ) { - super(options?.message ?? HTTP_STATUS_MAPPING[status] ?? "Unknown error", { - cause: options?.cause, - }); - this.status = status; - this.headers = options?.headers ?? {}; - } -} diff --git a/libs/sdk-js/src/auth/index.ts b/libs/sdk-js/src/auth/index.ts deleted file mode 100644 index c7b1ffb1f..000000000 --- a/libs/sdk-js/src/auth/index.ts +++ /dev/null @@ -1,46 +0,0 @@ -import type { - AuthenticateCallback, - AnyCallback, - CallbackEvent, - OnCallback, - BaseAuthReturn, - ToUserLike, - BaseUser, -} from "./types.js"; - -export class Auth< - TExtra = {}, - TAuthReturn extends BaseAuthReturn = BaseAuthReturn, - TUser extends BaseUser = ToUserLike, -> { - /** - * @internal - * @ignore - */ - "~handlerCache": { - authenticate?: AuthenticateCallback; - callbacks?: Record; - } = {}; - - authenticate( - cb: AuthenticateCallback, - ): Auth { - this["~handlerCache"].authenticate = cb; - return this as unknown as Auth; - } - - on(event: T, callback: OnCallback): this { - this["~handlerCache"].callbacks ??= {}; - const events: string[] = Array.isArray(event) ? event : [event]; - for (const event of events) { - this["~handlerCache"].callbacks[event] = callback as AnyCallback; - } - return this; - } -} - -export type { - Filters as AuthFilters, - EventValueMap as AuthEventValueMap, -} from "./types.js"; -export { HTTPException } from "./error.js"; diff --git a/libs/sdk-js/src/auth/types.ts b/libs/sdk-js/src/auth/types.ts deleted file mode 100644 index cc12c4e5b..000000000 --- a/libs/sdk-js/src/auth/types.ts +++ /dev/null @@ -1,411 +0,0 @@ -type Maybe = T | null | undefined; -type PromiseMaybe = Promise | T; - -interface AssistantConfig { - tags?: Maybe; - recursion_limit?: Maybe; - configurable?: Maybe<{ - thread_id?: Maybe; - thread_ts?: Maybe; - [key: string]: unknown; - }>; -} - -/** - * @inline - */ -interface AssistantCreate { - assistant_id?: Maybe; - metadata?: Maybe>; - config?: Maybe; - if_exists?: Maybe<"raise" | "do_nothing">; - name?: Maybe; - graph_id: string; -} - -/** - * @inline - */ -interface AssistantRead { - assistant_id: string; - metadata?: Maybe>; -} - -/** - * @inline - */ -interface AssistantUpdate { - assistant_id: string; - metadata?: Maybe>; - config?: Maybe; - graph_id?: Maybe; - name?: Maybe; - version?: Maybe; -} - -/** - * @inline - */ -interface AssistantDelete { - assistant_id: string; -} - -/** - * @inline - */ -interface AssistantSearch { - graph_id?: Maybe; - metadata?: Maybe>; - limit?: Maybe; - offset?: Maybe; -} - -/** - * @inline - */ -interface ThreadCreate { - thread_id?: Maybe; - metadata?: Maybe>; - if_exists?: Maybe<"raise" | "do_nothing">; -} - -/** - * @inline - */ -interface ThreadRead { - thread_id?: Maybe; -} - -/** - * @inline - */ -interface ThreadUpdate { - thread_id?: Maybe; - metadata?: Maybe>; - action?: Maybe<"interrupt" | "rollback">; -} - -/** - * @inline - */ -interface ThreadDelete { - thread_id?: Maybe; - run_id?: Maybe; -} - -/** - * @inline - */ -interface ThreadSearch { - thread_id?: Maybe; - status?: Maybe<"idle" | "busy" | "interrupted" | "error" | (string & {})>; - metadata?: Maybe>; - values?: Maybe>; - limit?: Maybe; - offset?: Maybe; -} - -/** - * @inline - */ -interface CronCreate { - payload?: Maybe>; - schedule: string; - cron_id?: Maybe; - thread_id?: Maybe; - user_id?: Maybe; - end_time?: Maybe; -} - -/** - * @inline - */ -interface CronRead { - cron_id: string; -} - -/** - * @inline - */ -interface CronUpdate { - cron_id: string; - payload?: Maybe>; - schedule?: Maybe; -} - -/** - * @inline - */ -interface CronDelete { - cron_id: string; -} - -/** - * @inline - */ -interface CronSearch { - assistant_id?: Maybe; - thread_id?: Maybe; - limit?: Maybe; - offset?: Maybe; -} - -/** - * @inline - */ -interface StorePut { - namespace: string[]; - key: string; - value: Record; -} - -/** - * @inline - */ -interface StoreGet { - namespace: Maybe; - key: string; -} - -/** - * @inline - */ -interface StoreSearch { - namespace?: Maybe; - filter?: Maybe>; - limit?: Maybe; - offset?: Maybe; - query?: Maybe; -} - -/** - * @inline - */ -interface StoreListNamespaces { - namespace?: Maybe; - suffix?: Maybe; - max_depth?: Maybe; - limit?: Maybe; - offset?: Maybe; -} - -/** - * @inline - */ -interface StoreDelete { - namespace?: Maybe; - key: string; -} - -/** - * @inline - */ -interface RunsCreate { - thread_id?: Maybe; - assistant_id: string; - run_id: string; - status: Maybe< - "pending" | "running" | "error" | "success" | "timeout" | "interrupted" - >; - metadata?: Maybe>; - prevent_insert_if_inflight?: Maybe; - multitask_strategy?: Maybe<"interrupt" | "rollback" | "reject" | "enqueue">; - if_not_exists?: Maybe<"reject" | "create">; - after_seconds?: Maybe; - kwargs: Record; -} - -export interface EventValueMap { - ["threads:create"]: ThreadCreate; - ["threads:read"]: ThreadRead; - ["threads:update"]: ThreadUpdate; - ["threads:delete"]: ThreadDelete; - ["threads:search"]: ThreadSearch; - ["threads:create_run"]: RunsCreate; - - ["assistants:create"]: AssistantCreate; - ["assistants:read"]: AssistantRead; - ["assistants:update"]: AssistantUpdate; - ["assistants:delete"]: AssistantDelete; - ["assistants:search"]: AssistantSearch; - - ["crons:create"]: CronCreate; - ["crons:read"]: CronRead; - ["crons:update"]: CronUpdate; - ["crons:delete"]: CronDelete; - ["crons:search"]: CronSearch; - - ["store:put"]: StorePut; - ["store:get"]: StoreGet; - ["store:search"]: StoreSearch; - ["store:list_namespaces"]: StoreListNamespaces; - ["store:delete"]: StoreDelete; -} -interface ResourceType { - threads: - | "threads:create" - | "threads:read" - | "threads:update" - | "threads:delete" - | "threads:search" - | "threads:create_run"; - - assistants: - | "assistants:create" - | "assistants:read" - | "assistants:update" - | "assistants:delete" - | "assistants:search"; - crons: - | "crons:create" - | "crons:read" - | "crons:update" - | "crons:delete" - | "crons:search"; - - store: - | "store:put" - | "store:get" - | "store:search" - | "store:list_namespaces" - | "store:delete"; -} -interface ActionType { - "*:create": "threads:create" | "assistants:create" | "crons:create"; - - "*:read": "threads:read" | "assistants:read" | "crons:read"; - - "*:update": "threads:update" | "assistants:update" | "crons:update"; - - "*:delete": - | "threads:delete" - | "assistants:delete" - | "crons:delete" - | "store:delete"; - - "*:search": - | "threads:search" - | "assistants:search" - | "crons:search" - | "store:search"; - - "*:create_run": "threads:create_run"; - - "*:put": "store:put"; - - "*:get": "store:get"; - - "*:list_namespaces": "store:list_namespaces"; -} - -export type BaseAuthReturn = - | { - is_authenticated?: boolean; - display_name?: string; - identity: string; - permissions: string[]; - } - | string; - -export interface BaseUser { - is_authenticated: boolean; - display_name: string; - identity: string; - permissions: string[]; -} - -export type ToUserLike = T extends string - ? { - is_authenticated: boolean; - display_name: string; - identity: string; - permissions: string[]; - } - : Omit & { - is_authenticated: boolean; - display_name: string; - }; - -type CallbackParameter< - Event extends string = string, - Resource extends string = string, - Action extends string = string, - Value extends unknown = unknown, - TUser extends BaseUser = BaseUser, -> = { - event: Event; - resource: Resource; - action: Action; - value: Value; - user: TUser; - permissions: string[]; -}; - -type ContextMap = { - [EventType in keyof EventValueMap]: CallbackParameter< - EventType, - EventType extends `${infer Resource}:${string}` ? Resource : never, - EventType extends `${string}:${infer Action}` ? Action : never, - EventValueMap[EventType], - BaseUser - >; -}; - -type ActionCallbackParameter< - T extends keyof ActionType, - TUser extends BaseUser = BaseUser, -> = ContextMap[ActionType[T]] & { user: TUser }; -type AuthCallbackParameter< - T extends keyof EventValueMap, - TUser extends BaseUser = BaseUser, -> = ContextMap[T] & { user: TUser }; -type ResourceCallbackParameter< - T extends keyof ResourceType, - TUser extends BaseUser = BaseUser, -> = ContextMap[ResourceType[T]] & { user: TUser }; - -export type Filters = { - [key in TKey]: string | { [op in "$contains" | "$eq"]?: string }; -}; - -export interface AuthenticateCallback { - (request: Request): PromiseMaybe; -} - -type OnKey = keyof ResourceType | keyof ActionType | keyof EventValueMap; - -type OnSingleParameter< - T extends OnKey, - TUser extends BaseUser = BaseUser, -> = T extends keyof ResourceType - ? ResourceCallbackParameter - : T extends keyof ActionType - ? ActionCallbackParameter - : T extends keyof EventValueMap - ? AuthCallbackParameter - : never; - -type OnParameter< - T extends "*" | OnKey | OnKey[], - TUser extends BaseUser = BaseUser, -> = T extends OnKey[] - ? OnSingleParameter - : T extends "*" - ? AuthCallbackParameter - : T extends OnKey - ? OnSingleParameter - : never; - -export type AnyCallback = ( - request: CallbackParameter, -) => void | boolean | Filters; - -export type CallbackEvent = "*" | OnKey | OnKey[]; - -export type OnCallback< - T extends CallbackEvent, - TUser extends BaseUser = BaseUser, - TMetadata extends Record = Record, -> = ( - request: OnParameter, -) => void | boolean | Filters; diff --git a/libs/sdk-js/src/client.ts b/libs/sdk-js/src/client.ts deleted file mode 100644 index ae68bc180..000000000 --- a/libs/sdk-js/src/client.ts +++ /dev/null @@ -1,1699 +0,0 @@ -import { - Assistant, - AssistantGraph, - AssistantSortBy, - AssistantVersion, - CancelAction, - Checkpoint, - Config, - Cron, - CronCreateForThreadResponse, - CronCreateResponse, - CronSortBy, - DefaultValues, - GraphSchema, - Item, - ListNamespaceResponse, - Metadata, - Run, - RunStatus, - SearchItemsResponse, - SortOrder, - Subgraphs, - Thread, - ThreadSortBy, - ThreadState, - ThreadStatus, -} from "./schema.js"; -import type { - Command, - CronsCreatePayload, - OnConflictBehavior, - RunsCreatePayload, - RunsStreamPayload, - RunsWaitPayload, - StreamEvent, -} from "./types.js"; -import type { StreamMode, TypedAsyncGenerator } from "./types.stream.js"; -import { AsyncCaller, AsyncCallerParams } from "./utils/async_caller.js"; -import { getEnvironmentVariable } from "./utils/env.js"; -import { mergeSignals } from "./utils/signals.js"; -import { BytesLineDecoder, SSEDecoder } from "./utils/sse.js"; -import { IterableReadableStream } from "./utils/stream.js"; - -type HeaderValue = string | undefined | null; - -function* iterateHeaders( - headers: HeadersInit | Record, -): IterableIterator<[string, string | null]> { - let iter: Iterable<(HeaderValue | HeaderValue | null[])[]>; - let shouldClear = false; - - if (headers instanceof Headers) { - const entries: [string, string][] = []; - headers.forEach((value, name) => { - entries.push([name, value]); - }); - iter = entries; - } else if (Array.isArray(headers)) { - iter = headers; - } else { - shouldClear = true; - iter = Object.entries(headers ?? {}); - } - - for (let item of iter) { - const name = item[0]; - if (typeof name !== "string") - throw new TypeError( - `Expected header name to be a string, got ${typeof name}`, - ); - const values = Array.isArray(item[1]) ? item[1] : [item[1]]; - let didClear = false; - - for (const value of values) { - if (value === undefined) continue; - - // New object keys should always overwrite older headers - // Yield a null to clear the header in the headers object - // before adding the new value - if (shouldClear && !didClear) { - didClear = true; - yield [name, null]; - } - yield [name, value]; - } - } -} - -function mergeHeaders( - ...headerObjects: ( - | HeadersInit - | Record - | undefined - | null - )[] -) { - const outputHeaders = new Headers(); - for (const headers of headerObjects) { - if (!headers) continue; - for (const [name, value] of iterateHeaders(headers)) { - if (value === null) outputHeaders.delete(name); - else outputHeaders.append(name, value); - } - } - const headerEntries: [string, string][] = []; - outputHeaders.forEach((value, name) => { - headerEntries.push([name, value]); - }); - return Object.fromEntries(headerEntries); -} - -/** - * Get the API key from the environment. - * Precedence: - * 1. explicit argument - * 2. LANGGRAPH_API_KEY - * 3. LANGSMITH_API_KEY - * 4. LANGCHAIN_API_KEY - * - * @param apiKey - Optional API key provided as an argument - * @returns The API key if found, otherwise undefined - */ -export function getApiKey(apiKey?: string): string | undefined { - if (apiKey) { - return apiKey; - } - - const prefixes = ["LANGGRAPH", "LANGSMITH", "LANGCHAIN"]; - - for (const prefix of prefixes) { - const envKey = getEnvironmentVariable(`${prefix}_API_KEY`); - if (envKey) { - // Remove surrounding quotes - return envKey.trim().replace(/^["']|["']$/g, ""); - } - } - - return undefined; -} - -const REGEX_RUN_METADATA = - /(\/threads\/(?.+))?\/runs\/(?.+)/; - -function getRunMetadataFromResponse( - response: Response, -): { run_id: string; thread_id?: string } | undefined { - const contentLocation = response.headers.get("Content-Location"); - if (!contentLocation) return undefined; - - const match = REGEX_RUN_METADATA.exec(contentLocation); - - if (!match?.groups?.run_id) return undefined; - return { - run_id: match.groups.run_id, - thread_id: match.groups.thread_id || undefined, - }; -} - -export type RequestHook = ( - url: URL, - init: RequestInit, -) => Promise | RequestInit; - -export interface ClientConfig { - apiUrl?: string; - apiKey?: string; - callerOptions?: AsyncCallerParams; - timeoutMs?: number; - defaultHeaders?: Record; - onRequest?: RequestHook; -} - -class BaseClient { - protected asyncCaller: AsyncCaller; - - protected timeoutMs: number | undefined; - - protected apiUrl: string; - - protected defaultHeaders: Record; - - protected onRequest?: RequestHook; - - constructor(config?: ClientConfig) { - const callerOptions = { - maxRetries: 4, - maxConcurrency: 4, - ...config?.callerOptions, - }; - - let defaultApiUrl = "http://localhost:8123"; - if ( - !config?.apiUrl && - typeof globalThis === "object" && - globalThis != null - ) { - const fetchSmb = Symbol.for("langgraph_api:fetch"); - const urlSmb = Symbol.for("langgraph_api:url"); - - const global = globalThis as unknown as { - [fetchSmb]?: typeof fetch; - [urlSmb]?: string; - }; - - if (global[fetchSmb]) callerOptions.fetch ??= global[fetchSmb]; - if (global[urlSmb]) defaultApiUrl = global[urlSmb]; - } - - this.asyncCaller = new AsyncCaller(callerOptions); - this.timeoutMs = config?.timeoutMs; - - // default limit being capped by Chrome - // https://github.com/nodejs/undici/issues/1373 - // Regex to remove trailing slash, if present - this.apiUrl = config?.apiUrl?.replace(/\/$/, "") || defaultApiUrl; - this.defaultHeaders = config?.defaultHeaders || {}; - this.onRequest = config?.onRequest; - const apiKey = getApiKey(config?.apiKey); - if (apiKey) { - this.defaultHeaders["x-api-key"] = apiKey; - } - } - - protected prepareFetchOptions( - path: string, - options?: RequestInit & { - json?: unknown; - params?: Record; - timeoutMs?: number | null; - withResponse?: boolean; - }, - ): [url: URL, init: RequestInit] { - const mutatedOptions = { - ...options, - headers: mergeHeaders(this.defaultHeaders, options?.headers), - }; - - if (mutatedOptions.json) { - mutatedOptions.body = JSON.stringify(mutatedOptions.json); - mutatedOptions.headers = mergeHeaders(mutatedOptions.headers, { - "content-type": "application/json", - }); - delete mutatedOptions.json; - } - - if (mutatedOptions.withResponse) { - delete mutatedOptions.withResponse; - } - - let timeoutSignal: AbortSignal | null = null; - if (typeof options?.timeoutMs !== "undefined") { - if (options.timeoutMs != null) { - timeoutSignal = AbortSignal.timeout(options.timeoutMs); - } - } else if (this.timeoutMs != null) { - timeoutSignal = AbortSignal.timeout(this.timeoutMs); - } - - mutatedOptions.signal = mergeSignals(timeoutSignal, mutatedOptions.signal); - const targetUrl = new URL(`${this.apiUrl}${path}`); - - if (mutatedOptions.params) { - for (const [key, value] of Object.entries(mutatedOptions.params)) { - if (value == null) continue; - - let strValue = - typeof value === "string" || typeof value === "number" - ? value.toString() - : JSON.stringify(value); - - targetUrl.searchParams.append(key, strValue); - } - delete mutatedOptions.params; - } - - return [targetUrl, mutatedOptions]; - } - - protected async fetch( - path: string, - options: RequestInit & { - json?: unknown; - params?: Record; - timeoutMs?: number | null; - signal?: AbortSignal; - withResponse: true; - }, - ): Promise<[T, Response]>; - - protected async fetch( - path: string, - options?: RequestInit & { - json?: unknown; - params?: Record; - timeoutMs?: number | null; - signal?: AbortSignal; - withResponse?: false; - }, - ): Promise; - - protected async fetch( - path: string, - options?: RequestInit & { - json?: unknown; - params?: Record; - timeoutMs?: number | null; - signal?: AbortSignal; - withResponse?: boolean; - }, - ): Promise { - const [url, init] = this.prepareFetchOptions(path, options); - - let finalInit = init; - if (this.onRequest) { - finalInit = await this.onRequest(url, init); - } - - const response = await this.asyncCaller.fetch(url, finalInit); - - const body = (() => { - if (response.status === 202 || response.status === 204) { - return undefined as T; - } - return response.json() as Promise; - })(); - - if (options?.withResponse) { - return [await body, response]; - } - - return body; - } -} - -export class CronsClient extends BaseClient { - /** - * - * @param threadId The ID of the thread. - * @param assistantId Assistant ID to use for this cron job. - * @param payload Payload for creating a cron job. - * @returns The created background run. - */ - async createForThread( - threadId: string, - assistantId: string, - payload?: CronsCreatePayload, - ): Promise { - const json: Record = { - schedule: payload?.schedule, - input: payload?.input, - config: payload?.config, - metadata: payload?.metadata, - assistant_id: assistantId, - interrupt_before: payload?.interruptBefore, - interrupt_after: payload?.interruptAfter, - webhook: payload?.webhook, - multitask_strategy: payload?.multitaskStrategy, - if_not_exists: payload?.ifNotExists, - checkpoint_during: payload?.checkpointDuring, - }; - return this.fetch( - `/threads/${threadId}/runs/crons`, - { - method: "POST", - json, - }, - ); - } - - /** - * - * @param assistantId Assistant ID to use for this cron job. - * @param payload Payload for creating a cron job. - * @returns - */ - async create( - assistantId: string, - payload?: CronsCreatePayload, - ): Promise { - const json: Record = { - schedule: payload?.schedule, - input: payload?.input, - config: payload?.config, - metadata: payload?.metadata, - assistant_id: assistantId, - interrupt_before: payload?.interruptBefore, - interrupt_after: payload?.interruptAfter, - webhook: payload?.webhook, - multitask_strategy: payload?.multitaskStrategy, - if_not_exists: payload?.ifNotExists, - checkpoint_during: payload?.checkpointDuring, - }; - return this.fetch(`/runs/crons`, { - method: "POST", - json, - }); - } - - /** - * - * @param cronId Cron ID of Cron job to delete. - */ - async delete(cronId: string): Promise { - await this.fetch(`/runs/crons/${cronId}`, { - method: "DELETE", - }); - } - - /** - * - * @param query Query options. - * @returns List of crons. - */ - async search(query?: { - assistantId?: string; - threadId?: string; - limit?: number; - offset?: number; - sortBy?: CronSortBy; - sortOrder?: SortOrder; - }): Promise { - return this.fetch("/runs/crons/search", { - method: "POST", - json: { - assistant_id: query?.assistantId ?? undefined, - thread_id: query?.threadId ?? undefined, - limit: query?.limit ?? 10, - offset: query?.offset ?? 0, - sort_by: query?.sortBy ?? undefined, - sort_order: query?.sortOrder ?? undefined, - }, - }); - } -} - -export class AssistantsClient extends BaseClient { - /** - * Get an assistant by ID. - * - * @param assistantId The ID of the assistant. - * @returns Assistant - */ - async get(assistantId: string): Promise { - return this.fetch(`/assistants/${assistantId}`); - } - - /** - * Get the JSON representation of the graph assigned to a runnable - * @param assistantId The ID of the assistant. - * @param options.xray Whether to include subgraphs in the serialized graph representation. If an integer value is provided, only subgraphs with a depth less than or equal to the value will be included. - * @returns Serialized graph - */ - async getGraph( - assistantId: string, - options?: { xray?: boolean | number }, - ): Promise { - return this.fetch(`/assistants/${assistantId}/graph`, { - params: { xray: options?.xray }, - }); - } - - /** - * Get the state and config schema of the graph assigned to a runnable - * @param assistantId The ID of the assistant. - * @returns Graph schema - */ - async getSchemas(assistantId: string): Promise { - return this.fetch(`/assistants/${assistantId}/schemas`); - } - - /** - * Get the schemas of an assistant by ID. - * - * @param assistantId The ID of the assistant to get the schema of. - * @param options Additional options for getting subgraphs, such as namespace or recursion extraction. - * @returns The subgraphs of the assistant. - */ - async getSubgraphs( - assistantId: string, - options?: { - namespace?: string; - recurse?: boolean; - }, - ): Promise { - if (options?.namespace) { - return this.fetch( - `/assistants/${assistantId}/subgraphs/${options.namespace}`, - { params: { recurse: options?.recurse } }, - ); - } - return this.fetch(`/assistants/${assistantId}/subgraphs`, { - params: { recurse: options?.recurse }, - }); - } - - /** - * Create a new assistant. - * @param payload Payload for creating an assistant. - * @returns The created assistant. - */ - async create(payload: { - graphId: string; - config?: Config; - metadata?: Metadata; - assistantId?: string; - ifExists?: OnConflictBehavior; - name?: string; - description?: string; - }): Promise { - return this.fetch("/assistants", { - method: "POST", - json: { - graph_id: payload.graphId, - config: payload.config, - metadata: payload.metadata, - assistant_id: payload.assistantId, - if_exists: payload.ifExists, - name: payload.name, - description: payload.description, - }, - }); - } - - /** - * Update an assistant. - * @param assistantId ID of the assistant. - * @param payload Payload for updating the assistant. - * @returns The updated assistant. - */ - async update( - assistantId: string, - payload: { - graphId?: string; - config?: Config; - metadata?: Metadata; - name?: string; - description?: string; - }, - ): Promise { - return this.fetch(`/assistants/${assistantId}`, { - method: "PATCH", - json: { - graph_id: payload.graphId, - config: payload.config, - metadata: payload.metadata, - name: payload.name, - description: payload.description, - }, - }); - } - - /** - * Delete an assistant. - * - * @param assistantId ID of the assistant. - */ - async delete(assistantId: string): Promise { - return this.fetch(`/assistants/${assistantId}`, { - method: "DELETE", - }); - } - - /** - * List assistants. - * @param query Query options. - * @returns List of assistants. - */ - async search(query?: { - graphId?: string; - metadata?: Metadata; - limit?: number; - offset?: number; - sortBy?: AssistantSortBy; - sortOrder?: SortOrder; - }): Promise { - return this.fetch("/assistants/search", { - method: "POST", - json: { - graph_id: query?.graphId ?? undefined, - metadata: query?.metadata ?? undefined, - limit: query?.limit ?? 10, - offset: query?.offset ?? 0, - sort_by: query?.sortBy ?? undefined, - sort_order: query?.sortOrder ?? undefined, - }, - }); - } - - /** - * List all versions of an assistant. - * - * @param assistantId ID of the assistant. - * @returns List of assistant versions. - */ - async getVersions( - assistantId: string, - payload?: { - metadata?: Metadata; - limit?: number; - offset?: number; - }, - ): Promise { - return this.fetch( - `/assistants/${assistantId}/versions`, - { - method: "POST", - json: { - metadata: payload?.metadata ?? undefined, - limit: payload?.limit ?? 10, - offset: payload?.offset ?? 0, - }, - }, - ); - } - - /** - * Change the version of an assistant. - * - * @param assistantId ID of the assistant. - * @param version The version to change to. - * @returns The updated assistant. - */ - async setLatest(assistantId: string, version: number): Promise { - return this.fetch(`/assistants/${assistantId}/latest`, { - method: "POST", - json: { version }, - }); - } -} - -export class ThreadsClient< - TStateType = DefaultValues, - TUpdateType = TStateType, -> extends BaseClient { - /** - * Get a thread by ID. - * - * @param threadId ID of the thread. - * @returns The thread. - */ - async get( - threadId: string, - ): Promise> { - return this.fetch>(`/threads/${threadId}`); - } - - /** - * Create a new thread. - * - * @param payload Payload for creating a thread. - * @returns The created thread. - */ - async create(payload?: { - /** - * Metadata for the thread. - */ - metadata?: Metadata; - /** - * ID of the thread to create. - * - * If not provided, a random UUID will be generated. - */ - threadId?: string; - /** - * How to handle duplicate creation. - * - * @default "raise" - */ - ifExists?: OnConflictBehavior; - /** - * Graph ID to associate with the thread. - */ - graphId?: string; - /** - * Apply a list of supersteps when creating a thread, each containing a sequence of updates. - * - * Used for copying a thread between deployments. - */ - supersteps?: Array<{ - updates: Array<{ values: unknown; command?: Command; asNode: string }>; - }>; - }): Promise> { - return this.fetch>(`/threads`, { - method: "POST", - json: { - metadata: { - ...payload?.metadata, - graph_id: payload?.graphId, - }, - thread_id: payload?.threadId, - if_exists: payload?.ifExists, - supersteps: payload?.supersteps?.map((s) => ({ - updates: s.updates.map((u) => ({ - values: u.values, - command: u.command, - as_node: u.asNode, - })), - })), - }, - }); - } - - /** - * Copy an existing thread - * @param threadId ID of the thread to be copied - * @returns Newly copied thread - */ - async copy(threadId: string): Promise> { - return this.fetch>(`/threads/${threadId}/copy`, { - method: "POST", - }); - } - - /** - * Update a thread. - * - * @param threadId ID of the thread. - * @param payload Payload for updating the thread. - * @returns The updated thread. - */ - async update( - threadId: string, - payload?: { - /** - * Metadata for the thread. - */ - metadata?: Metadata; - }, - ): Promise { - return this.fetch(`/threads/${threadId}`, { - method: "PATCH", - json: { metadata: payload?.metadata }, - }); - } - - /** - * Delete a thread. - * - * @param threadId ID of the thread. - */ - async delete(threadId: string): Promise { - return this.fetch(`/threads/${threadId}`, { - method: "DELETE", - }); - } - - /** - * List threads - * - * @param query Query options - * @returns List of threads - */ - async search(query?: { - /** - * Metadata to filter threads by. - */ - metadata?: Metadata; - /** - * Maximum number of threads to return. - * Defaults to 10 - */ - limit?: number; - /** - * Offset to start from. - */ - offset?: number; - /** - * Thread status to filter on. - */ - status?: ThreadStatus; - /** - * Sort by. - */ - sortBy?: ThreadSortBy; - /** - * Sort order. - * Must be one of 'asc' or 'desc'. - */ - sortOrder?: SortOrder; - }): Promise[]> { - return this.fetch[]>("/threads/search", { - method: "POST", - json: { - metadata: query?.metadata ?? undefined, - limit: query?.limit ?? 10, - offset: query?.offset ?? 0, - status: query?.status, - sort_by: query?.sortBy, - sort_order: query?.sortOrder, - }, - }); - } - - /** - * Get state for a thread. - * - * @param threadId ID of the thread. - * @returns Thread state. - */ - async getState( - threadId: string, - checkpoint?: Checkpoint | string, - options?: { subgraphs?: boolean }, - ): Promise> { - if (checkpoint != null) { - if (typeof checkpoint !== "string") { - return this.fetch>( - `/threads/${threadId}/state/checkpoint`, - { - method: "POST", - json: { checkpoint, subgraphs: options?.subgraphs }, - }, - ); - } - - // deprecated - return this.fetch>( - `/threads/${threadId}/state/${checkpoint}`, - { params: { subgraphs: options?.subgraphs } }, - ); - } - - return this.fetch>(`/threads/${threadId}/state`, { - params: { subgraphs: options?.subgraphs }, - }); - } - - /** - * Add state to a thread. - * - * @param threadId The ID of the thread. - * @returns - */ - async updateState( - threadId: string, - options: { - values: ValuesType; - checkpoint?: Checkpoint; - checkpointId?: string; - asNode?: string; - }, - ): Promise> { - return this.fetch>( - `/threads/${threadId}/state`, - { - method: "POST", - json: { - values: options.values, - checkpoint_id: options.checkpointId, - checkpoint: options.checkpoint, - as_node: options?.asNode, - }, - }, - ); - } - - /** - * Patch the metadata of a thread. - * - * @param threadIdOrConfig Thread ID or config to patch the state of. - * @param metadata Metadata to patch the state with. - */ - async patchState( - threadIdOrConfig: string | Config, - metadata: Metadata, - ): Promise { - let threadId: string; - - if (typeof threadIdOrConfig !== "string") { - if (typeof threadIdOrConfig.configurable?.thread_id !== "string") { - throw new Error( - "Thread ID is required when updating state with a config.", - ); - } - threadId = threadIdOrConfig.configurable.thread_id; - } else { - threadId = threadIdOrConfig; - } - - return this.fetch(`/threads/${threadId}/state`, { - method: "PATCH", - json: { metadata: metadata }, - }); - } - - /** - * Get all past states for a thread. - * - * @param threadId ID of the thread. - * @param options Additional options. - * @returns List of thread states. - */ - async getHistory( - threadId: string, - options?: { - limit?: number; - before?: Config; - checkpoint?: Partial>; - metadata?: Metadata; - }, - ): Promise[]> { - return this.fetch[]>( - `/threads/${threadId}/history`, - { - method: "POST", - json: { - limit: options?.limit ?? 10, - before: options?.before, - metadata: options?.metadata, - checkpoint: options?.checkpoint, - }, - }, - ); - } -} - -export class RunsClient< - TStateType = DefaultValues, - TUpdateType = TStateType, - TCustomEventType = unknown, -> extends BaseClient { - stream< - TStreamMode extends StreamMode | StreamMode[] = StreamMode, - TSubgraphs extends boolean = false, - >( - threadId: null, - assistantId: string, - payload?: Omit< - RunsStreamPayload, - "multitaskStrategy" | "onCompletion" - >, - ): TypedAsyncGenerator< - TStreamMode, - TSubgraphs, - TStateType, - TUpdateType, - TCustomEventType - >; - - stream< - TStreamMode extends StreamMode | StreamMode[] = StreamMode, - TSubgraphs extends boolean = false, - >( - threadId: string, - assistantId: string, - payload?: RunsStreamPayload, - ): TypedAsyncGenerator< - TStreamMode, - TSubgraphs, - TStateType, - TUpdateType, - TCustomEventType - >; - - /** - * Create a run and stream the results. - * - * @param threadId The ID of the thread. - * @param assistantId Assistant ID to use for this run. - * @param payload Payload for creating a run. - */ - async *stream< - TStreamMode extends StreamMode | StreamMode[] = StreamMode, - TSubgraphs extends boolean = false, - >( - threadId: string | null, - assistantId: string, - payload?: RunsStreamPayload, - ): TypedAsyncGenerator< - TStreamMode, - TSubgraphs, - TStateType, - TUpdateType, - TCustomEventType - > { - const json: Record = { - input: payload?.input, - command: payload?.command, - config: payload?.config, - metadata: payload?.metadata, - stream_mode: payload?.streamMode, - stream_subgraphs: payload?.streamSubgraphs, - stream_resumable: payload?.streamResumable, - feedback_keys: payload?.feedbackKeys, - assistant_id: assistantId, - interrupt_before: payload?.interruptBefore, - interrupt_after: payload?.interruptAfter, - checkpoint: payload?.checkpoint, - checkpoint_id: payload?.checkpointId, - webhook: payload?.webhook, - multitask_strategy: payload?.multitaskStrategy, - on_completion: payload?.onCompletion, - on_disconnect: payload?.onDisconnect, - after_seconds: payload?.afterSeconds, - if_not_exists: payload?.ifNotExists, - checkpoint_during: payload?.checkpointDuring, - }; - - const endpoint = - threadId == null ? `/runs/stream` : `/threads/${threadId}/runs/stream`; - - const response = await this.asyncCaller.fetch( - ...this.prepareFetchOptions(endpoint, { - method: "POST", - json, - timeoutMs: null, - signal: payload?.signal, - }), - ); - - const runMetadata = getRunMetadataFromResponse(response); - if (runMetadata) payload?.onRunCreated?.(runMetadata); - - const stream: ReadableStream<{ event: any; data: any }> = ( - response.body || new ReadableStream({ start: (ctrl) => ctrl.close() }) - ) - .pipeThrough(BytesLineDecoder()) - .pipeThrough(SSEDecoder()); - - yield* IterableReadableStream.fromReadableStream(stream); - } - - /** - * Create a run. - * - * @param threadId The ID of the thread. - * @param assistantId Assistant ID to use for this run. - * @param payload Payload for creating a run. - * @returns The created run. - */ - async create( - threadId: string, - assistantId: string, - payload?: RunsCreatePayload, - ): Promise { - const json: Record = { - input: payload?.input, - command: payload?.command, - config: payload?.config, - metadata: payload?.metadata, - stream_mode: payload?.streamMode, - stream_subgraphs: payload?.streamSubgraphs, - stream_resumable: payload?.streamResumable, - assistant_id: assistantId, - interrupt_before: payload?.interruptBefore, - interrupt_after: payload?.interruptAfter, - webhook: payload?.webhook, - checkpoint: payload?.checkpoint, - checkpoint_id: payload?.checkpointId, - multitask_strategy: payload?.multitaskStrategy, - after_seconds: payload?.afterSeconds, - if_not_exists: payload?.ifNotExists, - checkpoint_during: payload?.checkpointDuring, - langsmith_tracer: payload?._langsmithTracer - ? { - project_name: payload?._langsmithTracer?.projectName, - example_id: payload?._langsmithTracer?.exampleId, - } - : undefined, - }; - - const [run, response] = await this.fetch(`/threads/${threadId}/runs`, { - method: "POST", - json, - signal: payload?.signal, - withResponse: true, - }); - - const runMetadata = getRunMetadataFromResponse(response); - if (runMetadata) payload?.onRunCreated?.(runMetadata); - - return run; - } - - /** - * Create a batch of stateless background runs. - * - * @param payloads An array of payloads for creating runs. - * @returns An array of created runs. - */ - async createBatch( - payloads: (RunsCreatePayload & { assistantId: string })[], - ): Promise { - const filteredPayloads = payloads - .map((payload) => ({ ...payload, assistant_id: payload.assistantId })) - .map((payload) => { - return Object.fromEntries( - Object.entries(payload).filter(([_, v]) => v !== undefined), - ); - }); - - return this.fetch("/runs/batch", { - method: "POST", - json: filteredPayloads, - }); - } - - async wait( - threadId: null, - assistantId: string, - payload?: Omit, - ): Promise; - - async wait( - threadId: string, - assistantId: string, - payload?: RunsWaitPayload, - ): Promise; - - /** - * Create a run and wait for it to complete. - * - * @param threadId The ID of the thread. - * @param assistantId Assistant ID to use for this run. - * @param payload Payload for creating a run. - * @returns The last values chunk of the thread. - */ - async wait( - threadId: string | null, - assistantId: string, - payload?: RunsWaitPayload, - ): Promise { - const json: Record = { - input: payload?.input, - command: payload?.command, - config: payload?.config, - metadata: payload?.metadata, - assistant_id: assistantId, - interrupt_before: payload?.interruptBefore, - interrupt_after: payload?.interruptAfter, - checkpoint: payload?.checkpoint, - checkpoint_id: payload?.checkpointId, - webhook: payload?.webhook, - multitask_strategy: payload?.multitaskStrategy, - on_completion: payload?.onCompletion, - on_disconnect: payload?.onDisconnect, - after_seconds: payload?.afterSeconds, - if_not_exists: payload?.ifNotExists, - checkpoint_during: payload?.checkpointDuring, - langsmith_tracer: payload?._langsmithTracer - ? { - project_name: payload?._langsmithTracer?.projectName, - example_id: payload?._langsmithTracer?.exampleId, - } - : undefined, - }; - const endpoint = - threadId == null ? `/runs/wait` : `/threads/${threadId}/runs/wait`; - const [run, response] = await this.fetch(endpoint, { - method: "POST", - json, - timeoutMs: null, - signal: payload?.signal, - withResponse: true, - }); - - const runMetadata = getRunMetadataFromResponse(response); - if (runMetadata) payload?.onRunCreated?.(runMetadata); - - const raiseError = - payload?.raiseError !== undefined ? payload.raiseError : true; - if ( - raiseError && - "__error__" in run && - typeof run.__error__ === "object" && - run.__error__ && - "error" in run.__error__ && - "message" in run.__error__ - ) { - throw new Error(`${run.__error__?.error}: ${run.__error__?.message}`); - } - return run; - } - - /** - * List all runs for a thread. - * - * @param threadId The ID of the thread. - * @param options Filtering and pagination options. - * @returns List of runs. - */ - async list( - threadId: string, - options?: { - /** - * Maximum number of runs to return. - * Defaults to 10 - */ - limit?: number; - - /** - * Offset to start from. - * Defaults to 0. - */ - offset?: number; - - /** - * Status of the run to filter by. - */ - status?: RunStatus; - }, - ): Promise { - return this.fetch(`/threads/${threadId}/runs`, { - params: { - limit: options?.limit ?? 10, - offset: options?.offset ?? 0, - status: options?.status ?? undefined, - }, - }); - } - - /** - * Get a run by ID. - * - * @param threadId The ID of the thread. - * @param runId The ID of the run. - * @returns The run. - */ - async get(threadId: string, runId: string): Promise { - return this.fetch(`/threads/${threadId}/runs/${runId}`); - } - - /** - * Cancel a run. - * - * @param threadId The ID of the thread. - * @param runId The ID of the run. - * @param wait Whether to block when canceling - * @param action Action to take when cancelling the run. Possible values are `interrupt` or `rollback`. Default is `interrupt`. - * @returns - */ - async cancel( - threadId: string, - runId: string, - wait: boolean = false, - action: CancelAction = "interrupt", - ): Promise { - return this.fetch(`/threads/${threadId}/runs/${runId}/cancel`, { - method: "POST", - params: { - wait: wait ? "1" : "0", - action: action, - }, - }); - } - - /** - * Block until a run is done. - * - * @param threadId The ID of the thread. - * @param runId The ID of the run. - * @returns - */ - async join( - threadId: string, - runId: string, - options?: { signal?: AbortSignal }, - ): Promise { - return this.fetch(`/threads/${threadId}/runs/${runId}/join`, { - timeoutMs: null, - signal: options?.signal, - }); - } - - /** - * Stream output from a run in real-time, until the run is done. - * - * @param threadId The ID of the thread. Can be set to `null` | `undefined` for stateless runs. - * @param runId The ID of the run. - * @param options Additional options for controlling the stream behavior: - * - signal: An AbortSignal that can be used to cancel the stream request - * - lastEventId: The ID of the last event received. Can be used to reconnect to a stream without losing events. - * - cancelOnDisconnect: When true, automatically cancels the run if the client disconnects from the stream - * - streamMode: Controls what types of events to receive from the stream (can be a single mode or array of modes) - * Must be a subset of the stream modes passed when creating the run. Background runs default to having the union of all - * stream modes enabled. - * @returns An async generator yielding stream parts. - */ - async *joinStream( - threadId: string | undefined | null, - runId: string, - options?: - | { - signal?: AbortSignal; - cancelOnDisconnect?: boolean; - lastEventId?: string; - streamMode?: StreamMode | StreamMode[]; - } - | AbortSignal, - ): AsyncGenerator<{ id?: string; event: StreamEvent; data: any }> { - const opts = - typeof options === "object" && - options != null && - options instanceof AbortSignal - ? { signal: options } - : options; - - const response = await this.asyncCaller.fetch( - ...this.prepareFetchOptions( - threadId != null - ? `/threads/${threadId}/runs/${runId}/stream` - : `/runs/${runId}/stream`, - { - method: "GET", - timeoutMs: null, - signal: opts?.signal, - headers: opts?.lastEventId - ? { "Last-Event-ID": opts.lastEventId } - : undefined, - params: { - cancel_on_disconnect: opts?.cancelOnDisconnect ? "1" : "0", - stream_mode: opts?.streamMode, - }, - }, - ), - ); - - const stream: ReadableStream<{ event: string; data: any }> = ( - response.body || new ReadableStream({ start: (ctrl) => ctrl.close() }) - ) - .pipeThrough(BytesLineDecoder()) - .pipeThrough(SSEDecoder()); - - yield* IterableReadableStream.fromReadableStream(stream); - } - - /** - * Delete a run. - * - * @param threadId The ID of the thread. - * @param runId The ID of the run. - * @returns - */ - async delete(threadId: string, runId: string): Promise { - return this.fetch(`/threads/${threadId}/runs/${runId}`, { - method: "DELETE", - }); - } -} - -interface APIItem { - namespace: string[]; - key: string; - value: Record; - created_at: string; - updated_at: string; -} -interface APISearchItemsResponse { - items: APIItem[]; -} - -export class StoreClient extends BaseClient { - /** - * Store or update an item. - * - * @param namespace A list of strings representing the namespace path. - * @param key The unique identifier for the item within the namespace. - * @param value A dictionary containing the item's data. - * @param options.index Controls search indexing - null (use defaults), false (disable), or list of field paths to index. - * @param options.ttl Optional time-to-live in minutes for the item, or null for no expiration. - * @returns Promise - * - * @example - * ```typescript - * await client.store.putItem( - * ["documents", "user123"], - * "item456", - * { title: "My Document", content: "Hello World" }, - * { ttl: 60 } // expires in 60 minutes - * ); - * ``` - */ - async putItem( - namespace: string[], - key: string, - value: Record, - options?: { - index?: false | string[] | null; - ttl?: number | null; - }, - ): Promise { - namespace.forEach((label) => { - if (label.includes(".")) { - throw new Error( - `Invalid namespace label '${label}'. Namespace labels cannot contain periods ('.')`, - ); - } - }); - - const payload = { - namespace, - key, - value, - index: options?.index, - ttl: options?.ttl, - }; - - return this.fetch("/store/items", { - method: "PUT", - json: payload, - }); - } - - /** - * Retrieve a single item. - * - * @param namespace A list of strings representing the namespace path. - * @param key The unique identifier for the item. - * @param options.refreshTtl Whether to refresh the TTL on this read operation. If null, uses the store's default behavior. - * @returns Promise - * - * @example - * ```typescript - * const item = await client.store.getItem( - * ["documents", "user123"], - * "item456", - * { refreshTtl: true } - * ); - * console.log(item); - * // { - * // namespace: ["documents", "user123"], - * // key: "item456", - * // value: { title: "My Document", content: "Hello World" }, - * // createdAt: "2024-07-30T12:00:00Z", - * // updatedAt: "2024-07-30T12:00:00Z" - * // } - * ``` - */ - async getItem( - namespace: string[], - key: string, - options?: { - refreshTtl?: boolean | null; - }, - ): Promise { - namespace.forEach((label) => { - if (label.includes(".")) { - throw new Error( - `Invalid namespace label '${label}'. Namespace labels cannot contain periods ('.')`, - ); - } - }); - - const params: Record = { - namespace: namespace.join("."), - key, - }; - - if (options?.refreshTtl !== undefined) { - params.refresh_ttl = options.refreshTtl; - } - - const response = await this.fetch("/store/items", { - params, - }); - - return response - ? { - ...response, - createdAt: response.created_at, - updatedAt: response.updated_at, - } - : null; - } - - /** - * Delete an item. - * - * @param namespace A list of strings representing the namespace path. - * @param key The unique identifier for the item. - * @returns Promise - */ - async deleteItem(namespace: string[], key: string): Promise { - namespace.forEach((label) => { - if (label.includes(".")) { - throw new Error( - `Invalid namespace label '${label}'. Namespace labels cannot contain periods ('.')`, - ); - } - }); - - return this.fetch("/store/items", { - method: "DELETE", - json: { namespace, key }, - }); - } - - /** - * Search for items within a namespace prefix. - * - * @param namespacePrefix List of strings representing the namespace prefix. - * @param options.filter Optional dictionary of key-value pairs to filter results. - * @param options.limit Maximum number of items to return (default is 10). - * @param options.offset Number of items to skip before returning results (default is 0). - * @param options.query Optional search query. - * @param options.refreshTtl Whether to refresh the TTL on items returned by this search. If null, uses the store's default behavior. - * @returns Promise - * - * @example - * ```typescript - * const results = await client.store.searchItems( - * ["documents"], - * { - * filter: { author: "John Doe" }, - * limit: 5, - * refreshTtl: true - * } - * ); - * console.log(results); - * // { - * // items: [ - * // { - * // namespace: ["documents", "user123"], - * // key: "item789", - * // value: { title: "Another Document", author: "John Doe" }, - * // createdAt: "2024-07-30T12:00:00Z", - * // updatedAt: "2024-07-30T12:00:00Z" - * // }, - * // // ... additional items ... - * // ] - * // } - * ``` - */ - async searchItems( - namespacePrefix: string[], - options?: { - filter?: Record; - limit?: number; - offset?: number; - query?: string; - refreshTtl?: boolean | null; - }, - ): Promise { - const payload = { - namespace_prefix: namespacePrefix, - filter: options?.filter, - limit: options?.limit ?? 10, - offset: options?.offset ?? 0, - query: options?.query, - refresh_ttl: options?.refreshTtl, - }; - - const response = await this.fetch( - "/store/items/search", - { - method: "POST", - json: payload, - }, - ); - return { - items: response.items.map((item) => ({ - ...item, - createdAt: item.created_at, - updatedAt: item.updated_at, - })), - }; - } - - /** - * List namespaces with optional match conditions. - * - * @param options.prefix Optional list of strings representing the prefix to filter namespaces. - * @param options.suffix Optional list of strings representing the suffix to filter namespaces. - * @param options.maxDepth Optional integer specifying the maximum depth of namespaces to return. - * @param options.limit Maximum number of namespaces to return (default is 100). - * @param options.offset Number of namespaces to skip before returning results (default is 0). - * @returns Promise - */ - async listNamespaces(options?: { - prefix?: string[]; - suffix?: string[]; - maxDepth?: number; - limit?: number; - offset?: number; - }): Promise { - const payload = { - prefix: options?.prefix, - suffix: options?.suffix, - max_depth: options?.maxDepth, - limit: options?.limit ?? 100, - offset: options?.offset ?? 0, - }; - - return this.fetch("/store/namespaces", { - method: "POST", - json: payload, - }); - } -} - -class UiClient extends BaseClient { - private static promiseCache: Record | undefined> = - {}; - - private static getOrCached(key: string, fn: () => Promise): Promise { - if (UiClient.promiseCache[key] != null) { - return UiClient.promiseCache[key] as Promise; - } - - const promise = fn(); - UiClient.promiseCache[key] = promise; - return promise; - } - - async getComponent(assistantId: string, agentName: string): Promise { - return UiClient["getOrCached"]( - `${this.apiUrl}-${assistantId}-${agentName}`, - async () => { - const response = await this.asyncCaller.fetch( - ...this.prepareFetchOptions(`/ui/${assistantId}`, { - headers: { - Accept: "text/html", - "Content-Type": "application/json", - }, - method: "POST", - json: { name: agentName }, - }), - ); - return response.text(); - }, - ); - } -} - -export class Client< - TStateType = DefaultValues, - TUpdateType = TStateType, - TCustomEventType = unknown, -> { - /** - * The client for interacting with assistants. - */ - public assistants: AssistantsClient; - - /** - * The client for interacting with threads. - */ - public threads: ThreadsClient; - - /** - * The client for interacting with runs. - */ - public runs: RunsClient; - - /** - * The client for interacting with cron runs. - */ - public crons: CronsClient; - - /** - * The client for interacting with the KV store. - */ - public store: StoreClient; - - /** - * The client for interacting with the UI. - * @internal Used by LoadExternalComponent and the API might change in the future. - */ - public "~ui": UiClient; - - /** - * @internal Used to obtain a stable key representing the client. - */ - private "~configHash": string | undefined; - - constructor(config?: ClientConfig) { - this["~configHash"] = (() => - JSON.stringify({ - apiUrl: config?.apiUrl, - apiKey: config?.apiKey, - timeoutMs: config?.timeoutMs, - defaultHeaders: config?.defaultHeaders, - - maxConcurrency: config?.callerOptions?.maxConcurrency, - maxRetries: config?.callerOptions?.maxRetries, - - callbacks: { - onFailedResponseHook: - config?.callerOptions?.onFailedResponseHook != null, - onRequest: config?.onRequest != null, - fetch: config?.callerOptions?.fetch != null, - }, - }))(); - - this.assistants = new AssistantsClient(config); - this.threads = new ThreadsClient(config); - this.runs = new RunsClient(config); - this.crons = new CronsClient(config); - this.store = new StoreClient(config); - this["~ui"] = new UiClient(config); - } -} - -/** - * @internal Used to obtain a stable key representing the client. - */ -export function getClientConfigHash(client: Client): string | undefined { - return client["~configHash"]; -} diff --git a/libs/sdk-js/src/index.ts b/libs/sdk-js/src/index.ts deleted file mode 100644 index 4318bbfc0..000000000 --- a/libs/sdk-js/src/index.ts +++ /dev/null @@ -1,56 +0,0 @@ -export { Client, getApiKey } from "./client.js"; -export type { ClientConfig, RequestHook } from "./client.js"; - -export type { - Assistant, - AssistantBase, - AssistantGraph, - AssistantVersion, - Checkpoint, - Config, - Cron, - CronCreateForThreadResponse, - CronCreateResponse, - DefaultValues, - GraphSchema, - Interrupt, - Item, - ListNamespaceResponse, - Metadata, - Run, - SearchItem, - SearchItemsResponse, - Thread, - ThreadState, - ThreadStatus, - ThreadTask, -} from "./schema.js"; -export { overrideFetchImplementation } from "./singletons/fetch.js"; - -export type { - Command, - OnConflictBehavior, - RunsInvokePayload, -} from "./types.js"; -export type { - AIMessage, - FunctionMessage, - HumanMessage, - Message, - RemoveMessage, - SystemMessage, - ToolMessage, -} from "./types.messages.js"; -export type { - CustomStreamEvent, - DebugStreamEvent, - ErrorStreamEvent, - EventsStreamEvent, - FeedbackStreamEvent, - MessagesStreamEvent, - MessagesTupleStreamEvent, - MetadataStreamEvent, - StreamMode, - UpdatesStreamEvent, - ValuesStreamEvent, -} from "./types.stream.js"; diff --git a/libs/sdk-js/src/react-ui/client.tsx b/libs/sdk-js/src/react-ui/client.tsx deleted file mode 100644 index 1484f491d..000000000 --- a/libs/sdk-js/src/react-ui/client.tsx +++ /dev/null @@ -1,279 +0,0 @@ -"use client"; - -import { useStream } from "../react/index.js"; -import type { UIMessage } from "./types.js"; - -import * as React from "react"; -import * as ReactDOM from "react-dom"; -import * as JsxRuntime from "react/jsx-runtime"; -import type { UseStream } from "../react/stream.js"; - -const UseStreamContext = React.createContext<{ - stream: ReturnType; - meta: unknown; -}>(null!); - -type BagTemplate = { - ConfigurableType?: Record; - InterruptType?: unknown; - CustomEventType?: unknown; - UpdateType?: unknown; - MetaType?: unknown; -}; - -type GetMetaType = Bag extends { MetaType: unknown } - ? Bag["MetaType"] - : unknown; - -interface UseStreamContext< - StateType extends Record = Record, - Bag extends BagTemplate = BagTemplate, -> extends UseStream { - meta?: GetMetaType; -} - -export function useStreamContext< - StateType extends Record = Record, - Bag extends { - ConfigurableType?: Record; - InterruptType?: unknown; - CustomEventType?: unknown; - UpdateType?: unknown; - MetaType?: unknown; - } = BagTemplate, ->(): UseStreamContext { - const ctx = React.useContext(UseStreamContext); - if (!ctx) { - throw new Error( - "useStreamContext must be used within a LoadExternalComponent", - ); - } - - return new Proxy(ctx, { - get(target, prop: keyof UseStreamContext) { - if (prop === "meta") return target.meta; - return target.stream[prop]; - }, - }) as unknown as UseStreamContext; -} - -interface ComponentTarget { - comp: React.FunctionComponent | React.ComponentClass; - target: HTMLElement; -} - -class ComponentStore { - private cache: Record = {}; - private boundCache: Record< - string, - { - subscribe: (onStoreChange: () => void) => () => void; - getSnapshot: () => ComponentTarget | undefined; - } - > = {}; - private callbacks: Record< - string, - (( - comp: React.FunctionComponent | React.ComponentClass, - el: HTMLElement, - ) => void)[] - > = {}; - - respond( - shadowRootId: string, - comp: React.FunctionComponent | React.ComponentClass, - targetElement: HTMLElement, - ) { - this.cache[shadowRootId] = { comp, target: targetElement }; - this.callbacks[shadowRootId]?.forEach((c) => c(comp, targetElement)); - } - - getBoundStore(shadowRootId: string) { - this.boundCache[shadowRootId] ??= { - subscribe: (onStoreChange: () => void) => { - this.callbacks[shadowRootId] ??= []; - this.callbacks[shadowRootId].push(onStoreChange); - return () => { - this.callbacks[shadowRootId] = this.callbacks[shadowRootId].filter( - (c) => c !== onStoreChange, - ); - }; - }, - getSnapshot: () => this.cache[shadowRootId], - }; - - return this.boundCache[shadowRootId]; - } -} - -const COMPONENT_STORE = new ComponentStore(); -const EXT_STORE_SYMBOL = Symbol.for("LGUI_EXT_STORE"); -const REQUIRE_SYMBOL = Symbol.for("LGUI_REQUIRE"); -const REQUIRE_EXTRA_SYMBOL = Symbol.for("LGUI_REQUIRE_EXTRA"); - -interface LoadExternalComponentProps - extends Pick, "style" | "className"> { - /** Stream of the assistant */ - stream: ReturnType; - - /** Namespace of UI components. Defaults to assistant ID. */ - namespace?: string; - - /** UI message to be rendered */ - message: UIMessage; - - /** Additional context to be passed to the child component */ - meta?: unknown; - - /** Fallback to be rendered when the component is loading */ - fallback?: React.ReactNode | Record; - - /** - * Map of components that can be rendered directly without fetching the UI code - * from the server. - */ - components?: Record; -} - -const isIterable = (value: unknown): value is Iterable => - value != null && typeof value === "object" && Symbol.iterator in value; - -const isPromise = (value: unknown): value is Promise => - value != null && - typeof value === "object" && - "then" in value && - typeof value.then === "function"; - -const isReactNode = (value: unknown): value is React.ReactNode => { - if (React.isValidElement(value)) return true; - if (value == null) return true; - if ( - typeof value === "string" || - typeof value === "number" || - typeof value === "bigint" || - typeof value === "boolean" - ) { - return true; - } - - if (isIterable(value)) return true; - if (isPromise(value)) return true; - - return false; -}; - -export function LoadExternalComponent({ - stream, - namespace, - message, - meta, - fallback, - components, - ...props -}: LoadExternalComponentProps) { - const ref = React.useRef(null); - const id = React.useId(); - const shadowRootId = `child-shadow-${id}`; - - const store = React.useMemo( - () => COMPONENT_STORE.getBoundStore(shadowRootId), - [shadowRootId], - ); - const state = React.useSyncExternalStore(store.subscribe, store.getSnapshot); - - const clientComponent = components?.[message.name]; - const hasClientComponent = clientComponent != null; - - const fallbackComponent = isReactNode(fallback) - ? fallback - : typeof fallback === "object" && fallback != null - ? fallback?.[message.name] - : null; - - const uiNamespace = namespace ?? stream.assistantId; - const uiClient = stream.client["~ui"]; - React.useEffect(() => { - if (hasClientComponent) return; - uiClient.getComponent(uiNamespace, message.name).then((html) => { - const dom = ref.current; - if (!dom) return; - const root = dom.shadowRoot ?? dom.attachShadow({ mode: "open" }); - const fragment = document - .createRange() - .createContextualFragment( - html.replace("{{shadowRootId}}", shadowRootId), - ); - root.appendChild(fragment); - }); - }, [uiClient, uiNamespace, message.name, shadowRootId, hasClientComponent]); - - if (hasClientComponent) { - return ( - - {React.createElement(clientComponent, message.props)} - - ); - } - - return ( - <> -
- - - {state?.target != null - ? ReactDOM.createPortal( - React.createElement(state.comp, message.props), - state.target, - ) - : fallbackComponent} - - - ); -} - -declare global { - interface Window { - [EXT_STORE_SYMBOL]: ComponentStore; - [REQUIRE_SYMBOL]: (name: string) => unknown; - [REQUIRE_EXTRA_SYMBOL]: Record; - } -} - -export function experimental_loadShare(name: string, module: unknown) { - if (typeof window === "undefined") return; - - window[REQUIRE_EXTRA_SYMBOL] ??= {}; - window[REQUIRE_EXTRA_SYMBOL][name] = module; -} - -export function bootstrapUiContext() { - if (typeof window === "undefined") { - return; - } - - window[EXT_STORE_SYMBOL] = COMPONENT_STORE; - window[REQUIRE_SYMBOL] = (name: string) => { - if (name === "react") return React; - if (name === "react-dom") return ReactDOM; - if (name === "react/jsx-runtime") return JsxRuntime; - if (name === "@langchain/langgraph-sdk/react") return { useStream }; - if (name === "@langchain/langgraph-sdk/react-ui") { - return { - useStreamContext, - LoadExternalComponent: () => { - throw new Error("Nesting LoadExternalComponent is not supported"); - }, - }; - } - - if ( - window[REQUIRE_EXTRA_SYMBOL] != null && - typeof window[REQUIRE_EXTRA_SYMBOL] === "object" && - name in window[REQUIRE_EXTRA_SYMBOL] - ) { - return window[REQUIRE_EXTRA_SYMBOL][name]; - } - - throw new Error(`Unknown module...: ${name}`); - }; -} diff --git a/libs/sdk-js/src/react-ui/index.ts b/libs/sdk-js/src/react-ui/index.ts deleted file mode 100644 index e63e79d16..000000000 --- a/libs/sdk-js/src/react-ui/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { bootstrapUiContext } from "./client.js"; -bootstrapUiContext(); - -export { - useStreamContext, - LoadExternalComponent, - experimental_loadShare, -} from "./client.js"; -export { - uiMessageReducer, - isUIMessage, - isRemoveUIMessage, - type UIMessage, - type RemoveUIMessage, -} from "./types.js"; diff --git a/libs/sdk-js/src/react-ui/server/index.ts b/libs/sdk-js/src/react-ui/server/index.ts deleted file mode 100644 index 45c2c1e78..000000000 --- a/libs/sdk-js/src/react-ui/server/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export { typedUi } from "./server.js"; -export { - uiMessageReducer, - type UIMessage, - type RemoveUIMessage, -} from "../types.js"; diff --git a/libs/sdk-js/src/react-ui/server/server.ts b/libs/sdk-js/src/react-ui/server/server.ts deleted file mode 100644 index 8eb14d17f..000000000 --- a/libs/sdk-js/src/react-ui/server/server.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { v4 as uuidv4 } from "uuid"; -import type { ComponentPropsWithoutRef, ElementType } from "react"; -import type { RemoveUIMessage, UIMessage } from "../types.js"; - -interface MessageLike { - id?: string; -} - -/** - * Helper to send and persist UI messages. Accepts a map of component names to React components - * as type argument to provide type safety. Will also write to the `options?.stateKey` state. - * - * @param config LangGraphRunnableConfig - * @param options - * @returns - */ -export const typedUi = >( - config: { - writer?: (chunk: unknown) => void; - runId?: string; - metadata?: Record; - tags?: string[]; - runName?: string; - configurable?: { - __pregel_send?: (writes_: [string, unknown][]) => void; - [key: string]: unknown; - }; - }, - options?: { - /** The key to write the UI messages to. Defaults to `ui`. */ - stateKey?: string; - }, -) => { - type PropMap = { [K in keyof Decl]: ComponentPropsWithoutRef }; - let items: (UIMessage | RemoveUIMessage)[] = []; - const stateKey = options?.stateKey ?? "ui"; - - const runId = (config.metadata?.run_id as string | undefined) ?? config.runId; - if (!runId) throw new Error("run_id is required"); - - function handlePush( - message: { - id?: string; - name: K; - props: PropMap[K]; - metadata?: Record; - }, - options?: { message?: MessageLike; merge?: boolean }, - ): UIMessage; - - function handlePush( - message: { - id?: string; - name: K; - props: Partial; - metadata?: Record; - }, - options: { message?: MessageLike; merge: true }, - ): UIMessage>; - - function handlePush( - message: { - id?: string; - name: K; - props: PropMap[K] | Partial; - metadata?: Record; - }, - options?: { message?: MessageLike; merge?: boolean }, - ): UIMessage> { - const evt: UIMessage> = { - type: "ui" as const, - id: message?.id ?? uuidv4(), - name: message?.name, - props: message?.props, - metadata: { - merge: options?.merge || undefined, - run_id: runId, - tags: config.tags, - name: config.runName, - ...message?.metadata, - ...(options?.message ? { message_id: options.message.id } : null), - }, - }; - items.push(evt); - config.writer?.(evt); - config.configurable?.__pregel_send?.([[stateKey, evt]]); - return evt; - } - - const handleDelete = (id: string): RemoveUIMessage => { - const evt: RemoveUIMessage = { type: "remove-ui", id }; - items.push(evt); - config.writer?.(evt); - config.configurable?.__pregel_send?.([[stateKey, evt]]); - return evt; - }; - - return { push: handlePush, delete: handleDelete, items }; -}; diff --git a/libs/sdk-js/src/react-ui/types.ts b/libs/sdk-js/src/react-ui/types.ts deleted file mode 100644 index 42499996d..000000000 --- a/libs/sdk-js/src/react-ui/types.ts +++ /dev/null @@ -1,66 +0,0 @@ -export interface UIMessage< - TName extends string = string, - TProps extends Record = Record, -> { - type: "ui"; - - id: string; - name: TName; - props: TProps; - metadata?: { - merge?: boolean; - run_id?: string; - name?: string; - tags?: string[]; - message_id?: string; - [key: string]: unknown; - }; -} - -export interface RemoveUIMessage { - type: "remove-ui"; - id: string; -} - -export function isUIMessage(message: unknown): message is UIMessage { - if (typeof message !== "object" || message == null) return false; - if (!("type" in message)) return false; - return message.type === "ui"; -} - -export function isRemoveUIMessage( - message: unknown, -): message is RemoveUIMessage { - if (typeof message !== "object" || message == null) return false; - if (!("type" in message)) return false; - return message.type === "remove-ui"; -} - -export function uiMessageReducer( - state: UIMessage[], - update: UIMessage | RemoveUIMessage | (UIMessage | RemoveUIMessage)[], -) { - const events = Array.isArray(update) ? update : [update]; - let newState = state.slice(); - - for (const event of events) { - if (event.type === "remove-ui") { - newState = newState.filter((ui) => ui.id !== event.id); - continue; - } - - const index = state.findIndex((ui) => ui.id === event.id); - if (index !== -1) { - newState[index] = - typeof event.metadata === "object" && - event.metadata != null && - event.metadata.merge - ? { ...event, props: { ...state[index].props, ...event.props } } - : event; - } else { - newState.push(event); - } - } - - return newState; -} diff --git a/libs/sdk-js/src/react/debug.tsx b/libs/sdk-js/src/react/debug.tsx deleted file mode 100644 index b5fc462fc..000000000 --- a/libs/sdk-js/src/react/debug.tsx +++ /dev/null @@ -1,102 +0,0 @@ -import { ThreadState } from "../schema.js"; - -interface Node { - type: "node"; - value: ThreadState; - path: string[]; -} - -interface Fork { - type: "fork"; - items: Array>; -} - -interface Sequence { - type: "sequence"; - items: Array | Fork>; -} - -interface ValidFork { - type: "fork"; - items: Array>; -} - -interface ValidSequence { - type: "sequence"; - items: [Node, ...(Node | ValidFork)[]]; -} - -// forks -export type CheckpointBranchPath = string[]; - -export type MessageBranch = { - current: CheckpointBranchPath; - options: CheckpointBranchPath[]; -}; - -export function DebugSegmentsView(props: { - sequence: ValidSequence; -}) { - const concatContent = (value: ThreadState) => { - let content; - try { - content = value.values?.messages?.at(-1)?.content ?? ""; - } catch { - content = JSON.stringify(value.values); - } - - content = content.replace(/(\n|\r\n)/g, ""); - if (content.length <= 23) return content; - return `${content.slice(0, 10)}...${content.slice(-10)}`; - }; - - return ( -
- {props.sequence.items.map((item, index) => { - if (item.type === "fork") { - return ( -
- {item.items.map((fork, idx) => { - const [first] = fork.items; - return ( -
- - Fork{" "} - - ...{first.path.at(-1)?.slice(-4)} - - -
- -
-
- ); - })} -
- ); - } - - if (item.type === "node") { - return ( -
-
-                ({item.value.metadata?.step}) ...
-                {item.value.checkpoint.checkpoint_id?.slice(-4)} (
-                {item.value.metadata?.source}): {concatContent(item.value)}
-              
- -
- ); - } - - return null; - })} -
- ); -} diff --git a/libs/sdk-js/src/react/index.ts b/libs/sdk-js/src/react/index.ts deleted file mode 100644 index 9b7e22871..000000000 --- a/libs/sdk-js/src/react/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export { - useStream, - type MessageMetadata, - type UseStream, - type UseStreamOptions, -} from "./stream.js"; diff --git a/libs/sdk-js/src/react/stream.tsx b/libs/sdk-js/src/react/stream.tsx deleted file mode 100644 index 4b7159ee1..000000000 --- a/libs/sdk-js/src/react/stream.tsx +++ /dev/null @@ -1,1264 +0,0 @@ -/* __LC_ALLOW_ENTRYPOINT_SIDE_EFFECTS__ */ -"use client"; - -import { Client, getClientConfigHash, type ClientConfig } from "../client.js"; -import type { - Command, - DisconnectMode, - MultitaskStrategy, - OnCompletionBehavior, -} from "../types.js"; -import type { Message } from "../types.messages.js"; -import type { - Checkpoint, - Config, - Interrupt, - Metadata, - ThreadState, -} from "../schema.js"; -import type { - CustomStreamEvent, - DebugStreamEvent, - ErrorStreamEvent, - EventsStreamEvent, - FeedbackStreamEvent, - MessagesStreamEvent, - MessagesTupleStreamEvent, - MetadataStreamEvent, - StreamMode, - UpdatesStreamEvent, - ValuesStreamEvent, -} from "../types.stream.js"; - -import { - type RefObject, - useCallback, - useEffect, - useMemo, - useRef, - useState, -} from "react"; -import { - type BaseMessageChunk, - type BaseMessage, - coerceMessageLikeToMessage, - convertToChunk, - isBaseMessageChunk, -} from "@langchain/core/messages"; - -class StreamError extends Error { - constructor(data: { error?: string; name?: string; message: string }) { - super(data.message); - this.name = data.name ?? data.error ?? "StreamError"; - } - - static isStructuredError(error: unknown): error is { - error?: string; - name?: string; - message: string; - } { - return typeof error === "object" && error != null && "message" in error; - } -} - -function tryConvertToChunk(message: BaseMessage): BaseMessageChunk | null { - try { - return convertToChunk(message); - } catch { - return null; - } -} - -class MessageTupleManager { - chunks: Record< - string, - { chunk?: BaseMessageChunk | BaseMessage; index?: number } - > = {}; - - constructor() { - this.chunks = {}; - } - - add(serialized: Message): string | null { - // TODO: this is sometimes sent from the API - // figure out how to prevent this or move this to LC.js - if (serialized.type.endsWith("MessageChunk")) { - serialized.type = serialized.type - .slice(0, -"MessageChunk".length) - .toLowerCase() as Message["type"]; - } - - const message = coerceMessageLikeToMessage(serialized); - const chunk = tryConvertToChunk(message); - - const id = (chunk ?? message).id; - if (!id) { - console.warn( - "No message ID found for chunk, ignoring in state", - serialized, - ); - return null; - } - - this.chunks[id] ??= {}; - if (chunk) { - const prev = this.chunks[id].chunk; - this.chunks[id].chunk = - (isBaseMessageChunk(prev) ? prev : null)?.concat(chunk) ?? chunk; - } else { - this.chunks[id].chunk = message; - } - - return id; - } - - clear() { - this.chunks = {}; - } - - get(id: string, defaultIndex: number) { - if (this.chunks[id] == null) return null; - this.chunks[id].index ??= defaultIndex; - - return this.chunks[id]; - } -} - -const toMessageDict = (chunk: BaseMessage): Message => { - const { type, data } = chunk.toDict(); - return { ...data, type } as Message; -}; - -function unique(array: T[]) { - return [...new Set(array)] as T[]; -} - -function findLastIndex(array: T[], predicate: (item: T) => boolean) { - for (let i = array.length - 1; i >= 0; i--) { - if (predicate(array[i])) return i; - } - return -1; -} - -interface Node { - type: "node"; - value: ThreadState; - path: string[]; -} - -interface Fork { - type: "fork"; - items: Array>; -} - -interface Sequence { - type: "sequence"; - items: Array | Fork>; -} - -interface ValidFork { - type: "fork"; - items: Array>; -} - -interface ValidSequence { - type: "sequence"; - items: [Node, ...(Node | ValidFork)[]]; -} - -export type MessageMetadata> = { - /** - * The ID of the message used. - */ - messageId: string; - - /** - * The first thread state the message was seen in. - */ - firstSeenState: ThreadState | undefined; - - /** - * The branch of the message. - */ - branch: string | undefined; - - /** - * The list of branches this message is part of. - * This is useful for displaying branching controls. - */ - branchOptions: string[] | undefined; -}; - -function getBranchSequence>( - history: ThreadState[], -) { - const childrenMap: Record[]> = {}; - - // First pass - collect nodes for each checkpoint - history.forEach((state) => { - const checkpointId = state.parent_checkpoint?.checkpoint_id ?? "$"; - childrenMap[checkpointId] ??= []; - childrenMap[checkpointId].push(state); - }); - - // Second pass - create a tree of sequences - type Task = { id: string; sequence: Sequence; path: string[] }; - const rootSequence: Sequence = { type: "sequence", items: [] }; - const queue: Task[] = [{ id: "$", sequence: rootSequence, path: [] }]; - - const paths: string[][] = []; - - const visited = new Set(); - while (queue.length > 0) { - const task = queue.shift()!; - if (visited.has(task.id)) continue; - visited.add(task.id); - - const children = childrenMap[task.id]; - if (children == null || children.length === 0) continue; - - // If we've encountered a fork (2+ children), push the fork - // to the sequence and add a new sequence for each child - let fork: Fork | undefined; - if (children.length > 1) { - fork = { type: "fork", items: [] }; - task.sequence.items.push(fork); - } - - for (const value of children) { - const id = value.checkpoint.checkpoint_id!; - - let sequence = task.sequence; - let path = task.path; - if (fork != null) { - sequence = { type: "sequence", items: [] }; - fork.items.unshift(sequence); - - path = path.slice(); - path.push(id); - paths.push(path); - } - - sequence.items.push({ type: "node", value, path }); - queue.push({ id, sequence, path }); - } - } - - return { rootSequence, paths }; -} - -const PATH_SEP = ">"; -const ROOT_ID = "$"; - -// Get flat view -function getBranchView>( - sequence: Sequence, - paths: string[][], - branch: string, -) { - const path = branch.split(PATH_SEP); - const pathMap: Record = {}; - - for (const path of paths) { - const parent = path.at(-2) ?? ROOT_ID; - pathMap[parent] ??= []; - pathMap[parent].unshift(path); - } - - const history: ThreadState[] = []; - const branchByCheckpoint: Record< - string, - { branch: string | undefined; branchOptions: string[] | undefined } - > = {}; - - const forkStack = path.slice(); - const queue: (Node | Fork)[] = [...sequence.items]; - - while (queue.length > 0) { - const item = queue.shift()!; - - if (item.type === "node") { - history.push(item.value); - branchByCheckpoint[item.value.checkpoint.checkpoint_id!] = { - branch: item.path.join(PATH_SEP), - branchOptions: (item.path.length > 0 - ? pathMap[item.path.at(-2) ?? ROOT_ID] ?? [] - : [] - ).map((p) => p.join(PATH_SEP)), - }; - } - if (item.type === "fork") { - const forkId = forkStack.shift(); - const index = - forkId != null - ? item.items.findIndex((value) => { - const firstItem = value.items.at(0); - if (!firstItem || firstItem.type !== "node") return false; - return firstItem.value.checkpoint.checkpoint_id === forkId; - }) - : -1; - - const nextItems = item.items.at(index)?.items ?? []; - queue.push(...nextItems); - } - } - - return { history, branchByCheckpoint }; -} - -function fetchHistory>( - client: Client, - threadId: string, -) { - return client.threads.getHistory(threadId, { limit: 1000 }); -} - -function useThreadHistory>( - threadId: string | undefined | null, - client: Client, - clearCallbackRef: RefObject<(() => void) | undefined>, - submittingRef: RefObject, -) { - const [history, setHistory] = useState[]>([]); - - const clientHash = getClientConfigHash(client); - const clientRef = useRef(client); - clientRef.current = client; - - const fetcher = useCallback( - ( - threadId: string | undefined | null, - ): Promise[]> => { - if (threadId != null) { - const client = clientRef.current; - return fetchHistory(client, threadId).then((history) => { - setHistory(history); - return history; - }); - } - - setHistory([]); - clearCallbackRef.current?.(); - return Promise.resolve([]); - }, - [], - ); - - useEffect(() => { - if (submittingRef.current) return; - fetcher(threadId); - }, [fetcher, clientHash, submittingRef, threadId]); - - return { - data: history, - mutate: (mutateId?: string) => fetcher(mutateId ?? threadId), - }; -} - -const useControllableThreadId = (options?: { - threadId?: string | null; - onThreadId?: (threadId: string) => void; -}): [string | null, (threadId: string) => void] => { - const [localThreadId, _setLocalThreadId] = useState( - options?.threadId ?? null, - ); - - const onThreadIdRef = useRef(options?.onThreadId); - onThreadIdRef.current = options?.onThreadId; - - const onThreadId = useCallback((threadId: string) => { - _setLocalThreadId(threadId); - onThreadIdRef.current?.(threadId); - }, []); - - if (!options || !("threadId" in options)) { - return [localThreadId, onThreadId]; - } - - return [options.threadId ?? null, onThreadId]; -}; - -type BagTemplate = { - ConfigurableType?: Record; - InterruptType?: unknown; - CustomEventType?: unknown; - UpdateType?: unknown; -}; - -type GetUpdateType< - Bag extends BagTemplate, - StateType extends Record, -> = Bag extends { UpdateType: unknown } - ? Bag["UpdateType"] - : Partial; - -type GetConfigurableType = Bag extends { - ConfigurableType: Record; -} - ? Bag["ConfigurableType"] - : Record; - -type GetInterruptType = Bag extends { - InterruptType: unknown; -} - ? Bag["InterruptType"] - : unknown; - -type GetCustomEventType = Bag extends { - CustomEventType: unknown; -} - ? Bag["CustomEventType"] - : unknown; - -interface RunCallbackMeta { - run_id: string; - thread_id: string; -} - -export interface UseStreamOptions< - StateType extends Record = Record, - Bag extends BagTemplate = BagTemplate, -> { - /** - * The ID of the assistant to use. - */ - assistantId: string; - - /** - * Client used to send requests. - */ - client?: Client; - - /** - * The URL of the API to use. - */ - apiUrl?: ClientConfig["apiUrl"]; - - /** - * The API key to use. - */ - apiKey?: ClientConfig["apiKey"]; - - /** - * Custom call options, such as custom fetch implementation. - */ - callerOptions?: ClientConfig["callerOptions"]; - - /** - * Default headers to send with requests. - */ - defaultHeaders?: ClientConfig["defaultHeaders"]; - - /** - * Specify the key within the state that contains messages. - * Defaults to "messages". - * - * @default "messages" - */ - messagesKey?: string; - - /** - * Callback that is called when an error occurs. - */ - onError?: (error: unknown, run: RunCallbackMeta | undefined) => void; - - /** - * Callback that is called when the stream is finished. - */ - onFinish?: ( - state: ThreadState, - run: RunCallbackMeta | undefined, - ) => void; - - /** - * Callback that is called when a new stream is created. - */ - onCreated?: (run: RunCallbackMeta) => void; - - /** - * Callback that is called when an update event is received. - */ - onUpdateEvent?: ( - data: UpdatesStreamEvent>["data"], - ) => void; - - /** - * Callback that is called when a custom event is received. - */ - onCustomEvent?: ( - data: CustomStreamEvent>["data"], - options: { - mutate: ( - update: Partial | ((prev: StateType) => Partial), - ) => void; - }, - ) => void; - - /** - * Callback that is called when a metadata event is received. - */ - onMetadataEvent?: (data: MetadataStreamEvent["data"]) => void; - - /** - * Callback that is called when a LangChain event is received. - * @see https://langchain-ai.github.io/langgraph/cloud/how-tos/stream_events/#stream-graph-in-events-mode for more details. - */ - onLangChainEvent?: (data: EventsStreamEvent["data"]) => void; - - /** - * Callback that is called when a debug event is received. - * @internal This API is experimental and subject to change. - */ - onDebugEvent?: (data: DebugStreamEvent["data"]) => void; - - /** - * Callback that is called when the stream is stopped by the user. - * Provides a mutate function to update the stream state immediately - * without requiring a server roundtrip. - * - * @example - * ```typescript - * onStop: ({ mutate }) => { - * mutate((prev) => ({ - * ...prev, - * ui: prev.ui?.map(component => - * component.props.isLoading - * ? { ...component, props: { ...component.props, stopped: true, isLoading: false }} - * : component - * ) - * })); - * } - * ``` - */ - onStop?: (options: { - mutate: ( - update: Partial | ((prev: StateType) => Partial), - ) => void; - }) => void; - - /** - * The ID of the thread to fetch history and current values from. - */ - threadId?: string | null; - - /** - * Callback that is called when the thread ID is updated (ie when a new thread is created). - */ - onThreadId?: (threadId: string) => void; - - /** Will reconnect the stream on mount */ - reconnectOnMount?: boolean | (() => RunMetadataStorage); - - /** - * Initial values to display immediately when loading a thread. - * Useful for displaying cached thread data while official history loads. - * These values will be replaced when official thread data is fetched. - * - * Note: UI components from initialValues will render immediately if they're - * predefined in LoadExternalComponent's components prop, providing instant - * cached UI display without server fetches. - */ - initialValues?: StateType | null; -} - -interface RunMetadataStorage { - getItem(key: `lg:stream:${string}`): string | null; - setItem(key: `lg:stream:${string}`, value: string): void; - removeItem(key: `lg:stream:${string}`): void; -} - -export interface UseStream< - StateType extends Record = Record, - Bag extends BagTemplate = BagTemplate, -> { - /** - * The current values of the thread. - */ - values: StateType; - - /** - * Last seen error from the thread or during streaming. - */ - error: unknown; - - /** - * Whether the stream is currently running. - */ - isLoading: boolean; - - /** - * Stops the stream. - */ - stop: () => void; - - /** - * Create and stream a run to the thread. - */ - submit: ( - values: GetUpdateType | null | undefined, - options?: SubmitOptions>, - ) => void; - - /** - * The current branch of the thread. - */ - branch: string; - - /** - * Set the branch of the thread. - */ - setBranch: (branch: string) => void; - - /** - * Flattened history of thread states of a thread. - */ - history: ThreadState[]; - - /** - * Tree of all branches for the thread. - * @experimental - */ - experimental_branchTree: Sequence; - - /** - * Get the interrupt value for the stream if interrupted. - */ - interrupt: Interrupt> | undefined; - - /** - * Messages inferred from the thread. - * Will automatically update with incoming message chunks. - */ - messages: Message[]; - - /** - * Get the metadata for a message, such as first thread state the message - * was seen in and branch information. - - * @param message - The message to get the metadata for. - * @param index - The index of the message in the thread. - * @returns The metadata for the message. - */ - getMessagesMetadata: ( - message: Message, - index?: number, - ) => MessageMetadata | undefined; - - /** - * LangGraph SDK client used to send request and receive responses. - */ - client: Client; - - /** - * The ID of the assistant to use. - */ - assistantId: string; - - /** - * Join an active stream. - */ - joinStream: ( - runId: string, - lastEventId?: string, - options?: { streamMode?: StreamMode | StreamMode[] }, - ) => Promise; -} - -type ConfigWithConfigurable> = - Config & { configurable?: ConfigurableType }; - -interface SubmitOptions< - StateType extends Record = Record, - ConfigurableType extends Record = Record, -> { - config?: ConfigWithConfigurable; - checkpoint?: Omit | null; - command?: Command; - interruptBefore?: "*" | string[]; - interruptAfter?: "*" | string[]; - metadata?: Metadata; - multitaskStrategy?: MultitaskStrategy; - onCompletion?: OnCompletionBehavior; - onDisconnect?: DisconnectMode; - feedbackKeys?: string[]; - streamMode?: Array; - optimisticValues?: - | Partial - | ((prev: StateType) => Partial); - /** - * Whether or not to stream the nodes of any subgraphs called - * by the assistant. - * @default false - */ - streamSubgraphs?: boolean; - streamResumable?: boolean; - /** - * The ID to use when creating a new thread. When provided, this ID will be used - * for thread creation when threadId is `null` or `undefined`. - * This enables optimistic UI updates where you know the thread ID - * before the thread is actually created. - */ - threadId?: string; -} - -function useStreamValuesState>() { - type Kind = "stream" | "stop"; - type Values = StateType | null; - type Update = Values | ((prev: Values, kind?: Kind) => Values); - type Mutate = Partial | ((prev: StateType) => Partial); - - const [values, setValues] = useState<[values: StateType, kind: Kind] | null>( - null, - ); - - const setStreamValues = useCallback( - (values: Update, kind: Kind = "stream") => { - if (typeof values === "function") { - setValues((prevTuple) => { - const [prevValues, prevKind] = prevTuple ?? [null, "stream"]; - const next = values(prevValues, prevKind); - - if (next == null) return null; - return [next, kind] as [StateType, Kind]; - }); - - return; - } - - if (values == null) setValues(null); - setValues([values, kind] as [StateType, Kind]); - }, - [], - ); - - const mutate = useCallback( - (kind: Kind, serverValues: StateType) => (update: Mutate) => { - setStreamValues((clientValues) => { - const prev = { ...serverValues, ...clientValues }; - const next = typeof update === "function" ? update(prev) : update; - return { ...prev, ...next }; - }, kind); - }, - [setStreamValues], - ); - - return [values?.[0] ?? null, setStreamValues, mutate] as [ - Values, - (update: Update, kind?: Kind) => void, - (kind: Kind, serverValues: StateType) => (update: Mutate) => void, - ]; -} - -export function useStream< - StateType extends Record = Record, - Bag extends { - ConfigurableType?: Record; - InterruptType?: unknown; - CustomEventType?: unknown; - UpdateType?: unknown; - } = BagTemplate, ->(options: UseStreamOptions): UseStream { - type UpdateType = GetUpdateType; - type CustomType = GetCustomEventType; - type InterruptType = GetInterruptType; - type ConfigurableType = GetConfigurableType; - - type EventStreamEvent = - | ValuesStreamEvent - | UpdatesStreamEvent - | CustomStreamEvent - | DebugStreamEvent - | MessagesStreamEvent - | MessagesTupleStreamEvent - | EventsStreamEvent - | MetadataStreamEvent - | ErrorStreamEvent - | FeedbackStreamEvent; - - let { assistantId, messagesKey, onCreated, onError, onFinish } = options; - - const reconnectOnMountRef = useRef(options.reconnectOnMount); - const runMetadataStorage = useMemo(() => { - if (typeof window === "undefined") return null; - const storage = reconnectOnMountRef.current; - if (storage === true) return window.sessionStorage; - if (typeof storage === "function") return storage(); - return null; - }, []); - - messagesKey ??= "messages"; - - const client = useMemo( - () => - options.client ?? - new Client({ - apiUrl: options.apiUrl, - apiKey: options.apiKey, - callerOptions: options.callerOptions, - defaultHeaders: options.defaultHeaders, - }), - [ - options.client, - options.apiKey, - options.apiUrl, - options.callerOptions, - options.defaultHeaders, - ], - ); - - const [threadId, onThreadId] = useControllableThreadId(options); - - const [branch, setBranch] = useState(""); - const [isLoading, setIsLoading] = useState(false); - - const [streamError, setStreamError] = useState(undefined); - const [streamValues, setStreamValues, getMutateFn] = - useStreamValuesState(); - - const messageManagerRef = useRef(new MessageTupleManager()); - const submittingRef = useRef(false); - const abortRef = useRef(null); - - const trackStreamModeRef = useRef< - Array<"values" | "updates" | "events" | "custom" | "messages-tuple"> - >([]); - - const trackStreamMode = useCallback( - (...mode: Exclude[]) => { - for (const m of mode) { - if (!trackStreamModeRef.current.includes(m)) { - trackStreamModeRef.current.push(m); - } - } - }, - [], - ); - - const hasUpdateListener = options.onUpdateEvent != null; - const hasCustomListener = options.onCustomEvent != null; - const hasLangChainListener = options.onLangChainEvent != null; - const hasDebugListener = options.onDebugEvent != null; - - const callbackStreamMode = useMemo(() => { - const modes: Exclude[] = []; - if (hasUpdateListener) modes.push("updates"); - if (hasCustomListener) modes.push("custom"); - if (hasLangChainListener) modes.push("events"); - if (hasDebugListener) modes.push("debug"); - return modes; - }, [ - hasUpdateListener, - hasCustomListener, - hasLangChainListener, - hasDebugListener, - ]); - - const clearCallbackRef = useRef<() => void>(null!); - clearCallbackRef.current = () => { - setStreamError(undefined); - setStreamValues(null); - }; - - // TODO: this should be done on the server to avoid pagination - // TODO: should we permit adapter? SWR / React Query? - // TODO: make this only when branching is expected - const history = useThreadHistory( - threadId, - client, - clearCallbackRef, - submittingRef, - ); - - const getMessages = useMemo(() => { - return (value: StateType) => - Array.isArray(value[messagesKey]) - ? (value[messagesKey] as Message[]) - : []; - }, [messagesKey]); - - const { rootSequence, paths } = getBranchSequence(history.data); - const { history: flatHistory, branchByCheckpoint } = getBranchView( - rootSequence, - paths, - branch, - ); - - const threadHead: ThreadState | undefined = flatHistory.at(-1); - const historyValues = - threadHead?.values ?? options.initialValues ?? ({} as StateType); - - const historyError = (() => { - const error = threadHead?.tasks?.at(-1)?.error; - if (error == null) return undefined; - try { - const parsed = JSON.parse(error) as unknown; - if (StreamError.isStructuredError(parsed)) { - return new StreamError(parsed); - } - - return parsed; - } catch { - // do nothing - } - return error; - })(); - - const messageMetadata = (() => { - const alreadyShown = new Set(); - return getMessages(historyValues).map( - (message, idx): MessageMetadata => { - const messageId = message.id ?? idx; - const firstSeenIdx = findLastIndex(history.data, (state) => - getMessages(state.values) - .map((m, idx) => m.id ?? idx) - .includes(messageId), - ); - - const firstSeen = history.data[firstSeenIdx] as - | ThreadState - | undefined; - - let branch = firstSeen - ? branchByCheckpoint[firstSeen.checkpoint.checkpoint_id!] - : undefined; - - if (!branch?.branch?.length) branch = undefined; - - // serialize branches - const optionsShown = branch?.branchOptions?.flat(2).join(","); - if (optionsShown) { - if (alreadyShown.has(optionsShown)) branch = undefined; - alreadyShown.add(optionsShown); - } - - return { - messageId: messageId.toString(), - firstSeenState: firstSeen, - - branch: branch?.branch, - branchOptions: branch?.branchOptions, - }; - }, - ); - })(); - - const stop = () => { - if (abortRef.current != null) abortRef.current.abort(); - abortRef.current = null; - - if (runMetadataStorage && threadId) { - const runId = runMetadataStorage.getItem(`lg:stream:${threadId}`); - if (runId) client.runs.cancel(threadId, runId); - runMetadataStorage.removeItem(`lg:stream:${threadId}`); - } - - options?.onStop?.({ mutate: getMutateFn("stop", historyValues) }); - }; - - async function consumeStream( - action: (signal: AbortSignal) => Promise<{ - onSuccess: () => Promise[]>; - stream: AsyncGenerator; - getCallbackMeta: () => { thread_id: string; run_id: string } | undefined; - }>, - ) { - let getCallbackMeta: - | (() => { thread_id: string; run_id: string } | undefined) - | undefined; - try { - setIsLoading(true); - setStreamError(undefined); - - submittingRef.current = true; - abortRef.current = new AbortController(); - - const run = await action(abortRef.current.signal); - getCallbackMeta = run.getCallbackMeta; - - let streamError: StreamError | undefined; - for await (const { event, data } of run.stream) { - if (event === "error") { - streamError = new StreamError(data); - break; - } - - if (event === "updates") options.onUpdateEvent?.(data); - if (event === "custom") - options.onCustomEvent?.(data, { - mutate: getMutateFn("stream", historyValues), - }); - if (event === "metadata") options.onMetadataEvent?.(data); - if (event === "events") options.onLangChainEvent?.(data); - if (event === "debug") options.onDebugEvent?.(data); - - if (event === "values") { - if ("__interrupt__" in data) { - // don't update values on interrupt values event - continue; - } - setStreamValues(data); - } - if (event === "messages") { - const [serialized] = data; - - const messageId = messageManagerRef.current.add(serialized); - if (!messageId) { - console.warn( - "Failed to add message to manager, no message ID found", - ); - continue; - } - - setStreamValues((streamValues) => { - const values = { ...historyValues, ...streamValues }; - - // Assumption: we're concatenating the message - const messages = getMessages(values).slice(); - const { chunk, index } = - messageManagerRef.current.get(messageId, messages.length) ?? {}; - - if (!chunk || index == null) return values; - messages[index] = toMessageDict(chunk); - - return { ...values, [messagesKey!]: messages }; - }); - } - } - - // TODO: stream created checkpoints to avoid an unnecessary network request - const result = await run.onSuccess(); - setStreamValues((values, kind) => { - // Do not clear out the user values set on `stop`. - if (kind === "stop") return values; - return null; - }); - if (streamError != null) throw streamError; - - const lastHead = result.at(0); - if (lastHead) onFinish?.(lastHead, getCallbackMeta?.()); - } catch (error) { - if ( - !( - error instanceof Error && - (error.name === "AbortError" || error.name === "TimeoutError") - ) - ) { - console.error(error); - setStreamError(error); - onError?.(error, getCallbackMeta?.()); - } - } finally { - setIsLoading(false); - - // Assumption: messages are already handled, we can clear the manager - messageManagerRef.current.clear(); - submittingRef.current = false; - abortRef.current = null; - } - } - - const joinStream = async ( - runId: string, - lastEventId?: string, - options?: { streamMode?: StreamMode | StreamMode[] }, - ) => { - lastEventId ??= "-1"; - if (!threadId) return; - await consumeStream(async (signal: AbortSignal) => { - const stream = client.runs.joinStream(threadId, runId, { - signal, - lastEventId, - streamMode: options?.streamMode, - }) as AsyncGenerator; - - return { - onSuccess: () => { - runMetadataStorage?.removeItem(`lg:stream:${threadId}`); - return history.mutate(threadId); - }, - stream, - getCallbackMeta: () => ({ thread_id: threadId, run_id: runId }), - }; - }); - }; - - const submit = async ( - values: UpdateType | null | undefined, - submitOptions?: SubmitOptions, - ) => { - await consumeStream(async (signal: AbortSignal) => { - // Unbranch things - const newPath = submitOptions?.checkpoint?.checkpoint_id - ? branchByCheckpoint[submitOptions?.checkpoint?.checkpoint_id]?.branch - : undefined; - - if (newPath != null) setBranch(newPath ?? ""); - - setStreamValues(() => { - if (submitOptions?.optimisticValues != null) { - return { - ...historyValues, - ...(typeof submitOptions.optimisticValues === "function" - ? submitOptions.optimisticValues(historyValues) - : submitOptions.optimisticValues), - }; - } - - return { ...historyValues }; - }); - - let usableThreadId = threadId; - if (!usableThreadId) { - const thread = await client.threads.create({ - threadId: submitOptions?.threadId, - }); - onThreadId(thread.thread_id); - usableThreadId = thread.thread_id; - } - - const streamMode = unique([ - ...(submitOptions?.streamMode ?? []), - ...trackStreamModeRef.current, - ...callbackStreamMode, - ]); - - const checkpoint = - submitOptions?.checkpoint ?? threadHead?.checkpoint ?? undefined; - // @ts-expect-error - if (checkpoint != null) delete checkpoint.thread_id; - let rejoinKey: `lg:stream:${string}` | undefined; - let callbackMeta: RunCallbackMeta | undefined; - const streamResumable = - submitOptions?.streamResumable ?? !!runMetadataStorage; - - const stream = client.runs.stream(usableThreadId, assistantId, { - input: values as Record, - config: submitOptions?.config, - command: submitOptions?.command, - - interruptBefore: submitOptions?.interruptBefore, - interruptAfter: submitOptions?.interruptAfter, - metadata: submitOptions?.metadata, - multitaskStrategy: submitOptions?.multitaskStrategy, - onCompletion: submitOptions?.onCompletion, - onDisconnect: - submitOptions?.onDisconnect ?? - (streamResumable ? "continue" : "cancel"), - - signal, - - checkpoint, - streamMode, - streamSubgraphs: submitOptions?.streamSubgraphs, - streamResumable, - onRunCreated(params) { - callbackMeta = { - run_id: params.run_id, - thread_id: params.thread_id ?? usableThreadId, - }; - - if (runMetadataStorage) { - rejoinKey = `lg:stream:${callbackMeta.thread_id}`; - runMetadataStorage.setItem(rejoinKey, callbackMeta.run_id); - } - onCreated?.(callbackMeta); - }, - }) as AsyncGenerator; - - return { - stream, - getCallbackMeta: () => callbackMeta, - onSuccess: () => { - if (rejoinKey) runMetadataStorage?.removeItem(rejoinKey); - return history.mutate(usableThreadId); - }, - }; - }); - }; - - const reconnectKey = useMemo(() => { - if (!runMetadataStorage || isLoading) return undefined; - if (typeof window === "undefined") return undefined; - const runId = runMetadataStorage?.getItem(`lg:stream:${threadId}`); - if (!runId) return undefined; - return { runId, threadId }; - }, [runMetadataStorage, isLoading, threadId]); - - const shouldReconnect = !!runMetadataStorage; - const reconnectRef = useRef({ threadId, shouldReconnect }); - - const joinStreamRef = useRef(joinStream); - joinStreamRef.current = joinStream; - - useEffect(() => { - // reset shouldReconnect when switching threads - if (reconnectRef.current.threadId !== threadId) { - reconnectRef.current = { threadId, shouldReconnect }; - } - }, [threadId, shouldReconnect]); - - useEffect(() => { - if (reconnectKey && reconnectRef.current.shouldReconnect) { - reconnectRef.current.shouldReconnect = false; - joinStreamRef.current?.(reconnectKey.runId); - } - }, [reconnectKey]); - - const error = streamError ?? historyError; - const values = streamValues ?? historyValues; - - return { - get values() { - trackStreamMode("values"); - return values; - }, - - client, - assistantId, - - error, - isLoading, - - stop, - submit, - - joinStream, - - branch, - setBranch, - - history: flatHistory, - experimental_branchTree: rootSequence, - - get interrupt() { - // Don't show the interrupt if the stream is loading - if (isLoading) return undefined; - - const interrupts = threadHead?.tasks?.at(-1)?.interrupts; - if (interrupts == null || interrupts.length === 0) { - // check if there's a next task present - const next = threadHead?.next ?? []; - if (!next.length || error != null) return undefined; - return { when: "breakpoint" }; - } - - // Return only the current interrupt - return interrupts.at(-1) as Interrupt | undefined; - }, - - get messages() { - trackStreamMode("messages-tuple", "values"); - return getMessages(values); - }, - - getMessagesMetadata( - message: Message, - index?: number, - ): MessageMetadata | undefined { - trackStreamMode("messages-tuple", "values"); - return messageMetadata?.find( - (m) => m.messageId === (message.id ?? index), - ); - }, - }; -} diff --git a/libs/sdk-js/src/schema.ts b/libs/sdk-js/src/schema.ts deleted file mode 100644 index 877cc7a18..000000000 --- a/libs/sdk-js/src/schema.ts +++ /dev/null @@ -1,334 +0,0 @@ -import type { JSONSchema7 } from "json-schema"; - -type Optional = T | null | undefined; - -export type RunStatus = - | "pending" - | "running" - | "error" - | "success" - | "timeout" - | "interrupted"; - -export type ThreadStatus = "idle" | "busy" | "interrupted" | "error"; - -type MultitaskStrategy = "reject" | "interrupt" | "rollback" | "enqueue"; - -export type CancelAction = "interrupt" | "rollback"; - -export type Config = { - /** - * Tags for this call and any sub-calls (eg. a Chain calling an LLM). - * You can use these to filter calls. - */ - tags?: string[]; - - /** - * Maximum number of times a call can recurse. - * If not provided, defaults to 25. - */ - recursion_limit?: number; - - /** - * Runtime values for attributes previously made configurable on this Runnable. - */ - configurable?: { - /** - * ID of the thread - */ - thread_id?: Optional; - - /** - * Timestamp of the state checkpoint - */ - checkpoint_id?: Optional; - - [key: string]: unknown; - }; -}; - -export interface GraphSchema { - /** - * The ID of the graph. - */ - graph_id: string; - - /** - * The schema for the input state. - * Missing if unable to generate JSON schema from graph. - */ - input_schema?: JSONSchema7 | null | undefined; - - /** - * The schema for the output state. - * Missing if unable to generate JSON schema from graph. - */ - output_schema?: JSONSchema7 | null | undefined; - - /** - * The schema for the graph state. - * Missing if unable to generate JSON schema from graph. - */ - state_schema?: JSONSchema7 | null | undefined; - - /** - * The schema for the graph config. - * Missing if unable to generate JSON schema from graph. - */ - config_schema?: JSONSchema7 | null | undefined; -} - -export type Subgraphs = Record; - -export type Metadata = Optional<{ - source?: "input" | "loop" | "update" | (string & {}); - - step?: number; - - writes?: Record | null; - - parents?: Record; - - [key: string]: unknown; -}>; - -export interface AssistantBase { - /** The ID of the assistant. */ - assistant_id: string; - - /** The ID of the graph. */ - graph_id: string; - - /** The assistant config. */ - config: Config; - - /** The time the assistant was created. */ - created_at: string; - - /** The assistant metadata. */ - metadata: Metadata; - - /** The version of the assistant. */ - version: number; - - /** The name of the assistant */ - name: string; - - /** The description of the assistant */ - description?: string; -} - -export interface AssistantVersion extends AssistantBase {} - -export interface Assistant extends AssistantBase { - /** The last time the assistant was updated. */ - updated_at: string; -} - -export interface AssistantGraph { - nodes: Array<{ - id: string | number; - name?: string; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - data?: Record | string; - metadata?: unknown; - }>; - edges: Array<{ - source: string; - target: string; - data?: string; - conditional?: boolean; - }>; -} - -/** - * An interrupt thrown inside a thread. - */ -export interface Interrupt { - value?: TValue; - when: "during" | (string & {}); - resumable?: boolean; - ns?: string[]; -} - -export interface Thread { - /** The ID of the thread. */ - thread_id: string; - - /** The time the thread was created. */ - created_at: string; - - /** The last time the thread was updated. */ - updated_at: string; - - /** The thread metadata. */ - metadata: Metadata; - - /** The status of the thread */ - status: ThreadStatus; - - /** The current state of the thread. */ - values: ValuesType; - - /** Interrupts which were thrown in this thread */ - interrupts: Record>; -} - -export interface Cron { - /** The ID of the cron */ - cron_id: string; - - /** The ID of the assistant */ - assistant_id: string; - - /** The ID of the thread */ - thread_id: Optional; - - /** The end date to stop running the cron. */ - end_time: Optional; - - /** The schedule to run, cron format. */ - schedule: string; - - /** The time the cron was created. */ - created_at: string; - - /** The last time the cron was updated. */ - updated_at: string; - - /** The run payload to use for creating new run. */ - payload: Record; - - /** The user ID of the cron */ - user_id: Optional; - - /** The next run date of the cron */ - next_run_date: Optional; - - /** The metadata of the cron */ - metadata: Record; -} - -export type DefaultValues = Record[] | Record; - -export interface ThreadState { - /** The state values */ - values: ValuesType; - - /** The next nodes to execute. If empty, the thread is done until new input is received */ - next: string[]; - - /** Checkpoint of the thread state */ - checkpoint: Checkpoint; - - /** Metadata for this state */ - metadata: Metadata; - - /** Time of state creation */ - created_at: Optional; - - /** The parent checkpoint. If missing, this is the root checkpoint */ - parent_checkpoint: Optional; - - /** Tasks to execute in this step. If already attempted, may contain an error */ - tasks: Array; -} - -export interface ThreadTask { - id: string; - name: string; - result?: unknown; - error: Optional; - interrupts: Array; - checkpoint: Optional; - state: Optional; -} - -export interface Run { - /** The ID of the run */ - run_id: string; - - /** The ID of the thread */ - thread_id: string; - - /** The assistant that wwas used for this run */ - assistant_id: string; - - /** The time the run was created */ - created_at: string; - - /** The last time the run was updated */ - updated_at: string; - - /** The status of the run. */ - status: RunStatus; - - /** Run metadata */ - metadata: Metadata; - - /** Strategy to handle concurrent runs on the same thread */ - multitask_strategy: Optional; -} - -export type Checkpoint = { - thread_id: string; - checkpoint_ns: string; - checkpoint_id: Optional; - checkpoint_map: Optional>; -}; - -export interface ListNamespaceResponse { - namespaces: string[][]; -} -export interface Item { - namespace: string[]; - key: string; - value: Record; - createdAt: string; - updatedAt: string; -} - -export interface SearchItem extends Item { - score?: number; -} -export interface SearchItemsResponse { - items: SearchItem[]; -} - -export interface CronCreateResponse { - cron_id: string; - assistant_id: string; - thread_id: string | undefined; - user_id: string; - payload: Record; - schedule: string; - next_run_date: string; - end_time: string | undefined; - created_at: string; - updated_at: string; - metadata: Metadata; -} - -export interface CronCreateForThreadResponse - extends Omit { - thread_id: string; -} - -export type AssistantSortBy = - | "assistant_id" - | "graph_id" - | "name" - | "created_at" - | "updated_at"; - -export type ThreadSortBy = "thread_id" | "status" | "created_at" | "updated_at"; - -export type CronSortBy = - | "cron_id" - | "assistant_id" - | "thread_id" - | "created_at" - | "updated_at" - | "next_run_date"; - -export type SortOrder = "asc" | "desc"; diff --git a/libs/sdk-js/src/singletons/fetch.ts b/libs/sdk-js/src/singletons/fetch.ts deleted file mode 100644 index 8ed71b000..000000000 --- a/libs/sdk-js/src/singletons/fetch.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Wrap the default fetch call due to issues with illegal invocations -// in some environments: -// https://stackoverflow.com/questions/69876859/why-does-bind-fix-failed-to-execute-fetch-on-window-illegal-invocation-err -// @ts-expect-error Broad typing to support a range of fetch implementations -const DEFAULT_FETCH_IMPLEMENTATION = (...args: any[]) => fetch(...args); - -const LANGSMITH_FETCH_IMPLEMENTATION_KEY = Symbol.for( - "lg:fetch_implementation", -); - -/** - * Overrides the fetch implementation used for LangSmith calls. - * You should use this if you need to use an implementation of fetch - * other than the default global (e.g. for dealing with proxies). - * @param fetch The new fetch function to use. - */ -export const overrideFetchImplementation = (fetch: (...args: any[]) => any) => { - (globalThis as any)[LANGSMITH_FETCH_IMPLEMENTATION_KEY] = fetch; -}; - -/** - * @internal - */ -export const _getFetchImplementation: () => (...args: any[]) => any = () => { - return ( - (globalThis as any)[LANGSMITH_FETCH_IMPLEMENTATION_KEY] ?? - DEFAULT_FETCH_IMPLEMENTATION - ); -}; diff --git a/libs/sdk-js/src/tests/fetch.test.ts b/libs/sdk-js/src/tests/fetch.test.ts deleted file mode 100644 index dc23b80c5..000000000 --- a/libs/sdk-js/src/tests/fetch.test.ts +++ /dev/null @@ -1,201 +0,0 @@ -import { describe, it, expect, beforeEach, afterEach, vi } from "vitest"; -import { Client } from "../client.js"; -import { overrideFetchImplementation } from "../singletons/fetch.js"; - -describe.each([["global"], ["mocked"]])( - "Client uses %s fetch", - (description: string) => { - let globalFetchMock: ReturnType; - let overriddenFetch: ReturnType; - - let expectedFetchMock: ReturnType; - let unexpectedFetchMock: ReturnType; - - beforeEach(() => { - globalFetchMock = vi.fn(() => - Promise.resolve({ - ok: true, - json: () => - Promise.resolve({ - batch_ingest_config: { - use_multipart_endpoint: true, - }, - }), - text: () => Promise.resolve(""), - headers: new Headers({}), - }), - ); - overriddenFetch = vi.fn(() => - Promise.resolve({ - ok: true, - json: () => - Promise.resolve({ - batch_ingest_config: { - use_multipart_endpoint: true, - }, - }), - text: () => Promise.resolve(""), - headers: new Headers({}), - }), - ); - expectedFetchMock = - description === "mocked" ? overriddenFetch : globalFetchMock; - unexpectedFetchMock = - description === "mocked" ? globalFetchMock : overriddenFetch; - - if (description === "mocked") { - overrideFetchImplementation(overriddenFetch); - } else { - overrideFetchImplementation(globalFetchMock); - } - // Mock global fetch - (globalThis as any).fetch = globalFetchMock; - }); - - afterEach(() => { - vi.restoreAllMocks(); - }); - - describe("createRuns", () => { - it("should create an example with the given input and generation", async () => { - const client = new Client({ apiKey: "test-api-key" }); - - const thread = await client.threads.create(); - expect(expectedFetchMock).toHaveBeenCalledTimes(1); - expect(unexpectedFetchMock).not.toHaveBeenCalled(); - - vi.clearAllMocks(); // Clear all mocks before the next operation - - // Then clear & run the function - await client.runs.create(thread.thread_id, "somegraph", { - input: { foo: "bar" }, - }); - expect(expectedFetchMock).toHaveBeenCalledTimes(1); - expect(unexpectedFetchMock).not.toHaveBeenCalled(); - }); - }); - - describe("header coalescing", () => { - it("should properly merge headers with conflicting name casing", async () => { - const client = new Client({ apiKey: "test-api-key" }); - await (client.threads as any).fetch("/test", { - headers: { "X-Api-Key": "custom-value" }, - }); - expect(expectedFetchMock).toHaveBeenCalledWith( - expect.any(URL), - expect.objectContaining({ - headers: expect.objectContaining({ - "x-api-key": "custom-value", - }), - }), - ); - }); - - it("should properly merge headers from multiple sources", async () => { - const client = new Client({ - apiKey: "test-api-key", - defaultHeaders: { - "x-default": "default-value", - "x-override": "default-value", - }, - }); - - await (client.threads as any).fetch("/test", { - headers: { - "x-custom": "custom-value", - "x-override": "custom-value", - }, - }); - - expect(expectedFetchMock).toHaveBeenCalledWith( - expect.any(URL), - expect.objectContaining({ - headers: expect.objectContaining({ - "x-api-key": "test-api-key", - "x-default": "default-value", - "x-custom": "custom-value", - "x-override": "custom-value", - }), - }), - ); - - vi.clearAllMocks(); - - // Test with null/undefined values - await (client.threads as any).fetch("/test", { - headers: { - "x-null": null, - "x-undefined": undefined, - "x-empty": "", - }, - }); - - expect(expectedFetchMock).toHaveBeenCalledWith( - expect.any(URL), - expect.objectContaining({ - headers: expect.objectContaining({ - "x-api-key": "test-api-key", - "x-default": "default-value", - }), - }), - ); - expect(expectedFetchMock).not.toHaveBeenCalledWith( - expect.any(URL), - expect.objectContaining({ - headers: expect.objectContaining({ - "x-null": null, - "x-undefined": undefined, - }), - }), - ); - }); - - it("should handle Headers object input", async () => { - const client = new Client({ apiKey: "test-api-key" }); - const headers = new Headers(); - headers.append("x-custom", "custom-value"); - headers.append("x-multi", "value1"); - headers.append("x-multi", "value2"); - - await (client.threads as any).fetch("/test", { headers }); - - expect(expectedFetchMock).toHaveBeenCalledWith( - expect.any(URL), - expect.objectContaining({ - headers: expect.objectContaining({ - "x-api-key": "test-api-key", - "x-custom": "custom-value", - "x-multi": "value1, value2", - }), - }), - ); - }); - - it("should handle array of header tuples", async () => { - const client = new Client({ - apiKey: "test-api-key", - defaultHeaders: { - "x-custom": "custom-value", - }, - }); - const headers = [ - ["x-multi", "value1"], - ["x-multi", "value2"], - ]; - - await (client.threads as any).fetch("/test", { headers }); - - expect(expectedFetchMock).toHaveBeenCalledWith( - expect.any(URL), - expect.objectContaining({ - headers: expect.objectContaining({ - "x-api-key": "test-api-key", - "x-custom": "custom-value", - "x-multi": "value1, value2", - }), - }), - ); - }); - }); - }, -); diff --git a/libs/sdk-js/src/tests/sse.test.ts b/libs/sdk-js/src/tests/sse.test.ts deleted file mode 100644 index 1dd6a6d94..000000000 --- a/libs/sdk-js/src/tests/sse.test.ts +++ /dev/null @@ -1,183 +0,0 @@ -import { describe, test, expect } from "vitest"; -import { Readable } from "node:stream"; -import { IterableReadableStream } from "../utils/stream.js"; -import { BytesLineDecoder, SSEDecoder } from "../utils/sse.js"; - -const gather = async (stream: ReadableStream): Promise => { - const results: T[] = []; - const iterator = IterableReadableStream.fromReadableStream(stream); - for await (const chunk of iterator) results.push(chunk); - return results; -}; - -const textEncoder = new TextEncoder(); -const textDecoder = new TextDecoder(); - -describe("BytesLineDecoder", () => { - const createStream = (chunks: Uint8Array[]) => { - return Readable.toWeb(Readable.from(chunks)) as ReadableStream; - }; - - test("handles single line with newline", async () => { - const input = createStream([textEncoder.encode("hello\n")]); - const decoded = input.pipeThrough(BytesLineDecoder()); - const results = await gather(decoded); - - expect(results.length).toBe(1); - expect(textDecoder.decode(results[0])).toBe("hello"); - }); - - test("handles multiple lines", async () => { - const input = createStream([textEncoder.encode("line1\nline2\nline3\n")]); - const decoded = input.pipeThrough(BytesLineDecoder()); - const results = await gather(decoded); - - expect(results.length).toBe(3); - expect(textDecoder.decode(results[0])).toBe("line1"); - expect(textDecoder.decode(results[1])).toBe("line2"); - expect(textDecoder.decode(results[2])).toBe("line3"); - }); - - test("handles split chunks", async () => { - const input = createStream([ - textEncoder.encode("li"), - textEncoder.encode("ne1\nli"), - textEncoder.encode("ne2\n"), - ]); - const decoded = input.pipeThrough(BytesLineDecoder()); - const results = await gather(decoded); - - expect(results.length).toBe(2); - expect(textDecoder.decode(results[0])).toBe("line1"); - expect(textDecoder.decode(results[1])).toBe("line2"); - }); - - test("handles CR LF line endings", async () => { - const input = createStream([textEncoder.encode("line1\r\nline2\r\n")]); - const decoded = input.pipeThrough(BytesLineDecoder()); - const results = await gather(decoded); - - expect(results.length).toBe(2); - expect(textDecoder.decode(results[0])).toBe("line1"); - expect(textDecoder.decode(results[1])).toBe("line2"); - }); - - test("handles split CR LF", async () => { - const input = createStream([ - textEncoder.encode("line1\r"), - textEncoder.encode("\nline2\r\n"), - ]); - const decoded = input.pipeThrough(BytesLineDecoder()); - const results = await gather(decoded); - - expect(results.length).toBe(2); - expect(textDecoder.decode(results[0])).toBe("line1"); - expect(textDecoder.decode(results[1])).toBe("line2"); - }); - - test("handles stale line", async () => { - const input = createStream([textEncoder.encode("hello")]); - const decoded = input.pipeThrough(BytesLineDecoder()); - const results = await gather(decoded); - - expect(results.length).toBe(1); - expect(textDecoder.decode(results[0])).toBe("hello"); - }); -}); - -describe("SSEDecoder", () => { - const createStream = (lines: string[]) => { - return Readable.toWeb( - Readable.from(lines.map((line) => textEncoder.encode(line))), - ) as ReadableStream; - }; - - test("decodes simple event", async () => { - const input = createStream([ - "event: test\n", - 'data: {"message": "hello"}\n', - "\n", - ]); - const decoded = input - .pipeThrough(BytesLineDecoder()) - .pipeThrough(SSEDecoder()); - - const results = await gather(decoded); - expect(results.length).toBe(1); - expect(results[0]).toEqual({ - event: "test", - data: { message: "hello" }, - }); - }); - - test("ignores comments", async () => { - const input = createStream([ - ": this is a comment\n", - "event: test\n", - 'data: {"message": "hello"}\n', - ]); - const decoded = input - .pipeThrough(BytesLineDecoder()) - .pipeThrough(SSEDecoder()); - - const results = await gather(decoded); - expect(results.length).toBe(1); - expect(results[0]).toEqual({ - event: "test", - data: { message: "hello" }, - }); - }); - - test("handles multiple events", async () => { - const input = createStream([ - "event: test1\n", - 'data: {"message": "hello"}\n', - "\n", - "event: test2\n", - 'data: {"message": "world"}\n', - "\n", - ]); - const decoded = input - .pipeThrough(BytesLineDecoder()) - .pipeThrough(SSEDecoder()); - - const results = await gather(decoded); - expect(results.length).toBe(2); - expect(results[0]).toEqual({ - event: "test1", - data: { message: "hello" }, - }); - expect(results[1]).toEqual({ - event: "test2", - data: { message: "world" }, - }); - }); - - test("end event without data", async () => { - const input = createStream(["event: test\n"]); - const decoded = input - .pipeThrough(BytesLineDecoder()) - .pipeThrough(SSEDecoder()); - - const results = await gather(decoded); - expect(results.length).toBe(1); - expect(results[0]).toEqual({ - event: "test", - data: null, - }); - }); - - test("end event without newline", async () => { - const input = createStream(["event: end"]); - const decoded = input - .pipeThrough(BytesLineDecoder()) - .pipeThrough(SSEDecoder()); - - const results = await gather(decoded); - expect(results.length).toBe(1); - expect(results[0]).toEqual({ - event: "end", - data: null, - }); - }); -}); diff --git a/libs/sdk-js/src/tests/stream.test.tsx b/libs/sdk-js/src/tests/stream.test.tsx deleted file mode 100644 index e05dde513..000000000 --- a/libs/sdk-js/src/tests/stream.test.tsx +++ /dev/null @@ -1,450 +0,0 @@ -import "@testing-library/jest-dom/vitest"; - -import { describe, it, expect, beforeEach, afterEach, vi } from "vitest"; -import { render, screen, waitFor } from "@testing-library/react"; -import { userEvent } from "@testing-library/user-event"; -import { setupServer } from "msw/node"; -import { http } from "msw"; -import { useStream } from "../react/stream.js"; -import type { Message } from "../types.messages.js"; - -import { StateGraph, MessagesAnnotation, START } from "@langchain/langgraph"; -import { MemorySaver } from "@langchain/langgraph-checkpoint"; -import { FakeStreamingChatModel } from "@langchain/core/utils/testing"; -import { AIMessage } from "@langchain/core/messages"; -import { createEmbedServer } from "@langchain/langgraph-api/experimental/embed"; -import { randomUUID } from "node:crypto"; -import { useState } from "react"; - -const threads = (() => { - const THREADS: Record< - string, - { thread_id: string; metadata: Record } - > = {}; - - return { - get: async (id: string) => THREADS[id], - put: async ( - threadId: string, - { metadata }: { metadata?: Record }, - ) => { - THREADS[threadId] = { thread_id: threadId, metadata: metadata ?? {} }; - }, - delete: async (threadId: string) => { - delete THREADS[threadId]; - }, - }; -})(); - -const checkpointer = new MemorySaver(); - -const model = new FakeStreamingChatModel({ responses: [new AIMessage("Hey")] }); -const agent = new StateGraph(MessagesAnnotation) - .addNode("agent", async (state: { messages: Message[] }) => { - const response = await model.invoke(state.messages); - return { messages: [response] }; - }) - .addEdge(START, "agent") - .compile(); - -const app = createEmbedServer({ graph: { agent }, checkpointer, threads }); -const server = setupServer(http.all("*", (ctx) => app.fetch(ctx.request))); - -function TestChatComponent() { - const { messages, isLoading, error, submit, stop } = useStream({ - assistantId: "agent", - apiKey: "test-api-key", - }); - - return ( -
-
- {messages.map((msg, i) => ( -
- {typeof msg.content === "string" - ? msg.content - : JSON.stringify(msg.content)} -
- ))} -
-
- {isLoading ? "Loading..." : "Not loading"} -
- {error ?
{String(error)}
: null} - - -
- ); -} - -describe("useStream", () => { - beforeEach(() => server.listen()); - - afterEach(() => { - server.resetHandlers(); - server.close(); - vi.clearAllMocks(); - }); - - it("renders initial state correctly", () => { - render(); - - expect(screen.getByTestId("loading")).toHaveTextContent("Not loading"); - expect(screen.getByTestId("messages")).toBeEmptyDOMElement(); - expect(screen.queryByTestId("error")).not.toBeInTheDocument(); - }); - - it("handles message submission and streaming", async () => { - const user = userEvent.setup(); - - render(); - - // Check loading state - await user.click(screen.getByTestId("submit")); - expect(screen.getByTestId("loading")).toHaveTextContent("Loading..."); - - // Wait for messages to appear - await waitFor(() => { - expect(screen.getByTestId("message-0")).toHaveTextContent("Hello"); - expect(screen.getByTestId("message-1")).toHaveTextContent("Hey"); - }); - - // Check final state - expect(screen.getByTestId("loading")).toHaveTextContent("Not loading"); - }); - - it("handles stop functionality", async () => { - const user = userEvent.setup(); - render(); - - // Start streaming and stop immediately - await user.click(screen.getByTestId("submit")); - await user.click(screen.getByTestId("stop")); - - // Check loading state is reset - await waitFor(() => { - expect(screen.getByTestId("loading")).toHaveTextContent("Not loading"); - }); - }); - - it("displays initial values immediately and clears them when submitting", async () => { - const user = userEvent.setup(); - - function TestCachedComponent() { - const { messages, values, submit } = useStream<{ - messages: Message[]; - }>({ - assistantId: "agent", - apiKey: "test-api-key", - initialValues: { - messages: [ - { id: "cached-1", type: "human", content: "Cached user message" }, - { id: "cached-2", type: "ai", content: "Cached AI response" }, - ], - }, - }); - - return ( -
-
- {messages.map((msg, i) => ( -
- {typeof msg.content === "string" - ? msg.content - : JSON.stringify(msg.content)} -
- ))} -
-
{JSON.stringify(values)}
- -
- ); - } - - render(); - - // Should immediately show cached messages - expect(screen.getByTestId("message-cached-0")).toHaveTextContent( - "Cached user message", - ); - expect(screen.getByTestId("message-cached-1")).toHaveTextContent( - "Cached AI response", - ); - - // Values should include initial values - expect(screen.getByTestId("values")).toHaveTextContent( - "Cached user message", - ); - - // Submitting should clear out the cached messages - await user.click(screen.getByTestId("submit")); - - // Wait for messages to appear - await waitFor(() => { - expect(screen.getByTestId("message-0")).toHaveTextContent("Hello"); - expect(screen.getByTestId("message-1")).toHaveTextContent("Hey"); - }); - }); - - it("accepts newThreadId option without errors", async () => { - const user = userEvent.setup(); - - const spy = vi.fn(); - const predeterminedThreadId = randomUUID(); - - // Test that newThreadId option can be passed without causing errors - function TestNewThreadComponent() { - const stream = useStream<{ messages: Message[] }>({ - assistantId: "agent", - apiKey: "test-api-key", - threadId: null, // Start with no thread - onThreadId: spy, // Mock callback - }); - - return ( -
-
- {stream.isLoading ? "Loading..." : "Not loading"} -
-
- {stream.client ? "Client ready" : "No client"} -
- -
- ); - } - - render(); - - // Should render without errors - expect(screen.getByTestId("loading")).toHaveTextContent("Not loading"); - expect(screen.getByTestId("thread-id")).toHaveTextContent("Client ready"); - - await user.click(screen.getByTestId("submit")); - expect(spy).toHaveBeenCalledWith(predeterminedThreadId); - expect(await threads.get(predeterminedThreadId)).toEqual({ - thread_id: predeterminedThreadId, - metadata: { - graph_id: "agent", - assistant_id: "agent", - }, - }); - }); - - it("onStop callback is called when stop is called", async () => { - const user = userEvent.setup(); - const onStopCallback = vi.fn(); - - function TestComponent() { - const { submit, stop } = useStream({ - assistantId: "agent", - apiKey: "test-api-key", - onStop: onStopCallback, - }); - - return ( -
- - -
- ); - } - - render(); - - // Start a stream and stop it - await user.click(screen.getByTestId("submit")); - await user.click(screen.getByTestId("stop")); - - // Verify onStop was called with mutate function - expect(onStopCallback).toHaveBeenCalledTimes(1); - expect(onStopCallback).toHaveBeenCalledWith( - expect.objectContaining({ - mutate: expect.any(Function), - }), - ); - }); - - it("onStop mutate function updates stream values immediately", async () => { - const user = userEvent.setup(); - - function TestComponent() { - const [stopped, setStopped] = useState(false); - const { submit, stop, messages } = useStream<{ messages: Message[] }>({ - assistantId: "agent", - apiKey: "test-api-key", - onStop: ({ mutate }) => { - setStopped(true); - mutate((prev) => ({ - ...prev, - messages: [ - ...(prev.messages ?? []), - { type: "ai", content: "Stream stopped" }, - ], - })); - }, - }); - - return ( -
-
- {stopped ? "Stopped" : "Not stopped"} -
-
- {messages.map((msg, i) => ( -
- {typeof msg.content === "string" - ? msg.content - : JSON.stringify(msg.content)} -
- ))} -
- - -
- ); - } - - render(); - - // Initial state - expect(screen.getByTestId("stopped-status")).toHaveTextContent( - "Not stopped", - ); - - // Start and stop stream - await user.click(screen.getByTestId("submit")); - await user.click(screen.getByTestId("stop")); - - // Verify state was updated immediately - await waitFor(() => { - expect(screen.getByTestId("stopped-status")).toHaveTextContent("Stopped"); - expect(screen.getByTestId("message-0")).toHaveTextContent( - "Stream stopped", - ); - }); - }); - - it("onStop handles functional updates correctly", async () => { - const user = userEvent.setup(); - - function TestComponent() { - const { submit, stop, values } = useStream({ - assistantId: "agent", - apiKey: "test-api-key", - initialValues: { - counter: 5, - items: ["item1", "item2"], - }, - onStop: ({ mutate }) => { - mutate((prev: any) => ({ - ...prev, - counter: (prev.counter || 0) + 10, - items: [...(prev.items || []), "stopped"], - })); - }, - }); - - return ( -
-
{(values as any).counter}
-
{(values as any).items?.join(", ")}
- - -
- ); - } - - render(); - - // Initial state - expect(screen.getByTestId("counter")).toHaveTextContent("5"); - expect(screen.getByTestId("items")).toHaveTextContent("item1, item2"); - - // Start and stop stream - await user.click(screen.getByTestId("submit")); - await user.click(screen.getByTestId("stop")); - - // Verify functional update was applied correctly - await waitFor(() => { - expect(screen.getByTestId("counter")).toHaveTextContent("15"); - expect(screen.getByTestId("items")).toHaveTextContent( - "item1, item2, stopped", - ); - }); - }); - - it("onStop is not called when stream completes naturally", async () => { - const user = userEvent.setup(); - - const onStopCallback = vi.fn(); - - function TestComponent() { - const { submit } = useStream({ - assistantId: "agent", - apiKey: "test-api-key", - onStop: onStopCallback, - }); - - return ( -
- -
- ); - } - - render(); - - // Start a stream and let it complete naturally - await user.click(screen.getByTestId("submit")); - - // Wait for stream to complete naturally - await waitFor(() => { - expect(onStopCallback).not.toHaveBeenCalled(); - }); - }); -}); diff --git a/libs/sdk-js/src/types.messages.ts b/libs/sdk-js/src/types.messages.ts deleted file mode 100644 index 26b929535..000000000 --- a/libs/sdk-js/src/types.messages.ts +++ /dev/null @@ -1,101 +0,0 @@ -type ImageDetail = "auto" | "low" | "high"; -type MessageContentImageUrl = { - type: "image_url"; - image_url: string | { url: string; detail?: ImageDetail | undefined }; -}; - -type MessageContentText = { type: "text"; text: string }; -type MessageContentComplex = MessageContentText | MessageContentImageUrl; -type MessageContent = string | MessageContentComplex[]; - -/** - * Model-specific additional kwargs, which is passed back to the underlying LLM. - */ -type MessageAdditionalKwargs = Record; - -type BaseMessage = { - additional_kwargs?: MessageAdditionalKwargs | undefined; - content: MessageContent; - id?: string | undefined; - name?: string | undefined; - response_metadata?: Record | undefined; -}; - -export type HumanMessage = BaseMessage & { - type: "human"; - example?: boolean | undefined; -}; - -export type AIMessage = BaseMessage & { - type: "ai"; - example?: boolean | undefined; - tool_calls?: - | { - name: string; - args: { [x: string]: any }; - id?: string | undefined; - type?: "tool_call" | undefined; - }[] - | undefined; - invalid_tool_calls?: - | { - name?: string | undefined; - args?: string | undefined; - id?: string | undefined; - error?: string | undefined; - type?: "invalid_tool_call" | undefined; - }[] - | undefined; - usage_metadata?: - | { - input_tokens: number; - output_tokens: number; - total_tokens: number; - input_token_details?: - | { - audio?: number | undefined; - cache_read?: number | undefined; - cache_creation?: number | undefined; - } - | undefined; - output_token_details?: - | { audio?: number | undefined; reasoning?: number | undefined } - | undefined; - } - | undefined; -}; - -export type ToolMessage = BaseMessage & { - type: "tool"; - status?: "error" | "success" | undefined; - tool_call_id: string; - /** - * Artifact of the Tool execution which is not meant to be sent to the model. - * - * Should only be specified if it is different from the message content, e.g. if only - * a subset of the full tool output is being passed as message content but the full - * output is needed in other parts of the code. - */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - artifact?: any; -}; - -export type SystemMessage = BaseMessage & { - type: "system"; -}; - -export type FunctionMessage = BaseMessage & { - type: "function"; -}; - -export type RemoveMessage = BaseMessage & { - type: "remove"; -}; - -export type Message = - | HumanMessage - | AIMessage - | ToolMessage - | SystemMessage - | FunctionMessage - | RemoveMessage; diff --git a/libs/sdk-js/src/types.stream.ts b/libs/sdk-js/src/types.stream.ts deleted file mode 100644 index 5d69c2b9f..000000000 --- a/libs/sdk-js/src/types.stream.ts +++ /dev/null @@ -1,231 +0,0 @@ -import type { Message } from "./types.messages.js"; - -/** - * Stream modes - * - "values": Stream only the state values. - * - "messages": Stream complete messages. - * - "messages-tuple": Stream (message chunk, metadata) tuples. - * - "updates": Stream updates to the state. - * - "events": Stream events occurring during execution. - * - "debug": Stream detailed debug information. - * - "custom": Stream custom events. - */ -export type StreamMode = - | "values" - | "messages" - | "updates" - | "events" - | "debug" - | "custom" - | "messages-tuple"; - -type MessageTupleMetadata = { - tags: string[]; - [key: string]: unknown; -}; - -type AsSubgraph = - { - id?: TEvent["id"]; - event: TEvent["event"] | `${TEvent["event"]}|${string}`; - data: TEvent["data"]; - }; - -/** - * Stream event with values after completion of each step. - */ -export type ValuesStreamEvent = { - id?: string; - event: "values"; - data: StateType; -}; - -/** @internal */ -export type SubgraphValuesStreamEvent = AsSubgraph< - ValuesStreamEvent ->; - -/** - * Stream event with message chunks coming from LLM invocations inside nodes. - */ -export type MessagesTupleStreamEvent = { - event: "messages"; - // TODO: add types for message and config, which do not depend on LangChain - // while making sure it's easy to keep them in sync. - data: [message: Message, config: MessageTupleMetadata]; -}; - -/** @internal */ -export type SubgraphMessagesTupleStreamEvent = - AsSubgraph; - -/** - * Metadata stream event with information about the run and thread - */ -export type MetadataStreamEvent = { - id?: string; - event: "metadata"; - data: { run_id: string; thread_id: string }; -}; - -/** - * Stream event with error information. - */ -export type ErrorStreamEvent = { - id?: string; - event: "error"; - data: { error: string; message: string }; -}; - -/** @internal */ -export type SubgraphErrorStreamEvent = AsSubgraph; - -/** - * Stream event with updates to the state after each step. - * The streamed outputs include the name of the node that - * produced the update as well as the update. - */ -export type UpdatesStreamEvent = { - id?: string; - event: "updates"; - data: { [node: string]: UpdateType }; -}; - -/** @internal */ -export type SubgraphUpdatesStreamEvent = AsSubgraph< - UpdatesStreamEvent ->; - -/** - * Streaming custom data from inside the nodes. - */ -export type CustomStreamEvent = { event: "custom"; data: T }; - -/** @internal */ -export type SubgraphCustomStreamEvent = AsSubgraph>; - -type MessagesMetadataStreamEvent = { - id?: string; - event: "messages/metadata"; - data: { [messageId: string]: { metadata: unknown } }; -}; -type MessagesCompleteStreamEvent = { - id?: string; - event: "messages/complete"; - data: Message[]; -}; -type MessagesPartialStreamEvent = { - id?: string; - event: "messages/partial"; - data: Message[]; -}; - -/** - * Message stream event specific to LangGraph Server. - * @deprecated Use `streamMode: "messages-tuple"` instead. - */ -export type MessagesStreamEvent = - | MessagesMetadataStreamEvent - | MessagesCompleteStreamEvent - | MessagesPartialStreamEvent; - -/** @internal */ -export type SubgraphMessagesStreamEvent = - | AsSubgraph - | AsSubgraph - | AsSubgraph; - -/** - * Stream event with detailed debug information. - */ -export type DebugStreamEvent = { id?: string; event: "debug"; data: unknown }; - -/** @internal */ -export type SubgraphDebugStreamEvent = AsSubgraph; - -/** - * Stream event with events occurring during execution. - */ -export type EventsStreamEvent = { - id?: string; - event: "events"; - data: { - event: - | `on_${"chat_model" | "llm" | "chain" | "tool" | "retriever" | "prompt"}_${"start" | "stream" | "end"}` - | (string & {}); - name: string; - tags: string[]; - run_id: string; - metadata: Record; - parent_ids: string[]; - data: unknown; - }; -}; - -/** @internal */ -export type SubgraphEventsStreamEvent = AsSubgraph; - -/** - * Stream event with a feedback key to signed URL map. Set `feedbackKeys` in - * the `RunsStreamPayload` to receive this event. - */ -export type FeedbackStreamEvent = { - id?: string; - event: "feedback"; - data: { [feedbackKey: string]: string }; -}; - -type GetStreamModeMap< - TStreamMode extends StreamMode | StreamMode[], - TStateType = unknown, - TUpdateType = TStateType, - TCustomType = unknown, -> = - | { - values: ValuesStreamEvent; - updates: UpdatesStreamEvent; - custom: CustomStreamEvent; - debug: DebugStreamEvent; - messages: MessagesStreamEvent; - "messages-tuple": MessagesTupleStreamEvent; - events: EventsStreamEvent; - }[TStreamMode extends StreamMode[] ? TStreamMode[number] : TStreamMode] - | ErrorStreamEvent - | MetadataStreamEvent - | FeedbackStreamEvent; - -type GetSubgraphsStreamModeMap< - TStreamMode extends StreamMode | StreamMode[], - TStateType = unknown, - TUpdateType = TStateType, - TCustomType = unknown, -> = - | { - values: SubgraphValuesStreamEvent; - updates: SubgraphUpdatesStreamEvent; - custom: SubgraphCustomStreamEvent; - debug: SubgraphDebugStreamEvent; - messages: SubgraphMessagesStreamEvent; - "messages-tuple": SubgraphMessagesTupleStreamEvent; - events: SubgraphEventsStreamEvent; - }[TStreamMode extends StreamMode[] ? TStreamMode[number] : TStreamMode] - | SubgraphErrorStreamEvent - | MetadataStreamEvent - | FeedbackStreamEvent; - -export type TypedAsyncGenerator< - TStreamMode extends StreamMode | StreamMode[] = [], - TSubgraphs extends boolean = false, - TStateType = unknown, - TUpdateType = TStateType, - TCustomType = unknown, -> = AsyncGenerator< - TSubgraphs extends true - ? GetSubgraphsStreamModeMap< - TStreamMode, - TStateType, - TUpdateType, - TCustomType - > - : GetStreamModeMap ->; diff --git a/libs/sdk-js/src/types.ts b/libs/sdk-js/src/types.ts deleted file mode 100644 index 743f714b3..000000000 --- a/libs/sdk-js/src/types.ts +++ /dev/null @@ -1,209 +0,0 @@ -import { LangChainTracer } from "@langchain/core/tracers/tracer_langchain"; -import { Checkpoint, Config, Metadata } from "./schema.js"; -import { StreamMode } from "./types.stream.js"; - -export type MultitaskStrategy = "reject" | "interrupt" | "rollback" | "enqueue"; -export type OnConflictBehavior = "raise" | "do_nothing"; -export type OnCompletionBehavior = "complete" | "continue"; -export type DisconnectMode = "cancel" | "continue"; -export type StreamEvent = - | "events" - | "metadata" - | "debug" - | "updates" - | "values" - | "messages/partial" - | "messages/metadata" - | "messages/complete" - | "messages" - | (string & {}); - -export interface Send { - node: string; - input: unknown | null; -} - -export interface Command { - /** - * An object to update the thread state with. - */ - update?: Record | [string, unknown][] | null; - - /** - * The value to return from an `interrupt` function call. - */ - resume?: unknown; - - /** - * Determine the next node to navigate to. Can be one of the following: - * - Name(s) of the node names to navigate to next. - * - `Send` command(s) to execute node(s) with provided input. - */ - goto?: Send | Send[] | string | string[]; -} - -export interface RunsInvokePayload { - /** - * Input to the run. Pass `null` to resume from the current state of the thread. - */ - input?: Record | null; - - /** - * Metadata for the run. - */ - metadata?: Metadata; - - /** - * Additional configuration for the run. - */ - config?: Config; - - /** - * Checkpoint ID for when creating a new run. - */ - checkpointId?: string; - - /** - * Checkpoint for when creating a new run. - */ - checkpoint?: Omit; - - /** - * Whether to checkpoint during the run (or only at the end/interruption). - */ - checkpointDuring?: boolean; - - /** - * Interrupt execution before entering these nodes. - */ - interruptBefore?: "*" | string[]; - - /** - * Interrupt execution after leaving these nodes. - */ - interruptAfter?: "*" | string[]; - - /** - * Strategy to handle concurrent runs on the same thread. Only relevant if - * there is a pending/inflight run on the same thread. One of: - * - "reject": Reject the new run. - * - "interrupt": Interrupt the current run, keeping steps completed until now, - and start a new one. - * - "rollback": Cancel and delete the existing run, rolling back the thread to - the state before it had started, then start the new run. - * - "enqueue": Queue up the new run to start after the current run finishes. - */ - multitaskStrategy?: MultitaskStrategy; - - /** - * Abort controller signal to cancel the run. - */ - signal?: AbortController["signal"]; - - /** - * Behavior to handle run completion. Only relevant if - * there is a pending/inflight run on the same thread. One of: - * - "complete": Complete the run. - * - "continue": Continue the run. - */ - onCompletion?: OnCompletionBehavior; - - /** - * Webhook to call when the run is complete. - */ - webhook?: string; - - /** - * Behavior to handle disconnection. Only relevant if - * there is a pending/inflight run on the same thread. One of: - * - "cancel": Cancel the run. - * - "continue": Continue the run. - */ - onDisconnect?: DisconnectMode; - - /** - * The number of seconds to wait before starting the run. - * Use to schedule future runs. - */ - afterSeconds?: number; - - /** - * Behavior if the specified run doesn't exist. Defaults to "reject". - */ - ifNotExists?: "create" | "reject"; - - /** - * One or more commands to invoke the graph with. - */ - command?: Command; - - /** - * Callback when a run is created. - */ - onRunCreated?: (params: { run_id: string; thread_id?: string }) => void; - - /** - * @internal - * For LangSmith tracing purposes only. Not part of the public API. - */ - _langsmithTracer?: LangChainTracer; -} - -export interface RunsStreamPayload< - TStreamMode extends StreamMode | StreamMode[] = [], - TSubgraphs extends boolean = false, -> extends RunsInvokePayload { - /** - * One of `"values"`, `"messages"`, `"messages-tuple"`, `"updates"`, `"events"`, `"debug"`, `"custom"`. - */ - streamMode?: TStreamMode; - - /** - * Stream output from subgraphs. By default, streams only the top graph. - */ - streamSubgraphs?: TSubgraphs; - - /** - * Whether the stream is considered resumable. - * If true, the stream can be resumed and replayed in its entirety even after disconnection. - */ - streamResumable?: boolean; - - /** - * Pass one or more feedbackKeys if you want to request short-lived signed URLs - * for submitting feedback to LangSmith with this key for this run. - */ - feedbackKeys?: string[]; -} - -export interface RunsCreatePayload extends RunsInvokePayload { - /** - * One of `"values"`, `"messages"`, `"messages-tuple"`, `"updates"`, `"events"`, `"debug"`, `"custom"`. - */ - streamMode?: StreamMode | Array; - - /** - * Stream output from subgraphs. By default, streams only the top graph. - */ - streamSubgraphs?: boolean; - - /** - * Whether the stream is considered resumable. - * If true, the stream can be resumed and replayed in its entirety even after disconnection. - */ - streamResumable?: boolean; -} - -export interface CronsCreatePayload extends RunsCreatePayload { - /** - * Schedule for running the Cron Job - */ - schedule: string; -} - -export interface RunsWaitPayload extends RunsStreamPayload { - /** - * Raise errors returned by the run. Default is `true`. - */ - raiseError?: boolean; -} diff --git a/libs/sdk-js/src/utils/async_caller.ts b/libs/sdk-js/src/utils/async_caller.ts deleted file mode 100644 index 5ee431622..000000000 --- a/libs/sdk-js/src/utils/async_caller.ts +++ /dev/null @@ -1,216 +0,0 @@ -import pRetry from "p-retry"; -import PQueueMod from "p-queue"; -import { _getFetchImplementation } from "../singletons/fetch.js"; - -const STATUS_NO_RETRY = [ - 400, // Bad Request - 401, // Unauthorized - 402, // Payment required - 403, // Forbidden - 404, // Not Found - 405, // Method Not Allowed - 406, // Not Acceptable - 407, // Proxy Authentication Required - 408, // Request Timeout - 409, // Conflict - 422, // Unprocessable Entity -]; - -type ResponseCallback = (response?: Response) => Promise; - -export interface AsyncCallerParams { - /** - * The maximum number of concurrent calls that can be made. - * Defaults to `Infinity`, which means no limit. - */ - maxConcurrency?: number; - /** - * The maximum number of retries that can be made for a single call, - * with an exponential backoff between each attempt. Defaults to 6. - */ - maxRetries?: number; - - onFailedResponseHook?: ResponseCallback; - - /** - * Specify a custom fetch implementation. - * - * By default we expect the `fetch` is available in the global scope. - */ - fetch?: typeof fetch | ((...args: any[]) => any); -} - -export interface AsyncCallerCallOptions { - signal?: AbortSignal; -} - -/** - * Do not rely on globalThis.Response, rather just - * do duck typing - */ -function isResponse(x: unknown): x is Response { - if (x == null || typeof x !== "object") return false; - return "status" in x && "statusText" in x && "text" in x; -} - -/** - * Utility error to properly handle failed requests - */ -class HTTPError extends Error { - status: number; - text: string; - - response?: Response; - - constructor(status: number, message: string, response?: Response) { - super(`HTTP ${status}: ${message}`); - this.status = status; - this.text = message; - this.response = response; - } - - static async fromResponse( - response: Response, - options?: { includeResponse?: boolean }, - ): Promise { - try { - return new HTTPError( - response.status, - await response.text(), - options?.includeResponse ? response : undefined, - ); - } catch { - return new HTTPError( - response.status, - response.statusText, - options?.includeResponse ? response : undefined, - ); - } - } -} - -/** - * A class that can be used to make async calls with concurrency and retry logic. - * - * This is useful for making calls to any kind of "expensive" external resource, - * be it because it's rate-limited, subject to network issues, etc. - * - * Concurrent calls are limited by the `maxConcurrency` parameter, which defaults - * to `Infinity`. This means that by default, all calls will be made in parallel. - * - * Retries are limited by the `maxRetries` parameter, which defaults to 5. This - * means that by default, each call will be retried up to 5 times, with an - * exponential backoff between each attempt. - */ -export class AsyncCaller { - protected maxConcurrency: AsyncCallerParams["maxConcurrency"]; - - protected maxRetries: AsyncCallerParams["maxRetries"]; - - private queue: (typeof import("p-queue"))["default"]["prototype"]; - - private onFailedResponseHook?: ResponseCallback; - - private customFetch?: typeof fetch; - - constructor(params: AsyncCallerParams) { - this.maxConcurrency = params.maxConcurrency ?? Infinity; - this.maxRetries = params.maxRetries ?? 4; - - if ("default" in PQueueMod) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - this.queue = new (PQueueMod.default as any)({ - concurrency: this.maxConcurrency, - }); - } else { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - this.queue = new (PQueueMod as any)({ concurrency: this.maxConcurrency }); - } - this.onFailedResponseHook = params?.onFailedResponseHook; - this.customFetch = params.fetch; - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - call Promise>( - callable: T, - ...args: Parameters - ): Promise>> { - const onFailedResponseHook = this.onFailedResponseHook; - return this.queue.add( - () => - pRetry( - () => - callable(...(args as Parameters)).catch(async (error) => { - // eslint-disable-next-line no-instanceof/no-instanceof - if (error instanceof Error) { - throw error; - } else if (isResponse(error)) { - throw await HTTPError.fromResponse(error, { - includeResponse: !!onFailedResponseHook, - }); - } else { - throw new Error(error); - } - }), - { - async onFailedAttempt(error) { - if ( - error.message.startsWith("Cancel") || - error.message.startsWith("TimeoutError") || - error.message.startsWith("AbortError") - ) { - throw error; - } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - if ((error as any)?.code === "ECONNABORTED") { - throw error; - } - - if (error instanceof HTTPError) { - if (STATUS_NO_RETRY.includes(error.status)) { - throw error; - } - if (onFailedResponseHook && error.response) { - await onFailedResponseHook(error.response); - } - } - }, - // If needed we can change some of the defaults here, - // but they're quite sensible. - retries: this.maxRetries, - randomize: true, - }, - ), - { throwOnTimeout: true }, - ); - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - callWithOptions Promise>( - options: AsyncCallerCallOptions, - callable: T, - ...args: Parameters - ): Promise>> { - // Note this doesn't cancel the underlying request, - // when available prefer to use the signal option of the underlying call - if (options.signal) { - return Promise.race([ - this.call(callable, ...args), - new Promise((_, reject) => { - options.signal?.addEventListener("abort", () => { - reject(new Error("AbortError")); - }); - }), - ]); - } - return this.call(callable, ...args); - } - - fetch(...args: Parameters): ReturnType { - const fetchFn = - this.customFetch ?? (_getFetchImplementation() as typeof fetch); - return this.call(() => - fetchFn(...args).then((res) => (res.ok ? res : Promise.reject(res))), - ); - } -} diff --git a/libs/sdk-js/src/utils/env.ts b/libs/sdk-js/src/utils/env.ts deleted file mode 100644 index 738c14fd5..000000000 --- a/libs/sdk-js/src/utils/env.ts +++ /dev/null @@ -1,11 +0,0 @@ -export function getEnvironmentVariable(name: string): string | undefined { - // Certain setups (Deno, frontend) will throw an error if you try to access environment variables - try { - return typeof process !== "undefined" - ? // eslint-disable-next-line no-process-env - process.env?.[name] - : undefined; - } catch (e) { - return undefined; - } -} diff --git a/libs/sdk-js/src/utils/signals.ts b/libs/sdk-js/src/utils/signals.ts deleted file mode 100644 index 915753325..000000000 --- a/libs/sdk-js/src/utils/signals.ts +++ /dev/null @@ -1,22 +0,0 @@ -export function mergeSignals(...signals: (AbortSignal | null | undefined)[]) { - const nonZeroSignals = signals.filter( - (signal): signal is AbortSignal => signal != null, - ); - - if (nonZeroSignals.length === 0) return undefined; - if (nonZeroSignals.length === 1) return nonZeroSignals[0]; - - const controller = new AbortController(); - for (const signal of signals) { - if (signal?.aborted) { - controller.abort(signal.reason); - return controller.signal; - } - - signal?.addEventListener("abort", () => controller.abort(signal.reason), { - once: true, - }); - } - - return controller.signal; -} diff --git a/libs/sdk-js/src/utils/sse.ts b/libs/sdk-js/src/utils/sse.ts deleted file mode 100644 index a080922f5..000000000 --- a/libs/sdk-js/src/utils/sse.ts +++ /dev/null @@ -1,175 +0,0 @@ -const CR = "\r".charCodeAt(0); -const LF = "\n".charCodeAt(0); -const NULL = "\0".charCodeAt(0); -const COLON = ":".charCodeAt(0); -const SPACE = " ".charCodeAt(0); - -const TRAILING_NEWLINE = [CR, LF]; - -export function BytesLineDecoder() { - let buffer: Uint8Array[] = []; - let trailingCr = false; - - return new TransformStream({ - start() { - buffer = []; - trailingCr = false; - }, - - transform(chunk, controller) { - // See https://docs.python.org/3/glossary.html#term-universal-newlines - let text = chunk; - - // Handle trailing CR from previous chunk - if (trailingCr) { - text = joinArrays([[CR], text]); - trailingCr = false; - } - - // Check for trailing CR in current chunk - if (text.length > 0 && text.at(-1) === CR) { - trailingCr = true; - text = text.subarray(0, -1); - } - - if (!text.length) return; - const trailingNewline = TRAILING_NEWLINE.includes(text.at(-1)!); - - const lastIdx = text.length - 1; - const { lines } = text.reduce<{ lines: Uint8Array[]; from: number }>( - (acc, cur, idx) => { - if (acc.from > idx) return acc; - - if (cur === CR || cur === LF) { - acc.lines.push(text.subarray(acc.from, idx)); - if (cur === CR && text[idx + 1] === LF) { - acc.from = idx + 2; - } else { - acc.from = idx + 1; - } - } - - if (idx === lastIdx && acc.from <= lastIdx) { - acc.lines.push(text.subarray(acc.from)); - } - - return acc; - }, - { lines: [], from: 0 }, - ); - - if (lines.length === 1 && !trailingNewline) { - buffer.push(lines[0]); - return; - } - - if (buffer.length) { - // Include existing buffer in first line - buffer.push(lines[0]); - lines[0] = joinArrays(buffer); - buffer = []; - } - - if (!trailingNewline) { - // If the last segment is not newline terminated, - // buffer it for the next chunk - if (lines.length) buffer = [lines.pop()!]; - } - - // Enqueue complete lines - for (const line of lines) { - controller.enqueue(line); - } - }, - - flush(controller) { - if (buffer.length) { - controller.enqueue(joinArrays(buffer)); - } - }, - }); -} - -interface StreamPart { - id: string | undefined; - event: string; - data: unknown; -} - -export function SSEDecoder() { - let event = ""; - let data: Uint8Array[] = []; - let lastEventId = ""; - let retry: number | null = null; - - const decoder = new TextDecoder(); - - return new TransformStream({ - transform(chunk, controller) { - // Handle empty line case - if (!chunk.length) { - if (!event && !data.length && !lastEventId && retry == null) return; - - const sse = { - id: lastEventId || undefined, - event, - data: data.length ? decodeArraysToJson(decoder, data) : null, - }; - - // NOTE: as per the SSE spec, do not reset lastEventId - event = ""; - data = []; - retry = null; - - controller.enqueue(sse); - return; - } - - // Ignore comments - if (chunk[0] === COLON) return; - - const sepIdx = chunk.indexOf(COLON); - if (sepIdx === -1) return; - - const fieldName = decoder.decode(chunk.subarray(0, sepIdx)); - let value = chunk.subarray(sepIdx + 1); - if (value[0] === SPACE) value = value.subarray(1); - - if (fieldName === "event") { - event = decoder.decode(value); - } else if (fieldName === "data") { - data.push(value); - } else if (fieldName === "id") { - if (value.indexOf(NULL) === -1) lastEventId = decoder.decode(value); - } else if (fieldName === "retry") { - const retryNum = Number.parseInt(decoder.decode(value)); - if (!Number.isNaN(retryNum)) retry = retryNum; - } - }, - - flush(controller) { - if (event) { - controller.enqueue({ - id: lastEventId || undefined, - event, - data: data.length ? decodeArraysToJson(decoder, data) : null, - }); - } - }, - }); -} - -function joinArrays(data: ArrayLike[]) { - const totalLength = data.reduce((acc, curr) => acc + curr.length, 0); - let merged = new Uint8Array(totalLength); - let offset = 0; - for (const c of data) { - merged.set(c, offset); - offset += c.length; - } - return merged; -} - -function decodeArraysToJson(decoder: TextDecoder, data: ArrayLike[]) { - return JSON.parse(decoder.decode(joinArrays(data))); -} diff --git a/libs/sdk-js/src/utils/stream.ts b/libs/sdk-js/src/utils/stream.ts deleted file mode 100644 index 510204992..000000000 --- a/libs/sdk-js/src/utils/stream.ts +++ /dev/null @@ -1,115 +0,0 @@ -// in this case don't quite match. -type IterableReadableStreamInterface = ReadableStream & AsyncIterable; - -/* - * Support async iterator syntax for ReadableStreams in all environments. - * Source: https://github.com/MattiasBuelens/web-streams-polyfill/pull/122#issuecomment-1627354490 - */ -export class IterableReadableStream - extends ReadableStream - implements IterableReadableStreamInterface -{ - public reader: ReadableStreamDefaultReader; - - ensureReader() { - if (!this.reader) { - this.reader = this.getReader(); - } - } - - async next(): Promise> { - this.ensureReader(); - try { - const result = await this.reader.read(); - if (result.done) { - this.reader.releaseLock(); // release lock when stream becomes closed - return { - done: true, - value: undefined, - }; - } else { - return { - done: false, - value: result.value, - }; - } - } catch (e) { - this.reader.releaseLock(); // release lock when stream becomes errored - throw e; - } - } - - async return(): Promise> { - this.ensureReader(); - // If wrapped in a Node stream, cancel is already called. - if (this.locked) { - const cancelPromise = this.reader.cancel(); // cancel first, but don't await yet - this.reader.releaseLock(); // release lock first - await cancelPromise; // now await it - } - return { done: true, value: undefined }; - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - async throw(e: any): Promise> { - this.ensureReader(); - if (this.locked) { - const cancelPromise = this.reader.cancel(); // cancel first, but don't await yet - this.reader.releaseLock(); // release lock first - await cancelPromise; // now await it - } - throw e; - } - - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore Not present in Node 18 types, required in latest Node 22 - async [Symbol.asyncDispose]() { - await this.return(); - } - - [Symbol.asyncIterator]() { - return this; - } - - static fromReadableStream(stream: ReadableStream) { - // From https://developer.mozilla.org/en-US/docs/Web/API/Streams_API/Using_readable_streams#reading_the_stream - const reader = stream.getReader(); - return new IterableReadableStream({ - start(controller) { - return pump(); - function pump(): Promise { - return reader.read().then(({ done, value }) => { - // When no more data needs to be consumed, close the stream - if (done) { - controller.close(); - return; - } - // Enqueue the next data chunk into our target stream - controller.enqueue(value); - return pump(); - }); - } - }, - cancel() { - reader.releaseLock(); - }, - }); - } - - static fromAsyncGenerator(generator: AsyncGenerator) { - return new IterableReadableStream({ - async pull(controller) { - const { value, done } = await generator.next(); - // When no more data needs to be consumed, close the stream - if (done) { - controller.close(); - } - // Fix: `else if (value)` will hang the streaming when nullish value (e.g. empty string) is pulled - controller.enqueue(value); - }, - async cancel(reason) { - await generator.return(reason); - }, - }); - } -} diff --git a/libs/sdk-js/tsconfig.cjs.json b/libs/sdk-js/tsconfig.cjs.json deleted file mode 100644 index 6f1705b8b..000000000 --- a/libs/sdk-js/tsconfig.cjs.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "module": "CommonJS", - "moduleResolution": "Node", - "declaration": false - }, - "exclude": ["node_modules", "dist", "**/tests"] -} diff --git a/libs/sdk-js/tsconfig.json b/libs/sdk-js/tsconfig.json deleted file mode 100644 index d5c1626ab..000000000 --- a/libs/sdk-js/tsconfig.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "extends": "@tsconfig/recommended", - "compilerOptions": { - "target": "ES2021", - "lib": ["ES2021", "ES2022.Object", "ES2022.Error", "DOM"], - "module": "NodeNext", - "moduleResolution": "nodenext", - "esModuleInterop": true, - "declaration": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "useDefineForClassFields": true, - "strictPropertyInitialization": false, - "allowJs": true, - "strict": true, - "jsx": "react-jsx", - "outDir": "dist" - }, - "include": ["src/**/*"], - "exclude": ["node_modules", "dist", "coverage"], - "includeVersion": true, - "typedocOptions": { - "entryPoints": ["src/client.ts"], - "readme": "none", - "out": "docs", - "plugin": ["typedoc-plugin-markdown"], - "excludePrivate": true, - "excludeProtected": true, - "excludeExternals": false - } -} diff --git a/libs/sdk-js/typedoc.auth.json b/libs/sdk-js/typedoc.auth.json deleted file mode 100644 index 1cb718f4a..000000000 --- a/libs/sdk-js/typedoc.auth.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "pageTitleTemplates": { - "index": "{projectName}/auth" - } -} diff --git a/libs/sdk-js/typedoc.react.json b/libs/sdk-js/typedoc.react.json deleted file mode 100644 index 6359dac1b..000000000 --- a/libs/sdk-js/typedoc.react.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "pageTitleTemplates": { - "index": "{projectName}/react" - } -} diff --git a/libs/sdk-js/vitest.config.ts b/libs/sdk-js/vitest.config.ts deleted file mode 100644 index 01f2a7fac..000000000 --- a/libs/sdk-js/vitest.config.ts +++ /dev/null @@ -1,11 +0,0 @@ -import react from "@vitejs/plugin-react"; -import { defineConfig } from "vitest/config"; - -export default defineConfig({ - plugins: [react()], - test: { - environment: "jsdom", - globals: true, - include: ["src/**/*.test.ts", "src/**/*.test.tsx"], - }, -}); diff --git a/libs/sdk-js/yarn.lock b/libs/sdk-js/yarn.lock deleted file mode 100644 index 0e4e00cc2..000000000 --- a/libs/sdk-js/yarn.lock +++ /dev/null @@ -1,5259 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@adobe/css-tools@^4.4.0": - version "4.4.2" - resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.4.2.tgz#c836b1bd81e6d62cd6cdf3ee4948bcdce8ea79c8" - integrity sha512-baYZExFpsdkBNuvGKTKWCwKH57HRZLVtycZS05WTQNVOiXVSeAki3nU35zlRbToeMW8aHlJfyS+1C4BOv27q0A== - -"@alloc/quick-lru@^5.2.0": - version "5.2.0" - resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30" - integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw== - -"@ampproject/remapping@^2.2.0", "@ampproject/remapping@^2.3.0": - version "2.3.0" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" - integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== - dependencies: - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.24" - -"@asamuzakjp/css-color@^3.1.2": - version "3.1.7" - resolved "https://registry.yarnpkg.com/@asamuzakjp/css-color/-/css-color-3.1.7.tgz#01fb8475bc8dc999ddc4b270ab2e31f82780d17f" - integrity sha512-Ok5fYhtwdyJQmU1PpEv6Si7Y+A4cYb8yNM9oiIJC9TzXPMuN9fvdonKJqcnz9TbFqV6bQ8z0giRq0iaOpGZV2g== - dependencies: - "@csstools/css-calc" "^2.1.3" - "@csstools/css-color-parser" "^3.0.9" - "@csstools/css-parser-algorithms" "^3.0.4" - "@csstools/css-tokenizer" "^3.0.3" - lru-cache "^10.4.3" - -"@babel/code-frame@^7.0.0": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" - integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== - dependencies: - "@babel/highlight" "^7.24.7" - picocolors "^1.0.0" - -"@babel/code-frame@^7.10.4", "@babel/code-frame@^7.26.2", "@babel/code-frame@^7.27.1": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be" - integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg== - dependencies: - "@babel/helper-validator-identifier" "^7.27.1" - js-tokens "^4.0.0" - picocolors "^1.1.1" - -"@babel/compat-data@^7.27.2": - version "7.27.2" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.27.2.tgz#4183f9e642fd84e74e3eea7ffa93a412e3b102c9" - integrity sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ== - -"@babel/core@^7.26.10": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.27.1.tgz#89de51e86bd12246003e3524704c49541b16c3e6" - integrity sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ== - dependencies: - "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.27.1" - "@babel/generator" "^7.27.1" - "@babel/helper-compilation-targets" "^7.27.1" - "@babel/helper-module-transforms" "^7.27.1" - "@babel/helpers" "^7.27.1" - "@babel/parser" "^7.27.1" - "@babel/template" "^7.27.1" - "@babel/traverse" "^7.27.1" - "@babel/types" "^7.27.1" - convert-source-map "^2.0.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.3" - semver "^6.3.1" - -"@babel/generator@^7.27.1": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.27.1.tgz#862d4fad858f7208edd487c28b58144036b76230" - integrity sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w== - dependencies: - "@babel/parser" "^7.27.1" - "@babel/types" "^7.27.1" - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.25" - jsesc "^3.0.2" - -"@babel/helper-compilation-targets@^7.27.1": - version "7.27.2" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz#46a0f6efab808d51d29ce96858dd10ce8732733d" - integrity sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ== - dependencies: - "@babel/compat-data" "^7.27.2" - "@babel/helper-validator-option" "^7.27.1" - browserslist "^4.24.0" - lru-cache "^5.1.1" - semver "^6.3.1" - -"@babel/helper-module-imports@^7.27.1": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz#7ef769a323e2655e126673bb6d2d6913bbead204" - integrity sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w== - dependencies: - "@babel/traverse" "^7.27.1" - "@babel/types" "^7.27.1" - -"@babel/helper-module-transforms@^7.27.1": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.27.1.tgz#e1663b8b71d2de948da5c4fb2a20ca4f3ec27a6f" - integrity sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g== - dependencies: - "@babel/helper-module-imports" "^7.27.1" - "@babel/helper-validator-identifier" "^7.27.1" - "@babel/traverse" "^7.27.1" - -"@babel/helper-plugin-utils@^7.27.1": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz#ddb2f876534ff8013e6c2b299bf4d39b3c51d44c" - integrity sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw== - -"@babel/helper-string-parser@^7.27.1": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687" - integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== - -"@babel/helper-validator-identifier@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" - integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== - -"@babel/helper-validator-identifier@^7.27.1": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz#a7054dcc145a967dd4dc8fee845a57c1316c9df8" - integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow== - -"@babel/helper-validator-option@^7.27.1": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz#fa52f5b1e7db1ab049445b421c4471303897702f" - integrity sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg== - -"@babel/helpers@^7.27.1": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.27.1.tgz#ffc27013038607cdba3288e692c3611c06a18aa4" - integrity sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ== - dependencies: - "@babel/template" "^7.27.1" - "@babel/types" "^7.27.1" - -"@babel/highlight@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" - integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw== - dependencies: - "@babel/helper-validator-identifier" "^7.24.7" - chalk "^2.4.2" - js-tokens "^4.0.0" - picocolors "^1.0.0" - -"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.27.1", "@babel/parser@^7.27.2": - version "7.27.2" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.27.2.tgz#577518bedb17a2ce4212afd052e01f7df0941127" - integrity sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw== - dependencies: - "@babel/types" "^7.27.1" - -"@babel/plugin-transform-react-jsx-self@^7.25.9": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz#af678d8506acf52c577cac73ff7fe6615c85fc92" - integrity sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw== - dependencies: - "@babel/helper-plugin-utils" "^7.27.1" - -"@babel/plugin-transform-react-jsx-source@^7.25.9": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz#dcfe2c24094bb757bf73960374e7c55e434f19f0" - integrity sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw== - dependencies: - "@babel/helper-plugin-utils" "^7.27.1" - -"@babel/runtime@^7.12.5": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.27.1.tgz#9fce313d12c9a77507f264de74626e87fd0dc541" - integrity sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog== - -"@babel/template@^7.27.1": - version "7.27.2" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.2.tgz#fa78ceed3c4e7b63ebf6cb39e5852fca45f6809d" - integrity sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw== - dependencies: - "@babel/code-frame" "^7.27.1" - "@babel/parser" "^7.27.2" - "@babel/types" "^7.27.1" - -"@babel/traverse@^7.27.1": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.27.1.tgz#4db772902b133bbddd1c4f7a7ee47761c1b9f291" - integrity sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg== - dependencies: - "@babel/code-frame" "^7.27.1" - "@babel/generator" "^7.27.1" - "@babel/parser" "^7.27.1" - "@babel/template" "^7.27.1" - "@babel/types" "^7.27.1" - debug "^4.3.1" - globals "^11.1.0" - -"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.27.1": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.27.1.tgz#9defc53c16fc899e46941fc6901a9eea1c9d8560" - integrity sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q== - dependencies: - "@babel/helper-string-parser" "^7.27.1" - "@babel/helper-validator-identifier" "^7.27.1" - -"@bundled-es-modules/cookie@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@bundled-es-modules/cookie/-/cookie-2.0.1.tgz#b41376af6a06b3e32a15241d927b840a9b4de507" - integrity sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw== - dependencies: - cookie "^0.7.2" - -"@bundled-es-modules/statuses@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@bundled-es-modules/statuses/-/statuses-1.0.1.tgz#761d10f44e51a94902c4da48675b71a76cc98872" - integrity sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg== - dependencies: - statuses "^2.0.1" - -"@bundled-es-modules/tough-cookie@^0.1.6": - version "0.1.6" - resolved "https://registry.yarnpkg.com/@bundled-es-modules/tough-cookie/-/tough-cookie-0.1.6.tgz#fa9cd3cedfeecd6783e8b0d378b4a99e52bde5d3" - integrity sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw== - dependencies: - "@types/tough-cookie" "^4.0.5" - tough-cookie "^4.1.4" - -"@cfworker/json-schema@^4.0.2": - version "4.1.1" - resolved "https://registry.yarnpkg.com/@cfworker/json-schema/-/json-schema-4.1.1.tgz#4a2a3947ee9fa7b7c24be981422831b8674c3be6" - integrity sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og== - -"@colors/colors@1.6.0", "@colors/colors@^1.6.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.6.0.tgz#ec6cd237440700bc23ca23087f513c75508958b0" - integrity sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA== - -"@commander-js/extra-typings@^13.0.0": - version "13.1.0" - resolved "https://registry.yarnpkg.com/@commander-js/extra-typings/-/extra-typings-13.1.0.tgz#026e29b04401c92fc4307223fbaadf1ff3e5551e" - integrity sha512-q5P52BYb1hwVWE6dtID7VvuJWrlfbCv4klj7BjUUOqMz4jbSZD4C9fJ9lRjL2jnBGTg+gDDlaXN51rkWcLk4fg== - -"@csstools/color-helpers@^5.0.2": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@csstools/color-helpers/-/color-helpers-5.0.2.tgz#82592c9a7c2b83c293d9161894e2a6471feb97b8" - integrity sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA== - -"@csstools/css-calc@^2.1.3": - version "2.1.3" - resolved "https://registry.yarnpkg.com/@csstools/css-calc/-/css-calc-2.1.3.tgz#6f68affcb569a86b91965e8622d644be35a08423" - integrity sha512-XBG3talrhid44BY1x3MHzUx/aTG8+x/Zi57M4aTKK9RFB4aLlF3TTSzfzn8nWVHWL3FgAXAxmupmDd6VWww+pw== - -"@csstools/css-color-parser@^3.0.9": - version "3.0.9" - resolved "https://registry.yarnpkg.com/@csstools/css-color-parser/-/css-color-parser-3.0.9.tgz#8d81b77d6f211495b5100ec4cad4c8828de49f6b" - integrity sha512-wILs5Zk7BU86UArYBJTPy/FMPPKVKHMj1ycCEyf3VUptol0JNRLFU/BZsJ4aiIHJEbSLiizzRrw8Pc1uAEDrXw== - dependencies: - "@csstools/color-helpers" "^5.0.2" - "@csstools/css-calc" "^2.1.3" - -"@csstools/css-parser-algorithms@^3.0.4": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.4.tgz#74426e93bd1c4dcab3e441f5cc7ba4fb35d94356" - integrity sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A== - -"@csstools/css-tokenizer@^3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@csstools/css-tokenizer/-/css-tokenizer-3.0.3.tgz#a5502c8539265fecbd873c1e395a890339f119c2" - integrity sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw== - -"@dabh/diagnostics@^2.0.2": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.3.tgz#7f7e97ee9a725dffc7808d93668cc984e1dc477a" - integrity sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA== - dependencies: - colorspace "1.1.x" - enabled "2.0.x" - kuler "^2.0.0" - -"@emnapi/core@^1.4.3": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.4.3.tgz#9ac52d2d5aea958f67e52c40a065f51de59b77d6" - integrity sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g== - dependencies: - "@emnapi/wasi-threads" "1.0.2" - tslib "^2.4.0" - -"@emnapi/runtime@^1.4.3": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.4.3.tgz#c0564665c80dc81c448adac23f9dfbed6c838f7d" - integrity sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ== - dependencies: - tslib "^2.4.0" - -"@emnapi/wasi-threads@1.0.2", "@emnapi/wasi-threads@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@emnapi/wasi-threads/-/wasi-threads-1.0.2.tgz#977f44f844eac7d6c138a415a123818c655f874c" - integrity sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA== - dependencies: - tslib "^2.4.0" - -"@esbuild/aix-ppc64@0.25.4": - version "0.25.4" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz#830d6476cbbca0c005136af07303646b419f1162" - integrity sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q== - -"@esbuild/aix-ppc64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz#4e0f91776c2b340e75558f60552195f6fad09f18" - integrity sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA== - -"@esbuild/android-arm64@0.25.4": - version "0.25.4" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.4.tgz#d11d4fc299224e729e2190cacadbcc00e7a9fd67" - integrity sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A== - -"@esbuild/android-arm64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz#bc766407f1718923f6b8079c8c61bf86ac3a6a4f" - integrity sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg== - -"@esbuild/android-arm@0.25.4": - version "0.25.4" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.4.tgz#5660bd25080553dd2a28438f2a401a29959bd9b1" - integrity sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ== - -"@esbuild/android-arm@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.5.tgz#4290d6d3407bae3883ad2cded1081a234473ce26" - integrity sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA== - -"@esbuild/android-x64@0.25.4": - version "0.25.4" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.4.tgz#18ddde705bf984e8cd9efec54e199ac18bc7bee1" - integrity sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ== - -"@esbuild/android-x64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.5.tgz#40c11d9cbca4f2406548c8a9895d321bc3b35eff" - integrity sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw== - -"@esbuild/darwin-arm64@0.25.4": - version "0.25.4" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz#b0b7fb55db8fc6f5de5a0207ae986eb9c4766e67" - integrity sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g== - -"@esbuild/darwin-arm64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz#49d8bf8b1df95f759ac81eb1d0736018006d7e34" - integrity sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ== - -"@esbuild/darwin-x64@0.25.4": - version "0.25.4" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.4.tgz#e6813fdeba0bba356cb350a4b80543fbe66bf26f" - integrity sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A== - -"@esbuild/darwin-x64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz#e27a5d92a14886ef1d492fd50fc61a2d4d87e418" - integrity sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ== - -"@esbuild/freebsd-arm64@0.25.4": - version "0.25.4" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.4.tgz#dc11a73d3ccdc308567b908b43c6698e850759be" - integrity sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ== - -"@esbuild/freebsd-arm64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz#97cede59d638840ca104e605cdb9f1b118ba0b1c" - integrity sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw== - -"@esbuild/freebsd-x64@0.25.4": - version "0.25.4" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.4.tgz#91da08db8bd1bff5f31924c57a81dab26e93a143" - integrity sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ== - -"@esbuild/freebsd-x64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz#71c77812042a1a8190c3d581e140d15b876b9c6f" - integrity sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw== - -"@esbuild/linux-arm64@0.25.4": - version "0.25.4" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.4.tgz#efc15e45c945a082708f9a9f73bfa8d4db49728a" - integrity sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ== - -"@esbuild/linux-arm64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz#f7b7c8f97eff8ffd2e47f6c67eb5c9765f2181b8" - integrity sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg== - -"@esbuild/linux-arm@0.25.4": - version "0.25.4" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.4.tgz#9b93c3e54ac49a2ede6f906e705d5d906f6db9e8" - integrity sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ== - -"@esbuild/linux-arm@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz#2a0be71b6cd8201fa559aea45598dffabc05d911" - integrity sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw== - -"@esbuild/linux-ia32@0.25.4": - version "0.25.4" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.4.tgz#be8ef2c3e1d99fca2d25c416b297d00360623596" - integrity sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ== - -"@esbuild/linux-ia32@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz#763414463cd9ea6fa1f96555d2762f9f84c61783" - integrity sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA== - -"@esbuild/linux-loong64@0.25.4": - version "0.25.4" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.4.tgz#b0840a2707c3fc02eec288d3f9defa3827cd7a87" - integrity sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA== - -"@esbuild/linux-loong64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz#428cf2213ff786a502a52c96cf29d1fcf1eb8506" - integrity sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg== - -"@esbuild/linux-mips64el@0.25.4": - version "0.25.4" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.4.tgz#2a198e5a458c9f0e75881a4e63d26ba0cf9df39f" - integrity sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg== - -"@esbuild/linux-mips64el@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz#5cbcc7fd841b4cd53358afd33527cd394e325d96" - integrity sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg== - -"@esbuild/linux-ppc64@0.25.4": - version "0.25.4" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.4.tgz#64f4ae0b923d7dd72fb860b9b22edb42007cf8f5" - integrity sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag== - -"@esbuild/linux-ppc64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz#0d954ab39ce4f5e50f00c4f8c4fd38f976c13ad9" - integrity sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ== - -"@esbuild/linux-riscv64@0.25.4": - version "0.25.4" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.4.tgz#fb2844b11fdddd39e29d291c7cf80f99b0d5158d" - integrity sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA== - -"@esbuild/linux-riscv64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz#0e7dd30730505abd8088321e8497e94b547bfb1e" - integrity sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA== - -"@esbuild/linux-s390x@0.25.4": - version "0.25.4" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.4.tgz#1466876e0aa3560c7673e63fdebc8278707bc750" - integrity sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g== - -"@esbuild/linux-s390x@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz#5669af81327a398a336d7e40e320b5bbd6e6e72d" - integrity sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ== - -"@esbuild/linux-x64@0.25.4": - version "0.25.4" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.4.tgz#c10fde899455db7cba5f11b3bccfa0e41bf4d0cd" - integrity sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA== - -"@esbuild/linux-x64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz#b2357dd153aa49038967ddc1ffd90c68a9d2a0d4" - integrity sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw== - -"@esbuild/netbsd-arm64@0.25.4": - version "0.25.4" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.4.tgz#02e483fbcbe3f18f0b02612a941b77be76c111a4" - integrity sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ== - -"@esbuild/netbsd-arm64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz#53b4dfb8fe1cee93777c9e366893bd3daa6ba63d" - integrity sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw== - -"@esbuild/netbsd-x64@0.25.4": - version "0.25.4" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.4.tgz#ec401fb0b1ed0ac01d978564c5fc8634ed1dc2ed" - integrity sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw== - -"@esbuild/netbsd-x64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz#a0206f6314ce7dc8713b7732703d0f58de1d1e79" - integrity sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ== - -"@esbuild/openbsd-arm64@0.25.4": - version "0.25.4" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.4.tgz#f272c2f41cfea1d91b93d487a51b5c5ca7a8c8c4" - integrity sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A== - -"@esbuild/openbsd-arm64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz#2a796c87c44e8de78001d808c77d948a21ec22fd" - integrity sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw== - -"@esbuild/openbsd-x64@0.25.4": - version "0.25.4" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.4.tgz#2e25950bc10fa9db1e5c868e3d50c44f7c150fd7" - integrity sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw== - -"@esbuild/openbsd-x64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz#28d0cd8909b7fa3953af998f2b2ed34f576728f0" - integrity sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg== - -"@esbuild/sunos-x64@0.25.4": - version "0.25.4" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.4.tgz#cd596fa65a67b3b7adc5ecd52d9f5733832e1abd" - integrity sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q== - -"@esbuild/sunos-x64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz#a28164f5b997e8247d407e36c90d3fd5ddbe0dc5" - integrity sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA== - -"@esbuild/win32-arm64@0.25.4": - version "0.25.4" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.4.tgz#b4dbcb57b21eeaf8331e424c3999b89d8951dc88" - integrity sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ== - -"@esbuild/win32-arm64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz#6eadbead38e8bd12f633a5190e45eff80e24007e" - integrity sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw== - -"@esbuild/win32-ia32@0.25.4": - version "0.25.4" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.4.tgz#410842e5d66d4ece1757634e297a87635eb82f7a" - integrity sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg== - -"@esbuild/win32-ia32@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz#bab6288005482f9ed2adb9ded7e88eba9a62cc0d" - integrity sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ== - -"@esbuild/win32-x64@0.25.4": - version "0.25.4" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz#0b17ec8a70b2385827d52314c1253160a0b9bacc" - integrity sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ== - -"@esbuild/win32-x64@0.25.5": - version "0.25.5" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz#7fc114af5f6563f19f73324b5d5ff36ece0803d1" - integrity sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g== - -"@gerrit0/mini-shiki@^1.24.0": - version "1.27.2" - resolved "https://registry.yarnpkg.com/@gerrit0/mini-shiki/-/mini-shiki-1.27.2.tgz#cf2a9fcb08a6581c78fc94821f0c854ec4b9f899" - integrity sha512-GeWyHz8ao2gBiUW4OJnQDxXQnFgZQwwQk05t/CVVgNBN7/rK8XZ7xY6YhLVv9tH3VppWWmr9DCl3MwemB/i+Og== - dependencies: - "@shikijs/engine-oniguruma" "^1.27.2" - "@shikijs/types" "^1.27.2" - "@shikijs/vscode-textmate" "^10.0.1" - -"@hono/node-server@^1.12.0": - version "1.14.4" - resolved "https://registry.yarnpkg.com/@hono/node-server/-/node-server-1.14.4.tgz#e6c27a8b40ae8fa8e49b58bc4b7554accfb2d298" - integrity sha512-DnxpshhYewr2q9ZN8ez/M5mmc3sucr8CT1sIgIy1bkeUXut9XWDkqHoFHRhWIQgkYnKpVRxunyhK7WzpJeJ6qQ== - -"@hono/zod-validator@^0.2.2": - version "0.2.2" - resolved "https://registry.yarnpkg.com/@hono/zod-validator/-/zod-validator-0.2.2.tgz#929a1c40aee5eac1ed9c84094d6d977e0b70187a" - integrity sha512-dSDxaPV70Py8wuIU2QNpoVEIOSzSXZ/6/B/h4xA7eOMz7+AarKTSGV8E6QwrdcCbBLkpqfJ4Q2TmBO0eP1tCBQ== - -"@inquirer/confirm@^5.0.0": - version "5.1.10" - resolved "https://registry.yarnpkg.com/@inquirer/confirm/-/confirm-5.1.10.tgz#de3732cb7ae9333bd3e354afee6a6ef8cf28d951" - integrity sha512-FxbQ9giWxUWKUk2O5XZ6PduVnH2CZ/fmMKMBkH71MHJvWr7WL5AHKevhzF1L5uYWB2P548o1RzVxrNd3dpmk6g== - dependencies: - "@inquirer/core" "^10.1.11" - "@inquirer/type" "^3.0.6" - -"@inquirer/core@^10.1.11": - version "10.1.11" - resolved "https://registry.yarnpkg.com/@inquirer/core/-/core-10.1.11.tgz#4022032b5b6b35970e1c3fcfc522bc250ef8810d" - integrity sha512-BXwI/MCqdtAhzNQlBEFE7CEflhPkl/BqvAuV/aK6lW3DClIfYVDWPP/kXuXHtBWC7/EEbNqd/1BGq2BGBBnuxw== - dependencies: - "@inquirer/figures" "^1.0.11" - "@inquirer/type" "^3.0.6" - ansi-escapes "^4.3.2" - cli-width "^4.1.0" - mute-stream "^2.0.0" - signal-exit "^4.1.0" - wrap-ansi "^6.2.0" - yoctocolors-cjs "^2.1.2" - -"@inquirer/figures@^1.0.11": - version "1.0.11" - resolved "https://registry.yarnpkg.com/@inquirer/figures/-/figures-1.0.11.tgz#4744e6db95288fea1dead779554859710a959a21" - integrity sha512-eOg92lvrn/aRUqbxRyvpEWnrvRuTYRifixHkYVpJiygTgVSBIHDqLh0SrMQXkafvULg3ck11V7xvR+zcgvpHFw== - -"@inquirer/type@^3.0.6": - version "3.0.6" - resolved "https://registry.yarnpkg.com/@inquirer/type/-/type-3.0.6.tgz#2500e435fc2014c5250eec3279f42b70b64089bd" - integrity sha512-/mKVCtVpyBu3IDarv0G+59KC4stsD5mDsGpYh+GKs1NZT88Jh52+cuoA1AtLk2Q0r/quNl+1cSUyLRHBFeD0XA== - -"@isaacs/cliui@^8.0.2": - version "8.0.2" - resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" - integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== - dependencies: - string-width "^5.1.2" - string-width-cjs "npm:string-width@^4.2.0" - strip-ansi "^7.0.1" - strip-ansi-cjs "npm:strip-ansi@^6.0.1" - wrap-ansi "^8.1.0" - wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" - -"@isaacs/fs-minipass@^4.0.0": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz#2d59ae3ab4b38fb4270bfa23d30f8e2e86c7fe32" - integrity sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w== - dependencies: - minipass "^7.0.4" - -"@jridgewell/gen-mapping@^0.3.5": - version "0.3.8" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz#4f0e06362e01362f823d348f1872b08f666d8142" - integrity sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA== - dependencies: - "@jridgewell/set-array" "^1.2.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.24" - -"@jridgewell/resolve-uri@^3.1.0": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" - integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== - -"@jridgewell/set-array@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" - integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== - -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" - integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== - -"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": - version "0.3.25" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" - integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== - dependencies: - "@jridgewell/resolve-uri" "^3.1.0" - "@jridgewell/sourcemap-codec" "^1.4.14" - -"@langchain/core@^0.3.61": - version "0.3.61" - resolved "https://registry.yarnpkg.com/@langchain/core/-/core-0.3.61.tgz#73e0f7971e99bd45985d2ba58229e41b93b6149d" - integrity sha512-4O7fw5SXNSE+uBnathLQrhm3t+7dZGagt/5kt37A+pXw0AkudxEBvveg73sSnpBd9SIz3/Vc7F4k8rCKXGbEDA== - dependencies: - "@cfworker/json-schema" "^4.0.2" - ansi-styles "^5.0.0" - camelcase "6" - decamelize "1.2.0" - js-tiktoken "^1.0.12" - langsmith "^0.3.33" - mustache "^4.2.0" - p-queue "^6.6.2" - p-retry "4" - uuid "^10.0.0" - zod "^3.25.32" - zod-to-json-schema "^3.22.3" - -"@langchain/langgraph-api@~0.0.41": - version "0.0.41" - resolved "https://registry.yarnpkg.com/@langchain/langgraph-api/-/langgraph-api-0.0.41.tgz#a8219651dfd097225e66129ce367ef8e0ae23d45" - integrity sha512-LxiVspoVRB5AYBoC04XmigFTjYtEut3Unf9dlwuMgdRMxfyiN/oI3Wuun9Q/Tfn7jYt3E8FVtUqCLgT1QUG3Rw== - dependencies: - "@babel/code-frame" "^7.26.2" - "@hono/node-server" "^1.12.0" - "@hono/zod-validator" "^0.2.2" - "@langchain/langgraph-ui" "0.0.41" - "@types/json-schema" "^7.0.15" - "@typescript/vfs" "^1.6.0" - dedent "^1.5.3" - dotenv "^16.4.7" - exit-hook "^4.0.0" - hono "^4.5.4" - langsmith "^0.3.33" - open "^10.1.0" - semver "^7.7.1" - stacktrace-parser "^0.1.10" - superjson "^2.2.2" - tsx "^4.19.3" - uuid "^10.0.0" - winston "^3.17.0" - winston-console-format "^1.0.8" - zod "^3.23.8" - -"@langchain/langgraph-checkpoint@~0.0.18": - version "0.0.18" - resolved "https://registry.yarnpkg.com/@langchain/langgraph-checkpoint/-/langgraph-checkpoint-0.0.18.tgz#2f7a9cdeda948ccc8d312ba9463810709d71d0b8" - integrity sha512-IS7zJj36VgY+4pf8ZjsVuUWef7oTwt1y9ylvwu0aLuOn1d0fg05Om9DLm3v2GZ2Df6bhLV1kfWAM0IAl9O5rQQ== - dependencies: - uuid "^10.0.0" - -"@langchain/langgraph-sdk@~0.0.32": - version "0.0.84" - resolved "https://registry.yarnpkg.com/@langchain/langgraph-sdk/-/langgraph-sdk-0.0.84.tgz#91f1bb431838c0f945326755681dcf3465ca4962" - integrity sha512-l0PFQyJ+6m6aclORNPPWlcRwgKcXVXsPaJCbCUYFABR3yf4cOpsjhUNR0cJ7+2cS400oieHjGRdGGyO/hbSjhg== - dependencies: - "@types/json-schema" "^7.0.15" - p-queue "^6.6.2" - p-retry "4" - uuid "^9.0.0" - -"@langchain/langgraph-ui@0.0.41": - version "0.0.41" - resolved "https://registry.yarnpkg.com/@langchain/langgraph-ui/-/langgraph-ui-0.0.41.tgz#6c581f150274b397031b687b6a569a220532cb85" - integrity sha512-7PSSYCgijNRrDbYDj0VuxzPMgUSh4uAO0Z35p4GuB0CZliztUaZVtSGET0mRscT7+98HeWdt4GnpP1fLZt8bxg== - dependencies: - "@commander-js/extra-typings" "^13.0.0" - commander "^13.0.0" - esbuild "^0.25.0" - esbuild-plugin-tailwindcss "^2.0.1" - zod "^3.23.8" - -"@langchain/langgraph@^0.3.5": - version "0.3.5" - resolved "https://registry.yarnpkg.com/@langchain/langgraph/-/langgraph-0.3.5.tgz#57e6d2de3b10ce148b4a4288839b9e9d6b4405e0" - integrity sha512-7astlgnp6BdMQJqmr+cbDgR10FYWNCaDLnbfEDHpqhKCCajU59m5snOdl4Vtu5UM6V2k3lgatNqWoflBtxhIyg== - dependencies: - "@langchain/langgraph-checkpoint" "~0.0.18" - "@langchain/langgraph-sdk" "~0.0.32" - uuid "^10.0.0" - zod "^3.25.32" - -"@langchain/scripts@^0.1.4": - version "0.1.4" - resolved "https://registry.yarnpkg.com/@langchain/scripts/-/scripts-0.1.4.tgz#8c5d03d627686f20b9522213c12e2b329e73e381" - integrity sha512-O+mv2aqUIm3XWxYBrwFWMeTI3aHWeFR8OYjGFXKc1MGV/3LLao3PciyQvKUg1SL7FemHJ1ltDx74rKuEv8xxPA== - dependencies: - "@octokit/rest" "^21.0.2" - "@rollup/wasm-node" "^4.19.0" - axios "^1.6.7" - commander "^11.1.0" - glob "^10.3.10" - lodash "^4.17.21" - readline "^1.3.0" - rimraf "^5.0.1" - rollup "^4.5.2" - ts-morph "^21.0.1" - typescript "^5.4.5" - -"@mswjs/interceptors@^0.37.0": - version "0.37.6" - resolved "https://registry.yarnpkg.com/@mswjs/interceptors/-/interceptors-0.37.6.tgz#2635319b7a81934e1ef1b5593ef7910347e2b761" - integrity sha512-wK+5pLK5XFmgtH3aQ2YVvA3HohS3xqV/OxuVOdNx9Wpnz7VE/fnC+e1A7ln6LFYeck7gOJ/dsZV6OLplOtAJ2w== - dependencies: - "@open-draft/deferred-promise" "^2.2.0" - "@open-draft/logger" "^0.3.0" - "@open-draft/until" "^2.0.0" - is-node-process "^1.2.0" - outvariant "^1.4.3" - strict-event-emitter "^0.5.1" - -"@napi-rs/wasm-runtime@^0.2.10": - version "0.2.11" - resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.11.tgz#192c1610e1625048089ab4e35bc0649ce478500e" - integrity sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA== - dependencies: - "@emnapi/core" "^1.4.3" - "@emnapi/runtime" "^1.4.3" - "@tybys/wasm-util" "^0.9.0" - -"@nodelib/fs.scandir@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== - dependencies: - "@nodelib/fs.stat" "2.0.5" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== - -"@nodelib/fs.walk@^1.2.3": - version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== - dependencies: - "@nodelib/fs.scandir" "2.1.5" - fastq "^1.6.0" - -"@octokit/auth-token@^5.0.0": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-5.1.1.tgz#3bbfe905111332a17f72d80bd0b51a3e2fa2cf07" - integrity sha512-rh3G3wDO8J9wSjfI436JUKzHIxq8NaiL0tVeB2aXmG6p/9859aUOAjA9pmSPNGGZxfwmaJ9ozOJImuNVJdpvbA== - -"@octokit/core@^6.1.2": - version "6.1.2" - resolved "https://registry.yarnpkg.com/@octokit/core/-/core-6.1.2.tgz#20442d0a97c411612da206411e356014d1d1bd17" - integrity sha512-hEb7Ma4cGJGEUNOAVmyfdB/3WirWMg5hDuNFVejGEDFqupeOysLc2sG6HJxY2etBp5YQu5Wtxwi020jS9xlUwg== - dependencies: - "@octokit/auth-token" "^5.0.0" - "@octokit/graphql" "^8.0.0" - "@octokit/request" "^9.0.0" - "@octokit/request-error" "^6.0.1" - "@octokit/types" "^13.0.0" - before-after-hook "^3.0.2" - universal-user-agent "^7.0.0" - -"@octokit/endpoint@^10.0.0": - version "10.1.1" - resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-10.1.1.tgz#1a9694e7aef6aa9d854dc78dd062945945869bcc" - integrity sha512-JYjh5rMOwXMJyUpj028cu0Gbp7qe/ihxfJMLc8VZBMMqSwLgOxDI1911gV4Enl1QSavAQNJcwmwBF9M0VvLh6Q== - dependencies: - "@octokit/types" "^13.0.0" - universal-user-agent "^7.0.2" - -"@octokit/graphql@^8.0.0": - version "8.1.1" - resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-8.1.1.tgz#3cacab5f2e55d91c733e3bf481d3a3f8a5f639c4" - integrity sha512-ukiRmuHTi6ebQx/HFRCXKbDlOh/7xEV6QUXaE7MJEKGNAncGI/STSbOkl12qVXZrfZdpXctx5O9X1AIaebiDBg== - dependencies: - "@octokit/request" "^9.0.0" - "@octokit/types" "^13.0.0" - universal-user-agent "^7.0.0" - -"@octokit/openapi-types@^22.2.0": - version "22.2.0" - resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-22.2.0.tgz#75aa7dcd440821d99def6a60b5f014207ae4968e" - integrity sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg== - -"@octokit/plugin-paginate-rest@^11.0.0": - version "11.3.5" - resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.3.5.tgz#a1929b3ba3dc7b63bc73bb6d3c7a3faf2a9c7649" - integrity sha512-cgwIRtKrpwhLoBi0CUNuY83DPGRMaWVjqVI/bGKsLJ4PzyWZNaEmhHroI2xlrVXkk6nFv0IsZpOp+ZWSWUS2AQ== - dependencies: - "@octokit/types" "^13.6.0" - -"@octokit/plugin-request-log@^5.3.1": - version "5.3.1" - resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-5.3.1.tgz#ccb75d9705de769b2aa82bcd105cc96eb0c00f69" - integrity sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw== - -"@octokit/plugin-rest-endpoint-methods@^13.0.0": - version "13.2.6" - resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.2.6.tgz#b9d343dbe88a6cb70cc7fa16faa98f0a29ffe654" - integrity sha512-wMsdyHMjSfKjGINkdGKki06VEkgdEldIGstIEyGX0wbYHGByOwN/KiM+hAAlUwAtPkP3gvXtVQA9L3ITdV2tVw== - dependencies: - "@octokit/types" "^13.6.1" - -"@octokit/request-error@^6.0.1": - version "6.1.5" - resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-6.1.5.tgz#907099e341c4e6179db623a0328d678024f54653" - integrity sha512-IlBTfGX8Yn/oFPMwSfvugfncK2EwRLjzbrpifNaMY8o/HTEAFqCA1FZxjD9cWvSKBHgrIhc4CSBIzMxiLsbzFQ== - dependencies: - "@octokit/types" "^13.0.0" - -"@octokit/request@^9.0.0": - version "9.1.3" - resolved "https://registry.yarnpkg.com/@octokit/request/-/request-9.1.3.tgz#42b693bc06238f43af3c037ebfd35621c6457838" - integrity sha512-V+TFhu5fdF3K58rs1pGUJIDH5RZLbZm5BI+MNF+6o/ssFNT4vWlCh/tVpF3NxGtP15HUxTTMUbsG5llAuU2CZA== - dependencies: - "@octokit/endpoint" "^10.0.0" - "@octokit/request-error" "^6.0.1" - "@octokit/types" "^13.1.0" - universal-user-agent "^7.0.2" - -"@octokit/rest@^21.0.2": - version "21.0.2" - resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-21.0.2.tgz#9b767dbc1098daea8310fd8b76bf7a97215d5972" - integrity sha512-+CiLisCoyWmYicH25y1cDfCrv41kRSvTq6pPWtRroRJzhsCZWZyCqGyI8foJT5LmScADSwRAnr/xo+eewL04wQ== - dependencies: - "@octokit/core" "^6.1.2" - "@octokit/plugin-paginate-rest" "^11.0.0" - "@octokit/plugin-request-log" "^5.3.1" - "@octokit/plugin-rest-endpoint-methods" "^13.0.0" - -"@octokit/types@^13.0.0", "@octokit/types@^13.1.0", "@octokit/types@^13.6.0", "@octokit/types@^13.6.1": - version "13.6.1" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-13.6.1.tgz#432fc6c0aaae54318e5b2d3e15c22ac97fc9b15f" - integrity sha512-PHZE9Z+kWXb23Ndik8MKPirBPziOc0D2/3KH1P+6jK5nGWe96kadZuE4jev2/Jq7FvIfTlT2Ltg8Fv2x1v0a5g== - dependencies: - "@octokit/openapi-types" "^22.2.0" - -"@open-draft/deferred-promise@^2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz#4a822d10f6f0e316be4d67b4d4f8c9a124b073bd" - integrity sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA== - -"@open-draft/logger@^0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@open-draft/logger/-/logger-0.3.0.tgz#2b3ab1242b360aa0adb28b85f5d7da1c133a0954" - integrity sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ== - dependencies: - is-node-process "^1.2.0" - outvariant "^1.4.0" - -"@open-draft/until@^2.0.0", "@open-draft/until@^2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@open-draft/until/-/until-2.1.0.tgz#0acf32f470af2ceaf47f095cdecd40d68666efda" - integrity sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg== - -"@pkgjs/parseargs@^0.11.0": - version "0.11.0" - resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" - integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== - -"@rollup/rollup-android-arm-eabi@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.4.tgz#c460b54c50d42f27f8254c435a4f3b3e01910bc8" - integrity sha512-jfUJrFct/hTA0XDM5p/htWKoNNTbDLY0KRwEt6pyOA6k2fmk0WVwl65PdUdJZgzGEHWx+49LilkcSaumQRyNQw== - -"@rollup/rollup-android-arm-eabi@4.40.2": - version "4.40.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.2.tgz#c228d00a41f0dbd6fb8b7ea819bbfbf1c1157a10" - integrity sha512-JkdNEq+DFxZfUwxvB58tHMHBHVgX23ew41g1OQinthJ+ryhdRk67O31S7sYw8u2lTjHUPFxwar07BBt1KHp/hg== - -"@rollup/rollup-android-arm64@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.4.tgz#96e01f3a04675d8d5973ab8d3fd6bc3be21fa5e1" - integrity sha512-j4nrEO6nHU1nZUuCfRKoCcvh7PIywQPUCBa2UsootTHvTHIoIu2BzueInGJhhvQO/2FTRdNYpf63xsgEqH9IhA== - -"@rollup/rollup-android-arm64@4.40.2": - version "4.40.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.2.tgz#e2b38d0c912169fd55d7e38d723aada208d37256" - integrity sha512-13unNoZ8NzUmnndhPTkWPWbX3vtHodYmy+I9kuLxN+F+l+x3LdVF7UCu8TWVMt1POHLh6oDHhnOA04n8oJZhBw== - -"@rollup/rollup-darwin-arm64@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.4.tgz#9b2ec23b17b47cbb2f771b81f86ede3ac6730bce" - integrity sha512-GmU/QgGtBTeraKyldC7cDVVvAJEOr3dFLKneez/n7BvX57UdhOqDsVwzU7UOnYA7AAOt+Xb26lk79PldDHgMIQ== - -"@rollup/rollup-darwin-arm64@4.40.2": - version "4.40.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.2.tgz#1fddb3690f2ae33df16d334c613377f05abe4878" - integrity sha512-Gzf1Hn2Aoe8VZzevHostPX23U7N5+4D36WJNHK88NZHCJr7aVMG4fadqkIf72eqVPGjGc0HJHNuUaUcxiR+N/w== - -"@rollup/rollup-darwin-x64@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.4.tgz#f30e4ee6929e048190cf10e0daa8e8ae035b6e46" - integrity sha512-N6oDBiZCBKlwYcsEPXGDE4g9RoxZLK6vT98M8111cW7VsVJFpNEqvJeIPfsCzbf0XEakPslh72X0gnlMi4Ddgg== - -"@rollup/rollup-darwin-x64@4.40.2": - version "4.40.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.2.tgz#818298d11c8109e1112590165142f14be24b396d" - integrity sha512-47N4hxa01a4x6XnJoskMKTS8XZ0CZMd8YTbINbi+w03A2w4j1RTlnGHOz/P0+Bg1LaVL6ufZyNprSg+fW5nYQQ== - -"@rollup/rollup-freebsd-arm64@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.24.4.tgz#c54b2373ec5bcf71f08c4519c7ae80a0b6c8e03b" - integrity sha512-py5oNShCCjCyjWXCZNrRGRpjWsF0ic8f4ieBNra5buQz0O/U6mMXCpC1LvrHuhJsNPgRt36tSYMidGzZiJF6mw== - -"@rollup/rollup-freebsd-arm64@4.40.2": - version "4.40.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.2.tgz#91a28dc527d5bed7f9ecf0e054297b3012e19618" - integrity sha512-8t6aL4MD+rXSHHZUR1z19+9OFJ2rl1wGKvckN47XFRVO+QL/dUSpKA2SLRo4vMg7ELA8pzGpC+W9OEd1Z/ZqoQ== - -"@rollup/rollup-freebsd-x64@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.24.4.tgz#3bc53aa29d5a34c28ba8e00def76aa612368458e" - integrity sha512-L7VVVW9FCnTTp4i7KrmHeDsDvjB4++KOBENYtNYAiYl96jeBThFfhP6HVxL74v4SiZEVDH/1ILscR5U9S4ms4g== - -"@rollup/rollup-freebsd-x64@4.40.2": - version "4.40.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.2.tgz#28acadefa76b5c7bede1576e065b51d335c62c62" - integrity sha512-C+AyHBzfpsOEYRFjztcYUFsH4S7UsE9cDtHCtma5BK8+ydOZYgMmWg1d/4KBytQspJCld8ZIujFMAdKG1xyr4Q== - -"@rollup/rollup-linux-arm-gnueabihf@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.4.tgz#c85aedd1710c9e267ee86b6d1ce355ecf7d9e8d9" - integrity sha512-10ICosOwYChROdQoQo589N5idQIisxjaFE/PAnX2i0Zr84mY0k9zul1ArH0rnJ/fpgiqfu13TFZR5A5YJLOYZA== - -"@rollup/rollup-linux-arm-gnueabihf@4.40.2": - version "4.40.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.2.tgz#819691464179cbcd9a9f9d3dc7617954840c6186" - integrity sha512-de6TFZYIvJwRNjmW3+gaXiZ2DaWL5D5yGmSYzkdzjBDS3W+B9JQ48oZEsmMvemqjtAFzE16DIBLqd6IQQRuG9Q== - -"@rollup/rollup-linux-arm-musleabihf@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.4.tgz#e77313408bf13995aecde281aec0cceb08747e42" - integrity sha512-ySAfWs69LYC7QhRDZNKqNhz2UKN8LDfbKSMAEtoEI0jitwfAG2iZwVqGACJT+kfYvvz3/JgsLlcBP+WWoKCLcw== - -"@rollup/rollup-linux-arm-musleabihf@4.40.2": - version "4.40.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.2.tgz#d149207039e4189e267e8724050388effc80d704" - integrity sha512-urjaEZubdIkacKc930hUDOfQPysezKla/O9qV+O89enqsqUmQm8Xj8O/vh0gHg4LYfv7Y7UsE3QjzLQzDYN1qg== - -"@rollup/rollup-linux-arm64-gnu@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.4.tgz#633f632397b3662108cfaa1abca2a80b85f51102" - integrity sha512-uHYJ0HNOI6pGEeZ/5mgm5arNVTI0nLlmrbdph+pGXpC9tFHFDQmDMOEqkmUObRfosJqpU8RliYoGz06qSdtcjg== - -"@rollup/rollup-linux-arm64-gnu@4.40.2": - version "4.40.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.2.tgz#fa72ebddb729c3c6d88973242f1a2153c83e86ec" - integrity sha512-KlE8IC0HFOC33taNt1zR8qNlBYHj31qGT1UqWqtvR/+NuCVhfufAq9fxO8BMFC22Wu0rxOwGVWxtCMvZVLmhQg== - -"@rollup/rollup-linux-arm64-musl@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.4.tgz#63edd72b29c4cced93e16113a68e1be9fef88907" - integrity sha512-38yiWLemQf7aLHDgTg85fh3hW9stJ0Muk7+s6tIkSUOMmi4Xbv5pH/5Bofnsb6spIwD5FJiR+jg71f0CH5OzoA== - -"@rollup/rollup-linux-arm64-musl@4.40.2": - version "4.40.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.2.tgz#2054216e34469ab8765588ebf343d531fc3c9228" - integrity sha512-j8CgxvfM0kbnhu4XgjnCWJQyyBOeBI1Zq91Z850aUddUmPeQvuAy6OiMdPS46gNFgy8gN1xkYyLgwLYZG3rBOg== - -"@rollup/rollup-linux-loongarch64-gnu@4.40.2": - version "4.40.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.2.tgz#818de242291841afbfc483a84f11e9c7a11959bc" - integrity sha512-Ybc/1qUampKuRF4tQXc7G7QY9YRyeVSykfK36Y5Qc5dmrIxwFhrOzqaVTNoZygqZ1ZieSWTibfFhQ5qK8jpWxw== - -"@rollup/rollup-linux-powerpc64le-gnu@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.4.tgz#a9418a4173df80848c0d47df0426a0bf183c4e75" - integrity sha512-q73XUPnkwt9ZNF2xRS4fvneSuaHw2BXuV5rI4cw0fWYVIWIBeDZX7c7FWhFQPNTnE24172K30I+dViWRVD9TwA== - -"@rollup/rollup-linux-powerpc64le-gnu@4.40.2": - version "4.40.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.2.tgz#0bb4cb8fc4a2c635f68c1208c924b2145eb647cb" - integrity sha512-3FCIrnrt03CCsZqSYAOW/k9n625pjpuMzVfeI+ZBUSDT3MVIFDSPfSUgIl9FqUftxcUXInvFah79hE1c9abD+Q== - -"@rollup/rollup-linux-riscv64-gnu@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.4.tgz#bc9c195db036a27e5e3339b02f51526b4ce1e988" - integrity sha512-Aie/TbmQi6UXokJqDZdmTJuZBCU3QBDA8oTKRGtd4ABi/nHgXICulfg1KI6n9/koDsiDbvHAiQO3YAUNa/7BCw== - -"@rollup/rollup-linux-riscv64-gnu@4.40.2": - version "4.40.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.2.tgz#4b3b8e541b7b13e447ae07774217d98c06f6926d" - integrity sha512-QNU7BFHEvHMp2ESSY3SozIkBPaPBDTsfVNGx3Xhv+TdvWXFGOSH2NJvhD1zKAT6AyuuErJgbdvaJhYVhVqrWTg== - -"@rollup/rollup-linux-riscv64-musl@4.40.2": - version "4.40.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.2.tgz#e065405e67d8bd64a7d0126c931bd9f03910817f" - integrity sha512-5W6vNYkhgfh7URiXTO1E9a0cy4fSgfE4+Hl5agb/U1sa0kjOLMLC1wObxwKxecE17j0URxuTrYZZME4/VH57Hg== - -"@rollup/rollup-linux-s390x-gnu@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.4.tgz#1651fdf8144ae89326c01da5d52c60be63e71a82" - integrity sha512-P8MPErVO/y8ohWSP9JY7lLQ8+YMHfTI4bAdtCi3pC2hTeqFJco2jYspzOzTUB8hwUWIIu1xwOrJE11nP+0JFAQ== - -"@rollup/rollup-linux-s390x-gnu@4.40.2": - version "4.40.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.2.tgz#dda3265bbbfe16a5d0089168fd07f5ebb2a866fe" - integrity sha512-B7LKIz+0+p348JoAL4X/YxGx9zOx3sR+o6Hj15Y3aaApNfAshK8+mWZEf759DXfRLeL2vg5LYJBB7DdcleYCoQ== - -"@rollup/rollup-linux-x64-gnu@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.4.tgz#e473de5e4acb95fcf930a35cbb7d3e8080e57a6f" - integrity sha512-K03TljaaoPK5FOyNMZAAEmhlyO49LaE4qCsr0lYHUKyb6QacTNF9pnfPpXnFlFD3TXuFbFbz7tJ51FujUXkXYA== - -"@rollup/rollup-linux-x64-gnu@4.40.2": - version "4.40.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.2.tgz#90993269b8b995b4067b7b9d72ff1c360ef90a17" - integrity sha512-lG7Xa+BmBNwpjmVUbmyKxdQJ3Q6whHjMjzQplOs5Z+Gj7mxPtWakGHqzMqNER68G67kmCX9qX57aRsW5V0VOng== - -"@rollup/rollup-linux-x64-musl@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.4.tgz#0af12dd2578c29af4037f0c834b4321429dd5b01" - integrity sha512-VJYl4xSl/wqG2D5xTYncVWW+26ICV4wubwN9Gs5NrqhJtayikwCXzPL8GDsLnaLU3WwhQ8W02IinYSFJfyo34Q== - -"@rollup/rollup-linux-x64-musl@4.40.2": - version "4.40.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.2.tgz#fdf5b09fd121eb8d977ebb0fda142c7c0167b8de" - integrity sha512-tD46wKHd+KJvsmije4bUskNuvWKFcTOIM9tZ/RrmIvcXnbi0YK/cKS9FzFtAm7Oxi2EhV5N2OpfFB348vSQRXA== - -"@rollup/rollup-win32-arm64-msvc@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.4.tgz#e48e78cdd45313b977c1390f4bfde7ab79be8871" - integrity sha512-ku2GvtPwQfCqoPFIJCqZ8o7bJcj+Y54cZSr43hHca6jLwAiCbZdBUOrqE6y29QFajNAzzpIOwsckaTFmN6/8TA== - -"@rollup/rollup-win32-arm64-msvc@4.40.2": - version "4.40.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.2.tgz#6397e1e012db64dfecfed0774cb9fcf89503d716" - integrity sha512-Bjv/HG8RRWLNkXwQQemdsWw4Mg+IJ29LK+bJPW2SCzPKOUaMmPEppQlu/Fqk1d7+DX3V7JbFdbkh/NMmurT6Pg== - -"@rollup/rollup-win32-ia32-msvc@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.4.tgz#a3fc8536d243fe161c796acb93eba43c250f311c" - integrity sha512-V3nCe+eTt/W6UYNr/wGvO1fLpHUrnlirlypZfKCT1fG6hWfqhPgQV/K/mRBXBpxc0eKLIF18pIOFVPh0mqHjlg== - -"@rollup/rollup-win32-ia32-msvc@4.40.2": - version "4.40.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.2.tgz#df0991464a52a35506103fe18d29913bf8798a0c" - integrity sha512-dt1llVSGEsGKvzeIO76HToiYPNPYPkmjhMHhP00T9S4rDern8P2ZWvWAQUEJ+R1UdMWJ/42i/QqJ2WV765GZcA== - -"@rollup/rollup-win32-x64-msvc@4.24.4": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.4.tgz#e2a9d1fd56524103a6cc8a54404d9d3ebc73c454" - integrity sha512-LTw1Dfd0mBIEqUVCxbvTE/LLo+9ZxVC9k99v1v4ahg9Aak6FpqOfNu5kRkeTAn0wphoC4JU7No1/rL+bBCEwhg== - -"@rollup/rollup-win32-x64-msvc@4.40.2": - version "4.40.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.2.tgz#8dae04d01a2cbd84d6297d99356674c6b993f0fc" - integrity sha512-bwspbWB04XJpeElvsp+DCylKfF4trJDa2Y9Go8O6A7YLX2LIKGcNK/CYImJN6ZP4DcuOHB4Utl3iCbnR62DudA== - -"@rollup/wasm-node@^4.19.0": - version "4.24.4" - resolved "https://registry.yarnpkg.com/@rollup/wasm-node/-/wasm-node-4.24.4.tgz#11d78f5cc85b04e81468f245c2dc0885d06d663d" - integrity sha512-WKJUdPcM8YAYujafY95+2EapqU3F/nwfBkXh9AfkBvWBwFhsvNJABA86Br6graRH2vRE4FBsiqjFvFWOtEO6wg== - dependencies: - "@types/estree" "1.0.6" - optionalDependencies: - fsevents "~2.3.2" - -"@shikijs/engine-oniguruma@^1.27.2": - version "1.29.2" - resolved "https://registry.yarnpkg.com/@shikijs/engine-oniguruma/-/engine-oniguruma-1.29.2.tgz#d879717ced61d44e78feab16f701f6edd75434f1" - integrity sha512-7iiOx3SG8+g1MnlzZVDYiaeHe7Ez2Kf2HrJzdmGwkRisT7r4rak0e655AcM/tF9JG/kg5fMNYlLLKglbN7gBqA== - dependencies: - "@shikijs/types" "1.29.2" - "@shikijs/vscode-textmate" "^10.0.1" - -"@shikijs/types@1.29.2", "@shikijs/types@^1.27.2": - version "1.29.2" - resolved "https://registry.yarnpkg.com/@shikijs/types/-/types-1.29.2.tgz#a93fdb410d1af8360c67bf5fc1d1a68d58e21c4f" - integrity sha512-VJjK0eIijTZf0QSTODEXCqinjBn0joAHQ+aPSBzrv4O2d/QSbsMw+ZeSRx03kV34Hy7NzUvV/7NqfYGRLrASmw== - dependencies: - "@shikijs/vscode-textmate" "^10.0.1" - "@types/hast" "^3.0.4" - -"@shikijs/vscode-textmate@^10.0.1": - version "10.0.1" - resolved "https://registry.yarnpkg.com/@shikijs/vscode-textmate/-/vscode-textmate-10.0.1.tgz#d06d45b67ac5e9b0088e3f67ebd3f25c6c3d711a" - integrity sha512-fTIQwLF+Qhuws31iw7Ncl1R3HUDtGwIipiJ9iU+UsDUwMhegFcQKQHd51nZjb7CArq0MvON8rbgCGQYWHUKAdg== - -"@tailwindcss/node@4.1.10": - version "4.1.10" - resolved "https://registry.yarnpkg.com/@tailwindcss/node/-/node-4.1.10.tgz#7a53a224cdd79a926ed990bbf97c74de9dadf595" - integrity sha512-2ACf1znY5fpRBwRhMgj9ZXvb2XZW8qs+oTfotJ2C5xR0/WNL7UHZ7zXl6s+rUqedL1mNi+0O+WQr5awGowS3PQ== - dependencies: - "@ampproject/remapping" "^2.3.0" - enhanced-resolve "^5.18.1" - jiti "^2.4.2" - lightningcss "1.30.1" - magic-string "^0.30.17" - source-map-js "^1.2.1" - tailwindcss "4.1.10" - -"@tailwindcss/oxide-android-arm64@4.1.10": - version "4.1.10" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.10.tgz#ad0f3cbfa219e1ee5fc8ad7170885feda397c4e3" - integrity sha512-VGLazCoRQ7rtsCzThaI1UyDu/XRYVyH4/EWiaSX6tFglE+xZB5cvtC5Omt0OQ+FfiIVP98su16jDVHDEIuH4iQ== - -"@tailwindcss/oxide-darwin-arm64@4.1.10": - version "4.1.10" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.10.tgz#d8d744f93310b45ce16420a9addd1c4329848929" - integrity sha512-ZIFqvR1irX2yNjWJzKCqTCcHZbgkSkSkZKbRM3BPzhDL/18idA8uWCoopYA2CSDdSGFlDAxYdU2yBHwAwx8euQ== - -"@tailwindcss/oxide-darwin-x64@4.1.10": - version "4.1.10" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.10.tgz#476490d1f95592a09801a53b48466e5065d7553f" - integrity sha512-eCA4zbIhWUFDXoamNztmS0MjXHSEJYlvATzWnRiTqJkcUteSjO94PoRHJy1Xbwp9bptjeIxxBHh+zBWFhttbrQ== - -"@tailwindcss/oxide-freebsd-x64@4.1.10": - version "4.1.10" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.10.tgz#7b7ccb813592209216ed39187eb8510ce6b4fc9d" - integrity sha512-8/392Xu12R0cc93DpiJvNpJ4wYVSiciUlkiOHOSOQNH3adq9Gi/dtySK7dVQjXIOzlpSHjeCL89RUUI8/GTI6g== - -"@tailwindcss/oxide-linux-arm-gnueabihf@4.1.10": - version "4.1.10" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.10.tgz#9f223c7994da846b9f3c70ac0b5713371c9b3b32" - integrity sha512-t9rhmLT6EqeuPT+MXhWhlRYIMSfh5LZ6kBrC4FS6/+M1yXwfCtp24UumgCWOAJVyjQwG+lYva6wWZxrfvB+NhQ== - -"@tailwindcss/oxide-linux-arm64-gnu@4.1.10": - version "4.1.10" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.10.tgz#58412e6a359a83144b30b415f637a52c8207f311" - integrity sha512-3oWrlNlxLRxXejQ8zImzrVLuZ/9Z2SeKoLhtCu0hpo38hTO2iL86eFOu4sVR8cZc6n3z7eRXXqtHJECa6mFOvA== - -"@tailwindcss/oxide-linux-arm64-musl@4.1.10": - version "4.1.10" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.10.tgz#3ed868b801a27e8cd35a615855bc94fd2786a6e8" - integrity sha512-saScU0cmWvg/Ez4gUmQWr9pvY9Kssxt+Xenfx1LG7LmqjcrvBnw4r9VjkFcqmbBb7GCBwYNcZi9X3/oMda9sqQ== - -"@tailwindcss/oxide-linux-x64-gnu@4.1.10": - version "4.1.10" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.10.tgz#aca15cc4cf9dcd687eda0f5cd2bc1f4bfb485562" - integrity sha512-/G3ao/ybV9YEEgAXeEg28dyH6gs1QG8tvdN9c2MNZdUXYBaIY/Gx0N6RlJzfLy/7Nkdok4kaxKPHKJUlAaoTdA== - -"@tailwindcss/oxide-linux-x64-musl@4.1.10": - version "4.1.10" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.10.tgz#0c77d1e94e499a9f85c80013e6052dd98d3cfee4" - integrity sha512-LNr7X8fTiKGRtQGOerSayc2pWJp/9ptRYAa4G+U+cjw9kJZvkopav1AQc5HHD+U364f71tZv6XamaHKgrIoVzA== - -"@tailwindcss/oxide-wasm32-wasi@4.1.10": - version "4.1.10" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.10.tgz#6e749424db4f6e076371a66da7c4daf1fcd4f9df" - integrity sha512-d6ekQpopFQJAcIK2i7ZzWOYGZ+A6NzzvQ3ozBvWFdeyqfOZdYHU66g5yr+/HC4ipP1ZgWsqa80+ISNILk+ae/Q== - dependencies: - "@emnapi/core" "^1.4.3" - "@emnapi/runtime" "^1.4.3" - "@emnapi/wasi-threads" "^1.0.2" - "@napi-rs/wasm-runtime" "^0.2.10" - "@tybys/wasm-util" "^0.9.0" - tslib "^2.8.0" - -"@tailwindcss/oxide-win32-arm64-msvc@4.1.10": - version "4.1.10" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.10.tgz#e1663b5a95425f0f458f616399ed9f6707d4a786" - integrity sha512-i1Iwg9gRbwNVOCYmnigWCCgow8nDWSFmeTUU5nbNx3rqbe4p0kRbEqLwLJbYZKmSSp23g4N6rCDmm7OuPBXhDA== - -"@tailwindcss/oxide-win32-x64-msvc@4.1.10": - version "4.1.10" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.10.tgz#de3d4e8b38c31caf2522ad0c6f0efdeb5034fc95" - integrity sha512-sGiJTjcBSfGq2DVRtaSljq5ZgZS2SDHSIfhOylkBvHVjwOsodBhnb3HdmiKkVuUGKD0I7G63abMOVaskj1KpOA== - -"@tailwindcss/oxide@4.1.10": - version "4.1.10" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide/-/oxide-4.1.10.tgz#b8ad6ae678b54bb533c2074092aadebac0a6d8fe" - integrity sha512-v0C43s7Pjw+B9w21htrQwuFObSkio2aV/qPx/mhrRldbqxbWJK6KizM+q7BF1/1CmuLqZqX3CeYF7s7P9fbA8Q== - dependencies: - detect-libc "^2.0.4" - tar "^7.4.3" - optionalDependencies: - "@tailwindcss/oxide-android-arm64" "4.1.10" - "@tailwindcss/oxide-darwin-arm64" "4.1.10" - "@tailwindcss/oxide-darwin-x64" "4.1.10" - "@tailwindcss/oxide-freebsd-x64" "4.1.10" - "@tailwindcss/oxide-linux-arm-gnueabihf" "4.1.10" - "@tailwindcss/oxide-linux-arm64-gnu" "4.1.10" - "@tailwindcss/oxide-linux-arm64-musl" "4.1.10" - "@tailwindcss/oxide-linux-x64-gnu" "4.1.10" - "@tailwindcss/oxide-linux-x64-musl" "4.1.10" - "@tailwindcss/oxide-wasm32-wasi" "4.1.10" - "@tailwindcss/oxide-win32-arm64-msvc" "4.1.10" - "@tailwindcss/oxide-win32-x64-msvc" "4.1.10" - -"@tailwindcss/postcss@^4.0.5": - version "4.1.10" - resolved "https://registry.yarnpkg.com/@tailwindcss/postcss/-/postcss-4.1.10.tgz#28e4edd9266a07e3fbfbdbf802563054c408d56b" - integrity sha512-B+7r7ABZbkXJwpvt2VMnS6ujcDoR2OOcFaqrLIo1xbcdxje4Vf+VgJdBzNNbrAjBj/rLZ66/tlQ1knIGNLKOBQ== - dependencies: - "@alloc/quick-lru" "^5.2.0" - "@tailwindcss/node" "4.1.10" - "@tailwindcss/oxide" "4.1.10" - postcss "^8.4.41" - tailwindcss "4.1.10" - -"@testing-library/dom@^10.4.0": - version "10.4.0" - resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-10.4.0.tgz#82a9d9462f11d240ecadbf406607c6ceeeff43a8" - integrity sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/runtime" "^7.12.5" - "@types/aria-query" "^5.0.1" - aria-query "5.3.0" - chalk "^4.1.0" - dom-accessibility-api "^0.5.9" - lz-string "^1.5.0" - pretty-format "^27.0.2" - -"@testing-library/jest-dom@^6.6.3": - version "6.6.3" - resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-6.6.3.tgz#26ba906cf928c0f8172e182c6fe214eb4f9f2bd2" - integrity sha512-IteBhl4XqYNkM54f4ejhLRJiZNqcSCoXUOG2CPK7qbD322KjQozM4kHQOfkG2oln9b9HTYqs+Sae8vBATubxxA== - dependencies: - "@adobe/css-tools" "^4.4.0" - aria-query "^5.0.0" - chalk "^3.0.0" - css.escape "^1.5.1" - dom-accessibility-api "^0.6.3" - lodash "^4.17.21" - redent "^3.0.0" - -"@testing-library/react@^16.3.0": - version "16.3.0" - resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-16.3.0.tgz#3a85bb9bdebf180cd76dba16454e242564d598a6" - integrity sha512-kFSyxiEDwv1WLl2fgsq6pPBbw5aWKrsY2/noi1Id0TK0UParSF62oFQFGHXIyaG4pp2tEub/Zlel+fjjZILDsw== - dependencies: - "@babel/runtime" "^7.12.5" - -"@testing-library/user-event@^14.6.1": - version "14.6.1" - resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-14.6.1.tgz#13e09a32d7a8b7060fe38304788ebf4197cd2149" - integrity sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw== - -"@textlint/ast-node-types@^12.6.1": - version "12.6.1" - resolved "https://registry.yarnpkg.com/@textlint/ast-node-types/-/ast-node-types-12.6.1.tgz#35ecefe74e701d7f632c083d4fda89cab1b89012" - integrity sha512-uzlJ+ZsCAyJm+lBi7j0UeBbj+Oy6w/VWoGJ3iHRHE5eZ8Z4iK66mq+PG/spupmbllLtz77OJbY89BYqgFyjXmA== - -"@textlint/markdown-to-ast@^12.1.1": - version "12.6.1" - resolved "https://registry.yarnpkg.com/@textlint/markdown-to-ast/-/markdown-to-ast-12.6.1.tgz#fcccb5733b3e76cd0db78a323763ab101f2d803b" - integrity sha512-T0HO+VrU9VbLRiEx/kH4+gwGMHNMIGkp0Pok+p0I33saOOLyhfGvwOKQgvt2qkxzQEV2L5MtGB8EnW4r5d3CqQ== - dependencies: - "@textlint/ast-node-types" "^12.6.1" - debug "^4.3.4" - mdast-util-gfm-autolink-literal "^0.1.3" - remark-footnotes "^3.0.0" - remark-frontmatter "^3.0.0" - remark-gfm "^1.0.0" - remark-parse "^9.0.0" - traverse "^0.6.7" - unified "^9.2.2" - -"@ts-morph/common@~0.22.0": - version "0.22.0" - resolved "https://registry.yarnpkg.com/@ts-morph/common/-/common-0.22.0.tgz#8951d451622a26472fbc3a227d6c3a90e687a683" - integrity sha512-HqNBuV/oIlMKdkLshXd1zKBqNQCsuPEsgQOkfFQ/eUKjRlwndXW1AjN9LVkBEIukm00gGXSRmfkl0Wv5VXLnlw== - dependencies: - fast-glob "^3.3.2" - minimatch "^9.0.3" - mkdirp "^3.0.1" - path-browserify "^1.0.1" - -"@tsconfig/recommended@^1.0.2": - version "1.0.6" - resolved "https://registry.yarnpkg.com/@tsconfig/recommended/-/recommended-1.0.6.tgz#217b78f9601215939d566a79d202a760ae185114" - integrity sha512-0IKu9GHYF1NGTJiYgfWwqnOQSlnE9V9R7YohHNNf0/fj/SyOZWzdd06JFr0fLpg1Mqw0kGbYg8w5xdkSqLKM9g== - -"@tybys/wasm-util@^0.9.0": - version "0.9.0" - resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.9.0.tgz#3e75eb00604c8d6db470bf18c37b7d984a0e3355" - integrity sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw== - dependencies: - tslib "^2.4.0" - -"@types/aria-query@^5.0.1": - version "5.0.4" - resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-5.0.4.tgz#1a31c3d378850d2778dabb6374d036dcba4ba708" - integrity sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw== - -"@types/babel__core@^7.20.5": - version "7.20.5" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" - integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== - dependencies: - "@babel/parser" "^7.20.7" - "@babel/types" "^7.20.7" - "@types/babel__generator" "*" - "@types/babel__template" "*" - "@types/babel__traverse" "*" - -"@types/babel__generator@*": - version "7.27.0" - resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.27.0.tgz#b5819294c51179957afaec341442f9341e4108a9" - integrity sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg== - dependencies: - "@babel/types" "^7.0.0" - -"@types/babel__template@*": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" - integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== - dependencies: - "@babel/parser" "^7.1.0" - "@babel/types" "^7.0.0" - -"@types/babel__traverse@*": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.7.tgz#968cdc2366ec3da159f61166428ee40f370e56c2" - integrity sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng== - dependencies: - "@babel/types" "^7.20.7" - -"@types/cookie@^0.6.0": - version "0.6.0" - resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.6.0.tgz#eac397f28bf1d6ae0ae081363eca2f425bedf0d5" - integrity sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA== - -"@types/estree@1.0.6": - version "1.0.6" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" - integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== - -"@types/estree@1.0.7", "@types/estree@^1.0.0": - version "1.0.7" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.7.tgz#4158d3105276773d5b7695cd4834b1722e4f37a8" - integrity sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ== - -"@types/hast@^3.0.4": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@types/hast/-/hast-3.0.4.tgz#1d6b39993b82cea6ad783945b0508c25903e15aa" - integrity sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ== - dependencies: - "@types/unist" "*" - -"@types/json-schema@^7.0.15": - version "7.0.15" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" - integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== - -"@types/mdast@^3.0.0": - version "3.0.15" - resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.15.tgz#49c524a263f30ffa28b71ae282f813ed000ab9f5" - integrity sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ== - dependencies: - "@types/unist" "^2" - -"@types/minimist@^1.2.0": - version "1.2.5" - resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.5.tgz#ec10755e871497bcd83efe927e43ec46e8c0747e" - integrity sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag== - -"@types/node@^20.12.12": - version "20.12.12" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.12.tgz#7cbecdf902085cec634fdb362172dfe12b8f2050" - integrity sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw== - dependencies: - undici-types "~5.26.4" - -"@types/normalize-package-data@^2.4.0": - version "2.4.4" - resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz#56e2cc26c397c038fab0e3a917a12d5c5909e901" - integrity sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA== - -"@types/react-dom@^19.0.3": - version "19.0.3" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-19.0.3.tgz#0804dfd279a165d5a0ad8b53a5b9e65f338050a4" - integrity sha512-0Knk+HJiMP/qOZgMyNFamlIjw9OFCsyC2ZbigmEEyXXixgre6IQpm/4V+r3qH4GC1JPvRJKInw+on2rV6YZLeA== - -"@types/react@^19.0.8": - version "19.0.9" - resolved "https://registry.yarnpkg.com/@types/react/-/react-19.0.9.tgz#675255eb7d978bdaf71f9d08f6b740d41b0b7f32" - integrity sha512-FedNTYgmMwSZmD1Sru/W1gJKuiYCN/3SuBkmZkcxX+FpO5zL76B22A9YNfAKg4HQO3Neh/30AiynP6BELdU0qQ== - dependencies: - csstype "^3.0.2" - -"@types/retry@0.12.0": - version "0.12.0" - resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" - integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== - -"@types/statuses@^2.0.4": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@types/statuses/-/statuses-2.0.5.tgz#f61ab46d5352fd73c863a1ea4e1cef3b0b51ae63" - integrity sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A== - -"@types/tough-cookie@^4.0.5": - version "4.0.5" - resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.5.tgz#cb6e2a691b70cb177c6e3ae9c1d2e8b2ea8cd304" - integrity sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA== - -"@types/triple-beam@^1.3.2": - version "1.3.5" - resolved "https://registry.yarnpkg.com/@types/triple-beam/-/triple-beam-1.3.5.tgz#74fef9ffbaa198eb8b588be029f38b00299caa2c" - integrity sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw== - -"@types/unist@*": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/unist/-/unist-3.0.3.tgz#acaab0f919ce69cce629c2d4ed2eb4adc1b6c20c" - integrity sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q== - -"@types/unist@^2", "@types/unist@^2.0.0", "@types/unist@^2.0.2": - version "2.0.10" - resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.10.tgz#04ffa7f406ab628f7f7e97ca23e290cd8ab15efc" - integrity sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA== - -"@types/uuid@^10.0.0": - version "10.0.0" - resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-10.0.0.tgz#e9c07fe50da0f53dc24970cca94d619ff03f6f6d" - integrity sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ== - -"@types/uuid@^9.0.1": - version "9.0.8" - resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.8.tgz#7545ba4fc3c003d6c756f651f3bf163d8f0f29ba" - integrity sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA== - -"@typescript/vfs@^1.6.0": - version "1.6.1" - resolved "https://registry.yarnpkg.com/@typescript/vfs/-/vfs-1.6.1.tgz#fe7087d5a43715754f7ea9bf6e0b905176c9eebd" - integrity sha512-JwoxboBh7Oz1v38tPbkrZ62ZXNHAk9bJ7c9x0eI5zBfBnBYGhURdbnh7Z4smN/MV48Y5OCcZb58n972UtbazsA== - dependencies: - debug "^4.1.1" - -"@vitejs/plugin-react@^4.4.1": - version "4.4.1" - resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-4.4.1.tgz#d7d1e9c9616d7536b0953637edfee7c6cbe2fe0f" - integrity sha512-IpEm5ZmeXAP/osiBXVVP5KjFMzbWOonMs0NaQQl+xYnUAcq4oHUBsF2+p4MgKWG4YMmFYJU8A6sxRPuowllm6w== - dependencies: - "@babel/core" "^7.26.10" - "@babel/plugin-transform-react-jsx-self" "^7.25.9" - "@babel/plugin-transform-react-jsx-source" "^7.25.9" - "@types/babel__core" "^7.20.5" - react-refresh "^0.17.0" - -"@vitest/expect@3.1.3": - version "3.1.3" - resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-3.1.3.tgz#bbca175cd2f23d7de9448a215baed8f3d7abd7b7" - integrity sha512-7FTQQuuLKmN1Ig/h+h/GO+44Q1IlglPlR2es4ab7Yvfx+Uk5xsv+Ykk+MEt/M2Yn/xGmzaLKxGw2lgy2bwuYqg== - dependencies: - "@vitest/spy" "3.1.3" - "@vitest/utils" "3.1.3" - chai "^5.2.0" - tinyrainbow "^2.0.0" - -"@vitest/mocker@3.1.3": - version "3.1.3" - resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-3.1.3.tgz#121d0f2fcca20c9ccada9e2d6e761f7fc687f4ce" - integrity sha512-PJbLjonJK82uCWHjzgBJZuR7zmAOrSvKk1QBxrennDIgtH4uK0TB1PvYmc0XBCigxxtiAVPfWtAdy4lpz8SQGQ== - dependencies: - "@vitest/spy" "3.1.3" - estree-walker "^3.0.3" - magic-string "^0.30.17" - -"@vitest/pretty-format@3.1.3", "@vitest/pretty-format@^3.1.3": - version "3.1.3" - resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-3.1.3.tgz#760b9eab5f253d7d2e7dcd28ef34570f584023d4" - integrity sha512-i6FDiBeJUGLDKADw2Gb01UtUNb12yyXAqC/mmRWuYl+m/U9GS7s8us5ONmGkGpUUo7/iAYzI2ePVfOZTYvUifA== - dependencies: - tinyrainbow "^2.0.0" - -"@vitest/runner@3.1.3": - version "3.1.3" - resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-3.1.3.tgz#b268fa90fca38fab363f1107f057c0a2a141ee45" - integrity sha512-Tae+ogtlNfFei5DggOsSUvkIaSuVywujMj6HzR97AHK6XK8i3BuVyIifWAm/sE3a15lF5RH9yQIrbXYuo0IFyA== - dependencies: - "@vitest/utils" "3.1.3" - pathe "^2.0.3" - -"@vitest/snapshot@3.1.3": - version "3.1.3" - resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-3.1.3.tgz#39a8f9f8c6ba732ffde59adeacf0a549bef11e76" - integrity sha512-XVa5OPNTYUsyqG9skuUkFzAeFnEzDp8hQu7kZ0N25B1+6KjGm4hWLtURyBbsIAOekfWQ7Wuz/N/XXzgYO3deWQ== - dependencies: - "@vitest/pretty-format" "3.1.3" - magic-string "^0.30.17" - pathe "^2.0.3" - -"@vitest/spy@3.1.3": - version "3.1.3" - resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-3.1.3.tgz#ca81e2b4f0c3d6c75f35defa77c3336f39c8f605" - integrity sha512-x6w+ctOEmEXdWaa6TO4ilb7l9DxPR5bwEb6hILKuxfU1NqWT2mpJD9NJN7t3OTfxmVlOMrvtoFJGdgyzZ605lQ== - dependencies: - tinyspy "^3.0.2" - -"@vitest/utils@3.1.3": - version "3.1.3" - resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-3.1.3.tgz#4f31bdfd646cd82d30bfa730d7410cb59d529669" - integrity sha512-2Ltrpht4OmHO9+c/nmHtF09HWiyWdworqnHIwjfvDyWjuwKbdkcS9AnhsDn+8E2RM4x++foD1/tNuLPVvWG1Rg== - dependencies: - "@vitest/pretty-format" "3.1.3" - loupe "^3.1.3" - tinyrainbow "^2.0.0" - -agent-base@^7.1.0, agent-base@^7.1.2: - version "7.1.3" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.3.tgz#29435eb821bc4194633a5b89e5bc4703bafc25a1" - integrity sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw== - -anchor-markdown-header@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/anchor-markdown-header/-/anchor-markdown-header-0.6.0.tgz#908f2031281766f44ac350380ca0de77ab7065b8" - integrity sha512-v7HJMtE1X7wTpNFseRhxsY/pivP4uAJbidVhPT+yhz4i/vV1+qx371IXuV9V7bN6KjFtheLJxqaSm0Y/8neJTA== - dependencies: - emoji-regex "~10.1.0" - -ansi-escapes@^4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" - integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== - dependencies: - type-fest "^0.21.3" - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-regex@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654" - integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA== - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -ansi-styles@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" - integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== - -ansi-styles@^6.1.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" - integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -aria-query@5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.0.tgz#650c569e41ad90b51b3d7df5e5eed1c7549c103e" - integrity sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A== - dependencies: - dequal "^2.0.3" - -aria-query@^5.0.0: - version "5.3.2" - resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.2.tgz#93f81a43480e33a338f19163a3d10a50c01dcd59" - integrity sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw== - -array-buffer-byte-length@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz#1e5583ec16763540a27ae52eed99ff899223568f" - integrity sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg== - dependencies: - call-bind "^1.0.5" - is-array-buffer "^3.0.4" - -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - -arraybuffer.prototype.slice@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz#097972f4255e41bc3425e37dc3f6421cf9aefde6" - integrity sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A== - dependencies: - array-buffer-byte-length "^1.0.1" - call-bind "^1.0.5" - define-properties "^1.2.1" - es-abstract "^1.22.3" - es-errors "^1.2.1" - get-intrinsic "^1.2.3" - is-array-buffer "^3.0.4" - is-shared-array-buffer "^1.0.2" - -arrify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== - -assertion-error@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-2.0.1.tgz#f641a196b335690b1070bf00b6e7593fec190bf7" - integrity sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA== - -async@^3.2.3: - version "3.2.6" - resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce" - integrity sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA== - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== - -autoprefixer@^10.4.20: - version "10.4.21" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.21.tgz#77189468e7a8ad1d9a37fbc08efc9f480cf0a95d" - integrity sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ== - dependencies: - browserslist "^4.24.4" - caniuse-lite "^1.0.30001702" - fraction.js "^4.3.7" - normalize-range "^0.1.2" - picocolors "^1.1.1" - postcss-value-parser "^4.2.0" - -available-typed-arrays@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" - integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== - dependencies: - possible-typed-array-names "^1.0.0" - -axios@^1.6.7: - version "1.8.2" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.8.2.tgz#fabe06e241dfe83071d4edfbcaa7b1c3a40f7979" - integrity sha512-ls4GYBm5aig9vWx8AWDSGLpnpDQRtWAfrjU+EuytuODrFBkqesN2RkOQCBzrA1RQNHw1SmRMSDDDSwzNAYQ6Rg== - dependencies: - follow-redirects "^1.15.6" - form-data "^4.0.0" - proxy-from-env "^1.1.0" - -bail@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776" - integrity sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ== - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -base64-js@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== - -before-after-hook@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-3.0.2.tgz#d5665a5fa8b62294a5aa0a499f933f4a1016195d" - integrity sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A== - -brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== - dependencies: - balanced-match "^1.0.0" - -braces@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" - integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== - dependencies: - fill-range "^7.1.1" - -browserslist@^4.24.0: - version "4.24.5" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.5.tgz#aa0f5b8560fe81fde84c6dcb38f759bafba0e11b" - integrity sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw== - dependencies: - caniuse-lite "^1.0.30001716" - electron-to-chromium "^1.5.149" - node-releases "^2.0.19" - update-browserslist-db "^1.1.3" - -browserslist@^4.24.4: - version "4.25.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.25.0.tgz#986aa9c6d87916885da2b50d8eb577ac8d133b2c" - integrity sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA== - dependencies: - caniuse-lite "^1.0.30001718" - electron-to-chromium "^1.5.160" - node-releases "^2.0.19" - update-browserslist-db "^1.1.3" - -bundle-name@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/bundle-name/-/bundle-name-4.1.0.tgz#f3b96b34160d6431a19d7688135af7cfb8797889" - integrity sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q== - dependencies: - run-applescript "^7.0.0" - -cac@^6.7.14: - version "6.7.14" - resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" - integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== - -call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" - integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== - dependencies: - es-define-property "^1.0.0" - es-errors "^1.3.0" - function-bind "^1.1.2" - get-intrinsic "^1.2.4" - set-function-length "^1.2.1" - -camelcase-keys@^6.2.2: - version "6.2.2" - resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-6.2.2.tgz#5e755d6ba51aa223ec7d3d52f25778210f9dc3c0" - integrity sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg== - dependencies: - camelcase "^5.3.1" - map-obj "^4.0.0" - quick-lru "^4.0.1" - -camelcase@6: - version "6.3.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" - integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== - -camelcase@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -caniuse-lite@^1.0.30001702, caniuse-lite@^1.0.30001718: - version "1.0.30001724" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001724.tgz#312e163553dd70d2c0fb603d74810c85d8ed94a0" - integrity sha512-WqJo7p0TbHDOythNTqYujmaJTvtYRZrjpP8TCvH6Vb9CYJerJNKamKzIWOM4BkQatWj9H2lYulpdAQNBe7QhNA== - -caniuse-lite@^1.0.30001716: - version "1.0.30001718" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001718.tgz#dae13a9c80d517c30c6197515a96131c194d8f82" - integrity sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw== - -ccount@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.1.0.tgz#246687debb6014735131be8abab2d93898f8d043" - integrity sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg== - -chai@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/chai/-/chai-5.2.0.tgz#1358ee106763624114addf84ab02697e411c9c05" - integrity sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw== - dependencies: - assertion-error "^2.0.1" - check-error "^2.1.1" - deep-eql "^5.0.1" - loupe "^3.1.0" - pathval "^2.0.0" - -chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" - integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -chalk@^4.1.0, chalk@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -character-entities-legacy@^1.0.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1" - integrity sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA== - -character-entities@^1.0.0: - version "1.2.4" - resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b" - integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw== - -character-reference-invalid@^1.0.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" - integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== - -check-error@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/check-error/-/check-error-2.1.1.tgz#87eb876ae71ee388fa0471fe423f494be1d96ccc" - integrity sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw== - -chownr@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-3.0.0.tgz#9855e64ecd240a9cc4267ce8a4aa5d24a1da15e4" - integrity sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g== - -cli-width@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-4.1.0.tgz#42daac41d3c254ef38ad8ac037672130173691c5" - integrity sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ== - -cliui@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" - integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.1" - wrap-ansi "^7.0.0" - -code-block-writer@^12.0.0: - version "12.0.0" - resolved "https://registry.yarnpkg.com/code-block-writer/-/code-block-writer-12.0.0.tgz#4dd58946eb4234105aff7f0035977b2afdc2a770" - integrity sha512-q4dMFMlXtKR3XNBHyMHt/3pwYNA69EDk00lloMOaaUMKPUXBw6lpXtbu3MMVG6/uOihGnRDOlkyqsONEUj60+w== - -color-convert@^1.9.0, color-convert@^1.9.3: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - -color-name@^1.0.0, color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -color-string@^1.6.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4" - integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg== - dependencies: - color-name "^1.0.0" - simple-swizzle "^0.2.2" - -color@^3.1.3: - version "3.2.1" - resolved "https://registry.yarnpkg.com/color/-/color-3.2.1.tgz#3544dc198caf4490c3ecc9a790b54fe9ff45e164" - integrity sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA== - dependencies: - color-convert "^1.9.3" - color-string "^1.6.0" - -colors@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" - integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== - -colorspace@1.1.x: - version "1.1.4" - resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.4.tgz#8d442d1186152f60453bf8070cd66eb364e59243" - integrity sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w== - dependencies: - color "^3.1.3" - text-hex "1.0.x" - -combined-stream@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - -commander@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-11.1.0.tgz#62fdce76006a68e5c1ab3314dc92e800eb83d906" - integrity sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ== - -commander@^13.0.0: - version "13.1.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-13.1.0.tgz#776167db68c78f38dcce1f9b8d7b8b9a488abf46" - integrity sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw== - -concat-md@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/concat-md/-/concat-md-0.5.1.tgz#03c72343a5d81306aa5ae1040d6368ffbc444781" - integrity sha512-iZr6yxlwPQ5IZup2mvqgm+JI0jnu5yGkND2ra5DinBtcevDQPQiAGpf4RXOnor1UpKBUydqegDLfPY8b+FfI+Q== - dependencies: - doctoc "^2.2.1" - front-matter "^4.0.2" - globby "^11.1.0" - lodash.startcase "^4.4.0" - meow "^9.0.0" - transform-markdown-links "^2.0.0" - -console-table-printer@^2.12.1: - version "2.12.1" - resolved "https://registry.yarnpkg.com/console-table-printer/-/console-table-printer-2.12.1.tgz#4a9646537a246a6d8de57075d4fae1e08abae267" - integrity sha512-wKGOQRRvdnd89pCeH96e2Fn4wkbenSP6LMHfjfyNLMbGuHEFbMqQNuxXqd0oXG9caIOQ1FTvc5Uijp9/4jujnQ== - dependencies: - simple-wcswidth "^1.0.1" - -convert-source-map@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" - integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== - -cookie@^0.7.2: - version "0.7.2" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7" - integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w== - -copy-anything@^3.0.2: - version "3.0.5" - resolved "https://registry.yarnpkg.com/copy-anything/-/copy-anything-3.0.5.tgz#2d92dce8c498f790fa7ad16b01a1ae5a45b020a0" - integrity sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w== - dependencies: - is-what "^4.1.8" - -cross-spawn@^7.0.0: - version "7.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.5.tgz#910aac880ff5243da96b728bc6521a5f6c2f2f82" - integrity sha512-ZVJrKKYunU38/76t0RMOulHOnUcbU9GbpWKAOZ0mhjr7CX6FVrH+4FrAapSOekrgFQ3f/8gwMEuIft0aKq6Hug== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -css.escape@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb" - integrity sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg== - -cssesc@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" - integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== - -cssstyle@^4.2.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-4.3.1.tgz#68a3c9f5a70aa97d5a6ebecc9805e511fc022eb8" - integrity sha512-ZgW+Jgdd7i52AaLYCriF8Mxqft0gD/R9i9wi6RWBhs1pqdPEzPjym7rvRKi397WmQFf3SlyUsszhw+VVCbx79Q== - dependencies: - "@asamuzakjp/css-color" "^3.1.2" - rrweb-cssom "^0.8.0" - -csstype@^3.0.2: - version "3.1.3" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" - integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== - -data-urls@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-5.0.0.tgz#2f76906bce1824429ffecb6920f45a0b30f00dde" - integrity sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg== - dependencies: - whatwg-mimetype "^4.0.0" - whatwg-url "^14.0.0" - -data-view-buffer@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.1.tgz#8ea6326efec17a2e42620696e671d7d5a8bc66b2" - integrity sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA== - dependencies: - call-bind "^1.0.6" - es-errors "^1.3.0" - is-data-view "^1.0.1" - -data-view-byte-length@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz#90721ca95ff280677eb793749fce1011347669e2" - integrity sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ== - dependencies: - call-bind "^1.0.7" - es-errors "^1.3.0" - is-data-view "^1.0.1" - -data-view-byte-offset@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz#5e0bbfb4828ed2d1b9b400cd8a7d119bca0ff18a" - integrity sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA== - dependencies: - call-bind "^1.0.6" - es-errors "^1.3.0" - is-data-view "^1.0.1" - -debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.4.0: - version "4.4.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b" - integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ== - dependencies: - ms "^2.1.3" - -debug@^4.0.0, debug@^4.3.4: - version "4.3.5" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" - integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== - dependencies: - ms "2.1.2" - -decamelize-keys@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.1.tgz#04a2d523b2f18d80d0158a43b895d56dff8d19d8" - integrity sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg== - dependencies: - decamelize "^1.1.0" - map-obj "^1.0.0" - -decamelize@1.2.0, decamelize@^1.1.0, decamelize@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== - -decimal.js@^10.5.0: - version "10.5.0" - resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.5.0.tgz#0f371c7cf6c4898ce0afb09836db73cd82010f22" - integrity sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw== - -dedent@^1.5.3: - version "1.6.0" - resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.6.0.tgz#79d52d6389b1ffa67d2bcef59ba51847a9d503b2" - integrity sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA== - -deep-eql@^5.0.1: - version "5.0.2" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-5.0.2.tgz#4b756d8d770a9257300825d52a2c2cff99c3a341" - integrity sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q== - -default-browser-id@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/default-browser-id/-/default-browser-id-5.0.0.tgz#a1d98bf960c15082d8a3fa69e83150ccccc3af26" - integrity sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA== - -default-browser@^5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/default-browser/-/default-browser-5.2.1.tgz#7b7ba61204ff3e425b556869ae6d3e9d9f1712cf" - integrity sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg== - dependencies: - bundle-name "^4.1.0" - default-browser-id "^5.0.0" - -define-data-property@^1.0.1, define-data-property@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" - integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== - dependencies: - es-define-property "^1.0.0" - es-errors "^1.3.0" - gopd "^1.0.1" - -define-lazy-prop@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz#dbb19adfb746d7fc6d734a06b72f4a00d021255f" - integrity sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg== - -define-properties@^1.2.0, define-properties@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" - integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== - dependencies: - define-data-property "^1.0.1" - has-property-descriptors "^1.0.0" - object-keys "^1.1.1" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== - -dequal@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" - integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== - -detect-libc@^2.0.3, detect-libc@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.4.tgz#f04715b8ba815e53b4d8109655b6508a6865a7e8" - integrity sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA== - -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -doctoc@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/doctoc/-/doctoc-2.2.1.tgz#83f6a6bf4df97defbe027c9a82d13091a138ffe2" - integrity sha512-qNJ1gsuo7hH40vlXTVVrADm6pdg30bns/Mo7Nv1SxuXSM1bwF9b4xQ40a6EFT/L1cI+Yylbyi8MPI4G4y7XJzQ== - dependencies: - "@textlint/markdown-to-ast" "^12.1.1" - anchor-markdown-header "^0.6.0" - htmlparser2 "^7.2.0" - minimist "^1.2.6" - underscore "^1.13.2" - update-section "^0.3.3" - -dom-accessibility-api@^0.5.9: - version "0.5.16" - resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz#5a7429e6066eb3664d911e33fb0e45de8eb08453" - integrity sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg== - -dom-accessibility-api@^0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz#993e925cc1d73f2c662e7d75dd5a5445259a8fd8" - integrity sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w== - -dom-serializer@^1.0.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30" - integrity sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag== - dependencies: - domelementtype "^2.0.1" - domhandler "^4.2.0" - entities "^2.0.0" - -domelementtype@^2.0.1, domelementtype@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" - integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== - -domhandler@^4.2.0, domhandler@^4.2.2: - version "4.3.1" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c" - integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ== - dependencies: - domelementtype "^2.2.0" - -domutils@^2.8.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" - integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== - dependencies: - dom-serializer "^1.0.1" - domelementtype "^2.2.0" - domhandler "^4.2.0" - -dotenv@^16.4.7: - version "16.5.0" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.5.0.tgz#092b49f25f808f020050051d1ff258e404c78692" - integrity sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg== - -eastasianwidth@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" - integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== - -electron-to-chromium@^1.5.149: - version "1.5.155" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.155.tgz#809dd0ae9ae1db87c358e0c0c17c09a2ffc432d1" - integrity sha512-ps5KcGGmwL8VaeJlvlDlu4fORQpv3+GIcF5I3f9tUKUlJ/wsysh6HU8P5L1XWRYeXfA0oJd4PyM8ds8zTFf6Ng== - -electron-to-chromium@^1.5.160: - version "1.5.172" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.172.tgz#fe1d99028d8d6321668d0f1fed61d99ac896259c" - integrity sha512-fnKW9dGgmBfsebbYognQSv0CGGLFH1a5iV9EDYTBwmAQn+whbzHbLFlC+3XbHc8xaNtpO0etm8LOcRXs1qMRkQ== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -emoji-regex@^9.2.2: - version "9.2.2" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" - integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== - -emoji-regex@~10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.1.0.tgz#d50e383743c0f7a5945c47087295afc112e3cf66" - integrity sha512-xAEnNCT3w2Tg6MA7ly6QqYJvEoY1tm9iIjJ3yMKK9JPlWuRHAMoe5iETwQnx3M9TVbFMfsrBgWKR+IsmswwNjg== - -enabled@2.0.x: - version "2.0.0" - resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2" - integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ== - -enhanced-resolve@^5.18.1: - version "5.18.1" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz#728ab082f8b7b6836de51f1637aab5d3b9568faf" - integrity sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg== - dependencies: - graceful-fs "^4.2.4" - tapable "^2.2.0" - -entities@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" - integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== - -entities@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/entities/-/entities-3.0.1.tgz#2b887ca62585e96db3903482d336c1006c3001d4" - integrity sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q== - -entities@^4.4.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" - integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== - -entities@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-6.0.0.tgz#09c9e29cb79b0a6459a9b9db9efb418ac5bb8e51" - integrity sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw== - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0: - version "1.23.3" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0" - integrity sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A== - dependencies: - array-buffer-byte-length "^1.0.1" - arraybuffer.prototype.slice "^1.0.3" - available-typed-arrays "^1.0.7" - call-bind "^1.0.7" - data-view-buffer "^1.0.1" - data-view-byte-length "^1.0.1" - data-view-byte-offset "^1.0.0" - es-define-property "^1.0.0" - es-errors "^1.3.0" - es-object-atoms "^1.0.0" - es-set-tostringtag "^2.0.3" - es-to-primitive "^1.2.1" - function.prototype.name "^1.1.6" - get-intrinsic "^1.2.4" - get-symbol-description "^1.0.2" - globalthis "^1.0.3" - gopd "^1.0.1" - has-property-descriptors "^1.0.2" - has-proto "^1.0.3" - has-symbols "^1.0.3" - hasown "^2.0.2" - internal-slot "^1.0.7" - is-array-buffer "^3.0.4" - is-callable "^1.2.7" - is-data-view "^1.0.1" - is-negative-zero "^2.0.3" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.3" - is-string "^1.0.7" - is-typed-array "^1.1.13" - is-weakref "^1.0.2" - object-inspect "^1.13.1" - object-keys "^1.1.1" - object.assign "^4.1.5" - regexp.prototype.flags "^1.5.2" - safe-array-concat "^1.1.2" - safe-regex-test "^1.0.3" - string.prototype.trim "^1.2.9" - string.prototype.trimend "^1.0.8" - string.prototype.trimstart "^1.0.8" - typed-array-buffer "^1.0.2" - typed-array-byte-length "^1.0.1" - typed-array-byte-offset "^1.0.2" - typed-array-length "^1.0.6" - unbox-primitive "^1.0.2" - which-typed-array "^1.1.15" - -es-define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" - integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== - dependencies: - get-intrinsic "^1.2.4" - -es-errors@^1.2.1, es-errors@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" - integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== - -es-module-lexer@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.7.0.tgz#9159601561880a85f2734560a9099b2c31e5372a" - integrity sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA== - -es-object-atoms@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.0.0.tgz#ddb55cd47ac2e240701260bc2a8e31ecb643d941" - integrity sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw== - dependencies: - es-errors "^1.3.0" - -es-set-tostringtag@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz#8bb60f0a440c2e4281962428438d58545af39777" - integrity sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ== - dependencies: - get-intrinsic "^1.2.4" - has-tostringtag "^1.0.2" - hasown "^2.0.1" - -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -esbuild-plugin-tailwindcss@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/esbuild-plugin-tailwindcss/-/esbuild-plugin-tailwindcss-2.0.1.tgz#74ca9c8bcd183e9596db077423d7566c2ce5ba62" - integrity sha512-62CPYzyfcRE7OowGmWGKs9sz43QhCa/dZ5h6ruZhDg65B5Zsn++4EA4NKIwEMbAio9JV8+FJZNXzejNX/RjSkg== - dependencies: - "@tailwindcss/postcss" "^4.0.5" - autoprefixer "^10.4.20" - postcss "^8.5.1" - postcss-modules "^6.0.1" - -esbuild@^0.25.0: - version "0.25.4" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.4.tgz#bb9a16334d4ef2c33c7301a924b8b863351a0854" - integrity sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q== - optionalDependencies: - "@esbuild/aix-ppc64" "0.25.4" - "@esbuild/android-arm" "0.25.4" - "@esbuild/android-arm64" "0.25.4" - "@esbuild/android-x64" "0.25.4" - "@esbuild/darwin-arm64" "0.25.4" - "@esbuild/darwin-x64" "0.25.4" - "@esbuild/freebsd-arm64" "0.25.4" - "@esbuild/freebsd-x64" "0.25.4" - "@esbuild/linux-arm" "0.25.4" - "@esbuild/linux-arm64" "0.25.4" - "@esbuild/linux-ia32" "0.25.4" - "@esbuild/linux-loong64" "0.25.4" - "@esbuild/linux-mips64el" "0.25.4" - "@esbuild/linux-ppc64" "0.25.4" - "@esbuild/linux-riscv64" "0.25.4" - "@esbuild/linux-s390x" "0.25.4" - "@esbuild/linux-x64" "0.25.4" - "@esbuild/netbsd-arm64" "0.25.4" - "@esbuild/netbsd-x64" "0.25.4" - "@esbuild/openbsd-arm64" "0.25.4" - "@esbuild/openbsd-x64" "0.25.4" - "@esbuild/sunos-x64" "0.25.4" - "@esbuild/win32-arm64" "0.25.4" - "@esbuild/win32-ia32" "0.25.4" - "@esbuild/win32-x64" "0.25.4" - -esbuild@~0.25.0: - version "0.25.5" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.5.tgz#71075054993fdfae76c66586f9b9c1f8d7edd430" - integrity sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ== - optionalDependencies: - "@esbuild/aix-ppc64" "0.25.5" - "@esbuild/android-arm" "0.25.5" - "@esbuild/android-arm64" "0.25.5" - "@esbuild/android-x64" "0.25.5" - "@esbuild/darwin-arm64" "0.25.5" - "@esbuild/darwin-x64" "0.25.5" - "@esbuild/freebsd-arm64" "0.25.5" - "@esbuild/freebsd-x64" "0.25.5" - "@esbuild/linux-arm" "0.25.5" - "@esbuild/linux-arm64" "0.25.5" - "@esbuild/linux-ia32" "0.25.5" - "@esbuild/linux-loong64" "0.25.5" - "@esbuild/linux-mips64el" "0.25.5" - "@esbuild/linux-ppc64" "0.25.5" - "@esbuild/linux-riscv64" "0.25.5" - "@esbuild/linux-s390x" "0.25.5" - "@esbuild/linux-x64" "0.25.5" - "@esbuild/netbsd-arm64" "0.25.5" - "@esbuild/netbsd-x64" "0.25.5" - "@esbuild/openbsd-arm64" "0.25.5" - "@esbuild/openbsd-x64" "0.25.5" - "@esbuild/sunos-x64" "0.25.5" - "@esbuild/win32-arm64" "0.25.5" - "@esbuild/win32-ia32" "0.25.5" - "@esbuild/win32-x64" "0.25.5" - -escalade@^3.1.1, escalade@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" - integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -estree-walker@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-3.0.3.tgz#67c3e549ec402a487b4fc193d1953a524752340d" - integrity sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g== - dependencies: - "@types/estree" "^1.0.0" - -eventemitter3@^4.0.4: - version "4.0.7" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" - integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== - -exit-hook@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-4.0.0.tgz#c1e16ebd03d3166f837b1502dac755bb5c460d58" - integrity sha512-Fqs7ChZm72y40wKjOFXBKg7nJZvQJmewP5/7LtePDdnah/+FH9Hp5sgMujSCMPXlxOAW2//1jrW9pnsY7o20vQ== - -expect-type@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.2.1.tgz#af76d8b357cf5fa76c41c09dafb79c549e75f71f" - integrity sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw== - -extend@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -fast-glob@^3.2.9, fast-glob@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" - integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - -fastq@^1.6.0: - version "1.17.1" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" - integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== - dependencies: - reusify "^1.0.4" - -fault@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/fault/-/fault-1.0.4.tgz#eafcfc0a6d214fc94601e170df29954a4f842f13" - integrity sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA== - dependencies: - format "^0.2.0" - -fdir@^6.4.4: - version "6.4.4" - resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.4.4.tgz#1cfcf86f875a883e19a8fab53622cfe992e8d2f9" - integrity sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg== - -fecha@^4.2.0: - version "4.2.3" - resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd" - integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw== - -fill-range@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" - integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== - dependencies: - to-regex-range "^5.0.1" - -find-up@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -fn.name@1.x.x: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" - integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== - -follow-redirects@^1.15.6: - version "1.15.9" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" - integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== - -for-each@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" - integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== - dependencies: - is-callable "^1.1.3" - -foreground-child@^3.1.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.0.tgz#0ac8644c06e431439f8561db8ecf29a7b5519c77" - integrity sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg== - dependencies: - cross-spawn "^7.0.0" - signal-exit "^4.0.1" - -form-data@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.1.tgz#ba1076daaaa5bfd7e99c1a6cb02aa0a5cff90d48" - integrity sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - -format@^0.2.0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" - integrity sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww== - -fraction.js@^4.3.7: - version "4.3.7" - resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7" - integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew== - -front-matter@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/front-matter/-/front-matter-4.0.2.tgz#b14e54dc745cfd7293484f3210d15ea4edd7f4d5" - integrity sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg== - dependencies: - js-yaml "^3.13.1" - -fsevents@~2.3.2, fsevents@~2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== - -function-bind@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== - -function.prototype.name@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd" - integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - functions-have-names "^1.2.3" - -functions-have-names@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" - integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== - -generic-names@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/generic-names/-/generic-names-4.0.0.tgz#0bd8a2fd23fe8ea16cbd0a279acd69c06933d9a3" - integrity sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A== - dependencies: - loader-utils "^3.2.0" - -gensync@^1.0.0-beta.2: - version "1.0.0-beta.2" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" - integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== - -get-caller-file@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" - integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== - dependencies: - es-errors "^1.3.0" - function-bind "^1.1.2" - has-proto "^1.0.1" - has-symbols "^1.0.3" - hasown "^2.0.0" - -get-symbol-description@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.2.tgz#533744d5aa20aca4e079c8e5daf7fd44202821f5" - integrity sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg== - dependencies: - call-bind "^1.0.5" - es-errors "^1.3.0" - get-intrinsic "^1.2.4" - -get-tsconfig@^4.7.5: - version "4.10.1" - resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.10.1.tgz#d34c1c01f47d65a606c37aa7a177bc3e56ab4b2e" - integrity sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ== - dependencies: - resolve-pkg-maps "^1.0.0" - -glob-parent@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob@^10.3.10, glob@^10.3.7: - version "10.4.5" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" - integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== - dependencies: - foreground-child "^3.1.0" - jackspeak "^3.1.2" - minimatch "^9.0.4" - minipass "^7.1.2" - package-json-from-dist "^1.0.0" - path-scurry "^1.11.1" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globalthis@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" - integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ== - dependencies: - define-properties "^1.2.1" - gopd "^1.0.1" - -globby@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" - integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.2.9" - ignore "^5.2.0" - merge2 "^1.4.1" - slash "^3.0.0" - -gopd@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" - integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== - dependencies: - get-intrinsic "^1.1.3" - -graceful-fs@^4.2.4: - version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" - integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== - -graphql@^16.8.1: - version "16.11.0" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.11.0.tgz#96d17f66370678027fdf59b2d4c20b4efaa8a633" - integrity sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw== - -hard-rejection@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" - integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA== - -has-bigints@^1.0.1, has-bigints@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" - integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" - integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== - dependencies: - es-define-property "^1.0.0" - -has-proto@^1.0.1, has-proto@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" - integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== - -has-symbols@^1.0.2, has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - -has-tostringtag@^1.0.0, has-tostringtag@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" - integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== - dependencies: - has-symbols "^1.0.3" - -hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" - integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== - dependencies: - function-bind "^1.1.2" - -headers-polyfill@^4.0.2: - version "4.0.3" - resolved "https://registry.yarnpkg.com/headers-polyfill/-/headers-polyfill-4.0.3.tgz#922a0155de30ecc1f785bcf04be77844ca95ad07" - integrity sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ== - -hono@^4.5.4, hono@^4.8.2: - version "4.8.2" - resolved "https://registry.yarnpkg.com/hono/-/hono-4.8.2.tgz#806ea770de3d799b7ff17dc9a17c430bf338ed99" - integrity sha512-hM+1RIn9PK1I6SiTNS6/y7O1mvg88awYLFEuEtoiMtRyT3SD2iu9pSFgbBXT3b1Ua4IwzvSTLvwO0SEhDxCi4w== - -hosted-git-info@^2.1.4: - version "2.8.9" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" - integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== - -hosted-git-info@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz#827b82867e9ff1c8d0c4d9d53880397d2c86d224" - integrity sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA== - dependencies: - lru-cache "^6.0.0" - -html-encoding-sniffer@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz#696df529a7cfd82446369dc5193e590a3735b448" - integrity sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ== - dependencies: - whatwg-encoding "^3.1.1" - -htmlparser2@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-7.2.0.tgz#8817cdea38bbc324392a90b1990908e81a65f5a5" - integrity sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog== - dependencies: - domelementtype "^2.0.1" - domhandler "^4.2.2" - domutils "^2.8.0" - entities "^3.0.1" - -http-proxy-agent@^7.0.2: - version "7.0.2" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" - integrity sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig== - dependencies: - agent-base "^7.1.0" - debug "^4.3.4" - -https-proxy-agent@^7.0.6: - version "7.0.6" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz#da8dfeac7da130b05c2ba4b59c9b6cd66611a6b9" - integrity sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw== - dependencies: - agent-base "^7.1.2" - debug "4" - -iconv-lite@0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" - integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== - dependencies: - safer-buffer ">= 2.1.2 < 3.0.0" - -icss-utils@^5.0.0, icss-utils@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" - integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== - -ignore@^5.2.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" - integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== - -indent-string@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" - integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== - -inherits@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -internal-slot@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" - integrity sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g== - dependencies: - es-errors "^1.3.0" - hasown "^2.0.0" - side-channel "^1.0.4" - -is-alphabetical@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d" - integrity sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg== - -is-alphanumerical@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz#7eb9a2431f855f6b1ef1a78e326df515696c4dbf" - integrity sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A== - dependencies: - is-alphabetical "^1.0.0" - is-decimal "^1.0.0" - -is-array-buffer@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98" - integrity sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.2.1" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== - -is-arrayish@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" - integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== - -is-bigint@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" - integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== - dependencies: - has-bigints "^1.0.1" - -is-boolean-object@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" - integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-buffer@^2.0.0: - version "2.0.5" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" - integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== - -is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" - integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== - -is-core-module@^2.13.0, is-core-module@^2.5.0: - version "2.14.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.14.0.tgz#43b8ef9f46a6a08888db67b1ffd4ec9e3dfd59d1" - integrity sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A== - dependencies: - hasown "^2.0.2" - -is-data-view@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.1.tgz#4b4d3a511b70f3dc26d42c03ca9ca515d847759f" - integrity sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w== - dependencies: - is-typed-array "^1.1.13" - -is-date-object@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== - dependencies: - has-tostringtag "^1.0.0" - -is-decimal@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" - integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw== - -is-docker@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-3.0.0.tgz#90093aa3106277d8a77a5910dbae71747e15a200" - integrity sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ== - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-glob@^4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-hexadecimal@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" - integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw== - -is-inside-container@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-inside-container/-/is-inside-container-1.0.0.tgz#e81fba699662eb31dbdaf26766a61d4814717ea4" - integrity sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA== - dependencies: - is-docker "^3.0.0" - -is-negative-zero@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747" - integrity sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw== - -is-node-process@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/is-node-process/-/is-node-process-1.2.0.tgz#ea02a1b90ddb3934a19aea414e88edef7e11d134" - integrity sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw== - -is-number-object@^1.0.4: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" - integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== - dependencies: - has-tostringtag "^1.0.0" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-plain-obj@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== - -is-plain-obj@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" - integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== - -is-potential-custom-element-name@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" - integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== - -is-regex@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-shared-array-buffer@^1.0.2, is-shared-array-buffer@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz#1237f1cba059cdb62431d378dcc37d9680181688" - integrity sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg== - dependencies: - call-bind "^1.0.7" - -is-stream@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== - -is-string@^1.0.5, is-string@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" - integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== - dependencies: - has-tostringtag "^1.0.0" - -is-symbol@^1.0.2, is-symbol@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" - integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== - dependencies: - has-symbols "^1.0.2" - -is-typed-array@^1.1.13: - version "1.1.13" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" - integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== - dependencies: - which-typed-array "^1.1.14" - -is-weakref@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" - integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== - dependencies: - call-bind "^1.0.2" - -is-what@^4.1.8: - version "4.1.16" - resolved "https://registry.yarnpkg.com/is-what/-/is-what-4.1.16.tgz#1ad860a19da8b4895ad5495da3182ce2acdd7a6f" - integrity sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A== - -is-wsl@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-3.1.0.tgz#e1c657e39c10090afcbedec61720f6b924c3cbd2" - integrity sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw== - dependencies: - is-inside-container "^1.0.0" - -isarray@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" - integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -jackspeak@^3.1.2: - version "3.4.3" - resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" - integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== - dependencies: - "@isaacs/cliui" "^8.0.2" - optionalDependencies: - "@pkgjs/parseargs" "^0.11.0" - -jiti@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/jiti/-/jiti-2.4.2.tgz#d19b7732ebb6116b06e2038da74a55366faef560" - integrity sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A== - -js-tiktoken@^1.0.12: - version "1.0.18" - resolved "https://registry.yarnpkg.com/js-tiktoken/-/js-tiktoken-1.0.18.tgz#aaf68dda155bc693e6f0a572b9a359d569cb53df" - integrity sha512-hFYx4xYf6URgcttcGvGuOBJhTxPYZ2R5eIesqCaNRJmYH8sNmsfTeWg4yu//7u1VD/qIUkgKJTpGom9oHXmB4g== - dependencies: - base64-js "^1.5.1" - -js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^3.13.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -jsdom@^26.1.0: - version "26.1.0" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-26.1.0.tgz#ab5f1c1cafc04bd878725490974ea5e8bf0c72b3" - integrity sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg== - dependencies: - cssstyle "^4.2.1" - data-urls "^5.0.0" - decimal.js "^10.5.0" - html-encoding-sniffer "^4.0.0" - http-proxy-agent "^7.0.2" - https-proxy-agent "^7.0.6" - is-potential-custom-element-name "^1.0.1" - nwsapi "^2.2.16" - parse5 "^7.2.1" - rrweb-cssom "^0.8.0" - saxes "^6.0.0" - symbol-tree "^3.2.4" - tough-cookie "^5.1.1" - w3c-xmlserializer "^5.0.0" - webidl-conversions "^7.0.0" - whatwg-encoding "^3.1.1" - whatwg-mimetype "^4.0.0" - whatwg-url "^14.1.1" - ws "^8.18.0" - xml-name-validator "^5.0.0" - -jsesc@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" - integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== - -json-parse-even-better-errors@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - -json5@^2.2.3: - version "2.2.3" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" - integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== - -kind-of@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" - integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== - -kuler@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3" - integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A== - -langsmith@^0.3.33: - version "0.3.33" - resolved "https://registry.yarnpkg.com/langsmith/-/langsmith-0.3.33.tgz#f6c56b338cd6a9aa139dbbafcf4b037320eb3041" - integrity sha512-imNIaBL6+ElE5eMzNHYwFxo6W/6rHlqcaUjCYoIeGdCYWlARxE3CTGKul5DJnaUgGP2CTLFeNXyvRx5HWC/4KQ== - dependencies: - "@types/uuid" "^10.0.0" - chalk "^4.1.2" - console-table-printer "^2.12.1" - p-queue "^6.6.2" - p-retry "4" - semver "^7.6.3" - uuid "^10.0.0" - -lightningcss-darwin-arm64@1.30.1: - version "1.30.1" - resolved "https://registry.yarnpkg.com/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz#3d47ce5e221b9567c703950edf2529ca4a3700ae" - integrity sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ== - -lightningcss-darwin-x64@1.30.1: - version "1.30.1" - resolved "https://registry.yarnpkg.com/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz#e81105d3fd6330860c15fe860f64d39cff5fbd22" - integrity sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA== - -lightningcss-freebsd-x64@1.30.1: - version "1.30.1" - resolved "https://registry.yarnpkg.com/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz#a0e732031083ff9d625c5db021d09eb085af8be4" - integrity sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig== - -lightningcss-linux-arm-gnueabihf@1.30.1: - version "1.30.1" - resolved "https://registry.yarnpkg.com/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz#1f5ecca6095528ddb649f9304ba2560c72474908" - integrity sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q== - -lightningcss-linux-arm64-gnu@1.30.1: - version "1.30.1" - resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz#eee7799726103bffff1e88993df726f6911ec009" - integrity sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw== - -lightningcss-linux-arm64-musl@1.30.1: - version "1.30.1" - resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz#f2e4b53f42892feeef8f620cbb889f7c064a7dfe" - integrity sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ== - -lightningcss-linux-x64-gnu@1.30.1: - version "1.30.1" - resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz#2fc7096224bc000ebb97eea94aea248c5b0eb157" - integrity sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw== - -lightningcss-linux-x64-musl@1.30.1: - version "1.30.1" - resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz#66dca2b159fd819ea832c44895d07e5b31d75f26" - integrity sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ== - -lightningcss-win32-arm64-msvc@1.30.1: - version "1.30.1" - resolved "https://registry.yarnpkg.com/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz#7d8110a19d7c2d22bfdf2f2bb8be68e7d1b69039" - integrity sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA== - -lightningcss-win32-x64-msvc@1.30.1: - version "1.30.1" - resolved "https://registry.yarnpkg.com/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz#fd7dd008ea98494b85d24b4bea016793f2e0e352" - integrity sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg== - -lightningcss@1.30.1: - version "1.30.1" - resolved "https://registry.yarnpkg.com/lightningcss/-/lightningcss-1.30.1.tgz#78e979c2d595bfcb90d2a8c0eb632fe6c5bfed5d" - integrity sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg== - dependencies: - detect-libc "^2.0.3" - optionalDependencies: - lightningcss-darwin-arm64 "1.30.1" - lightningcss-darwin-x64 "1.30.1" - lightningcss-freebsd-x64 "1.30.1" - lightningcss-linux-arm-gnueabihf "1.30.1" - lightningcss-linux-arm64-gnu "1.30.1" - lightningcss-linux-arm64-musl "1.30.1" - lightningcss-linux-x64-gnu "1.30.1" - lightningcss-linux-x64-musl "1.30.1" - lightningcss-win32-arm64-msvc "1.30.1" - lightningcss-win32-x64-msvc "1.30.1" - -lines-and-columns@^1.1.6: - version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== - -linkify-it@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-5.0.0.tgz#9ef238bfa6dc70bd8e7f9572b52d369af569b421" - integrity sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ== - dependencies: - uc.micro "^2.0.0" - -loader-utils@^3.2.0: - version "3.3.1" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.3.1.tgz#735b9a19fd63648ca7adbd31c2327dfe281304e5" - integrity sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg== - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -lodash.camelcase@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" - integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== - -lodash.startcase@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.startcase/-/lodash.startcase-4.4.0.tgz#9436e34ed26093ed7ffae1936144350915d9add8" - integrity sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg== - -lodash@^4.17.21: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -logform@^2.2.0, logform@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/logform/-/logform-2.7.0.tgz#cfca97528ef290f2e125a08396805002b2d060d1" - integrity sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ== - dependencies: - "@colors/colors" "1.6.0" - "@types/triple-beam" "^1.3.2" - fecha "^4.2.0" - ms "^2.1.1" - safe-stable-stringify "^2.3.1" - triple-beam "^1.3.0" - -longest-streak@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.4.tgz#b8599957da5b5dab64dee3fe316fa774597d90e4" - integrity sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg== - -loupe@^3.1.0, loupe@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.1.3.tgz#042a8f7986d77f3d0f98ef7990a2b2fef18b0fd2" - integrity sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug== - -lru-cache@^10.2.0, lru-cache@^10.4.3: - version "10.4.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" - integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== - -lru-cache@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== - dependencies: - yallist "^3.0.2" - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -lunr@^2.3.9: - version "2.3.9" - resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" - integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow== - -lz-string@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941" - integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ== - -magic-string@^0.30.17: - version "0.30.17" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.17.tgz#450a449673d2460e5bbcfba9a61916a1714c7453" - integrity sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA== - dependencies: - "@jridgewell/sourcemap-codec" "^1.5.0" - -map-obj@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" - integrity sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg== - -map-obj@^4.0.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a" - integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ== - -markdown-it@^14.1.0: - version "14.1.0" - resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-14.1.0.tgz#3c3c5992883c633db4714ccb4d7b5935d98b7d45" - integrity sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg== - dependencies: - argparse "^2.0.1" - entities "^4.4.0" - linkify-it "^5.0.0" - mdurl "^2.0.0" - punycode.js "^2.3.1" - uc.micro "^2.1.0" - -markdown-table@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-2.0.0.tgz#194a90ced26d31fe753d8b9434430214c011865b" - integrity sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A== - dependencies: - repeat-string "^1.0.0" - -mdast-util-find-and-replace@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/mdast-util-find-and-replace/-/mdast-util-find-and-replace-1.1.1.tgz#b7db1e873f96f66588c321f1363069abf607d1b5" - integrity sha512-9cKl33Y21lyckGzpSmEQnIDjEfeeWelN5s1kUW1LwdB0Fkuq2u+4GdqcGEygYxJE8GVqCl0741bYXHgamfWAZA== - dependencies: - escape-string-regexp "^4.0.0" - unist-util-is "^4.0.0" - unist-util-visit-parents "^3.0.0" - -mdast-util-footnote@^0.1.0: - version "0.1.7" - resolved "https://registry.yarnpkg.com/mdast-util-footnote/-/mdast-util-footnote-0.1.7.tgz#4b226caeab4613a3362c144c94af0fdd6f7e0ef0" - integrity sha512-QxNdO8qSxqbO2e3m09KwDKfWiLgqyCurdWTQ198NpbZ2hxntdc+VKS4fDJCmNWbAroUdYnSthu+XbZ8ovh8C3w== - dependencies: - mdast-util-to-markdown "^0.6.0" - micromark "~2.11.0" - -mdast-util-from-markdown@^0.8.0: - version "0.8.5" - resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.5.tgz#d1ef2ca42bc377ecb0463a987910dae89bd9a28c" - integrity sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ== - dependencies: - "@types/mdast" "^3.0.0" - mdast-util-to-string "^2.0.0" - micromark "~2.11.0" - parse-entities "^2.0.0" - unist-util-stringify-position "^2.0.0" - -mdast-util-frontmatter@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/mdast-util-frontmatter/-/mdast-util-frontmatter-0.2.0.tgz#8bd5cd55e236c03e204a036f7372ebe9e6748240" - integrity sha512-FHKL4w4S5fdt1KjJCwB0178WJ0evnyyQr5kXTM3wrOVpytD0hrkvd+AOOjU9Td8onOejCkmZ+HQRT3CZ3coHHQ== - dependencies: - micromark-extension-frontmatter "^0.2.0" - -mdast-util-gfm-autolink-literal@^0.1.0, mdast-util-gfm-autolink-literal@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-0.1.3.tgz#9c4ff399c5ddd2ece40bd3b13e5447d84e385fb7" - integrity sha512-GjmLjWrXg1wqMIO9+ZsRik/s7PLwTaeCHVB7vRxUwLntZc8mzmTsLVr6HW1yLokcnhfURsn5zmSVdi3/xWWu1A== - dependencies: - ccount "^1.0.0" - mdast-util-find-and-replace "^1.1.0" - micromark "^2.11.3" - -mdast-util-gfm-strikethrough@^0.2.0: - version "0.2.3" - resolved "https://registry.yarnpkg.com/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-0.2.3.tgz#45eea337b7fff0755a291844fbea79996c322890" - integrity sha512-5OQLXpt6qdbttcDG/UxYY7Yjj3e8P7X16LzvpX8pIQPYJ/C2Z1qFGMmcw+1PZMUM3Z8wt8NRfYTvCni93mgsgA== - dependencies: - mdast-util-to-markdown "^0.6.0" - -mdast-util-gfm-table@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/mdast-util-gfm-table/-/mdast-util-gfm-table-0.1.6.tgz#af05aeadc8e5ee004eeddfb324b2ad8c029b6ecf" - integrity sha512-j4yDxQ66AJSBwGkbpFEp9uG/LS1tZV3P33fN1gkyRB2LoRL+RR3f76m0HPHaby6F4Z5xr9Fv1URmATlRRUIpRQ== - dependencies: - markdown-table "^2.0.0" - mdast-util-to-markdown "~0.6.0" - -mdast-util-gfm-task-list-item@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-0.1.6.tgz#70c885e6b9f543ddd7e6b41f9703ee55b084af10" - integrity sha512-/d51FFIfPsSmCIRNp7E6pozM9z1GYPIkSy1urQ8s/o4TC22BZ7DqfHFWiqBD23bc7J3vV1Fc9O4QIHBlfuit8A== - dependencies: - mdast-util-to-markdown "~0.6.0" - -mdast-util-gfm@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/mdast-util-gfm/-/mdast-util-gfm-0.1.2.tgz#8ecddafe57d266540f6881f5c57ff19725bd351c" - integrity sha512-NNkhDx/qYcuOWB7xHUGWZYVXvjPFFd6afg6/e2g+SV4r9q5XUcCbV4Wfa3DLYIiD+xAEZc6K4MGaE/m0KDcPwQ== - dependencies: - mdast-util-gfm-autolink-literal "^0.1.0" - mdast-util-gfm-strikethrough "^0.2.0" - mdast-util-gfm-table "^0.1.0" - mdast-util-gfm-task-list-item "^0.1.0" - mdast-util-to-markdown "^0.6.1" - -mdast-util-to-markdown@^0.6.0, mdast-util-to-markdown@^0.6.1, mdast-util-to-markdown@~0.6.0: - version "0.6.5" - resolved "https://registry.yarnpkg.com/mdast-util-to-markdown/-/mdast-util-to-markdown-0.6.5.tgz#b33f67ca820d69e6cc527a93d4039249b504bebe" - integrity sha512-XeV9sDE7ZlOQvs45C9UKMtfTcctcaj/pGwH8YLbMHoMOXNNCn2LsqVQOqrF1+/NU8lKDAqozme9SCXWyo9oAcQ== - dependencies: - "@types/unist" "^2.0.0" - longest-streak "^2.0.0" - mdast-util-to-string "^2.0.0" - parse-entities "^2.0.0" - repeat-string "^1.0.0" - zwitch "^1.0.0" - -mdast-util-to-string@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz#b8cfe6a713e1091cb5b728fc48885a4767f8b97b" - integrity sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w== - -mdurl@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-2.0.0.tgz#80676ec0433025dd3e17ee983d0fe8de5a2237e0" - integrity sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w== - -meow@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/meow/-/meow-9.0.0.tgz#cd9510bc5cac9dee7d03c73ee1f9ad959f4ea364" - integrity sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ== - dependencies: - "@types/minimist" "^1.2.0" - camelcase-keys "^6.2.2" - decamelize "^1.2.0" - decamelize-keys "^1.1.0" - hard-rejection "^2.1.0" - minimist-options "4.1.0" - normalize-package-data "^3.0.0" - read-pkg-up "^7.0.1" - redent "^3.0.0" - trim-newlines "^3.0.0" - type-fest "^0.18.0" - yargs-parser "^20.2.3" - -merge2@^1.3.0, merge2@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -micromark-extension-footnote@^0.3.0: - version "0.3.2" - resolved "https://registry.yarnpkg.com/micromark-extension-footnote/-/micromark-extension-footnote-0.3.2.tgz#129b74ef4920ce96719b2c06102ee7abb2b88a20" - integrity sha512-gr/BeIxbIWQoUm02cIfK7mdMZ/fbroRpLsck4kvFtjbzP4yi+OPVbnukTc/zy0i7spC2xYE/dbX1Sur8BEDJsQ== - dependencies: - micromark "~2.11.0" - -micromark-extension-frontmatter@^0.2.0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/micromark-extension-frontmatter/-/micromark-extension-frontmatter-0.2.2.tgz#61b8e92e9213e1d3c13f5a59e7862f5ca98dfa53" - integrity sha512-q6nPLFCMTLtfsctAuS0Xh4vaolxSFUWUWR6PZSrXXiRy+SANGllpcqdXFv2z07l0Xz/6Hl40hK0ffNCJPH2n1A== - dependencies: - fault "^1.0.0" - -micromark-extension-gfm-autolink-literal@~0.5.0: - version "0.5.7" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-0.5.7.tgz#53866c1f0c7ef940ae7ca1f72c6faef8fed9f204" - integrity sha512-ePiDGH0/lhcngCe8FtH4ARFoxKTUelMp4L7Gg2pujYD5CSMb9PbblnyL+AAMud/SNMyusbS2XDSiPIRcQoNFAw== - dependencies: - micromark "~2.11.3" - -micromark-extension-gfm-strikethrough@~0.6.5: - version "0.6.5" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-0.6.5.tgz#96cb83356ff87bf31670eefb7ad7bba73e6514d1" - integrity sha512-PpOKlgokpQRwUesRwWEp+fHjGGkZEejj83k9gU5iXCbDG+XBA92BqnRKYJdfqfkrRcZRgGuPuXb7DaK/DmxOhw== - dependencies: - micromark "~2.11.0" - -micromark-extension-gfm-table@~0.4.0: - version "0.4.3" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-table/-/micromark-extension-gfm-table-0.4.3.tgz#4d49f1ce0ca84996c853880b9446698947f1802b" - integrity sha512-hVGvESPq0fk6ALWtomcwmgLvH8ZSVpcPjzi0AjPclB9FsVRgMtGZkUcpE0zgjOCFAznKepF4z3hX8z6e3HODdA== - dependencies: - micromark "~2.11.0" - -micromark-extension-gfm-tagfilter@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-0.3.0.tgz#d9f26a65adee984c9ccdd7e182220493562841ad" - integrity sha512-9GU0xBatryXifL//FJH+tAZ6i240xQuFrSL7mYi8f4oZSbc+NvXjkrHemeYP0+L4ZUT+Ptz3b95zhUZnMtoi/Q== - -micromark-extension-gfm-task-list-item@~0.3.0: - version "0.3.3" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-0.3.3.tgz#d90c755f2533ed55a718129cee11257f136283b8" - integrity sha512-0zvM5iSLKrc/NQl84pZSjGo66aTGd57C1idmlWmE87lkMcXrTxg1uXa/nXomxJytoje9trP0NDLvw4bZ/Z/XCQ== - dependencies: - micromark "~2.11.0" - -micromark-extension-gfm@^0.3.0: - version "0.3.3" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm/-/micromark-extension-gfm-0.3.3.tgz#36d1a4c089ca8bdfd978c9bd2bf1a0cb24e2acfe" - integrity sha512-oVN4zv5/tAIA+l3GbMi7lWeYpJ14oQyJ3uEim20ktYFAcfX1x3LNlFGGlmrZHt7u9YlKExmyJdDGaTt6cMSR/A== - dependencies: - micromark "~2.11.0" - micromark-extension-gfm-autolink-literal "~0.5.0" - micromark-extension-gfm-strikethrough "~0.6.5" - micromark-extension-gfm-table "~0.4.0" - micromark-extension-gfm-tagfilter "~0.3.0" - micromark-extension-gfm-task-list-item "~0.3.0" - -micromark@^2.11.3, micromark@~2.11.0, micromark@~2.11.3: - version "2.11.4" - resolved "https://registry.yarnpkg.com/micromark/-/micromark-2.11.4.tgz#d13436138eea826383e822449c9a5c50ee44665a" - integrity sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA== - dependencies: - debug "^4.0.0" - parse-entities "^2.0.0" - -micromatch@^4.0.4: - version "4.0.8" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" - integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== - dependencies: - braces "^3.0.3" - picomatch "^2.3.1" - -mime-db@1.52.0: - version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== - -mime-types@^2.1.12: - version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== - dependencies: - mime-db "1.52.0" - -min-indent@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" - integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== - -minimatch@^9.0.3, minimatch@^9.0.5: - version "9.0.5" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" - integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== - dependencies: - brace-expansion "^2.0.1" - -minimatch@^9.0.4: - version "9.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51" - integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw== - dependencies: - brace-expansion "^2.0.1" - -minimist-options@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" - integrity sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A== - dependencies: - arrify "^1.0.1" - is-plain-obj "^1.1.0" - kind-of "^6.0.3" - -minimist@^1.2.6: - version "1.2.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" - integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== - -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.4, minipass@^7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" - integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== - -minizlib@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-3.0.2.tgz#f33d638eb279f664439aa38dc5f91607468cb574" - integrity sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA== - dependencies: - minipass "^7.1.2" - -mkdirp@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50" - integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@^2.1.1, ms@^2.1.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -msw@^2.8.2: - version "2.8.2" - resolved "https://registry.yarnpkg.com/msw/-/msw-2.8.2.tgz#a35545275403da472f4ed2152cd3c77000db544c" - integrity sha512-ugu8RBgUj6//RD0utqDDPdS+QIs36BKYkDAM6u59hcMVtFM4PM0vW4l3G1R+1uCWP2EWFUG8reT/gPXVEtx7/w== - dependencies: - "@bundled-es-modules/cookie" "^2.0.1" - "@bundled-es-modules/statuses" "^1.0.1" - "@bundled-es-modules/tough-cookie" "^0.1.6" - "@inquirer/confirm" "^5.0.0" - "@mswjs/interceptors" "^0.37.0" - "@open-draft/deferred-promise" "^2.2.0" - "@open-draft/until" "^2.1.0" - "@types/cookie" "^0.6.0" - "@types/statuses" "^2.0.4" - graphql "^16.8.1" - headers-polyfill "^4.0.2" - is-node-process "^1.2.0" - outvariant "^1.4.3" - path-to-regexp "^6.3.0" - picocolors "^1.1.1" - strict-event-emitter "^0.5.1" - type-fest "^4.26.1" - yargs "^17.7.2" - -mustache@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/mustache/-/mustache-4.2.0.tgz#e5892324d60a12ec9c2a73359edca52972bf6f64" - integrity sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ== - -mute-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-2.0.0.tgz#a5446fc0c512b71c83c44d908d5c7b7b4c493b2b" - integrity sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA== - -nanoid@^3.3.11, nanoid@^3.3.8: - version "3.3.11" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" - integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== - -node-releases@^2.0.19: - version "2.0.19" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314" - integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw== - -normalize-package-data@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" - integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== - dependencies: - hosted-git-info "^2.1.4" - resolve "^1.10.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - -normalize-package-data@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-3.0.3.tgz#dbcc3e2da59509a0983422884cd172eefdfa525e" - integrity sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA== - dependencies: - hosted-git-info "^4.0.1" - is-core-module "^2.5.0" - semver "^7.3.4" - validate-npm-package-license "^3.0.1" - -normalize-range@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" - integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== - -nwsapi@^2.2.16: - version "2.2.20" - resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.20.tgz#22e53253c61e7b0e7e93cef42c891154bcca11ef" - integrity sha512-/ieB+mDe4MrrKMT8z+mQL8klXydZWGR5Dowt4RAGKbJ3kIGEx3X4ljUo+6V73IXtUPWgfOlU5B9MlGxFO5T+cA== - -object-inspect@^1.13.1: - version "1.13.2" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff" - integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g== - -object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.5: - version "4.1.5" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" - integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== - dependencies: - call-bind "^1.0.5" - define-properties "^1.2.1" - has-symbols "^1.0.3" - object-keys "^1.1.1" - -one-time@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/one-time/-/one-time-1.0.0.tgz#e06bc174aed214ed58edede573b433bbf827cb45" - integrity sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g== - dependencies: - fn.name "1.x.x" - -open@^10.1.0: - version "10.1.2" - resolved "https://registry.yarnpkg.com/open/-/open-10.1.2.tgz#d5df40984755c9a9c3c93df8156a12467e882925" - integrity sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw== - dependencies: - default-browser "^5.2.1" - define-lazy-prop "^3.0.0" - is-inside-container "^1.0.0" - is-wsl "^3.1.0" - -outvariant@^1.4.0, outvariant@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/outvariant/-/outvariant-1.4.3.tgz#221c1bfc093e8fec7075497e7799fdbf43d14873" - integrity sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA== - -p-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== - -p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-queue@^6.6.2: - version "6.6.2" - resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-6.6.2.tgz#2068a9dcf8e67dd0ec3e7a2bcb76810faa85e426" - integrity sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ== - dependencies: - eventemitter3 "^4.0.4" - p-timeout "^3.2.0" - -p-retry@4: - version "4.6.2" - resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.2.tgz#9baae7184057edd4e17231cee04264106e092a16" - integrity sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ== - dependencies: - "@types/retry" "0.12.0" - retry "^0.13.1" - -p-timeout@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-3.2.0.tgz#c7e17abc971d2a7962ef83626b35d635acf23dfe" - integrity sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg== - dependencies: - p-finally "^1.0.0" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -package-json-from-dist@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" - integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== - -parse-entities@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-2.0.0.tgz#53c6eb5b9314a1f4ec99fa0fdf7ce01ecda0cbe8" - integrity sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ== - dependencies: - character-entities "^1.0.0" - character-entities-legacy "^1.0.0" - character-reference-invalid "^1.0.0" - is-alphanumerical "^1.0.0" - is-decimal "^1.0.0" - is-hexadecimal "^1.0.0" - -parse-json@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" - integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== - dependencies: - "@babel/code-frame" "^7.0.0" - error-ex "^1.3.1" - json-parse-even-better-errors "^2.3.0" - lines-and-columns "^1.1.6" - -parse5@^7.2.1: - version "7.3.0" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.3.0.tgz#d7e224fa72399c7a175099f45fc2ad024b05ec05" - integrity sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw== - dependencies: - entities "^6.0.0" - -path-browserify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" - integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-scurry@^1.11.1: - version "1.11.1" - resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" - integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== - dependencies: - lru-cache "^10.2.0" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" - -path-to-regexp@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.3.0.tgz#2b6a26a337737a8e1416f9272ed0766b1c0389f4" - integrity sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ== - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -pathe@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/pathe/-/pathe-2.0.3.tgz#3ecbec55421685b70a9da872b2cff3e1cbed1716" - integrity sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w== - -pathval@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-2.0.0.tgz#7e2550b422601d4f6b8e26f1301bc8f15a741a25" - integrity sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA== - -picocolors@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" - integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== - -picocolors@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" - integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== - -picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -picomatch@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab" - integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== - -possible-typed-array-names@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" - integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== - -postcss-modules-extract-imports@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz#b4497cb85a9c0c4b5aabeb759bb25e8d89f15002" - integrity sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q== - -postcss-modules-local-by-default@^4.0.5: - version "4.2.0" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz#d150f43837831dae25e4085596e84f6f5d6ec368" - integrity sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw== - dependencies: - icss-utils "^5.0.0" - postcss-selector-parser "^7.0.0" - postcss-value-parser "^4.1.0" - -postcss-modules-scope@^3.2.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz#1bbccddcb398f1d7a511e0a2d1d047718af4078c" - integrity sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA== - dependencies: - postcss-selector-parser "^7.0.0" - -postcss-modules-values@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" - integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== - dependencies: - icss-utils "^5.0.0" - -postcss-modules@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/postcss-modules/-/postcss-modules-6.0.1.tgz#e3e895918c060c14fa6a22f84ba14a4286f436a5" - integrity sha512-zyo2sAkVvuZFFy0gc2+4O+xar5dYlaVy/ebO24KT0ftk/iJevSNyPyQellsBLlnccwh7f6V6Y4GvuKRYToNgpQ== - dependencies: - generic-names "^4.0.0" - icss-utils "^5.1.0" - lodash.camelcase "^4.3.0" - postcss-modules-extract-imports "^3.1.0" - postcss-modules-local-by-default "^4.0.5" - postcss-modules-scope "^3.2.0" - postcss-modules-values "^4.0.0" - string-hash "^1.1.3" - -postcss-selector-parser@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz#4d6af97eba65d73bc4d84bcb343e865d7dd16262" - integrity sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA== - dependencies: - cssesc "^3.0.0" - util-deprecate "^1.0.2" - -postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" - integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== - -postcss@^8.4.41, postcss@^8.5.1: - version "8.5.6" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.6.tgz#2825006615a619b4f62a9e7426cc120b349a8f3c" - integrity sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg== - dependencies: - nanoid "^3.3.11" - picocolors "^1.1.1" - source-map-js "^1.2.1" - -postcss@^8.5.3: - version "8.5.3" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.3.tgz#1463b6f1c7fb16fe258736cba29a2de35237eafb" - integrity sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A== - dependencies: - nanoid "^3.3.8" - picocolors "^1.1.1" - source-map-js "^1.2.1" - -prettier@^3.2.5: - version "3.2.5" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.5.tgz#e52bc3090586e824964a8813b09aba6233b28368" - integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A== - -pretty-format@^27.0.2: - version "27.5.1" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" - integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== - dependencies: - ansi-regex "^5.0.1" - ansi-styles "^5.0.0" - react-is "^17.0.1" - -proxy-from-env@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" - integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== - -psl@^1.1.33: - version "1.15.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.15.0.tgz#bdace31896f1d97cec6a79e8224898ce93d974c6" - integrity sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w== - dependencies: - punycode "^2.3.1" - -punycode.js@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/punycode.js/-/punycode.js-2.3.1.tgz#6b53e56ad75588234e79f4affa90972c7dd8cdb7" - integrity sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA== - -punycode@^2.1.1, punycode@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" - integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== - -querystringify@^2.1.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" - integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== - -queue-microtask@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -quick-lru@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" - integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g== - -react-dom@^19.0.0: - version "19.0.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.0.0.tgz#43446f1f01c65a4cd7f7588083e686a6726cfb57" - integrity sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ== - dependencies: - scheduler "^0.25.0" - -react-is@^17.0.1: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" - integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== - -react-refresh@^0.17.0: - version "0.17.0" - resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.17.0.tgz#b7e579c3657f23d04eccbe4ad2e58a8ed51e7e53" - integrity sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ== - -react@^19.0.0: - version "19.0.0" - resolved "https://registry.yarnpkg.com/react/-/react-19.0.0.tgz#6e1969251b9f108870aa4bff37a0ce9ddfaaabdd" - integrity sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ== - -read-pkg-up@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" - integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== - dependencies: - find-up "^4.1.0" - read-pkg "^5.2.0" - type-fest "^0.8.1" - -read-pkg@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" - integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== - dependencies: - "@types/normalize-package-data" "^2.4.0" - normalize-package-data "^2.5.0" - parse-json "^5.0.0" - type-fest "^0.6.0" - -readable-stream@^3.4.0, readable-stream@^3.6.2: - version "3.6.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" - integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readline@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/readline/-/readline-1.3.0.tgz#c580d77ef2cfc8752b132498060dc9793a7ac01c" - integrity sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg== - -redent@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" - integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== - dependencies: - indent-string "^4.0.0" - strip-indent "^3.0.0" - -regexp.prototype.flags@^1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz#138f644a3350f981a858c44f6bb1a61ff59be334" - integrity sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw== - dependencies: - call-bind "^1.0.6" - define-properties "^1.2.1" - es-errors "^1.3.0" - set-function-name "^2.0.1" - -remark-footnotes@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/remark-footnotes/-/remark-footnotes-3.0.0.tgz#5756b56f8464fa7ed80dbba0c966136305d8cb8d" - integrity sha512-ZssAvH9FjGYlJ/PBVKdSmfyPc3Cz4rTWgZLI4iE/SX8Nt5l3o3oEjv3wwG5VD7xOjktzdwp5coac+kJV9l4jgg== - dependencies: - mdast-util-footnote "^0.1.0" - micromark-extension-footnote "^0.3.0" - -remark-frontmatter@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/remark-frontmatter/-/remark-frontmatter-3.0.0.tgz#ca5d996361765c859bd944505f377d6b186a6ec6" - integrity sha512-mSuDd3svCHs+2PyO29h7iijIZx4plX0fheacJcAoYAASfgzgVIcXGYSq9GFyYocFLftQs8IOmmkgtOovs6d4oA== - dependencies: - mdast-util-frontmatter "^0.2.0" - micromark-extension-frontmatter "^0.2.0" - -remark-gfm@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/remark-gfm/-/remark-gfm-1.0.0.tgz#9213643001be3f277da6256464d56fd28c3b3c0d" - integrity sha512-KfexHJCiqvrdBZVbQ6RopMZGwaXz6wFJEfByIuEwGf0arvITHjiKKZ1dpXujjH9KZdm1//XJQwgfnJ3lmXaDPA== - dependencies: - mdast-util-gfm "^0.1.0" - micromark-extension-gfm "^0.3.0" - -remark-parse@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-9.0.0.tgz#4d20a299665880e4f4af5d90b7c7b8a935853640" - integrity sha512-geKatMwSzEXKHuzBNU1z676sGcDcFoChMK38TgdHJNAYfFtsfHDQG7MoJAjs6sgYMqyLduCYWDIWZIxiPeafEw== - dependencies: - mdast-util-from-markdown "^0.8.0" - -repeat-string@^1.0.0: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== - -requires-port@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== - -resolve-pkg-maps@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" - integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== - -resolve@^1.10.0: - version "1.22.8" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" - integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== - dependencies: - is-core-module "^2.13.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -retry@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" - integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -rimraf@^5.0.1: - version "5.0.10" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.10.tgz#23b9843d3dc92db71f96e1a2ce92e39fd2a8221c" - integrity sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ== - dependencies: - glob "^10.3.7" - -rollup@^4.34.9: - version "4.40.2" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.40.2.tgz#778e88b7a197542682b3e318581f7697f55f0619" - integrity sha512-tfUOg6DTP4rhQ3VjOO6B4wyrJnGOX85requAXvqYTHsOgb2TFJdZ3aWpT8W2kPoypSGP7dZUyzxJ9ee4buM5Fg== - dependencies: - "@types/estree" "1.0.7" - optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.40.2" - "@rollup/rollup-android-arm64" "4.40.2" - "@rollup/rollup-darwin-arm64" "4.40.2" - "@rollup/rollup-darwin-x64" "4.40.2" - "@rollup/rollup-freebsd-arm64" "4.40.2" - "@rollup/rollup-freebsd-x64" "4.40.2" - "@rollup/rollup-linux-arm-gnueabihf" "4.40.2" - "@rollup/rollup-linux-arm-musleabihf" "4.40.2" - "@rollup/rollup-linux-arm64-gnu" "4.40.2" - "@rollup/rollup-linux-arm64-musl" "4.40.2" - "@rollup/rollup-linux-loongarch64-gnu" "4.40.2" - "@rollup/rollup-linux-powerpc64le-gnu" "4.40.2" - "@rollup/rollup-linux-riscv64-gnu" "4.40.2" - "@rollup/rollup-linux-riscv64-musl" "4.40.2" - "@rollup/rollup-linux-s390x-gnu" "4.40.2" - "@rollup/rollup-linux-x64-gnu" "4.40.2" - "@rollup/rollup-linux-x64-musl" "4.40.2" - "@rollup/rollup-win32-arm64-msvc" "4.40.2" - "@rollup/rollup-win32-ia32-msvc" "4.40.2" - "@rollup/rollup-win32-x64-msvc" "4.40.2" - fsevents "~2.3.2" - -rollup@^4.5.2: - version "4.24.4" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.24.4.tgz#fdc76918de02213c95447c9ffff5e35dddb1d058" - integrity sha512-vGorVWIsWfX3xbcyAS+I047kFKapHYivmkaT63Smj77XwvLSJos6M1xGqZnBPFQFBRZDOcG1QnYEIxAvTr/HjA== - dependencies: - "@types/estree" "1.0.6" - optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.24.4" - "@rollup/rollup-android-arm64" "4.24.4" - "@rollup/rollup-darwin-arm64" "4.24.4" - "@rollup/rollup-darwin-x64" "4.24.4" - "@rollup/rollup-freebsd-arm64" "4.24.4" - "@rollup/rollup-freebsd-x64" "4.24.4" - "@rollup/rollup-linux-arm-gnueabihf" "4.24.4" - "@rollup/rollup-linux-arm-musleabihf" "4.24.4" - "@rollup/rollup-linux-arm64-gnu" "4.24.4" - "@rollup/rollup-linux-arm64-musl" "4.24.4" - "@rollup/rollup-linux-powerpc64le-gnu" "4.24.4" - "@rollup/rollup-linux-riscv64-gnu" "4.24.4" - "@rollup/rollup-linux-s390x-gnu" "4.24.4" - "@rollup/rollup-linux-x64-gnu" "4.24.4" - "@rollup/rollup-linux-x64-musl" "4.24.4" - "@rollup/rollup-win32-arm64-msvc" "4.24.4" - "@rollup/rollup-win32-ia32-msvc" "4.24.4" - "@rollup/rollup-win32-x64-msvc" "4.24.4" - fsevents "~2.3.2" - -rrweb-cssom@^0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz#3021d1b4352fbf3b614aaeed0bc0d5739abe0bc2" - integrity sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw== - -run-applescript@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/run-applescript/-/run-applescript-7.0.0.tgz#e5a553c2bffd620e169d276c1cd8f1b64778fbeb" - integrity sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A== - -run-parallel@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== - dependencies: - queue-microtask "^1.2.2" - -safe-array-concat@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.2.tgz#81d77ee0c4e8b863635227c721278dd524c20edb" - integrity sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q== - dependencies: - call-bind "^1.0.7" - get-intrinsic "^1.2.4" - has-symbols "^1.0.3" - isarray "^2.0.5" - -safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safe-regex-test@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.3.tgz#a5b4c0f06e0ab50ea2c395c14d8371232924c377" - integrity sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw== - dependencies: - call-bind "^1.0.6" - es-errors "^1.3.0" - is-regex "^1.1.4" - -safe-stable-stringify@^2.3.1: - version "2.5.0" - resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz#4ca2f8e385f2831c432a719b108a3bf7af42a1dd" - integrity sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA== - -"safer-buffer@>= 2.1.2 < 3.0.0": - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -saxes@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/saxes/-/saxes-6.0.0.tgz#fe5b4a4768df4f14a201b1ba6a65c1f3d9988cc5" - integrity sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA== - dependencies: - xmlchars "^2.2.0" - -scheduler@^0.25.0: - version "0.25.0" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.25.0.tgz#336cd9768e8cceebf52d3c80e3dcf5de23e7e015" - integrity sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA== - -"semver@2 || 3 || 4 || 5": - version "5.7.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" - integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== - -semver@^6.3.1: - version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - -semver@^7.3.4: - version "7.6.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" - integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== - -semver@^7.6.3: - version "7.6.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" - integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== - -semver@^7.7.1: - version "7.7.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.2.tgz#67d99fdcd35cec21e6f8b87a7fd515a33f982b58" - integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA== - -set-function-length@^1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" - integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== - dependencies: - define-data-property "^1.1.4" - es-errors "^1.3.0" - function-bind "^1.1.2" - get-intrinsic "^1.2.4" - gopd "^1.0.1" - has-property-descriptors "^1.0.2" - -set-function-name@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985" - integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ== - dependencies: - define-data-property "^1.1.4" - es-errors "^1.3.0" - functions-have-names "^1.2.3" - has-property-descriptors "^1.0.2" - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -side-channel@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" - integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== - dependencies: - call-bind "^1.0.7" - es-errors "^1.3.0" - get-intrinsic "^1.2.4" - object-inspect "^1.13.1" - -siginfo@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/siginfo/-/siginfo-2.0.0.tgz#32e76c70b79724e3bb567cb9d543eb858ccfaf30" - integrity sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g== - -signal-exit@^4.0.1, signal-exit@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" - integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== - -simple-swizzle@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" - integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg== - dependencies: - is-arrayish "^0.3.1" - -simple-wcswidth@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/simple-wcswidth/-/simple-wcswidth-1.0.1.tgz#8ab18ac0ae342f9d9b629604e54d2aa1ecb018b2" - integrity sha512-xMO/8eNREtaROt7tJvWJqHBDTMFN4eiQ5I4JRMuilwfnFcV5W9u7RUkueNkdw0jPqGMX36iCywelS5yilTuOxg== - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -source-map-js@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" - integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== - -spdx-correct@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" - integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz#5d607d27fc806f66d7b64a766650fa890f04ed66" - integrity sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w== - -spdx-expression-parse@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" - integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.18" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz#22aa922dcf2f2885a6494a261f2d8b75345d0326" - integrity sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ== - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== - -stack-trace@0.0.x: - version "0.0.10" - resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" - integrity sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg== - -stackback@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/stackback/-/stackback-0.0.2.tgz#1ac8a0d9483848d1695e418b6d031a3c3ce68e3b" - integrity sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw== - -stacktrace-parser@^0.1.10: - version "0.1.11" - resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.11.tgz#c7c08f9b29ef566b9a6f7b255d7db572f66fabc4" - integrity sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg== - dependencies: - type-fest "^0.7.1" - -statuses@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" - integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== - -std-env@^3.9.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.9.0.tgz#1a6f7243b339dca4c9fd55e1c7504c77ef23e8f1" - integrity sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw== - -strict-event-emitter@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz#1602ece81c51574ca39c6815e09f1a3e8550bd93" - integrity sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ== - -string-hash@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b" - integrity sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A== - -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - name string-width-cjs - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^5.0.1, string-width@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" - integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== - dependencies: - eastasianwidth "^0.2.0" - emoji-regex "^9.2.2" - strip-ansi "^7.0.1" - -string.prototype.trim@^1.2.9: - version "1.2.9" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz#b6fa326d72d2c78b6df02f7759c73f8f6274faa4" - integrity sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.0" - es-object-atoms "^1.0.0" - -string.prototype.trimend@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz#3651b8513719e8a9f48de7f2f77640b26652b229" - integrity sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-object-atoms "^1.0.0" - -string.prototype.trimstart@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz#7ee834dda8c7c17eff3118472bb35bfedaa34dde" - integrity sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-object-atoms "^1.0.0" - -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: - name strip-ansi-cjs - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^7.0.1: - version "7.1.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" - integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== - dependencies: - ansi-regex "^6.0.1" - -strip-indent@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" - integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== - dependencies: - min-indent "^1.0.0" - -superjson@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/superjson/-/superjson-2.2.2.tgz#9d52bf0bf6b5751a3c3472f1292e714782ba3173" - integrity sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q== - dependencies: - copy-anything "^3.0.2" - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - -symbol-tree@^3.2.4: - version "3.2.4" - resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" - integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== - -tailwindcss@4.1.10: - version "4.1.10" - resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-4.1.10.tgz#515741b0a79316d1971d182f7fbc435b68679373" - integrity sha512-P3nr6WkvKV/ONsTzj6Gb57sWPMX29EPNPopo7+FcpkQaNsrNpZ1pv8QmrYI2RqEKD7mlGqLnGovlcYnBK0IqUA== - -tapable@^2.2.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.2.tgz#ab4984340d30cb9989a490032f086dbb8b56d872" - integrity sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg== - -tar@^7.4.3: - version "7.4.3" - resolved "https://registry.yarnpkg.com/tar/-/tar-7.4.3.tgz#88bbe9286a3fcd900e94592cda7a22b192e80571" - integrity sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw== - dependencies: - "@isaacs/fs-minipass" "^4.0.0" - chownr "^3.0.0" - minipass "^7.1.2" - minizlib "^3.0.1" - mkdirp "^3.0.1" - yallist "^5.0.0" - -text-hex@1.0.x: - version "1.0.0" - resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5" - integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg== - -tinybench@^2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.9.0.tgz#103c9f8ba6d7237a47ab6dd1dcff77251863426b" - integrity sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg== - -tinyexec@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-0.3.2.tgz#941794e657a85e496577995c6eef66f53f42b3d2" - integrity sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA== - -tinyglobby@^0.2.13: - version "0.2.13" - resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.13.tgz#a0e46515ce6cbcd65331537e57484af5a7b2ff7e" - integrity sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw== - dependencies: - fdir "^6.4.4" - picomatch "^4.0.2" - -tinypool@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-1.0.2.tgz#706193cc532f4c100f66aa00b01c42173d9051b2" - integrity sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA== - -tinyrainbow@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-2.0.0.tgz#9509b2162436315e80e3eee0fcce4474d2444294" - integrity sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw== - -tinyspy@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-3.0.2.tgz#86dd3cf3d737b15adcf17d7887c84a75201df20a" - integrity sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q== - -tldts-core@^6.1.86: - version "6.1.86" - resolved "https://registry.yarnpkg.com/tldts-core/-/tldts-core-6.1.86.tgz#a93e6ed9d505cb54c542ce43feb14c73913265d8" - integrity sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA== - -tldts@^6.1.32: - version "6.1.86" - resolved "https://registry.yarnpkg.com/tldts/-/tldts-6.1.86.tgz#087e0555b31b9725ee48ca7e77edc56115cd82f7" - integrity sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ== - dependencies: - tldts-core "^6.1.86" - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -tough-cookie@^4.1.4: - version "4.1.4" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.4.tgz#945f1461b45b5a8c76821c33ea49c3ac192c1b36" - integrity sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag== - dependencies: - psl "^1.1.33" - punycode "^2.1.1" - universalify "^0.2.0" - url-parse "^1.5.3" - -tough-cookie@^5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-5.1.2.tgz#66d774b4a1d9e12dc75089725af3ac75ec31bed7" - integrity sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A== - dependencies: - tldts "^6.1.32" - -tr46@^5.1.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-5.1.1.tgz#96ae867cddb8fdb64a49cc3059a8d428bcf238ca" - integrity sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw== - dependencies: - punycode "^2.3.1" - -transform-markdown-links@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/transform-markdown-links/-/transform-markdown-links-2.1.0.tgz#de2178d96ef0e020226ebd967dcc5873df039792" - integrity sha512-7HWQwQ9US+tJSMMzi1aP+KA3QwfjDs8sB4H5GBMRHFNBMQVdgoF6VfIFy2nJR/UHRTkYoGFwWh2pe+QIwSvfOA== - -traverse@^0.6.7: - version "0.6.9" - resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.9.tgz#76cfdbacf06382d460b76f8b735a44a6209d8b81" - integrity sha512-7bBrcF+/LQzSgFmT0X5YclVqQxtv7TDJ1f8Wj7ibBu/U6BMLeOpUxuZjV7rMc44UtKxlnMFigdhFAIszSX1DMg== - dependencies: - gopd "^1.0.1" - typedarray.prototype.slice "^1.0.3" - which-typed-array "^1.1.15" - -trim-newlines@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" - integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw== - -triple-beam@^1.3.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.4.1.tgz#6fde70271dc6e5d73ca0c3b24e2d92afb7441984" - integrity sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg== - -trough@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" - integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== - -ts-morph@^21.0.1: - version "21.0.1" - resolved "https://registry.yarnpkg.com/ts-morph/-/ts-morph-21.0.1.tgz#712302a0f6e9dbf1aa8d9cf33a4386c4b18c2006" - integrity sha512-dbDtVdEAncKctzrVZ+Nr7kHpHkv+0JDJb2MjjpBaj8bFeCkePU9rHfMklmhuLFnpeq/EJZk2IhStY6NzqgjOkg== - dependencies: - "@ts-morph/common" "~0.22.0" - code-block-writer "^12.0.0" - -tslib@^2.4.0, tslib@^2.8.0: - version "2.8.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" - integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== - -tsx@^4.19.3: - version "4.20.3" - resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.20.3.tgz#f913e4911d59ad177c1bcee19d1035ef8dd6e2fb" - integrity sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ== - dependencies: - esbuild "~0.25.0" - get-tsconfig "^4.7.5" - optionalDependencies: - fsevents "~2.3.3" - -type-fest@^0.18.0: - version "0.18.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f" - integrity sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw== - -type-fest@^0.21.3: - version "0.21.3" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" - integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== - -type-fest@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" - integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== - -type-fest@^0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" - integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== - -type-fest@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" - integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== - -type-fest@^4.26.1: - version "4.41.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.41.0.tgz#6ae1c8e5731273c2bf1f58ad39cbae2c91a46c58" - integrity sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA== - -typed-array-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz#1867c5d83b20fcb5ccf32649e5e2fc7424474ff3" - integrity sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ== - dependencies: - call-bind "^1.0.7" - es-errors "^1.3.0" - is-typed-array "^1.1.13" - -typed-array-byte-length@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz#d92972d3cff99a3fa2e765a28fcdc0f1d89dec67" - integrity sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw== - dependencies: - call-bind "^1.0.7" - for-each "^0.3.3" - gopd "^1.0.1" - has-proto "^1.0.3" - is-typed-array "^1.1.13" - -typed-array-byte-offset@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz#f9ec1acb9259f395093e4567eb3c28a580d02063" - integrity sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA== - dependencies: - available-typed-arrays "^1.0.7" - call-bind "^1.0.7" - for-each "^0.3.3" - gopd "^1.0.1" - has-proto "^1.0.3" - is-typed-array "^1.1.13" - -typed-array-length@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.6.tgz#57155207c76e64a3457482dfdc1c9d1d3c4c73a3" - integrity sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g== - dependencies: - call-bind "^1.0.7" - for-each "^0.3.3" - gopd "^1.0.1" - has-proto "^1.0.3" - is-typed-array "^1.1.13" - possible-typed-array-names "^1.0.0" - -typedarray.prototype.slice@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/typedarray.prototype.slice/-/typedarray.prototype.slice-1.0.3.tgz#bce2f685d3279f543239e4d595e0d021731d2d1a" - integrity sha512-8WbVAQAUlENo1q3c3zZYuy5k9VzBQvp8AX9WOtbvyWlLM1v5JaSRmjubLjzHF4JFtptjH/5c/i95yaElvcjC0A== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-abstract "^1.23.0" - es-errors "^1.3.0" - typed-array-buffer "^1.0.2" - typed-array-byte-offset "^1.0.2" - -typedoc-plugin-markdown@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.4.2.tgz#fc31779595aa9bf00e66709f3894e048345bf7ed" - integrity sha512-kJVkU2Wd+AXQpyL6DlYXXRrfNrHrEIUgiABWH8Z+2Lz5Sq6an4dQ/hfvP75bbokjNDUskOdFlEEm/0fSVyC7eg== - -typedoc@^0.27.7: - version "0.27.7" - resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.27.7.tgz#09047ffb5c845f45765de26c68b77260867fe967" - integrity sha512-K/JaUPX18+61W3VXek1cWC5gwmuLvYTOXJzBvD9W7jFvbPnefRnCHQCEPw7MSNrP/Hj7JJrhZtDDLKdcYm6ucg== - dependencies: - "@gerrit0/mini-shiki" "^1.24.0" - lunr "^2.3.9" - markdown-it "^14.1.0" - minimatch "^9.0.5" - yaml "^2.6.1" - -typescript@^5.4.5: - version "5.4.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611" - integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== - -uc.micro@^2.0.0, uc.micro@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-2.1.0.tgz#f8d3f7d0ec4c3dea35a7e3c8efa4cb8b45c9e7ee" - integrity sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A== - -unbox-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" - integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== - dependencies: - call-bind "^1.0.2" - has-bigints "^1.0.2" - has-symbols "^1.0.3" - which-boxed-primitive "^1.0.2" - -underscore@^1.13.2: - version "1.13.6" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.6.tgz#04786a1f589dc6c09f761fc5f45b89e935136441" - integrity sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A== - -undici-types@~5.26.4: - version "5.26.5" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" - integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== - -unified@^9.2.2: - version "9.2.2" - resolved "https://registry.yarnpkg.com/unified/-/unified-9.2.2.tgz#67649a1abfc3ab85d2969502902775eb03146975" - integrity sha512-Sg7j110mtefBD+qunSLO1lqOEKdrwBFBrR6Qd8f4uwkhWNlbkaqwHse6e7QvD3AP/MNoJdEDLaf8OxYyoWgorQ== - dependencies: - bail "^1.0.0" - extend "^3.0.0" - is-buffer "^2.0.0" - is-plain-obj "^2.0.0" - trough "^1.0.0" - vfile "^4.0.0" - -unist-util-is@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-4.1.0.tgz#976e5f462a7a5de73d94b706bac1b90671b57797" - integrity sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg== - -unist-util-stringify-position@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz#cce3bfa1cdf85ba7375d1d5b17bdc4cada9bd9da" - integrity sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g== - dependencies: - "@types/unist" "^2.0.2" - -unist-util-visit-parents@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz#65a6ce698f78a6b0f56aa0e88f13801886cdaef6" - integrity sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg== - dependencies: - "@types/unist" "^2.0.0" - unist-util-is "^4.0.0" - -universal-user-agent@^7.0.0, universal-user-agent@^7.0.2: - version "7.0.2" - resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-7.0.2.tgz#52e7d0e9b3dc4df06cc33cb2b9fd79041a54827e" - integrity sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q== - -universalify@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" - integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== - -update-browserslist-db@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz#348377dd245216f9e7060ff50b15a1b740b75420" - integrity sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw== - dependencies: - escalade "^3.2.0" - picocolors "^1.1.1" - -update-section@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/update-section/-/update-section-0.3.3.tgz#458f17820d37820dc60e20b86d94391b00123158" - integrity sha512-BpRZMZpgXLuTiKeiu7kK0nIPwGdyrqrs6EDSaXtjD/aQ2T+qVo9a5hRC3HN3iJjCMxNT/VxoLGQ7E/OzE5ucnw== - -url-parse@^1.5.3: - version "1.5.10" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" - integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== - dependencies: - querystringify "^2.1.1" - requires-port "^1.0.0" - -util-deprecate@^1.0.1, util-deprecate@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== - -uuid@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-10.0.0.tgz#5a95aa454e6e002725c79055fd42aaba30ca6294" - integrity sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ== - -uuid@^9.0.0: - version "9.0.1" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" - integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== - -validate-npm-package-license@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" - -vfile-message@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-2.0.4.tgz#5b43b88171d409eae58477d13f23dd41d52c371a" - integrity sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ== - dependencies: - "@types/unist" "^2.0.0" - unist-util-stringify-position "^2.0.0" - -vfile@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/vfile/-/vfile-4.2.1.tgz#03f1dce28fc625c625bc6514350fbdb00fa9e624" - integrity sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA== - dependencies: - "@types/unist" "^2.0.0" - is-buffer "^2.0.0" - unist-util-stringify-position "^2.0.0" - vfile-message "^2.0.0" - -vite-node@3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-3.1.3.tgz#d021ced40b5a057305eaea9ce62c610c33b60a48" - integrity sha512-uHV4plJ2IxCl4u1up1FQRrqclylKAogbtBfOTwcuJ28xFi+89PZ57BRh+naIRvH70HPwxy5QHYzg1OrEaC7AbA== - dependencies: - cac "^6.7.14" - debug "^4.4.0" - es-module-lexer "^1.7.0" - pathe "^2.0.3" - vite "^5.0.0 || ^6.0.0" - -"vite@^5.0.0 || ^6.0.0": - version "6.3.5" - resolved "https://registry.yarnpkg.com/vite/-/vite-6.3.5.tgz#fec73879013c9c0128c8d284504c6d19410d12a3" - integrity sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ== - dependencies: - esbuild "^0.25.0" - fdir "^6.4.4" - picomatch "^4.0.2" - postcss "^8.5.3" - rollup "^4.34.9" - tinyglobby "^0.2.13" - optionalDependencies: - fsevents "~2.3.3" - -vitest@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/vitest/-/vitest-3.1.3.tgz#0b0b01932408cd3af61867f4468d28bd83406ffb" - integrity sha512-188iM4hAHQ0km23TN/adso1q5hhwKqUpv+Sd6p5sOuh6FhQnRNW3IsiIpvxqahtBabsJ2SLZgmGSpcYK4wQYJw== - dependencies: - "@vitest/expect" "3.1.3" - "@vitest/mocker" "3.1.3" - "@vitest/pretty-format" "^3.1.3" - "@vitest/runner" "3.1.3" - "@vitest/snapshot" "3.1.3" - "@vitest/spy" "3.1.3" - "@vitest/utils" "3.1.3" - chai "^5.2.0" - debug "^4.4.0" - expect-type "^1.2.1" - magic-string "^0.30.17" - pathe "^2.0.3" - std-env "^3.9.0" - tinybench "^2.9.0" - tinyexec "^0.3.2" - tinyglobby "^0.2.13" - tinypool "^1.0.2" - tinyrainbow "^2.0.0" - vite "^5.0.0 || ^6.0.0" - vite-node "3.1.3" - why-is-node-running "^2.3.0" - -w3c-xmlserializer@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz#f925ba26855158594d907313cedd1476c5967f6c" - integrity sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA== - dependencies: - xml-name-validator "^5.0.0" - -webidl-conversions@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" - integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== - -whatwg-encoding@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz#d0f4ef769905d426e1688f3e34381a99b60b76e5" - integrity sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ== - dependencies: - iconv-lite "0.6.3" - -whatwg-mimetype@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz#bc1bf94a985dc50388d54a9258ac405c3ca2fc0a" - integrity sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg== - -whatwg-url@^14.0.0, whatwg-url@^14.1.1: - version "14.2.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-14.2.0.tgz#4ee02d5d725155dae004f6ae95c73e7ef5d95663" - integrity sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw== - dependencies: - tr46 "^5.1.0" - webidl-conversions "^7.0.0" - -which-boxed-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== - dependencies: - is-bigint "^1.0.1" - is-boolean-object "^1.1.0" - is-number-object "^1.0.4" - is-string "^1.0.5" - is-symbol "^1.0.3" - -which-typed-array@^1.1.14, which-typed-array@^1.1.15: - version "1.1.15" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" - integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA== - dependencies: - available-typed-arrays "^1.0.7" - call-bind "^1.0.7" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.2" - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -why-is-node-running@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/why-is-node-running/-/why-is-node-running-2.3.0.tgz#a3f69a97107f494b3cdc3bdddd883a7d65cebf04" - integrity sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w== - dependencies: - siginfo "^2.0.0" - stackback "0.0.2" - -winston-console-format@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/winston-console-format/-/winston-console-format-1.0.8.tgz#591adc8e9567c3397a3fa2e29e596d56e48db840" - integrity sha512-dq7t/E0D0QRi4XIOwu6HM1+5e//WPqylH88GVjKEhQVrzGFg34MCz+G7pMJcXFBen9C0kBsu5GYgbYsE2LDwKw== - dependencies: - colors "^1.4.0" - logform "^2.2.0" - triple-beam "^1.3.0" - -winston-transport@^4.9.0: - version "4.9.0" - resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.9.0.tgz#3bba345de10297654ea6f33519424560003b3bf9" - integrity sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A== - dependencies: - logform "^2.7.0" - readable-stream "^3.6.2" - triple-beam "^1.3.0" - -winston@^3.17.0: - version "3.17.0" - resolved "https://registry.yarnpkg.com/winston/-/winston-3.17.0.tgz#74b8665ce9b4ea7b29d0922cfccf852a08a11423" - integrity sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw== - dependencies: - "@colors/colors" "^1.6.0" - "@dabh/diagnostics" "^2.0.2" - async "^3.2.3" - is-stream "^2.0.0" - logform "^2.7.0" - one-time "^1.0.0" - readable-stream "^3.4.0" - safe-stable-stringify "^2.3.1" - stack-trace "0.0.x" - triple-beam "^1.3.0" - winston-transport "^4.9.0" - -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: - name wrap-ansi-cjs - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" - integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" - integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== - dependencies: - ansi-styles "^6.1.0" - string-width "^5.0.1" - strip-ansi "^7.0.1" - -ws@^8.18.0: - version "8.18.2" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.2.tgz#42738b2be57ced85f46154320aabb51ab003705a" - integrity sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ== - -xml-name-validator@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-5.0.0.tgz#82be9b957f7afdacf961e5980f1bf227c0bf7673" - integrity sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg== - -xmlchars@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" - integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== - -y18n@^5.0.5: - version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" - integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== - -yallist@^3.0.2: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yallist@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-5.0.0.tgz#00e2de443639ed0d78fd87de0d27469fbcffb533" - integrity sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw== - -yaml@^2.6.1: - version "2.7.0" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.7.0.tgz#aef9bb617a64c937a9a748803786ad8d3ffe1e98" - integrity sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA== - -yargs-parser@^20.2.3: - version "20.2.9" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" - integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== - -yargs-parser@^21.1.1: - version "21.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" - integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== - -yargs@^17.7.2: - version "17.7.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" - integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== - dependencies: - cliui "^8.0.1" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.3" - y18n "^5.0.5" - yargs-parser "^21.1.1" - -yoctocolors-cjs@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz#f4b905a840a37506813a7acaa28febe97767a242" - integrity sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA== - -zod-to-json-schema@^3.22.3: - version "3.24.1" - resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.24.1.tgz#f08c6725091aadabffa820ba8d50c7ab527f227a" - integrity sha512-3h08nf3Vw3Wl3PK+q3ow/lIil81IT2Oa7YpQyUUDsEWbXveMesdfK1xBd2RhCkynwZndAxixji/7SYJJowr62w== - -zod@^3.23.8, zod@^3.25.32: - version "3.25.67" - resolved "https://registry.yarnpkg.com/zod/-/zod-3.25.67.tgz#62987e4078e2ab0f63b491ef0c4f33df24236da8" - integrity sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw== - -zwitch@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920" - integrity sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw== From dc95d1af887ed4636dfec1a606d8a67609da324e Mon Sep 17 00:00:00 2001 From: Tat Dat Duong Date: Thu, 3 Jul 2025 16:52:35 +0200 Subject: [PATCH 020/129] Add a README.md --- libs/sdk-js/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 libs/sdk-js/README.md diff --git a/libs/sdk-js/README.md b/libs/sdk-js/README.md new file mode 100644 index 000000000..c12e9310e --- /dev/null +++ b/libs/sdk-js/README.md @@ -0,0 +1 @@ +This repository has been moved to [langchain-ai/langgraphjs](https://github.com/langchain-ai/langgraphjs/tree/main/libs/sdk). \ No newline at end of file From 07cd4d83e1215d9cff6f9ccce9ac63fed3f6df7e Mon Sep 17 00:00:00 2001 From: Andrew Nguonly Date: Thu, 3 Jul 2025 16:04:27 -0700 Subject: [PATCH 021/129] docs: Add note about preemptive compute infra (#5339) * Add note about preemtive compute infra. * Fix spelling error. --- docs/docs/concepts/langgraph_control_plane.md | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/docs/docs/concepts/langgraph_control_plane.md b/docs/docs/concepts/langgraph_control_plane.md index f3562516c..ebc880ce5 100644 --- a/docs/docs/concepts/langgraph_control_plane.md +++ b/docs/docs/concepts/langgraph_control_plane.md @@ -46,21 +46,40 @@ For simplicity, the control plane offers two deployment types with different res | **Deployment Type** | **CPU/Memory** | **Scaling** | **Database** | |---------------------|-----------------|---------------------|----------------------------------------------------------------------------------| -| Development | 1 CPU, 1 GB RAM | Up to 1 container | 10 GB disk, no backups | -| Production | 2 CPU, 2 GB RAM | Up to 10 containers | Autoscaling disk, automatic backups, highly available (multi-zone configuration) | +| Development | 1 CPU, 1 GB RAM | Up to 1 replica | 10 GB disk, no backups | +| Production | 2 CPU, 2 GB RAM | Up to 10 replicas | Autoscaling disk, automatic backups, highly available (multi-zone configuration) | -CPU and memory resources are per container. +CPU and memory resources are per replica. !!! warning "Immutable Deployment Type" Once a deployment is created, the deployment type cannot be changed. -!!! info "Resource Customization" - For `Production` type deployments, resources can be manually increased on a case-by-case basis depending on use case and capacity constraints. Contact support@langchain.dev to request an increase in resources. +!!! info "Self-Hosted Deployment" + Resources for [Self-Hosted Data Plane](../concepts/langgraph_self_hosted_data_plane.md) and [Self-Hosted Control Plane](../concepts/langgraph_self_hosted_control_plane.md) deployments can be fully customized. Deployment types are only applicable for [Cloud SaaS](../concepts/langgraph_cloud.md) deployments. - For `Development` types deployments, database disk size can be manually increased on a case-by-case basis depending on use case and capacity constraints. For most use cases, [TTLs](../how-tos/ttl/configure_ttl.md) should be configured to manage disk usage. Contact support@langchain.dev to request an increase in resources. +#### Production - Resources for [Self-Hosted Data Plane](../concepts/langgraph_self_hosted_data_plane.md) and [Self-Hosted Control Plane](../concepts/langgraph_self_hosted_control_plane.md) deployments can be fully customized. +`Production` type deployments are suitable for "production" workloads. For example, select `Production` for customer-facing applications in the critical path. + +Resources for `Production` type deployments can be manually increased on a case-by-case basis depending on use case and capacity constraints. Contact support@langchain.dev to request an increase in resources. + +#### Development + +`Development` type deployments are suitable development and testing. For example, select `Development` for internal testing environments. `Development` type deployments are not suitable for "production" workloads. + +!!! danger "Preemptible Compute Infrastructure" + `Development` type deployments (API server, queue server, and database) are provisioned on preemptible compute infrastructure. This means the compute infrastructure **may be terminated at any time without notice**. This may result in intermittent... + + - Redis connection timeouts/errors + - Postgres connection timeouts/errors + - Failed or retrying background runs + + This behavior is expected. Preemptible compute infrastructure **significantly reduces the cost to provision a `Development` type deployment**. By design, LangGraph Server is fault-tolerant. The implementation will automatically attempt to recover from Redis/Postgres connection errors and retry failed background runs. + + `Production` type deployments are provisioned on durable compute infrastructure, not preemptible compute infrastructure. + +Database disk size for `Development` type deployments can be manually increased on a case-by-case basis depending on use case and capacity constraints. For most use cases, [TTLs](../how-tos/ttl/configure_ttl.md) should be configured to manage disk usage. Contact support@langchain.dev to request an increase in resources. ### Database Provisioning From 690b6f4ea11ed699ca3de030cc14c92ee5651c03 Mon Sep 17 00:00:00 2001 From: Tat Dat Duong Date: Fri, 4 Jul 2025 16:29:38 +0200 Subject: [PATCH 022/129] fix(docs): invalid command for creating langgraph app Closes https://github.com/langchain-ai/langgraphjs/issues/1331 --- docs/docs/concepts/template_applications.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/concepts/template_applications.md b/docs/docs/concepts/template_applications.md index 76ebff698..8da3229b9 100644 --- a/docs/docs/concepts/template_applications.md +++ b/docs/docs/concepts/template_applications.md @@ -64,7 +64,7 @@ To create a new app from a template, use the `langgraph new` command. === "JS" ```bash - npx @langchain/langgraph-cli new + npm create langgraph@latest ``` ## Next Steps From cac0cd5522b7c1d7a3c38b6402b96f1e56b6e5de Mon Sep 17 00:00:00 2001 From: Chris G Date: Mon, 7 Jul 2025 02:35:37 +0200 Subject: [PATCH 023/129] docs: update name of CompiledGraph CompiledStateGraph (#5348) The name (and type) has changed. See: https://langchain-ai.github.io/langgraph/reference/graphs/#langgraph.graph.state.StateGraph.compile --- docs/docs/tutorials/get-started/1-build-basic-chatbot.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/tutorials/get-started/1-build-basic-chatbot.md b/docs/docs/tutorials/get-started/1-build-basic-chatbot.md index 9235fa65f..3304822c6 100644 --- a/docs/docs/tutorials/get-started/1-build-basic-chatbot.md +++ b/docs/docs/tutorials/get-started/1-build-basic-chatbot.md @@ -112,7 +112,7 @@ This tells the graph to terminate after running the chatbot node. ## 6. Compile the graph Before running the graph, we'll need to compile it. We can do so by calling `compile()` -on the graph builder. This creates a `CompiledGraph` we can invoke on our state. +on the graph builder. This creates a `CompiledStateGraph` we can invoke on our state. ```python graph = graph_builder.compile() From d8756f257ede24658b51c95dec315b8218adba0a Mon Sep 17 00:00:00 2001 From: Shivang Agarwal Date: Mon, 7 Jul 2025 06:06:28 +0530 Subject: [PATCH 024/129] Updated TAVILY Key Setup (#5346) --- docs/docs/tutorials/get-started/2-add-tools.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/docs/tutorials/get-started/2-add-tools.md b/docs/docs/tutorials/get-started/2-add-tools.md index 33accd9a8..4d30ae522 100644 --- a/docs/docs/tutorials/get-started/2-add-tools.md +++ b/docs/docs/tutorials/get-started/2-add-tools.md @@ -23,12 +23,16 @@ pip install -U langchain-tavily Configure your environment with your search engine API key: -```bash +```python +def _set_env(var: str): + if not os.environ.get(var): + os.environ[var] = getpass.getpass(f"{var}: ") + _set_env("TAVILY_API_KEY") ``` ``` -TAVILY_API_KEY: ········ +os.environ["TAVILY_API_KEY"]: "········" ``` ## 3. Define the tool From 269590c4d92a59daebd5f8646e9ab8cc8adff401 Mon Sep 17 00:00:00 2001 From: jessicaou Date: Sun, 6 Jul 2025 17:37:54 -0700 Subject: [PATCH 025/129] docs: update case studies (#5353) --- docs/docs/adopters.md | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/docs/docs/adopters.md b/docs/docs/adopters.md index 91142d44f..d2b8a278b 100644 --- a/docs/docs/adopters.md +++ b/docs/docs/adopters.md @@ -8,24 +8,41 @@ This list of companies using LangGraph and their success stories is compiled fro | [AirTop](https://www.airtop.ai/) | Software & Technology (GenAI Native) | Browser automation for AI agents | [Case study, 2024](https://blog.langchain.dev/customers-airtop/) | | [AppFolio](https://www.appfolio.com/) | Real Estate | Copilot for domain-specific task | [Case study, 2024](https://blog.langchain.dev/customers-appfolio/) | | [Athena Intelligence](https://www.athenaintel.com/) | Software & Technology (GenAI Native) | Research & summarization | [Case study, 2024](https://blog.langchain.dev/customers-athena-intelligence/) | +| [BlackRock](https://www.blackrock.com/) | Financial Services | Copilot for domain-specific task | [Interrupt talk, 2025](https://youtu.be/oyqeCHFM5U4?feature=shared) | | [Captide](https://www.captide.co/) | Software & Technology (GenAI Native) | Data extraction | [Case study, 2025](https://blog.langchain.dev/how-captide-is-redefining-equity-research-with-agentic-workflows-built-on-langgraph-and-langsmith/) | -| [Cisco Outshift](https://outshift.cisco.com/) | Software & Technology | DevOps | [Blog post, 2025](https://outshift.cisco.com/blog/build-react-agent-application-for-devops-tasks-using-rest-apis) | +| [Cisco CX](https://www.cisco.com/site/us/en/services/modern-data-center/index.html?CCID=cc005911&DTID=eivtotr001480&OID=srwsas032775) | Software & Technology | Customer support | [Interrupt Talk, 2025](https://youtu.be/gPhyPRtIMn0?feature=shared) | +| [Cisco Outshift](https://outshift.cisco.com/) | Software & Technology | DevOps | [Video story, 2025](https://www.youtube.com/watch?v=htcb-vGR_x0); [Case study, 2025](https://blog.langchain.com/cisco-outshift/); [Blog post, 2025](https://outshift.cisco.com/blog/build-react-agent-application-for-devops-tasks-using-rest-apis) | +| [Cisco TAC](https://www.cisco.com/c/en/us/support/index.html) | Software & Technology | Customer support | [Video story, 2025](https://youtu.be/EAj0HBDGqaE?feature=shared) | +| [City of Hope](https://www.cityofhope.org/) | Non-profit | Copilot for domain-specific task | [Video story, 2025](https://youtu.be/9ABwtK2gIZU?feature=shared) | | [C.H. Robinson](https://www.chrobinson.com/en-us/) | Logistics | Automation | [Case study, 2025](https://blog.langchain.dev/customers-chrobinson/) | +| [Definely](https://www.definely.com/) | Legal | Copilot for domain-specific task | [Case study, 2025](https://blog.langchain.com/customers-definely/) | +| [Docent Pro](https://docentpro.com/) | Travel | GenAI embedded product experiences | [Case study, 2025](https://blog.langchain.com/customers-docentpro/) | | [Elastic](https://www.elastic.co/) | Software & Technology | Copilot for domain-specific task | [Blog post, 2025](https://www.elastic.co/blog/elastic-security-generative-ai-features) | +| [Exa](https://exa.ai/) | Software & Technology (GenAI Native) | Search | [Case study, 2025](https://blog.langchain.com/exa/) | | [GitLab](https://about.gitlab.com/) | Software & Technology | Code generation | [Duo workflow docs](https://handbook.gitlab.com/handbook/engineering/architecture/design-documents/duo_workflow/) | +| [Harmonic](https://harmonic.ai/) | Software & Technology | Search | [Case study, 2025](https://blog.langchain.com/customers-harmonic/) | | [Inconvo](https://inconvo.ai/?ref=blog.langchain.dev) | Software & Technology | Code generation | [Case study, 2025](https://blog.langchain.dev/customers-inconvo/) | | [Infor](https://infor.com/) | Software & Technology | GenAI embedded product experiences; customer support; copilot | [Case study, 2025](https://blog.langchain.dev/customers-infor/) | +| [J.P. Morgan](https://www.jpmorganchase.com/) | Financial Services | Copilot for domain-specific task | [Interrupt talk, 2025](https://youtu.be/yMalr0jiOAc?feature=shared) | | [Klarna](https://www.klarna.com/) | Fintech | Copilot for domain-specific task | [Case study, 2025](https://blog.langchain.dev/customers-klarna/) | | [Komodo Health](https://www.komodohealth.com/) | Healthcare | Copilot for domain-specific task | [Blog post](https://www.komodohealth.com/perspectives/new-gen-ai-assistant-empowers-the-enterprise/) | -| [LinkedIn](https://www.linkedin.com/) | Social Media | Code generation; Search & discovery | [Blog post, 2025](https://www.linkedin.com/blog/engineering/ai/practical-text-to-sql-for-data-analytics); [Blog post, 2024](https://www.linkedin.com/blog/engineering/generative-ai/behind-the-platform-the-journey-to-create-the-linkedin-genai-application-tech-stack) | +| [LinkedIn](https://www.linkedin.com/) | Social Media | Code generation; Search & discovery | [Interrupt talk, 2025](https://youtu.be/NmblVxyBhi8?feature=shared); [Blog post, 2025](https://www.linkedin.com/blog/engineering/ai/practical-text-to-sql-for-data-analytics); [Blog post, 2024](https://www.linkedin.com/blog/engineering/generative-ai/behind-the-platform-the-journey-to-create-the-linkedin-genai-application-tech-stack) | | [Minimal](https://gominimal.ai/) | E-commerce | Customer support | [Case study, 2025](https://blog.langchain.dev/how-minimal-built-a-multi-agent-customer-support-system-with-langgraph-langsmith/) | +| [Modern Treasury](https://www.moderntreasury.com/) | Fintech | GenAI embedded product experiences | [Video story, 2025](https://youtu.be/AwAiffXqaCU?feature=shared) | +| [Monday](https://monday.com/) | Software & Technology | GenAI embedded product experiences | [Interrupt talk, 2025](https://blog.langchain.dev/how-minimal-built-a-multi-agent-customer-support-system-with-langgraph-langsmith/) | +| [Morningstar](https://www.morningstar.com/) | Financial Services | Research & summarization | [Video story, 2025](https://youtu.be/6LidoFXCJPs?feature=shared) | | [OpenRecovery](https://www.openrecovery.com/) | Healthcare | Copilot for domain-specific task | [Case study, 2024](https://blog.langchain.dev/customers-openrecovery/) | +| [Pigment](https://www.pigment.com/) | Fintech | GenAI embedded product experiences | [Video story, 2025](https://youtu.be/5JVSO2KYOmE?feature=shared) | +| [Prosper](https://www.prosper.com/) | Fintech | Customer support | [Video story, 2025](https://youtu.be/9RFNOYtkwsc?feature=shared) | | [Qodo](https://www.qodo.ai/) | Software & Technology (GenAI Native) | Code generation | [Blog post, 2025](https://www.qodo.ai/blog/why-we-chose-langgraph-to-build-our-coding-agent/) | -| [Rakuten](https://www.rakuten.com/) | E-commerce / Fintech | Copilot for domain-specific task | [Blog post, 2025](https://rakuten.today/blog/from-ai-hype-to-real-world-tools-rakuten-teams-up-with-langchain.html) | +| [Rakuten](https://www.rakuten.com/) | E-commerce / Fintech | Copilot for domain-specific task | [Video story, 2025](https://youtu.be/gD1LIjCkuA8?feature=shared); [Blog post, 2025](https://rakuten.today/blog/from-ai-hype-to-real-world-tools-rakuten-teams-up-with-langchain.html) | | [Replit](https://replit.com/) | Software & Technology | Code generation | [Blog post, 2024](https://blog.langchain.dev/customers-replit/); [Breakout agent story, 2024](https://www.langchain.com/breakoutagents/replit); [Fireside chat video, 2024](https://www.youtube.com/watch?v=ViykMqljjxU) | | [Rexera](https://www.rexera.com/) | Real Estate (GenAI Native) | Copilot for domain-specific task | [Case study, 2024](https://blog.langchain.dev/customers-rexera/) | +| [Abu Dhabi Government](https://www.tamm.abudhabi/) | Government | Search | [Case study, 2025](https://blog.langchain.com/customers-abu-dhabi-government/) | | [Tradestack](https://www.tradestack.uk/) | Software & Technology (GenAI Native) | Copilot for domain-specific task | [Case study, 2024](https://blog.langchain.dev/customers-tradestack/) | -| [Uber](https://www.uber.com/) | Transportation | Developer productivity; Code generation | [Presentation, 2024](https://dpe.org/sessions/ty-smith-adam-huda/this-year-in-ubers-ai-driven-developer-productivity-revolution/); [Video, 2024](https://www.youtube.com/watch?v=8rkA5vWUE4Y) | -| [Unify](https://www.unifygtm.com/) | Software & Technology (GenAI Native) | Copilot for domain-specific task | [Blog post, 2024](https://blog.langchain.dev/unify-launches-agents-for-account-qualification-using-langgraph-and-langsmith/) | -| [Vizient](https://www.vizientinc.com/) | Healthcare | Copilot for domain-specific task | [Case study, 2025](https://blog.langchain.dev/p/3d2cd58c-13a5-4df9-bd84-7d54ed0ed82c/) | +| [Uber](https://www.uber.com/) | Transportation | Developer productivity; Code generation | [Interrupt talk, 2025](https://youtu.be/Bugs0dVcNI8?feature=shared); [Presentation, 2024](https://dpe.org/sessions/ty-smith-adam-huda/this-year-in-ubers-ai-driven-developer-productivity-revolution/); [Video, 2024](https://www.youtube.com/watch?v=8rkA5vWUE4Y) | +| [Unify](https://www.unifygtm.com/) | Software & Technology (GenAI Native) | Copilot for domain-specific task | [Interrupt talk, 2025](https://youtu.be/pKk-LfhujwI?feature=shared); [Blog post, 2024](https://blog.langchain.dev/unify-launches-agents-for-account-qualification-using-langgraph-and-langsmith/) | +| [Vizient](https://www.vizientinc.com/) | Healthcare | Copilot for domain-specific task | [Video story, 2025](https://www.youtube.com/watch?v=vrjJ6NuyTWA); [Case study, 2025](https://blog.langchain.dev/p/3d2cd58c-13a5-4df9-bd84-7d54ed0ed82c/) | | [Vodafone](https://www.vodafone.com/) | Telecommunications | Code generation; internal search | [Case study, 2025](https://blog.langchain.dev/customers-vodafone/) | +| [WebToon](https://www.webtoons.com/en/) | Media & Entertainment | Data extraction | [Case study, 2025](https://blog.langchain.com/customers-webtoon/) | +| [11x](https://www.11x.ai/) | Software & Technology (GenAI Native) | Research & outreach | [Interrupt talk, 2025](https://youtu.be/fegwPmaAPQk?feature=shared) | From 4abf94846241f3546a0194efd40e109745e7d005 Mon Sep 17 00:00:00 2001 From: lc-arjun Date: Mon, 7 Jul 2025 08:05:46 -0700 Subject: [PATCH 026/129] docs: add -tunnel flag for node server (#5373) add -tunnel flag for node server --- docs/docs/troubleshooting/studio.md | 4 +- libs/sdk-js/client.cjs | 1 + libs/sdk-js/client.d.cts | 1 + libs/sdk-js/client.d.ts | 1 + libs/sdk-js/client.js | 1 + libs/sdk-js/docs/README.md | 26 + libs/sdk-js/docs/auth/README.md | 18 + libs/sdk-js/docs/auth/classes/Auth.md | 75 +++ .../sdk-js/docs/auth/classes/HTTPException.md | 185 +++++++ .../docs/auth/interfaces/AuthEventValueMap.md | 481 ++++++++++++++++++ .../docs/auth/type-aliases/AuthFilters.md | 15 + libs/sdk-js/docs/classes/AssistantsClient.md | 385 ++++++++++++++ libs/sdk-js/docs/classes/Client.md | 98 ++++ libs/sdk-js/docs/classes/CronsClient.md | 151 ++++++ libs/sdk-js/docs/classes/RunsClient.md | 469 +++++++++++++++++ libs/sdk-js/docs/classes/StoreClient.md | 314 ++++++++++++ libs/sdk-js/docs/classes/ThreadsClient.md | 433 ++++++++++++++++ libs/sdk-js/docs/functions/getApiKey.md | 32 ++ libs/sdk-js/docs/interfaces/ClientConfig.md | 57 +++ libs/sdk-js/docs/react/README.md | 18 + libs/sdk-js/docs/react/functions/useStream.md | 27 + .../sdk-js/docs/react/interfaces/UseStream.md | 227 +++++++++ .../docs/react/interfaces/UseStreamOptions.md | 343 +++++++++++++ .../react/type-aliases/MessageMetadata.md | 42 ++ libs/sdk-js/docs/type-aliases/RequestHook.md | 25 + libs/sdk-js/index.cjs | 1 + libs/sdk-js/index.d.cts | 1 + libs/sdk-js/index.d.ts | 1 + libs/sdk-js/index.js | 1 + libs/sdk-js/react.cjs | 1 + libs/sdk-js/react.d.cts | 1 + libs/sdk-js/react.d.ts | 1 + libs/sdk-js/react.js | 1 + 33 files changed, 3435 insertions(+), 2 deletions(-) create mode 100644 libs/sdk-js/client.cjs create mode 100644 libs/sdk-js/client.d.cts create mode 100644 libs/sdk-js/client.d.ts create mode 100644 libs/sdk-js/client.js create mode 100644 libs/sdk-js/docs/README.md create mode 100644 libs/sdk-js/docs/auth/README.md create mode 100644 libs/sdk-js/docs/auth/classes/Auth.md create mode 100644 libs/sdk-js/docs/auth/classes/HTTPException.md create mode 100644 libs/sdk-js/docs/auth/interfaces/AuthEventValueMap.md create mode 100644 libs/sdk-js/docs/auth/type-aliases/AuthFilters.md create mode 100644 libs/sdk-js/docs/classes/AssistantsClient.md create mode 100644 libs/sdk-js/docs/classes/Client.md create mode 100644 libs/sdk-js/docs/classes/CronsClient.md create mode 100644 libs/sdk-js/docs/classes/RunsClient.md create mode 100644 libs/sdk-js/docs/classes/StoreClient.md create mode 100644 libs/sdk-js/docs/classes/ThreadsClient.md create mode 100644 libs/sdk-js/docs/functions/getApiKey.md create mode 100644 libs/sdk-js/docs/interfaces/ClientConfig.md create mode 100644 libs/sdk-js/docs/react/README.md create mode 100644 libs/sdk-js/docs/react/functions/useStream.md create mode 100644 libs/sdk-js/docs/react/interfaces/UseStream.md create mode 100644 libs/sdk-js/docs/react/interfaces/UseStreamOptions.md create mode 100644 libs/sdk-js/docs/react/type-aliases/MessageMetadata.md create mode 100644 libs/sdk-js/docs/type-aliases/RequestHook.md create mode 100644 libs/sdk-js/index.cjs create mode 100644 libs/sdk-js/index.d.cts create mode 100644 libs/sdk-js/index.d.ts create mode 100644 libs/sdk-js/index.js create mode 100644 libs/sdk-js/react.cjs create mode 100644 libs/sdk-js/react.d.cts create mode 100644 libs/sdk-js/react.d.ts create mode 100644 libs/sdk-js/react.js diff --git a/docs/docs/troubleshooting/studio.md b/docs/docs/troubleshooting/studio.md index b06f325de..3fcbdea7f 100644 --- a/docs/docs/troubleshooting/studio.md +++ b/docs/docs/troubleshooting/studio.md @@ -17,7 +17,7 @@ Safari blocks plain-HTTP traffic on localhost. When running Studio with `langgra ```shell # Requires @langchain/langgraph-cli>=0.0.26 - npx @langchain/langgraph-cli dev + npx @langchain/langgraph-cli dev --tunnel ``` The command outputs a URL in this format: @@ -55,7 +55,7 @@ Disable Brave Shields for LangSmith using the Brave icon in the URL bar. ```shell # Requires @langchain/langgraph-cli>=0.0.26 - npx @langchain/langgraph-cli dev + npx @langchain/langgraph-cli dev --tunnel ``` The command outputs a URL in this format: diff --git a/libs/sdk-js/client.cjs b/libs/sdk-js/client.cjs new file mode 100644 index 000000000..680e5bd38 --- /dev/null +++ b/libs/sdk-js/client.cjs @@ -0,0 +1 @@ +module.exports = require('./dist/client.cjs'); \ No newline at end of file diff --git a/libs/sdk-js/client.d.cts b/libs/sdk-js/client.d.cts new file mode 100644 index 000000000..1c03ff9cb --- /dev/null +++ b/libs/sdk-js/client.d.cts @@ -0,0 +1 @@ +export * from './dist/client.js' \ No newline at end of file diff --git a/libs/sdk-js/client.d.ts b/libs/sdk-js/client.d.ts new file mode 100644 index 000000000..1c03ff9cb --- /dev/null +++ b/libs/sdk-js/client.d.ts @@ -0,0 +1 @@ +export * from './dist/client.js' \ No newline at end of file diff --git a/libs/sdk-js/client.js b/libs/sdk-js/client.js new file mode 100644 index 000000000..1c03ff9cb --- /dev/null +++ b/libs/sdk-js/client.js @@ -0,0 +1 @@ +export * from './dist/client.js' \ No newline at end of file diff --git a/libs/sdk-js/docs/README.md b/libs/sdk-js/docs/README.md new file mode 100644 index 000000000..a1627b448 --- /dev/null +++ b/libs/sdk-js/docs/README.md @@ -0,0 +1,26 @@ +**@langchain/langgraph-sdk** + +*** + +# @langchain/langgraph-sdk + +## Classes + +- [AssistantsClient](classes/AssistantsClient.md) +- [Client](classes/Client.md) +- [CronsClient](classes/CronsClient.md) +- [RunsClient](classes/RunsClient.md) +- [StoreClient](classes/StoreClient.md) +- [ThreadsClient](classes/ThreadsClient.md) + +## Interfaces + +- [ClientConfig](interfaces/ClientConfig.md) + +## Type Aliases + +- [RequestHook](type-aliases/RequestHook.md) + +## Functions + +- [getApiKey](functions/getApiKey.md) diff --git a/libs/sdk-js/docs/auth/README.md b/libs/sdk-js/docs/auth/README.md new file mode 100644 index 000000000..351cb8490 --- /dev/null +++ b/libs/sdk-js/docs/auth/README.md @@ -0,0 +1,18 @@ +**@langchain/langgraph-sdk** + +*** + +# @langchain/langgraph-sdk/auth + +## Classes + +- [Auth](classes/Auth.md) +- [HTTPException](classes/HTTPException.md) + +## Interfaces + +- [AuthEventValueMap](interfaces/AuthEventValueMap.md) + +## Type Aliases + +- [AuthFilters](type-aliases/AuthFilters.md) diff --git a/libs/sdk-js/docs/auth/classes/Auth.md b/libs/sdk-js/docs/auth/classes/Auth.md new file mode 100644 index 000000000..4b4cc618a --- /dev/null +++ b/libs/sdk-js/docs/auth/classes/Auth.md @@ -0,0 +1,75 @@ +[**@langchain/langgraph-sdk**](../README.md) + +*** + +[@langchain/langgraph-sdk](../README.md) / Auth + +# Class: Auth\ + +Defined in: [src/auth/index.ts:11](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/index.ts#L11) + +## Type Parameters + +• **TExtra** = \{\} + +• **TAuthReturn** *extends* `BaseAuthReturn` = `BaseAuthReturn` + +• **TUser** *extends* `BaseUser` = `ToUserLike`\<`TAuthReturn`\> + +## Constructors + +### new Auth() + +> **new Auth**\<`TExtra`, `TAuthReturn`, `TUser`\>(): [`Auth`](Auth.md)\<`TExtra`, `TAuthReturn`, `TUser`\> + +#### Returns + +[`Auth`](Auth.md)\<`TExtra`, `TAuthReturn`, `TUser`\> + +## Methods + +### authenticate() + +> **authenticate**\<`T`\>(`cb`): [`Auth`](Auth.md)\<`TExtra`, `T`\> + +Defined in: [src/auth/index.ts:25](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/index.ts#L25) + +#### Type Parameters + +• **T** *extends* `BaseAuthReturn` + +#### Parameters + +##### cb + +`AuthenticateCallback`\<`T`\> + +#### Returns + +[`Auth`](Auth.md)\<`TExtra`, `T`\> + +*** + +### on() + +> **on**\<`T`\>(`event`, `callback`): `this` + +Defined in: [src/auth/index.ts:32](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/index.ts#L32) + +#### Type Parameters + +• **T** *extends* `CallbackEvent` + +#### Parameters + +##### event + +`T` + +##### callback + +`OnCallback`\<`T`, `TUser`\> + +#### Returns + +`this` diff --git a/libs/sdk-js/docs/auth/classes/HTTPException.md b/libs/sdk-js/docs/auth/classes/HTTPException.md new file mode 100644 index 000000000..0db191af5 --- /dev/null +++ b/libs/sdk-js/docs/auth/classes/HTTPException.md @@ -0,0 +1,185 @@ +[**@langchain/langgraph-sdk**](../README.md) + +*** + +[@langchain/langgraph-sdk](../README.md) / HTTPException + +# Class: HTTPException + +Defined in: [src/auth/error.ts:66](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/error.ts#L66) + +## Extends + +- `Error` + +## Constructors + +### new HTTPException() + +> **new HTTPException**(`status`, `options`?): [`HTTPException`](HTTPException.md) + +Defined in: [src/auth/error.ts:70](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/error.ts#L70) + +#### Parameters + +##### status + +`number` + +##### options? + +###### cause? + +`unknown` + +###### headers? + +`HeadersInit` + +###### message? + +`string` + +#### Returns + +[`HTTPException`](HTTPException.md) + +#### Overrides + +`Error.constructor` + +## Properties + +### cause? + +> `optional` **cause**: `unknown` + +Defined in: node\_modules/typescript/lib/lib.es2022.error.d.ts:24 + +#### Inherited from + +`Error.cause` + +*** + +### headers + +> **headers**: `HeadersInit` + +Defined in: [src/auth/error.ts:68](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/error.ts#L68) + +*** + +### message + +> **message**: `string` + +Defined in: node\_modules/typescript/lib/lib.es5.d.ts:1077 + +#### Inherited from + +`Error.message` + +*** + +### name + +> **name**: `string` + +Defined in: node\_modules/typescript/lib/lib.es5.d.ts:1076 + +#### Inherited from + +`Error.name` + +*** + +### stack? + +> `optional` **stack**: `string` + +Defined in: node\_modules/typescript/lib/lib.es5.d.ts:1078 + +#### Inherited from + +`Error.stack` + +*** + +### status + +> **status**: `number` + +Defined in: [src/auth/error.ts:67](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/error.ts#L67) + +*** + +### prepareStackTrace()? + +> `static` `optional` **prepareStackTrace**: (`err`, `stackTraces`) => `any` + +Defined in: node\_modules/@types/node/globals.d.ts:28 + +Optional override for formatting stack traces + +#### Parameters + +##### err + +`Error` + +##### stackTraces + +`CallSite`[] + +#### Returns + +`any` + +#### See + +https://v8.dev/docs/stack-trace-api#customizing-stack-traces + +#### Inherited from + +`Error.prepareStackTrace` + +*** + +### stackTraceLimit + +> `static` **stackTraceLimit**: `number` + +Defined in: node\_modules/@types/node/globals.d.ts:30 + +#### Inherited from + +`Error.stackTraceLimit` + +## Methods + +### captureStackTrace() + +> `static` **captureStackTrace**(`targetObject`, `constructorOpt`?): `void` + +Defined in: node\_modules/@types/node/globals.d.ts:21 + +Create .stack property on a target object + +#### Parameters + +##### targetObject + +`object` + +##### constructorOpt? + +`Function` + +#### Returns + +`void` + +#### Inherited from + +`Error.captureStackTrace` diff --git a/libs/sdk-js/docs/auth/interfaces/AuthEventValueMap.md b/libs/sdk-js/docs/auth/interfaces/AuthEventValueMap.md new file mode 100644 index 000000000..686e1a39b --- /dev/null +++ b/libs/sdk-js/docs/auth/interfaces/AuthEventValueMap.md @@ -0,0 +1,481 @@ +[**@langchain/langgraph-sdk**](../README.md) + +*** + +[@langchain/langgraph-sdk](../README.md) / AuthEventValueMap + +# Interface: AuthEventValueMap + +Defined in: [src/auth/types.ts:218](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L218) + +## Properties + +### assistants:create + +> **assistants:create**: `object` + +Defined in: [src/auth/types.ts:226](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L226) + +#### assistant\_id? + +> `optional` **assistant\_id**: `Maybe`\<`string`\> + +#### config? + +> `optional` **config**: `Maybe`\<`AssistantConfig`\> + +#### graph\_id + +> **graph\_id**: `string` + +#### if\_exists? + +> `optional` **if\_exists**: `Maybe`\<`"raise"` \| `"do_nothing"`\> + +#### metadata? + +> `optional` **metadata**: `Maybe`\<`Record`\<`string`, `unknown`\>\> + +#### name? + +> `optional` **name**: `Maybe`\<`string`\> + +*** + +### assistants:delete + +> **assistants:delete**: `object` + +Defined in: [src/auth/types.ts:229](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L229) + +#### assistant\_id + +> **assistant\_id**: `string` + +*** + +### assistants:read + +> **assistants:read**: `object` + +Defined in: [src/auth/types.ts:227](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L227) + +#### assistant\_id + +> **assistant\_id**: `string` + +#### metadata? + +> `optional` **metadata**: `Maybe`\<`Record`\<`string`, `unknown`\>\> + +*** + +### assistants:search + +> **assistants:search**: `object` + +Defined in: [src/auth/types.ts:230](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L230) + +#### graph\_id? + +> `optional` **graph\_id**: `Maybe`\<`string`\> + +#### limit? + +> `optional` **limit**: `Maybe`\<`number`\> + +#### metadata? + +> `optional` **metadata**: `Maybe`\<`Record`\<`string`, `unknown`\>\> + +#### offset? + +> `optional` **offset**: `Maybe`\<`number`\> + +*** + +### assistants:update + +> **assistants:update**: `object` + +Defined in: [src/auth/types.ts:228](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L228) + +#### assistant\_id + +> **assistant\_id**: `string` + +#### config? + +> `optional` **config**: `Maybe`\<`AssistantConfig`\> + +#### graph\_id? + +> `optional` **graph\_id**: `Maybe`\<`string`\> + +#### metadata? + +> `optional` **metadata**: `Maybe`\<`Record`\<`string`, `unknown`\>\> + +#### name? + +> `optional` **name**: `Maybe`\<`string`\> + +#### version? + +> `optional` **version**: `Maybe`\<`number`\> + +*** + +### crons:create + +> **crons:create**: `object` + +Defined in: [src/auth/types.ts:232](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L232) + +#### cron\_id? + +> `optional` **cron\_id**: `Maybe`\<`string`\> + +#### end\_time? + +> `optional` **end\_time**: `Maybe`\<`string`\> + +#### payload? + +> `optional` **payload**: `Maybe`\<`Record`\<`string`, `unknown`\>\> + +#### schedule + +> **schedule**: `string` + +#### thread\_id? + +> `optional` **thread\_id**: `Maybe`\<`string`\> + +#### user\_id? + +> `optional` **user\_id**: `Maybe`\<`string`\> + +*** + +### crons:delete + +> **crons:delete**: `object` + +Defined in: [src/auth/types.ts:235](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L235) + +#### cron\_id + +> **cron\_id**: `string` + +*** + +### crons:read + +> **crons:read**: `object` + +Defined in: [src/auth/types.ts:233](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L233) + +#### cron\_id + +> **cron\_id**: `string` + +*** + +### crons:search + +> **crons:search**: `object` + +Defined in: [src/auth/types.ts:236](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L236) + +#### assistant\_id? + +> `optional` **assistant\_id**: `Maybe`\<`string`\> + +#### limit? + +> `optional` **limit**: `Maybe`\<`number`\> + +#### offset? + +> `optional` **offset**: `Maybe`\<`number`\> + +#### thread\_id? + +> `optional` **thread\_id**: `Maybe`\<`string`\> + +*** + +### crons:update + +> **crons:update**: `object` + +Defined in: [src/auth/types.ts:234](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L234) + +#### cron\_id + +> **cron\_id**: `string` + +#### payload? + +> `optional` **payload**: `Maybe`\<`Record`\<`string`, `unknown`\>\> + +#### schedule? + +> `optional` **schedule**: `Maybe`\<`string`\> + +*** + +### store:delete + +> **store:delete**: `object` + +Defined in: [src/auth/types.ts:242](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L242) + +#### key + +> **key**: `string` + +#### namespace? + +> `optional` **namespace**: `Maybe`\<`string`[]\> + +*** + +### store:get + +> **store:get**: `object` + +Defined in: [src/auth/types.ts:239](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L239) + +#### key + +> **key**: `string` + +#### namespace + +> **namespace**: `Maybe`\<`string`[]\> + +*** + +### store:list\_namespaces + +> **store:list\_namespaces**: `object` + +Defined in: [src/auth/types.ts:241](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L241) + +#### limit? + +> `optional` **limit**: `Maybe`\<`number`\> + +#### max\_depth? + +> `optional` **max\_depth**: `Maybe`\<`number`\> + +#### namespace? + +> `optional` **namespace**: `Maybe`\<`string`[]\> + +#### offset? + +> `optional` **offset**: `Maybe`\<`number`\> + +#### suffix? + +> `optional` **suffix**: `Maybe`\<`string`[]\> + +*** + +### store:put + +> **store:put**: `object` + +Defined in: [src/auth/types.ts:238](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L238) + +#### key + +> **key**: `string` + +#### namespace + +> **namespace**: `string`[] + +#### value + +> **value**: `Record`\<`string`, `unknown`\> + +*** + +### store:search + +> **store:search**: `object` + +Defined in: [src/auth/types.ts:240](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L240) + +#### filter? + +> `optional` **filter**: `Maybe`\<`Record`\<`string`, `unknown`\>\> + +#### limit? + +> `optional` **limit**: `Maybe`\<`number`\> + +#### namespace? + +> `optional` **namespace**: `Maybe`\<`string`[]\> + +#### offset? + +> `optional` **offset**: `Maybe`\<`number`\> + +#### query? + +> `optional` **query**: `Maybe`\<`string`\> + +*** + +### threads:create + +> **threads:create**: `object` + +Defined in: [src/auth/types.ts:219](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L219) + +#### if\_exists? + +> `optional` **if\_exists**: `Maybe`\<`"raise"` \| `"do_nothing"`\> + +#### metadata? + +> `optional` **metadata**: `Maybe`\<`Record`\<`string`, `unknown`\>\> + +#### thread\_id? + +> `optional` **thread\_id**: `Maybe`\<`string`\> + +*** + +### threads:create\_run + +> **threads:create\_run**: `object` + +Defined in: [src/auth/types.ts:224](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L224) + +#### after\_seconds? + +> `optional` **after\_seconds**: `Maybe`\<`number`\> + +#### assistant\_id + +> **assistant\_id**: `string` + +#### if\_not\_exists? + +> `optional` **if\_not\_exists**: `Maybe`\<`"reject"` \| `"create"`\> + +#### kwargs + +> **kwargs**: `Record`\<`string`, `unknown`\> + +#### metadata? + +> `optional` **metadata**: `Maybe`\<`Record`\<`string`, `unknown`\>\> + +#### multitask\_strategy? + +> `optional` **multitask\_strategy**: `Maybe`\<`"reject"` \| `"interrupt"` \| `"rollback"` \| `"enqueue"`\> + +#### prevent\_insert\_if\_inflight? + +> `optional` **prevent\_insert\_if\_inflight**: `Maybe`\<`boolean`\> + +#### run\_id + +> **run\_id**: `string` + +#### status + +> **status**: `Maybe`\<`"pending"` \| `"running"` \| `"error"` \| `"success"` \| `"timeout"` \| `"interrupted"`\> + +#### thread\_id? + +> `optional` **thread\_id**: `Maybe`\<`string`\> + +*** + +### threads:delete + +> **threads:delete**: `object` + +Defined in: [src/auth/types.ts:222](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L222) + +#### run\_id? + +> `optional` **run\_id**: `Maybe`\<`string`\> + +#### thread\_id? + +> `optional` **thread\_id**: `Maybe`\<`string`\> + +*** + +### threads:read + +> **threads:read**: `object` + +Defined in: [src/auth/types.ts:220](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L220) + +#### thread\_id? + +> `optional` **thread\_id**: `Maybe`\<`string`\> + +*** + +### threads:search + +> **threads:search**: `object` + +Defined in: [src/auth/types.ts:223](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L223) + +#### limit? + +> `optional` **limit**: `Maybe`\<`number`\> + +#### metadata? + +> `optional` **metadata**: `Maybe`\<`Record`\<`string`, `unknown`\>\> + +#### offset? + +> `optional` **offset**: `Maybe`\<`number`\> + +#### status? + +> `optional` **status**: `Maybe`\<`"error"` \| `"interrupted"` \| `"idle"` \| `"busy"` \| `string` & `object`\> + +#### thread\_id? + +> `optional` **thread\_id**: `Maybe`\<`string`\> + +#### values? + +> `optional` **values**: `Maybe`\<`Record`\<`string`, `unknown`\>\> + +*** + +### threads:update + +> **threads:update**: `object` + +Defined in: [src/auth/types.ts:221](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L221) + +#### action? + +> `optional` **action**: `Maybe`\<`"interrupt"` \| `"rollback"`\> + +#### metadata? + +> `optional` **metadata**: `Maybe`\<`Record`\<`string`, `unknown`\>\> + +#### thread\_id? + +> `optional` **thread\_id**: `Maybe`\<`string`\> diff --git a/libs/sdk-js/docs/auth/type-aliases/AuthFilters.md b/libs/sdk-js/docs/auth/type-aliases/AuthFilters.md new file mode 100644 index 000000000..b9b2e1fb2 --- /dev/null +++ b/libs/sdk-js/docs/auth/type-aliases/AuthFilters.md @@ -0,0 +1,15 @@ +[**@langchain/langgraph-sdk**](../README.md) + +*** + +[@langchain/langgraph-sdk](../README.md) / AuthFilters + +# Type Alias: AuthFilters\ + +> **AuthFilters**\<`TKey`\>: \{ \[key in TKey\]: string \| \{ \[op in "$contains" \| "$eq"\]?: string \} \} + +Defined in: [src/auth/types.ts:367](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L367) + +## Type Parameters + +• **TKey** *extends* `string` \| `number` \| `symbol` diff --git a/libs/sdk-js/docs/classes/AssistantsClient.md b/libs/sdk-js/docs/classes/AssistantsClient.md new file mode 100644 index 000000000..571dc16e8 --- /dev/null +++ b/libs/sdk-js/docs/classes/AssistantsClient.md @@ -0,0 +1,385 @@ +[**@langchain/langgraph-sdk**](../README.md) + +*** + +[@langchain/langgraph-sdk](../README.md) / AssistantsClient + +# Class: AssistantsClient + +Defined in: [client.ts:431](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L431) + +## Extends + +- `BaseClient` + +## Constructors + +### new AssistantsClient() + +> **new AssistantsClient**(`config`?): [`AssistantsClient`](AssistantsClient.md) + +Defined in: [client.ts:183](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L183) + +#### Parameters + +##### config? + +[`ClientConfig`](../interfaces/ClientConfig.md) + +#### Returns + +[`AssistantsClient`](AssistantsClient.md) + +#### Inherited from + +`BaseClient.constructor` + +## Methods + +### create() + +> **create**(`payload`): `Promise`\<`Assistant`\> + +Defined in: [client.ts:496](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L496) + +Create a new assistant. + +#### Parameters + +##### payload + +Payload for creating an assistant. + +###### assistantId? + +`string` + +###### config? + +`Config` + +###### description? + +`string` + +###### graphId + +`string` + +###### ifExists? + +`OnConflictBehavior` + +###### metadata? + +`Metadata` + +###### name? + +`string` + +#### Returns + +`Promise`\<`Assistant`\> + +The created assistant. + +*** + +### delete() + +> **delete**(`assistantId`): `Promise`\<`void`\> + +Defined in: [client.ts:552](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L552) + +Delete an assistant. + +#### Parameters + +##### assistantId + +`string` + +ID of the assistant. + +#### Returns + +`Promise`\<`void`\> + +*** + +### get() + +> **get**(`assistantId`): `Promise`\<`Assistant`\> + +Defined in: [client.ts:438](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L438) + +Get an assistant by ID. + +#### Parameters + +##### assistantId + +`string` + +The ID of the assistant. + +#### Returns + +`Promise`\<`Assistant`\> + +Assistant + +*** + +### getGraph() + +> **getGraph**(`assistantId`, `options`?): `Promise`\<`AssistantGraph`\> + +Defined in: [client.ts:448](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L448) + +Get the JSON representation of the graph assigned to a runnable + +#### Parameters + +##### assistantId + +`string` + +The ID of the assistant. + +##### options? + +###### xray? + +`number` \| `boolean` + +Whether to include subgraphs in the serialized graph representation. If an integer value is provided, only subgraphs with a depth less than or equal to the value will be included. + +#### Returns + +`Promise`\<`AssistantGraph`\> + +Serialized graph + +*** + +### getSchemas() + +> **getSchemas**(`assistantId`): `Promise`\<`GraphSchema`\> + +Defined in: [client.ts:462](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L462) + +Get the state and config schema of the graph assigned to a runnable + +#### Parameters + +##### assistantId + +`string` + +The ID of the assistant. + +#### Returns + +`Promise`\<`GraphSchema`\> + +Graph schema + +*** + +### getSubgraphs() + +> **getSubgraphs**(`assistantId`, `options`?): `Promise`\<`Subgraphs`\> + +Defined in: [client.ts:473](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L473) + +Get the schemas of an assistant by ID. + +#### Parameters + +##### assistantId + +`string` + +The ID of the assistant to get the schema of. + +##### options? + +Additional options for getting subgraphs, such as namespace or recursion extraction. + +###### namespace? + +`string` + +###### recurse? + +`boolean` + +#### Returns + +`Promise`\<`Subgraphs`\> + +The subgraphs of the assistant. + +*** + +### getVersions() + +> **getVersions**(`assistantId`, `payload`?): `Promise`\<`AssistantVersion`[]\> + +Defined in: [client.ts:590](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L590) + +List all versions of an assistant. + +#### Parameters + +##### assistantId + +`string` + +ID of the assistant. + +##### payload? + +###### limit? + +`number` + +###### metadata? + +`Metadata` + +###### offset? + +`number` + +#### Returns + +`Promise`\<`AssistantVersion`[]\> + +List of assistant versions. + +*** + +### search() + +> **search**(`query`?): `Promise`\<`Assistant`[]\> + +Defined in: [client.ts:563](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L563) + +List assistants. + +#### Parameters + +##### query? + +Query options. + +###### graphId? + +`string` + +###### limit? + +`number` + +###### metadata? + +`Metadata` + +###### offset? + +`number` + +###### sortBy? + +`AssistantSortBy` + +###### sortOrder? + +`SortOrder` + +#### Returns + +`Promise`\<`Assistant`[]\> + +List of assistants. + +*** + +### setLatest() + +> **setLatest**(`assistantId`, `version`): `Promise`\<`Assistant`\> + +Defined in: [client.ts:618](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L618) + +Change the version of an assistant. + +#### Parameters + +##### assistantId + +`string` + +ID of the assistant. + +##### version + +`number` + +The version to change to. + +#### Returns + +`Promise`\<`Assistant`\> + +The updated assistant. + +*** + +### update() + +> **update**(`assistantId`, `payload`): `Promise`\<`Assistant`\> + +Defined in: [client.ts:525](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L525) + +Update an assistant. + +#### Parameters + +##### assistantId + +`string` + +ID of the assistant. + +##### payload + +Payload for updating the assistant. + +###### config? + +`Config` + +###### description? + +`string` + +###### graphId? + +`string` + +###### metadata? + +`Metadata` + +###### name? + +`string` + +#### Returns + +`Promise`\<`Assistant`\> + +The updated assistant. diff --git a/libs/sdk-js/docs/classes/Client.md b/libs/sdk-js/docs/classes/Client.md new file mode 100644 index 000000000..b0afc23de --- /dev/null +++ b/libs/sdk-js/docs/classes/Client.md @@ -0,0 +1,98 @@ +[**@langchain/langgraph-sdk**](../README.md) + +*** + +[@langchain/langgraph-sdk](../README.md) / Client + +# Class: Client\ + +Defined in: [client.ts:1620](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1620) + +## Type Parameters + +• **TStateType** = `DefaultValues` + +• **TUpdateType** = `TStateType` + +• **TCustomEventType** = `unknown` + +## Constructors + +### new Client() + +> **new Client**\<`TStateType`, `TUpdateType`, `TCustomEventType`\>(`config`?): [`Client`](Client.md)\<`TStateType`, `TUpdateType`, `TCustomEventType`\> + +Defined in: [client.ts:1656](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1656) + +#### Parameters + +##### config? + +[`ClientConfig`](../interfaces/ClientConfig.md) + +#### Returns + +[`Client`](Client.md)\<`TStateType`, `TUpdateType`, `TCustomEventType`\> + +## Properties + +### ~ui + +> **~ui**: `UiClient` + +Defined in: [client.ts:1654](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1654) + +**`Internal`** + +The client for interacting with the UI. + Used by LoadExternalComponent and the API might change in the future. + +*** + +### assistants + +> **assistants**: [`AssistantsClient`](AssistantsClient.md) + +Defined in: [client.ts:1628](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1628) + +The client for interacting with assistants. + +*** + +### crons + +> **crons**: [`CronsClient`](CronsClient.md) + +Defined in: [client.ts:1643](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1643) + +The client for interacting with cron runs. + +*** + +### runs + +> **runs**: [`RunsClient`](RunsClient.md)\<`TStateType`, `TUpdateType`, `TCustomEventType`\> + +Defined in: [client.ts:1638](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1638) + +The client for interacting with runs. + +*** + +### store + +> **store**: [`StoreClient`](StoreClient.md) + +Defined in: [client.ts:1648](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1648) + +The client for interacting with the KV store. + +*** + +### threads + +> **threads**: [`ThreadsClient`](ThreadsClient.md)\<`TStateType`, `TUpdateType`\> + +Defined in: [client.ts:1633](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1633) + +The client for interacting with threads. diff --git a/libs/sdk-js/docs/classes/CronsClient.md b/libs/sdk-js/docs/classes/CronsClient.md new file mode 100644 index 000000000..ae0017d9c --- /dev/null +++ b/libs/sdk-js/docs/classes/CronsClient.md @@ -0,0 +1,151 @@ +[**@langchain/langgraph-sdk**](../README.md) + +*** + +[@langchain/langgraph-sdk](../README.md) / CronsClient + +# Class: CronsClient + +Defined in: [client.ts:334](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L334) + +## Extends + +- `BaseClient` + +## Constructors + +### new CronsClient() + +> **new CronsClient**(`config`?): [`CronsClient`](CronsClient.md) + +Defined in: [client.ts:183](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L183) + +#### Parameters + +##### config? + +[`ClientConfig`](../interfaces/ClientConfig.md) + +#### Returns + +[`CronsClient`](CronsClient.md) + +#### Inherited from + +`BaseClient.constructor` + +## Methods + +### create() + +> **create**(`assistantId`, `payload`?): `Promise`\<`CronCreateResponse`\> + +Defined in: [client.ts:375](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L375) + +#### Parameters + +##### assistantId + +`string` + +Assistant ID to use for this cron job. + +##### payload? + +`CronsCreatePayload` + +Payload for creating a cron job. + +#### Returns + +`Promise`\<`CronCreateResponse`\> + +*** + +### createForThread() + +> **createForThread**(`threadId`, `assistantId`, `payload`?): `Promise`\<`CronCreateForThreadResponse`\> + +Defined in: [client.ts:342](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L342) + +#### Parameters + +##### threadId + +`string` + +The ID of the thread. + +##### assistantId + +`string` + +Assistant ID to use for this cron job. + +##### payload? + +`CronsCreatePayload` + +Payload for creating a cron job. + +#### Returns + +`Promise`\<`CronCreateForThreadResponse`\> + +The created background run. + +*** + +### delete() + +> **delete**(`cronId`): `Promise`\<`void`\> + +Defined in: [client.ts:402](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L402) + +#### Parameters + +##### cronId + +`string` + +Cron ID of Cron job to delete. + +#### Returns + +`Promise`\<`void`\> + +*** + +### search() + +> **search**(`query`?): `Promise`\<`Cron`[]\> + +Defined in: [client.ts:413](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L413) + +#### Parameters + +##### query? + +Query options. + +###### assistantId? + +`string` + +###### limit? + +`number` + +###### offset? + +`number` + +###### threadId? + +`string` + +#### Returns + +`Promise`\<`Cron`[]\> + +List of crons. diff --git a/libs/sdk-js/docs/classes/RunsClient.md b/libs/sdk-js/docs/classes/RunsClient.md new file mode 100644 index 000000000..15f666453 --- /dev/null +++ b/libs/sdk-js/docs/classes/RunsClient.md @@ -0,0 +1,469 @@ +[**@langchain/langgraph-sdk**](../README.md) + +*** + +[@langchain/langgraph-sdk](../README.md) / RunsClient + +# Class: RunsClient\ + +Defined in: [client.ts:912](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L912) + +## Extends + +- `BaseClient` + +## Type Parameters + +• **TStateType** = `DefaultValues` + +• **TUpdateType** = `TStateType` + +• **TCustomEventType** = `unknown` + +## Constructors + +### new RunsClient() + +> **new RunsClient**\<`TStateType`, `TUpdateType`, `TCustomEventType`\>(`config`?): [`RunsClient`](RunsClient.md)\<`TStateType`, `TUpdateType`, `TCustomEventType`\> + +Defined in: [client.ts:183](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L183) + +#### Parameters + +##### config? + +[`ClientConfig`](../interfaces/ClientConfig.md) + +#### Returns + +[`RunsClient`](RunsClient.md)\<`TStateType`, `TUpdateType`, `TCustomEventType`\> + +#### Inherited from + +`BaseClient.constructor` + +## Methods + +### cancel() + +> **cancel**(`threadId`, `runId`, `wait`, `action`): `Promise`\<`void`\> + +Defined in: [client.ts:1227](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1227) + +Cancel a run. + +#### Parameters + +##### threadId + +`string` + +The ID of the thread. + +##### runId + +`string` + +The ID of the run. + +##### wait + +`boolean` = `false` + +Whether to block when canceling + +##### action + +`CancelAction` = `"interrupt"` + +Action to take when cancelling the run. Possible values are `interrupt` or `rollback`. Default is `interrupt`. + +#### Returns + +`Promise`\<`void`\> + +*** + +### create() + +> **create**(`threadId`, `assistantId`, `payload`?): `Promise`\<`Run`\> + +Defined in: [client.ts:1026](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1026) + +Create a run. + +#### Parameters + +##### threadId + +`string` + +The ID of the thread. + +##### assistantId + +`string` + +Assistant ID to use for this run. + +##### payload? + +`RunsCreatePayload` + +Payload for creating a run. + +#### Returns + +`Promise`\<`Run`\> + +The created run. + +*** + +### createBatch() + +> **createBatch**(`payloads`): `Promise`\<`Run`[]\> + +Defined in: [client.ts:1076](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1076) + +Create a batch of stateless background runs. + +#### Parameters + +##### payloads + +`RunsCreatePayload` & `object`[] + +An array of payloads for creating runs. + +#### Returns + +`Promise`\<`Run`[]\> + +An array of created runs. + +*** + +### delete() + +> **delete**(`threadId`, `runId`): `Promise`\<`void`\> + +Defined in: [client.ts:1329](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1329) + +Delete a run. + +#### Parameters + +##### threadId + +`string` + +The ID of the thread. + +##### runId + +`string` + +The ID of the run. + +#### Returns + +`Promise`\<`void`\> + +*** + +### get() + +> **get**(`threadId`, `runId`): `Promise`\<`Run`\> + +Defined in: [client.ts:1214](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1214) + +Get a run by ID. + +#### Parameters + +##### threadId + +`string` + +The ID of the thread. + +##### runId + +`string` + +The ID of the run. + +#### Returns + +`Promise`\<`Run`\> + +The run. + +*** + +### join() + +> **join**(`threadId`, `runId`, `options`?): `Promise`\<`void`\> + +Defined in: [client.ts:1249](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1249) + +Block until a run is done. + +#### Parameters + +##### threadId + +`string` + +The ID of the thread. + +##### runId + +`string` + +The ID of the run. + +##### options? + +###### signal? + +`AbortSignal` + +#### Returns + +`Promise`\<`void`\> + +*** + +### joinStream() + +> **joinStream**(`threadId`, `runId`, `options`?): `AsyncGenerator`\<\{ `data`: `any`; `event`: `StreamEvent`; `id`: `string`; \}\> + +Defined in: [client.ts:1274](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1274) + +Stream output from a run in real-time, until the run is done. + +#### Parameters + +##### threadId + +The ID of the thread. Can be set to `null` | `undefined` for stateless runs. + +`undefined` | `null` | `string` + +##### runId + +`string` + +The ID of the run. + +##### options? + +Additional options for controlling the stream behavior: + - signal: An AbortSignal that can be used to cancel the stream request + - lastEventId: The ID of the last event received. Can be used to reconnect to a stream without losing events. + - cancelOnDisconnect: When true, automatically cancels the run if the client disconnects from the stream + - streamMode: Controls what types of events to receive from the stream (can be a single mode or array of modes) + Must be a subset of the stream modes passed when creating the run. Background runs default to having the union of all + stream modes enabled. + +`AbortSignal` | \{ `cancelOnDisconnect`: `boolean`; `lastEventId`: `string`; `signal`: `AbortSignal`; `streamMode`: `StreamMode` \| `StreamMode`[]; \} + +#### Returns + +`AsyncGenerator`\<\{ `data`: `any`; `event`: `StreamEvent`; `id`: `string`; \}\> + +An async generator yielding stream parts. + +*** + +### list() + +> **list**(`threadId`, `options`?): `Promise`\<`Run`[]\> + +Defined in: [client.ts:1177](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1177) + +List all runs for a thread. + +#### Parameters + +##### threadId + +`string` + +The ID of the thread. + +##### options? + +Filtering and pagination options. + +###### limit? + +`number` + +Maximum number of runs to return. +Defaults to 10 + +###### offset? + +`number` + +Offset to start from. +Defaults to 0. + +###### status? + +`RunStatus` + +Status of the run to filter by. + +#### Returns + +`Promise`\<`Run`[]\> + +List of runs. + +*** + +### stream() + +Create a run and stream the results. + +#### Param + +The ID of the thread. + +#### Param + +Assistant ID to use for this run. + +#### Param + +Payload for creating a run. + +#### Call Signature + +> **stream**\<`TStreamMode`, `TSubgraphs`\>(`threadId`, `assistantId`, `payload`?): `TypedAsyncGenerator`\<`TStreamMode`, `TSubgraphs`, `TStateType`, `TUpdateType`, `TCustomEventType`\> + +Defined in: [client.ts:917](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L917) + +##### Type Parameters + +• **TStreamMode** *extends* `StreamMode` \| `StreamMode`[] = `StreamMode` + +• **TSubgraphs** *extends* `boolean` = `false` + +##### Parameters + +###### threadId + +`null` + +###### assistantId + +`string` + +###### payload? + +`Omit`\<`RunsStreamPayload`\<`TStreamMode`, `TSubgraphs`\>, `"multitaskStrategy"` \| `"onCompletion"`\> + +##### Returns + +`TypedAsyncGenerator`\<`TStreamMode`, `TSubgraphs`, `TStateType`, `TUpdateType`, `TCustomEventType`\> + +#### Call Signature + +> **stream**\<`TStreamMode`, `TSubgraphs`\>(`threadId`, `assistantId`, `payload`?): `TypedAsyncGenerator`\<`TStreamMode`, `TSubgraphs`, `TStateType`, `TUpdateType`, `TCustomEventType`\> + +Defined in: [client.ts:935](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L935) + +##### Type Parameters + +• **TStreamMode** *extends* `StreamMode` \| `StreamMode`[] = `StreamMode` + +• **TSubgraphs** *extends* `boolean` = `false` + +##### Parameters + +###### threadId + +`string` + +###### assistantId + +`string` + +###### payload? + +`RunsStreamPayload`\<`TStreamMode`, `TSubgraphs`\> + +##### Returns + +`TypedAsyncGenerator`\<`TStreamMode`, `TSubgraphs`, `TStateType`, `TUpdateType`, `TCustomEventType`\> + +*** + +### wait() + +Create a run and wait for it to complete. + +#### Param + +The ID of the thread. + +#### Param + +Assistant ID to use for this run. + +#### Param + +Payload for creating a run. + +#### Call Signature + +> **wait**(`threadId`, `assistantId`, `payload`?): `Promise`\<`DefaultValues`\> + +Defined in: [client.ts:1093](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1093) + +##### Parameters + +###### threadId + +`null` + +###### assistantId + +`string` + +###### payload? + +`Omit`\<`RunsWaitPayload`, `"multitaskStrategy"` \| `"onCompletion"`\> + +##### Returns + +`Promise`\<`DefaultValues`\> + +#### Call Signature + +> **wait**(`threadId`, `assistantId`, `payload`?): `Promise`\<`DefaultValues`\> + +Defined in: [client.ts:1099](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1099) + +##### Parameters + +###### threadId + +`string` + +###### assistantId + +`string` + +###### payload? + +`RunsWaitPayload` + +##### Returns + +`Promise`\<`DefaultValues`\> diff --git a/libs/sdk-js/docs/classes/StoreClient.md b/libs/sdk-js/docs/classes/StoreClient.md new file mode 100644 index 000000000..97e223da3 --- /dev/null +++ b/libs/sdk-js/docs/classes/StoreClient.md @@ -0,0 +1,314 @@ +[**@langchain/langgraph-sdk**](../README.md) + +*** + +[@langchain/langgraph-sdk](../README.md) / StoreClient + +# Class: StoreClient + +Defined in: [client.ts:1347](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1347) + +## Extends + +- `BaseClient` + +## Constructors + +### new StoreClient() + +> **new StoreClient**(`config`?): [`StoreClient`](StoreClient.md) + +Defined in: [client.ts:183](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L183) + +#### Parameters + +##### config? + +[`ClientConfig`](../interfaces/ClientConfig.md) + +#### Returns + +[`StoreClient`](StoreClient.md) + +#### Inherited from + +`BaseClient.constructor` + +## Methods + +### deleteItem() + +> **deleteItem**(`namespace`, `key`): `Promise`\<`void`\> + +Defined in: [client.ts:1468](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1468) + +Delete an item. + +#### Parameters + +##### namespace + +`string`[] + +A list of strings representing the namespace path. + +##### key + +`string` + +The unique identifier for the item. + +#### Returns + +`Promise`\<`void`\> + +Promise + +*** + +### getItem() + +> **getItem**(`namespace`, `key`, `options`?): `Promise`\<`null` \| `Item`\> + +Defined in: [client.ts:1424](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1424) + +Retrieve a single item. + +#### Parameters + +##### namespace + +`string`[] + +A list of strings representing the namespace path. + +##### key + +`string` + +The unique identifier for the item. + +##### options? + +###### refreshTtl? + +`null` \| `boolean` + +Whether to refresh the TTL on this read operation. If null, uses the store's default behavior. + +#### Returns + +`Promise`\<`null` \| `Item`\> + +Promise + +#### Example + +```typescript +const item = await client.store.getItem( + ["documents", "user123"], + "item456", + { refreshTtl: true } +); +console.log(item); +// { +// namespace: ["documents", "user123"], +// key: "item456", +// value: { title: "My Document", content: "Hello World" }, +// createdAt: "2024-07-30T12:00:00Z", +// updatedAt: "2024-07-30T12:00:00Z" +// } +``` + +*** + +### listNamespaces() + +> **listNamespaces**(`options`?): `Promise`\<`ListNamespaceResponse`\> + +Defined in: [client.ts:1564](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1564) + +List namespaces with optional match conditions. + +#### Parameters + +##### options? + +###### limit? + +`number` + +Maximum number of namespaces to return (default is 100). + +###### maxDepth? + +`number` + +Optional integer specifying the maximum depth of namespaces to return. + +###### offset? + +`number` + +Number of namespaces to skip before returning results (default is 0). + +###### prefix? + +`string`[] + +Optional list of strings representing the prefix to filter namespaces. + +###### suffix? + +`string`[] + +Optional list of strings representing the suffix to filter namespaces. + +#### Returns + +`Promise`\<`ListNamespaceResponse`\> + +Promise + +*** + +### putItem() + +> **putItem**(`namespace`, `key`, `value`, `options`?): `Promise`\<`void`\> + +Defined in: [client.ts:1368](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1368) + +Store or update an item. + +#### Parameters + +##### namespace + +`string`[] + +A list of strings representing the namespace path. + +##### key + +`string` + +The unique identifier for the item within the namespace. + +##### value + +`Record`\<`string`, `any`\> + +A dictionary containing the item's data. + +##### options? + +###### index? + +`null` \| `false` \| `string`[] + +Controls search indexing - null (use defaults), false (disable), or list of field paths to index. + +###### ttl? + +`null` \| `number` + +Optional time-to-live in minutes for the item, or null for no expiration. + +#### Returns + +`Promise`\<`void`\> + +Promise + +#### Example + +```typescript +await client.store.putItem( + ["documents", "user123"], + "item456", + { title: "My Document", content: "Hello World" }, + { ttl: 60 } // expires in 60 minutes +); +``` + +*** + +### searchItems() + +> **searchItems**(`namespacePrefix`, `options`?): `Promise`\<`SearchItemsResponse`\> + +Defined in: [client.ts:1519](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1519) + +Search for items within a namespace prefix. + +#### Parameters + +##### namespacePrefix + +`string`[] + +List of strings representing the namespace prefix. + +##### options? + +###### filter? + +`Record`\<`string`, `any`\> + +Optional dictionary of key-value pairs to filter results. + +###### limit? + +`number` + +Maximum number of items to return (default is 10). + +###### offset? + +`number` + +Number of items to skip before returning results (default is 0). + +###### query? + +`string` + +Optional search query. + +###### refreshTtl? + +`null` \| `boolean` + +Whether to refresh the TTL on items returned by this search. If null, uses the store's default behavior. + +#### Returns + +`Promise`\<`SearchItemsResponse`\> + +Promise + +#### Example + +```typescript +const results = await client.store.searchItems( + ["documents"], + { + filter: { author: "John Doe" }, + limit: 5, + refreshTtl: true + } +); +console.log(results); +// { +// items: [ +// { +// namespace: ["documents", "user123"], +// key: "item789", +// value: { title: "Another Document", author: "John Doe" }, +// createdAt: "2024-07-30T12:00:00Z", +// updatedAt: "2024-07-30T12:00:00Z" +// }, +// // ... additional items ... +// ] +// } +``` diff --git a/libs/sdk-js/docs/classes/ThreadsClient.md b/libs/sdk-js/docs/classes/ThreadsClient.md new file mode 100644 index 000000000..7dc422c98 --- /dev/null +++ b/libs/sdk-js/docs/classes/ThreadsClient.md @@ -0,0 +1,433 @@ +[**@langchain/langgraph-sdk**](../README.md) + +*** + +[@langchain/langgraph-sdk](../README.md) / ThreadsClient + +# Class: ThreadsClient\ + +Defined in: [client.ts:626](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L626) + +## Extends + +- `BaseClient` + +## Type Parameters + +• **TStateType** = `DefaultValues` + +• **TUpdateType** = `TStateType` + +## Constructors + +### new ThreadsClient() + +> **new ThreadsClient**\<`TStateType`, `TUpdateType`\>(`config`?): [`ThreadsClient`](ThreadsClient.md)\<`TStateType`, `TUpdateType`\> + +Defined in: [client.ts:183](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L183) + +#### Parameters + +##### config? + +[`ClientConfig`](../interfaces/ClientConfig.md) + +#### Returns + +[`ThreadsClient`](ThreadsClient.md)\<`TStateType`, `TUpdateType`\> + +#### Inherited from + +`BaseClient.constructor` + +## Methods + +### copy() + +> **copy**(`threadId`): `Promise`\<`Thread`\<`TStateType`\>\> + +Defined in: [client.ts:703](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L703) + +Copy an existing thread + +#### Parameters + +##### threadId + +`string` + +ID of the thread to be copied + +#### Returns + +`Promise`\<`Thread`\<`TStateType`\>\> + +Newly copied thread + +*** + +### create() + +> **create**(`payload`?): `Promise`\<`Thread`\<`TStateType`\>\> + +Defined in: [client.ts:648](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L648) + +Create a new thread. + +#### Parameters + +##### payload? + +Payload for creating a thread. + +###### graphId? + +`string` + +Graph ID to associate with the thread. + +###### ifExists? + +`OnConflictBehavior` + +How to handle duplicate creation. + +**Default** + +```ts +"raise" +``` + +###### metadata? + +`Metadata` + +Metadata for the thread. + +###### supersteps? + +`object`[] + +Apply a list of supersteps when creating a thread, each containing a sequence of updates. + +Used for copying a thread between deployments. + +###### threadId? + +`string` + +ID of the thread to create. + +If not provided, a random UUID will be generated. + +#### Returns + +`Promise`\<`Thread`\<`TStateType`\>\> + +The created thread. + +*** + +### delete() + +> **delete**(`threadId`): `Promise`\<`void`\> + +Defined in: [client.ts:736](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L736) + +Delete a thread. + +#### Parameters + +##### threadId + +`string` + +ID of the thread. + +#### Returns + +`Promise`\<`void`\> + +*** + +### get() + +> **get**\<`ValuesType`\>(`threadId`): `Promise`\<`Thread`\<`ValuesType`\>\> + +Defined in: [client.ts:636](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L636) + +Get a thread by ID. + +#### Type Parameters + +• **ValuesType** = `TStateType` + +#### Parameters + +##### threadId + +`string` + +ID of the thread. + +#### Returns + +`Promise`\<`Thread`\<`ValuesType`\>\> + +The thread. + +*** + +### getHistory() + +> **getHistory**\<`ValuesType`\>(`threadId`, `options`?): `Promise`\<`ThreadState`\<`ValuesType`\>[]\> + +Defined in: [client.ts:888](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L888) + +Get all past states for a thread. + +#### Type Parameters + +• **ValuesType** = `TStateType` + +#### Parameters + +##### threadId + +`string` + +ID of the thread. + +##### options? + +Additional options. + +###### before? + +`Config` + +###### checkpoint? + +`Partial`\<`Omit`\<`Checkpoint`, `"thread_id"`\>\> + +###### limit? + +`number` + +###### metadata? + +`Metadata` + +#### Returns + +`Promise`\<`ThreadState`\<`ValuesType`\>[]\> + +List of thread states. + +*** + +### getState() + +> **getState**\<`ValuesType`\>(`threadId`, `checkpoint`?, `options`?): `Promise`\<`ThreadState`\<`ValuesType`\>\> + +Defined in: [client.ts:795](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L795) + +Get state for a thread. + +#### Type Parameters + +• **ValuesType** = `TStateType` + +#### Parameters + +##### threadId + +`string` + +ID of the thread. + +##### checkpoint? + +`string` | `Checkpoint` + +##### options? + +###### subgraphs? + +`boolean` + +#### Returns + +`Promise`\<`ThreadState`\<`ValuesType`\>\> + +Thread state. + +*** + +### patchState() + +> **patchState**(`threadIdOrConfig`, `metadata`): `Promise`\<`void`\> + +Defined in: [client.ts:858](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L858) + +Patch the metadata of a thread. + +#### Parameters + +##### threadIdOrConfig + +Thread ID or config to patch the state of. + +`string` | `Config` + +##### metadata + +`Metadata` + +Metadata to patch the state with. + +#### Returns + +`Promise`\<`void`\> + +*** + +### search() + +> **search**\<`ValuesType`\>(`query`?): `Promise`\<`Thread`\<`ValuesType`\>[]\> + +Defined in: [client.ts:748](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L748) + +List threads + +#### Type Parameters + +• **ValuesType** = `TStateType` + +#### Parameters + +##### query? + +Query options + +###### limit? + +`number` + +Maximum number of threads to return. +Defaults to 10 + +###### metadata? + +`Metadata` + +Metadata to filter threads by. + +###### offset? + +`number` + +Offset to start from. + +###### sortBy? + +`ThreadSortBy` + +Sort by. + +###### sortOrder? + +`SortOrder` + +Sort order. +Must be one of 'asc' or 'desc'. + +###### status? + +`ThreadStatus` + +Thread status to filter on. + +#### Returns + +`Promise`\<`Thread`\<`ValuesType`\>[]\> + +List of threads + +*** + +### update() + +> **update**(`threadId`, `payload`?): `Promise`\<`Thread`\<`DefaultValues`\>\> + +Defined in: [client.ts:716](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L716) + +Update a thread. + +#### Parameters + +##### threadId + +`string` + +ID of the thread. + +##### payload? + +Payload for updating the thread. + +###### metadata? + +`Metadata` + +Metadata for the thread. + +#### Returns + +`Promise`\<`Thread`\<`DefaultValues`\>\> + +The updated thread. + +*** + +### updateState() + +> **updateState**\<`ValuesType`\>(`threadId`, `options`): `Promise`\<`Pick`\<`Config`, `"configurable"`\>\> + +Defined in: [client.ts:829](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L829) + +Add state to a thread. + +#### Type Parameters + +• **ValuesType** = `TUpdateType` + +#### Parameters + +##### threadId + +`string` + +The ID of the thread. + +##### options + +###### asNode? + +`string` + +###### checkpoint? + +`Checkpoint` + +###### checkpointId? + +`string` + +###### values + +`ValuesType` + +#### Returns + +`Promise`\<`Pick`\<`Config`, `"configurable"`\>\> diff --git a/libs/sdk-js/docs/functions/getApiKey.md b/libs/sdk-js/docs/functions/getApiKey.md new file mode 100644 index 000000000..8c8e4f1fa --- /dev/null +++ b/libs/sdk-js/docs/functions/getApiKey.md @@ -0,0 +1,32 @@ +[**@langchain/langgraph-sdk**](../README.md) + +*** + +[@langchain/langgraph-sdk](../README.md) / getApiKey + +# Function: getApiKey() + +> **getApiKey**(`apiKey`?): `undefined` \| `string` + +Defined in: [client.ts:122](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L122) + +Get the API key from the environment. +Precedence: + 1. explicit argument + 2. LANGGRAPH_API_KEY + 3. LANGSMITH_API_KEY + 4. LANGCHAIN_API_KEY + +## Parameters + +### apiKey? + +`string` + +Optional API key provided as an argument + +## Returns + +`undefined` \| `string` + +The API key if found, otherwise undefined diff --git a/libs/sdk-js/docs/interfaces/ClientConfig.md b/libs/sdk-js/docs/interfaces/ClientConfig.md new file mode 100644 index 000000000..38c402010 --- /dev/null +++ b/libs/sdk-js/docs/interfaces/ClientConfig.md @@ -0,0 +1,57 @@ +[**@langchain/langgraph-sdk**](../README.md) + +*** + +[@langchain/langgraph-sdk](../README.md) / ClientConfig + +# Interface: ClientConfig + +Defined in: [client.ts:163](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L163) + +## Properties + +### apiKey? + +> `optional` **apiKey**: `string` + +Defined in: [client.ts:165](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L165) + +*** + +### apiUrl? + +> `optional` **apiUrl**: `string` + +Defined in: [client.ts:164](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L164) + +*** + +### callerOptions? + +> `optional` **callerOptions**: `AsyncCallerParams` + +Defined in: [client.ts:166](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L166) + +*** + +### defaultHeaders? + +> `optional` **defaultHeaders**: `Record`\<`string`, `HeaderValue`\> + +Defined in: [client.ts:168](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L168) + +*** + +### onRequest? + +> `optional` **onRequest**: [`RequestHook`](../type-aliases/RequestHook.md) + +Defined in: [client.ts:169](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L169) + +*** + +### timeoutMs? + +> `optional` **timeoutMs**: `number` + +Defined in: [client.ts:167](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L167) diff --git a/libs/sdk-js/docs/react/README.md b/libs/sdk-js/docs/react/README.md new file mode 100644 index 000000000..0933ca79b --- /dev/null +++ b/libs/sdk-js/docs/react/README.md @@ -0,0 +1,18 @@ +**@langchain/langgraph-sdk** + +*** + +# @langchain/langgraph-sdk/react + +## Interfaces + +- [UseStream](interfaces/UseStream.md) +- [UseStreamOptions](interfaces/UseStreamOptions.md) + +## Type Aliases + +- [MessageMetadata](type-aliases/MessageMetadata.md) + +## Functions + +- [useStream](functions/useStream.md) diff --git a/libs/sdk-js/docs/react/functions/useStream.md b/libs/sdk-js/docs/react/functions/useStream.md new file mode 100644 index 000000000..a9cb7d468 --- /dev/null +++ b/libs/sdk-js/docs/react/functions/useStream.md @@ -0,0 +1,27 @@ +[**@langchain/langgraph-sdk**](../README.md) + +*** + +[@langchain/langgraph-sdk](../README.md) / useStream + +# Function: useStream() + +> **useStream**\<`StateType`, `Bag`\>(`options`): [`UseStream`](../interfaces/UseStream.md)\<`StateType`, `Bag`\> + +Defined in: [react/stream.tsx:652](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L652) + +## Type Parameters + +• **StateType** *extends* `Record`\<`string`, `unknown`\> = `Record`\<`string`, `unknown`\> + +• **Bag** *extends* `object` = `BagTemplate` + +## Parameters + +### options + +[`UseStreamOptions`](../interfaces/UseStreamOptions.md)\<`StateType`, `Bag`\> + +## Returns + +[`UseStream`](../interfaces/UseStream.md)\<`StateType`, `Bag`\> diff --git a/libs/sdk-js/docs/react/interfaces/UseStream.md b/libs/sdk-js/docs/react/interfaces/UseStream.md new file mode 100644 index 000000000..06d1c4375 --- /dev/null +++ b/libs/sdk-js/docs/react/interfaces/UseStream.md @@ -0,0 +1,227 @@ +[**@langchain/langgraph-sdk**](../README.md) + +*** + +[@langchain/langgraph-sdk](../README.md) / UseStream + +# Interface: UseStream\ + +Defined in: [react/stream.tsx:529](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L529) + +## Type Parameters + +• **StateType** *extends* `Record`\<`string`, `unknown`\> = `Record`\<`string`, `unknown`\> + +• **Bag** *extends* `BagTemplate` = `BagTemplate` + +## Properties + +### assistantId + +> **assistantId**: `string` + +Defined in: [react/stream.tsx:614](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L614) + +The ID of the assistant to use. + +*** + +### branch + +> **branch**: `string` + +Defined in: [react/stream.tsx:564](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L564) + +The current branch of the thread. + +*** + +### client + +> **client**: `Client` + +Defined in: [react/stream.tsx:609](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L609) + +LangGraph SDK client used to send request and receive responses. + +*** + +### error + +> **error**: `unknown` + +Defined in: [react/stream.tsx:541](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L541) + +Last seen error from the thread or during streaming. + +*** + +### experimental\_branchTree + +> **experimental\_branchTree**: `Sequence`\<`StateType`\> + +Defined in: [react/stream.tsx:580](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L580) + +**`Experimental`** + +Tree of all branches for the thread. + +*** + +### getMessagesMetadata() + +> **getMessagesMetadata**: (`message`, `index`?) => `undefined` \| [`MessageMetadata`](../type-aliases/MessageMetadata.md)\<`StateType`\> + +Defined in: [react/stream.tsx:601](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L601) + +Get the metadata for a message, such as first thread state the message +was seen in and branch information. + +#### Parameters + +##### message + +`Message` + +The message to get the metadata for. + +##### index? + +`number` + +The index of the message in the thread. + +#### Returns + +`undefined` \| [`MessageMetadata`](../type-aliases/MessageMetadata.md)\<`StateType`\> + +The metadata for the message. + +*** + +### history + +> **history**: `ThreadState`\<`StateType`\>[] + +Defined in: [react/stream.tsx:574](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L574) + +Flattened history of thread states of a thread. + +*** + +### interrupt + +> **interrupt**: `undefined` \| `Interrupt`\<`GetInterruptType`\<`Bag`\>\> + +Defined in: [react/stream.tsx:585](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L585) + +Get the interrupt value for the stream if interrupted. + +*** + +### isLoading + +> **isLoading**: `boolean` + +Defined in: [react/stream.tsx:546](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L546) + +Whether the stream is currently running. + +*** + +### joinStream() + +> **joinStream**: (`runId`) => `Promise`\<`void`\> + +Defined in: [react/stream.tsx:619](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L619) + +Join an active stream. + +#### Parameters + +##### runId + +`string` + +#### Returns + +`Promise`\<`void`\> + +*** + +### messages + +> **messages**: `Message`[] + +Defined in: [react/stream.tsx:591](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L591) + +Messages inferred from the thread. +Will automatically update with incoming message chunks. + +*** + +### setBranch() + +> **setBranch**: (`branch`) => `void` + +Defined in: [react/stream.tsx:569](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L569) + +Set the branch of the thread. + +#### Parameters + +##### branch + +`string` + +#### Returns + +`void` + +*** + +### stop() + +> **stop**: () => `void` + +Defined in: [react/stream.tsx:551](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L551) + +Stops the stream. + +#### Returns + +`void` + +*** + +### submit() + +> **submit**: (`values`, `options`?) => `void` + +Defined in: [react/stream.tsx:556](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L556) + +Create and stream a run to the thread. + +#### Parameters + +##### values + +`undefined` | `null` | `GetUpdateType`\<`Bag`, `StateType`\> + +##### options? + +`SubmitOptions`\<`StateType`, `GetConfigurableType`\<`Bag`\>\> + +#### Returns + +`void` + +*** + +### values + +> **values**: `StateType` + +Defined in: [react/stream.tsx:536](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L536) + +The current values of the thread. diff --git a/libs/sdk-js/docs/react/interfaces/UseStreamOptions.md b/libs/sdk-js/docs/react/interfaces/UseStreamOptions.md new file mode 100644 index 000000000..9fbb6f702 --- /dev/null +++ b/libs/sdk-js/docs/react/interfaces/UseStreamOptions.md @@ -0,0 +1,343 @@ +[**@langchain/langgraph-sdk**](../README.md) + +*** + +[@langchain/langgraph-sdk](../README.md) / UseStreamOptions + +# Interface: UseStreamOptions\ + +Defined in: [react/stream.tsx:413](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L413) + +## Type Parameters + +• **StateType** *extends* `Record`\<`string`, `unknown`\> = `Record`\<`string`, `unknown`\> + +• **Bag** *extends* `BagTemplate` = `BagTemplate` + +## Properties + +### apiKey? + +> `optional` **apiKey**: `string` + +Defined in: [react/stream.tsx:435](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L435) + +The API key to use. + +*** + +### apiUrl? + +> `optional` **apiUrl**: `string` + +Defined in: [react/stream.tsx:430](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L430) + +The URL of the API to use. + +*** + +### assistantId + +> **assistantId**: `string` + +Defined in: [react/stream.tsx:420](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L420) + +The ID of the assistant to use. + +*** + +### callerOptions? + +> `optional` **callerOptions**: `AsyncCallerParams` + +Defined in: [react/stream.tsx:440](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L440) + +Custom call options, such as custom fetch implementation. + +*** + +### client? + +> `optional` **client**: `Client`\<`DefaultValues`, `DefaultValues`, `unknown`\> + +Defined in: [react/stream.tsx:425](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L425) + +Client used to send requests. + +*** + +### defaultHeaders? + +> `optional` **defaultHeaders**: `Record`\<`string`, `HeaderValue`\> + +Defined in: [react/stream.tsx:445](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L445) + +Default headers to send with requests. + +*** + +### messagesKey? + +> `optional` **messagesKey**: `string` + +Defined in: [react/stream.tsx:453](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L453) + +Specify the key within the state that contains messages. +Defaults to "messages". + +#### Default + +```ts +"messages" +``` + +*** + +### onCreated()? + +> `optional` **onCreated**: (`run`) => `void` + +Defined in: [react/stream.tsx:471](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L471) + +Callback that is called when a new stream is created. + +#### Parameters + +##### run + +`RunCallbackMeta` + +#### Returns + +`void` + +*** + +### onCustomEvent()? + +> `optional` **onCustomEvent**: (`data`, `options`) => `void` + +Defined in: [react/stream.tsx:483](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L483) + +Callback that is called when a custom event is received. + +#### Parameters + +##### data + +`GetCustomEventType`\<`Bag`\> + +##### options + +###### mutate + +(`update`) => `void` + +#### Returns + +`void` + +*** + +### onDebugEvent()? + +> `optional` **onDebugEvent**: (`data`) => `void` + +Defined in: [react/stream.tsx:507](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L507) + +**`Internal`** + +Callback that is called when a debug event is received. + This API is experimental and subject to change. + +#### Parameters + +##### data + +`unknown` + +#### Returns + +`void` + +*** + +### onError()? + +> `optional` **onError**: (`error`, `run`) => `void` + +Defined in: [react/stream.tsx:458](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L458) + +Callback that is called when an error occurs. + +#### Parameters + +##### error + +`unknown` + +##### run + +`undefined` | `RunCallbackMeta` + +#### Returns + +`void` + +*** + +### onFinish()? + +> `optional` **onFinish**: (`state`, `run`) => `void` + +Defined in: [react/stream.tsx:463](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L463) + +Callback that is called when the stream is finished. + +#### Parameters + +##### state + +`ThreadState`\<`StateType`\> + +##### run + +`undefined` | `RunCallbackMeta` + +#### Returns + +`void` + +*** + +### onLangChainEvent()? + +> `optional` **onLangChainEvent**: (`data`) => `void` + +Defined in: [react/stream.tsx:501](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L501) + +Callback that is called when a LangChain event is received. + +#### Parameters + +##### data + +###### data + +`unknown` + +###### event + +`string` & `object` \| `"on_tool_start"` \| `"on_tool_stream"` \| `"on_tool_end"` \| `"on_chat_model_start"` \| `"on_chat_model_stream"` \| `"on_chat_model_end"` \| `"on_llm_start"` \| `"on_llm_stream"` \| `"on_llm_end"` \| `"on_chain_start"` \| `"on_chain_stream"` \| `"on_chain_end"` \| `"on_retriever_start"` \| `"on_retriever_stream"` \| `"on_retriever_end"` \| `"on_prompt_start"` \| `"on_prompt_stream"` \| `"on_prompt_end"` + +###### metadata + +`Record`\<`string`, `unknown`\> + +###### name + +`string` + +###### parent_ids + +`string`[] + +###### run_id + +`string` + +###### tags + +`string`[] + +#### Returns + +`void` + +#### See + +https://langchain-ai.github.io/langgraph/cloud/how-tos/stream_events/#stream-graph-in-events-mode for more details. + +*** + +### onMetadataEvent()? + +> `optional` **onMetadataEvent**: (`data`) => `void` + +Defined in: [react/stream.tsx:495](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L495) + +Callback that is called when a metadata event is received. + +#### Parameters + +##### data + +###### run_id + +`string` + +###### thread_id + +`string` + +#### Returns + +`void` + +*** + +### onThreadId()? + +> `optional` **onThreadId**: (`threadId`) => `void` + +Defined in: [react/stream.tsx:517](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L517) + +Callback that is called when the thread ID is updated (ie when a new thread is created). + +#### Parameters + +##### threadId + +`string` + +#### Returns + +`void` + +*** + +### onUpdateEvent()? + +> `optional` **onUpdateEvent**: (`data`) => `void` + +Defined in: [react/stream.tsx:476](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L476) + +Callback that is called when an update event is received. + +#### Parameters + +##### data + +#### Returns + +`void` + +*** + +### reconnectOnMount? + +> `optional` **reconnectOnMount**: `boolean` \| () => `RunMetadataStorage` + +Defined in: [react/stream.tsx:520](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L520) + +Will reconnect the stream on mount + +*** + +### threadId? + +> `optional` **threadId**: `null` \| `string` + +Defined in: [react/stream.tsx:512](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L512) + +The ID of the thread to fetch history and current values from. diff --git a/libs/sdk-js/docs/react/type-aliases/MessageMetadata.md b/libs/sdk-js/docs/react/type-aliases/MessageMetadata.md new file mode 100644 index 000000000..9496a7913 --- /dev/null +++ b/libs/sdk-js/docs/react/type-aliases/MessageMetadata.md @@ -0,0 +1,42 @@ +[**@langchain/langgraph-sdk**](../README.md) + +*** + +[@langchain/langgraph-sdk](../README.md) / MessageMetadata + +# Type Alias: MessageMetadata\ + +> **MessageMetadata**\<`StateType`\>: `object` + +Defined in: [react/stream.tsx:169](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L169) + +## Type Parameters + +• **StateType** *extends* `Record`\<`string`, `unknown`\> + +## Type declaration + +### branch + +> **branch**: `string` \| `undefined` + +The branch of the message. + +### branchOptions + +> **branchOptions**: `string`[] \| `undefined` + +The list of branches this message is part of. +This is useful for displaying branching controls. + +### firstSeenState + +> **firstSeenState**: `ThreadState`\<`StateType`\> \| `undefined` + +The first thread state the message was seen in. + +### messageId + +> **messageId**: `string` + +The ID of the message used. diff --git a/libs/sdk-js/docs/type-aliases/RequestHook.md b/libs/sdk-js/docs/type-aliases/RequestHook.md new file mode 100644 index 000000000..53d535e2e --- /dev/null +++ b/libs/sdk-js/docs/type-aliases/RequestHook.md @@ -0,0 +1,25 @@ +[**@langchain/langgraph-sdk**](../README.md) + +*** + +[@langchain/langgraph-sdk](../README.md) / RequestHook + +# Type Alias: RequestHook() + +> **RequestHook**: (`url`, `init`) => `Promise`\<`RequestInit`\> \| `RequestInit` + +Defined in: [client.ts:158](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L158) + +## Parameters + +### url + +`URL` + +### init + +`RequestInit` + +## Returns + +`Promise`\<`RequestInit`\> \| `RequestInit` diff --git a/libs/sdk-js/index.cjs b/libs/sdk-js/index.cjs new file mode 100644 index 000000000..c84256f7a --- /dev/null +++ b/libs/sdk-js/index.cjs @@ -0,0 +1 @@ +module.exports = require('./dist/index.cjs'); \ No newline at end of file diff --git a/libs/sdk-js/index.d.cts b/libs/sdk-js/index.d.cts new file mode 100644 index 000000000..485d17256 --- /dev/null +++ b/libs/sdk-js/index.d.cts @@ -0,0 +1 @@ +export * from './dist/index.js' \ No newline at end of file diff --git a/libs/sdk-js/index.d.ts b/libs/sdk-js/index.d.ts new file mode 100644 index 000000000..485d17256 --- /dev/null +++ b/libs/sdk-js/index.d.ts @@ -0,0 +1 @@ +export * from './dist/index.js' \ No newline at end of file diff --git a/libs/sdk-js/index.js b/libs/sdk-js/index.js new file mode 100644 index 000000000..485d17256 --- /dev/null +++ b/libs/sdk-js/index.js @@ -0,0 +1 @@ +export * from './dist/index.js' \ No newline at end of file diff --git a/libs/sdk-js/react.cjs b/libs/sdk-js/react.cjs new file mode 100644 index 000000000..86a38b8c3 --- /dev/null +++ b/libs/sdk-js/react.cjs @@ -0,0 +1 @@ +module.exports = require('./dist/react/index.cjs'); \ No newline at end of file diff --git a/libs/sdk-js/react.d.cts b/libs/sdk-js/react.d.cts new file mode 100644 index 000000000..fd96c4787 --- /dev/null +++ b/libs/sdk-js/react.d.cts @@ -0,0 +1 @@ +export * from './dist/react/index.js' \ No newline at end of file diff --git a/libs/sdk-js/react.d.ts b/libs/sdk-js/react.d.ts new file mode 100644 index 000000000..fd96c4787 --- /dev/null +++ b/libs/sdk-js/react.d.ts @@ -0,0 +1 @@ +export * from './dist/react/index.js' \ No newline at end of file diff --git a/libs/sdk-js/react.js b/libs/sdk-js/react.js new file mode 100644 index 000000000..fd96c4787 --- /dev/null +++ b/libs/sdk-js/react.js @@ -0,0 +1 @@ +export * from './dist/react/index.js' \ No newline at end of file From c9966c4febc681388055a0f91f1e19532c66c8ea Mon Sep 17 00:00:00 2001 From: Andrew Nguonly Date: Mon, 7 Jul 2025 12:39:44 -0400 Subject: [PATCH 027/129] docs: Add section about data region for LGP data plane (#5378) Add section about data region. --- docs/docs/concepts/langgraph_data_plane.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/docs/concepts/langgraph_data_plane.md b/docs/docs/concepts/langgraph_data_plane.md index 0b52b8b6f..5d7473cb6 100644 --- a/docs/docs/concepts/langgraph_data_plane.md +++ b/docs/docs/concepts/langgraph_data_plane.md @@ -50,6 +50,15 @@ Runs in a LangGraph Server may be retried for specific failures (currently only This section describes various features of the data plane. +### Data Region + +!!! info "Only for Cloud SaaS" + Data regions are only applicable for [Cloud SaaS](../concepts/langgraph_cloud.md) deployments. + +Deployments can be created in 2 data regions: US and EU + +The data region for a deployment is implied by the data region of the LangSmith organization where the deployment is created. Deployments and the underlying database for the deployments cannot be migrated between data regions. + ### Autoscaling [`Production` type](../concepts/langgraph_control_plane.md#deployment-types) deployments automatically scale up to 10 containers. Scaling is based on 3 metrics: From 844417591d5368b1f5d69de0c86068ed253da45d Mon Sep 17 00:00:00 2001 From: Michael Li Date: Tue, 8 Jul 2025 05:09:00 +1000 Subject: [PATCH 028/129] fix: remove empty notebook (#5379) --- examples/human_in_the_loop/breakpoints.ipynb | 1 - 1 file changed, 1 deletion(-) delete mode 100644 examples/human_in_the_loop/breakpoints.ipynb diff --git a/examples/human_in_the_loop/breakpoints.ipynb b/examples/human_in_the_loop/breakpoints.ipynb deleted file mode 100644 index 0519ecba6..000000000 --- a/examples/human_in_the_loop/breakpoints.ipynb +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file From 7f57e0097575897feeff72aca9cb3d84f169efd4 Mon Sep 17 00:00:00 2001 From: Eugene Yurtsev Date: Mon, 7 Jul 2025 15:10:01 -0400 Subject: [PATCH 029/129] docs: move script into scripts (#5384) --- extract_images.py => docs/_scripts/extract_images.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename extract_images.py => docs/_scripts/extract_images.py (100%) diff --git a/extract_images.py b/docs/_scripts/extract_images.py similarity index 100% rename from extract_images.py rename to docs/_scripts/extract_images.py From 1800df7048510e9dc5330b57236420845dc07310 Mon Sep 17 00:00:00 2001 From: jito Date: Tue, 8 Jul 2025 04:25:06 +0900 Subject: [PATCH 030/129] Fix docstring for _unset_config_context function (#5374) Signed-off-by: jitokim --- libs/langgraph/langgraph/utils/runnable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/langgraph/langgraph/utils/runnable.py b/libs/langgraph/langgraph/utils/runnable.py index 3ca48aec3..4274c8134 100644 --- a/libs/langgraph/langgraph/utils/runnable.py +++ b/libs/langgraph/langgraph/utils/runnable.py @@ -83,7 +83,7 @@ def _unset_config_context(token: Token[RunnableConfig | None], run: Any = None) """Set the child Runnable config + tracing context. Args: - config: The config to set. + token: The config token to reset. """ var_child_runnable_config.reset(token) if run is not None: From e99f6292c510fb5ee046b17a75a006f3b429447d Mon Sep 17 00:00:00 2001 From: jito Date: Tue, 8 Jul 2025 04:27:09 +0900 Subject: [PATCH 031/129] =?UTF-8?q?Fix=20typo=20in=20StreamMode=20debug=20?= =?UTF-8?q?description:=20checlkpoints=20=E2=86=92=20checkpoints=20(#5371)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: jitokim --- libs/langgraph/langgraph/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/langgraph/langgraph/types.py b/libs/langgraph/langgraph/types.py index d95c4fd51..095e73c24 100644 --- a/libs/langgraph/langgraph/types.py +++ b/libs/langgraph/langgraph/types.py @@ -59,7 +59,7 @@ StreamMode = Literal[ - `"messages"`: Emit LLM messages token-by-token together with metadata for any LLM invocations inside nodes or tasks. - `"checkpoints"`: Emit an event when a checkpoint is created, in the same format as returned by get_state(). - `"tasks"`: Emit events when tasks start and finish, including their results and errors. -- `"debug"`: Emit "checlkpoints" and "tasks" events, for debugging purposes. +- `"debug"`: Emit "checkpoints" and "tasks" events, for debugging purposes. """ StreamWriter = Callable[[Any], None] From 141afa8c6278090555a51db6e425e996bbb229f1 Mon Sep 17 00:00:00 2001 From: Michael Li Date: Tue, 8 Jul 2025 05:54:02 +1000 Subject: [PATCH 032/129] fix: remove unused import in generate_llms_text.py (#5380) --- docs/_scripts/generate_llms_text.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/docs/_scripts/generate_llms_text.py b/docs/_scripts/generate_llms_text.py index ff981834e..a262549c9 100644 --- a/docs/_scripts/generate_llms_text.py +++ b/docs/_scripts/generate_llms_text.py @@ -14,10 +14,7 @@ from mkdocs.structure.pages import Page from pydantic import BaseModel, Field from yaml import SafeLoader -from _scripts.notebook_hooks import ( - _on_page_markdown_with_config, - _apply_conditional_rendering, -) +from _scripts.notebook_hooks import _on_page_markdown_with_config HERE = os.path.dirname(os.path.abspath(__file__)) # Get source directory (parent of HERE / docs) From de6c25689d03f8e2115eb8d06091e0353268d9b6 Mon Sep 17 00:00:00 2001 From: Serhii Polishchuk Date: Mon, 7 Jul 2025 22:00:57 +0200 Subject: [PATCH 033/129] dcos: Fix deprecation of TavilySearch (#5375) Fix deprecation: The class `TavilySearchResults` was deprecated in LangChain 0.3.25 and will be removed in 1.0 --- .../tutorials/multi_agent/hierarchical_agent_teams.ipynb | 6 +++--- .../tutorials/multi_agent/multi-agent-collaboration.ipynb | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/docs/tutorials/multi_agent/hierarchical_agent_teams.ipynb b/docs/docs/tutorials/multi_agent/hierarchical_agent_teams.ipynb index 3031fa74a..4222d111e 100644 --- a/docs/docs/tutorials/multi_agent/hierarchical_agent_teams.ipynb +++ b/docs/docs/tutorials/multi_agent/hierarchical_agent_teams.ipynb @@ -49,7 +49,7 @@ "outputs": [], "source": [ "%%capture --no-stderr\n", - "%pip install -U langgraph langchain_community langchain_anthropic langchain_experimental" + "%pip install -U langgraph langchain_community langchain_anthropic langchain-tavily langchain_experimental" ] }, { @@ -121,10 +121,10 @@ "from typing import Annotated, List\n", "\n", "from langchain_community.document_loaders import WebBaseLoader\n", - "from langchain_community.tools.tavily_search import TavilySearchResults\n", + "from langchain_tavily import TavilySearch\n", "from langchain_core.tools import tool\n", "\n", - "tavily_tool = TavilySearchResults(max_results=5)\n", + "tavily_tool = TavilySearch(max_results=5)\n", "\n", "\n", "@tool\n", diff --git a/docs/docs/tutorials/multi_agent/multi-agent-collaboration.ipynb b/docs/docs/tutorials/multi_agent/multi-agent-collaboration.ipynb index 6bdaf978e..223cb4fb6 100644 --- a/docs/docs/tutorials/multi_agent/multi-agent-collaboration.ipynb +++ b/docs/docs/tutorials/multi_agent/multi-agent-collaboration.ipynb @@ -37,7 +37,7 @@ "outputs": [], "source": [ "%%capture --no-stderr\n", - "%pip install -U langchain_community langchain_anthropic langchain_experimental matplotlib langgraph" + "%pip install -U langchain_community langchain_anthropic langchain-tavily langchain_experimental matplotlib langgraph" ] }, { @@ -92,11 +92,11 @@ "source": [ "from typing import Annotated\n", "\n", - "from langchain_community.tools.tavily_search import TavilySearchResults\n", + "from langchain_tavily import TavilySearch\n", "from langchain_core.tools import tool\n", "from langchain_experimental.utilities import PythonREPL\n", "\n", - "tavily_tool = TavilySearchResults(max_results=5)\n", + "tavily_tool = TavilySearch(max_results=5)\n", "\n", "# Warning: This executes code locally, which can be unsafe when not sandboxed\n", "\n", From f3a7925d864d6af62189f55529c9df3b5ccf1c47 Mon Sep 17 00:00:00 2001 From: jito Date: Tue, 8 Jul 2025 05:09:55 +0900 Subject: [PATCH 034/129] =?UTF-8?q?Fix=20typo:=20funtion=20=E2=86=92=20fun?= =?UTF-8?q?ction=20(#5370)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix typos Signed-off-by: jitokim --- libs/langgraph/bench/react_agent.py | 4 ++-- libs/langgraph/tests/__snapshots__/test_large_cases.ambr | 2 +- libs/langgraph/tests/test_large_cases.py | 8 ++++---- libs/langgraph/tests/test_large_cases_async.py | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/libs/langgraph/bench/react_agent.py b/libs/langgraph/bench/react_agent.py index a6f84f2dc..59e60fb95 100644 --- a/libs/langgraph/bench/react_agent.py +++ b/libs/langgraph/bench/react_agent.py @@ -15,7 +15,7 @@ from langgraph.pregel import Pregel def react_agent(n_tools: int, checkpointer: Optional[BaseCheckpointSaver]) -> Pregel: - class FakeFuntionChatModel(FakeMessagesListChatModel): + class FakeFunctionChatModel(FakeMessagesListChatModel): def bind_tools(self, functions: list): return self @@ -40,7 +40,7 @@ def react_agent(n_tools: int, checkpointer: Optional[BaseCheckpointSaver]) -> Pr description="", ) - model = FakeFuntionChatModel( + model = FakeFunctionChatModel( responses=[ AIMessage( content="", diff --git a/libs/langgraph/tests/__snapshots__/test_large_cases.ambr b/libs/langgraph/tests/__snapshots__/test_large_cases.ambr index 56b3fb6aa..3b3b383ff 100644 --- a/libs/langgraph/tests/__snapshots__/test_large_cases.ambr +++ b/libs/langgraph/tests/__snapshots__/test_large_cases.ambr @@ -218,7 +218,7 @@ "id": [ "tests", "test_large_cases", - "FakeFuntionChatModel" + "FakeFunctionChatModel" ], "name": "agent" } diff --git a/libs/langgraph/tests/test_large_cases.py b/libs/langgraph/tests/test_large_cases.py index 81de033ba..e642d07da 100644 --- a/libs/langgraph/tests/test_large_cases.py +++ b/libs/langgraph/tests/test_large_cases.py @@ -2377,7 +2377,7 @@ def test_message_graph( from langchain_core.outputs import ChatGeneration, ChatResult from langchain_core.tools import tool - class FakeFuntionChatModel(FakeMessagesListChatModel): + class FakeFunctionChatModel(FakeMessagesListChatModel): def bind_functions(self, functions: list): return self @@ -2403,7 +2403,7 @@ def test_message_graph( tools = [search_api] - model = FakeFuntionChatModel( + model = FakeFunctionChatModel( responses=[ AIMessage( content="", @@ -3100,7 +3100,7 @@ def test_root_graph( from langchain_core.outputs import ChatGeneration, ChatResult from langchain_core.tools import tool - class FakeFuntionChatModel(FakeMessagesListChatModel): + class FakeFunctionChatModel(FakeMessagesListChatModel): def bind_functions(self, functions: list): return self @@ -3126,7 +3126,7 @@ def test_root_graph( tools = [search_api] - model = FakeFuntionChatModel( + model = FakeFunctionChatModel( responses=[ AIMessage( content="", diff --git a/libs/langgraph/tests/test_large_cases_async.py b/libs/langgraph/tests/test_large_cases_async.py index 824624680..29f92d8b9 100644 --- a/libs/langgraph/tests/test_large_cases_async.py +++ b/libs/langgraph/tests/test_large_cases_async.py @@ -2066,7 +2066,7 @@ async def test_message_graph(async_checkpointer: BaseCheckpointSaver) -> None: from langchain_core.messages import AIMessage, HumanMessage from langchain_core.tools import tool - class FakeFuntionChatModel(FakeMessagesListChatModel): + class FakeFunctionChatModel(FakeMessagesListChatModel): def bind_functions(self, functions: list): return self @@ -2077,7 +2077,7 @@ async def test_message_graph(async_checkpointer: BaseCheckpointSaver) -> None: tools = [search_api] - model = FakeFuntionChatModel( + model = FakeFunctionChatModel( responses=[ AIMessage( content="", From cd58fad69db699d5ee653c8d4df1469efbea4117 Mon Sep 17 00:00:00 2001 From: Lauren Hirata Singh Date: Mon, 7 Jul 2025 17:03:05 -0400 Subject: [PATCH 035/129] docs: feedback edits (#5387) --- docs/_scripts/notebook_hooks.py | 1 + docs/docs/agents/overview.md | 2 +- docs/docs/agents/tools.md | 310 ------------------------------ docs/docs/how-tos/graph-api.md | 2 +- docs/docs/how-tos/tool-calling.md | 2 + docs/overrides/main.html | 9 +- 6 files changed, 12 insertions(+), 314 deletions(-) delete mode 100644 docs/docs/agents/tools.md diff --git a/docs/_scripts/notebook_hooks.py b/docs/_scripts/notebook_hooks.py index 7b7f049eb..db31e41ce 100644 --- a/docs/_scripts/notebook_hooks.py +++ b/docs/_scripts/notebook_hooks.py @@ -72,6 +72,7 @@ REDIRECT_MAP = { "how-tos/pass-config-to-tools.ipynb": "how-tos/tool-calling.ipynb#access-config", "how-tos/pass-run-time-values-to-tools.ipynb": "how-tos/tool-calling.ipynb#read-state", "how-tos/update-state-from-tools.ipynb": "how-tos/tool-calling.ipynb#update-state", + "agents/tools.md": "how-tos/tool-calling.md", # multi-agent how-tos "how-tos/agent-handoffs.ipynb": "how-tos/multi_agent.md#handoffs", "how-tos/multi-agent-network.ipynb": "how-tos/multi_agent.md#use-in-a-multi-agent-system", diff --git a/docs/docs/agents/overview.md b/docs/docs/agents/overview.md index d61b9d6ed..96fef74b3 100644 --- a/docs/docs/agents/overview.md +++ b/docs/docs/agents/overview.md @@ -60,7 +60,7 @@ Use the following tool to visualize the graph generated by and to view an outline of the corresponding code. It allows you to explore the infrastructure of the agent as defined by the presence of: -* [`tools`](../agents/tools.md): A list of tools (functions, APIs, or other callable objects) that the agent can use to perform tasks. +* [`tools`](../how-tos/tool-calling.md): A list of tools (functions, APIs, or other callable objects) that the agent can use to perform tasks. * [`pre_model_hook`](../how-tos/create-react-agent-manage-message-history.ipynb): A function that is called before the model is invoked. It can be used to condense messages or perform other preprocessing tasks. * `post_model_hook`: A function that is called after the model is invoked. It can be used to implement guardrails, human-in-the-loop flows, or other postprocessing tasks. * [`response_format`](../agents/agents.md#6-configure-structured-output): A data structure used to constrain the type of the final output, e.g., a `pydantic` `BaseModel`. diff --git a/docs/docs/agents/tools.md b/docs/docs/agents/tools.md deleted file mode 100644 index e9f45effb..000000000 --- a/docs/docs/agents/tools.md +++ /dev/null @@ -1,310 +0,0 @@ ---- -search: - boost: 2 -tags: - - agent -hide: - - tags ---- - -# Tools - -[Tools](https://python.langchain.com/docs/concepts/tools/) are a way to encapsulate a function and its input schema in a way that can be passed to a chat model that supports tool calling. This allows the model to request the execution of this function with specific inputs. - -You can either [define your own tools](#define-simple-tools) or use [prebuilt integrations](#prebuilt-tools) that LangChain provides. - -## Define simple tools - -You can pass a vanilla function to `create_react_agent` to use as a tool: - -```python -from langgraph.prebuilt import create_react_agent - -def multiply(a: int, b: int) -> int: - """Multiply two numbers.""" - return a * b - -create_react_agent( - model="anthropic:claude-3-7-sonnet", - tools=[multiply] -) -``` - -`create_react_agent` automatically converts vanilla functions to [LangChain tools](https://python.langchain.com/docs/concepts/tools/#tool-interface). - -## Customize tools - -For more control over tool behavior, use the `@tool` decorator: - -```python -# highlight-next-line -from langchain_core.tools import tool - -# highlight-next-line -@tool("multiply_tool", parse_docstring=True) -def multiply(a: int, b: int) -> int: - """Multiply two numbers. - - Args: - a: First operand - b: Second operand - """ - return a * b -``` - -You can also define a custom input schema using Pydantic: - -```python -from pydantic import BaseModel, Field - -class MultiplyInputSchema(BaseModel): - """Multiply two numbers""" - a: int = Field(description="First operand") - b: int = Field(description="Second operand") - -# highlight-next-line -@tool("multiply_tool", args_schema=MultiplyInputSchema) -def multiply(a: int, b: int) -> int: - return a * b -``` - -For additional customization, refer to the [custom tools guide](https://python.langchain.com/docs/how_to/custom_tools/). - -## Hide arguments from the model - -Some tools require runtime-only arguments (e.g., user ID or session context) that should not be controllable by the model. - -You can put these arguments in the `state` or `config` of the agent, and access -this information inside the tool: - -```python -from langgraph.prebuilt import InjectedState -from langgraph.prebuilt.chat_agent_executor import AgentState -from langchain_core.runnables import RunnableConfig - -def my_tool( - # This will be populated by an LLM - tool_arg: str, - # access information that's dynamically updated inside the agent - # highlight-next-line - state: Annotated[AgentState, InjectedState], - # access static data that is passed at agent invocation - # highlight-next-line - config: RunnableConfig, -) -> str: - """My tool.""" - do_something_with_state(state["messages"]) - do_something_with_config(config) - ... -``` - -## Disable parallel tool calling - -Some model providers support executing multiple tools in parallel, but -allow users to disable this feature. - -For supported providers, you can disable parallel tool calling by setting `parallel_tool_calls=False` via the `model.bind_tools()` method: - -```python -from langchain.chat_models import init_chat_model - -def add(a: int, b: int) -> int: - """Add two numbers""" - return a + b - -def multiply(a: int, b: int) -> int: - """Multiply two numbers.""" - return a * b - -model = init_chat_model("anthropic:claude-3-5-sonnet-latest", temperature=0) -tools = [add, multiply] -agent = create_react_agent( - # disable parallel tool calls - # highlight-next-line - model=model.bind_tools(tools, parallel_tool_calls=False), - tools=tools -) - -agent.invoke( - {"messages": [{"role": "user", "content": "what's 3 + 5 and 4 * 7?"}]} -) -``` - -## Return tool results directly - -Use `return_direct=True` to return tool results immediately and stop the agent loop: - -```python -from langchain_core.tools import tool - -# highlight-next-line -@tool(return_direct=True) -def add(a: int, b: int) -> int: - """Add two numbers""" - return a + b - -agent = create_react_agent( - model="anthropic:claude-3-7-sonnet-latest", - tools=[add] -) - -agent.invoke( - {"messages": [{"role": "user", "content": "what's 3 + 5?"}]} -) -``` - -## Force tool use - -To force the agent to use specific tools, you can set the `tool_choice` option in `model.bind_tools()`: - -```python -from langchain_core.tools import tool - -# highlight-next-line -@tool(return_direct=True) -def greet(user_name: str) -> int: - """Greet user.""" - return f"Hello {user_name}!" - -tools = [greet] - -agent = create_react_agent( - # highlight-next-line - model=model.bind_tools(tools, tool_choice={"type": "tool", "name": "greet"}), - tools=tools -) - -agent.invoke( - {"messages": [{"role": "user", "content": "Hi, I am Bob"}]} -) -``` - -!!! Warning "Avoid infinite loops" - - Forcing tool usage without stopping conditions can create infinite loops. Use one of the following safeguards: - - - Mark the tool with [`return_direct=True`](#return-tool-results-directly) to end the loop after execution. - - Set [`recursion_limit`](../concepts/low_level.md#recursion-limit) to restrict the number of execution steps. - -## Handle tool errors - -By default, the agent will catch all exceptions raised during tool calls and will pass those as tool messages to the LLM. To control how the errors are handled, you can use the prebuilt [`ToolNode`][langgraph.prebuilt.tool_node.ToolNode] — the node that executes tools inside `create_react_agent` — via its `handle_tool_errors` parameter: - -=== "Enable error handling (default)" - - ```python - from langgraph.prebuilt import create_react_agent - - def multiply(a: int, b: int) -> int: - """Multiply two numbers.""" - if a == 42: - raise ValueError("The ultimate error") - return a * b - - # Run with error handling (default) - agent = create_react_agent( - model="anthropic:claude-3-7-sonnet-latest", - tools=[multiply] - ) - agent.invoke( - {"messages": [{"role": "user", "content": "what's 42 x 7?"}]} - ) - ``` - -=== "Disable error handling" - - ```python - from langgraph.prebuilt import create_react_agent, ToolNode - - def multiply(a: int, b: int) -> int: - """Multiply two numbers.""" - if a == 42: - raise ValueError("The ultimate error") - return a * b - - # highlight-next-line - tool_node = ToolNode( - [multiply], - # highlight-next-line - handle_tool_errors=False # (1)! - ) - agent_no_error_handling = create_react_agent( - model="anthropic:claude-3-7-sonnet-latest", - tools=tool_node - ) - agent_no_error_handling.invoke( - {"messages": [{"role": "user", "content": "what's 42 x 7?"}]} - ) - ``` - - 1. This disables error handling (enabled by default). See all available strategies in the [API reference][langgraph.prebuilt.tool_node.ToolNode]. - -=== "Custom error handling" - - ```python - from langgraph.prebuilt import create_react_agent, ToolNode - - def multiply(a: int, b: int) -> int: - """Multiply two numbers.""" - if a == 42: - raise ValueError("The ultimate error") - return a * b - - # highlight-next-line - tool_node = ToolNode( - [multiply], - # highlight-next-line - handle_tool_errors=( - "Can't use 42 as a first operand, you must switch operands!" # (1)! - ) - ) - agent_custom_error_handling = create_react_agent( - model="anthropic:claude-3-7-sonnet-latest", - tools=tool_node - ) - agent_custom_error_handling.invoke( - {"messages": [{"role": "user", "content": "what's 42 x 7?"}]} - ) - ``` - - 1. This provides a custom message to send to the LLM in case of an exception. See all available strategies in the [API reference][langgraph.prebuilt.tool_node.ToolNode]. - -See [API reference][langgraph.prebuilt.tool_node.ToolNode] for more information on different tool error handling options. - -## Working with memory - -LangGraph allows access to short-term and long-term memory from tools. See [Memory](../how-tos/memory/add-memory.md) guide for more information on: - -* how to [read](../how-tos/memory/add-memory.md#read-short-term) from and [write](../how-tos/memory/add-memory.md#write-short-term) to **short-term** memory -* how to [read](../how-tos/memory/add-memory.md#read-long-term) from and [write](../how-tos/memory/add-memory.md#write-long-term) to **long-term** memory - -## Prebuilt tools - -You can use prebuilt tools from model providers by passing a dictionary with tool specs to the `tools` parameter of `create_react_agent`. For example, to use the `web_search_preview` tool from OpenAI: - -```python -from langgraph.prebuilt import create_react_agent - -agent = create_react_agent( - model="openai:gpt-4o-mini", - tools=[{"type": "web_search_preview"}] -) -response = agent.invoke( - {"messages": ["What was a positive news story from today?"]} -) -``` - -Additionally, LangChain supports a wide range of prebuilt tool integrations for interacting with APIs, databases, file systems, web data, and more. These tools extend the functionality of agents and enable rapid development. - -You can browse the full list of available integrations in the [LangChain integrations directory](https://python.langchain.com/docs/integrations/tools/). - -Some commonly used tool categories include: - -- **Search**: Bing, SerpAPI, Tavily -- **Code interpreters**: Python REPL, Node.js REPL -- **Databases**: SQL, MongoDB, Redis -- **Web data**: Web scraping and browsing -- **APIs**: OpenWeatherMap, NewsAPI, and others - -These integrations can be configured and added to your agents using the same `tools` parameter shown in the examples above. - diff --git a/docs/docs/how-tos/graph-api.md b/docs/docs/how-tos/graph-api.md index 2e15cacb1..3cf08f8c5 100644 --- a/docs/docs/how-tos/graph-api.md +++ b/docs/docs/how-tos/graph-api.md @@ -658,7 +658,7 @@ print(graph.invoke({}, {"configurable": {"my_runtime_value": "b"}})) There are many use cases where you may wish for your node to have a custom retry policy, for example if you are calling an API, querying a database, or calling an LLM, etc. LangGraph lets you add retry policies to nodes. -To configure a retry policy, pass the `retry_policy` parameter to the [add_node](https://langchain-ai.github.io/langgraph/reference/graphs.md#langgraph.graph.state.StateGraph.add_node). The `retry_policy` parameter takes in a `RetryPolicy` named tuple object. Below we instantiate a `RetryPolicy` object with the default parameters and associate it with a node: +To configure a retry policy, pass the `retry_policy` parameter to the [add_node](../reference/graphs.md#langgraph.graph.state.StateGraph.add_node). The `retry_policy` parameter takes in a `RetryPolicy` named tuple object. Below we instantiate a `RetryPolicy` object with the default parameters and associate it with a node: ```python from langgraph.pregel import RetryPolicy diff --git a/docs/docs/how-tos/tool-calling.md b/docs/docs/how-tos/tool-calling.md index a2e711ba3..9968b0036 100644 --- a/docs/docs/how-tos/tool-calling.md +++ b/docs/docs/how-tos/tool-calling.md @@ -344,6 +344,8 @@ tool_node.invoke({"messages": [...]}) ## Tool customization +For more control over tool behavior, use the `@tool` decorator. + ### Parameter descriptions Auto-generate descriptions from docstrings: diff --git a/docs/overrides/main.html b/docs/overrides/main.html index 12a20dfbb..b3e63c56d 100644 --- a/docs/overrides/main.html +++ b/docs/overrides/main.html @@ -184,7 +184,12 @@ j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= visibility: hidden; } - /* Dark mode banner links */ + /* Dark mode banner styling */ + [data-md-color-scheme="slate"] .md-banner { + background-color: #CFC9FA; /* Same light purple for both modes */ + color: #000000; + } + [data-md-color-scheme="slate"] .md-banner a { color: #000000; } @@ -220,5 +225,5 @@ j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= {% endblock %} {% block announce %} -We are growing and hiring for multiple roles for LangChain, LangGraph and LangSmith. Join our team! +Our Building Ambient Agents with LangGraph course is now available on LangChain Academy! {% endblock %} From c13c4746266bf41b8091c8758f0ae04349e48499 Mon Sep 17 00:00:00 2001 From: hari-dhanushkodi Date: Mon, 7 Jul 2025 17:44:57 -0400 Subject: [PATCH 036/129] docs: update lgp deployment metric list (#5388) --- docs/docs/concepts/langgraph_control_plane.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/docs/concepts/langgraph_control_plane.md b/docs/docs/concepts/langgraph_control_plane.md index ebc880ce5..006a57df9 100644 --- a/docs/docs/concepts/langgraph_control_plane.md +++ b/docs/docs/concepts/langgraph_control_plane.md @@ -112,6 +112,8 @@ After a deployment is ready, the control plane monitors the deployment and recor - Number of container restarts. - Number of replicas (this will increase with [autoscaling](../concepts/langgraph_data_plane.md#autoscaling)). - [Postgres](../concepts/langgraph_data_plane.md#postgres) CPU, memory usage, and disk usage. +- [LangGraph Server queue](../concepts/langgraph_server.md#persistence-and-task-queue) pending/active run count. +- [LangGraph Server API](../concepts/langgraph_server.md) success response count, error response count, and latency. These metrics are displayed as charts in the Control Plane UI. From 8118e905432748f0cfd85d2d3df0aa3dfcb74a17 Mon Sep 17 00:00:00 2001 From: ccurme Date: Mon, 7 Jul 2025 18:02:02 -0400 Subject: [PATCH 037/129] docs: update sql tutorial (#5389) --- docs/docs/tutorials/sql-agent.ipynb | 335 +++++++++------------------- 1 file changed, 109 insertions(+), 226 deletions(-) diff --git a/docs/docs/tutorials/sql-agent.ipynb b/docs/docs/tutorials/sql-agent.ipynb index 843179305..a06626f40 100644 --- a/docs/docs/tutorials/sql-agent.ipynb +++ b/docs/docs/tutorials/sql-agent.ipynb @@ -264,183 +264,109 @@ "text": [ "================================\u001b[1m Human Message \u001b[0m=================================\n", "\n", - "Which sales agent made the most in sales in 2009?\n", + "Which genre on average has the longest tracks?\n", "==================================\u001b[1m Ai Message \u001b[0m==================================\n", "Tool Calls:\n", - " sql_db_list_tables (call_0MfnhUYmRNVe03m6fYClaoa0)\n", - " Call ID: call_0MfnhUYmRNVe03m6fYClaoa0\n", + " sql_db_list_tables (call_d8lCgywSroCgpVl558nmXKwA)\n", + " Call ID: call_d8lCgywSroCgpVl558nmXKwA\n", " Args:\n", - " tool_input:\n", "=================================\u001b[1m Tool Message \u001b[0m=================================\n", "Name: sql_db_list_tables\n", "\n", "Album, Artist, Customer, Employee, Genre, Invoice, InvoiceLine, MediaType, Playlist, PlaylistTrack, Track\n", "==================================\u001b[1m Ai Message \u001b[0m==================================\n", "Tool Calls:\n", - " sql_db_schema (call_XwI6uES0HeZ2xCRxkkdWzB3I)\n", - " Call ID: call_XwI6uES0HeZ2xCRxkkdWzB3I\n", + " sql_db_schema (call_nNf6IIUcwMYLIkE0l6uWkZHe)\n", + " Call ID: call_nNf6IIUcwMYLIkE0l6uWkZHe\n", " Args:\n", - " table_names: Employee, Invoice, InvoiceLine\n", + " table_names: Genre, Track\n", "=================================\u001b[1m Tool Message \u001b[0m=================================\n", "Name: sql_db_schema\n", "\n", "\n", - "CREATE TABLE \"Employee\" (\n", - "\t\"EmployeeId\" INTEGER NOT NULL, \n", - "\t\"LastName\" NVARCHAR(20) NOT NULL, \n", - "\t\"FirstName\" NVARCHAR(20) NOT NULL, \n", - "\t\"Title\" NVARCHAR(30), \n", - "\t\"ReportsTo\" INTEGER, \n", - "\t\"BirthDate\" DATETIME, \n", - "\t\"HireDate\" DATETIME, \n", - "\t\"Address\" NVARCHAR(70), \n", - "\t\"City\" NVARCHAR(40), \n", - "\t\"State\" NVARCHAR(40), \n", - "\t\"Country\" NVARCHAR(40), \n", - "\t\"PostalCode\" NVARCHAR(10), \n", - "\t\"Phone\" NVARCHAR(24), \n", - "\t\"Fax\" NVARCHAR(24), \n", - "\t\"Email\" NVARCHAR(60), \n", - "\tPRIMARY KEY (\"EmployeeId\"), \n", - "\tFOREIGN KEY(\"ReportsTo\") REFERENCES \"Employee\" (\"EmployeeId\")\n", + "CREATE TABLE \"Genre\" (\n", + "\t\"GenreId\" INTEGER NOT NULL, \n", + "\t\"Name\" NVARCHAR(120), \n", + "\tPRIMARY KEY (\"GenreId\")\n", ")\n", "\n", "/*\n", - "3 rows from Employee table:\n", - "EmployeeId\tLastName\tFirstName\tTitle\tReportsTo\tBirthDate\tHireDate\tAddress\tCity\tState\tCountry\tPostalCode\tPhone\tFax\tEmail\n", - "1\tAdams\tAndrew\tGeneral Manager\tNone\t1962-02-18 00:00:00\t2002-08-14 00:00:00\t11120 Jasper Ave NW\tEdmonton\tAB\tCanada\tT5K 2N1\t+1 (780) 428-9482\t+1 (780) 428-3457\tandrew@chinookcorp.com\n", - "2\tEdwards\tNancy\tSales Manager\t1\t1958-12-08 00:00:00\t2002-05-01 00:00:00\t825 8 Ave SW\tCalgary\tAB\tCanada\tT2P 2T3\t+1 (403) 262-3443\t+1 (403) 262-3322\tnancy@chinookcorp.com\n", - "3\tPeacock\tJane\tSales Support Agent\t2\t1973-08-29 00:00:00\t2002-04-01 00:00:00\t1111 6 Ave SW\tCalgary\tAB\tCanada\tT2P 5M5\t+1 (403) 262-3443\t+1 (403) 262-6712\tjane@chinookcorp.com\n", + "3 rows from Genre table:\n", + "GenreId\tName\n", + "1\tRock\n", + "2\tJazz\n", + "3\tMetal\n", "*/\n", "\n", "\n", - "CREATE TABLE \"Invoice\" (\n", - "\t\"InvoiceId\" INTEGER NOT NULL, \n", - "\t\"CustomerId\" INTEGER NOT NULL, \n", - "\t\"InvoiceDate\" DATETIME NOT NULL, \n", - "\t\"BillingAddress\" NVARCHAR(70), \n", - "\t\"BillingCity\" NVARCHAR(40), \n", - "\t\"BillingState\" NVARCHAR(40), \n", - "\t\"BillingCountry\" NVARCHAR(40), \n", - "\t\"BillingPostalCode\" NVARCHAR(10), \n", - "\t\"Total\" NUMERIC(10, 2) NOT NULL, \n", - "\tPRIMARY KEY (\"InvoiceId\"), \n", - "\tFOREIGN KEY(\"CustomerId\") REFERENCES \"Customer\" (\"CustomerId\")\n", - ")\n", - "\n", - "/*\n", - "3 rows from Invoice table:\n", - "InvoiceId\tCustomerId\tInvoiceDate\tBillingAddress\tBillingCity\tBillingState\tBillingCountry\tBillingPostalCode\tTotal\n", - "1\t2\t2009-01-01 00:00:00\tTheodor-Heuss-Straße 34\tStuttgart\tNone\tGermany\t70174\t1.98\n", - "2\t4\t2009-01-02 00:00:00\tUllevålsveien 14\tOslo\tNone\tNorway\t0171\t3.96\n", - "3\t8\t2009-01-03 00:00:00\tGrétrystraat 63\tBrussels\tNone\tBelgium\t1000\t5.94\n", - "*/\n", - "\n", - "\n", - "CREATE TABLE \"InvoiceLine\" (\n", - "\t\"InvoiceLineId\" INTEGER NOT NULL, \n", - "\t\"InvoiceId\" INTEGER NOT NULL, \n", + "CREATE TABLE \"Track\" (\n", "\t\"TrackId\" INTEGER NOT NULL, \n", + "\t\"Name\" NVARCHAR(200) NOT NULL, \n", + "\t\"AlbumId\" INTEGER, \n", + "\t\"MediaTypeId\" INTEGER NOT NULL, \n", + "\t\"GenreId\" INTEGER, \n", + "\t\"Composer\" NVARCHAR(220), \n", + "\t\"Milliseconds\" INTEGER NOT NULL, \n", + "\t\"Bytes\" INTEGER, \n", "\t\"UnitPrice\" NUMERIC(10, 2) NOT NULL, \n", - "\t\"Quantity\" INTEGER NOT NULL, \n", - "\tPRIMARY KEY (\"InvoiceLineId\"), \n", - "\tFOREIGN KEY(\"TrackId\") REFERENCES \"Track\" (\"TrackId\"), \n", - "\tFOREIGN KEY(\"InvoiceId\") REFERENCES \"Invoice\" (\"InvoiceId\")\n", + "\tPRIMARY KEY (\"TrackId\"), \n", + "\tFOREIGN KEY(\"MediaTypeId\") REFERENCES \"MediaType\" (\"MediaTypeId\"), \n", + "\tFOREIGN KEY(\"GenreId\") REFERENCES \"Genre\" (\"GenreId\"), \n", + "\tFOREIGN KEY(\"AlbumId\") REFERENCES \"Album\" (\"AlbumId\")\n", ")\n", "\n", "/*\n", - "3 rows from InvoiceLine table:\n", - "InvoiceLineId\tInvoiceId\tTrackId\tUnitPrice\tQuantity\n", - "1\t1\t2\t0.99\t1\n", - "2\t1\t4\t0.99\t1\n", - "3\t2\t6\t0.99\t1\n", + "3 rows from Track table:\n", + "TrackId\tName\tAlbumId\tMediaTypeId\tGenreId\tComposer\tMilliseconds\tBytes\tUnitPrice\n", + "1\tFor Those About To Rock (We Salute You)\t1\t1\t1\tAngus Young, Malcolm Young, Brian Johnson\t343719\t11170334\t0.99\n", + "2\tBalls to the Wall\t2\t2\t1\tNone\t342562\t5510424\t0.99\n", + "3\tFast As a Shark\t3\t2\t1\tF. Baltes, S. Kaufman, U. Dirkscneider & W. Hoffman\t230619\t3990994\t0.99\n", "*/\n", "==================================\u001b[1m Ai Message \u001b[0m==================================\n", "Tool Calls:\n", - " sql_db_schema (call_dHE5FKSycFhYIkdPKtpEk9rM)\n", - " Call ID: call_dHE5FKSycFhYIkdPKtpEk9rM\n", + " sql_db_query_checker (call_urTRmtiGtTxkwHtscec7Fd2K)\n", + " Call ID: call_urTRmtiGtTxkwHtscec7Fd2K\n", " Args:\n", - " table_names: Customer\n", - "=================================\u001b[1m Tool Message \u001b[0m=================================\n", - "Name: sql_db_schema\n", - "\n", - "\n", - "CREATE TABLE \"Customer\" (\n", - "\t\"CustomerId\" INTEGER NOT NULL, \n", - "\t\"FirstName\" NVARCHAR(40) NOT NULL, \n", - "\t\"LastName\" NVARCHAR(20) NOT NULL, \n", - "\t\"Company\" NVARCHAR(80), \n", - "\t\"Address\" NVARCHAR(70), \n", - "\t\"City\" NVARCHAR(40), \n", - "\t\"State\" NVARCHAR(40), \n", - "\t\"Country\" NVARCHAR(40), \n", - "\t\"PostalCode\" NVARCHAR(10), \n", - "\t\"Phone\" NVARCHAR(24), \n", - "\t\"Fax\" NVARCHAR(24), \n", - "\t\"Email\" NVARCHAR(60) NOT NULL, \n", - "\t\"SupportRepId\" INTEGER, \n", - "\tPRIMARY KEY (\"CustomerId\"), \n", - "\tFOREIGN KEY(\"SupportRepId\") REFERENCES \"Employee\" (\"EmployeeId\")\n", - ")\n", - "\n", - "/*\n", - "3 rows from Customer table:\n", - "CustomerId\tFirstName\tLastName\tCompany\tAddress\tCity\tState\tCountry\tPostalCode\tPhone\tFax\tEmail\tSupportRepId\n", - "1\tLuís\tGonçalves\tEmbraer - Empresa Brasileira de Aeronáutica S.A.\tAv. Brigadeiro Faria Lima, 2170\tSão José dos Campos\tSP\tBrazil\t12227-000\t+55 (12) 3923-5555\t+55 (12) 3923-5566\tluisg@embraer.com.br\t3\n", - "2\tLeonie\tKöhler\tNone\tTheodor-Heuss-Straße 34\tStuttgart\tNone\tGermany\t70174\t+49 0711 2842222\tNone\tleonekohler@surfeu.de\t5\n", - "3\tFrançois\tTremblay\tNone\t1498 rue Bélanger\tMontréal\tQC\tCanada\tH2G 1A7\t+1 (514) 721-4711\tNone\tftremblay@gmail.com\t3\n", - "*/\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "Tool Calls:\n", - " sql_db_query_checker (call_QPtWY5cUZWgWhr13Kz6eBJkU)\n", - " Call ID: call_QPtWY5cUZWgWhr13Kz6eBJkU\n", - " Args:\n", - " query: SELECT e.EmployeeId, e.FirstName, e.LastName, SUM(i.Total) as TotalSales\n", - "FROM Employee e\n", - "JOIN Customer c ON e.EmployeeId = c.SupportRepId\n", - "JOIN Invoice i ON c.CustomerId = i.CustomerId\n", - "WHERE i.InvoiceDate BETWEEN '2009-01-01' AND '2009-12-31'\n", - "GROUP BY e.EmployeeId, e.FirstName, e.LastName\n", - "ORDER BY TotalSales DESC\n", + " query: SELECT Genre.Name, AVG(Track.Milliseconds) AS AvgMilliseconds\n", + "FROM Track\n", + "JOIN Genre ON Track.GenreId = Genre.GenreId\n", + "GROUP BY Genre.Name\n", + "ORDER BY AvgMilliseconds DESC\n", "LIMIT 1;\n", "=================================\u001b[1m Tool Message \u001b[0m=================================\n", "Name: sql_db_query_checker\n", "\n", "```sql\n", - "SELECT e.EmployeeId, e.FirstName, e.LastName, SUM(i.Total) as TotalSales\n", - "FROM Employee e\n", - "JOIN Customer c ON e.EmployeeId = c.SupportRepId\n", - "JOIN Invoice i ON c.CustomerId = i.CustomerId\n", - "WHERE i.InvoiceDate BETWEEN '2009-01-01' AND '2009-12-31'\n", - "GROUP BY e.EmployeeId, e.FirstName, e.LastName\n", - "ORDER BY TotalSales DESC\n", + "SELECT Genre.Name, AVG(Track.Milliseconds) AS AvgMilliseconds\n", + "FROM Track\n", + "JOIN Genre ON Track.GenreId = Genre.GenreId\n", + "GROUP BY Genre.Name\n", + "ORDER BY AvgMilliseconds DESC\n", "LIMIT 1;\n", "```\n", "==================================\u001b[1m Ai Message \u001b[0m==================================\n", "Tool Calls:\n", - " sql_db_query (call_X747YMElSeY5D3CfhE6KzLUj)\n", - " Call ID: call_X747YMElSeY5D3CfhE6KzLUj\n", + " sql_db_query (call_RNMqyUEMv0rvy0UxSwrXY2AV)\n", + " Call ID: call_RNMqyUEMv0rvy0UxSwrXY2AV\n", " Args:\n", - " query: SELECT e.EmployeeId, e.FirstName, e.LastName, SUM(i.Total) as TotalSales\n", - "FROM Employee e\n", - "JOIN Customer c ON e.EmployeeId = c.SupportRepId\n", - "JOIN Invoice i ON c.CustomerId = i.CustomerId\n", - "WHERE i.InvoiceDate BETWEEN '2009-01-01' AND '2009-12-31'\n", - "GROUP BY e.EmployeeId, e.FirstName, e.LastName\n", - "ORDER BY TotalSales DESC\n", + " query: SELECT Genre.Name, AVG(Track.Milliseconds) AS AvgMilliseconds\n", + "FROM Track\n", + "JOIN Genre ON Track.GenreId = Genre.GenreId\n", + "GROUP BY Genre.Name\n", + "ORDER BY AvgMilliseconds DESC\n", "LIMIT 1;\n", "=================================\u001b[1m Tool Message \u001b[0m=================================\n", "Name: sql_db_query\n", "\n", - "[(5, 'Steve', 'Johnson', 164.34)]\n", + "[('Sci Fi & Fantasy', 2911783.0384615385)]\n", "==================================\u001b[1m Ai Message \u001b[0m==================================\n", "\n", - "The sales agent who made the most in sales in 2009 was Steve Johnson, with total sales of 164.34.\n" + "The genre with the longest average track length is \"Sci Fi & Fantasy,\" with an average duration of about 2,911,783 milliseconds (approximately 48.5 minutes) per track.\n" ] } ], "source": [ - "question = \"Which sales agent made the most in sales in 2009?\"\n", + "question = \"Which genre on average has the longest tracks?\"\n", "\n", "for step in agent.stream(\n", " {\"messages\": [{\"role\": \"user\", \"content\": question}]},\n", @@ -484,7 +410,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 6, "id": "992f6ce6-f932-4f44-994c-c0ba5032dbd1", "metadata": {}, "outputs": [], @@ -606,7 +532,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 7, "id": "8b3ce09d-0eec-456d-8447-d04f79ccfc23", "metadata": {}, "outputs": [], @@ -652,13 +578,13 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 8, "id": "f728ed5f-7bcd-489e-9174-4e4725962335", "metadata": {}, "outputs": [ { "data": { - "image/png": "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", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAATQAAAKFCAIAAADNnYKFAAAAAXNSR0IArs4c6QAAIABJREFUeJzs3WdYE9nbBvCTTkIJvXcEkY6iIhZEQF17J/be/a91Laviir2uq666lrWsImAvK+oqa8MKShUrVektECAJKe+H8c1a6BLmAM/v8gPJzJw8Cd7MOTOTMxS5XI4AAPihkl0AAKBqEE4AMAXhBABTEE4AMAXhBABTEE4AMEUnuwDQXGWnicpLJGUlEmmlXFQhI7uc2rHYVCqdoqpBV9WgGVqqkF1O7ShwnhPUS9LTkpTEspTEMisHVURBqhp0TX2muEJKdl21Y7FpRXniMr5EKpGnJZVbOnCsnNQcOmtQKGRXVg0IJ6ir2HvFT64X2rioWTmqWjqqUpv5kCg1sSwlsSw5oczNW7ODrxbZ5VQBwglql5MmDD+WbeOq5jVAh0bHdUfTUA+vFiQ+4vedZGRmyya7li9AOEEtXj4pSXzE7z/VmKNOI7sWZRGVy26eyjaz47h5a5Jdy38gnKAm7+MEaUnlvQL0yS6kKdy/mK9tyHT01CC7kE8gnKBaz24W8vMkfmNbRTIJd8/l0eiUboN1yS4EwXlOUK3k+LK8D6JWlUyEkPdwPWG5NOlpCdmFIAgnqBo/X/I6uqTfFCOyCyGB32iDD+8q8j6IyC4Ewgmqcv9Snn1HXIZeTc/Rk3vvYh7ZVUA4wTeyUoXCMqmVoyrZhZDG2FqFyaKmJZWTWwaEE3zt5eOS7ngcESFRt0F6Sc9IHnlCOMEXhGWylASBgUWTXnoaFha2Zs2aBmy4fPnyS5cuKaEipGXAyM0Q8fMrldF4HUE4wRdSEgWWTd6hffnyZRNvWBdWjqopiWXKa79WcJ4TfOHfM7lWTmqW7TjKaDw1NfXAgQPR0dFyudzFxWXChAlubm4zZsx4/vw5scLJkyft7e1DQ0Pv37+fkJDAYrHat28/d+5cU1NThNDSpUtpNJqRkdGJEye2bt26dOlSYis1NbU7d+40erVZKcKEh3z/sQaN3nIdwZ4TfCErRaiuqZQvEorF4hkzZtBotD179uzfv59Opy9cuFAoFB48eNDJyal///5RUVH29vYxMTHbtm1zdXXdvn372rVrCwsLV61aRbTAYDDevXv37t27nTt3uru7R0ZGIoRWr16tjGQihNS16B/eVSij5TqC73OCL5SXSFQ1lPK/Ii0trbCwcPTo0fb29gihzZs3P3/+XCKRfLWas7NzWFiYubk5nU5HCFVWVi5cuJDP53O5XAqFkpmZ+ddff6moqCCERCLlnopU1aCXl3xdXlOCcIL/yKRILJSpqCqlP2Vubq6lpfXLL7/069evQ4cOrq6uHh4e365Go9E+fPiwY8eOhISEsrJPQ77CwkIul4sQsrKyIpLZBChUxOLQKgRStho5V/xDtxb8RyaVs9WV9feaxWIdOnSoW7duwcHBU6dOHTJkyLVr175d7e7du4sWLXJwcDh06NCzZ8/27t37VSNKKq9KbFWqjLyvkUM4wX/oTEqlSCYWKmvOEUtLywULFly9enXnzp1t2rQJDAx89erVV+tcuHDBzc1t7ty5dnZ2FAqltLRUScXURVFupSqXtC/KQTjBF1Q1aGV8pQy0UlNTL1++jBBSUVHp0aPHli1b6HR6UlLSV6vx+Xx9/f+uto+IiFBGMXVRViIl9yusEE7wBWMbTnmpUnpyfD4/KCho165dGRkZaWlpR48elUgkrq6uCCEzM7OEhIRnz54VFhba2dk9fvw4KipKIpGcOnWK2DYrK+vbBlkslr6+vmLlRi+4vERiZqeUU0p1BOEEX9A1Yr6LFSijZVdX159//jk8PHzo0KHDhw9/8eLFgQMHrK2tEULDhg2jUChz5859+/btnDlzvLy8Fi1a1KVLl+zs7LVr1zo4OPz444/Xr1//ts0pU6Y8e/Zs8eLFFRWNf87jfZxAS5/Z6M3WHVyEAL4gKJac3f1hUqAl2YWQ7/S29N7jDHWMSMsn7DnBF9Q06UaWKoXZZF5TioMyvlRdm0FiMuE8J6iCXXv1R3/n959a7Tetp0+f/vbt22+fl0qlcrmcuHjgWxcvXtTUVMr0WTExMQsWLKhykVQqpVKplGqmpr19+zaNVvUhn0d/57dxUWvUMusNurWgCmd3f+g6SNeommnR8/LyKiur3rWKRKLqTkUaGxs3ao1fyMzMbMBW1ZVUmC0OP549dpn5d9f1XSCcoArZqcKXT0payaR737p7Pt/KgWNuT+ahWhhzgqoZWqroGDHvX8wnuxASPL1eyFalkp5MCCeolmsPTbFQFvVPIdmFNKm4ByX5WaJOfbTJLgRBtxbU4tk/RRQq8sDyViKNLv4Bvzi/svsQXKZogXCCWkReyS/jS3uPI+07x03j3oV8mVTec4Qe2YX8B8IJavc6uvTO2bwu/XVcunHJrqXxJT4ueXg136u/rmMXvGYDhXCCOpFUyiOv5KcllTl05lo5qpJ7dr5RFOVWpiQI3sWW6RozvQbqqnCwO/4C4QT1UMaXxkUWpyaWiYUyK0c1GgOpatA1tBlSSTO4szWdSS0pqCzjS8UiWcabcioVWTmqOXhyNfUwvRQHwgkaorRIkp0iLOVXlpdIEQWVFTfyl0IePnzo6elJbdQb9Kpy6XI5UtWgqXEZBhYsri6jERtXBggnwFHXrl0jIiKaeN4D3GDXzwYAECCcAGAKwgkApiCcAGAKwgkApiCcAGAKwgkApiCcAGAKwgkApiCcAGAKwgkApiCcAGAKwgkApiCcAGAKwgkApiCcAGAKwgkApiCcAGAKwgkApiCcAGAKwgkApiCcAGAKwgkApiCcAEcGBgbV3Su+9YBwAhzl5OTAdOcQTgAwBeEEAFMQTgAwBeEEAFMQTgAwBeEEAFMQTgAwBeEEAFMQTgAwBeEEAFMQTgAwBeEEAFMQTgAwBeEEAFMQTgAwRYFvzQF8/PDDDwwGg0KhfPz40dDQkEqlSiQSc3PzAwcOkF0aCehkFwDAf2g0WmZmJvFzdnY2QkhDQ2Py5Mlk10UO6NYCjLi4uHzVlWvbtm3nzp3Jq4hMEE6AkdGjRxsZGSketubdJoQT4MXZ2dnFxUXx0MHBoVOnTqRWRCYIJ8DL6NGj9fX1id3muHHjyC6HTBBOgBdnZ2cHBweEULt27Tw9Pckuh0xwtBZ8UlEqzc8Sl5dKyC4E9e02pSCN1a/HiNfRpWTXgthqNF1jFked1vQvDec5AUII/ROc8/FdhaYeU4VDwv9CnFWK5bkZFcY27B8mGjbxS0M4Abq4P9PCQb2NmzrZheArNVHw6hl/+DxjKq3p5qGHcLZ2145mmdqpWzmpkV0I7rKSKxIfFQ6dY9JkrwgHhFq1rBShTEaBZNaFkTWbrcZIf13eZK8I4WzVCrJELDYMMuuKxaHmZ4qa7OUgnK1aGV+qrs0gu4pmQ0ObKSyVNdnLwamUVk0mk8NBh7qTSmWVkqYLJ+w5AcAUhBMATEE4AcAUhBMATEE4AcAUhBMATEE4AcAUhBMATEE4AcAUhBMATEE4AcAUhBPUz5Bhfif+OowQOnc+xNe/SafGS05+5+PrERf3orpF8fExTVmPskE4QQM5tHMaP25azetcuBi2acuaurQ2dLh/ZtbHRiqthYBvpYAGatfOqV07p5rXef36ZV2ays7OKi4uaqS6Wg4IJ2igc+dD9u3fefufpwih9PTUo8cOxMRGy+VyR0cX3qgJzs5uCxbNiI19jhC6efPvPw6ctLO1r7KdFzFRixbPQgiNHTe4a1fv9UE7Hj26H/Hvjbj4FyUl/Hb2TuPHT3N381CsLxKL9u3/9e69W3K5vJdPn+nT5tFoX39f/PqNK5evnEtJeWdl1aaXT+/hw0ZTKJTq6lTy59Rw0K0F30ssFi9YNINGo23ZvGfHtv10Gn3lqoVCoXDXzoPt2jn17t3/39tR1SUTIeTu5rFpwy6E0KmTl9YH7RAKhRs2rRKJRMuXrd24YZe5ueXKVQsLCwsU6+/es9XOrt3yZWvHjpkSGvbXtfBLXzV46/b1LVvX2tnaB5+8PG3q3LPngvfu21FdnSJR081sUF+w5wTfKyMjraiocPiw0UQC1wRujo17LpE0cP5bFRWVwwdD2Gw2l6uJEGpn73Tp8tn4hBjvHr7ECh3ad/Lz7Uuk+sbNq//+e3PggGGft3Dt2kUXF/cF85cjhLS0tCdPnLV1e9C4MVMKCwuqrJPFYjXGx9D4IJzge5mammtqam3e+ou/Xz831w5OTq6f90IboLy87PCRvTGx0QUF+cQzn49IO3p0Ufzs0M75QeS/n28rk8kSEmMnjJ+ueMbdvaNMJouLf+HZuVvj1qlsEE7wvVgs1m+/Hvr72sWz54KP/LnP2Nh00oQZ/v79GtZaTk72/IXT2rt3Wr1yo4ODM4VC8e/zxU0ZVFX/myuQw+Hw+cWfLxWLxZWVlUf+3Hfkz32fP19UVNi4dTYBCCdoBObmlrNnLZg8adbz50/Dr1/euDnQwtK6hnFmDe7c/UcsFi9ftpbNZn+1zyQIhRWKn8vKy4jer4KKigqHw+nt37/H/3eDCcZGplXWaWXVpk0buwbU2QTggBD4XunpqeHXLxPB8PLq8cuaLXQ6/c2bpIa1VlLCV1fXIJKJELp77/ZXK7x5+0rx8+vXL02Mzb5awcbGrlRQ6u7mQfxzcnTV0dbV1zeoss737980rM4mAOEE36ukhL91W9D+A7s+fMzIyEg7FXxUIpE4OboihExMzJKSEp6/eFZUVFhDC2bmlgihO3f+eZmUYG1tW1CQf/nKOYlE8uTpw+fPn3K5mrm52YqVI/698eTpQ4TQP7fCk5ISfHx6f9Xa9KnzIiPvXAu/JJPJ4uNjgtatWLRkllgsrrLOWk/Vkgi6teB7OTm5Llr487Hjf4SdOYkQ8ujQeeeOA5aW1gihgf2HvXmT9NPSuVs27/HoUO3d402MTfv2GXj02AEnR9dfd/6RlpZ84q9Dv+7a1NHDc9nSX0JCTwSfPlZaWtK//1CE0LSpcw8e2r18xY96evq8gAk/9B30VWvOzm4HD5w6FXz0j4O7hcIKRweX9et2slisKus0N7dU/ifUQHCvlFbt0d8FcjnVubsW2YU0D0lPiytKK72H6TXNy0G3FgBMQbcWNIUVKxckVPOVkX79hsyetaDJK2oGIJygKSxZtEpcKa5yEYfNafJymgcIJ2gKOjq6ZJfQ/MCYEwBMQTgBwBSEEwBMQTgBwBSEEwBMQTgBwBSEEwBMQTgBwBSEEwBMQThbNRUOjfr1tJKgWlQqlaPWdBfVQThbNS0DZnZaRR1WBAghlJtewdWFcIImYd6WIxRIZVL4Tm+dlBSILR3U6rBi44BwtmpUGvIepnf7dCbZhTQDt09ndemvw1ShNNkrwkwIAOWmiy4e+OjcXVtLn8niwBj0C+IKWWGW8OWT4j4TDE3bsJvypSGcACGExELZ8zvF+R9FZcUNnKm9ceXm5enp6TXdTqp66lp0LQOmaw9NjnpT/9mCcAIcde3aNSIiAtsbJTQNGHMCgCkIJwCYgnACgCkIJwCYgnACgCkIJwCYgnACgCkIJwCYgnACgCkIJwCYgnACgCkIJwCYgnACgCkIJwCYgnACgCkIJwCYgnACgCkIJwCYgnACgCkIJwCYgnACgCkIJwCYgnACgCkIJ8BR27ZtKRQc5pQmE4QT4Oj169cw3TmEEwBMQTgBwBSEEwBMQTgBwBSEEwBMQTgBwBSEEwBMQTgBwBSEEwBMQTgBwBSEEwBMQTgBwBSEEwBMQTgBwBSEEwBMUeBbcwAfvXv3ptPpVCo1KytLT0+PSqUihIyNjQ8fPkx2aSSgk10AAP/Jy8uj0WgIIQqFkp+fjxDicDg8Ho/susgB3VqAEU9Pz6+6cjY2Nn5+fuRVRCYIJ8DIpEmTNDU1FQ9VVVXHjBlDakVkgnACjHTu3NnOzk7x0MbGxt/fn9SKyAThBHiZMGECl8sldputdrRJgHACvHTp0sXW1hYhZGFh0bt3b7LLIRMcrW32ZFJ5flalTCoju5BGM3zA1LwPlSMGTsxOE5JdS6OhUinahkw6ox6T8cJ5zmZMUCx5cLkgOb7Uylm9JL+S7HJATbi6jJQEgUU7Va8BOpp6jLpsAuFsrspLpMHb03uPM9EyYJJdC6irkvzKf059HDbXVEOn9k4rhLNZkkrkf6xIHr/KhuxCQEOEbEset9yCrUareTUIZ7N0/2K+jhHbzF6V7EJAQ2SlVHx4U9prlH7Nq8HR2mYp43W5unadxi0AQ1wdRtrL8lpXg3A2SzQmVUMHhprNFUeDrsqlS8S1rAbhbJYKs0RyGYxHmrGCLBGFUstvEMIJAKYgnABgCsIJAKYgnABgCsIJAKYgnABgCsIJAKYgnABgCsIJAKYgnABgCsIJAKYgnKBq586H+PXuTPw8ZJjfib+a05zrV/++4OPrIZFIyC7ku0A4AZlSUt7zxgwguwpMQTgBmV6/eUl2CfiC2fdai/T01B2/boiLe2FsZNK9e68pk2czmUyE0PkLoY8f309KSmCyWK4u7adOnWtibNqwl7h85VxY2F8lpSWent2mTp7DGzNg1coNvr36IISu37hy+cq5lJR3VlZtevn0Hj5sNIVCOXrsANFb9vH1mDN74cgRY6trWS6Xnzt/+saNqxkf0izMrTw8PKdMnk3cVaW694UQKijIX7fh58TEOFNTc17AhP79hhDPJybGHT9x8NWrRK6mVhfP7hMnzFBVVUUIrQ1aTqFQunh237ZjHY1Gs2/r+MuaLRcvnTl+4qCGBrdP7wGzZs6nUCgIoUeP7kf8eyMu/kVJCb+dvdP48dPc3Twa9qHVAPacrUJ2dta8/012dnLbsX1/QMCE2xHXd+/ZihCKj4/Zs3ebo6NrUND25cvWFhUVbti4qmEvkfQq8dddm7y9/f46fr5nD7+g9SsQQsRtwm7dvr5l61o7W/vgk5enTZ179lzw3n07EEKTJ83iBUwwMDD893ZUDclECJ0/H3Ly1J8jho8JCb46cODwv69dDAk9UcP7QgjR6fTde7eOHzdt544D9vaOu37bnJOTjRD68DFjydI5QpFw756j69ZuT05+u3DRDGJ0SqfTExJjExJjz4SGH9j3V0Ji7PyF02Uy6dXLd9cEbg47c/LJk0iEkFAo3LBplUgkWr5s7cYNu8zNLVeuWlhYWNCwz60GsOdsFc6eC2apqEyeNItGo7V378hkMl+/fokQcnBwPnokzNTUnE6nI4QklZU/r1rIL+FzNbj1fYmbN69qa+tMnjSLTqd7efV48zbp5ct4YtG1axddXNwXzF+OENLS0p48cdbW7UHjxkzR0tKuY+Oxcc/btnXo02cAQmhA/6Hu7h0rystreF8IIYlEMmjgiM6dvBBC+vqGt26FJ71KMDAwvHUrnEFnrFu7ncvVRAgtWbx69NiBDyLv9PT2QwiJxeJ5c5cwGAwuV9Paqo1EKpk8aRZCyN3NQ1NT633yW0/PbioqKocPhrDZbKKFdvZOly6fjU+I8e7hW98PrWYQzlYhOfmtra090Q9ECPXtM7Bvn4EIIRqNlpn54fd9O5JeJZSVlRFLi4sKGxDO5JR37do5ESFHCPXo7nv8xCGEkEwmS0iMnTB+umJNd/eOMpksLv5F3f83Ozm5Hjy0Z+u2IBcX9y5deig63tW9L4KrS3viB02uFkJIJBQihBITY+3tHYlcIYQMDY2MjU3j4l8Q4TQxMWMwPk3OxOZwdLR1Fa2pclQFglLi5/LyssNH9sbERhcU5H/60IqL6vuJ1QrC2SqUlQk0NbW+fT4y8u6qwMVjx0yeOWO+jY1tVPSTpcvmNewlBIJSfX1DxUPF/36xWFxZWXnkz31H/tz3+fpFRYV1b3zE8DEcjmrkw7tbtq6l0+k9e/rPnP6jrq5ede+LoPhLQQwUFXW+ev3Sx/eLIWLR/3dKiX64wlcPCTk52fMXTmvv3mn1yo0ODs4UCsW/j2fd30vdQThbBVVVtbLysm+fv3rtgrOz27Spc4mHij1DA7BYKpLK/2adLyj8tEtRUVHhcDi9/fv3+HI/aWxUj8NOVCp1QP+hA/oPTU1Nfv786bETB8vKBBvX/1rd+6qBto6us7Mb0VlV4GpoVr/F1+7c/UcsFi9ftpbNZitpn0mAcLYKbds6XLl6TiKREDuT2xE3wsMvbdm8p6SEb2hgpFjt/v2IBr+EiYnZ27evFA8jI+8ofraxsSsVlCqOZ1ZWVmZlfdTXN6h74zduXLWza2dlZWNpaW1paV0qKP372oUa3lcNTdlY2978529Xl/aKvWJqarKpqXndiykp4auraxDJRAjdvXe77tvWCxytbRX69xsiFot3/roxKvrJ/Qf/Hjq8R0dXj0ajtbGxexb1+EVMlEQiOXP2FLFydk5WA16iq5d3WlpK8Oljcrn8WdTj+PgYxaLpU+dFRt65Fn5JJpPFx8cErVuxaMkssViMEDI1NS8oyH/w4E5GRloNjd+OuB74y08PH97jl/AfP35w/0GEk6NrDe+rhqZGjBgrk8n27tshFAozMtL+OLh7yrSA5JR3dX+n1ta2BQX5l6+ck0gkT54+fP78KZermZubXfcW6gj2nK2Cqan55k27t29fF379MovF6tN7wLRp8xBCU6bMKS8vW7V6UUVFxbChvOXL1mZlfVy+4seVP6+v70v06N5r6JBRx08cDDtz0sHBedq0eXPnTSIOrjg7ux08cOpU8NE/Du4WCiscHVzWr9vJYrEQQp6duzk7ua1es2TihBmTJs6orvHFi1bt/X37ytWLEELa2joD+g8dOWJcDe+rBhrqGkcOh4aEHJ85e1x6eqq9veNPS1bb2drX/Z369uqTlpZ84q9Dv+7a1NHDc9nSX0JCTwSfPubq2qFTxy71+cxqAbdjaJb2L30/eqk1rT73k1M2iUSSmprcps2n+1InvUqcM3fioT+CFc+Az53c8H7Ghlp+g9CtBY0jPiFm+swxv+3ekp2d9fJl/G+/bXZ0dLGxsSW7rmYMurWgrlasXJDw2Ujyc/36DZk9a8HiRSvDr1+eMm2Umpq6RwfPWbMWfH4Oo2bBp4+dPn2sykUWltZ7d//5HYU3VxBOUFdLFq0SV1Z9fw8Om0NcuzOg/9CGNT5w4HAfn6pvMk+ntdL/pa30bYMG0NHRrcNaDaSupq6upq689psjGHMCgCkIJwCYgnACgCkIJwCYgnACgCkIJwCYgnACgCkIJwCYgnACgCkIZ7NkaKGCEEZfSQH1ZWCuQqHW8huEcDZLUom8IFtIdhWggYrzxBUCKbWm74QjCGdzZeWkWpgtIrsK0EAFWSIbZ7VaV4NwNksdfLXevSjJeF1OdiGg3nLThbF3Cz371z5nL8yE0IwFb023bc/V1GVqG7HIrgXUgkJBhdmikoLKhIdF43+2qMsXXSGczduLf4tTXpbRaJSc9BY1BJVIpHR6bWOyZkXfTEUqkVm2U+3gV+1Eu1+BcAIcde3aNSIigpgErNWCMScAmIJwAoApCCcAmIJwAoApCCcAmIJwAoApCCcAmIJwAoApCCcAmIJwAoApCCcAmIJwAoApCCcAmIJwAoApCCcAmIJwAoApCCcAmIJwAoApCCcAmIJwAoApCCcAmIJwAoApCCcAmIJwAhy5uLiQXQL5IJwAR3FxcWSXQD4IJwCYgnACgCkIJwCYgnACgCkIJwCYgnACgCkIJwCYgnACgCkIJwCYgnACgCkIJwCYgnACgCkIJwCYgnACgCkIJwCYosjlcrJrAOCTESNGMJlMKpWalJRkbW3NYDCoVCqXy/3999/JLo0EdLILAOA/qampxA8UCiUlJQUhxGQyFyxYQHZd5IBuLcCIq6urTCb7/Blzc/NRo0aRVxGZIJwAI2PHjtXW1lY8ZLFYAQEBpFZEJggnwEivXr3Mzc0VD01NTYcOHUpqRWSCcAK8BAQEqKmpEbtNHo9HdjlkgnACvPTp08fS0lIul5uYmLTm3SYcrW29ykulZJdQrZHDxmVm/MYbORHnIlVUaVQl79rgPGfr8vaFIOZucX6miKkCnabvQ0FsVZp7T812nTSU9QoQztYj9i4/412FS3dtLQMm2bW0BEU54pePi7X06Z37atdh9XqDcLYWUf8UFeRUeg3UJ7uQlibqZj6DhboN0m30lqFv0yrw8yQ56SJIpjJ49NYV8KW5GaJGbxnC2SrkZFRQqBSyq2ix6HRqTrqw0ZuFcLYKgmKJvhmb7CpaLF1TFQFf0ujNwqmUVkFUIYNjC8ojEctEZbI6rFg/sOcEAFMQTgAwBeEEAFMQTgAwBeEEAFMQTgAwBeEEAFMQTgAwBeEEAFMQTgAwBeEEAFMQTtAMjAz44fCRVjfpO4QTNKa1QcuvhV8iu4oWAsIJGtPr1y/JLqHlgK+MgaoVFRVu2hyY+DLO3Mxy8OCRHz6k33/w7/GjZxFChYUF+/bvTEiMFQqFHTt2mTBumpmZBULIx9cDIbRt+7r9B369culODY2np6cePXYgJjZaLpc7OrrwRk1wdnZDCEml0jNnTx0/cRAh5NDOedLEmcTzCCE6nXH+QuiBP3YxmUwnJ7cVy4O4GlyEkEQiOfLnvsdPHuTmZjs5uQ0dPMrTsxuxyZBhfpMmzvzwIf3c+dOamlpdPLvPm7tk4+bVkZF3zcwsxo2Z0rt3f4SQQCA4c/bk02ePUlPf62jrenl5T5k8W0VFpUk+5prAnhNUbev2oPSM1G1b961ft/PJk8gnTyKpVCqRn4WLZ8bERi9c8POfh0O1NLXnzJ34MfMDQuj6tUiE0E9LVtecTLFYvGDRDBqNtmXznh3b9tNp9JWrFgqFQoTQwUN7Ll06E7R2+6qfN+jpGSxb8b/09E+3Nrp771ZZmWDL5j0/LQlMSIg5enQ/8fzuPVvPngseOiQg+NQV7x6+a9YuvXvvNrGIwWCEhB43N7e8Ef5w2tS54dcvL1w0w7dX339uPPbp6b9tx7pSQSlORd8DAAAgAElEQVRC6PyFkODTxwJGjd+4YdfMmfPv3P2H+OtAOggnqAKfX/z48YNRI8c7tHPS0dFdvGhVdnYmsSg+PiY9PfXnFes6d/LS1taZPWuBBlfz3LngujeekZFWVFQ4fNhoO1t7GxvbNYGb167dJpFI+CX8sDMnebyJHT08u3b1XrJ4lUcHz4LCfGIrDkd1/Lip7m4e3j18vby84+JfIIREItGNm1fHjJ40aOBwrga33w+DfXv1PfHXIcVr2baxHzRwOJPJ7OntjxBydHTx6elPp9N9evaWSCTpaSkIoVEjxx0+eLqnt5+7m0f3bj4+PXs/ffawsT/RhoBuLajC++S3CCEnJ1fioZqaWvv2ndIzUhFC8QkxDAajvXtHYhGFQnFz7RAb97zujZuammtqam3e+ou/Xz831w5OTq7ubh4IodjY5wghe3tHYjU6nR60dptiK2cnN8XPXA1NsUiEEHrzJkksFnf06KJY5ObaIfz6ZX4Jn+j0mptbEs+rqqoihCwtbYiHbDYHIVRaWkLsYJ9FPdq8Zc27928kEglCSEtLKVNd1heEE1SB+F+rqqqmeEZDg0v8IBCUVlZWEsNLBU1Nrbo3zmKxfvv10N/XLp49F3zkz33GxqaTJszw9+8nEJQihFRYVQ/26PT//q9SKBRFMQih/82f+tXKRYUFRDgVaxKoVU3SfvDQnmvXLs6cOb+jRxcDA8PDR37H5IAzhBNUgcVSQQhVisWKZ4qKC4kfdHR02Wz2hvW/fr4+jUqrV/vm5pazZy2YPGnW8+dPw69f3rg50MLSmvhbUF5eVvd2dHT1EEKLF600MTH7/Hl9fcM6tiCXy69cPTdi+JgB/T/dl4UIPA4gnKAKxNHXlNT3lpbWxPHM58+fGhgYIYRsbOwqKir09Q1NjE2JlTOzPmpy67HnTE9PTXwZ90PfQSoqKl5ePTp37tq3X9c3b5J6evvT6fTYuOft2jkRsVmxcoGPt3+fPgOqa8rUxJzFYiGEiI4xcZBZLpdzOJw6FlNZWVlRUaGr+2lGX7FY/PDRvbq/F6WCA0KgCibGphYWVsdPHPyY+UEgEOz6bZORkQmxqEP7Tp06eW3fvi4nJ5vPL7546cys2eOvX79M9Ff19PSjoh6/iIkiBm9VKinhb90WtP/Arg8fMzIy0k4FH5VIJE6Ormpqav5+/S5dOhN+/fKLmKg9e7dFRz8hglodDoczaeLME38dio+PEYvFd+/dXrJ0zq7fNtf9nTKZTHNzy/Drlz9mfuDzi7duD3J2cistLSkvL6/PB6YUsOcEVVu6JHD7zvXjJwy1sbb19++nqqqWlJRALNq0YdflK+eC1q94+TLezMzCz++HYcM+3Uhz7JgpR48dePrs4engq+pq6lW27OTkumjhz8eO/xF25iRCyKND5507DhC76Pk/Ltv12+YdOzdIpdI2NnZBv2xTHNGpDi9ggo2NXXDIsefPn6qqqjk6uCxevKpe73T1yo2/79sxafIIFRWVObMXubl5PH36cMKkYWfDrternUYH90ppFR79XSCXU52716PzyecXC4VCA4NPg7cVKxfQafR1QduVVmMz9jqKLygU9xyp17jNQrcWVG1t0PKFi2bcf/Avn1/818kj0dFPBg0aQXZRrQvsOVuFhuw5S/jbtgelp6fm5eVYmFuNHzeta1fvum8+cFDP6hYtW/ZLt67VLm2OlLTnhHC2Cg0I53fK+v8rir6lpamNw5WrjUhJ4YQDQkApjAyNyS6h2YMxJwCYgnACgCkIJwCYgnACgCkIJwCYgnACgCkIJwCYgnACgCkIJwCYgiuEWgUmmyqTwR9iZWEwaSqqjf/xwi+sVVDXpOdlVJBdRYuVm1Ghym38/RyEs1XQN2PDFxyURyqV6Zs1/qX8EM5WQVOPbmDGeng5l+xCWqBnN/LVuTQDc1ajtwxfGWtF4u7z099WOHfV1jZgIkodNgA1KswWv3pSpG3E7OivlO/iQThbl7cvBLH3ivMyRQwm1umUSKR0ev2m22x6qhp0N2/Ndp00lNQ+hLOVqiiTkl1CTfr163fhwgVi2ks8sTk0Zfc+4FRKK8VWxXq/JJYI2Ko0FgvrIpUNDggBgCkIJwCYgnACgCkIJwCYgnACgCkIJwCYgnACgCkIJwCYgnACgCkIJwCYgnACgCkIJwCYgnACgCkIJwCYgnACgCkIJwCYgnACgCkIJwCYgnACgCkIJwCYgnACgCkIJwCYgnACHLm4uJBdAvkgnABHcXFxZJdAPggnAJiCcAKAKQgnAJiCcAKAKQgnAJiCcAKAKQgnAJiCcAKAKQgnAJiCcAKAKQgnAJiCcAKAKQgnAJiCcAKAKQgnAJiCcAKAKYpcLie7BgA+ad++PfEDhUJBCMnlciqVOnPmzOnTp5NdGglgzwkwYmNjQ6VSqVQqhUKhUChUKtXS0nLcuHFk10UOCCfAyJgxY1gsluIhnU4fPHgwm80mtSjSQDgBRoYOHWpmZqZ4aGJiMnLkSFIrIhOEE+BlxIgRxM6TTqcPGTJERUWF7IpIA+EEeBkxYgSx8zQ1NR0+fDjZ5ZAJwgmwM3LkSCaTOXDgQA6HQ3YtZIJTKS1HdERRamIZjUbNSa8gu5bvJZFI6XQa2VV8L30LtkQss2yn2rG3VgM2h3C2EKc2p7f10NTUZ+gYqcCvFBMUKirMEvHzxXH3CyeusqTUs58K4WwJTm1O7+Cna2LbqjuBOCvIFEeEfJyy1qpeW0E4m71nN4toDJptew2yCwE1SYkXlPPFnv21674JHBBq9lISBVoGrDqsCMikbcR6F1dar00gnM0enUHVMYRw4o6ry1DVoEsq67EJhLPZy0qtkFPILgLUQW6GUC6rxygSwgkApiCcAGAKwgkApiCcAGAKwgkApiCcAGAKwgkApiCcAGAKwgkApiCcAGAKwgkApiCcAGAKwgkApiCcAAspKe95YwaQXQVeIJwAC6/fvCS7BOxAOFujy1fOjRs/ZNCQXhs3B+bkZPv4etyOuEEsSkyMW7ps3qDBPuMnDtu3/9eysjLi+bVBy4PWrXj48N6gIb38+3jOXzg9KSlB0eD1G1fmzJv0Q/9uc+ZNOnsuWDH3zeChvufOnZ6/cLqPr0dJaQlC6PyF0KXL5g0c1HP4yD5B61Z8zPyAEDp67MCWrWuJSs6cPYUQKiwsWL9hJW/MgCHD/DZsWp2RkVaX93U74sa48UN8fD3mzJuUlZ3p4+tx6/Z1hFBI6Ikf+ndTrEa8UGTk3ZqLX/PL0qB1K/44uNvH1+PY8YM+vh4JCbGKRt69e+Pj60HUryQQzlYn6VXir7s2eXv7/XX8fM8efkHrVyCEqFQqQujDx4wlS+cIRcK9e46uW7s9OfntwkUzJBIJMf964su4f25dO7D/r/C/H7CYrE1b1hAN3rp9fcvWtXa29sEnL0+bOvfsueC9+3YQixgMxtVrF9q0abtt6+8cNic+PmbP3m2Ojq5BQduXL1tbVFS4YeMqhNDkSbN4ARMMDAz/vR01csRYqVS6cPHMmNjohQt+/vNwqJam9py5E2uNQXp66oaNq3x9+166GDFl8uyNm1YTZde8Vc3FJ6e8S055t2HdziGDRxoYGN66Ha7Y8O69W1yuprGRyff9NmoC4Wx1bt68qq2tM3nSLC5X08urR0cPT8WiW7fCGXTGurXbzc0tLS2tlyxe/fbd6weRd4ilFeXlPy0JNDYyodPpvr36ZmSklZeXI4SuXbvo4uK+YP5yLS3t9u4dJ0+cdfFiWFFRIXEnPw0N7v/mLvHo0JlOpzs4OB89EjZ2zGR3N4+OHp6jRo5LSkrgl/C/qjA+PiY9PfXnFes6d/LS1taZPWuBBlfz3Lngmt/XjZtXNTW1JoyfrqGu4dGh88D+w+ryadRcfHZ25to1W728emhqag0cMDwi4oZUKiU2/PfOP316DyBuVagkEM5WJznlXbt2TopdSo/uvopFiYmx9vaOXK4m8dDQ0MjY2DQu/gXx0MzcUjEFu5qaOkKotLREJpMlJMZ29OiiaMTdvaNMJlNs1dbOQbGIRqNlZn5Y8fP8AYO8fXw9fl61ECFUXFT4VYXxCTEMBqO9e0fiIYVCcXPtEBv3vOb39e7d67ZtHWi0T1NROzq5Enf4rGGTWou3MLdS3Kylf78hgjLBkyeRCKHk5HcfP2b0+2FwzSV9p1p2+qDlEQhK9fUNFQ8VUSQWvXr90sfX4/P1iwoLiB+Iru9XxGJxZWXlkT/3Hflz3xdb/X/kmEym4snIyLurAhePHTN55oz5Nja2UdFPli6bV2WFlZWVX5WhqVnLpOnFxUUmJv/doYytUvuNA2sv/rP7EWpqanX18r4dcd3Lq8fde7fsbO0tLOo3D219QThbHRZLRVL53yRwBYX5ip+1dXSdnd0mT5r1+fpcDU1UPRUVFQ6H09u/f48evp8/b2xk+u3KV69dcHZ2mzZ1LvFQIKh6qkgdHV02m71h/a+fP0mj1nJ3BnV1DZFYpHhYXlFe3ZpSmbQBxRM7z7XrlpeUljyIvNPvhyE11/P9IJytjomJ2du3rxQPI/9/SIkQsrG2vfnP364u7RU7ydTUZFNT85obtLGxKxWUurt92tFVVlZmZX3U1zf4ds2SEr6hgZHi4f37EdU1WFFRoa9vaGL8KSSZWR81ubXsOQ0NjZ88jZTJZETxsbHRikUMBlMkEkkkEqIzn56W0oDiEUKdO3fV0OCGhp5IS0vx8+1bcz3fD8acrU5XL++0tJTg08fkcvmzqMfx8TGKRSNGjJXJZHv37RAKhRkZaX8c3D1lWkByyruaG5w+dV5k5J1r4ZdkMll8fEzQuhWLlswSi8XfrtnGxu5Z1OMXMVESiYQ4ZYIQys7JQgiZmpoXFOQ/eHAnIyOtQ/tOnTp5bd++Licnm88vvnjpzKzZ469fv1xzGd7efvn5efv2/yqRSB4/fhB25qRikYODs1wuv37jCnEeJTjkWAOKJ0a/P/QddO78aa8uPT4fDigJhLPV6dG919Aho46fODh0uP+Fi6HTps0jThsghDTUNY4cDmWrsGfOHjdh0vCY2Oiflqy2s7WvuUFnZ7eDB07Fxb0YOtx/ydI5ZWWC9et2fn73eIUpU+Z07uS1avWi3n275ORkL1+21r6tw/IVP966fd2zczdnJ7fVa5YQZ1w3bdjl7e0XtH7FkGF+5y+E+Pn9MGwYr+YyOnp4zpzx46NH9/z7eG7YuOrzznk7e8fZsxYcPLjbx9cjaP2KqZPnKI4V1b14gpeXt0gk6u3fvw6f9PeCe6U0e78veTduZZuqDtZUTSKRpKYmt2ljRzxMepU4Z+7EQ38EK55pGYqLi4YO9w9cvcmnp38jNhsSeuLy5bMn/7pY5eGxmgVvej9lrTWDVdezLzDmbHXiE2IWLZ41ZPDIgFETCgvzd+/Z6ujoYmNjS3ZduIuJic7M+nD8xMFf1mxtQDIbAMLZ6ri7eSxetDL8+uUp00apqal7dPCcNWuBUk+mN5bg08dOnz5W5SILS+u9u/9U6qsvXT6PRqNNnTKncycvpb6QAnRrm736dmubL5FIJK6s5lANoqipqTV5RfUD3VrQYrFYrBoO1bQ8reDvLQDNE4QTAExBOAHAFIQTAExBOAHAFIQTAExBOAHAFIQTAExBOJs5OdIzUWkO194BpGOsgupzPR6Es5mjILFIWpJf9UVtAB/lJZKSQjFDpR5/RyGczZ6ZnWppoYTsKkAtSgoqLR3qd/UvhLN5Kysr02ubf+dsFtmFgFrcPZvdpZ92vTaBcDZLAoEAIfTw4cP+/fvn5mVPWm0Zsi2lMBs6tzji51We3ZU6aoEZW62WOcq+Al8Za2aKiop++uknAwODDRs25OXl6enpEc+XlUgjL+e/jSm1cVEvKaisrRncSSVSGr1+/5W/n0goolAoFCqFgij/oTb8aJuGDj0loczKUbVLfx2uLqO+m0M4m4djx449f/589+7deXl5mZmZrq6uVa4mk6K8TJFc2ux/pzNmzNi7d+/nc942gVWrVqWnp9NoNDabzWKxmEwmjUaTSCRsNnvt2rUNaJBCoegaM2mMBsYbvs+Jrw8fPly7dm348OE6OjoCgWDu3LkIIT09PcXe8ltUGjIwawnfeLR11jO25tR6p5PGNXfx2GXLluUVFqIv59ONiopqyjIUYMyJnZcvX6ampiKE9u3bhxDS1NRECM2bN69t27Zkl9Z0duzY0cTJRAi5u7t369btqyc1NDSauAwF6NbiIicnx8DAYP/+/Y8ePdq4caOpadWTjrcSjx8/7tSpU9PMo/U5Pp8/fvz4zMxM4qFMJgsPDzcwqHqOaWWDPSf5Xrx44e/v/+TJE4TQmDFjTpw40cqTiRBavHhxZSUJh7W4XO7o0aMVNy8yMDCYOnXqn38qd+qw6kA4ySEQCIKCglatWkV0XMPCwgYNGkT85yC7NCx4enoq7hfWxEaPHm1jYyOTyVRVVcPDw69evSoUCkeMGPHyZVPfexu6tU0qIiIiOjr6p59+ysjIePHiRe/evRV/pAE+Xrx4sWjRon///VfxTGpqamBgoIuLy5IlS5qsDNhzKp1UKg0PDy8rK5NKpdevX/fw8EAImZmZDRo0CJJZncePH8tkMrJe3d3d/fNkIoQsLS2J4UavXr0ePHjQNGXAnlNZSktLKyoq9PX1J06caG5uHhgYSNyPBNRF165dIyIiMJwIs6SkJDAwkMPhrFu3Ttkdb9hzNjKhUIgQOnHixKBBg0pLSxFCx48fX7duHSSzXkgcc9ZMQ0Nj165dPXv27Nq16+XLtdz47DvBnrPRvHnzZuvWrb169RozZkxqaqqlpSXZFQHlCgoKyszMDAoK0tfXV0b7EM7vIhKJTp8+LRAI5s2bFxsbK5fL3dzcyC6qJSDrPGd9RUVFBQYGjho1atKkSY3eOO5vHk/v378PDg5GCKWkpAgEgsGDByOEXF1dIZmNhazznPXl4eFx7do1gUAwatSoV69e1WGLeoBw1kNiYqJIJKqsrFy5ciVxWy57e/t58+aZmZmRXVpL07VrVzzHnFWaN2/e5s2b169fv3PnzkZsFrq1tRMIBGpqajNnzhQKhYcOHWIwGM3ihnmg6QUHB//5559BQUFeXo1wm0AIZ02uXLmyZ8+eXbt2OTg4FBYWamvX75vsoMEiIyO7dOmC/5jzW3w+PzAwUE1NLSgo6Dt3/s3vzStbZmbmunXrwsLCEEKGhoYhISEODg4IIUhmU1q6dGmzGHN+i8vl/vbbbz169PDy8rpy5cr3NAXh/CQiIoII5Nu3b11dXYcMGYIQ6tixI2SSFM1rzPmtPn36PHny5Pnz57Nnz87Ly2tYI626W1tZWfnkyZNu3bpFR0eHhoaOHTu2uhkGAGiYZ8+eBQYG8ni8iRMn1nfb1rjnFAgEUqlUJBL16NEjOjoaIdShQ4etW7dCMvERGRlJ4rW1jahjx47h4eElJSUBAQGvX7+u17ataM8pkUjodPqaNWvu3r178+ZNGo3WrDtOLRu219Y22Pv379esWdOhQ4eFCxfWcZNWsed8+PDh9OnTExMTEUIjRoy4c+cOMXcT2XWBajX3Mee3bGxsTp48aWBg4Ofn9/Dhw7ps0mL3nCUlJefOnTM2Nu7Tp8+1a9eMjIzc3d3JLgoAVFxcHBgYqKGhERQUVPO5opa253z//n1ERARC6NatW+Xl5Z06dUII9evXD5LZvLSYMee3NDU1d+/e3a1bN09Pz6tXr9awZosKZ1xcnOLCumHDhs2dO1dLS4vsokBDHDlyRCJpyTeA6du379OnT58+fXr48OHq1mlR4bSzswsJCfHx8SG7EPC9dHV1m+PlQfU1f/780NDQ6pa2nPeflZW1Y8cOsqsAjWPr1q1NP28tKWr4G9RywlleXh4XF0d2FaBxtOAxZ921nHAaGxsTM02CFqD5XlvbiFpOONlstrOzM9lVgMbR8s5zNkDLCWdWVtaGDRvIrgI0jtYz5qxBywknjDlbEhhztqhwwpizJYExZ4sKJ4w5WxIYc7aocMKYsyWBMWeLCieMOVsSGHO2qHDCmLMlgTFniwonjDlbEhhztqhwwpizJYExZ4sKJ4w5WxIYc7aocMKYsyWBMWeLCieMOVsSGHMihJp9t37hwoX37t2Ty+UUCkUmk1GpVGJWpOfPn5NdGmi4rVu3kl0C+Zr9nnP69On6+vpUKpVCodBoNAqFIpfLYcag5g7GnC0hnA4ODk5OTp8/o6OjM2bMGPIqAo0AxpwtIZwIoQkTJujo6CgempmZ+fr6kloR+F4w5mwh4XR2dlYcClJVVR07dizZFYHvBec5W0g4EUKTJk0idp7W1tZ+fn5klwO+171792DM2ULC6eTk5OrqqqKiAqPNlmHFihUw5qzldgyVIvnzf4ty04VlpdImrKohxOLKosJCA0MDsguphaYug0KlmFiznbpqkF0Ldvr27ctkMhFCBQUFWlpaVCpVIpEYGxvXMPNys1ZQUDBmzJgbN25UubSmbn1uhuj87x/cvHXsPDRZqs1idG5CdgG1o1GphTnC0hLp6W3pAYvMqDQK2RVhhEajZWZmEj9nZ2cTN4oeP3482XWRo9pwfnwvfHytYOwKm6atp1XQ1GcghPRMWKE7M0b/ZE52ORhxdnbOzs4mbqhBsLW19fb2JrUo0lQ95pRJ0YNLeb5jjJu8nlbEwILt2EX7/sV8sgvBCI/HMzIyUjxszbvNasOZ8bacqUKj0aHHpVzGNpxXUSVkV4ERNzc3e3t7xUN7e/uuXbuSWhGZqg5ncY7YyIrT5MW0OiwOVc9EpbSwJd9Oq77GjBmjq6tL7DZ5PB7Z5ZCp6nAKy2WSytZ+lqlpCIor4aP+XPv27du1a0eMNrt37052OWRq7RdhgO8lR+UCaVmJpEIglVQ2zl3S+/WcnJ9OG9ArIDmhrFEapNMpbDUaR4POUadRms9YDcIJGqK0UJKaVPb2RZmwQiYormSq0NS0WGJRY50M1/3Ba1FJBnqcwW+U5pgqNEGRSFwhVdVgsNgUWzdVSwc1ri7u//lxrw/gprRIcu9CflGuhK7CVNPV0LZhk11Rnej+/w+CwopXL8pjH2RzdWg9hupq6TPILawGEE5QD3fPFbyJKdW31jZ1VSW7lgZS02arabMRQiW55ed/z7Sw5/iN1iO7qKq1kGtrgbJJJfLj69KK+HRbLzOuYXNN5uc09Dk2nqYCIevw6hRhOY7H5CCcoHbCMtkfy5MN2xloGqmRXUsj0zRUtWhvfHxdahkfuxNaEE5QizK+NOy3Dw6+lixVfIdn34OhQm/bw+L8vix+Pl7fg4Fwglqc2Jhq6tLyL+Q0czP+a2Ma2VV8AcIJanL5ULZVB+NW8tUZWy+z83szya7iPxBOUK2XT0rKBRQVdSbZhTQRliq9UkaPuVtMdiGfQDhBtR5cytez1ia7iialb6P98GoB2VV8AuEEVYu7z9e14NKYret/CIVKMbTVjrqFxc5T6R/9yIAfDh/5vVGaSk5+5+PrERf3olFaAzWLi+RztPD9ZtK5K1u37RmtjJbVdDjxD1tHOEFzJCiWVAikrWe0+Tkmhy6XUwqzxWQXAuEEVUl9WcY1aAmXATWMup5aSmI52VU03rW1Uqn0zNlTx08cRAg5tHOeNHGms7Pbp9egM85fCD3wxy4mk+nk5LZieRBXg4sQkkgkR/7c9/jJg9zcbCcnt6GDR3l6diM2KSkt+eOP366FX+JyNT06dJ4+7X8GBoZfveKJvw4Hnz76686D7ewdaygsNTV585Y1796/0dTUCly16dCRvZYW1osXrQwJPXH8xMHwvx8Qq+XkZPPGDFgftKNrV2+EUGJi3PETB1+9SuRqanXx7D5xwgxVVVWE0JpfltJoNAMDo5DQEyt/Xrdj54axY6aMGztF8SEMHe4/dMioyZNmNdYHS4rsNBFdRYm7zWfPrz56diEr552RQRs3Z7/uXXjEvEFrNvXp4zujrLz4ZsRhFpPd1tZz8A+LNDR0EUIiUfmps4HvkqOMDNp06ThMebUhhJgcRlYq+eFstD3nwUN7Ll06E7R2+6qfN+jpGSxb8b/09FRi0d17t8rKBFs27/lpSWBCQszRo/uJ53fv2Xr2XPDQIQHBp6549/Bds3bp3Xu3idAuX/FjfkHezh0H/jfvp9y8nOU//yiRfHF11a3b148eO7B65caakymVSpet+J+Wts7pU1e2bt4bEnYiIyONwajlSpcPHzOWLJ0jFAn37jm6bu325OS3CxfNIApgMBjJKe+SU95tWLfTo4OnT8/et26HKzZ8ERNVWlri26vvd3yQWBDwJQyWsuZbfB57I/TCOlPjtj8vuvCD/+x7D0MuXfuVWESjMe48OEmhUINW3Fz6Y1hKWuyNfw8Ri8IubsgvyJg5ae/E0Vuyc5NfvYlUUnkIIQaLVlZC/tV8jbPn5Jfww86cXDB/eUcPT4RQ585dy8vLCgrzzc0tEUIcjur4cVOJNSMf3o2Lf4EQEolEN25eHTN60qCBwxFC/X4YnJAQe+KvQ949fB8/eZCUlHD86FliczMzi7AzJwsL/zvAHRMTvWXrLzNn/Ejs5WoQFf0kNzdn88bdenr6enr68/+3jDdmQM1T9SKEbt0KZ9AZ69Zu53I1EUJLFq8ePXbgg8g7Pb39KBRKdnbmgX1/qaioIIT69xsSfv3y23evbdu0RQjdvXvLvq0DUXazVsaXamsp6xtLT6MvWVu4Dxu4FCGkrqbdx3dG2IX1vt6T1NW0EUK62qZ+3pMRQmy2ets2nh8+vkII8UvyYhNuBQxdbWHmhBAa0Gfey1f3lVQeQojOpJeXkh/Oxtlzpqa8RwjZ//9OjE6nB63d5u7mQTx0dnJTrMnV0BSLRAihN2+SxGJxR48uikVurh2Sk9/xS/jv37/lcDiK/+J2tvarfl6vr/9ptuj0jNRVgYt8e/XlBZy/ep8AABQXSURBVEyotbD379+oqKhYWX2a4NPAwFBf36DWcCYmxtrbOxLJRAgZGhoZG5sSf1MQQhbmVkQyEUKOji6mpua3boUjhORy+d17t/39+9ftM8Mak02jM5Sy55TJZCnpcXa2nRXP2Fp7yOWylNQY4qGpSTvFIjZbQygSIIQKiz4ihAz0rRSLzD5brdHRGFR2k1xITKFQrK2tq1vaOH8dBYJShJAKS6Xq1/jsjjSKKUmJTf43f+pXKxcVFpSVCVjVNIUQ+m33FolEoq2tU90KX7RWVMhmf3E+QEWl9i8HCwSlr16/9PH1+Kow4gcmi/X580MGjTwZ/OesmfNfxERVVJT7+f1Ql8IwJ5fJxMJKBrvx8ymRiKXSyuu3Dly/deDz50vLCv//xyouFSwr5yOEWMz/fpVMphK/5F0plFSKm+IWB3K5PDk5ubqljRNOVVU1hFB5eT1mfNHR1UMILV600sTE7PPn9fUNORzViopy4jbV327Yp/cAe3vHHTs3eHh4tnfvWPOrqKtriMWiz5+pqKh6oC+V/ffL0NbRdXZ2++qgDldDs8oN/Xv3P3Dwt6joJ48e3/fq0kNDvSXcZEFVgy5ptDlHvsBkqrCYnA5u/Vwce33+vI52TbP1q3K4CCFxpVDxjFDUONMLVUkilqpqkD8PQeN0a9u0aUun02PjPt3pXS6XL/95/o0bV2vYxNTEnMViIYTc3TyIf5YW1hbmVhwOx76tg1AofP0miVgzPT11waIZ79+/JR729u8/oP/QHt17bdi4il9SyxwzRobGZWVlikNTHzM/5OXlEj8zGEyRSKQ4zpSelqLYysbaNjc329WlvaI2LU3t6kaSGuoaPb397t69FRFxw9+vX90+MNzpmbBk0saZretbxkZ2FcLSNtYdiH+W5i7q6jqa3JpucqOlaYwQSk2PIx5KJJVv3z9VUnnEN8t1TVh1WFG5Giecampq/n79Ll06E3798ouYqD17t0VHP2nXzqmGTTgczqSJM0/8dSg+PkYsFt+9d3vJ0jm7ftuMEPLw8DQxMTt4cPf9B/8+i3q867fNebk5FhZWn2++9Kc1dDp985Y1NRfWpUsPJpO5bcc6oVD49t3rTZsD1dQ+fV3YwcFZLpdfv3GFOI8SHHJMsdWIEWNlMtnefTuEQmFGRtofB3dPmRaQnPKuulfp128IccxWcSqouTO0YJXmC5TUeD//2QlJd59EX5bJZClpMSfDVv5xdK5EUtNJf02uvqW5642Ig7l5aZWVolNnViNlzqJXmiswtmwp4UQIzf9xmZubx46dGxYtnhUfHxP0y7ZaD1ryAib8tCQwOOTYwME9f9u9xdjIdPHiVcQYdfvWfTK5LHDNT0uXzVNhszdt/O2rW6mqqqquWb35yZPI8xdCa3gJNTW1Det/FVZUDBjkPXPWuB7de+nq6hOL2tk7zp614ODB3T6+HkHrV0ydPIfY5xM7wyOHQ9kq7Jmzx02YNDwmNvqnJavtbO2rexV3Nw86ne7v16/F3O/V3J5Tml8hV87cHVYWbgtnn0hJjfllS98/jv2vQiiYPHYbg1FLGEYPX2Nu6rhr/4SV6304bI1O7Qeh2g7sNRg/t8zKifxrMKq+BeCT8MLKSuTq3QK/kTB56ihXl/YL5i9vxDZfv0maPWfCiWPnTE3rfVeiS/vS+k8x0jLA7kK5m6dyRVKOul7zmFyvEZUVCpFI0H9KU9xLsuZbAMLle9/l3bs3kZF3N25aPZo3sQHJxJlbd25hRhHZVZCgMKPItQcWR/WafTcs+PSx06ePVbnIwtJ67+4/lfrqBw/tfhb12N+/35TJs5X6Qk1P35ylY0AvyS3T0K+6gxf5+Ez47QNVLqqsFFXXTeUNC3Rq12i39Iu4dzzi/okqF7FZahWiqofNY0eua2fnVeUiQUGFqjrVtA0W/YVm360tLy+v7uwInU5XXEiALWy7tQih4jxJ+IkcI4evr2omiMQVImHV5zMqRGVsVtWRZnM0GPRGe7MiUblIVPVvXyIR06t5ITZbvbq/HTmvcn1HaTfZodqG39m6WeBwOBwOvl87bNY09ehOnuovo/MNbHW/XcpislnVXAmggapYXxlYLA6L1Wi//bzkgjaubBxOohBgzAlq4txVQ8+QWpiBxZePlar4Y6mGhrxDL4y6WhBOUIteo/SMTKgFaY1zTyE8FX4o0dSW9hnfFEdo6w7CCWrXpb+Wtq40710+2YUoRX5KgTqnsuewOl2t3ZQgnKBOfEbotfNg577OFuQr8aLWJiYoKM9OyrZxYPqP1Se7lio0+wNCoMk4ddEwa8OJvJqf/pyvZaapqs1uppNNy+VIkF9RnFnM1ab6j9bTMcLxUDmEE9QPV4/eb7JhboYoLpL/6m6uhq6Kqo4qhUqhs+gMFh1RlHU93XeiyCmVIkmlSCKTycsLy/g5FW1c1f1G6RpZV/vNRBxAOEG96Zux/Hj6fjz9jDcVOenC/ExRWaFEwqDy88ifsa5KXH2mVCxT5dJ1DBn63bQs7Gv6eho+IJyg4czs2GZ2WFxM0yJVHU4qHdHhWFGTYKvSMe0LArJVnUBVDTq/ANMuSguT+0HI1W6Z970E36nqcOoYscTCpphDpZUTFEuMrNg0RrM85gmUrepwGpizGEzKu5jSJq+ndXl0NdfNG6PrxQBWqh1Y9p1g+OG14PWzlnzRFrkiTmc5eXEtHeCqfVC1mo7WDpxh9G9Y7vndaRraDBU1Zc3/3WjkSCavesI+rHDU6Znvy5kqVCcvDTt38ufCANiq5VSKzyh9YZksP1NUxid/Auya5eTknDlzZt68eWQXUgsqDTl0VtM1YlFw/zMCSFb7eU4VVaqpbTM4l0V/n5tbEdPWQ53sQgBoHPDXGwBMQTgBwBSEEwBMQTgBwBSEEwBMQTgBwBSEEwBMQTgBwBSEEwBMQTgBwBSEEwBMQTgBwBSEEwBMQTgBwBSEEwBMQTgBwBSEEwBMQTgBwBSEEwBMQTgBwBSEEwBMQTgBwFTLCSeTyaRSqWlpaWQXAkBdxcbGampWez8Oilzecu5A9+jRox07dhgaGvJ4vG7dupFdDgDVOnfuXEhIiL6+/qpVq4yMjKpcp0WFk/D48eOQkJDU1NRRo0bxeDz8b9AAWo+srKyQkJDQ0NDBgwfzeDwrK6saVm6B4SR8/PgxNDQ0JCRkxIgRAQEBFhYWZFcEWrWnT5+Ghoa+efOGx+MFBATQ6bXfbKHFhlMhLCwsNDTU2NiYx+N17dqV7HJAq3P+/PmQkBBdXV0ej9ejR4+6b9jyw0l49OhRSEhIWlpaQEAAj8ejUOB+tUC5srOzQ0JCQkJCBg8eHBAQYG1tXd8WWks4CR8/fiQ+r1GjRgUEBJibm5NdEWiBnj17FhIS8vr1ax6Px+Px6tKDrVLrCqdCWFhYSEiIqalpQEAA9HVBYzl//nxoaKi2tjaPx/P29v7O1lppOAkPHz4MDQ1NS0sj/sKRXQ5ornJycoge2cCBAwMCAmxsbBql2VYdTsKHDx+Io9vEqRczMzOyKwLNRlRUVEhIyKtXr4hjGQwGoxEbh3D+hzj1YmZmxuPxvLy8yC4HYO38+fNhYWGampo8Hq9nz57KeAkI59eIvm56ejpxPorscgBecnJyiD/iAwYMaMQebJUgnFXLyMgICQkJCwuDvi4gREdHh4SEvHz5kujBMplMZb8ihLMWxJ9Jc3PzgIAA6Ou2ThcuXAgNDeVyuTwez8fHp8leF8JZJw8fPgwJCfnw4QOPxxs1ahTZ5YCmkJubS/xp7tevH4/HU2oPtkoQznpIT08PDQ0NCwsjOjampqZkVwSUIjo6OjQ0NCEhgTjuwGKxSCkDwtkQxEktCwsLHo/XpUsXsssBjebixYshISFcLjcgIKBXr17kFgPhbLjIyMiQkJDMzMyAgADo6zZreXl5xLnuvn378ni8Nm3akF0RgnA2grS0tLCwsLCwMOIyIxMTE7IrAvUQHR0dFhYWFxdH/PrI6sFWCcLZOORyOfGn19LSMiAgAPq6+Lt06VJISIiGhgYOPdgqQTgb2YMHD0JDQ6Gvi638/HzikEGfPn14PJ6trS3ZFVULwqkUaWlpoaGhZ8+eJQ73QV8XB8+fPw8NDY2NjSV6sCoqKmRXVAsIpxLJZDKir2tlZcXj8Tw9Pb9awcfHZ9u2bR4eHiQV2Fpcvnw5JCRETU2Nx+Ph2YOtEoSzKTx48CAkJCQ7OzsgIGDkyJH/1969BzV15XEAP7l5kMQEkCBVE7SUJZItM20VQ5WdAibyUBZolARf7U5nde3Lot3Zimy6uxaqu+MUOh3c7RTt1na2QWsgTrvB8bHtFLbqVEWQNWMtCELAklCB5CaEJOwf1424BXmp9+Ty+/x178m5Ob9k8h1OLjfnUo05OTlWq1UqlR48eFAikdBdIwP19PRQP9xNT0/X6XRyuZzuiiYHwvnwtLW1GQwGo9FIXWaUk5PDYrH8fr9cLjcYDHRXxyjUDLaxsZG6XAT/GeyoIJwPm8/nq6qqKi8v9/v9gUalUrl///7A7vAwav6mr7d7yNnvpalMTHF5BH8WERXNly8Wjdqhpqbm8OHDIpFIp9OpVKqHXuD9BOGkR3Jy8uDgYGCXzWZnZ2fr9XqEUHfboOlvnTEJojkyAYcHC5HdhSCIgV4POeDtvk6u3Sbj8W8vSmyz2ajrYDMyMrRabdDNYEc1xaWHwDSRJMlmswO7Pp+vtrZWJpNlpq77xty7/o3HEKRyTEKEUG+3p7qic802WWPTxcAM9sSJE0E6gx0V/OWkQWpqqsfj4fP5HA6HIAiCILhcLpvN5rC5GYq92h0xkMyJ6L7uuvzvHvPFEgbMYEcF4aSH0WgUi8UCgSAkJEQkEgkEglmzZtlaQ9osruTcR+iuLmgcKWvVFkaLwpk5AWTmq8KfRqP5aeN35+yRMgEd5QSreTFCe9cgU8MJN/nBiKvfN+J7KJiAYeR2+ifQLyhBOAHAFIQTAExBOAHAFIQTAExBOAHAFIQTAExBOAHAFIQTAExBOAHAFIQTAExBOAHAFIQTAExBOAHAFIQTAExBOAHAFIQziLW0XEtTJZ45U7dWm/nrLesQQkXFhUXFhYEOx49/nqZKJEkSIZSnUZuOfXbo40rVSmV2Tsqfdu+0223jDkGSZLF+R9bqX6zMeLrGdKTyQMVzv1qDELpiaU5TJV6xNAd6btyUt/+vZdR2b6+9pLS4YH12nkZdukd/40Yb1X7UaFiTn1FX/6VqpfK9in2vbd/8uzdeGTmc/s3flpQW3793KLhBOIMYl8tFCB36pFKn3fT6jt+P27mq6hBBEDXVpz768GjT5Ya/f/T+uEO8U/52y/fflZd9UPXpFx0d7SdPmalB78Hn821//TcNl85vL9x1sLJqdnjESy8/32ntQAjxeDySdB479lnRzt3P5mpXZeaev3Cut9dOHeh2u8+crVu27JnJvAdMBuEMYiwWCyG0NPHp/LUbFPGPj9tfKo3euOEFsUgskUQuTVx29eqVe/d3OBxffXVSq920SK6IiJC8/NIODoc77qJTTU0N7e3XdxW9laRcHhEheXFrYWhY+NGj/6AKdrvdBQXPq1WZMtmCtLR0oVB4+l/HqQPr6r9ECCUpkyfzHjAZhDPoyeMUE+0pv9NTLA51Oh337t/e3ur1euP/F3sWi6VQJIwfzssNXC538VNLA0c9+cSSS40XAh3iF91+Qh6Pp1ZlnTxppna//vp08vIUkWj01aJnIGaujDSj8CZ8v1fqL+3EURNOoUAYaBm5PRaHY2BoaChNddfdmcLDZwe2eTxeYDt7tabGdKTT2iGJiDx7rl5f/PakKmQ2CCeT+fy+6RweFhaOEBr03FmZ3kk6x+rs9d2+c4REEikQCEpLykY+yiZGX7ksNjZOoUgwm01xcfECgTApCea0d0A4GYXH5d3q+zGwGzhNOjVz585HCFkszfK4eOqOhv9pbgzh8xFCIbwQhJDLRVI9HQ6HzdZDbcfGyl0uV1TUXOl8GdVi7eoMD5s91iirsnINVYc6OtrVqiwOBz6Qd8B3TkZRKBIsluaWlmsIoW/Pn6VOsUzZnDlRCQlPVB6o6Oi8YbP1lJXvGXD0Uw9FRy8Ui8T/NJuGh4e9Xu/ev/xBLA6lHlqyWKlULt+3762bN7v7+m7VmI5sfXFTbe2xsUZZkZZht/ecPVe/Kit3OtUyD4STUfJytaoVmVu2bkhTJZrNpo3rX0AITWdR/6Kdu+MX/XzzlnX5uiyn05HyjJpq53K5ev0ei6V5hXrpug2/TE1ZOW+eNDDQntLylBT17pKiPI3aWG1Qq7M0moKxhhAKhUuWJC2IfjQmJnbKdTIS3I4BI6c+/SFiPv9nT4bSXciYyt/de6nxwocHDt/H5/R4PPm6rC2bX129Km+yx9ZV33wsQbgoUXwf68EHTPEBbbq7uzqtN4zVhoULY2BO+1MQzhmtqalh14jL/f7PJx/XUCdsH5BTp2srD1TExz/+xzf/PNl/88wEMK3FCC3T2ntcYSuRRD7MSqYAprWAyfBP4IwFZ2sBwBSEEwBMQTgBwBSEEwBMQTgBwBSEEwBMQTgBwBSEEwBMQTgBwBSEEyMCMdvlmNbaBTONy+EVhjL2KjcIJ0YipSEDPw7RXUUwcfR5JfMmuoRS0IFwYkT+lKirlXTc8tJdSHC4er5fGisQihn7GWbsCwtS+dui6003b/3gobsQ3F27OGBtcaoKougu5AGCn4xhhxzwfV5pZbFYUQsEBBt+5XgXNofVb/d43H6+kEjf+Ajd5TxYEE5MdbW6bV0e1wBMce/CIliiMHbkfP4cGW8C3YMbhBMATMF3TgAwBeEEAFMQTgAwBeEEAFMQTgAwBeEEAFP/BSqHYnk7/hoJAAAAAElFTkSuQmCC", "text/plain": [ "" ] @@ -684,7 +610,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 9, "id": "6c800a77-2359-4011-ab0c-dad22ed333b1", "metadata": {}, "outputs": [ @@ -694,135 +620,92 @@ "text": [ "================================\u001b[1m Human Message \u001b[0m=================================\n", "\n", - "Which sales agent made the most in sales in 2009?\n", + "Which genre on average has the longest tracks?\n", "==================================\u001b[1m Ai Message \u001b[0m==================================\n", "\n", "Available tables: Album, Artist, Customer, Employee, Genre, Invoice, InvoiceLine, MediaType, Playlist, PlaylistTrack, Track\n", "==================================\u001b[1m Ai Message \u001b[0m==================================\n", "Tool Calls:\n", - " sql_db_schema (call_rMs3sF1HVcAGggGf89ZNvtLE)\n", - " Call ID: call_rMs3sF1HVcAGggGf89ZNvtLE\n", + " sql_db_schema (call_qxKtYiHgf93AiTDin9ez5wFp)\n", + " Call ID: call_qxKtYiHgf93AiTDin9ez5wFp\n", " Args:\n", - " table_names: Employee,Invoice,Customer\n", + " table_names: Genre,Track\n", "=================================\u001b[1m Tool Message \u001b[0m=================================\n", "Name: sql_db_schema\n", "\n", "\n", - "CREATE TABLE \"Customer\" (\n", - "\t\"CustomerId\" INTEGER NOT NULL, \n", - "\t\"FirstName\" NVARCHAR(40) NOT NULL, \n", - "\t\"LastName\" NVARCHAR(20) NOT NULL, \n", - "\t\"Company\" NVARCHAR(80), \n", - "\t\"Address\" NVARCHAR(70), \n", - "\t\"City\" NVARCHAR(40), \n", - "\t\"State\" NVARCHAR(40), \n", - "\t\"Country\" NVARCHAR(40), \n", - "\t\"PostalCode\" NVARCHAR(10), \n", - "\t\"Phone\" NVARCHAR(24), \n", - "\t\"Fax\" NVARCHAR(24), \n", - "\t\"Email\" NVARCHAR(60) NOT NULL, \n", - "\t\"SupportRepId\" INTEGER, \n", - "\tPRIMARY KEY (\"CustomerId\"), \n", - "\tFOREIGN KEY(\"SupportRepId\") REFERENCES \"Employee\" (\"EmployeeId\")\n", + "CREATE TABLE \"Genre\" (\n", + "\t\"GenreId\" INTEGER NOT NULL, \n", + "\t\"Name\" NVARCHAR(120), \n", + "\tPRIMARY KEY (\"GenreId\")\n", ")\n", "\n", "/*\n", - "3 rows from Customer table:\n", - "CustomerId\tFirstName\tLastName\tCompany\tAddress\tCity\tState\tCountry\tPostalCode\tPhone\tFax\tEmail\tSupportRepId\n", - "1\tLuís\tGonçalves\tEmbraer - Empresa Brasileira de Aeronáutica S.A.\tAv. Brigadeiro Faria Lima, 2170\tSão José dos Campos\tSP\tBrazil\t12227-000\t+55 (12) 3923-5555\t+55 (12) 3923-5566\tluisg@embraer.com.br\t3\n", - "2\tLeonie\tKöhler\tNone\tTheodor-Heuss-Straße 34\tStuttgart\tNone\tGermany\t70174\t+49 0711 2842222\tNone\tleonekohler@surfeu.de\t5\n", - "3\tFrançois\tTremblay\tNone\t1498 rue Bélanger\tMontréal\tQC\tCanada\tH2G 1A7\t+1 (514) 721-4711\tNone\tftremblay@gmail.com\t3\n", + "3 rows from Genre table:\n", + "GenreId\tName\n", + "1\tRock\n", + "2\tJazz\n", + "3\tMetal\n", "*/\n", "\n", "\n", - "CREATE TABLE \"Employee\" (\n", - "\t\"EmployeeId\" INTEGER NOT NULL, \n", - "\t\"LastName\" NVARCHAR(20) NOT NULL, \n", - "\t\"FirstName\" NVARCHAR(20) NOT NULL, \n", - "\t\"Title\" NVARCHAR(30), \n", - "\t\"ReportsTo\" INTEGER, \n", - "\t\"BirthDate\" DATETIME, \n", - "\t\"HireDate\" DATETIME, \n", - "\t\"Address\" NVARCHAR(70), \n", - "\t\"City\" NVARCHAR(40), \n", - "\t\"State\" NVARCHAR(40), \n", - "\t\"Country\" NVARCHAR(40), \n", - "\t\"PostalCode\" NVARCHAR(10), \n", - "\t\"Phone\" NVARCHAR(24), \n", - "\t\"Fax\" NVARCHAR(24), \n", - "\t\"Email\" NVARCHAR(60), \n", - "\tPRIMARY KEY (\"EmployeeId\"), \n", - "\tFOREIGN KEY(\"ReportsTo\") REFERENCES \"Employee\" (\"EmployeeId\")\n", + "CREATE TABLE \"Track\" (\n", + "\t\"TrackId\" INTEGER NOT NULL, \n", + "\t\"Name\" NVARCHAR(200) NOT NULL, \n", + "\t\"AlbumId\" INTEGER, \n", + "\t\"MediaTypeId\" INTEGER NOT NULL, \n", + "\t\"GenreId\" INTEGER, \n", + "\t\"Composer\" NVARCHAR(220), \n", + "\t\"Milliseconds\" INTEGER NOT NULL, \n", + "\t\"Bytes\" INTEGER, \n", + "\t\"UnitPrice\" NUMERIC(10, 2) NOT NULL, \n", + "\tPRIMARY KEY (\"TrackId\"), \n", + "\tFOREIGN KEY(\"MediaTypeId\") REFERENCES \"MediaType\" (\"MediaTypeId\"), \n", + "\tFOREIGN KEY(\"GenreId\") REFERENCES \"Genre\" (\"GenreId\"), \n", + "\tFOREIGN KEY(\"AlbumId\") REFERENCES \"Album\" (\"AlbumId\")\n", ")\n", "\n", "/*\n", - "3 rows from Employee table:\n", - "EmployeeId\tLastName\tFirstName\tTitle\tReportsTo\tBirthDate\tHireDate\tAddress\tCity\tState\tCountry\tPostalCode\tPhone\tFax\tEmail\n", - "1\tAdams\tAndrew\tGeneral Manager\tNone\t1962-02-18 00:00:00\t2002-08-14 00:00:00\t11120 Jasper Ave NW\tEdmonton\tAB\tCanada\tT5K 2N1\t+1 (780) 428-9482\t+1 (780) 428-3457\tandrew@chinookcorp.com\n", - "2\tEdwards\tNancy\tSales Manager\t1\t1958-12-08 00:00:00\t2002-05-01 00:00:00\t825 8 Ave SW\tCalgary\tAB\tCanada\tT2P 2T3\t+1 (403) 262-3443\t+1 (403) 262-3322\tnancy@chinookcorp.com\n", - "3\tPeacock\tJane\tSales Support Agent\t2\t1973-08-29 00:00:00\t2002-04-01 00:00:00\t1111 6 Ave SW\tCalgary\tAB\tCanada\tT2P 5M5\t+1 (403) 262-3443\t+1 (403) 262-6712\tjane@chinookcorp.com\n", - "*/\n", - "\n", - "\n", - "CREATE TABLE \"Invoice\" (\n", - "\t\"InvoiceId\" INTEGER NOT NULL, \n", - "\t\"CustomerId\" INTEGER NOT NULL, \n", - "\t\"InvoiceDate\" DATETIME NOT NULL, \n", - "\t\"BillingAddress\" NVARCHAR(70), \n", - "\t\"BillingCity\" NVARCHAR(40), \n", - "\t\"BillingState\" NVARCHAR(40), \n", - "\t\"BillingCountry\" NVARCHAR(40), \n", - "\t\"BillingPostalCode\" NVARCHAR(10), \n", - "\t\"Total\" NUMERIC(10, 2) NOT NULL, \n", - "\tPRIMARY KEY (\"InvoiceId\"), \n", - "\tFOREIGN KEY(\"CustomerId\") REFERENCES \"Customer\" (\"CustomerId\")\n", - ")\n", - "\n", - "/*\n", - "3 rows from Invoice table:\n", - "InvoiceId\tCustomerId\tInvoiceDate\tBillingAddress\tBillingCity\tBillingState\tBillingCountry\tBillingPostalCode\tTotal\n", - "1\t2\t2009-01-01 00:00:00\tTheodor-Heuss-Straße 34\tStuttgart\tNone\tGermany\t70174\t1.98\n", - "2\t4\t2009-01-02 00:00:00\tUllevålsveien 14\tOslo\tNone\tNorway\t0171\t3.96\n", - "3\t8\t2009-01-03 00:00:00\tGrétrystraat 63\tBrussels\tNone\tBelgium\t1000\t5.94\n", + "3 rows from Track table:\n", + "TrackId\tName\tAlbumId\tMediaTypeId\tGenreId\tComposer\tMilliseconds\tBytes\tUnitPrice\n", + "1\tFor Those About To Rock (We Salute You)\t1\t1\t1\tAngus Young, Malcolm Young, Brian Johnson\t343719\t11170334\t0.99\n", + "2\tBalls to the Wall\t2\t2\t1\tNone\t342562\t5510424\t0.99\n", + "3\tFast As a Shark\t3\t2\t1\tF. Baltes, S. Kaufman, U. Dirkscneider & W. Hoffman\t230619\t3990994\t0.99\n", "*/\n", "==================================\u001b[1m Ai Message \u001b[0m==================================\n", "Tool Calls:\n", - " sql_db_query (call_TQyoJSV78xEWHqc69PiYHjdS)\n", - " Call ID: call_TQyoJSV78xEWHqc69PiYHjdS\n", + " sql_db_query (call_RPN3GABMfb6DTaFTLlwnZxVN)\n", + " Call ID: call_RPN3GABMfb6DTaFTLlwnZxVN\n", " Args:\n", - " query: SELECT e.FirstName, e.LastName, SUM(i.Total) as TotalSales\n", - "FROM Employee e\n", - "JOIN Customer c ON e.EmployeeId = c.SupportRepId\n", - "JOIN Invoice i ON c.CustomerId = i.CustomerId\n", - "WHERE strftime('%Y', i.InvoiceDate) = '2009'\n", - "GROUP BY e.EmployeeId\n", - "ORDER BY TotalSales DESC\n", + " query: SELECT Genre.Name, AVG(Track.Milliseconds) AS AvgTrackLength\n", + "FROM Track\n", + "JOIN Genre ON Track.GenreId = Genre.GenreId\n", + "GROUP BY Genre.GenreId\n", + "ORDER BY AvgTrackLength DESC\n", "LIMIT 1;\n", "==================================\u001b[1m Ai Message \u001b[0m==================================\n", "Tool Calls:\n", - " sql_db_query (call_tSQOuxc7iQ1jvLzXSofCqK4V)\n", - " Call ID: call_tSQOuxc7iQ1jvLzXSofCqK4V\n", + " sql_db_query (call_PR4s8ymiF3ZQLaoZADXtdqcl)\n", + " Call ID: call_PR4s8ymiF3ZQLaoZADXtdqcl\n", " Args:\n", - " query: SELECT e.FirstName, e.LastName, SUM(i.Total) as TotalSales\n", - "FROM Employee e\n", - "JOIN Customer c ON e.EmployeeId = c.SupportRepId\n", - "JOIN Invoice i ON c.CustomerId = i.CustomerId\n", - "WHERE strftime('%Y', i.InvoiceDate) = '2009'\n", - "GROUP BY e.EmployeeId\n", - "ORDER BY TotalSales DESC\n", + " query: SELECT Genre.Name, AVG(Track.Milliseconds) AS AvgTrackLength\n", + "FROM Track\n", + "JOIN Genre ON Track.GenreId = Genre.GenreId\n", + "GROUP BY Genre.GenreId\n", + "ORDER BY AvgTrackLength DESC\n", "LIMIT 1;\n", "=================================\u001b[1m Tool Message \u001b[0m=================================\n", "Name: sql_db_query\n", "\n", - "[('Steve', 'Johnson', 164.34)]\n", + "[('Sci Fi & Fantasy', 2911783.0384615385)]\n", "==================================\u001b[1m Ai Message \u001b[0m==================================\n", "\n", - "The sales agent who made the most in sales in 2009 was Steve Johnson, with total sales of 164.34.\n" + "The genre with the longest tracks on average is \"Sci Fi & Fantasy,\" with an average track length of approximately 2,911,783 milliseconds.\n" ] } ], "source": [ - "question = \"Which sales agent made the most in sales in 2009?\"\n", + "question = \"Which genre on average has the longest tracks?\"\n", "\n", "for step in agent.stream(\n", " {\"messages\": [{\"role\": \"user\", \"content\": question}]},\n", @@ -838,7 +721,7 @@ "source": [ "!!! tip\n", "\n", - " See [LangSmith trace](https://smith.langchain.com/public/36a9ebbb-7cc4-4c54-b4db-cb12e124a649/r) for the above run." + " See [LangSmith trace](https://smith.langchain.com/public/94b8c9ac-12f7-4692-8706-836a1f30f1ea/r) for the above run." ] }, { From 5413f9db9f99f75ebb8a8e067ca13476fe8ebadd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Jul 2025 19:00:51 -0400 Subject: [PATCH 038/129] chore(deps): bump peter-evans/create-pull-request from 6 to 7 (#5365) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 6 to 7. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/v6...v7) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/uv_lock_ugprade.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/uv_lock_ugprade.yml b/.github/workflows/uv_lock_ugprade.yml index 8acd39393..de079ec4c 100644 --- a/.github/workflows/uv_lock_ugprade.yml +++ b/.github/workflows/uv_lock_ugprade.yml @@ -30,7 +30,7 @@ jobs: run: make lock-upgrade - name: Create Pull Request - uses: peter-evans/create-pull-request@v6 + uses: peter-evans/create-pull-request@v7 with: token: ${{ secrets.GITHUB_TOKEN }} commit-message: "chore: upgrade dependencies with `uv lock --upgrade`" From fa36a50444d05d6c47d79d3f96681b6d113c5b75 Mon Sep 17 00:00:00 2001 From: Fadel Akram Date: Tue, 8 Jul 2025 00:14:17 +0100 Subject: [PATCH 039/129] docs: correct link in docs/docs/how-tos/graph-api.md (#5377) Update graph-api.md --- docs/docs/how-tos/graph-api.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/how-tos/graph-api.md b/docs/docs/how-tos/graph-api.md index 3cf08f8c5..4a71cc77d 100644 --- a/docs/docs/how-tos/graph-api.md +++ b/docs/docs/how-tos/graph-api.md @@ -163,7 +163,7 @@ Hello! In practice, there are additional considerations for updating lists of messages: - We may wish to update an existing message in the state. -- We may want to accept short-hands for [message formats](../concepts/low_level.md#using-messages-in-your-graph), such as [OpenAI format](https://python.langchain.com/docs/concepts/messages.md#openai-format). +- We may want to accept short-hands for [message formats](../concepts/low_level.md#using-messages-in-your-graph), such as [OpenAI format](https://python.langchain.com/docs/concepts/messages/#openai-format). LangGraph includes a built-in reducer `add_messages` that handles these considerations: @@ -1874,4 +1874,4 @@ except ImportError: print( "You likely need to install dependencies for pygraphviz, see more here https://github.com/pygraphviz/pygraphviz/blob/main/INSTALL.txt" ) -``` \ No newline at end of file +``` From cba4d9e3bcdc2595206200d655142f9e7f621a19 Mon Sep 17 00:00:00 2001 From: David <31293924+dreadn0ught@users.noreply.github.com> Date: Tue, 8 Jul 2025 01:18:55 +0200 Subject: [PATCH 040/129] docs: Update quick_start.md Rest API Guide (#5368) Update quick_start.md Rest API Guide The curl command in the quick start needs some minor changes to work out of the box. I hope by adding these changes then new users can get started more quickly --- docs/docs/cloud/quick_start.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/docs/cloud/quick_start.md b/docs/docs/cloud/quick_start.md index 2823b891d..41ad577e1 100644 --- a/docs/docs/cloud/quick_start.md +++ b/docs/docs/cloud/quick_start.md @@ -154,8 +154,9 @@ You can now test the API: ```bash curl -s --request POST \ - --url \ + --url /runs/stream \ --header 'Content-Type: application/json' \ + --header "X-Api-Key: \ --data "{ \"assistant_id\": \"agent\", \"input\": { From 4321ed0f870b795434e7f81f0b7cc10d3c925ca4 Mon Sep 17 00:00:00 2001 From: jito Date: Tue, 8 Jul 2025 08:19:16 +0900 Subject: [PATCH 041/129] Remove duplicate CONFIG_KEY_CHECKPOINT_MAP from RESERVED set (#5372) Signed-off-by: jitokim --- libs/langgraph/langgraph/constants.py | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/langgraph/langgraph/constants.py b/libs/langgraph/langgraph/constants.py index ac53718e1..f524de39f 100644 --- a/libs/langgraph/langgraph/constants.py +++ b/libs/langgraph/langgraph/constants.py @@ -119,7 +119,6 @@ RESERVED = { CONFIG_KEY_STREAM, CONFIG_KEY_STREAM_WRITER, CONFIG_KEY_STORE, - CONFIG_KEY_CHECKPOINT_MAP, CONFIG_KEY_RESUMING, CONFIG_KEY_TASK_ID, CONFIG_KEY_CHECKPOINT_MAP, From 4c73b176ff28485d72aa819054e0a1c8d5db2cf4 Mon Sep 17 00:00:00 2001 From: Youssef Ahmed Mohamed Abdelrahman <109446360+unauthorised-401@users.noreply.github.com> Date: Tue, 8 Jul 2025 02:22:53 +0300 Subject: [PATCH 042/129] docs: fix typo in persistence (#5329) * docs: fix typo in application_structure * docs: fix typo in persistence --- docs/docs/concepts/persistence.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/concepts/persistence.md b/docs/docs/concepts/persistence.md index 7c612cf60..f3d807946 100644 --- a/docs/docs/concepts/persistence.md +++ b/docs/docs/concepts/persistence.md @@ -5,7 +5,7 @@ search: # Persistence -LangGraph has a built-in persistence layer, implemented through checkpointers. When you compile graph with a checkpointer, the checkpointer saves a `checkpoint` of the graph state at every super-step. Those checkpoints are saved to a `thread`, which can be accessed after graph execution. Because `threads` allow access to graph's state after execution, several powerful capabilities including human-in-the-loop, memory, time travel, and fault-tolerance are all possible. Below, we'll discuss each of these concepts in more detail. +LangGraph has a built-in persistence layer, implemented through checkpointers. When you compile a graph with a checkpointer, the checkpointer saves a `checkpoint` of the graph state at every super-step. Those checkpoints are saved to a `thread`, which can be accessed after graph execution. Because `threads` allow access to graph's state after execution, several powerful capabilities including human-in-the-loop, memory, time travel, and fault-tolerance are all possible. Below, we'll discuss each of these concepts in more detail. ![Checkpoints](img/persistence/checkpoints.jpg) @@ -78,7 +78,7 @@ After we run the graph, we expect to see exactly 4 checkpoints: * checkpoint with the outputs of `node_a` `{'foo': 'a', 'bar': ['a']}` and `node_b` as the next node to be executed * checkpoint with the outputs of `node_b` `{'foo': 'b', 'bar': ['a', 'b']}` and no next nodes to be executed -Note that we `bar` channel values contain outputs from both nodes as we have a reducer for `bar` channel. +Note that the `bar` channel values contain outputs from both nodes as we have a reducer for `bar` channel. ### Get state From 87f2e6939542eb4ce61f009071d1d06a2e7dcf11 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 7 Jul 2025 23:24:32 +0000 Subject: [PATCH 043/129] chore[deps]: upgrade dependencies with `uv lock --upgrade` (#5358) * chore: upgrade dependencies with `uv lock --upgrade` * linting * upgrade PR title --------- Co-authored-by: sydney-runkle <54324534+sydney-runkle@users.noreply.github.com> Co-authored-by: Sydney Runkle --- .github/workflows/uv_lock_ugprade.yml | 4 +- .../langgraph/checkpoint/postgres/aio.py | 2 +- .../langgraph/checkpoint/postgres/shallow.py | 2 +- .../langgraph/store/postgres/base.py | 8 +- libs/checkpoint-postgres/uv.lock | 196 +-- .../langgraph/checkpoint/sqlite/aio.py | 2 +- libs/checkpoint-sqlite/uv.lock | 196 +-- libs/checkpoint/uv.lock | 317 ++--- libs/cli/examples/graphs/storm.py | 4 +- libs/cli/langgraph_cli/config.py | 5 +- libs/cli/langgraph_cli/templates.py | 2 +- libs/cli/tests/unit_tests/cli/test_cli.py | 12 +- .../tests/unit_tests/cli/test_templates.py | 18 +- libs/cli/uv.lock | 575 +++++---- libs/langgraph/tests/test_runnable.py | 4 +- libs/langgraph/uv.lock | 1077 +++++++++-------- libs/prebuilt/uv.lock | 190 +-- libs/sdk-py/uv.lock | 154 ++- 18 files changed, 1486 insertions(+), 1282 deletions(-) diff --git a/.github/workflows/uv_lock_ugprade.yml b/.github/workflows/uv_lock_ugprade.yml index de079ec4c..75d74890c 100644 --- a/.github/workflows/uv_lock_ugprade.yml +++ b/.github/workflows/uv_lock_ugprade.yml @@ -33,8 +33,8 @@ jobs: uses: peter-evans/create-pull-request@v7 with: token: ${{ secrets.GITHUB_TOKEN }} - commit-message: "chore: upgrade dependencies with `uv lock --upgrade`" - title: "chore: upgrade dependencies with `uv lock --upgrade`" + commit-message: "chore[deps]: upgrade dependencies with `uv lock --upgrade`" + title: "chore[deps]: upgrade dependencies with `uv lock --upgrade`" body: | This PR updates the dependencies in all Python packages using `uv lock --upgrade`. diff --git a/libs/checkpoint-postgres/langgraph/checkpoint/postgres/aio.py b/libs/checkpoint-postgres/langgraph/checkpoint/postgres/aio.py index 9fc7673b2..8775c2df5 100644 --- a/libs/checkpoint-postgres/langgraph/checkpoint/postgres/aio.py +++ b/libs/checkpoint-postgres/langgraph/checkpoint/postgres/aio.py @@ -452,7 +452,7 @@ class AsyncPostgresSaver(BasePostgresSaver): while True: try: yield asyncio.run_coroutine_threadsafe( - anext(aiter_), # noqa: F821 + anext(aiter_), # type: ignore[arg-type] # noqa: F821 self.loop, ).result() except StopAsyncIteration: diff --git a/libs/checkpoint-postgres/langgraph/checkpoint/postgres/shallow.py b/libs/checkpoint-postgres/langgraph/checkpoint/postgres/shallow.py index af2aacef8..16f4094ae 100644 --- a/libs/checkpoint-postgres/langgraph/checkpoint/postgres/shallow.py +++ b/libs/checkpoint-postgres/langgraph/checkpoint/postgres/shallow.py @@ -877,7 +877,7 @@ class AsyncShallowPostgresSaver(BasePostgresSaver): while True: try: yield asyncio.run_coroutine_threadsafe( - anext(aiter_), # noqa: F821 + anext(aiter_), # type: ignore[arg-type] # noqa: F821 self.loop, ).result() except StopAsyncIteration: diff --git a/libs/checkpoint-postgres/langgraph/store/postgres/base.py b/libs/checkpoint-postgres/langgraph/store/postgres/base.py index 6b57cebae..bf17c20cd 100644 --- a/libs/checkpoint-postgres/langgraph/store/postgres/base.py +++ b/libs/checkpoint-postgres/langgraph/store/postgres/base.py @@ -448,10 +448,8 @@ class BasePostgresStore(Generic[C]): score_operator, post_operator = get_distance_operator(self) post_operator = post_operator.replace("scored", "uniq") - vector_type = ( - cast(PostgresIndexConfig, self.index_config) - .get("ann_index_config", {}) - .get("vector_type", "vector") + vector_type = self.index_config.get("ann_index_config", {}).get( + "vector_type", "vector" ) # For hamming bit vectors, or “regular” vectors @@ -1141,7 +1139,7 @@ def _get_vector_type_ops(store: BasePostgresStore) -> str: if not store.index_config: return "vector_cosine_ops" - config = cast(PostgresIndexConfig, store.index_config) + config = store.index_config index_config = config.get("ann_index_config", _DEFAULT_ANN_CONFIG).copy() vector_type = cast(str, index_config.get("vector_type", "vector")) if vector_type not in ("vector", "halfvec"): diff --git a/libs/checkpoint-postgres/uv.lock b/libs/checkpoint-postgres/uv.lock index 45161991d..ff12c6faa 100644 --- a/libs/checkpoint-postgres/uv.lock +++ b/libs/checkpoint-postgres/uv.lock @@ -1,10 +1,6 @@ version = 1 revision = 2 requires-python = ">=3.9" -resolution-markers = [ - "python_full_version >= '3.12.4'", - "python_full_version < '3.12.4'", -] [[package]] name = "annotated-types" @@ -32,11 +28,11 @@ wheels = [ [[package]] name = "certifi" -version = "2025.4.26" +version = "2025.6.15" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e8/9e/c05b3920a3b7d20d3d3310465f50348e5b3694f4f88c6daf736eef3024c4/certifi-2025.4.26.tar.gz", hash = "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6", size = 160705, upload-time = "2025-04-26T02:12:29.51Z" } +sdist = { url = "https://files.pythonhosted.org/packages/73/f7/f14b46d4bcd21092d7d3ccef689615220d8a08fb25e564b65d20738e672e/certifi-2025.6.15.tar.gz", hash = "sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b", size = 158753, upload-time = "2025-06-15T02:45:51.329Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4a/7e/3db2bd1b1f9e95f7cddca6d6e75e2f2bd9f51b1246e546d88addca0106bd/certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3", size = 159618, upload-time = "2025-04-26T02:12:27.662Z" }, + { url = "https://files.pythonhosted.org/packages/84/ae/320161bd181fc06471eed047ecce67b693fd7515b16d495d8932db763426/certifi-2025.6.15-py3-none-any.whl", hash = "sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057", size = 157650, upload-time = "2025-06-15T02:45:49.977Z" }, ] [[package]] @@ -205,7 +201,7 @@ name = "exceptiongroup" version = "1.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.12.4'" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" } wheels = [ @@ -290,7 +286,7 @@ wheels = [ [[package]] name = "langchain-core" -version = "0.3.60" +version = "0.3.68" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jsonpatch" }, @@ -301,9 +297,9 @@ dependencies = [ { name = "tenacity" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5b/75/95129aaada92980a002a31e002610a80af3c8967ae7884710372e89cdde0/langchain_core-0.3.60.tar.gz", hash = "sha256:63dd1bdf7939816115399522661ca85a2f3686a61440f2f46ebd86d1b028595b", size = 557456, upload-time = "2025-05-15T15:23:23.642Z" } +sdist = { url = "https://files.pythonhosted.org/packages/23/20/f5b18a17bfbe3416177e702ab2fd230b7d168abb17be31fb48f43f0bb772/langchain_core-0.3.68.tar.gz", hash = "sha256:312e1932ac9aa2eaf111b70fdc171776fa571d1a86c1f873dcac88a094b19c6f", size = 563041, upload-time = "2025-07-03T17:02:28.704Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2d/bc/344f5b11fdfe0e27f7064d2e829921a791461dc32e5ed285fe6325518c26/langchain_core-0.3.60-py3-none-any.whl", hash = "sha256:2ccdf06b12e699b1b0962bc02837056c075b4981c3d13f82a4d4c30bb22ea3dc", size = 437890, upload-time = "2025-05-15T15:23:22.278Z" }, + { url = "https://files.pythonhosted.org/packages/f9/da/c89be0a272993bfcb762b2a356b9f55de507784c2755ad63caec25d183bf/langchain_core-0.3.68-py3-none-any.whl", hash = "sha256:5e5c1fbef419590537c91b8c2d86af896fbcbaf0d5ed7fdcdd77f7d8f3467ba0", size = 441405, upload-time = "2025-07-03T17:02:27.115Z" }, ] [[package]] @@ -385,7 +381,7 @@ dev = [ [[package]] name = "langsmith" -version = "0.3.42" +version = "0.4.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, @@ -396,53 +392,54 @@ dependencies = [ { name = "requests-toolbelt" }, { name = "zstandard" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3a/44/fe171c0b0fb0377b191aebf0b7779e0c7b2a53693c6a01ddad737212495d/langsmith-0.3.42.tar.gz", hash = "sha256:2b5cbc450ab808b992362aac6943bb1d285579aa68a3a8be901d30a393458f25", size = 345619, upload-time = "2025-05-03T03:07:17.873Z" } +sdist = { url = "https://files.pythonhosted.org/packages/20/c8/8d2e0fc438d2d3d8d4300f7684ea30a754344ed00d7ba9cc2705241d2a5f/langsmith-0.4.4.tar.gz", hash = "sha256:70c53bbff24a7872e88e6fa0af98270f4986a6e364f9e85db1cc5636defa4d66", size = 352105, upload-time = "2025-06-27T19:20:36.207Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/89/8e/e8a58e0abaae3f3ac4702e9ca35d1fc6159711556b64ffd0e247771a3f12/langsmith-0.3.42-py3-none-any.whl", hash = "sha256:18114327f3364385dae4026ebfd57d1c1cb46d8f80931098f0f10abe533475ff", size = 360334, upload-time = "2025-05-03T03:07:15.491Z" }, + { url = "https://files.pythonhosted.org/packages/1d/33/a3337eb70d795495a299a1640d7a75f17fb917155a64309b96106e7b9452/langsmith-0.4.4-py3-none-any.whl", hash = "sha256:014c68329bd085bd6c770a6405c61bb6881f82eb554ce8c4d1984b0035fd1716", size = 367687, upload-time = "2025-06-27T19:20:33.839Z" }, ] [[package]] name = "mypy" -version = "1.15.0" +version = "1.16.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "mypy-extensions" }, + { name = "pathspec" }, { name = "tomli", marker = "python_full_version < '3.11'" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ce/43/d5e49a86afa64bd3839ea0d5b9c7103487007d728e1293f52525d6d5486a/mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43", size = 3239717, upload-time = "2025-02-05T03:50:34.655Z" } +sdist = { url = "https://files.pythonhosted.org/packages/81/69/92c7fa98112e4d9eb075a239caa4ef4649ad7d441545ccffbd5e34607cbb/mypy-1.16.1.tar.gz", hash = "sha256:6bd00a0a2094841c5e47e7374bb42b83d64c527a502e3334e1173a0c24437bab", size = 3324747, upload-time = "2025-06-16T16:51:35.145Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/68/f8/65a7ce8d0e09b6329ad0c8d40330d100ea343bd4dd04c4f8ae26462d0a17/mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13", size = 10738433, upload-time = "2025-02-05T03:49:29.145Z" }, - { url = "https://files.pythonhosted.org/packages/b4/95/9c0ecb8eacfe048583706249439ff52105b3f552ea9c4024166c03224270/mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559", size = 9861472, upload-time = "2025-02-05T03:49:16.986Z" }, - { url = "https://files.pythonhosted.org/packages/84/09/9ec95e982e282e20c0d5407bc65031dfd0f0f8ecc66b69538296e06fcbee/mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b", size = 11611424, upload-time = "2025-02-05T03:49:46.908Z" }, - { url = "https://files.pythonhosted.org/packages/78/13/f7d14e55865036a1e6a0a69580c240f43bc1f37407fe9235c0d4ef25ffb0/mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3", size = 12365450, upload-time = "2025-02-05T03:50:05.89Z" }, - { url = "https://files.pythonhosted.org/packages/48/e1/301a73852d40c241e915ac6d7bcd7fedd47d519246db2d7b86b9d7e7a0cb/mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b", size = 12551765, upload-time = "2025-02-05T03:49:33.56Z" }, - { url = "https://files.pythonhosted.org/packages/77/ba/c37bc323ae5fe7f3f15a28e06ab012cd0b7552886118943e90b15af31195/mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828", size = 9274701, upload-time = "2025-02-05T03:49:38.981Z" }, - { url = "https://files.pythonhosted.org/packages/03/bc/f6339726c627bd7ca1ce0fa56c9ae2d0144604a319e0e339bdadafbbb599/mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f", size = 10662338, upload-time = "2025-02-05T03:50:17.287Z" }, - { url = "https://files.pythonhosted.org/packages/e2/90/8dcf506ca1a09b0d17555cc00cd69aee402c203911410136cd716559efe7/mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5", size = 9787540, upload-time = "2025-02-05T03:49:51.21Z" }, - { url = "https://files.pythonhosted.org/packages/05/05/a10f9479681e5da09ef2f9426f650d7b550d4bafbef683b69aad1ba87457/mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e", size = 11538051, upload-time = "2025-02-05T03:50:20.885Z" }, - { url = "https://files.pythonhosted.org/packages/e9/9a/1f7d18b30edd57441a6411fcbc0c6869448d1a4bacbaee60656ac0fc29c8/mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c", size = 12286751, upload-time = "2025-02-05T03:49:42.408Z" }, - { url = "https://files.pythonhosted.org/packages/72/af/19ff499b6f1dafcaf56f9881f7a965ac2f474f69f6f618b5175b044299f5/mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f", size = 12421783, upload-time = "2025-02-05T03:49:07.707Z" }, - { url = "https://files.pythonhosted.org/packages/96/39/11b57431a1f686c1aed54bf794870efe0f6aeca11aca281a0bd87a5ad42c/mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f", size = 9265618, upload-time = "2025-02-05T03:49:54.581Z" }, - { url = "https://files.pythonhosted.org/packages/98/3a/03c74331c5eb8bd025734e04c9840532226775c47a2c39b56a0c8d4f128d/mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd", size = 10793981, upload-time = "2025-02-05T03:50:28.25Z" }, - { url = "https://files.pythonhosted.org/packages/f0/1a/41759b18f2cfd568848a37c89030aeb03534411eef981df621d8fad08a1d/mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f", size = 9749175, upload-time = "2025-02-05T03:50:13.411Z" }, - { url = "https://files.pythonhosted.org/packages/12/7e/873481abf1ef112c582db832740f4c11b2bfa510e829d6da29b0ab8c3f9c/mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464", size = 11455675, upload-time = "2025-02-05T03:50:31.421Z" }, - { url = "https://files.pythonhosted.org/packages/b3/d0/92ae4cde706923a2d3f2d6c39629134063ff64b9dedca9c1388363da072d/mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee", size = 12410020, upload-time = "2025-02-05T03:48:48.705Z" }, - { url = "https://files.pythonhosted.org/packages/46/8b/df49974b337cce35f828ba6fda228152d6db45fed4c86ba56ffe442434fd/mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e", size = 12498582, upload-time = "2025-02-05T03:49:03.628Z" }, - { url = "https://files.pythonhosted.org/packages/13/50/da5203fcf6c53044a0b699939f31075c45ae8a4cadf538a9069b165c1050/mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22", size = 9366614, upload-time = "2025-02-05T03:50:00.313Z" }, - { url = "https://files.pythonhosted.org/packages/6a/9b/fd2e05d6ffff24d912f150b87db9e364fa8282045c875654ce7e32fffa66/mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445", size = 10788592, upload-time = "2025-02-05T03:48:55.789Z" }, - { url = "https://files.pythonhosted.org/packages/74/37/b246d711c28a03ead1fd906bbc7106659aed7c089d55fe40dd58db812628/mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d", size = 9753611, upload-time = "2025-02-05T03:48:44.581Z" }, - { url = "https://files.pythonhosted.org/packages/a6/ac/395808a92e10cfdac8003c3de9a2ab6dc7cde6c0d2a4df3df1b815ffd067/mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5", size = 11438443, upload-time = "2025-02-05T03:49:25.514Z" }, - { url = "https://files.pythonhosted.org/packages/d2/8b/801aa06445d2de3895f59e476f38f3f8d610ef5d6908245f07d002676cbf/mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036", size = 12402541, upload-time = "2025-02-05T03:49:57.623Z" }, - { url = "https://files.pythonhosted.org/packages/c7/67/5a4268782eb77344cc613a4cf23540928e41f018a9a1ec4c6882baf20ab8/mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357", size = 12494348, upload-time = "2025-02-05T03:48:52.361Z" }, - { url = "https://files.pythonhosted.org/packages/83/3e/57bb447f7bbbfaabf1712d96f9df142624a386d98fb026a761532526057e/mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf", size = 9373648, upload-time = "2025-02-05T03:49:11.395Z" }, - { url = "https://files.pythonhosted.org/packages/5a/fa/79cf41a55b682794abe71372151dbbf856e3008f6767057229e6649d294a/mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078", size = 10737129, upload-time = "2025-02-05T03:50:24.509Z" }, - { url = "https://files.pythonhosted.org/packages/d3/33/dd8feb2597d648de29e3da0a8bf4e1afbda472964d2a4a0052203a6f3594/mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba", size = 9856335, upload-time = "2025-02-05T03:49:36.398Z" }, - { url = "https://files.pythonhosted.org/packages/e4/b5/74508959c1b06b96674b364ffeb7ae5802646b32929b7701fc6b18447592/mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5", size = 11611935, upload-time = "2025-02-05T03:49:14.154Z" }, - { url = "https://files.pythonhosted.org/packages/6c/53/da61b9d9973efcd6507183fdad96606996191657fe79701b2c818714d573/mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b", size = 12365827, upload-time = "2025-02-05T03:48:59.458Z" }, - { url = "https://files.pythonhosted.org/packages/c1/72/965bd9ee89540c79a25778cc080c7e6ef40aa1eeac4d52cec7eae6eb5228/mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2", size = 12541924, upload-time = "2025-02-05T03:50:03.12Z" }, - { url = "https://files.pythonhosted.org/packages/46/d0/f41645c2eb263e6c77ada7d76f894c580c9ddb20d77f0c24d34273a4dab2/mypy-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980", size = 9271176, upload-time = "2025-02-05T03:50:10.86Z" }, - { url = "https://files.pythonhosted.org/packages/09/4e/a7d65c7322c510de2c409ff3828b03354a7c43f5a8ed458a7a131b41c7b9/mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e", size = 2221777, upload-time = "2025-02-05T03:50:08.348Z" }, + { url = "https://files.pythonhosted.org/packages/8e/12/2bf23a80fcef5edb75de9a1e295d778e0f46ea89eb8b115818b663eff42b/mypy-1.16.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b4f0fed1022a63c6fec38f28b7fc77fca47fd490445c69d0a66266c59dd0b88a", size = 10958644, upload-time = "2025-06-16T16:51:11.649Z" }, + { url = "https://files.pythonhosted.org/packages/08/50/bfe47b3b278eacf348291742fd5e6613bbc4b3434b72ce9361896417cfe5/mypy-1.16.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:86042bbf9f5a05ea000d3203cf87aa9d0ccf9a01f73f71c58979eb9249f46d72", size = 10087033, upload-time = "2025-06-16T16:35:30.089Z" }, + { url = "https://files.pythonhosted.org/packages/21/de/40307c12fe25675a0776aaa2cdd2879cf30d99eec91b898de00228dc3ab5/mypy-1.16.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ea7469ee5902c95542bea7ee545f7006508c65c8c54b06dc2c92676ce526f3ea", size = 11875645, upload-time = "2025-06-16T16:35:48.49Z" }, + { url = "https://files.pythonhosted.org/packages/a6/d8/85bdb59e4a98b7a31495bd8f1a4445d8ffc86cde4ab1f8c11d247c11aedc/mypy-1.16.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:352025753ef6a83cb9e7f2427319bb7875d1fdda8439d1e23de12ab164179574", size = 12616986, upload-time = "2025-06-16T16:48:39.526Z" }, + { url = "https://files.pythonhosted.org/packages/0e/d0/bb25731158fa8f8ee9e068d3e94fcceb4971fedf1424248496292512afe9/mypy-1.16.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ff9fa5b16e4c1364eb89a4d16bcda9987f05d39604e1e6c35378a2987c1aac2d", size = 12878632, upload-time = "2025-06-16T16:36:08.195Z" }, + { url = "https://files.pythonhosted.org/packages/2d/11/822a9beb7a2b825c0cb06132ca0a5183f8327a5e23ef89717c9474ba0bc6/mypy-1.16.1-cp310-cp310-win_amd64.whl", hash = "sha256:1256688e284632382f8f3b9e2123df7d279f603c561f099758e66dd6ed4e8bd6", size = 9484391, upload-time = "2025-06-16T16:37:56.151Z" }, + { url = "https://files.pythonhosted.org/packages/9a/61/ec1245aa1c325cb7a6c0f8570a2eee3bfc40fa90d19b1267f8e50b5c8645/mypy-1.16.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:472e4e4c100062488ec643f6162dd0d5208e33e2f34544e1fc931372e806c0cc", size = 10890557, upload-time = "2025-06-16T16:37:21.421Z" }, + { url = "https://files.pythonhosted.org/packages/6b/bb/6eccc0ba0aa0c7a87df24e73f0ad34170514abd8162eb0c75fd7128171fb/mypy-1.16.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea16e2a7d2714277e349e24d19a782a663a34ed60864006e8585db08f8ad1782", size = 10012921, upload-time = "2025-06-16T16:51:28.659Z" }, + { url = "https://files.pythonhosted.org/packages/5f/80/b337a12e2006715f99f529e732c5f6a8c143bb58c92bb142d5ab380963a5/mypy-1.16.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:08e850ea22adc4d8a4014651575567b0318ede51e8e9fe7a68f25391af699507", size = 11802887, upload-time = "2025-06-16T16:50:53.627Z" }, + { url = "https://files.pythonhosted.org/packages/d9/59/f7af072d09793d581a745a25737c7c0a945760036b16aeb620f658a017af/mypy-1.16.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22d76a63a42619bfb90122889b903519149879ddbf2ba4251834727944c8baca", size = 12531658, upload-time = "2025-06-16T16:33:55.002Z" }, + { url = "https://files.pythonhosted.org/packages/82/c4/607672f2d6c0254b94a646cfc45ad589dd71b04aa1f3d642b840f7cce06c/mypy-1.16.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2c7ce0662b6b9dc8f4ed86eb7a5d505ee3298c04b40ec13b30e572c0e5ae17c4", size = 12732486, upload-time = "2025-06-16T16:37:03.301Z" }, + { url = "https://files.pythonhosted.org/packages/b6/5e/136555ec1d80df877a707cebf9081bd3a9f397dedc1ab9750518d87489ec/mypy-1.16.1-cp311-cp311-win_amd64.whl", hash = "sha256:211287e98e05352a2e1d4e8759c5490925a7c784ddc84207f4714822f8cf99b6", size = 9479482, upload-time = "2025-06-16T16:47:37.48Z" }, + { url = "https://files.pythonhosted.org/packages/b4/d6/39482e5fcc724c15bf6280ff5806548c7185e0c090712a3736ed4d07e8b7/mypy-1.16.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:af4792433f09575d9eeca5c63d7d90ca4aeceda9d8355e136f80f8967639183d", size = 11066493, upload-time = "2025-06-16T16:47:01.683Z" }, + { url = "https://files.pythonhosted.org/packages/e6/e5/26c347890efc6b757f4d5bb83f4a0cf5958b8cf49c938ac99b8b72b420a6/mypy-1.16.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:66df38405fd8466ce3517eda1f6640611a0b8e70895e2a9462d1d4323c5eb4b9", size = 10081687, upload-time = "2025-06-16T16:48:19.367Z" }, + { url = "https://files.pythonhosted.org/packages/44/c7/b5cb264c97b86914487d6a24bd8688c0172e37ec0f43e93b9691cae9468b/mypy-1.16.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44e7acddb3c48bd2713994d098729494117803616e116032af192871aed80b79", size = 11839723, upload-time = "2025-06-16T16:49:20.912Z" }, + { url = "https://files.pythonhosted.org/packages/15/f8/491997a9b8a554204f834ed4816bda813aefda31cf873bb099deee3c9a99/mypy-1.16.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0ab5eca37b50188163fa7c1b73c685ac66c4e9bdee4a85c9adac0e91d8895e15", size = 12722980, upload-time = "2025-06-16T16:37:40.929Z" }, + { url = "https://files.pythonhosted.org/packages/df/f0/2bd41e174b5fd93bc9de9a28e4fb673113633b8a7f3a607fa4a73595e468/mypy-1.16.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb6229b2c9086247e21a83c309754b9058b438704ad2f6807f0d8227f6ebdd", size = 12903328, upload-time = "2025-06-16T16:34:35.099Z" }, + { url = "https://files.pythonhosted.org/packages/61/81/5572108a7bec2c46b8aff7e9b524f371fe6ab5efb534d38d6b37b5490da8/mypy-1.16.1-cp312-cp312-win_amd64.whl", hash = "sha256:1f0435cf920e287ff68af3d10a118a73f212deb2ce087619eb4e648116d1fe9b", size = 9562321, upload-time = "2025-06-16T16:48:58.823Z" }, + { url = "https://files.pythonhosted.org/packages/28/e3/96964af4a75a949e67df4b95318fe2b7427ac8189bbc3ef28f92a1c5bc56/mypy-1.16.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ddc91eb318c8751c69ddb200a5937f1232ee8efb4e64e9f4bc475a33719de438", size = 11063480, upload-time = "2025-06-16T16:47:56.205Z" }, + { url = "https://files.pythonhosted.org/packages/f5/4d/cd1a42b8e5be278fab7010fb289d9307a63e07153f0ae1510a3d7b703193/mypy-1.16.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:87ff2c13d58bdc4bbe7dc0dedfe622c0f04e2cb2a492269f3b418df2de05c536", size = 10090538, upload-time = "2025-06-16T16:46:43.92Z" }, + { url = "https://files.pythonhosted.org/packages/c9/4f/c3c6b4b66374b5f68bab07c8cabd63a049ff69796b844bc759a0ca99bb2a/mypy-1.16.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a7cfb0fe29fe5a9841b7c8ee6dffb52382c45acdf68f032145b75620acfbd6f", size = 11836839, upload-time = "2025-06-16T16:36:28.039Z" }, + { url = "https://files.pythonhosted.org/packages/b4/7e/81ca3b074021ad9775e5cb97ebe0089c0f13684b066a750b7dc208438403/mypy-1.16.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:051e1677689c9d9578b9c7f4d206d763f9bbd95723cd1416fad50db49d52f359", size = 12715634, upload-time = "2025-06-16T16:50:34.441Z" }, + { url = "https://files.pythonhosted.org/packages/e9/95/bdd40c8be346fa4c70edb4081d727a54d0a05382d84966869738cfa8a497/mypy-1.16.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d5d2309511cc56c021b4b4e462907c2b12f669b2dbeb68300110ec27723971be", size = 12895584, upload-time = "2025-06-16T16:34:54.857Z" }, + { url = "https://files.pythonhosted.org/packages/5a/fd/d486a0827a1c597b3b48b1bdef47228a6e9ee8102ab8c28f944cb83b65dc/mypy-1.16.1-cp313-cp313-win_amd64.whl", hash = "sha256:4f58ac32771341e38a853c5d0ec0dfe27e18e27da9cdb8bbc882d2249c71a3ee", size = 9573886, upload-time = "2025-06-16T16:36:43.589Z" }, + { url = "https://files.pythonhosted.org/packages/49/5e/ed1e6a7344005df11dfd58b0fdd59ce939a0ba9f7ed37754bf20670b74db/mypy-1.16.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7fc688329af6a287567f45cc1cefb9db662defeb14625213a5b7da6e692e2069", size = 10959511, upload-time = "2025-06-16T16:47:21.945Z" }, + { url = "https://files.pythonhosted.org/packages/30/88/a7cbc2541e91fe04f43d9e4577264b260fecedb9bccb64ffb1a34b7e6c22/mypy-1.16.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e198ab3f55924c03ead626ff424cad1732d0d391478dfbf7bb97b34602395da", size = 10075555, upload-time = "2025-06-16T16:50:14.084Z" }, + { url = "https://files.pythonhosted.org/packages/93/f7/c62b1e31a32fbd1546cca5e0a2e5f181be5761265ad1f2e94f2a306fa906/mypy-1.16.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:09aa4f91ada245f0a45dbc47e548fd94e0dd5a8433e0114917dc3b526912a30c", size = 11874169, upload-time = "2025-06-16T16:49:42.276Z" }, + { url = "https://files.pythonhosted.org/packages/c8/15/db580a28034657fb6cb87af2f8996435a5b19d429ea4dcd6e1c73d418e60/mypy-1.16.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13c7cd5b1cb2909aa318a90fd1b7e31f17c50b242953e7dd58345b2a814f6383", size = 12610060, upload-time = "2025-06-16T16:34:15.215Z" }, + { url = "https://files.pythonhosted.org/packages/ec/78/c17f48f6843048fa92d1489d3095e99324f2a8c420f831a04ccc454e2e51/mypy-1.16.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:58e07fb958bc5d752a280da0e890c538f1515b79a65757bbdc54252ba82e0b40", size = 12875199, upload-time = "2025-06-16T16:35:14.448Z" }, + { url = "https://files.pythonhosted.org/packages/bc/d6/ed42167d0a42680381653fd251d877382351e1bd2c6dd8a818764be3beb1/mypy-1.16.1-cp39-cp39-win_amd64.whl", hash = "sha256:f895078594d918f93337a505f8add9bd654d1a24962b4c6ed9390e12531eb31b", size = 9487033, upload-time = "2025-06-16T16:49:57.907Z" }, + { url = "https://files.pythonhosted.org/packages/cf/d3/53e684e78e07c1a2bf7105715e5edd09ce951fc3f47cf9ed095ec1b7a037/mypy-1.16.1-py3-none-any.whl", hash = "sha256:5fc2ac4027d0ef28d6ba69a0343737a23c4d1b83672bf38d1fe237bdc0643b37", size = 2265923, upload-time = "2025-06-16T16:48:02.366Z" }, ] [[package]] @@ -590,6 +587,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451, upload-time = "2024-11-08T09:47:44.722Z" }, ] +[[package]] +name = "pathspec" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" }, +] + [[package]] name = "pluggy" version = "1.6.0" @@ -702,7 +708,7 @@ wheels = [ [[package]] name = "pydantic" -version = "2.11.4" +version = "2.11.7" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-types" }, @@ -710,9 +716,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/77/ab/5250d56ad03884ab5efd07f734203943c8a8ab40d551e208af81d0257bf2/pydantic-2.11.4.tar.gz", hash = "sha256:32738d19d63a226a52eed76645a98ee07c1f410ee41d93b4afbfa85ed8111c2d", size = 786540, upload-time = "2025-04-29T20:38:55.02Z" } +sdist = { url = "https://files.pythonhosted.org/packages/00/dd/4325abf92c39ba8623b5af936ddb36ffcfe0beae70405d456ab1fb2f5b8c/pydantic-2.11.7.tar.gz", hash = "sha256:d989c3c6cb79469287b1569f7447a17848c998458d49ebe294e975b9baf0f0db", size = 788350, upload-time = "2025-06-14T08:33:17.137Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e7/12/46b65f3534d099349e38ef6ec98b1a5a81f42536d17e0ba382c28c67ba67/pydantic-2.11.4-py3-none-any.whl", hash = "sha256:d9615eaa9ac5a063471da949c8fc16376a84afb5024688b3ff885693506764eb", size = 443900, upload-time = "2025-04-29T20:38:52.724Z" }, + { url = "https://files.pythonhosted.org/packages/6a/c0/ec2b1c8712ca690e5d61979dee872603e92b8a32f94cc1b72d53beab008a/pydantic-2.11.7-py3-none-any.whl", hash = "sha256:dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b", size = 444782, upload-time = "2025-06-14T08:33:14.905Z" }, ] [[package]] @@ -824,9 +830,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d4/29/3cade8a924a61f60ccfa10842f75eb12787e1440e2b8660ceffeb26685e7/pydantic_core-2.33.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2807668ba86cb38c6817ad9bc66215ab8584d1d304030ce4f0887336f28a5e27", size = 2066661, upload-time = "2025-04-23T18:33:49.995Z" }, ] +[[package]] +name = "pygments" +version = "2.19.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, +] + [[package]] name = "pytest" -version = "8.3.5" +version = "8.4.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, @@ -834,36 +849,37 @@ dependencies = [ { name = "iniconfig" }, { name = "packaging" }, { name = "pluggy" }, + { name = "pygments" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ae/3c/c9d525a414d506893f0cd8a8d0de7706446213181570cdbd766691164e40/pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845", size = 1450891, upload-time = "2025-03-02T12:54:54.503Z" } +sdist = { url = "https://files.pythonhosted.org/packages/08/ba/45911d754e8eba3d5a841a5ce61a65a685ff1798421ac054f85aa8747dfb/pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c", size = 1517714, upload-time = "2025-06-18T05:48:06.109Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/30/3d/64ad57c803f1fa1e963a7946b6e0fea4a70df53c1a7fed304586539c2bac/pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", size = 343634, upload-time = "2025-03-02T12:54:52.069Z" }, + { url = "https://files.pythonhosted.org/packages/29/16/c8a903f4c4dffe7a12843191437d7cd8e32751d5de349d45d3fe69544e87/pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7", size = 365474, upload-time = "2025-06-18T05:48:03.955Z" }, ] [[package]] name = "pytest-asyncio" -version = "0.26.0" +version = "1.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pytest" }, { name = "typing-extensions", marker = "python_full_version < '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8e/c4/453c52c659521066969523e87d85d54139bbd17b78f09532fb8eb8cdb58e/pytest_asyncio-0.26.0.tar.gz", hash = "sha256:c4df2a697648241ff39e7f0e4a73050b03f123f760673956cf0d72a4990e312f", size = 54156, upload-time = "2025-03-25T06:22:28.883Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/d4/14f53324cb1a6381bef29d698987625d80052bb33932d8e7cbf9b337b17c/pytest_asyncio-1.0.0.tar.gz", hash = "sha256:d15463d13f4456e1ead2594520216b225a16f781e144f8fdf6c5bb4667c48b3f", size = 46960, upload-time = "2025-05-26T04:54:40.484Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/20/7f/338843f449ace853647ace35870874f69a764d251872ed1b4de9f234822c/pytest_asyncio-0.26.0-py3-none-any.whl", hash = "sha256:7b51ed894f4fbea1340262bdae5135797ebbe21d8638978e35d31c6d19f72fb0", size = 19694, upload-time = "2025-03-25T06:22:27.807Z" }, + { url = "https://files.pythonhosted.org/packages/30/05/ce271016e351fddc8399e546f6e23761967ee09c8c568bbfbecb0c150171/pytest_asyncio-1.0.0-py3-none-any.whl", hash = "sha256:4f024da9f1ef945e680dc68610b52550e36590a67fd31bb3b4943979a1f90ef3", size = 15976, upload-time = "2025-05-26T04:54:39.035Z" }, ] [[package]] name = "pytest-mock" -version = "3.14.0" +version = "3.14.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c6/90/a955c3ab35ccd41ad4de556596fa86685bf4fc5ffcc62d22d856cfd4e29a/pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0", size = 32814, upload-time = "2024-03-21T22:14:04.964Z" } +sdist = { url = "https://files.pythonhosted.org/packages/71/28/67172c96ba684058a4d24ffe144d64783d2a270d0af0d9e792737bddc75c/pytest_mock-3.14.1.tar.gz", hash = "sha256:159e9edac4c451ce77a5cdb9fc5d1100708d2dd4ba3c3df572f14097351af80e", size = 33241, upload-time = "2025-05-26T13:58:45.167Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f2/3b/b26f90f74e2986a82df6e7ac7e319b8ea7ccece1caec9f8ab6104dc70603/pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f", size = 9863, upload-time = "2024-03-21T22:14:02.694Z" }, + { url = "https://files.pythonhosted.org/packages/b2/05/77b60e520511c53d1c1ca75f1930c7dd8e971d0c4379b7f4b3f9644685ba/pytest_mock-3.14.1-py3-none-any.whl", hash = "sha256:178aefcd11307d874b4cd3100344e7e2d888d9791a6a1d9bfe90fbc1b74fd1d0", size = 9923, upload-time = "2025-05-26T13:58:43.487Z" }, ] [[package]] @@ -934,7 +950,7 @@ wheels = [ [[package]] name = "requests" -version = "2.32.3" +version = "2.32.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, @@ -942,9 +958,9 @@ dependencies = [ { name = "idna" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218, upload-time = "2024-05-29T15:37:49.536Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e1/0a/929373653770d8a0d7ea76c37de6e41f11eb07559b103b1c02cafb3f7cf8/requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422", size = 135258, upload-time = "2025-06-09T16:43:07.34Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928, upload-time = "2024-05-29T15:37:47.027Z" }, + { url = "https://files.pythonhosted.org/packages/7c/e4/56027c4a6b4ae70ca9de302488c5ca95ad4a39e190093d6c1a8ace08341b/requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", size = 64847, upload-time = "2025-06-09T16:43:05.728Z" }, ] [[package]] @@ -961,27 +977,27 @@ wheels = [ [[package]] name = "ruff" -version = "0.11.10" +version = "0.12.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e8/4c/4a3c5a97faaae6b428b336dcca81d03ad04779f8072c267ad2bd860126bf/ruff-0.11.10.tar.gz", hash = "sha256:d522fb204b4959909ecac47da02830daec102eeb100fb50ea9554818d47a5fa6", size = 4165632, upload-time = "2025-05-15T14:08:56.76Z" } +sdist = { url = "https://files.pythonhosted.org/packages/6c/3d/d9a195676f25d00dbfcf3cf95fdd4c685c497fcfa7e862a44ac5e4e96480/ruff-0.12.2.tar.gz", hash = "sha256:d7b4f55cd6f325cb7621244f19c873c565a08aff5a4ba9c69aa7355f3f7afd3e", size = 4432239, upload-time = "2025-07-03T16:40:19.566Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2f/9f/596c628f8824a2ce4cd12b0f0b4c0629a62dfffc5d0f742c19a1d71be108/ruff-0.11.10-py3-none-linux_armv6l.whl", hash = "sha256:859a7bfa7bc8888abbea31ef8a2b411714e6a80f0d173c2a82f9041ed6b50f58", size = 10316243, upload-time = "2025-05-15T14:08:12.884Z" }, - { url = "https://files.pythonhosted.org/packages/3c/38/c1e0b77ab58b426f8c332c1d1d3432d9fc9a9ea622806e208220cb133c9e/ruff-0.11.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:968220a57e09ea5e4fd48ed1c646419961a0570727c7e069842edd018ee8afed", size = 11083636, upload-time = "2025-05-15T14:08:16.551Z" }, - { url = "https://files.pythonhosted.org/packages/23/41/b75e15961d6047d7fe1b13886e56e8413be8467a4e1be0a07f3b303cd65a/ruff-0.11.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1067245bad978e7aa7b22f67113ecc6eb241dca0d9b696144256c3a879663bca", size = 10441624, upload-time = "2025-05-15T14:08:19.032Z" }, - { url = "https://files.pythonhosted.org/packages/b6/2c/e396b6703f131406db1811ea3d746f29d91b41bbd43ad572fea30da1435d/ruff-0.11.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4854fd09c7aed5b1590e996a81aeff0c9ff51378b084eb5a0b9cd9518e6cff2", size = 10624358, upload-time = "2025-05-15T14:08:21.542Z" }, - { url = "https://files.pythonhosted.org/packages/bd/8c/ee6cca8bdaf0f9a3704796022851a33cd37d1340bceaf4f6e991eb164e2e/ruff-0.11.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8b4564e9f99168c0f9195a0fd5fa5928004b33b377137f978055e40008a082c5", size = 10176850, upload-time = "2025-05-15T14:08:23.682Z" }, - { url = "https://files.pythonhosted.org/packages/e9/ce/4e27e131a434321b3b7c66512c3ee7505b446eb1c8a80777c023f7e876e6/ruff-0.11.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b6a9cc5b62c03cc1fea0044ed8576379dbaf751d5503d718c973d5418483641", size = 11759787, upload-time = "2025-05-15T14:08:25.733Z" }, - { url = "https://files.pythonhosted.org/packages/58/de/1e2e77fc72adc7cf5b5123fd04a59ed329651d3eab9825674a9e640b100b/ruff-0.11.10-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:607ecbb6f03e44c9e0a93aedacb17b4eb4f3563d00e8b474298a201622677947", size = 12430479, upload-time = "2025-05-15T14:08:28.013Z" }, - { url = "https://files.pythonhosted.org/packages/07/ed/af0f2340f33b70d50121628ef175523cc4c37619e98d98748c85764c8d88/ruff-0.11.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7b3a522fa389402cd2137df9ddefe848f727250535c70dafa840badffb56b7a4", size = 11919760, upload-time = "2025-05-15T14:08:30.956Z" }, - { url = "https://files.pythonhosted.org/packages/24/09/d7b3d3226d535cb89234390f418d10e00a157b6c4a06dfbe723e9322cb7d/ruff-0.11.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f071b0deed7e9245d5820dac235cbdd4ef99d7b12ff04c330a241ad3534319f", size = 14041747, upload-time = "2025-05-15T14:08:33.297Z" }, - { url = "https://files.pythonhosted.org/packages/62/b3/a63b4e91850e3f47f78795e6630ee9266cb6963de8f0191600289c2bb8f4/ruff-0.11.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a60e3a0a617eafba1f2e4186d827759d65348fa53708ca547e384db28406a0b", size = 11550657, upload-time = "2025-05-15T14:08:35.639Z" }, - { url = "https://files.pythonhosted.org/packages/46/63/a4f95c241d79402ccdbdb1d823d156c89fbb36ebfc4289dce092e6c0aa8f/ruff-0.11.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:da8ec977eaa4b7bf75470fb575bea2cb41a0e07c7ea9d5a0a97d13dbca697bf2", size = 10489671, upload-time = "2025-05-15T14:08:38.437Z" }, - { url = "https://files.pythonhosted.org/packages/6a/9b/c2238bfebf1e473495659c523d50b1685258b6345d5ab0b418ca3f010cd7/ruff-0.11.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ddf8967e08227d1bd95cc0851ef80d2ad9c7c0c5aab1eba31db49cf0a7b99523", size = 10160135, upload-time = "2025-05-15T14:08:41.247Z" }, - { url = "https://files.pythonhosted.org/packages/ba/ef/ba7251dd15206688dbfba7d413c0312e94df3b31b08f5d695580b755a899/ruff-0.11.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5a94acf798a82db188f6f36575d80609072b032105d114b0f98661e1679c9125", size = 11170179, upload-time = "2025-05-15T14:08:43.762Z" }, - { url = "https://files.pythonhosted.org/packages/73/9f/5c336717293203ba275dbfa2ea16e49b29a9fd9a0ea8b6febfc17e133577/ruff-0.11.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:3afead355f1d16d95630df28d4ba17fb2cb9c8dfac8d21ced14984121f639bad", size = 11626021, upload-time = "2025-05-15T14:08:46.451Z" }, - { url = "https://files.pythonhosted.org/packages/d9/2b/162fa86d2639076667c9aa59196c020dc6d7023ac8f342416c2f5ec4bda0/ruff-0.11.10-py3-none-win32.whl", hash = "sha256:dc061a98d32a97211af7e7f3fa1d4ca2fcf919fb96c28f39551f35fc55bdbc19", size = 10494958, upload-time = "2025-05-15T14:08:49.601Z" }, - { url = "https://files.pythonhosted.org/packages/24/f3/66643d8f32f50a4b0d09a4832b7d919145ee2b944d43e604fbd7c144d175/ruff-0.11.10-py3-none-win_amd64.whl", hash = "sha256:5cc725fbb4d25b0f185cb42df07ab6b76c4489b4bfb740a175f3a59c70e8a224", size = 11650285, upload-time = "2025-05-15T14:08:52.392Z" }, - { url = "https://files.pythonhosted.org/packages/95/3a/2e8704d19f376c799748ff9cb041225c1d59f3e7711bc5596c8cfdc24925/ruff-0.11.10-py3-none-win_arm64.whl", hash = "sha256:ef69637b35fb8b210743926778d0e45e1bffa850a7c61e428c6b971549b5f5d1", size = 10765278, upload-time = "2025-05-15T14:08:54.56Z" }, + { url = "https://files.pythonhosted.org/packages/74/b6/2098d0126d2d3318fd5bec3ad40d06c25d377d95749f7a0c5af17129b3b1/ruff-0.12.2-py3-none-linux_armv6l.whl", hash = "sha256:093ea2b221df1d2b8e7ad92fc6ffdca40a2cb10d8564477a987b44fd4008a7be", size = 10369761, upload-time = "2025-07-03T16:39:38.847Z" }, + { url = "https://files.pythonhosted.org/packages/b1/4b/5da0142033dbe155dc598cfb99262d8ee2449d76920ea92c4eeb9547c208/ruff-0.12.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:09e4cf27cc10f96b1708100fa851e0daf21767e9709e1649175355280e0d950e", size = 11155659, upload-time = "2025-07-03T16:39:42.294Z" }, + { url = "https://files.pythonhosted.org/packages/3e/21/967b82550a503d7c5c5c127d11c935344b35e8c521f52915fc858fb3e473/ruff-0.12.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:8ae64755b22f4ff85e9c52d1f82644abd0b6b6b6deedceb74bd71f35c24044cc", size = 10537769, upload-time = "2025-07-03T16:39:44.75Z" }, + { url = "https://files.pythonhosted.org/packages/33/91/00cff7102e2ec71a4890fb7ba1803f2cdb122d82787c7d7cf8041fe8cbc1/ruff-0.12.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3eb3a6b2db4d6e2c77e682f0b988d4d61aff06860158fdb413118ca133d57922", size = 10717602, upload-time = "2025-07-03T16:39:47.652Z" }, + { url = "https://files.pythonhosted.org/packages/9b/eb/928814daec4e1ba9115858adcda44a637fb9010618721937491e4e2283b8/ruff-0.12.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:73448de992d05517170fc37169cbca857dfeaeaa8c2b9be494d7bcb0d36c8f4b", size = 10198772, upload-time = "2025-07-03T16:39:49.641Z" }, + { url = "https://files.pythonhosted.org/packages/50/fa/f15089bc20c40f4f72334f9145dde55ab2b680e51afb3b55422effbf2fb6/ruff-0.12.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b8b94317cbc2ae4a2771af641739f933934b03555e51515e6e021c64441532d", size = 11845173, upload-time = "2025-07-03T16:39:52.069Z" }, + { url = "https://files.pythonhosted.org/packages/43/9f/1f6f98f39f2b9302acc161a4a2187b1e3a97634fe918a8e731e591841cf4/ruff-0.12.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:45fc42c3bf1d30d2008023a0a9a0cfb06bf9835b147f11fe0679f21ae86d34b1", size = 12553002, upload-time = "2025-07-03T16:39:54.551Z" }, + { url = "https://files.pythonhosted.org/packages/d8/70/08991ac46e38ddd231c8f4fd05ef189b1b94be8883e8c0c146a025c20a19/ruff-0.12.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce48f675c394c37e958bf229fb5c1e843e20945a6d962cf3ea20b7a107dcd9f4", size = 12171330, upload-time = "2025-07-03T16:39:57.55Z" }, + { url = "https://files.pythonhosted.org/packages/88/a9/5a55266fec474acfd0a1c73285f19dd22461d95a538f29bba02edd07a5d9/ruff-0.12.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:793d8859445ea47591272021a81391350205a4af65a9392401f418a95dfb75c9", size = 11774717, upload-time = "2025-07-03T16:39:59.78Z" }, + { url = "https://files.pythonhosted.org/packages/87/e5/0c270e458fc73c46c0d0f7cf970bb14786e5fdb88c87b5e423a4bd65232b/ruff-0.12.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6932323db80484dda89153da3d8e58164d01d6da86857c79f1961934354992da", size = 11646659, upload-time = "2025-07-03T16:40:01.934Z" }, + { url = "https://files.pythonhosted.org/packages/b7/b6/45ab96070c9752af37f0be364d849ed70e9ccede07675b0ec4e3ef76b63b/ruff-0.12.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6aa7e623a3a11538108f61e859ebf016c4f14a7e6e4eba1980190cacb57714ce", size = 10604012, upload-time = "2025-07-03T16:40:04.363Z" }, + { url = "https://files.pythonhosted.org/packages/86/91/26a6e6a424eb147cc7627eebae095cfa0b4b337a7c1c413c447c9ebb72fd/ruff-0.12.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:2a4a20aeed74671b2def096bdf2eac610c7d8ffcbf4fb0e627c06947a1d7078d", size = 10176799, upload-time = "2025-07-03T16:40:06.514Z" }, + { url = "https://files.pythonhosted.org/packages/f5/0c/9f344583465a61c8918a7cda604226e77b2c548daf8ef7c2bfccf2b37200/ruff-0.12.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:71a4c550195612f486c9d1f2b045a600aeba851b298c667807ae933478fcef04", size = 11241507, upload-time = "2025-07-03T16:40:08.708Z" }, + { url = "https://files.pythonhosted.org/packages/1c/b7/99c34ded8fb5f86c0280278fa89a0066c3760edc326e935ce0b1550d315d/ruff-0.12.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:4987b8f4ceadf597c927beee65a5eaf994c6e2b631df963f86d8ad1bdea99342", size = 11717609, upload-time = "2025-07-03T16:40:10.836Z" }, + { url = "https://files.pythonhosted.org/packages/51/de/8589fa724590faa057e5a6d171e7f2f6cffe3287406ef40e49c682c07d89/ruff-0.12.2-py3-none-win32.whl", hash = "sha256:369ffb69b70cd55b6c3fc453b9492d98aed98062db9fec828cdfd069555f5f1a", size = 10523823, upload-time = "2025-07-03T16:40:13.203Z" }, + { url = "https://files.pythonhosted.org/packages/94/47/8abf129102ae4c90cba0c2199a1a9b0fa896f6f806238d6f8c14448cc748/ruff-0.12.2-py3-none-win_amd64.whl", hash = "sha256:dca8a3b6d6dc9810ed8f328d406516bf4d660c00caeaef36eb831cf4871b0639", size = 11629831, upload-time = "2025-07-03T16:40:15.478Z" }, + { url = "https://files.pythonhosted.org/packages/e2/1f/72d2946e3cc7456bb837e88000eb3437e55f80db339c840c04015a11115d/ruff-0.12.2-py3-none-win_arm64.whl", hash = "sha256:48d6c6bfb4761df68bc05ae630e24f506755e702d4fb08f08460be778c7ccb12", size = 10735334, upload-time = "2025-07-03T16:40:17.677Z" }, ] [[package]] @@ -1043,23 +1059,23 @@ wheels = [ [[package]] name = "typing-extensions" -version = "4.13.2" +version = "4.14.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f6/37/23083fcd6e35492953e8d2aaaa68b860eb422b34627b13f2ce3eb6106061/typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef", size = 106967, upload-time = "2025-04-10T14:19:05.416Z" } +sdist = { url = "https://files.pythonhosted.org/packages/98/5a/da40306b885cc8c09109dc2e1abd358d5684b1425678151cdaed4731c822/typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36", size = 107673, upload-time = "2025-07-04T13:28:34.16Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806, upload-time = "2025-04-10T14:19:03.967Z" }, + { url = "https://files.pythonhosted.org/packages/b5/00/d631e67a838026495268c2f6884f3711a15a9a2a96cd244fdaea53b823fb/typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76", size = 43906, upload-time = "2025-07-04T13:28:32.743Z" }, ] [[package]] name = "typing-inspection" -version = "0.4.0" +version = "0.4.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/82/5c/e6082df02e215b846b4b8c0b887a64d7d08ffaba30605502639d44c06b82/typing_inspection-0.4.0.tar.gz", hash = "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122", size = 76222, upload-time = "2025-02-25T17:27:59.638Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/b1/0c11f5058406b3af7609f121aaa6b609744687f1d158b3c3a5bf4cc94238/typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28", size = 75726, upload-time = "2025-05-21T18:55:23.885Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/31/08/aa4fdfb71f7de5176385bd9e90852eaf6b5d622735020ad600f2bab54385/typing_inspection-0.4.0-py3-none-any.whl", hash = "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f", size = 14125, upload-time = "2025-02-25T17:27:57.754Z" }, + { url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552, upload-time = "2025-05-21T18:55:22.152Z" }, ] [[package]] @@ -1073,11 +1089,11 @@ wheels = [ [[package]] name = "urllib3" -version = "2.4.0" +version = "2.5.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8a/78/16493d9c386d8e60e442a35feac5e00f0913c0f4b7c217c11e8ec2ff53e0/urllib3-2.4.0.tar.gz", hash = "sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466", size = 390672, upload-time = "2025-04-10T15:23:39.232Z" } +sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6b/11/cc635220681e93a0183390e26485430ca2c7b5f9d33b15c74c2861cb8091/urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813", size = 128680, upload-time = "2025-04-10T15:23:37.377Z" }, + { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" }, ] [[package]] diff --git a/libs/checkpoint-sqlite/langgraph/checkpoint/sqlite/aio.py b/libs/checkpoint-sqlite/langgraph/checkpoint/sqlite/aio.py index 6ee30b259..1f40c6229 100644 --- a/libs/checkpoint-sqlite/langgraph/checkpoint/sqlite/aio.py +++ b/libs/checkpoint-sqlite/langgraph/checkpoint/sqlite/aio.py @@ -203,7 +203,7 @@ class AsyncSqliteSaver(BaseCheckpointSaver[str]): while True: try: yield asyncio.run_coroutine_threadsafe( - anext(aiter_), # noqa: F821 + anext(aiter_), # type: ignore[arg-type] # noqa: F821 self.loop, ).result() except StopAsyncIteration: diff --git a/libs/checkpoint-sqlite/uv.lock b/libs/checkpoint-sqlite/uv.lock index f2d58d81f..a7615b59e 100644 --- a/libs/checkpoint-sqlite/uv.lock +++ b/libs/checkpoint-sqlite/uv.lock @@ -1,10 +1,6 @@ version = 1 revision = 2 requires-python = ">=3.9" -resolution-markers = [ - "python_full_version >= '3.12.4'", - "python_full_version < '3.12.4'", -] [[package]] name = "aiosqlite" @@ -44,11 +40,11 @@ wheels = [ [[package]] name = "certifi" -version = "2025.4.26" +version = "2025.6.15" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e8/9e/c05b3920a3b7d20d3d3310465f50348e5b3694f4f88c6daf736eef3024c4/certifi-2025.4.26.tar.gz", hash = "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6", size = 160705, upload-time = "2025-04-26T02:12:29.51Z" } +sdist = { url = "https://files.pythonhosted.org/packages/73/f7/f14b46d4bcd21092d7d3ccef689615220d8a08fb25e564b65d20738e672e/certifi-2025.6.15.tar.gz", hash = "sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b", size = 158753, upload-time = "2025-06-15T02:45:51.329Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4a/7e/3db2bd1b1f9e95f7cddca6d6e75e2f2bd9f51b1246e546d88addca0106bd/certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3", size = 159618, upload-time = "2025-04-26T02:12:27.662Z" }, + { url = "https://files.pythonhosted.org/packages/84/ae/320161bd181fc06471eed047ecce67b693fd7515b16d495d8932db763426/certifi-2025.6.15-py3-none-any.whl", hash = "sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057", size = 157650, upload-time = "2025-06-15T02:45:49.977Z" }, ] [[package]] @@ -217,7 +213,7 @@ name = "exceptiongroup" version = "1.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.12.4'" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" } wheels = [ @@ -302,7 +298,7 @@ wheels = [ [[package]] name = "langchain-core" -version = "0.3.60" +version = "0.3.68" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jsonpatch" }, @@ -313,9 +309,9 @@ dependencies = [ { name = "tenacity" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5b/75/95129aaada92980a002a31e002610a80af3c8967ae7884710372e89cdde0/langchain_core-0.3.60.tar.gz", hash = "sha256:63dd1bdf7939816115399522661ca85a2f3686a61440f2f46ebd86d1b028595b", size = 557456, upload-time = "2025-05-15T15:23:23.642Z" } +sdist = { url = "https://files.pythonhosted.org/packages/23/20/f5b18a17bfbe3416177e702ab2fd230b7d168abb17be31fb48f43f0bb772/langchain_core-0.3.68.tar.gz", hash = "sha256:312e1932ac9aa2eaf111b70fdc171776fa571d1a86c1f873dcac88a094b19c6f", size = 563041, upload-time = "2025-07-03T17:02:28.704Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2d/bc/344f5b11fdfe0e27f7064d2e829921a791461dc32e5ed285fe6325518c26/langchain_core-0.3.60-py3-none-any.whl", hash = "sha256:2ccdf06b12e699b1b0962bc02837056c075b4981c3d13f82a4d4c30bb22ea3dc", size = 437890, upload-time = "2025-05-15T15:23:22.278Z" }, + { url = "https://files.pythonhosted.org/packages/f9/da/c89be0a272993bfcb762b2a356b9f55de507784c2755ad63caec25d183bf/langchain_core-0.3.68-py3-none-any.whl", hash = "sha256:5e5c1fbef419590537c91b8c2d86af896fbcbaf0d5ed7fdcdd77f7d8f3467ba0", size = 441405, upload-time = "2025-07-03T17:02:27.115Z" }, ] [[package]] @@ -393,7 +389,7 @@ dev = [ [[package]] name = "langsmith" -version = "0.3.42" +version = "0.4.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, @@ -404,53 +400,54 @@ dependencies = [ { name = "requests-toolbelt" }, { name = "zstandard" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3a/44/fe171c0b0fb0377b191aebf0b7779e0c7b2a53693c6a01ddad737212495d/langsmith-0.3.42.tar.gz", hash = "sha256:2b5cbc450ab808b992362aac6943bb1d285579aa68a3a8be901d30a393458f25", size = 345619, upload-time = "2025-05-03T03:07:17.873Z" } +sdist = { url = "https://files.pythonhosted.org/packages/20/c8/8d2e0fc438d2d3d8d4300f7684ea30a754344ed00d7ba9cc2705241d2a5f/langsmith-0.4.4.tar.gz", hash = "sha256:70c53bbff24a7872e88e6fa0af98270f4986a6e364f9e85db1cc5636defa4d66", size = 352105, upload-time = "2025-06-27T19:20:36.207Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/89/8e/e8a58e0abaae3f3ac4702e9ca35d1fc6159711556b64ffd0e247771a3f12/langsmith-0.3.42-py3-none-any.whl", hash = "sha256:18114327f3364385dae4026ebfd57d1c1cb46d8f80931098f0f10abe533475ff", size = 360334, upload-time = "2025-05-03T03:07:15.491Z" }, + { url = "https://files.pythonhosted.org/packages/1d/33/a3337eb70d795495a299a1640d7a75f17fb917155a64309b96106e7b9452/langsmith-0.4.4-py3-none-any.whl", hash = "sha256:014c68329bd085bd6c770a6405c61bb6881f82eb554ce8c4d1984b0035fd1716", size = 367687, upload-time = "2025-06-27T19:20:33.839Z" }, ] [[package]] name = "mypy" -version = "1.15.0" +version = "1.16.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "mypy-extensions" }, + { name = "pathspec" }, { name = "tomli", marker = "python_full_version < '3.11'" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ce/43/d5e49a86afa64bd3839ea0d5b9c7103487007d728e1293f52525d6d5486a/mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43", size = 3239717, upload-time = "2025-02-05T03:50:34.655Z" } +sdist = { url = "https://files.pythonhosted.org/packages/81/69/92c7fa98112e4d9eb075a239caa4ef4649ad7d441545ccffbd5e34607cbb/mypy-1.16.1.tar.gz", hash = "sha256:6bd00a0a2094841c5e47e7374bb42b83d64c527a502e3334e1173a0c24437bab", size = 3324747, upload-time = "2025-06-16T16:51:35.145Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/68/f8/65a7ce8d0e09b6329ad0c8d40330d100ea343bd4dd04c4f8ae26462d0a17/mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13", size = 10738433, upload-time = "2025-02-05T03:49:29.145Z" }, - { url = "https://files.pythonhosted.org/packages/b4/95/9c0ecb8eacfe048583706249439ff52105b3f552ea9c4024166c03224270/mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559", size = 9861472, upload-time = "2025-02-05T03:49:16.986Z" }, - { url = "https://files.pythonhosted.org/packages/84/09/9ec95e982e282e20c0d5407bc65031dfd0f0f8ecc66b69538296e06fcbee/mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b", size = 11611424, upload-time = "2025-02-05T03:49:46.908Z" }, - { url = "https://files.pythonhosted.org/packages/78/13/f7d14e55865036a1e6a0a69580c240f43bc1f37407fe9235c0d4ef25ffb0/mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3", size = 12365450, upload-time = "2025-02-05T03:50:05.89Z" }, - { url = "https://files.pythonhosted.org/packages/48/e1/301a73852d40c241e915ac6d7bcd7fedd47d519246db2d7b86b9d7e7a0cb/mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b", size = 12551765, upload-time = "2025-02-05T03:49:33.56Z" }, - { url = "https://files.pythonhosted.org/packages/77/ba/c37bc323ae5fe7f3f15a28e06ab012cd0b7552886118943e90b15af31195/mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828", size = 9274701, upload-time = "2025-02-05T03:49:38.981Z" }, - { url = "https://files.pythonhosted.org/packages/03/bc/f6339726c627bd7ca1ce0fa56c9ae2d0144604a319e0e339bdadafbbb599/mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f", size = 10662338, upload-time = "2025-02-05T03:50:17.287Z" }, - { url = "https://files.pythonhosted.org/packages/e2/90/8dcf506ca1a09b0d17555cc00cd69aee402c203911410136cd716559efe7/mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5", size = 9787540, upload-time = "2025-02-05T03:49:51.21Z" }, - { url = "https://files.pythonhosted.org/packages/05/05/a10f9479681e5da09ef2f9426f650d7b550d4bafbef683b69aad1ba87457/mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e", size = 11538051, upload-time = "2025-02-05T03:50:20.885Z" }, - { url = "https://files.pythonhosted.org/packages/e9/9a/1f7d18b30edd57441a6411fcbc0c6869448d1a4bacbaee60656ac0fc29c8/mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c", size = 12286751, upload-time = "2025-02-05T03:49:42.408Z" }, - { url = "https://files.pythonhosted.org/packages/72/af/19ff499b6f1dafcaf56f9881f7a965ac2f474f69f6f618b5175b044299f5/mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f", size = 12421783, upload-time = "2025-02-05T03:49:07.707Z" }, - { url = "https://files.pythonhosted.org/packages/96/39/11b57431a1f686c1aed54bf794870efe0f6aeca11aca281a0bd87a5ad42c/mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f", size = 9265618, upload-time = "2025-02-05T03:49:54.581Z" }, - { url = "https://files.pythonhosted.org/packages/98/3a/03c74331c5eb8bd025734e04c9840532226775c47a2c39b56a0c8d4f128d/mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd", size = 10793981, upload-time = "2025-02-05T03:50:28.25Z" }, - { url = "https://files.pythonhosted.org/packages/f0/1a/41759b18f2cfd568848a37c89030aeb03534411eef981df621d8fad08a1d/mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f", size = 9749175, upload-time = "2025-02-05T03:50:13.411Z" }, - { url = "https://files.pythonhosted.org/packages/12/7e/873481abf1ef112c582db832740f4c11b2bfa510e829d6da29b0ab8c3f9c/mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464", size = 11455675, upload-time = "2025-02-05T03:50:31.421Z" }, - { url = "https://files.pythonhosted.org/packages/b3/d0/92ae4cde706923a2d3f2d6c39629134063ff64b9dedca9c1388363da072d/mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee", size = 12410020, upload-time = "2025-02-05T03:48:48.705Z" }, - { url = "https://files.pythonhosted.org/packages/46/8b/df49974b337cce35f828ba6fda228152d6db45fed4c86ba56ffe442434fd/mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e", size = 12498582, upload-time = "2025-02-05T03:49:03.628Z" }, - { url = "https://files.pythonhosted.org/packages/13/50/da5203fcf6c53044a0b699939f31075c45ae8a4cadf538a9069b165c1050/mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22", size = 9366614, upload-time = "2025-02-05T03:50:00.313Z" }, - { url = "https://files.pythonhosted.org/packages/6a/9b/fd2e05d6ffff24d912f150b87db9e364fa8282045c875654ce7e32fffa66/mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445", size = 10788592, upload-time = "2025-02-05T03:48:55.789Z" }, - { url = "https://files.pythonhosted.org/packages/74/37/b246d711c28a03ead1fd906bbc7106659aed7c089d55fe40dd58db812628/mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d", size = 9753611, upload-time = "2025-02-05T03:48:44.581Z" }, - { url = "https://files.pythonhosted.org/packages/a6/ac/395808a92e10cfdac8003c3de9a2ab6dc7cde6c0d2a4df3df1b815ffd067/mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5", size = 11438443, upload-time = "2025-02-05T03:49:25.514Z" }, - { url = "https://files.pythonhosted.org/packages/d2/8b/801aa06445d2de3895f59e476f38f3f8d610ef5d6908245f07d002676cbf/mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036", size = 12402541, upload-time = "2025-02-05T03:49:57.623Z" }, - { url = "https://files.pythonhosted.org/packages/c7/67/5a4268782eb77344cc613a4cf23540928e41f018a9a1ec4c6882baf20ab8/mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357", size = 12494348, upload-time = "2025-02-05T03:48:52.361Z" }, - { url = "https://files.pythonhosted.org/packages/83/3e/57bb447f7bbbfaabf1712d96f9df142624a386d98fb026a761532526057e/mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf", size = 9373648, upload-time = "2025-02-05T03:49:11.395Z" }, - { url = "https://files.pythonhosted.org/packages/5a/fa/79cf41a55b682794abe71372151dbbf856e3008f6767057229e6649d294a/mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078", size = 10737129, upload-time = "2025-02-05T03:50:24.509Z" }, - { url = "https://files.pythonhosted.org/packages/d3/33/dd8feb2597d648de29e3da0a8bf4e1afbda472964d2a4a0052203a6f3594/mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba", size = 9856335, upload-time = "2025-02-05T03:49:36.398Z" }, - { url = "https://files.pythonhosted.org/packages/e4/b5/74508959c1b06b96674b364ffeb7ae5802646b32929b7701fc6b18447592/mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5", size = 11611935, upload-time = "2025-02-05T03:49:14.154Z" }, - { url = "https://files.pythonhosted.org/packages/6c/53/da61b9d9973efcd6507183fdad96606996191657fe79701b2c818714d573/mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b", size = 12365827, upload-time = "2025-02-05T03:48:59.458Z" }, - { url = "https://files.pythonhosted.org/packages/c1/72/965bd9ee89540c79a25778cc080c7e6ef40aa1eeac4d52cec7eae6eb5228/mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2", size = 12541924, upload-time = "2025-02-05T03:50:03.12Z" }, - { url = "https://files.pythonhosted.org/packages/46/d0/f41645c2eb263e6c77ada7d76f894c580c9ddb20d77f0c24d34273a4dab2/mypy-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980", size = 9271176, upload-time = "2025-02-05T03:50:10.86Z" }, - { url = "https://files.pythonhosted.org/packages/09/4e/a7d65c7322c510de2c409ff3828b03354a7c43f5a8ed458a7a131b41c7b9/mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e", size = 2221777, upload-time = "2025-02-05T03:50:08.348Z" }, + { url = "https://files.pythonhosted.org/packages/8e/12/2bf23a80fcef5edb75de9a1e295d778e0f46ea89eb8b115818b663eff42b/mypy-1.16.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b4f0fed1022a63c6fec38f28b7fc77fca47fd490445c69d0a66266c59dd0b88a", size = 10958644, upload-time = "2025-06-16T16:51:11.649Z" }, + { url = "https://files.pythonhosted.org/packages/08/50/bfe47b3b278eacf348291742fd5e6613bbc4b3434b72ce9361896417cfe5/mypy-1.16.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:86042bbf9f5a05ea000d3203cf87aa9d0ccf9a01f73f71c58979eb9249f46d72", size = 10087033, upload-time = "2025-06-16T16:35:30.089Z" }, + { url = "https://files.pythonhosted.org/packages/21/de/40307c12fe25675a0776aaa2cdd2879cf30d99eec91b898de00228dc3ab5/mypy-1.16.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ea7469ee5902c95542bea7ee545f7006508c65c8c54b06dc2c92676ce526f3ea", size = 11875645, upload-time = "2025-06-16T16:35:48.49Z" }, + { url = "https://files.pythonhosted.org/packages/a6/d8/85bdb59e4a98b7a31495bd8f1a4445d8ffc86cde4ab1f8c11d247c11aedc/mypy-1.16.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:352025753ef6a83cb9e7f2427319bb7875d1fdda8439d1e23de12ab164179574", size = 12616986, upload-time = "2025-06-16T16:48:39.526Z" }, + { url = "https://files.pythonhosted.org/packages/0e/d0/bb25731158fa8f8ee9e068d3e94fcceb4971fedf1424248496292512afe9/mypy-1.16.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ff9fa5b16e4c1364eb89a4d16bcda9987f05d39604e1e6c35378a2987c1aac2d", size = 12878632, upload-time = "2025-06-16T16:36:08.195Z" }, + { url = "https://files.pythonhosted.org/packages/2d/11/822a9beb7a2b825c0cb06132ca0a5183f8327a5e23ef89717c9474ba0bc6/mypy-1.16.1-cp310-cp310-win_amd64.whl", hash = "sha256:1256688e284632382f8f3b9e2123df7d279f603c561f099758e66dd6ed4e8bd6", size = 9484391, upload-time = "2025-06-16T16:37:56.151Z" }, + { url = "https://files.pythonhosted.org/packages/9a/61/ec1245aa1c325cb7a6c0f8570a2eee3bfc40fa90d19b1267f8e50b5c8645/mypy-1.16.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:472e4e4c100062488ec643f6162dd0d5208e33e2f34544e1fc931372e806c0cc", size = 10890557, upload-time = "2025-06-16T16:37:21.421Z" }, + { url = "https://files.pythonhosted.org/packages/6b/bb/6eccc0ba0aa0c7a87df24e73f0ad34170514abd8162eb0c75fd7128171fb/mypy-1.16.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea16e2a7d2714277e349e24d19a782a663a34ed60864006e8585db08f8ad1782", size = 10012921, upload-time = "2025-06-16T16:51:28.659Z" }, + { url = "https://files.pythonhosted.org/packages/5f/80/b337a12e2006715f99f529e732c5f6a8c143bb58c92bb142d5ab380963a5/mypy-1.16.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:08e850ea22adc4d8a4014651575567b0318ede51e8e9fe7a68f25391af699507", size = 11802887, upload-time = "2025-06-16T16:50:53.627Z" }, + { url = "https://files.pythonhosted.org/packages/d9/59/f7af072d09793d581a745a25737c7c0a945760036b16aeb620f658a017af/mypy-1.16.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22d76a63a42619bfb90122889b903519149879ddbf2ba4251834727944c8baca", size = 12531658, upload-time = "2025-06-16T16:33:55.002Z" }, + { url = "https://files.pythonhosted.org/packages/82/c4/607672f2d6c0254b94a646cfc45ad589dd71b04aa1f3d642b840f7cce06c/mypy-1.16.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2c7ce0662b6b9dc8f4ed86eb7a5d505ee3298c04b40ec13b30e572c0e5ae17c4", size = 12732486, upload-time = "2025-06-16T16:37:03.301Z" }, + { url = "https://files.pythonhosted.org/packages/b6/5e/136555ec1d80df877a707cebf9081bd3a9f397dedc1ab9750518d87489ec/mypy-1.16.1-cp311-cp311-win_amd64.whl", hash = "sha256:211287e98e05352a2e1d4e8759c5490925a7c784ddc84207f4714822f8cf99b6", size = 9479482, upload-time = "2025-06-16T16:47:37.48Z" }, + { url = "https://files.pythonhosted.org/packages/b4/d6/39482e5fcc724c15bf6280ff5806548c7185e0c090712a3736ed4d07e8b7/mypy-1.16.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:af4792433f09575d9eeca5c63d7d90ca4aeceda9d8355e136f80f8967639183d", size = 11066493, upload-time = "2025-06-16T16:47:01.683Z" }, + { url = "https://files.pythonhosted.org/packages/e6/e5/26c347890efc6b757f4d5bb83f4a0cf5958b8cf49c938ac99b8b72b420a6/mypy-1.16.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:66df38405fd8466ce3517eda1f6640611a0b8e70895e2a9462d1d4323c5eb4b9", size = 10081687, upload-time = "2025-06-16T16:48:19.367Z" }, + { url = "https://files.pythonhosted.org/packages/44/c7/b5cb264c97b86914487d6a24bd8688c0172e37ec0f43e93b9691cae9468b/mypy-1.16.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44e7acddb3c48bd2713994d098729494117803616e116032af192871aed80b79", size = 11839723, upload-time = "2025-06-16T16:49:20.912Z" }, + { url = "https://files.pythonhosted.org/packages/15/f8/491997a9b8a554204f834ed4816bda813aefda31cf873bb099deee3c9a99/mypy-1.16.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0ab5eca37b50188163fa7c1b73c685ac66c4e9bdee4a85c9adac0e91d8895e15", size = 12722980, upload-time = "2025-06-16T16:37:40.929Z" }, + { url = "https://files.pythonhosted.org/packages/df/f0/2bd41e174b5fd93bc9de9a28e4fb673113633b8a7f3a607fa4a73595e468/mypy-1.16.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb6229b2c9086247e21a83c309754b9058b438704ad2f6807f0d8227f6ebdd", size = 12903328, upload-time = "2025-06-16T16:34:35.099Z" }, + { url = "https://files.pythonhosted.org/packages/61/81/5572108a7bec2c46b8aff7e9b524f371fe6ab5efb534d38d6b37b5490da8/mypy-1.16.1-cp312-cp312-win_amd64.whl", hash = "sha256:1f0435cf920e287ff68af3d10a118a73f212deb2ce087619eb4e648116d1fe9b", size = 9562321, upload-time = "2025-06-16T16:48:58.823Z" }, + { url = "https://files.pythonhosted.org/packages/28/e3/96964af4a75a949e67df4b95318fe2b7427ac8189bbc3ef28f92a1c5bc56/mypy-1.16.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ddc91eb318c8751c69ddb200a5937f1232ee8efb4e64e9f4bc475a33719de438", size = 11063480, upload-time = "2025-06-16T16:47:56.205Z" }, + { url = "https://files.pythonhosted.org/packages/f5/4d/cd1a42b8e5be278fab7010fb289d9307a63e07153f0ae1510a3d7b703193/mypy-1.16.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:87ff2c13d58bdc4bbe7dc0dedfe622c0f04e2cb2a492269f3b418df2de05c536", size = 10090538, upload-time = "2025-06-16T16:46:43.92Z" }, + { url = "https://files.pythonhosted.org/packages/c9/4f/c3c6b4b66374b5f68bab07c8cabd63a049ff69796b844bc759a0ca99bb2a/mypy-1.16.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a7cfb0fe29fe5a9841b7c8ee6dffb52382c45acdf68f032145b75620acfbd6f", size = 11836839, upload-time = "2025-06-16T16:36:28.039Z" }, + { url = "https://files.pythonhosted.org/packages/b4/7e/81ca3b074021ad9775e5cb97ebe0089c0f13684b066a750b7dc208438403/mypy-1.16.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:051e1677689c9d9578b9c7f4d206d763f9bbd95723cd1416fad50db49d52f359", size = 12715634, upload-time = "2025-06-16T16:50:34.441Z" }, + { url = "https://files.pythonhosted.org/packages/e9/95/bdd40c8be346fa4c70edb4081d727a54d0a05382d84966869738cfa8a497/mypy-1.16.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d5d2309511cc56c021b4b4e462907c2b12f669b2dbeb68300110ec27723971be", size = 12895584, upload-time = "2025-06-16T16:34:54.857Z" }, + { url = "https://files.pythonhosted.org/packages/5a/fd/d486a0827a1c597b3b48b1bdef47228a6e9ee8102ab8c28f944cb83b65dc/mypy-1.16.1-cp313-cp313-win_amd64.whl", hash = "sha256:4f58ac32771341e38a853c5d0ec0dfe27e18e27da9cdb8bbc882d2249c71a3ee", size = 9573886, upload-time = "2025-06-16T16:36:43.589Z" }, + { url = "https://files.pythonhosted.org/packages/49/5e/ed1e6a7344005df11dfd58b0fdd59ce939a0ba9f7ed37754bf20670b74db/mypy-1.16.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7fc688329af6a287567f45cc1cefb9db662defeb14625213a5b7da6e692e2069", size = 10959511, upload-time = "2025-06-16T16:47:21.945Z" }, + { url = "https://files.pythonhosted.org/packages/30/88/a7cbc2541e91fe04f43d9e4577264b260fecedb9bccb64ffb1a34b7e6c22/mypy-1.16.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e198ab3f55924c03ead626ff424cad1732d0d391478dfbf7bb97b34602395da", size = 10075555, upload-time = "2025-06-16T16:50:14.084Z" }, + { url = "https://files.pythonhosted.org/packages/93/f7/c62b1e31a32fbd1546cca5e0a2e5f181be5761265ad1f2e94f2a306fa906/mypy-1.16.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:09aa4f91ada245f0a45dbc47e548fd94e0dd5a8433e0114917dc3b526912a30c", size = 11874169, upload-time = "2025-06-16T16:49:42.276Z" }, + { url = "https://files.pythonhosted.org/packages/c8/15/db580a28034657fb6cb87af2f8996435a5b19d429ea4dcd6e1c73d418e60/mypy-1.16.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13c7cd5b1cb2909aa318a90fd1b7e31f17c50b242953e7dd58345b2a814f6383", size = 12610060, upload-time = "2025-06-16T16:34:15.215Z" }, + { url = "https://files.pythonhosted.org/packages/ec/78/c17f48f6843048fa92d1489d3095e99324f2a8c420f831a04ccc454e2e51/mypy-1.16.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:58e07fb958bc5d752a280da0e890c538f1515b79a65757bbdc54252ba82e0b40", size = 12875199, upload-time = "2025-06-16T16:35:14.448Z" }, + { url = "https://files.pythonhosted.org/packages/bc/d6/ed42167d0a42680381653fd251d877382351e1bd2c6dd8a818764be3beb1/mypy-1.16.1-cp39-cp39-win_amd64.whl", hash = "sha256:f895078594d918f93337a505f8add9bd654d1a24962b4c6ed9390e12531eb31b", size = 9487033, upload-time = "2025-06-16T16:49:57.907Z" }, + { url = "https://files.pythonhosted.org/packages/cf/d3/53e684e78e07c1a2bf7105715e5edd09ce951fc3f47cf9ed095ec1b7a037/mypy-1.16.1-py3-none-any.whl", hash = "sha256:5fc2ac4027d0ef28d6ba69a0343737a23c4d1b83672bf38d1fe237bdc0643b37", size = 2265923, upload-time = "2025-06-16T16:48:02.366Z" }, ] [[package]] @@ -598,6 +595,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451, upload-time = "2024-11-08T09:47:44.722Z" }, ] +[[package]] +name = "pathspec" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" }, +] + [[package]] name = "pluggy" version = "1.6.0" @@ -618,7 +624,7 @@ wheels = [ [[package]] name = "pydantic" -version = "2.11.4" +version = "2.11.7" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-types" }, @@ -626,9 +632,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/77/ab/5250d56ad03884ab5efd07f734203943c8a8ab40d551e208af81d0257bf2/pydantic-2.11.4.tar.gz", hash = "sha256:32738d19d63a226a52eed76645a98ee07c1f410ee41d93b4afbfa85ed8111c2d", size = 786540, upload-time = "2025-04-29T20:38:55.02Z" } +sdist = { url = "https://files.pythonhosted.org/packages/00/dd/4325abf92c39ba8623b5af936ddb36ffcfe0beae70405d456ab1fb2f5b8c/pydantic-2.11.7.tar.gz", hash = "sha256:d989c3c6cb79469287b1569f7447a17848c998458d49ebe294e975b9baf0f0db", size = 788350, upload-time = "2025-06-14T08:33:17.137Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e7/12/46b65f3534d099349e38ef6ec98b1a5a81f42536d17e0ba382c28c67ba67/pydantic-2.11.4-py3-none-any.whl", hash = "sha256:d9615eaa9ac5a063471da949c8fc16376a84afb5024688b3ff885693506764eb", size = 443900, upload-time = "2025-04-29T20:38:52.724Z" }, + { url = "https://files.pythonhosted.org/packages/6a/c0/ec2b1c8712ca690e5d61979dee872603e92b8a32f94cc1b72d53beab008a/pydantic-2.11.7-py3-none-any.whl", hash = "sha256:dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b", size = 444782, upload-time = "2025-06-14T08:33:14.905Z" }, ] [[package]] @@ -740,9 +746,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d4/29/3cade8a924a61f60ccfa10842f75eb12787e1440e2b8660ceffeb26685e7/pydantic_core-2.33.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2807668ba86cb38c6817ad9bc66215ab8584d1d304030ce4f0887336f28a5e27", size = 2066661, upload-time = "2025-04-23T18:33:49.995Z" }, ] +[[package]] +name = "pygments" +version = "2.19.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, +] + [[package]] name = "pytest" -version = "8.3.5" +version = "8.4.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, @@ -750,36 +765,37 @@ dependencies = [ { name = "iniconfig" }, { name = "packaging" }, { name = "pluggy" }, + { name = "pygments" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ae/3c/c9d525a414d506893f0cd8a8d0de7706446213181570cdbd766691164e40/pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845", size = 1450891, upload-time = "2025-03-02T12:54:54.503Z" } +sdist = { url = "https://files.pythonhosted.org/packages/08/ba/45911d754e8eba3d5a841a5ce61a65a685ff1798421ac054f85aa8747dfb/pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c", size = 1517714, upload-time = "2025-06-18T05:48:06.109Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/30/3d/64ad57c803f1fa1e963a7946b6e0fea4a70df53c1a7fed304586539c2bac/pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", size = 343634, upload-time = "2025-03-02T12:54:52.069Z" }, + { url = "https://files.pythonhosted.org/packages/29/16/c8a903f4c4dffe7a12843191437d7cd8e32751d5de349d45d3fe69544e87/pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7", size = 365474, upload-time = "2025-06-18T05:48:03.955Z" }, ] [[package]] name = "pytest-asyncio" -version = "0.26.0" +version = "1.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pytest" }, { name = "typing-extensions", marker = "python_full_version < '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8e/c4/453c52c659521066969523e87d85d54139bbd17b78f09532fb8eb8cdb58e/pytest_asyncio-0.26.0.tar.gz", hash = "sha256:c4df2a697648241ff39e7f0e4a73050b03f123f760673956cf0d72a4990e312f", size = 54156, upload-time = "2025-03-25T06:22:28.883Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/d4/14f53324cb1a6381bef29d698987625d80052bb33932d8e7cbf9b337b17c/pytest_asyncio-1.0.0.tar.gz", hash = "sha256:d15463d13f4456e1ead2594520216b225a16f781e144f8fdf6c5bb4667c48b3f", size = 46960, upload-time = "2025-05-26T04:54:40.484Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/20/7f/338843f449ace853647ace35870874f69a764d251872ed1b4de9f234822c/pytest_asyncio-0.26.0-py3-none-any.whl", hash = "sha256:7b51ed894f4fbea1340262bdae5135797ebbe21d8638978e35d31c6d19f72fb0", size = 19694, upload-time = "2025-03-25T06:22:27.807Z" }, + { url = "https://files.pythonhosted.org/packages/30/05/ce271016e351fddc8399e546f6e23761967ee09c8c568bbfbecb0c150171/pytest_asyncio-1.0.0-py3-none-any.whl", hash = "sha256:4f024da9f1ef945e680dc68610b52550e36590a67fd31bb3b4943979a1f90ef3", size = 15976, upload-time = "2025-05-26T04:54:39.035Z" }, ] [[package]] name = "pytest-mock" -version = "3.14.0" +version = "3.14.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c6/90/a955c3ab35ccd41ad4de556596fa86685bf4fc5ffcc62d22d856cfd4e29a/pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0", size = 32814, upload-time = "2024-03-21T22:14:04.964Z" } +sdist = { url = "https://files.pythonhosted.org/packages/71/28/67172c96ba684058a4d24ffe144d64783d2a270d0af0d9e792737bddc75c/pytest_mock-3.14.1.tar.gz", hash = "sha256:159e9edac4c451ce77a5cdb9fc5d1100708d2dd4ba3c3df572f14097351af80e", size = 33241, upload-time = "2025-05-26T13:58:45.167Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f2/3b/b26f90f74e2986a82df6e7ac7e319b8ea7ccece1caec9f8ab6104dc70603/pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f", size = 9863, upload-time = "2024-03-21T22:14:02.694Z" }, + { url = "https://files.pythonhosted.org/packages/b2/05/77b60e520511c53d1c1ca75f1930c7dd8e971d0c4379b7f4b3f9644685ba/pytest_mock-3.14.1-py3-none-any.whl", hash = "sha256:178aefcd11307d874b4cd3100344e7e2d888d9791a6a1d9bfe90fbc1b74fd1d0", size = 9923, upload-time = "2025-05-26T13:58:43.487Z" }, ] [[package]] @@ -862,7 +878,7 @@ wheels = [ [[package]] name = "requests" -version = "2.32.3" +version = "2.32.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, @@ -870,9 +886,9 @@ dependencies = [ { name = "idna" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218, upload-time = "2024-05-29T15:37:49.536Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e1/0a/929373653770d8a0d7ea76c37de6e41f11eb07559b103b1c02cafb3f7cf8/requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422", size = 135258, upload-time = "2025-06-09T16:43:07.34Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928, upload-time = "2024-05-29T15:37:47.027Z" }, + { url = "https://files.pythonhosted.org/packages/7c/e4/56027c4a6b4ae70ca9de302488c5ca95ad4a39e190093d6c1a8ace08341b/requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", size = 64847, upload-time = "2025-06-09T16:43:05.728Z" }, ] [[package]] @@ -889,27 +905,27 @@ wheels = [ [[package]] name = "ruff" -version = "0.11.10" +version = "0.12.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e8/4c/4a3c5a97faaae6b428b336dcca81d03ad04779f8072c267ad2bd860126bf/ruff-0.11.10.tar.gz", hash = "sha256:d522fb204b4959909ecac47da02830daec102eeb100fb50ea9554818d47a5fa6", size = 4165632, upload-time = "2025-05-15T14:08:56.76Z" } +sdist = { url = "https://files.pythonhosted.org/packages/6c/3d/d9a195676f25d00dbfcf3cf95fdd4c685c497fcfa7e862a44ac5e4e96480/ruff-0.12.2.tar.gz", hash = "sha256:d7b4f55cd6f325cb7621244f19c873c565a08aff5a4ba9c69aa7355f3f7afd3e", size = 4432239, upload-time = "2025-07-03T16:40:19.566Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2f/9f/596c628f8824a2ce4cd12b0f0b4c0629a62dfffc5d0f742c19a1d71be108/ruff-0.11.10-py3-none-linux_armv6l.whl", hash = "sha256:859a7bfa7bc8888abbea31ef8a2b411714e6a80f0d173c2a82f9041ed6b50f58", size = 10316243, upload-time = "2025-05-15T14:08:12.884Z" }, - { url = "https://files.pythonhosted.org/packages/3c/38/c1e0b77ab58b426f8c332c1d1d3432d9fc9a9ea622806e208220cb133c9e/ruff-0.11.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:968220a57e09ea5e4fd48ed1c646419961a0570727c7e069842edd018ee8afed", size = 11083636, upload-time = "2025-05-15T14:08:16.551Z" }, - { url = "https://files.pythonhosted.org/packages/23/41/b75e15961d6047d7fe1b13886e56e8413be8467a4e1be0a07f3b303cd65a/ruff-0.11.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1067245bad978e7aa7b22f67113ecc6eb241dca0d9b696144256c3a879663bca", size = 10441624, upload-time = "2025-05-15T14:08:19.032Z" }, - { url = "https://files.pythonhosted.org/packages/b6/2c/e396b6703f131406db1811ea3d746f29d91b41bbd43ad572fea30da1435d/ruff-0.11.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4854fd09c7aed5b1590e996a81aeff0c9ff51378b084eb5a0b9cd9518e6cff2", size = 10624358, upload-time = "2025-05-15T14:08:21.542Z" }, - { url = "https://files.pythonhosted.org/packages/bd/8c/ee6cca8bdaf0f9a3704796022851a33cd37d1340bceaf4f6e991eb164e2e/ruff-0.11.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8b4564e9f99168c0f9195a0fd5fa5928004b33b377137f978055e40008a082c5", size = 10176850, upload-time = "2025-05-15T14:08:23.682Z" }, - { url = "https://files.pythonhosted.org/packages/e9/ce/4e27e131a434321b3b7c66512c3ee7505b446eb1c8a80777c023f7e876e6/ruff-0.11.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b6a9cc5b62c03cc1fea0044ed8576379dbaf751d5503d718c973d5418483641", size = 11759787, upload-time = "2025-05-15T14:08:25.733Z" }, - { url = "https://files.pythonhosted.org/packages/58/de/1e2e77fc72adc7cf5b5123fd04a59ed329651d3eab9825674a9e640b100b/ruff-0.11.10-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:607ecbb6f03e44c9e0a93aedacb17b4eb4f3563d00e8b474298a201622677947", size = 12430479, upload-time = "2025-05-15T14:08:28.013Z" }, - { url = "https://files.pythonhosted.org/packages/07/ed/af0f2340f33b70d50121628ef175523cc4c37619e98d98748c85764c8d88/ruff-0.11.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7b3a522fa389402cd2137df9ddefe848f727250535c70dafa840badffb56b7a4", size = 11919760, upload-time = "2025-05-15T14:08:30.956Z" }, - { url = "https://files.pythonhosted.org/packages/24/09/d7b3d3226d535cb89234390f418d10e00a157b6c4a06dfbe723e9322cb7d/ruff-0.11.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f071b0deed7e9245d5820dac235cbdd4ef99d7b12ff04c330a241ad3534319f", size = 14041747, upload-time = "2025-05-15T14:08:33.297Z" }, - { url = "https://files.pythonhosted.org/packages/62/b3/a63b4e91850e3f47f78795e6630ee9266cb6963de8f0191600289c2bb8f4/ruff-0.11.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a60e3a0a617eafba1f2e4186d827759d65348fa53708ca547e384db28406a0b", size = 11550657, upload-time = "2025-05-15T14:08:35.639Z" }, - { url = "https://files.pythonhosted.org/packages/46/63/a4f95c241d79402ccdbdb1d823d156c89fbb36ebfc4289dce092e6c0aa8f/ruff-0.11.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:da8ec977eaa4b7bf75470fb575bea2cb41a0e07c7ea9d5a0a97d13dbca697bf2", size = 10489671, upload-time = "2025-05-15T14:08:38.437Z" }, - { url = "https://files.pythonhosted.org/packages/6a/9b/c2238bfebf1e473495659c523d50b1685258b6345d5ab0b418ca3f010cd7/ruff-0.11.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ddf8967e08227d1bd95cc0851ef80d2ad9c7c0c5aab1eba31db49cf0a7b99523", size = 10160135, upload-time = "2025-05-15T14:08:41.247Z" }, - { url = "https://files.pythonhosted.org/packages/ba/ef/ba7251dd15206688dbfba7d413c0312e94df3b31b08f5d695580b755a899/ruff-0.11.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5a94acf798a82db188f6f36575d80609072b032105d114b0f98661e1679c9125", size = 11170179, upload-time = "2025-05-15T14:08:43.762Z" }, - { url = "https://files.pythonhosted.org/packages/73/9f/5c336717293203ba275dbfa2ea16e49b29a9fd9a0ea8b6febfc17e133577/ruff-0.11.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:3afead355f1d16d95630df28d4ba17fb2cb9c8dfac8d21ced14984121f639bad", size = 11626021, upload-time = "2025-05-15T14:08:46.451Z" }, - { url = "https://files.pythonhosted.org/packages/d9/2b/162fa86d2639076667c9aa59196c020dc6d7023ac8f342416c2f5ec4bda0/ruff-0.11.10-py3-none-win32.whl", hash = "sha256:dc061a98d32a97211af7e7f3fa1d4ca2fcf919fb96c28f39551f35fc55bdbc19", size = 10494958, upload-time = "2025-05-15T14:08:49.601Z" }, - { url = "https://files.pythonhosted.org/packages/24/f3/66643d8f32f50a4b0d09a4832b7d919145ee2b944d43e604fbd7c144d175/ruff-0.11.10-py3-none-win_amd64.whl", hash = "sha256:5cc725fbb4d25b0f185cb42df07ab6b76c4489b4bfb740a175f3a59c70e8a224", size = 11650285, upload-time = "2025-05-15T14:08:52.392Z" }, - { url = "https://files.pythonhosted.org/packages/95/3a/2e8704d19f376c799748ff9cb041225c1d59f3e7711bc5596c8cfdc24925/ruff-0.11.10-py3-none-win_arm64.whl", hash = "sha256:ef69637b35fb8b210743926778d0e45e1bffa850a7c61e428c6b971549b5f5d1", size = 10765278, upload-time = "2025-05-15T14:08:54.56Z" }, + { url = "https://files.pythonhosted.org/packages/74/b6/2098d0126d2d3318fd5bec3ad40d06c25d377d95749f7a0c5af17129b3b1/ruff-0.12.2-py3-none-linux_armv6l.whl", hash = "sha256:093ea2b221df1d2b8e7ad92fc6ffdca40a2cb10d8564477a987b44fd4008a7be", size = 10369761, upload-time = "2025-07-03T16:39:38.847Z" }, + { url = "https://files.pythonhosted.org/packages/b1/4b/5da0142033dbe155dc598cfb99262d8ee2449d76920ea92c4eeb9547c208/ruff-0.12.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:09e4cf27cc10f96b1708100fa851e0daf21767e9709e1649175355280e0d950e", size = 11155659, upload-time = "2025-07-03T16:39:42.294Z" }, + { url = "https://files.pythonhosted.org/packages/3e/21/967b82550a503d7c5c5c127d11c935344b35e8c521f52915fc858fb3e473/ruff-0.12.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:8ae64755b22f4ff85e9c52d1f82644abd0b6b6b6deedceb74bd71f35c24044cc", size = 10537769, upload-time = "2025-07-03T16:39:44.75Z" }, + { url = "https://files.pythonhosted.org/packages/33/91/00cff7102e2ec71a4890fb7ba1803f2cdb122d82787c7d7cf8041fe8cbc1/ruff-0.12.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3eb3a6b2db4d6e2c77e682f0b988d4d61aff06860158fdb413118ca133d57922", size = 10717602, upload-time = "2025-07-03T16:39:47.652Z" }, + { url = "https://files.pythonhosted.org/packages/9b/eb/928814daec4e1ba9115858adcda44a637fb9010618721937491e4e2283b8/ruff-0.12.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:73448de992d05517170fc37169cbca857dfeaeaa8c2b9be494d7bcb0d36c8f4b", size = 10198772, upload-time = "2025-07-03T16:39:49.641Z" }, + { url = "https://files.pythonhosted.org/packages/50/fa/f15089bc20c40f4f72334f9145dde55ab2b680e51afb3b55422effbf2fb6/ruff-0.12.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b8b94317cbc2ae4a2771af641739f933934b03555e51515e6e021c64441532d", size = 11845173, upload-time = "2025-07-03T16:39:52.069Z" }, + { url = "https://files.pythonhosted.org/packages/43/9f/1f6f98f39f2b9302acc161a4a2187b1e3a97634fe918a8e731e591841cf4/ruff-0.12.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:45fc42c3bf1d30d2008023a0a9a0cfb06bf9835b147f11fe0679f21ae86d34b1", size = 12553002, upload-time = "2025-07-03T16:39:54.551Z" }, + { url = "https://files.pythonhosted.org/packages/d8/70/08991ac46e38ddd231c8f4fd05ef189b1b94be8883e8c0c146a025c20a19/ruff-0.12.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce48f675c394c37e958bf229fb5c1e843e20945a6d962cf3ea20b7a107dcd9f4", size = 12171330, upload-time = "2025-07-03T16:39:57.55Z" }, + { url = "https://files.pythonhosted.org/packages/88/a9/5a55266fec474acfd0a1c73285f19dd22461d95a538f29bba02edd07a5d9/ruff-0.12.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:793d8859445ea47591272021a81391350205a4af65a9392401f418a95dfb75c9", size = 11774717, upload-time = "2025-07-03T16:39:59.78Z" }, + { url = "https://files.pythonhosted.org/packages/87/e5/0c270e458fc73c46c0d0f7cf970bb14786e5fdb88c87b5e423a4bd65232b/ruff-0.12.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6932323db80484dda89153da3d8e58164d01d6da86857c79f1961934354992da", size = 11646659, upload-time = "2025-07-03T16:40:01.934Z" }, + { url = "https://files.pythonhosted.org/packages/b7/b6/45ab96070c9752af37f0be364d849ed70e9ccede07675b0ec4e3ef76b63b/ruff-0.12.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6aa7e623a3a11538108f61e859ebf016c4f14a7e6e4eba1980190cacb57714ce", size = 10604012, upload-time = "2025-07-03T16:40:04.363Z" }, + { url = "https://files.pythonhosted.org/packages/86/91/26a6e6a424eb147cc7627eebae095cfa0b4b337a7c1c413c447c9ebb72fd/ruff-0.12.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:2a4a20aeed74671b2def096bdf2eac610c7d8ffcbf4fb0e627c06947a1d7078d", size = 10176799, upload-time = "2025-07-03T16:40:06.514Z" }, + { url = "https://files.pythonhosted.org/packages/f5/0c/9f344583465a61c8918a7cda604226e77b2c548daf8ef7c2bfccf2b37200/ruff-0.12.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:71a4c550195612f486c9d1f2b045a600aeba851b298c667807ae933478fcef04", size = 11241507, upload-time = "2025-07-03T16:40:08.708Z" }, + { url = "https://files.pythonhosted.org/packages/1c/b7/99c34ded8fb5f86c0280278fa89a0066c3760edc326e935ce0b1550d315d/ruff-0.12.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:4987b8f4ceadf597c927beee65a5eaf994c6e2b631df963f86d8ad1bdea99342", size = 11717609, upload-time = "2025-07-03T16:40:10.836Z" }, + { url = "https://files.pythonhosted.org/packages/51/de/8589fa724590faa057e5a6d171e7f2f6cffe3287406ef40e49c682c07d89/ruff-0.12.2-py3-none-win32.whl", hash = "sha256:369ffb69b70cd55b6c3fc453b9492d98aed98062db9fec828cdfd069555f5f1a", size = 10523823, upload-time = "2025-07-03T16:40:13.203Z" }, + { url = "https://files.pythonhosted.org/packages/94/47/8abf129102ae4c90cba0c2199a1a9b0fa896f6f806238d6f8c14448cc748/ruff-0.12.2-py3-none-win_amd64.whl", hash = "sha256:dca8a3b6d6dc9810ed8f328d406516bf4d660c00caeaef36eb831cf4871b0639", size = 11629831, upload-time = "2025-07-03T16:40:15.478Z" }, + { url = "https://files.pythonhosted.org/packages/e2/1f/72d2946e3cc7456bb837e88000eb3437e55f80db339c840c04015a11115d/ruff-0.12.2-py3-none-win_arm64.whl", hash = "sha256:48d6c6bfb4761df68bc05ae630e24f506755e702d4fb08f08460be778c7ccb12", size = 10735334, upload-time = "2025-07-03T16:40:17.677Z" }, ] [[package]] @@ -983,32 +999,32 @@ wheels = [ [[package]] name = "typing-extensions" -version = "4.13.2" +version = "4.14.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f6/37/23083fcd6e35492953e8d2aaaa68b860eb422b34627b13f2ce3eb6106061/typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef", size = 106967, upload-time = "2025-04-10T14:19:05.416Z" } +sdist = { url = "https://files.pythonhosted.org/packages/98/5a/da40306b885cc8c09109dc2e1abd358d5684b1425678151cdaed4731c822/typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36", size = 107673, upload-time = "2025-07-04T13:28:34.16Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806, upload-time = "2025-04-10T14:19:03.967Z" }, + { url = "https://files.pythonhosted.org/packages/b5/00/d631e67a838026495268c2f6884f3711a15a9a2a96cd244fdaea53b823fb/typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76", size = 43906, upload-time = "2025-07-04T13:28:32.743Z" }, ] [[package]] name = "typing-inspection" -version = "0.4.0" +version = "0.4.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/82/5c/e6082df02e215b846b4b8c0b887a64d7d08ffaba30605502639d44c06b82/typing_inspection-0.4.0.tar.gz", hash = "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122", size = 76222, upload-time = "2025-02-25T17:27:59.638Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/b1/0c11f5058406b3af7609f121aaa6b609744687f1d158b3c3a5bf4cc94238/typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28", size = 75726, upload-time = "2025-05-21T18:55:23.885Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/31/08/aa4fdfb71f7de5176385bd9e90852eaf6b5d622735020ad600f2bab54385/typing_inspection-0.4.0-py3-none-any.whl", hash = "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f", size = 14125, upload-time = "2025-02-25T17:27:57.754Z" }, + { url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552, upload-time = "2025-05-21T18:55:22.152Z" }, ] [[package]] name = "urllib3" -version = "2.4.0" +version = "2.5.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8a/78/16493d9c386d8e60e442a35feac5e00f0913c0f4b7c217c11e8ec2ff53e0/urllib3-2.4.0.tar.gz", hash = "sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466", size = 390672, upload-time = "2025-04-10T15:23:39.232Z" } +sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6b/11/cc635220681e93a0183390e26485430ca2c7b5f9d33b15c74c2861cb8091/urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813", size = 128680, upload-time = "2025-04-10T15:23:37.377Z" }, + { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" }, ] [[package]] diff --git a/libs/checkpoint/uv.lock b/libs/checkpoint/uv.lock index 0fad33ab7..b77cf894b 100644 --- a/libs/checkpoint/uv.lock +++ b/libs/checkpoint/uv.lock @@ -2,8 +2,7 @@ version = 1 revision = 2 requires-python = ">=3.9" resolution-markers = [ - "python_full_version >= '3.12.4'", - "python_full_version >= '3.12' and python_full_version < '3.12.4'", + "python_full_version >= '3.12'", "python_full_version == '3.11.*'", "python_full_version == '3.10.*'", "python_full_version < '3.10'", @@ -35,11 +34,11 @@ wheels = [ [[package]] name = "certifi" -version = "2025.4.26" +version = "2025.6.15" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e8/9e/c05b3920a3b7d20d3d3310465f50348e5b3694f4f88c6daf736eef3024c4/certifi-2025.4.26.tar.gz", hash = "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6", size = 160705, upload-time = "2025-04-26T02:12:29.51Z" } +sdist = { url = "https://files.pythonhosted.org/packages/73/f7/f14b46d4bcd21092d7d3ccef689615220d8a08fb25e564b65d20738e672e/certifi-2025.6.15.tar.gz", hash = "sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b", size = 158753, upload-time = "2025-06-15T02:45:51.329Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4a/7e/3db2bd1b1f9e95f7cddca6d6e75e2f2bd9f51b1246e546d88addca0106bd/certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3", size = 159618, upload-time = "2025-04-26T02:12:27.662Z" }, + { url = "https://files.pythonhosted.org/packages/84/ae/320161bd181fc06471eed047ecce67b693fd7515b16d495d8932db763426/certifi-2025.6.15-py3-none-any.whl", hash = "sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057", size = 157650, upload-time = "2025-06-15T02:45:49.977Z" }, ] [[package]] @@ -306,7 +305,7 @@ wheels = [ [[package]] name = "langchain-core" -version = "0.3.60" +version = "0.3.68" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jsonpatch" }, @@ -317,9 +316,9 @@ dependencies = [ { name = "tenacity" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5b/75/95129aaada92980a002a31e002610a80af3c8967ae7884710372e89cdde0/langchain_core-0.3.60.tar.gz", hash = "sha256:63dd1bdf7939816115399522661ca85a2f3686a61440f2f46ebd86d1b028595b", size = 557456, upload-time = "2025-05-15T15:23:23.642Z" } +sdist = { url = "https://files.pythonhosted.org/packages/23/20/f5b18a17bfbe3416177e702ab2fd230b7d168abb17be31fb48f43f0bb772/langchain_core-0.3.68.tar.gz", hash = "sha256:312e1932ac9aa2eaf111b70fdc171776fa571d1a86c1f873dcac88a094b19c6f", size = 563041, upload-time = "2025-07-03T17:02:28.704Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2d/bc/344f5b11fdfe0e27f7064d2e829921a791461dc32e5ed285fe6325518c26/langchain_core-0.3.60-py3-none-any.whl", hash = "sha256:2ccdf06b12e699b1b0962bc02837056c075b4981c3d13f82a4d4c30bb22ea3dc", size = 437890, upload-time = "2025-05-15T15:23:22.278Z" }, + { url = "https://files.pythonhosted.org/packages/f9/da/c89be0a272993bfcb762b2a356b9f55de507784c2755ad63caec25d183bf/langchain_core-0.3.68-py3-none-any.whl", hash = "sha256:5e5c1fbef419590537c91b8c2d86af896fbcbaf0d5ed7fdcdd77f7d8f3467ba0", size = 441405, upload-time = "2025-07-03T17:02:27.115Z" }, ] [[package]] @@ -338,10 +337,10 @@ dev = [ { name = "mypy" }, { name = "numpy", version = "2.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, - { name = "numpy", version = "2.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "numpy", version = "2.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "pandas" }, { name = "pandas-stubs", version = "2.2.2.240807", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "pandas-stubs", version = "2.2.3.250527", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "pandas-stubs", version = "2.3.0.250703", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "pytest" }, { name = "pytest-asyncio" }, { name = "pytest-mock" }, @@ -372,7 +371,7 @@ dev = [ [[package]] name = "langsmith" -version = "0.3.42" +version = "0.4.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, @@ -383,9 +382,9 @@ dependencies = [ { name = "requests-toolbelt" }, { name = "zstandard" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3a/44/fe171c0b0fb0377b191aebf0b7779e0c7b2a53693c6a01ddad737212495d/langsmith-0.3.42.tar.gz", hash = "sha256:2b5cbc450ab808b992362aac6943bb1d285579aa68a3a8be901d30a393458f25", size = 345619, upload-time = "2025-05-03T03:07:17.873Z" } +sdist = { url = "https://files.pythonhosted.org/packages/20/c8/8d2e0fc438d2d3d8d4300f7684ea30a754344ed00d7ba9cc2705241d2a5f/langsmith-0.4.4.tar.gz", hash = "sha256:70c53bbff24a7872e88e6fa0af98270f4986a6e364f9e85db1cc5636defa4d66", size = 352105, upload-time = "2025-06-27T19:20:36.207Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/89/8e/e8a58e0abaae3f3ac4702e9ca35d1fc6159711556b64ffd0e247771a3f12/langsmith-0.3.42-py3-none-any.whl", hash = "sha256:18114327f3364385dae4026ebfd57d1c1cb46d8f80931098f0f10abe533475ff", size = 360334, upload-time = "2025-05-03T03:07:15.491Z" }, + { url = "https://files.pythonhosted.org/packages/1d/33/a3337eb70d795495a299a1640d7a75f17fb917155a64309b96106e7b9452/langsmith-0.4.4-py3-none-any.whl", hash = "sha256:014c68329bd085bd6c770a6405c61bb6881f82eb554ce8c4d1984b0035fd1716", size = 367687, upload-time = "2025-06-27T19:20:33.839Z" }, ] [[package]] @@ -402,46 +401,47 @@ wheels = [ [[package]] name = "mypy" -version = "1.15.0" +version = "1.16.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "mypy-extensions" }, + { name = "pathspec" }, { name = "tomli", marker = "python_full_version < '3.11'" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ce/43/d5e49a86afa64bd3839ea0d5b9c7103487007d728e1293f52525d6d5486a/mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43", size = 3239717, upload-time = "2025-02-05T03:50:34.655Z" } +sdist = { url = "https://files.pythonhosted.org/packages/81/69/92c7fa98112e4d9eb075a239caa4ef4649ad7d441545ccffbd5e34607cbb/mypy-1.16.1.tar.gz", hash = "sha256:6bd00a0a2094841c5e47e7374bb42b83d64c527a502e3334e1173a0c24437bab", size = 3324747, upload-time = "2025-06-16T16:51:35.145Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/68/f8/65a7ce8d0e09b6329ad0c8d40330d100ea343bd4dd04c4f8ae26462d0a17/mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13", size = 10738433, upload-time = "2025-02-05T03:49:29.145Z" }, - { url = "https://files.pythonhosted.org/packages/b4/95/9c0ecb8eacfe048583706249439ff52105b3f552ea9c4024166c03224270/mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559", size = 9861472, upload-time = "2025-02-05T03:49:16.986Z" }, - { url = "https://files.pythonhosted.org/packages/84/09/9ec95e982e282e20c0d5407bc65031dfd0f0f8ecc66b69538296e06fcbee/mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b", size = 11611424, upload-time = "2025-02-05T03:49:46.908Z" }, - { url = "https://files.pythonhosted.org/packages/78/13/f7d14e55865036a1e6a0a69580c240f43bc1f37407fe9235c0d4ef25ffb0/mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3", size = 12365450, upload-time = "2025-02-05T03:50:05.89Z" }, - { url = "https://files.pythonhosted.org/packages/48/e1/301a73852d40c241e915ac6d7bcd7fedd47d519246db2d7b86b9d7e7a0cb/mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b", size = 12551765, upload-time = "2025-02-05T03:49:33.56Z" }, - { url = "https://files.pythonhosted.org/packages/77/ba/c37bc323ae5fe7f3f15a28e06ab012cd0b7552886118943e90b15af31195/mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828", size = 9274701, upload-time = "2025-02-05T03:49:38.981Z" }, - { url = "https://files.pythonhosted.org/packages/03/bc/f6339726c627bd7ca1ce0fa56c9ae2d0144604a319e0e339bdadafbbb599/mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f", size = 10662338, upload-time = "2025-02-05T03:50:17.287Z" }, - { url = "https://files.pythonhosted.org/packages/e2/90/8dcf506ca1a09b0d17555cc00cd69aee402c203911410136cd716559efe7/mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5", size = 9787540, upload-time = "2025-02-05T03:49:51.21Z" }, - { url = "https://files.pythonhosted.org/packages/05/05/a10f9479681e5da09ef2f9426f650d7b550d4bafbef683b69aad1ba87457/mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e", size = 11538051, upload-time = "2025-02-05T03:50:20.885Z" }, - { url = "https://files.pythonhosted.org/packages/e9/9a/1f7d18b30edd57441a6411fcbc0c6869448d1a4bacbaee60656ac0fc29c8/mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c", size = 12286751, upload-time = "2025-02-05T03:49:42.408Z" }, - { url = "https://files.pythonhosted.org/packages/72/af/19ff499b6f1dafcaf56f9881f7a965ac2f474f69f6f618b5175b044299f5/mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f", size = 12421783, upload-time = "2025-02-05T03:49:07.707Z" }, - { url = "https://files.pythonhosted.org/packages/96/39/11b57431a1f686c1aed54bf794870efe0f6aeca11aca281a0bd87a5ad42c/mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f", size = 9265618, upload-time = "2025-02-05T03:49:54.581Z" }, - { url = "https://files.pythonhosted.org/packages/98/3a/03c74331c5eb8bd025734e04c9840532226775c47a2c39b56a0c8d4f128d/mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd", size = 10793981, upload-time = "2025-02-05T03:50:28.25Z" }, - { url = "https://files.pythonhosted.org/packages/f0/1a/41759b18f2cfd568848a37c89030aeb03534411eef981df621d8fad08a1d/mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f", size = 9749175, upload-time = "2025-02-05T03:50:13.411Z" }, - { url = "https://files.pythonhosted.org/packages/12/7e/873481abf1ef112c582db832740f4c11b2bfa510e829d6da29b0ab8c3f9c/mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464", size = 11455675, upload-time = "2025-02-05T03:50:31.421Z" }, - { url = "https://files.pythonhosted.org/packages/b3/d0/92ae4cde706923a2d3f2d6c39629134063ff64b9dedca9c1388363da072d/mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee", size = 12410020, upload-time = "2025-02-05T03:48:48.705Z" }, - { url = "https://files.pythonhosted.org/packages/46/8b/df49974b337cce35f828ba6fda228152d6db45fed4c86ba56ffe442434fd/mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e", size = 12498582, upload-time = "2025-02-05T03:49:03.628Z" }, - { url = "https://files.pythonhosted.org/packages/13/50/da5203fcf6c53044a0b699939f31075c45ae8a4cadf538a9069b165c1050/mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22", size = 9366614, upload-time = "2025-02-05T03:50:00.313Z" }, - { url = "https://files.pythonhosted.org/packages/6a/9b/fd2e05d6ffff24d912f150b87db9e364fa8282045c875654ce7e32fffa66/mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445", size = 10788592, upload-time = "2025-02-05T03:48:55.789Z" }, - { url = "https://files.pythonhosted.org/packages/74/37/b246d711c28a03ead1fd906bbc7106659aed7c089d55fe40dd58db812628/mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d", size = 9753611, upload-time = "2025-02-05T03:48:44.581Z" }, - { url = "https://files.pythonhosted.org/packages/a6/ac/395808a92e10cfdac8003c3de9a2ab6dc7cde6c0d2a4df3df1b815ffd067/mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5", size = 11438443, upload-time = "2025-02-05T03:49:25.514Z" }, - { url = "https://files.pythonhosted.org/packages/d2/8b/801aa06445d2de3895f59e476f38f3f8d610ef5d6908245f07d002676cbf/mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036", size = 12402541, upload-time = "2025-02-05T03:49:57.623Z" }, - { url = "https://files.pythonhosted.org/packages/c7/67/5a4268782eb77344cc613a4cf23540928e41f018a9a1ec4c6882baf20ab8/mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357", size = 12494348, upload-time = "2025-02-05T03:48:52.361Z" }, - { url = "https://files.pythonhosted.org/packages/83/3e/57bb447f7bbbfaabf1712d96f9df142624a386d98fb026a761532526057e/mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf", size = 9373648, upload-time = "2025-02-05T03:49:11.395Z" }, - { url = "https://files.pythonhosted.org/packages/5a/fa/79cf41a55b682794abe71372151dbbf856e3008f6767057229e6649d294a/mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078", size = 10737129, upload-time = "2025-02-05T03:50:24.509Z" }, - { url = "https://files.pythonhosted.org/packages/d3/33/dd8feb2597d648de29e3da0a8bf4e1afbda472964d2a4a0052203a6f3594/mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba", size = 9856335, upload-time = "2025-02-05T03:49:36.398Z" }, - { url = "https://files.pythonhosted.org/packages/e4/b5/74508959c1b06b96674b364ffeb7ae5802646b32929b7701fc6b18447592/mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5", size = 11611935, upload-time = "2025-02-05T03:49:14.154Z" }, - { url = "https://files.pythonhosted.org/packages/6c/53/da61b9d9973efcd6507183fdad96606996191657fe79701b2c818714d573/mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b", size = 12365827, upload-time = "2025-02-05T03:48:59.458Z" }, - { url = "https://files.pythonhosted.org/packages/c1/72/965bd9ee89540c79a25778cc080c7e6ef40aa1eeac4d52cec7eae6eb5228/mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2", size = 12541924, upload-time = "2025-02-05T03:50:03.12Z" }, - { url = "https://files.pythonhosted.org/packages/46/d0/f41645c2eb263e6c77ada7d76f894c580c9ddb20d77f0c24d34273a4dab2/mypy-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980", size = 9271176, upload-time = "2025-02-05T03:50:10.86Z" }, - { url = "https://files.pythonhosted.org/packages/09/4e/a7d65c7322c510de2c409ff3828b03354a7c43f5a8ed458a7a131b41c7b9/mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e", size = 2221777, upload-time = "2025-02-05T03:50:08.348Z" }, + { url = "https://files.pythonhosted.org/packages/8e/12/2bf23a80fcef5edb75de9a1e295d778e0f46ea89eb8b115818b663eff42b/mypy-1.16.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b4f0fed1022a63c6fec38f28b7fc77fca47fd490445c69d0a66266c59dd0b88a", size = 10958644, upload-time = "2025-06-16T16:51:11.649Z" }, + { url = "https://files.pythonhosted.org/packages/08/50/bfe47b3b278eacf348291742fd5e6613bbc4b3434b72ce9361896417cfe5/mypy-1.16.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:86042bbf9f5a05ea000d3203cf87aa9d0ccf9a01f73f71c58979eb9249f46d72", size = 10087033, upload-time = "2025-06-16T16:35:30.089Z" }, + { url = "https://files.pythonhosted.org/packages/21/de/40307c12fe25675a0776aaa2cdd2879cf30d99eec91b898de00228dc3ab5/mypy-1.16.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ea7469ee5902c95542bea7ee545f7006508c65c8c54b06dc2c92676ce526f3ea", size = 11875645, upload-time = "2025-06-16T16:35:48.49Z" }, + { url = "https://files.pythonhosted.org/packages/a6/d8/85bdb59e4a98b7a31495bd8f1a4445d8ffc86cde4ab1f8c11d247c11aedc/mypy-1.16.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:352025753ef6a83cb9e7f2427319bb7875d1fdda8439d1e23de12ab164179574", size = 12616986, upload-time = "2025-06-16T16:48:39.526Z" }, + { url = "https://files.pythonhosted.org/packages/0e/d0/bb25731158fa8f8ee9e068d3e94fcceb4971fedf1424248496292512afe9/mypy-1.16.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ff9fa5b16e4c1364eb89a4d16bcda9987f05d39604e1e6c35378a2987c1aac2d", size = 12878632, upload-time = "2025-06-16T16:36:08.195Z" }, + { url = "https://files.pythonhosted.org/packages/2d/11/822a9beb7a2b825c0cb06132ca0a5183f8327a5e23ef89717c9474ba0bc6/mypy-1.16.1-cp310-cp310-win_amd64.whl", hash = "sha256:1256688e284632382f8f3b9e2123df7d279f603c561f099758e66dd6ed4e8bd6", size = 9484391, upload-time = "2025-06-16T16:37:56.151Z" }, + { url = "https://files.pythonhosted.org/packages/9a/61/ec1245aa1c325cb7a6c0f8570a2eee3bfc40fa90d19b1267f8e50b5c8645/mypy-1.16.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:472e4e4c100062488ec643f6162dd0d5208e33e2f34544e1fc931372e806c0cc", size = 10890557, upload-time = "2025-06-16T16:37:21.421Z" }, + { url = "https://files.pythonhosted.org/packages/6b/bb/6eccc0ba0aa0c7a87df24e73f0ad34170514abd8162eb0c75fd7128171fb/mypy-1.16.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea16e2a7d2714277e349e24d19a782a663a34ed60864006e8585db08f8ad1782", size = 10012921, upload-time = "2025-06-16T16:51:28.659Z" }, + { url = "https://files.pythonhosted.org/packages/5f/80/b337a12e2006715f99f529e732c5f6a8c143bb58c92bb142d5ab380963a5/mypy-1.16.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:08e850ea22adc4d8a4014651575567b0318ede51e8e9fe7a68f25391af699507", size = 11802887, upload-time = "2025-06-16T16:50:53.627Z" }, + { url = "https://files.pythonhosted.org/packages/d9/59/f7af072d09793d581a745a25737c7c0a945760036b16aeb620f658a017af/mypy-1.16.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22d76a63a42619bfb90122889b903519149879ddbf2ba4251834727944c8baca", size = 12531658, upload-time = "2025-06-16T16:33:55.002Z" }, + { url = "https://files.pythonhosted.org/packages/82/c4/607672f2d6c0254b94a646cfc45ad589dd71b04aa1f3d642b840f7cce06c/mypy-1.16.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2c7ce0662b6b9dc8f4ed86eb7a5d505ee3298c04b40ec13b30e572c0e5ae17c4", size = 12732486, upload-time = "2025-06-16T16:37:03.301Z" }, + { url = "https://files.pythonhosted.org/packages/b6/5e/136555ec1d80df877a707cebf9081bd3a9f397dedc1ab9750518d87489ec/mypy-1.16.1-cp311-cp311-win_amd64.whl", hash = "sha256:211287e98e05352a2e1d4e8759c5490925a7c784ddc84207f4714822f8cf99b6", size = 9479482, upload-time = "2025-06-16T16:47:37.48Z" }, + { url = "https://files.pythonhosted.org/packages/b4/d6/39482e5fcc724c15bf6280ff5806548c7185e0c090712a3736ed4d07e8b7/mypy-1.16.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:af4792433f09575d9eeca5c63d7d90ca4aeceda9d8355e136f80f8967639183d", size = 11066493, upload-time = "2025-06-16T16:47:01.683Z" }, + { url = "https://files.pythonhosted.org/packages/e6/e5/26c347890efc6b757f4d5bb83f4a0cf5958b8cf49c938ac99b8b72b420a6/mypy-1.16.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:66df38405fd8466ce3517eda1f6640611a0b8e70895e2a9462d1d4323c5eb4b9", size = 10081687, upload-time = "2025-06-16T16:48:19.367Z" }, + { url = "https://files.pythonhosted.org/packages/44/c7/b5cb264c97b86914487d6a24bd8688c0172e37ec0f43e93b9691cae9468b/mypy-1.16.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44e7acddb3c48bd2713994d098729494117803616e116032af192871aed80b79", size = 11839723, upload-time = "2025-06-16T16:49:20.912Z" }, + { url = "https://files.pythonhosted.org/packages/15/f8/491997a9b8a554204f834ed4816bda813aefda31cf873bb099deee3c9a99/mypy-1.16.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0ab5eca37b50188163fa7c1b73c685ac66c4e9bdee4a85c9adac0e91d8895e15", size = 12722980, upload-time = "2025-06-16T16:37:40.929Z" }, + { url = "https://files.pythonhosted.org/packages/df/f0/2bd41e174b5fd93bc9de9a28e4fb673113633b8a7f3a607fa4a73595e468/mypy-1.16.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb6229b2c9086247e21a83c309754b9058b438704ad2f6807f0d8227f6ebdd", size = 12903328, upload-time = "2025-06-16T16:34:35.099Z" }, + { url = "https://files.pythonhosted.org/packages/61/81/5572108a7bec2c46b8aff7e9b524f371fe6ab5efb534d38d6b37b5490da8/mypy-1.16.1-cp312-cp312-win_amd64.whl", hash = "sha256:1f0435cf920e287ff68af3d10a118a73f212deb2ce087619eb4e648116d1fe9b", size = 9562321, upload-time = "2025-06-16T16:48:58.823Z" }, + { url = "https://files.pythonhosted.org/packages/28/e3/96964af4a75a949e67df4b95318fe2b7427ac8189bbc3ef28f92a1c5bc56/mypy-1.16.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ddc91eb318c8751c69ddb200a5937f1232ee8efb4e64e9f4bc475a33719de438", size = 11063480, upload-time = "2025-06-16T16:47:56.205Z" }, + { url = "https://files.pythonhosted.org/packages/f5/4d/cd1a42b8e5be278fab7010fb289d9307a63e07153f0ae1510a3d7b703193/mypy-1.16.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:87ff2c13d58bdc4bbe7dc0dedfe622c0f04e2cb2a492269f3b418df2de05c536", size = 10090538, upload-time = "2025-06-16T16:46:43.92Z" }, + { url = "https://files.pythonhosted.org/packages/c9/4f/c3c6b4b66374b5f68bab07c8cabd63a049ff69796b844bc759a0ca99bb2a/mypy-1.16.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a7cfb0fe29fe5a9841b7c8ee6dffb52382c45acdf68f032145b75620acfbd6f", size = 11836839, upload-time = "2025-06-16T16:36:28.039Z" }, + { url = "https://files.pythonhosted.org/packages/b4/7e/81ca3b074021ad9775e5cb97ebe0089c0f13684b066a750b7dc208438403/mypy-1.16.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:051e1677689c9d9578b9c7f4d206d763f9bbd95723cd1416fad50db49d52f359", size = 12715634, upload-time = "2025-06-16T16:50:34.441Z" }, + { url = "https://files.pythonhosted.org/packages/e9/95/bdd40c8be346fa4c70edb4081d727a54d0a05382d84966869738cfa8a497/mypy-1.16.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d5d2309511cc56c021b4b4e462907c2b12f669b2dbeb68300110ec27723971be", size = 12895584, upload-time = "2025-06-16T16:34:54.857Z" }, + { url = "https://files.pythonhosted.org/packages/5a/fd/d486a0827a1c597b3b48b1bdef47228a6e9ee8102ab8c28f944cb83b65dc/mypy-1.16.1-cp313-cp313-win_amd64.whl", hash = "sha256:4f58ac32771341e38a853c5d0ec0dfe27e18e27da9cdb8bbc882d2249c71a3ee", size = 9573886, upload-time = "2025-06-16T16:36:43.589Z" }, + { url = "https://files.pythonhosted.org/packages/49/5e/ed1e6a7344005df11dfd58b0fdd59ce939a0ba9f7ed37754bf20670b74db/mypy-1.16.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7fc688329af6a287567f45cc1cefb9db662defeb14625213a5b7da6e692e2069", size = 10959511, upload-time = "2025-06-16T16:47:21.945Z" }, + { url = "https://files.pythonhosted.org/packages/30/88/a7cbc2541e91fe04f43d9e4577264b260fecedb9bccb64ffb1a34b7e6c22/mypy-1.16.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e198ab3f55924c03ead626ff424cad1732d0d391478dfbf7bb97b34602395da", size = 10075555, upload-time = "2025-06-16T16:50:14.084Z" }, + { url = "https://files.pythonhosted.org/packages/93/f7/c62b1e31a32fbd1546cca5e0a2e5f181be5761265ad1f2e94f2a306fa906/mypy-1.16.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:09aa4f91ada245f0a45dbc47e548fd94e0dd5a8433e0114917dc3b526912a30c", size = 11874169, upload-time = "2025-06-16T16:49:42.276Z" }, + { url = "https://files.pythonhosted.org/packages/c8/15/db580a28034657fb6cb87af2f8996435a5b19d429ea4dcd6e1c73d418e60/mypy-1.16.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13c7cd5b1cb2909aa318a90fd1b7e31f17c50b242953e7dd58345b2a814f6383", size = 12610060, upload-time = "2025-06-16T16:34:15.215Z" }, + { url = "https://files.pythonhosted.org/packages/ec/78/c17f48f6843048fa92d1489d3095e99324f2a8c420f831a04ccc454e2e51/mypy-1.16.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:58e07fb958bc5d752a280da0e890c538f1515b79a65757bbdc54252ba82e0b40", size = 12875199, upload-time = "2025-06-16T16:35:14.448Z" }, + { url = "https://files.pythonhosted.org/packages/bc/d6/ed42167d0a42680381653fd251d877382351e1bd2c6dd8a818764be3beb1/mypy-1.16.1-cp39-cp39-win_amd64.whl", hash = "sha256:f895078594d918f93337a505f8add9bd654d1a24962b4c6ed9390e12531eb31b", size = 9487033, upload-time = "2025-06-16T16:49:57.907Z" }, + { url = "https://files.pythonhosted.org/packages/cf/d3/53e684e78e07c1a2bf7105715e5edd09ce951fc3f47cf9ed095ec1b7a037/mypy-1.16.1-py3-none-any.whl", hash = "sha256:5fc2ac4027d0ef28d6ba69a0343737a23c4d1b83672bf38d1fe237bdc0643b37", size = 2265923, upload-time = "2025-06-16T16:48:02.366Z" }, ] [[package]] @@ -575,65 +575,64 @@ wheels = [ [[package]] name = "numpy" -version = "2.3.0" +version = "2.3.1" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version >= '3.12.4'", - "python_full_version >= '3.12' and python_full_version < '3.12.4'", + "python_full_version >= '3.12'", "python_full_version == '3.11.*'", ] -sdist = { url = "https://files.pythonhosted.org/packages/f3/db/8e12381333aea300890829a0a36bfa738cac95475d88982d538725143fd9/numpy-2.3.0.tar.gz", hash = "sha256:581f87f9e9e9db2cba2141400e160e9dd644ee248788d6f90636eeb8fd9260a6", size = 20382813, upload-time = "2025-06-07T14:54:32.608Z" } +sdist = { url = "https://files.pythonhosted.org/packages/2e/19/d7c972dfe90a353dbd3efbbe1d14a5951de80c99c9dc1b93cd998d51dc0f/numpy-2.3.1.tar.gz", hash = "sha256:1ec9ae20a4226da374362cca3c62cd753faf2f951440b0e3b98e93c235441d2b", size = 20390372, upload-time = "2025-06-21T12:28:33.469Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fd/5f/df67435257d827eb3b8af66f585223dc2c3f2eb7ad0b50cb1dae2f35f494/numpy-2.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c3c9fdde0fa18afa1099d6257eb82890ea4f3102847e692193b54e00312a9ae9", size = 21199688, upload-time = "2025-06-07T14:36:52.067Z" }, - { url = "https://files.pythonhosted.org/packages/e5/ce/aad219575055d6c9ef29c8c540c81e1c38815d3be1fe09cdbe53d48ee838/numpy-2.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:46d16f72c2192da7b83984aa5455baee640e33a9f1e61e656f29adf55e406c2b", size = 14359277, upload-time = "2025-06-07T14:37:15.325Z" }, - { url = "https://files.pythonhosted.org/packages/29/6b/2d31da8e6d2ec99bed54c185337a87f8fbeccc1cd9804e38217e92f3f5e2/numpy-2.3.0-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:a0be278be9307c4ab06b788f2a077f05e180aea817b3e41cebbd5aaf7bd85ed3", size = 5376069, upload-time = "2025-06-07T14:37:25.636Z" }, - { url = "https://files.pythonhosted.org/packages/7d/2a/6c59a062397553ec7045c53d5fcdad44e4536e54972faa2ba44153bca984/numpy-2.3.0-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:99224862d1412d2562248d4710126355d3a8db7672170a39d6909ac47687a8a4", size = 6913057, upload-time = "2025-06-07T14:37:37.215Z" }, - { url = "https://files.pythonhosted.org/packages/d5/5a/8df16f258d28d033e4f359e29d3aeb54663243ac7b71504e89deeb813202/numpy-2.3.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:2393a914db64b0ead0ab80c962e42d09d5f385802006a6c87835acb1f58adb96", size = 14568083, upload-time = "2025-06-07T14:37:59.337Z" }, - { url = "https://files.pythonhosted.org/packages/0a/92/0528a563dfc2cdccdcb208c0e241a4bb500d7cde218651ffb834e8febc50/numpy-2.3.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:7729c8008d55e80784bd113787ce876ca117185c579c0d626f59b87d433ea779", size = 16929402, upload-time = "2025-06-07T14:38:24.343Z" }, - { url = "https://files.pythonhosted.org/packages/e4/2f/e7a8c8d4a2212c527568d84f31587012cf5497a7271ea1f23332142f634e/numpy-2.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:06d4fb37a8d383b769281714897420c5cc3545c79dc427df57fc9b852ee0bf58", size = 15879193, upload-time = "2025-06-07T14:38:48.007Z" }, - { url = "https://files.pythonhosted.org/packages/e2/c3/dada3f005953847fe35f42ac0fe746f6e1ea90b4c6775e4be605dcd7b578/numpy-2.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c39ec392b5db5088259c68250e342612db82dc80ce044cf16496cf14cf6bc6f8", size = 18665318, upload-time = "2025-06-07T14:39:15.794Z" }, - { url = "https://files.pythonhosted.org/packages/3b/ae/3f448517dedefc8dd64d803f9d51a8904a48df730e00a3c5fb1e75a60620/numpy-2.3.0-cp311-cp311-win32.whl", hash = "sha256:ee9d3ee70d62827bc91f3ea5eee33153212c41f639918550ac0475e3588da59f", size = 6601108, upload-time = "2025-06-07T14:39:27.176Z" }, - { url = "https://files.pythonhosted.org/packages/8c/4a/556406d2bb2b9874c8cbc840c962683ac28f21efbc9b01177d78f0199ca1/numpy-2.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:43c55b6a860b0eb44d42341438b03513cf3879cb3617afb749ad49307e164edd", size = 13021525, upload-time = "2025-06-07T14:39:46.637Z" }, - { url = "https://files.pythonhosted.org/packages/ed/ee/bf54278aef30335ffa9a189f869ea09e1a195b3f4b93062164a3b02678a7/numpy-2.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:2e6a1409eee0cb0316cb64640a49a49ca44deb1a537e6b1121dc7c458a1299a8", size = 10170327, upload-time = "2025-06-07T14:40:02.703Z" }, - { url = "https://files.pythonhosted.org/packages/89/59/9df493df81ac6f76e9f05cdbe013cdb0c9a37b434f6e594f5bd25e278908/numpy-2.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:389b85335838155a9076e9ad7f8fdba0827496ec2d2dc32ce69ce7898bde03ba", size = 20897025, upload-time = "2025-06-07T14:40:33.558Z" }, - { url = "https://files.pythonhosted.org/packages/2f/86/4ff04335901d6cf3a6bb9c748b0097546ae5af35e455ae9b962ebff4ecd7/numpy-2.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9498f60cd6bb8238d8eaf468a3d5bb031d34cd12556af53510f05fcf581c1b7e", size = 14129882, upload-time = "2025-06-07T14:40:55.034Z" }, - { url = "https://files.pythonhosted.org/packages/71/8d/a942cd4f959de7f08a79ab0c7e6cecb7431d5403dce78959a726f0f57aa1/numpy-2.3.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:622a65d40d8eb427d8e722fd410ac3ad4958002f109230bc714fa551044ebae2", size = 5110181, upload-time = "2025-06-07T14:41:04.4Z" }, - { url = "https://files.pythonhosted.org/packages/86/5d/45850982efc7b2c839c5626fb67fbbc520d5b0d7c1ba1ae3651f2f74c296/numpy-2.3.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:b9446d9d8505aadadb686d51d838f2b6688c9e85636a0c3abaeb55ed54756459", size = 6647581, upload-time = "2025-06-07T14:41:14.695Z" }, - { url = "https://files.pythonhosted.org/packages/1a/c0/c871d4a83f93b00373d3eebe4b01525eee8ef10b623a335ec262b58f4dc1/numpy-2.3.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:50080245365d75137a2bf46151e975de63146ae6d79f7e6bd5c0e85c9931d06a", size = 14262317, upload-time = "2025-06-07T14:41:35.862Z" }, - { url = "https://files.pythonhosted.org/packages/b7/f6/bc47f5fa666d5ff4145254f9e618d56e6a4ef9b874654ca74c19113bb538/numpy-2.3.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:c24bb4113c66936eeaa0dc1e47c74770453d34f46ee07ae4efd853a2ed1ad10a", size = 16633919, upload-time = "2025-06-07T14:42:00.622Z" }, - { url = "https://files.pythonhosted.org/packages/f5/b4/65f48009ca0c9b76df5f404fccdea5a985a1bb2e34e97f21a17d9ad1a4ba/numpy-2.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4d8d294287fdf685281e671886c6dcdf0291a7c19db3e5cb4178d07ccf6ecc67", size = 15567651, upload-time = "2025-06-07T14:42:24.429Z" }, - { url = "https://files.pythonhosted.org/packages/f1/62/5367855a2018578e9334ed08252ef67cc302e53edc869666f71641cad40b/numpy-2.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6295f81f093b7f5769d1728a6bd8bf7466de2adfa771ede944ce6711382b89dc", size = 18361723, upload-time = "2025-06-07T14:42:51.167Z" }, - { url = "https://files.pythonhosted.org/packages/d4/75/5baed8cd867eabee8aad1e74d7197d73971d6a3d40c821f1848b8fab8b84/numpy-2.3.0-cp312-cp312-win32.whl", hash = "sha256:e6648078bdd974ef5d15cecc31b0c410e2e24178a6e10bf511e0557eed0f2570", size = 6318285, upload-time = "2025-06-07T14:43:02.052Z" }, - { url = "https://files.pythonhosted.org/packages/bc/49/d5781eaa1a15acb3b3a3f49dc9e2ff18d92d0ce5c2976f4ab5c0a7360250/numpy-2.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:0898c67a58cdaaf29994bc0e2c65230fd4de0ac40afaf1584ed0b02cd74c6fdd", size = 12732594, upload-time = "2025-06-07T14:43:21.071Z" }, - { url = "https://files.pythonhosted.org/packages/c2/1c/6d343e030815c7c97a1f9fbad00211b47717c7fe446834c224bd5311e6f1/numpy-2.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:bd8df082b6c4695753ad6193018c05aac465d634834dca47a3ae06d4bb22d9ea", size = 9891498, upload-time = "2025-06-07T14:43:36.332Z" }, - { url = "https://files.pythonhosted.org/packages/73/fc/1d67f751fd4dbafc5780244fe699bc4084268bad44b7c5deb0492473127b/numpy-2.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5754ab5595bfa2c2387d241296e0381c21f44a4b90a776c3c1d39eede13a746a", size = 20889633, upload-time = "2025-06-07T14:44:06.839Z" }, - { url = "https://files.pythonhosted.org/packages/e8/95/73ffdb69e5c3f19ec4530f8924c4386e7ba097efc94b9c0aff607178ad94/numpy-2.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d11fa02f77752d8099573d64e5fe33de3229b6632036ec08f7080f46b6649959", size = 14151683, upload-time = "2025-06-07T14:44:28.847Z" }, - { url = "https://files.pythonhosted.org/packages/64/d5/06d4bb31bb65a1d9c419eb5676173a2f90fd8da3c59f816cc54c640ce265/numpy-2.3.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:aba48d17e87688a765ab1cd557882052f238e2f36545dfa8e29e6a91aef77afe", size = 5102683, upload-time = "2025-06-07T14:44:38.417Z" }, - { url = "https://files.pythonhosted.org/packages/12/8b/6c2cef44f8ccdc231f6b56013dff1d71138c48124334aded36b1a1b30c5a/numpy-2.3.0-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:4dc58865623023b63b10d52f18abaac3729346a7a46a778381e0e3af4b7f3beb", size = 6640253, upload-time = "2025-06-07T14:44:49.359Z" }, - { url = "https://files.pythonhosted.org/packages/62/aa/fca4bf8de3396ddb59544df9b75ffe5b73096174de97a9492d426f5cd4aa/numpy-2.3.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:df470d376f54e052c76517393fa443758fefcdd634645bc9c1f84eafc67087f0", size = 14258658, upload-time = "2025-06-07T14:45:10.156Z" }, - { url = "https://files.pythonhosted.org/packages/1c/12/734dce1087eed1875f2297f687e671cfe53a091b6f2f55f0c7241aad041b/numpy-2.3.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:87717eb24d4a8a64683b7a4e91ace04e2f5c7c77872f823f02a94feee186168f", size = 16628765, upload-time = "2025-06-07T14:45:35.076Z" }, - { url = "https://files.pythonhosted.org/packages/48/03/ffa41ade0e825cbcd5606a5669962419528212a16082763fc051a7247d76/numpy-2.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d8fa264d56882b59dcb5ea4d6ab6f31d0c58a57b41aec605848b6eb2ef4a43e8", size = 15564335, upload-time = "2025-06-07T14:45:58.797Z" }, - { url = "https://files.pythonhosted.org/packages/07/58/869398a11863310aee0ff85a3e13b4c12f20d032b90c4b3ee93c3b728393/numpy-2.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e651756066a0eaf900916497e20e02fe1ae544187cb0fe88de981671ee7f6270", size = 18360608, upload-time = "2025-06-07T14:46:25.687Z" }, - { url = "https://files.pythonhosted.org/packages/2f/8a/5756935752ad278c17e8a061eb2127c9a3edf4ba2c31779548b336f23c8d/numpy-2.3.0-cp313-cp313-win32.whl", hash = "sha256:e43c3cce3b6ae5f94696669ff2a6eafd9a6b9332008bafa4117af70f4b88be6f", size = 6310005, upload-time = "2025-06-07T14:50:13.138Z" }, - { url = "https://files.pythonhosted.org/packages/08/60/61d60cf0dfc0bf15381eaef46366ebc0c1a787856d1db0c80b006092af84/numpy-2.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:81ae0bf2564cf475f94be4a27ef7bcf8af0c3e28da46770fc904da9abd5279b5", size = 12729093, upload-time = "2025-06-07T14:50:31.82Z" }, - { url = "https://files.pythonhosted.org/packages/66/31/2f2f2d2b3e3c32d5753d01437240feaa32220b73258c9eef2e42a0832866/numpy-2.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:c8738baa52505fa6e82778580b23f945e3578412554d937093eac9205e845e6e", size = 9885689, upload-time = "2025-06-07T14:50:47.888Z" }, - { url = "https://files.pythonhosted.org/packages/f1/89/c7828f23cc50f607ceb912774bb4cff225ccae7131c431398ad8400e2c98/numpy-2.3.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:39b27d8b38942a647f048b675f134dd5a567f95bfff481f9109ec308515c51d8", size = 20986612, upload-time = "2025-06-07T14:46:56.077Z" }, - { url = "https://files.pythonhosted.org/packages/dd/46/79ecf47da34c4c50eedec7511e53d57ffdfd31c742c00be7dc1d5ffdb917/numpy-2.3.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:0eba4a1ea88f9a6f30f56fdafdeb8da3774349eacddab9581a21234b8535d3d3", size = 14298953, upload-time = "2025-06-07T14:47:18.053Z" }, - { url = "https://files.pythonhosted.org/packages/59/44/f6caf50713d6ff4480640bccb2a534ce1d8e6e0960c8f864947439f0ee95/numpy-2.3.0-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:b0f1f11d0a1da54927436505a5a7670b154eac27f5672afc389661013dfe3d4f", size = 5225806, upload-time = "2025-06-07T14:47:27.524Z" }, - { url = "https://files.pythonhosted.org/packages/a6/43/e1fd1aca7c97e234dd05e66de4ab7a5be54548257efcdd1bc33637e72102/numpy-2.3.0-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:690d0a5b60a47e1f9dcec7b77750a4854c0d690e9058b7bef3106e3ae9117808", size = 6735169, upload-time = "2025-06-07T14:47:38.057Z" }, - { url = "https://files.pythonhosted.org/packages/84/89/f76f93b06a03177c0faa7ca94d0856c4e5c4bcaf3c5f77640c9ed0303e1c/numpy-2.3.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:8b51ead2b258284458e570942137155978583e407babc22e3d0ed7af33ce06f8", size = 14330701, upload-time = "2025-06-07T14:47:59.113Z" }, - { url = "https://files.pythonhosted.org/packages/aa/f5/4858c3e9ff7a7d64561b20580cf7cc5d085794bd465a19604945d6501f6c/numpy-2.3.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:aaf81c7b82c73bd9b45e79cfb9476cb9c29e937494bfe9092c26aece812818ad", size = 16692983, upload-time = "2025-06-07T14:48:24.196Z" }, - { url = "https://files.pythonhosted.org/packages/08/17/0e3b4182e691a10e9483bcc62b4bb8693dbf9ea5dc9ba0b77a60435074bb/numpy-2.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:f420033a20b4f6a2a11f585f93c843ac40686a7c3fa514060a97d9de93e5e72b", size = 15641435, upload-time = "2025-06-07T14:48:47.712Z" }, - { url = "https://files.pythonhosted.org/packages/4e/d5/463279fda028d3c1efa74e7e8d507605ae87f33dbd0543cf4c4527c8b882/numpy-2.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d344ca32ab482bcf8735d8f95091ad081f97120546f3d250240868430ce52555", size = 18433798, upload-time = "2025-06-07T14:49:14.866Z" }, - { url = "https://files.pythonhosted.org/packages/0e/1e/7a9d98c886d4c39a2b4d3a7c026bffcf8fbcaf518782132d12a301cfc47a/numpy-2.3.0-cp313-cp313t-win32.whl", hash = "sha256:48a2e8eaf76364c32a1feaa60d6925eaf32ed7a040183b807e02674305beef61", size = 6438632, upload-time = "2025-06-07T14:49:25.67Z" }, - { url = "https://files.pythonhosted.org/packages/fe/ab/66fc909931d5eb230107d016861824f335ae2c0533f422e654e5ff556784/numpy-2.3.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ba17f93a94e503551f154de210e4d50c5e3ee20f7e7a1b5f6ce3f22d419b93bb", size = 12868491, upload-time = "2025-06-07T14:49:44.898Z" }, - { url = "https://files.pythonhosted.org/packages/ee/e8/2c8a1c9e34d6f6d600c83d5ce5b71646c32a13f34ca5c518cc060639841c/numpy-2.3.0-cp313-cp313t-win_arm64.whl", hash = "sha256:f14e016d9409680959691c109be98c436c6249eaf7f118b424679793607b5944", size = 9935345, upload-time = "2025-06-07T14:50:02.311Z" }, - { url = "https://files.pythonhosted.org/packages/6a/a2/f8c1133f90eaa1c11bbbec1dc28a42054d0ce74bc2c9838c5437ba5d4980/numpy-2.3.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:80b46117c7359de8167cc00a2c7d823bdd505e8c7727ae0871025a86d668283b", size = 21070759, upload-time = "2025-06-07T14:51:18.241Z" }, - { url = "https://files.pythonhosted.org/packages/6c/e0/4c05fc44ba28463096eee5ae2a12832c8d2759cc5bcec34ae33386d3ff83/numpy-2.3.0-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:5814a0f43e70c061f47abd5857d120179609ddc32a613138cbb6c4e9e2dbdda5", size = 5301054, upload-time = "2025-06-07T14:51:27.413Z" }, - { url = "https://files.pythonhosted.org/packages/8a/3b/6c06cdebe922bbc2a466fe2105f50f661238ea223972a69c7deb823821e7/numpy-2.3.0-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:ef6c1e88fd6b81ac6d215ed71dc8cd027e54d4bf1d2682d362449097156267a2", size = 6817520, upload-time = "2025-06-07T14:51:38.015Z" }, - { url = "https://files.pythonhosted.org/packages/9d/a3/1e536797fd10eb3c5dbd2e376671667c9af19e241843548575267242ea02/numpy-2.3.0-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:33a5a12a45bb82d9997e2c0b12adae97507ad7c347546190a18ff14c28bbca12", size = 14398078, upload-time = "2025-06-07T14:52:00.122Z" }, - { url = "https://files.pythonhosted.org/packages/7c/61/9d574b10d9368ecb1a0c923952aa593510a20df4940aa615b3a71337c8db/numpy-2.3.0-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:54dfc8681c1906d239e95ab1508d0a533c4a9505e52ee2d71a5472b04437ef97", size = 16751324, upload-time = "2025-06-07T14:52:25.077Z" }, - { url = "https://files.pythonhosted.org/packages/39/de/bcad52ce972dc26232629ca3a99721fd4b22c1d2bda84d5db6541913ef9c/numpy-2.3.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:e017a8a251ff4d18d71f139e28bdc7c31edba7a507f72b1414ed902cbe48c74d", size = 12924237, upload-time = "2025-06-07T14:52:44.713Z" }, + { url = "https://files.pythonhosted.org/packages/b0/c7/87c64d7ab426156530676000c94784ef55676df2f13b2796f97722464124/numpy-2.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6ea9e48336a402551f52cd8f593343699003d2353daa4b72ce8d34f66b722070", size = 21199346, upload-time = "2025-06-21T11:47:47.57Z" }, + { url = "https://files.pythonhosted.org/packages/58/0e/0966c2f44beeac12af8d836e5b5f826a407cf34c45cb73ddcdfce9f5960b/numpy-2.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5ccb7336eaf0e77c1635b232c141846493a588ec9ea777a7c24d7166bb8533ae", size = 14361143, upload-time = "2025-06-21T11:48:10.766Z" }, + { url = "https://files.pythonhosted.org/packages/7d/31/6e35a247acb1bfc19226791dfc7d4c30002cd4e620e11e58b0ddf836fe52/numpy-2.3.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:0bb3a4a61e1d327e035275d2a993c96fa786e4913aa089843e6a2d9dd205c66a", size = 5378989, upload-time = "2025-06-21T11:48:19.998Z" }, + { url = "https://files.pythonhosted.org/packages/b0/25/93b621219bb6f5a2d4e713a824522c69ab1f06a57cd571cda70e2e31af44/numpy-2.3.1-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:e344eb79dab01f1e838ebb67aab09965fb271d6da6b00adda26328ac27d4a66e", size = 6912890, upload-time = "2025-06-21T11:48:31.376Z" }, + { url = "https://files.pythonhosted.org/packages/ef/60/6b06ed98d11fb32e27fb59468b42383f3877146d3ee639f733776b6ac596/numpy-2.3.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:467db865b392168ceb1ef1ffa6f5a86e62468c43e0cfb4ab6da667ede10e58db", size = 14569032, upload-time = "2025-06-21T11:48:52.563Z" }, + { url = "https://files.pythonhosted.org/packages/75/c9/9bec03675192077467a9c7c2bdd1f2e922bd01d3a69b15c3a0fdcd8548f6/numpy-2.3.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:afed2ce4a84f6b0fc6c1ce734ff368cbf5a5e24e8954a338f3bdffa0718adffb", size = 16930354, upload-time = "2025-06-21T11:49:17.473Z" }, + { url = "https://files.pythonhosted.org/packages/6a/e2/5756a00cabcf50a3f527a0c968b2b4881c62b1379223931853114fa04cda/numpy-2.3.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0025048b3c1557a20bc80d06fdeb8cc7fc193721484cca82b2cfa072fec71a93", size = 15879605, upload-time = "2025-06-21T11:49:41.161Z" }, + { url = "https://files.pythonhosted.org/packages/ff/86/a471f65f0a86f1ca62dcc90b9fa46174dd48f50214e5446bc16a775646c5/numpy-2.3.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a5ee121b60aa509679b682819c602579e1df14a5b07fe95671c8849aad8f2115", size = 18666994, upload-time = "2025-06-21T11:50:08.516Z" }, + { url = "https://files.pythonhosted.org/packages/43/a6/482a53e469b32be6500aaf61cfafd1de7a0b0d484babf679209c3298852e/numpy-2.3.1-cp311-cp311-win32.whl", hash = "sha256:a8b740f5579ae4585831b3cf0e3b0425c667274f82a484866d2adf9570539369", size = 6603672, upload-time = "2025-06-21T11:50:19.584Z" }, + { url = "https://files.pythonhosted.org/packages/6b/fb/bb613f4122c310a13ec67585c70e14b03bfc7ebabd24f4d5138b97371d7c/numpy-2.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:d4580adadc53311b163444f877e0789f1c8861e2698f6b2a4ca852fda154f3ff", size = 13024015, upload-time = "2025-06-21T11:50:39.139Z" }, + { url = "https://files.pythonhosted.org/packages/51/58/2d842825af9a0c041aca246dc92eb725e1bc5e1c9ac89712625db0c4e11c/numpy-2.3.1-cp311-cp311-win_arm64.whl", hash = "sha256:ec0bdafa906f95adc9a0c6f26a4871fa753f25caaa0e032578a30457bff0af6a", size = 10456989, upload-time = "2025-06-21T11:50:55.616Z" }, + { url = "https://files.pythonhosted.org/packages/c6/56/71ad5022e2f63cfe0ca93559403d0edef14aea70a841d640bd13cdba578e/numpy-2.3.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2959d8f268f3d8ee402b04a9ec4bb7604555aeacf78b360dc4ec27f1d508177d", size = 20896664, upload-time = "2025-06-21T12:15:30.845Z" }, + { url = "https://files.pythonhosted.org/packages/25/65/2db52ba049813670f7f987cc5db6dac9be7cd95e923cc6832b3d32d87cef/numpy-2.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:762e0c0c6b56bdedfef9a8e1d4538556438288c4276901ea008ae44091954e29", size = 14131078, upload-time = "2025-06-21T12:15:52.23Z" }, + { url = "https://files.pythonhosted.org/packages/57/dd/28fa3c17b0e751047ac928c1e1b6990238faad76e9b147e585b573d9d1bd/numpy-2.3.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:867ef172a0976aaa1f1d1b63cf2090de8b636a7674607d514505fb7276ab08fc", size = 5112554, upload-time = "2025-06-21T12:16:01.434Z" }, + { url = "https://files.pythonhosted.org/packages/c9/fc/84ea0cba8e760c4644b708b6819d91784c290288c27aca916115e3311d17/numpy-2.3.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:4e602e1b8682c2b833af89ba641ad4176053aaa50f5cacda1a27004352dde943", size = 6646560, upload-time = "2025-06-21T12:16:11.895Z" }, + { url = "https://files.pythonhosted.org/packages/61/b2/512b0c2ddec985ad1e496b0bd853eeb572315c0f07cd6997473ced8f15e2/numpy-2.3.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:8e333040d069eba1652fb08962ec5b76af7f2c7bce1df7e1418c8055cf776f25", size = 14260638, upload-time = "2025-06-21T12:16:32.611Z" }, + { url = "https://files.pythonhosted.org/packages/6e/45/c51cb248e679a6c6ab14b7a8e3ead3f4a3fe7425fc7a6f98b3f147bec532/numpy-2.3.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:e7cbf5a5eafd8d230a3ce356d892512185230e4781a361229bd902ff403bc660", size = 16632729, upload-time = "2025-06-21T12:16:57.439Z" }, + { url = "https://files.pythonhosted.org/packages/e4/ff/feb4be2e5c09a3da161b412019caf47183099cbea1132fd98061808c2df2/numpy-2.3.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5f1b8f26d1086835f442286c1d9b64bb3974b0b1e41bb105358fd07d20872952", size = 15565330, upload-time = "2025-06-21T12:17:20.638Z" }, + { url = "https://files.pythonhosted.org/packages/bc/6d/ceafe87587101e9ab0d370e4f6e5f3f3a85b9a697f2318738e5e7e176ce3/numpy-2.3.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ee8340cb48c9b7a5899d1149eece41ca535513a9698098edbade2a8e7a84da77", size = 18361734, upload-time = "2025-06-21T12:17:47.938Z" }, + { url = "https://files.pythonhosted.org/packages/2b/19/0fb49a3ea088be691f040c9bf1817e4669a339d6e98579f91859b902c636/numpy-2.3.1-cp312-cp312-win32.whl", hash = "sha256:e772dda20a6002ef7061713dc1e2585bc1b534e7909b2030b5a46dae8ff077ab", size = 6320411, upload-time = "2025-06-21T12:17:58.475Z" }, + { url = "https://files.pythonhosted.org/packages/b1/3e/e28f4c1dd9e042eb57a3eb652f200225e311b608632bc727ae378623d4f8/numpy-2.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:cfecc7822543abdea6de08758091da655ea2210b8ffa1faf116b940693d3df76", size = 12734973, upload-time = "2025-06-21T12:18:17.601Z" }, + { url = "https://files.pythonhosted.org/packages/04/a8/8a5e9079dc722acf53522b8f8842e79541ea81835e9b5483388701421073/numpy-2.3.1-cp312-cp312-win_arm64.whl", hash = "sha256:7be91b2239af2658653c5bb6f1b8bccafaf08226a258caf78ce44710a0160d30", size = 10191491, upload-time = "2025-06-21T12:18:33.585Z" }, + { url = "https://files.pythonhosted.org/packages/d4/bd/35ad97006d8abff8631293f8ea6adf07b0108ce6fec68da3c3fcca1197f2/numpy-2.3.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:25a1992b0a3fdcdaec9f552ef10d8103186f5397ab45e2d25f8ac51b1a6b97e8", size = 20889381, upload-time = "2025-06-21T12:19:04.103Z" }, + { url = "https://files.pythonhosted.org/packages/f1/4f/df5923874d8095b6062495b39729178eef4a922119cee32a12ee1bd4664c/numpy-2.3.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7dea630156d39b02a63c18f508f85010230409db5b2927ba59c8ba4ab3e8272e", size = 14152726, upload-time = "2025-06-21T12:19:25.599Z" }, + { url = "https://files.pythonhosted.org/packages/8c/0f/a1f269b125806212a876f7efb049b06c6f8772cf0121139f97774cd95626/numpy-2.3.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:bada6058dd886061f10ea15f230ccf7dfff40572e99fef440a4a857c8728c9c0", size = 5105145, upload-time = "2025-06-21T12:19:34.782Z" }, + { url = "https://files.pythonhosted.org/packages/6d/63/a7f7fd5f375b0361682f6ffbf686787e82b7bbd561268e4f30afad2bb3c0/numpy-2.3.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:a894f3816eb17b29e4783e5873f92faf55b710c2519e5c351767c51f79d8526d", size = 6639409, upload-time = "2025-06-21T12:19:45.228Z" }, + { url = "https://files.pythonhosted.org/packages/bf/0d/1854a4121af895aab383f4aa233748f1df4671ef331d898e32426756a8a6/numpy-2.3.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:18703df6c4a4fee55fd3d6e5a253d01c5d33a295409b03fda0c86b3ca2ff41a1", size = 14257630, upload-time = "2025-06-21T12:20:06.544Z" }, + { url = "https://files.pythonhosted.org/packages/50/30/af1b277b443f2fb08acf1c55ce9d68ee540043f158630d62cef012750f9f/numpy-2.3.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:5902660491bd7a48b2ec16c23ccb9124b8abfd9583c5fdfa123fe6b421e03de1", size = 16627546, upload-time = "2025-06-21T12:20:31.002Z" }, + { url = "https://files.pythonhosted.org/packages/6e/ec/3b68220c277e463095342d254c61be8144c31208db18d3fd8ef02712bcd6/numpy-2.3.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:36890eb9e9d2081137bd78d29050ba63b8dab95dff7912eadf1185e80074b2a0", size = 15562538, upload-time = "2025-06-21T12:20:54.322Z" }, + { url = "https://files.pythonhosted.org/packages/77/2b/4014f2bcc4404484021c74d4c5ee8eb3de7e3f7ac75f06672f8dcf85140a/numpy-2.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a780033466159c2270531e2b8ac063704592a0bc62ec4a1b991c7c40705eb0e8", size = 18360327, upload-time = "2025-06-21T12:21:21.053Z" }, + { url = "https://files.pythonhosted.org/packages/40/8d/2ddd6c9b30fcf920837b8672f6c65590c7d92e43084c25fc65edc22e93ca/numpy-2.3.1-cp313-cp313-win32.whl", hash = "sha256:39bff12c076812595c3a306f22bfe49919c5513aa1e0e70fac756a0be7c2a2b8", size = 6312330, upload-time = "2025-06-21T12:25:07.447Z" }, + { url = "https://files.pythonhosted.org/packages/dd/c8/beaba449925988d415efccb45bf977ff8327a02f655090627318f6398c7b/numpy-2.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d5ee6eec45f08ce507a6570e06f2f879b374a552087a4179ea7838edbcbfa42", size = 12731565, upload-time = "2025-06-21T12:25:26.444Z" }, + { url = "https://files.pythonhosted.org/packages/0b/c3/5c0c575d7ec78c1126998071f58facfc124006635da75b090805e642c62e/numpy-2.3.1-cp313-cp313-win_arm64.whl", hash = "sha256:0c4d9e0a8368db90f93bd192bfa771ace63137c3488d198ee21dfb8e7771916e", size = 10190262, upload-time = "2025-06-21T12:25:42.196Z" }, + { url = "https://files.pythonhosted.org/packages/ea/19/a029cd335cf72f79d2644dcfc22d90f09caa86265cbbde3b5702ccef6890/numpy-2.3.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:b0b5397374f32ec0649dd98c652a1798192042e715df918c20672c62fb52d4b8", size = 20987593, upload-time = "2025-06-21T12:21:51.664Z" }, + { url = "https://files.pythonhosted.org/packages/25/91/8ea8894406209107d9ce19b66314194675d31761fe2cb3c84fe2eeae2f37/numpy-2.3.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:c5bdf2015ccfcee8253fb8be695516ac4457c743473a43290fd36eba6a1777eb", size = 14300523, upload-time = "2025-06-21T12:22:13.583Z" }, + { url = "https://files.pythonhosted.org/packages/a6/7f/06187b0066eefc9e7ce77d5f2ddb4e314a55220ad62dd0bfc9f2c44bac14/numpy-2.3.1-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:d70f20df7f08b90a2062c1f07737dd340adccf2068d0f1b9b3d56e2038979fee", size = 5227993, upload-time = "2025-06-21T12:22:22.53Z" }, + { url = "https://files.pythonhosted.org/packages/e8/ec/a926c293c605fa75e9cfb09f1e4840098ed46d2edaa6e2152ee35dc01ed3/numpy-2.3.1-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:2fb86b7e58f9ac50e1e9dd1290154107e47d1eef23a0ae9145ded06ea606f992", size = 6736652, upload-time = "2025-06-21T12:22:33.629Z" }, + { url = "https://files.pythonhosted.org/packages/e3/62/d68e52fb6fde5586650d4c0ce0b05ff3a48ad4df4ffd1b8866479d1d671d/numpy-2.3.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:23ab05b2d241f76cb883ce8b9a93a680752fbfcbd51c50eff0b88b979e471d8c", size = 14331561, upload-time = "2025-06-21T12:22:55.056Z" }, + { url = "https://files.pythonhosted.org/packages/fc/ec/b74d3f2430960044bdad6900d9f5edc2dc0fb8bf5a0be0f65287bf2cbe27/numpy-2.3.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:ce2ce9e5de4703a673e705183f64fd5da5bf36e7beddcb63a25ee2286e71ca48", size = 16693349, upload-time = "2025-06-21T12:23:20.53Z" }, + { url = "https://files.pythonhosted.org/packages/0d/15/def96774b9d7eb198ddadfcbd20281b20ebb510580419197e225f5c55c3e/numpy-2.3.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c4913079974eeb5c16ccfd2b1f09354b8fed7e0d6f2cab933104a09a6419b1ee", size = 15642053, upload-time = "2025-06-21T12:23:43.697Z" }, + { url = "https://files.pythonhosted.org/packages/2b/57/c3203974762a759540c6ae71d0ea2341c1fa41d84e4971a8e76d7141678a/numpy-2.3.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:010ce9b4f00d5c036053ca684c77441f2f2c934fd23bee058b4d6f196efd8280", size = 18434184, upload-time = "2025-06-21T12:24:10.708Z" }, + { url = "https://files.pythonhosted.org/packages/22/8a/ccdf201457ed8ac6245187850aff4ca56a79edbea4829f4e9f14d46fa9a5/numpy-2.3.1-cp313-cp313t-win32.whl", hash = "sha256:6269b9edfe32912584ec496d91b00b6d34282ca1d07eb10e82dfc780907d6c2e", size = 6440678, upload-time = "2025-06-21T12:24:21.596Z" }, + { url = "https://files.pythonhosted.org/packages/f1/7e/7f431d8bd8eb7e03d79294aed238b1b0b174b3148570d03a8a8a8f6a0da9/numpy-2.3.1-cp313-cp313t-win_amd64.whl", hash = "sha256:2a809637460e88a113e186e87f228d74ae2852a2e0c44de275263376f17b5bdc", size = 12870697, upload-time = "2025-06-21T12:24:40.644Z" }, + { url = "https://files.pythonhosted.org/packages/d4/ca/af82bf0fad4c3e573c6930ed743b5308492ff19917c7caaf2f9b6f9e2e98/numpy-2.3.1-cp313-cp313t-win_arm64.whl", hash = "sha256:eccb9a159db9aed60800187bc47a6d3451553f0e1b08b068d8b277ddfbb9b244", size = 10260376, upload-time = "2025-06-21T12:24:56.884Z" }, + { url = "https://files.pythonhosted.org/packages/e8/34/facc13b9b42ddca30498fc51f7f73c3d0f2be179943a4b4da8686e259740/numpy-2.3.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ad506d4b09e684394c42c966ec1527f6ebc25da7f4da4b1b056606ffe446b8a3", size = 21070637, upload-time = "2025-06-21T12:26:12.518Z" }, + { url = "https://files.pythonhosted.org/packages/65/b6/41b705d9dbae04649b529fc9bd3387664c3281c7cd78b404a4efe73dcc45/numpy-2.3.1-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:ebb8603d45bc86bbd5edb0d63e52c5fd9e7945d3a503b77e486bd88dde67a19b", size = 5304087, upload-time = "2025-06-21T12:26:22.294Z" }, + { url = "https://files.pythonhosted.org/packages/7a/b4/fe3ac1902bff7a4934a22d49e1c9d71a623204d654d4cc43c6e8fe337fcb/numpy-2.3.1-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:15aa4c392ac396e2ad3d0a2680c0f0dee420f9fed14eef09bdb9450ee6dcb7b7", size = 6817588, upload-time = "2025-06-21T12:26:32.939Z" }, + { url = "https://files.pythonhosted.org/packages/ae/ee/89bedf69c36ace1ac8f59e97811c1f5031e179a37e4821c3a230bf750142/numpy-2.3.1-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c6e0bf9d1a2f50d2b65a7cf56db37c095af17b59f6c132396f7c6d5dd76484df", size = 14399010, upload-time = "2025-06-21T12:26:54.086Z" }, + { url = "https://files.pythonhosted.org/packages/15/08/e00e7070ede29b2b176165eba18d6f9784d5349be3c0c1218338e79c27fd/numpy-2.3.1-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:eabd7e8740d494ce2b4ea0ff05afa1b7b291e978c0ae075487c51e8bd93c0c68", size = 16752042, upload-time = "2025-06-21T12:27:19.018Z" }, + { url = "https://files.pythonhosted.org/packages/48/6b/1c6b515a83d5564b1698a61efa245727c8feecf308f4091f565988519d20/numpy-2.3.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:e610832418a2bc09d974cc9fecebfa51e9532d6190223bc5ef6a7402ebf3b5cb", size = 12927246, upload-time = "2025-06-21T12:27:38.618Z" }, ] [[package]] @@ -779,7 +778,7 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy", version = "2.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, - { name = "numpy", version = "2.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "numpy", version = "2.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "python-dateutil" }, { name = "pytz" }, { name = "tzdata" }, @@ -847,22 +846,30 @@ wheels = [ [[package]] name = "pandas-stubs" -version = "2.2.3.250527" +version = "2.3.0.250703" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version >= '3.12.4'", - "python_full_version >= '3.12' and python_full_version < '3.12.4'", + "python_full_version >= '3.12'", "python_full_version == '3.11.*'", "python_full_version == '3.10.*'", ] dependencies = [ { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, - { name = "numpy", version = "2.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "numpy", version = "2.3.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "types-pytz", marker = "python_full_version >= '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5f/0d/5fe7f7f3596eb1c2526fea151e9470f86b379183d8b9debe44b2098651ca/pandas_stubs-2.2.3.250527.tar.gz", hash = "sha256:e2d694c4e72106055295ad143664e5c99e5815b07190d1ff85b73b13ff019e63", size = 106312, upload-time = "2025-05-27T15:24:29.716Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ec/df/c1c51c5cec087b8f4d04669308b700e9648745a77cdd0c8c5e16520703ca/pandas_stubs-2.3.0.250703.tar.gz", hash = "sha256:fb6a8478327b16ed65c46b1541de74f5c5947f3601850caf3e885e0140584717", size = 103910, upload-time = "2025-07-02T17:49:11.667Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ec/f8/46141ba8c9d7064dc5008bfb4a6ae5bd3c30e4c61c28b5c5ed485bf358ba/pandas_stubs-2.2.3.250527-py3-none-any.whl", hash = "sha256:cd0a49a95b8c5f944e605be711042a4dd8550e2c559b43d70ba2c4b524b66163", size = 159683, upload-time = "2025-05-27T15:24:28.4Z" }, + { url = "https://files.pythonhosted.org/packages/75/cb/09d5f9bf7c8659af134ae0ffc1a349038a5d0ff93e45aedc225bde2872a3/pandas_stubs-2.3.0.250703-py3-none-any.whl", hash = "sha256:a9265fc69909f0f7a9cabc5f596d86c9d531499fed86b7838fd3278285d76b81", size = 154719, upload-time = "2025-07-02T17:49:10.697Z" }, +] + +[[package]] +name = "pathspec" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" }, ] [[package]] @@ -885,7 +892,7 @@ wheels = [ [[package]] name = "pydantic" -version = "2.11.4" +version = "2.11.7" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-types" }, @@ -893,9 +900,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/77/ab/5250d56ad03884ab5efd07f734203943c8a8ab40d551e208af81d0257bf2/pydantic-2.11.4.tar.gz", hash = "sha256:32738d19d63a226a52eed76645a98ee07c1f410ee41d93b4afbfa85ed8111c2d", size = 786540, upload-time = "2025-04-29T20:38:55.02Z" } +sdist = { url = "https://files.pythonhosted.org/packages/00/dd/4325abf92c39ba8623b5af936ddb36ffcfe0beae70405d456ab1fb2f5b8c/pydantic-2.11.7.tar.gz", hash = "sha256:d989c3c6cb79469287b1569f7447a17848c998458d49ebe294e975b9baf0f0db", size = 788350, upload-time = "2025-06-14T08:33:17.137Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e7/12/46b65f3534d099349e38ef6ec98b1a5a81f42536d17e0ba382c28c67ba67/pydantic-2.11.4-py3-none-any.whl", hash = "sha256:d9615eaa9ac5a063471da949c8fc16376a84afb5024688b3ff885693506764eb", size = 443900, upload-time = "2025-04-29T20:38:52.724Z" }, + { url = "https://files.pythonhosted.org/packages/6a/c0/ec2b1c8712ca690e5d61979dee872603e92b8a32f94cc1b72d53beab008a/pydantic-2.11.7-py3-none-any.whl", hash = "sha256:dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b", size = 444782, upload-time = "2025-06-14T08:33:14.905Z" }, ] [[package]] @@ -1007,9 +1014,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d4/29/3cade8a924a61f60ccfa10842f75eb12787e1440e2b8660ceffeb26685e7/pydantic_core-2.33.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2807668ba86cb38c6817ad9bc66215ab8584d1d304030ce4f0887336f28a5e27", size = 2066661, upload-time = "2025-04-23T18:33:49.995Z" }, ] +[[package]] +name = "pygments" +version = "2.19.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, +] + [[package]] name = "pytest" -version = "8.3.5" +version = "8.4.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, @@ -1017,36 +1033,37 @@ dependencies = [ { name = "iniconfig" }, { name = "packaging" }, { name = "pluggy" }, + { name = "pygments" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ae/3c/c9d525a414d506893f0cd8a8d0de7706446213181570cdbd766691164e40/pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845", size = 1450891, upload-time = "2025-03-02T12:54:54.503Z" } +sdist = { url = "https://files.pythonhosted.org/packages/08/ba/45911d754e8eba3d5a841a5ce61a65a685ff1798421ac054f85aa8747dfb/pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c", size = 1517714, upload-time = "2025-06-18T05:48:06.109Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/30/3d/64ad57c803f1fa1e963a7946b6e0fea4a70df53c1a7fed304586539c2bac/pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", size = 343634, upload-time = "2025-03-02T12:54:52.069Z" }, + { url = "https://files.pythonhosted.org/packages/29/16/c8a903f4c4dffe7a12843191437d7cd8e32751d5de349d45d3fe69544e87/pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7", size = 365474, upload-time = "2025-06-18T05:48:03.955Z" }, ] [[package]] name = "pytest-asyncio" -version = "0.26.0" +version = "1.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pytest" }, { name = "typing-extensions", marker = "python_full_version < '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8e/c4/453c52c659521066969523e87d85d54139bbd17b78f09532fb8eb8cdb58e/pytest_asyncio-0.26.0.tar.gz", hash = "sha256:c4df2a697648241ff39e7f0e4a73050b03f123f760673956cf0d72a4990e312f", size = 54156, upload-time = "2025-03-25T06:22:28.883Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/d4/14f53324cb1a6381bef29d698987625d80052bb33932d8e7cbf9b337b17c/pytest_asyncio-1.0.0.tar.gz", hash = "sha256:d15463d13f4456e1ead2594520216b225a16f781e144f8fdf6c5bb4667c48b3f", size = 46960, upload-time = "2025-05-26T04:54:40.484Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/20/7f/338843f449ace853647ace35870874f69a764d251872ed1b4de9f234822c/pytest_asyncio-0.26.0-py3-none-any.whl", hash = "sha256:7b51ed894f4fbea1340262bdae5135797ebbe21d8638978e35d31c6d19f72fb0", size = 19694, upload-time = "2025-03-25T06:22:27.807Z" }, + { url = "https://files.pythonhosted.org/packages/30/05/ce271016e351fddc8399e546f6e23761967ee09c8c568bbfbecb0c150171/pytest_asyncio-1.0.0-py3-none-any.whl", hash = "sha256:4f024da9f1ef945e680dc68610b52550e36590a67fd31bb3b4943979a1f90ef3", size = 15976, upload-time = "2025-05-26T04:54:39.035Z" }, ] [[package]] name = "pytest-mock" -version = "3.14.0" +version = "3.14.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c6/90/a955c3ab35ccd41ad4de556596fa86685bf4fc5ffcc62d22d856cfd4e29a/pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0", size = 32814, upload-time = "2024-03-21T22:14:04.964Z" } +sdist = { url = "https://files.pythonhosted.org/packages/71/28/67172c96ba684058a4d24ffe144d64783d2a270d0af0d9e792737bddc75c/pytest_mock-3.14.1.tar.gz", hash = "sha256:159e9edac4c451ce77a5cdb9fc5d1100708d2dd4ba3c3df572f14097351af80e", size = 33241, upload-time = "2025-05-26T13:58:45.167Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f2/3b/b26f90f74e2986a82df6e7ac7e319b8ea7ccece1caec9f8ab6104dc70603/pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f", size = 9863, upload-time = "2024-03-21T22:14:02.694Z" }, + { url = "https://files.pythonhosted.org/packages/b2/05/77b60e520511c53d1c1ca75f1930c7dd8e971d0c4379b7f4b3f9644685ba/pytest_mock-3.14.1-py3-none-any.whl", hash = "sha256:178aefcd11307d874b4cd3100344e7e2d888d9791a6a1d9bfe90fbc1b74fd1d0", size = 9923, upload-time = "2025-05-26T13:58:43.487Z" }, ] [[package]] @@ -1138,7 +1155,7 @@ wheels = [ [[package]] name = "requests" -version = "2.32.3" +version = "2.32.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, @@ -1146,9 +1163,9 @@ dependencies = [ { name = "idna" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218, upload-time = "2024-05-29T15:37:49.536Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e1/0a/929373653770d8a0d7ea76c37de6e41f11eb07559b103b1c02cafb3f7cf8/requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422", size = 135258, upload-time = "2025-06-09T16:43:07.34Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928, upload-time = "2024-05-29T15:37:47.027Z" }, + { url = "https://files.pythonhosted.org/packages/7c/e4/56027c4a6b4ae70ca9de302488c5ca95ad4a39e190093d6c1a8ace08341b/requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", size = 64847, upload-time = "2025-06-09T16:43:05.728Z" }, ] [[package]] @@ -1165,27 +1182,27 @@ wheels = [ [[package]] name = "ruff" -version = "0.11.10" +version = "0.12.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e8/4c/4a3c5a97faaae6b428b336dcca81d03ad04779f8072c267ad2bd860126bf/ruff-0.11.10.tar.gz", hash = "sha256:d522fb204b4959909ecac47da02830daec102eeb100fb50ea9554818d47a5fa6", size = 4165632, upload-time = "2025-05-15T14:08:56.76Z" } +sdist = { url = "https://files.pythonhosted.org/packages/6c/3d/d9a195676f25d00dbfcf3cf95fdd4c685c497fcfa7e862a44ac5e4e96480/ruff-0.12.2.tar.gz", hash = "sha256:d7b4f55cd6f325cb7621244f19c873c565a08aff5a4ba9c69aa7355f3f7afd3e", size = 4432239, upload-time = "2025-07-03T16:40:19.566Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2f/9f/596c628f8824a2ce4cd12b0f0b4c0629a62dfffc5d0f742c19a1d71be108/ruff-0.11.10-py3-none-linux_armv6l.whl", hash = "sha256:859a7bfa7bc8888abbea31ef8a2b411714e6a80f0d173c2a82f9041ed6b50f58", size = 10316243, upload-time = "2025-05-15T14:08:12.884Z" }, - { url = "https://files.pythonhosted.org/packages/3c/38/c1e0b77ab58b426f8c332c1d1d3432d9fc9a9ea622806e208220cb133c9e/ruff-0.11.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:968220a57e09ea5e4fd48ed1c646419961a0570727c7e069842edd018ee8afed", size = 11083636, upload-time = "2025-05-15T14:08:16.551Z" }, - { url = "https://files.pythonhosted.org/packages/23/41/b75e15961d6047d7fe1b13886e56e8413be8467a4e1be0a07f3b303cd65a/ruff-0.11.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1067245bad978e7aa7b22f67113ecc6eb241dca0d9b696144256c3a879663bca", size = 10441624, upload-time = "2025-05-15T14:08:19.032Z" }, - { url = "https://files.pythonhosted.org/packages/b6/2c/e396b6703f131406db1811ea3d746f29d91b41bbd43ad572fea30da1435d/ruff-0.11.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4854fd09c7aed5b1590e996a81aeff0c9ff51378b084eb5a0b9cd9518e6cff2", size = 10624358, upload-time = "2025-05-15T14:08:21.542Z" }, - { url = "https://files.pythonhosted.org/packages/bd/8c/ee6cca8bdaf0f9a3704796022851a33cd37d1340bceaf4f6e991eb164e2e/ruff-0.11.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8b4564e9f99168c0f9195a0fd5fa5928004b33b377137f978055e40008a082c5", size = 10176850, upload-time = "2025-05-15T14:08:23.682Z" }, - { url = "https://files.pythonhosted.org/packages/e9/ce/4e27e131a434321b3b7c66512c3ee7505b446eb1c8a80777c023f7e876e6/ruff-0.11.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b6a9cc5b62c03cc1fea0044ed8576379dbaf751d5503d718c973d5418483641", size = 11759787, upload-time = "2025-05-15T14:08:25.733Z" }, - { url = "https://files.pythonhosted.org/packages/58/de/1e2e77fc72adc7cf5b5123fd04a59ed329651d3eab9825674a9e640b100b/ruff-0.11.10-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:607ecbb6f03e44c9e0a93aedacb17b4eb4f3563d00e8b474298a201622677947", size = 12430479, upload-time = "2025-05-15T14:08:28.013Z" }, - { url = "https://files.pythonhosted.org/packages/07/ed/af0f2340f33b70d50121628ef175523cc4c37619e98d98748c85764c8d88/ruff-0.11.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7b3a522fa389402cd2137df9ddefe848f727250535c70dafa840badffb56b7a4", size = 11919760, upload-time = "2025-05-15T14:08:30.956Z" }, - { url = "https://files.pythonhosted.org/packages/24/09/d7b3d3226d535cb89234390f418d10e00a157b6c4a06dfbe723e9322cb7d/ruff-0.11.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f071b0deed7e9245d5820dac235cbdd4ef99d7b12ff04c330a241ad3534319f", size = 14041747, upload-time = "2025-05-15T14:08:33.297Z" }, - { url = "https://files.pythonhosted.org/packages/62/b3/a63b4e91850e3f47f78795e6630ee9266cb6963de8f0191600289c2bb8f4/ruff-0.11.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a60e3a0a617eafba1f2e4186d827759d65348fa53708ca547e384db28406a0b", size = 11550657, upload-time = "2025-05-15T14:08:35.639Z" }, - { url = "https://files.pythonhosted.org/packages/46/63/a4f95c241d79402ccdbdb1d823d156c89fbb36ebfc4289dce092e6c0aa8f/ruff-0.11.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:da8ec977eaa4b7bf75470fb575bea2cb41a0e07c7ea9d5a0a97d13dbca697bf2", size = 10489671, upload-time = "2025-05-15T14:08:38.437Z" }, - { url = "https://files.pythonhosted.org/packages/6a/9b/c2238bfebf1e473495659c523d50b1685258b6345d5ab0b418ca3f010cd7/ruff-0.11.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ddf8967e08227d1bd95cc0851ef80d2ad9c7c0c5aab1eba31db49cf0a7b99523", size = 10160135, upload-time = "2025-05-15T14:08:41.247Z" }, - { url = "https://files.pythonhosted.org/packages/ba/ef/ba7251dd15206688dbfba7d413c0312e94df3b31b08f5d695580b755a899/ruff-0.11.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5a94acf798a82db188f6f36575d80609072b032105d114b0f98661e1679c9125", size = 11170179, upload-time = "2025-05-15T14:08:43.762Z" }, - { url = "https://files.pythonhosted.org/packages/73/9f/5c336717293203ba275dbfa2ea16e49b29a9fd9a0ea8b6febfc17e133577/ruff-0.11.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:3afead355f1d16d95630df28d4ba17fb2cb9c8dfac8d21ced14984121f639bad", size = 11626021, upload-time = "2025-05-15T14:08:46.451Z" }, - { url = "https://files.pythonhosted.org/packages/d9/2b/162fa86d2639076667c9aa59196c020dc6d7023ac8f342416c2f5ec4bda0/ruff-0.11.10-py3-none-win32.whl", hash = "sha256:dc061a98d32a97211af7e7f3fa1d4ca2fcf919fb96c28f39551f35fc55bdbc19", size = 10494958, upload-time = "2025-05-15T14:08:49.601Z" }, - { url = "https://files.pythonhosted.org/packages/24/f3/66643d8f32f50a4b0d09a4832b7d919145ee2b944d43e604fbd7c144d175/ruff-0.11.10-py3-none-win_amd64.whl", hash = "sha256:5cc725fbb4d25b0f185cb42df07ab6b76c4489b4bfb740a175f3a59c70e8a224", size = 11650285, upload-time = "2025-05-15T14:08:52.392Z" }, - { url = "https://files.pythonhosted.org/packages/95/3a/2e8704d19f376c799748ff9cb041225c1d59f3e7711bc5596c8cfdc24925/ruff-0.11.10-py3-none-win_arm64.whl", hash = "sha256:ef69637b35fb8b210743926778d0e45e1bffa850a7c61e428c6b971549b5f5d1", size = 10765278, upload-time = "2025-05-15T14:08:54.56Z" }, + { url = "https://files.pythonhosted.org/packages/74/b6/2098d0126d2d3318fd5bec3ad40d06c25d377d95749f7a0c5af17129b3b1/ruff-0.12.2-py3-none-linux_armv6l.whl", hash = "sha256:093ea2b221df1d2b8e7ad92fc6ffdca40a2cb10d8564477a987b44fd4008a7be", size = 10369761, upload-time = "2025-07-03T16:39:38.847Z" }, + { url = "https://files.pythonhosted.org/packages/b1/4b/5da0142033dbe155dc598cfb99262d8ee2449d76920ea92c4eeb9547c208/ruff-0.12.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:09e4cf27cc10f96b1708100fa851e0daf21767e9709e1649175355280e0d950e", size = 11155659, upload-time = "2025-07-03T16:39:42.294Z" }, + { url = "https://files.pythonhosted.org/packages/3e/21/967b82550a503d7c5c5c127d11c935344b35e8c521f52915fc858fb3e473/ruff-0.12.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:8ae64755b22f4ff85e9c52d1f82644abd0b6b6b6deedceb74bd71f35c24044cc", size = 10537769, upload-time = "2025-07-03T16:39:44.75Z" }, + { url = "https://files.pythonhosted.org/packages/33/91/00cff7102e2ec71a4890fb7ba1803f2cdb122d82787c7d7cf8041fe8cbc1/ruff-0.12.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3eb3a6b2db4d6e2c77e682f0b988d4d61aff06860158fdb413118ca133d57922", size = 10717602, upload-time = "2025-07-03T16:39:47.652Z" }, + { url = "https://files.pythonhosted.org/packages/9b/eb/928814daec4e1ba9115858adcda44a637fb9010618721937491e4e2283b8/ruff-0.12.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:73448de992d05517170fc37169cbca857dfeaeaa8c2b9be494d7bcb0d36c8f4b", size = 10198772, upload-time = "2025-07-03T16:39:49.641Z" }, + { url = "https://files.pythonhosted.org/packages/50/fa/f15089bc20c40f4f72334f9145dde55ab2b680e51afb3b55422effbf2fb6/ruff-0.12.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b8b94317cbc2ae4a2771af641739f933934b03555e51515e6e021c64441532d", size = 11845173, upload-time = "2025-07-03T16:39:52.069Z" }, + { url = "https://files.pythonhosted.org/packages/43/9f/1f6f98f39f2b9302acc161a4a2187b1e3a97634fe918a8e731e591841cf4/ruff-0.12.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:45fc42c3bf1d30d2008023a0a9a0cfb06bf9835b147f11fe0679f21ae86d34b1", size = 12553002, upload-time = "2025-07-03T16:39:54.551Z" }, + { url = "https://files.pythonhosted.org/packages/d8/70/08991ac46e38ddd231c8f4fd05ef189b1b94be8883e8c0c146a025c20a19/ruff-0.12.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce48f675c394c37e958bf229fb5c1e843e20945a6d962cf3ea20b7a107dcd9f4", size = 12171330, upload-time = "2025-07-03T16:39:57.55Z" }, + { url = "https://files.pythonhosted.org/packages/88/a9/5a55266fec474acfd0a1c73285f19dd22461d95a538f29bba02edd07a5d9/ruff-0.12.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:793d8859445ea47591272021a81391350205a4af65a9392401f418a95dfb75c9", size = 11774717, upload-time = "2025-07-03T16:39:59.78Z" }, + { url = "https://files.pythonhosted.org/packages/87/e5/0c270e458fc73c46c0d0f7cf970bb14786e5fdb88c87b5e423a4bd65232b/ruff-0.12.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6932323db80484dda89153da3d8e58164d01d6da86857c79f1961934354992da", size = 11646659, upload-time = "2025-07-03T16:40:01.934Z" }, + { url = "https://files.pythonhosted.org/packages/b7/b6/45ab96070c9752af37f0be364d849ed70e9ccede07675b0ec4e3ef76b63b/ruff-0.12.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6aa7e623a3a11538108f61e859ebf016c4f14a7e6e4eba1980190cacb57714ce", size = 10604012, upload-time = "2025-07-03T16:40:04.363Z" }, + { url = "https://files.pythonhosted.org/packages/86/91/26a6e6a424eb147cc7627eebae095cfa0b4b337a7c1c413c447c9ebb72fd/ruff-0.12.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:2a4a20aeed74671b2def096bdf2eac610c7d8ffcbf4fb0e627c06947a1d7078d", size = 10176799, upload-time = "2025-07-03T16:40:06.514Z" }, + { url = "https://files.pythonhosted.org/packages/f5/0c/9f344583465a61c8918a7cda604226e77b2c548daf8ef7c2bfccf2b37200/ruff-0.12.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:71a4c550195612f486c9d1f2b045a600aeba851b298c667807ae933478fcef04", size = 11241507, upload-time = "2025-07-03T16:40:08.708Z" }, + { url = "https://files.pythonhosted.org/packages/1c/b7/99c34ded8fb5f86c0280278fa89a0066c3760edc326e935ce0b1550d315d/ruff-0.12.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:4987b8f4ceadf597c927beee65a5eaf994c6e2b631df963f86d8ad1bdea99342", size = 11717609, upload-time = "2025-07-03T16:40:10.836Z" }, + { url = "https://files.pythonhosted.org/packages/51/de/8589fa724590faa057e5a6d171e7f2f6cffe3287406ef40e49c682c07d89/ruff-0.12.2-py3-none-win32.whl", hash = "sha256:369ffb69b70cd55b6c3fc453b9492d98aed98062db9fec828cdfd069555f5f1a", size = 10523823, upload-time = "2025-07-03T16:40:13.203Z" }, + { url = "https://files.pythonhosted.org/packages/94/47/8abf129102ae4c90cba0c2199a1a9b0fa896f6f806238d6f8c14448cc748/ruff-0.12.2-py3-none-win_amd64.whl", hash = "sha256:dca8a3b6d6dc9810ed8f328d406516bf4d660c00caeaef36eb831cf4871b0639", size = 11629831, upload-time = "2025-07-03T16:40:15.478Z" }, + { url = "https://files.pythonhosted.org/packages/e2/1f/72d2946e3cc7456bb837e88000eb3437e55f80db339c840c04015a11115d/ruff-0.12.2-py3-none-win_arm64.whl", hash = "sha256:48d6c6bfb4761df68bc05ae630e24f506755e702d4fb08f08460be778c7ccb12", size = 10735334, upload-time = "2025-07-03T16:40:17.677Z" }, ] [[package]] @@ -1265,11 +1282,11 @@ wheels = [ [[package]] name = "typing-extensions" -version = "4.13.2" +version = "4.14.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f6/37/23083fcd6e35492953e8d2aaaa68b860eb422b34627b13f2ce3eb6106061/typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef", size = 106967, upload-time = "2025-04-10T14:19:05.416Z" } +sdist = { url = "https://files.pythonhosted.org/packages/98/5a/da40306b885cc8c09109dc2e1abd358d5684b1425678151cdaed4731c822/typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36", size = 107673, upload-time = "2025-07-04T13:28:34.16Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806, upload-time = "2025-04-10T14:19:03.967Z" }, + { url = "https://files.pythonhosted.org/packages/b5/00/d631e67a838026495268c2f6884f3711a15a9a2a96cd244fdaea53b823fb/typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76", size = 43906, upload-time = "2025-07-04T13:28:32.743Z" }, ] [[package]] @@ -1287,14 +1304,14 @@ wheels = [ [[package]] name = "typing-inspection" -version = "0.4.0" +version = "0.4.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/82/5c/e6082df02e215b846b4b8c0b887a64d7d08ffaba30605502639d44c06b82/typing_inspection-0.4.0.tar.gz", hash = "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122", size = 76222, upload-time = "2025-02-25T17:27:59.638Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/b1/0c11f5058406b3af7609f121aaa6b609744687f1d158b3c3a5bf4cc94238/typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28", size = 75726, upload-time = "2025-05-21T18:55:23.885Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/31/08/aa4fdfb71f7de5176385bd9e90852eaf6b5d622735020ad600f2bab54385/typing_inspection-0.4.0-py3-none-any.whl", hash = "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f", size = 14125, upload-time = "2025-02-25T17:27:57.754Z" }, + { url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552, upload-time = "2025-05-21T18:55:22.152Z" }, ] [[package]] @@ -1308,11 +1325,11 @@ wheels = [ [[package]] name = "urllib3" -version = "2.4.0" +version = "2.5.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8a/78/16493d9c386d8e60e442a35feac5e00f0913c0f4b7c217c11e8ec2ff53e0/urllib3-2.4.0.tar.gz", hash = "sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466", size = 390672, upload-time = "2025-04-10T15:23:39.232Z" } +sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6b/11/cc635220681e93a0183390e26485430ca2c7b5f9d33b15c74c2861cb8091/urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813", size = 128680, upload-time = "2025-04-10T15:23:37.377Z" }, + { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" }, ] [[package]] diff --git a/libs/cli/examples/graphs/storm.py b/libs/cli/examples/graphs/storm.py index 184ed04ef..147f0fdac 100644 --- a/libs/cli/examples/graphs/storm.py +++ b/libs/cli/examples/graphs/storm.py @@ -285,7 +285,7 @@ class AnswerWithCitations(BaseModel): @property def as_str(self) -> str: return f"{self.answer}\n\nCitations:\n\n" + "\n".join( - f"[{i+1}]: {url}" for i, url in enumerate(self.cited_urls) + f"[{i + 1}]: {url}" for i, url in enumerate(self.cited_urls) ) @@ -553,7 +553,7 @@ async def conduct_interviews(state: ResearchState): def format_conversation(interview_state): messages = interview_state["messages"] convo = "\n".join(f"{m.name}: {m.content}" for m in messages) - return f'Conversation with {interview_state["editor"].name}\n\n' + convo + return f"Conversation with {interview_state['editor'].name}\n\n" + convo async def refine_outline(state: ResearchState): diff --git a/libs/cli/langgraph_cli/config.py b/libs/cli/langgraph_cli/config.py index ece457aad..cd0356350 100644 --- a/libs/cli/langgraph_cli/config.py +++ b/libs/cli/langgraph_cli/config.py @@ -602,8 +602,7 @@ def validate_config(config: Config) -> Config: if not config["graphs"]: raise click.UsageError( - "No graphs found in config. " - "Add at least one graph to 'graphs' dictionary." + "No graphs found in config. Add at least one graph to 'graphs' dictionary." ) # Validate image_distro config @@ -1181,7 +1180,7 @@ def python_config_to_docker( ) for reqpath, destpath in local_deps.pip_reqs ) - pip_reqs_str += f'{os.linesep}RUN {pip_install} {" ".join("-r " + r for _,r in local_deps.pip_reqs)}' + pip_reqs_str += f"{os.linesep}RUN {pip_install} {' '.join('-r ' + r for _, r in local_deps.pip_reqs)}" pip_reqs_str = f"""# -- Installing local requirements -- {pip_reqs_str} # -- End of local requirements install --""" diff --git a/libs/cli/langgraph_cli/templates.py b/libs/cli/langgraph_cli/templates.py index cd336e255..4ea915228 100644 --- a/libs/cli/langgraph_cli/templates.py +++ b/libs/cli/langgraph_cli/templates.py @@ -123,7 +123,7 @@ def _download_repo_with_requests(repo_url: str, path: str) -> None: ) except error.HTTPError as e: click.secho( - f"❌ Error: Failed to download repository.\n" f"Details: {e}\n", + f"❌ Error: Failed to download repository.\nDetails: {e}\n", fg="red", bold=True, err=True, diff --git a/libs/cli/tests/unit_tests/cli/test_cli.py b/libs/cli/tests/unit_tests/cli/test_cli.py index d07d6f7a8..268f44e00 100644 --- a/libs/cli/tests/unit_tests/cli/test_cli.py +++ b/libs/cli/tests/unit_tests/cli/test_cli.py @@ -280,9 +280,9 @@ def test_version_option() -> None: assert result.exit_code == 0, "Expected exit code 0 for --version option" # Check that the output contains the correct version information - assert ( - "LangGraph CLI, version" in result.output - ), "Expected version information in output" + assert "LangGraph CLI, version" in result.output, ( + "Expected version information in output" + ) def test_dockerfile_command_basic() -> None: @@ -570,6 +570,6 @@ def test_build_generate_proper_build_context(): build_context_pattern = re.compile(r"--build-context\s+(\w+)=([^\s]+)") build_contexts = re.findall(build_context_pattern, result.output) - assert ( - len(build_contexts) == 2 - ), f"Expected 2 build contexts, but found {len(build_contexts)}" + assert len(build_contexts) == 2, ( + f"Expected 2 build contexts, but found {len(build_contexts)}" + ) diff --git a/libs/cli/tests/unit_tests/cli/test_templates.py b/libs/cli/tests/unit_tests/cli/test_templates.py index acd7651d0..cbdf4bbe1 100644 --- a/libs/cli/tests/unit_tests/cli/test_templates.py +++ b/libs/cli/tests/unit_tests/cli/test_templates.py @@ -42,18 +42,18 @@ def test_create_new_with_mocked_download(mock_urlopen: MagicMock) -> None: # Verify CLI command execution and success assert result.exit_code == 0, result.output - assert ( - "New project created" in result.output - ), "Expected success message in output." + assert "New project created" in result.output, ( + "Expected success message in output." + ) # Verify that the directory is not empty assert os.listdir(temp_dir), "Expected files to be created in temp directory." # Check for a known file in the extracted content extracted_files = [f.name for f in Path(temp_dir).glob("*")] - assert ( - "test-file.txt" in extracted_files - ), "Expected 'test-file.txt' in the extracted content." + assert "test-file.txt" in extracted_files, ( + "Expected 'test-file.txt' in the extracted content." + ) def test_invalid_template_id() -> None: @@ -65,6 +65,6 @@ def test_invalid_template_id() -> None: # Verify the command failed and proper message is displayed assert result.exit_code != 0, "Expected non-zero exit code for invalid template." - assert ( - "Template 'invalid-template-id' not found" in result.output - ), "Expected error message in output." + assert "Template 'invalid-template-id' not found" in result.output, ( + "Expected error message in output." + ) diff --git a/libs/cli/uv.lock b/libs/cli/uv.lock index 839e68015..a6a0d0270 100644 --- a/libs/cli/uv.lock +++ b/libs/cli/uv.lock @@ -2,10 +2,9 @@ version = 1 revision = 2 requires-python = ">=3.9" resolution-markers = [ - "python_full_version >= '3.12.4' and python_full_version < '4.0'", - "python_full_version >= '3.11' and python_full_version < '3.12.4'", - "python_full_version >= '4.0'", - "python_full_version < '3.11'", + "python_full_version >= '3.11'", + "python_full_version == '3.10.*'", + "python_full_version < '3.10'", ] [[package]] @@ -45,11 +44,11 @@ wheels = [ [[package]] name = "certifi" -version = "2025.4.26" +version = "2025.6.15" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e8/9e/c05b3920a3b7d20d3d3310465f50348e5b3694f4f88c6daf736eef3024c4/certifi-2025.4.26.tar.gz", hash = "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6", size = 160705, upload-time = "2025-04-26T02:12:29.51Z" } +sdist = { url = "https://files.pythonhosted.org/packages/73/f7/f14b46d4bcd21092d7d3ccef689615220d8a08fb25e564b65d20738e672e/certifi-2025.6.15.tar.gz", hash = "sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b", size = 158753, upload-time = "2025-06-15T02:45:51.329Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4a/7e/3db2bd1b1f9e95f7cddca6d6e75e2f2bd9f51b1246e546d88addca0106bd/certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3", size = 159618, upload-time = "2025-04-26T02:12:27.662Z" }, + { url = "https://files.pythonhosted.org/packages/84/ae/320161bd181fc06471eed047ecce67b693fd7515b16d495d8932db763426/certifi-2025.6.15-py3-none-any.whl", hash = "sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057", size = 157650, upload-time = "2025-06-15T02:45:49.977Z" }, ] [[package]] @@ -199,14 +198,33 @@ wheels = [ name = "click" version = "8.1.8" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.10'", +] dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "colorama", marker = "python_full_version < '3.10' and sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593, upload-time = "2024-12-21T18:38:44.339Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188, upload-time = "2024-12-21T18:38:41.666Z" }, ] +[[package]] +name = "click" +version = "8.2.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.11'", + "python_full_version == '3.10.*'", +] +dependencies = [ + { name = "colorama", marker = "python_full_version >= '3.10' and sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/60/6c/8ca2efa64cf75a977a0d7fac081354553ebe483345c734fb6b6515d96bbc/click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202", size = 286342, upload-time = "2025-05-20T23:19:49.832Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/85/32/10bb5764d90a8eee674e9dc6f4db6a0ab47c8c4d0d83c27f7c39ac415a4d/click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b", size = 102215, upload-time = "2025-05-20T23:19:47.796Z" }, +] + [[package]] name = "cloudpickle" version = "3.1.1" @@ -289,11 +307,14 @@ sdist = { url = "https://files.pythonhosted.org/packages/a2/55/8f8cab2afd404cf57 [[package]] name = "exceptiongroup" -version = "1.2.2" +version = "1.3.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/09/35/2495c4ac46b980e4ca1f6ad6db102322ef3ad2410b79fdde159a4b0f3b92/exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc", size = 28883, upload-time = "2024-07-12T22:26:00.161Z" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/02/cc/b7e31358aac6ed1ef2bb790a9746ac2c69bcb3c8588b41616914eb106eaf/exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b", size = 16453, upload-time = "2024-07-12T22:25:58.476Z" }, + { url = "https://files.pythonhosted.org/packages/36/f4/c6e662dade71f56cd2f3735141b265c3c79293c109549c1e6933b0651ffc/exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10", size = 16674, upload-time = "2025-05-10T17:42:49.33Z" }, ] [[package]] @@ -423,7 +444,7 @@ wheels = [ [[package]] name = "langchain-core" -version = "0.3.66" +version = "0.3.68" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jsonpatch", marker = "python_full_version >= '3.11'" }, @@ -434,31 +455,31 @@ dependencies = [ { name = "tenacity", marker = "python_full_version >= '3.11'" }, { name = "typing-extensions", marker = "python_full_version >= '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f0/63/470aa84393bad5d51749417af58522a691174f8b2d05843f5633d473faa0/langchain_core-0.3.66.tar.gz", hash = "sha256:350c92e792ec1401f4b740d759b95f297710a50de29e1be9fbfff8676ef62117", size = 560102, upload-time = "2025-06-20T22:08:19.532Z" } +sdist = { url = "https://files.pythonhosted.org/packages/23/20/f5b18a17bfbe3416177e702ab2fd230b7d168abb17be31fb48f43f0bb772/langchain_core-0.3.68.tar.gz", hash = "sha256:312e1932ac9aa2eaf111b70fdc171776fa571d1a86c1f873dcac88a094b19c6f", size = 563041, upload-time = "2025-07-03T17:02:28.704Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c0/c3/8080431fd7567a340d3a42e36c0bb3970a8d00d5e27bf3ca2103b3b55996/langchain_core-0.3.66-py3-none-any.whl", hash = "sha256:65cd6c3659afa4f91de7aa681397a0c53ff9282425c281e53646dd7faf16099e", size = 438874, upload-time = "2025-06-20T22:08:17.52Z" }, + { url = "https://files.pythonhosted.org/packages/f9/da/c89be0a272993bfcb762b2a356b9f55de507784c2755ad63caec25d183bf/langchain_core-0.3.68-py3-none-any.whl", hash = "sha256:5e5c1fbef419590537c91b8c2d86af896fbcbaf0d5ed7fdcdd77f7d8f3467ba0", size = 441405, upload-time = "2025-07-03T17:02:27.115Z" }, ] [[package]] name = "langgraph" -version = "0.4.3" +version = "0.5.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "langchain-core", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, + { name = "langchain-core", marker = "python_full_version >= '3.11'" }, { name = "langgraph-checkpoint", marker = "python_full_version >= '3.11'" }, - { name = "langgraph-prebuilt", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, - { name = "langgraph-sdk", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, + { name = "langgraph-prebuilt", marker = "python_full_version >= '3.11'" }, + { name = "langgraph-sdk", marker = "python_full_version >= '3.11'" }, { name = "pydantic", marker = "python_full_version >= '3.11'" }, { name = "xxhash", marker = "python_full_version >= '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/60/9e/5a64602eff18a99d0216a80eff823051ffbdb7c11b5a16171cee8b1ccce5/langgraph-0.4.3.tar.gz", hash = "sha256:272d5d5903f2c2882dbeeba849846a0f2500bd83fb3734a3801ebe64c1a60bdd", size = 125407, upload-time = "2025-05-08T03:40:02.882Z" } +sdist = { url = "https://files.pythonhosted.org/packages/72/db/864d8e6c6e921f27b357980d0cfca847366238c1bb8a6bffd766f651004e/langgraph-0.5.1.tar.gz", hash = "sha256:312d341979e38034dde60e08df53505b8a196619df1266d6eacf6b002a0a65a8", size = 437339, upload-time = "2025-07-02T21:15:56.581Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/35/53/0a20edd9f41eb3707722444ec1b43752b792bbe904d1c8cc3ba27f8eb2c8/langgraph-0.4.3-py3-none-any.whl", hash = "sha256:dec926e034f4d440b92a3c52139cb6e9763bc1791e79a6ea53a233309cec864f", size = 151191, upload-time = "2025-05-08T03:40:01.07Z" }, + { url = "https://files.pythonhosted.org/packages/4d/fa/69e83057b7a6062c0785deccdd22610003611c16cac7b4218b4b87c4924a/langgraph-0.5.1-py3-none-any.whl", hash = "sha256:707f0cc0d2713011fff4578bf57de8226cd96bcc0679868be2f41eb0984bb5af", size = 143695, upload-time = "2025-07-02T21:15:55.148Z" }, ] [[package]] name = "langgraph-api" -version = "0.2.67" +version = "0.2.78" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cloudpickle", marker = "python_full_version >= '3.11'" }, @@ -481,22 +502,22 @@ dependencies = [ { name = "uvicorn", marker = "python_full_version >= '3.11'" }, { name = "watchfiles", marker = "python_full_version >= '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a2/36/a1ef1b9cc71450068708ebf6fc0fa5342c3e3129f37932f195b2a1c7814b/langgraph_api-0.2.67.tar.gz", hash = "sha256:68f2237fd4612d6d0e750824170a4ed9a9566b610ca2d6a605fb136bab32d908", size = 228371, upload-time = "2025-06-26T01:53:44.07Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ba/88/1aa91bede22d1393a53605ff13a57d6cb3ce2831eb250a8a8f814c548d2e/langgraph_api-0.2.78.tar.gz", hash = "sha256:37aad4fe764934f358dbb26d50b4acbf4180aac673499d1502b5b468cc7acba4", size = 233581, upload-time = "2025-07-02T19:11:01.154Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cc/b1/69e2366b16daeec87954e04e04e478308be5dde5d54cc79d0e125c4accb4/langgraph_api-0.2.67-py3-none-any.whl", hash = "sha256:0e06e6df6152e8fb3a98ca512c7c73927d688e841fe1000df6a3badc42d9b268", size = 183672, upload-time = "2025-06-26T01:53:42.794Z" }, + { url = "https://files.pythonhosted.org/packages/7e/76/46626d99c36fce0c1ee1e1581f54b29acbed5e9f2e7cf9a198c825547d91/langgraph_api-0.2.78-py3-none-any.whl", hash = "sha256:57abe7fff9763d6f4eaf4419d103f75e77dca6d271db3816777c04bd67db4449", size = 190222, upload-time = "2025-07-02T19:10:59.793Z" }, ] [[package]] name = "langgraph-checkpoint" -version = "2.0.25" +version = "2.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "langchain-core", marker = "python_full_version >= '3.11'" }, { name = "ormsgpack", marker = "python_full_version >= '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c5/72/d49828e6929cb3ded1472aa3e5e4a369d292c4f21021ac683d28fbc8f4f8/langgraph_checkpoint-2.0.25.tar.gz", hash = "sha256:77a63cab7b5f84dec1d49db561326ec28bdd48bcefb7fe4ac372069d2609287b", size = 36952, upload-time = "2025-04-26T21:00:43.5Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/30/c04abcb2ac30f200dbfde5839ca3832552fe2bd852d9e85a68e47418a11c/langgraph_checkpoint-2.1.0.tar.gz", hash = "sha256:cdaa2f0b49aa130ab185c02d82f02b40299a1fbc9ac59ac20cecce09642a1abe", size = 135501, upload-time = "2025-06-16T22:05:01.918Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/12/52/bceb5b5348c7a60ef0625ab0a0a0a9ff5d78f0e12aed8cc55c49d5e8a8c9/langgraph_checkpoint-2.0.25-py3-none-any.whl", hash = "sha256:23416a0f5bc9dd712ac10918fc13e8c9c4530c419d2985a441df71a38fc81602", size = 42312, upload-time = "2025-04-26T21:00:42.242Z" }, + { url = "https://files.pythonhosted.org/packages/0f/41/390a97d9d0abe5b71eea2f6fb618d8adadefa674e97f837bae6cda670bc7/langgraph_checkpoint-2.1.0-py3-none-any.whl", hash = "sha256:4cea3e512081da1241396a519cbfe4c5d92836545e2c64e85b6f5c34a1b8bc61", size = 43844, upload-time = "2025-06-16T22:05:00.758Z" }, ] [[package]] @@ -504,7 +525,8 @@ name = "langgraph-cli" version = "0.3.3" source = { editable = "." } dependencies = [ - { name = "click" }, + { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "click", version = "8.2.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "langgraph-sdk", marker = "python_full_version >= '3.11'" }, ] @@ -551,20 +573,20 @@ dev = [ [[package]] name = "langgraph-prebuilt" -version = "0.1.8" +version = "0.5.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "langchain-core", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, - { name = "langgraph-checkpoint", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, + { name = "langchain-core", marker = "python_full_version >= '3.11'" }, + { name = "langgraph-checkpoint", marker = "python_full_version >= '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/57/30/f31f0e076c37d097b53e4cff5d479a3686e1991f6c86a1a4727d5d1f5489/langgraph_prebuilt-0.1.8.tar.gz", hash = "sha256:4de7659151829b2b955b6798df6800e580e617782c15c2c5b29b139697491831", size = 24543, upload-time = "2025-04-03T16:04:19.932Z" } +sdist = { url = "https://files.pythonhosted.org/packages/bb/11/98134c47832fbde0caf0e06f1a104577da9215c358d7854093c1d835b272/langgraph_prebuilt-0.5.2.tar.gz", hash = "sha256:2c900a5be0d6a93ea2521e0d931697cad2b646f1fcda7aa5c39d8d7539772465", size = 117808, upload-time = "2025-06-30T19:52:48.307Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/36/72/9e092665502f8f52f2708065ed14fbbba3f95d1a1b65d62049b0c5fcdf00/langgraph_prebuilt-0.1.8-py3-none-any.whl", hash = "sha256:ae97b828ae00be2cefec503423aa782e1bff165e9b94592e224da132f2526968", size = 25903, upload-time = "2025-04-03T16:04:18.993Z" }, + { url = "https://files.pythonhosted.org/packages/c3/64/6bc45ab9e0e1112698ebff579fe21f5606ea65cd08266995a357e312a4d2/langgraph_prebuilt-0.5.2-py3-none-any.whl", hash = "sha256:1f4cd55deca49dffc3e5127eec12fcd244fc381321002f728afa88642d5ec59d", size = 23776, upload-time = "2025-06-30T19:52:47.494Z" }, ] [[package]] name = "langgraph-runtime-inmem" -version = "0.3.3" +version = "0.3.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "blockbuster", marker = "python_full_version >= '3.11'" }, @@ -574,27 +596,27 @@ dependencies = [ { name = "starlette", marker = "python_full_version >= '3.11'" }, { name = "structlog", marker = "python_full_version >= '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a8/c6/c6c515df38179517a187b11cc9506caac9bc7c25ab0adc1e21b463e338fd/langgraph_runtime_inmem-0.3.3.tar.gz", hash = "sha256:1b5bc8b05989f48c64c826d826e576a6e77f42349eca3382f38f8ed1d1f026e4", size = 77443, upload-time = "2025-06-24T19:50:36.235Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c1/17/7ff669ff44a53ab342903c2996fff75a77494af9fe56abcfbca64fe2342b/langgraph_runtime_inmem-0.3.4.tar.gz", hash = "sha256:eda7828f3ea07126e5265024b74a3fa9bf611633ad83ba3296ab9f51d89b7c0c", size = 77424, upload-time = "2025-07-01T14:45:07.465Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/36/87/1b47cf8a9a9ab8e6460203921e05f59e1e95dc0636e64a7429cd0e579a79/langgraph_runtime_inmem-0.3.3-py3-none-any.whl", hash = "sha256:ed485d520870a96a4a2e81188f2dbf993e7b96c5c65804bcdfdcb39df71be3ce", size = 29146, upload-time = "2025-06-24T19:50:35.083Z" }, + { url = "https://files.pythonhosted.org/packages/95/0e/39c13ca7229a9425a0e5744a1d3817f80d38dd5ca7703494fb9cf836ba45/langgraph_runtime_inmem-0.3.4-py3-none-any.whl", hash = "sha256:dcb9ac68ac90b3fb1ddaf666d14a367ab70e69d5bb5589b77a72c318e29104ae", size = 29139, upload-time = "2025-07-01T14:45:06.472Z" }, ] [[package]] name = "langgraph-sdk" -version = "0.1.66" +version = "0.1.72" 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/97/7a/5fede018d8b9100db14211cfdb94aefd0e5f2e9ae738072f3d4cc443465b/langgraph_sdk-0.1.66.tar.gz", hash = "sha256:81474ad4555a06004cc7a2f4ab477135d5eaf7db11fbcf2a69257fb2d717582e", size = 44049, upload-time = "2025-04-30T22:59:09.085Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c0/a6/cf13ace9bc7f0e8b13852ced0b37ece97f3140e232821c28bc852f8c1ea2/langgraph_sdk-0.1.72.tar.gz", hash = "sha256:396d8195881830700e2d54a0a9ee273e8b1173428e667502ef9c182a3cec7ab7", size = 71600, upload-time = "2025-06-27T01:12:03.788Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/97/06/87ce0b8043ba5a4ec8369a243f3140f8fd9d9b7aab1d8a9351711739beea/langgraph_sdk-0.1.66-py3-none-any.whl", hash = "sha256:f781c63f3e913d3d6bedb02cb84d775cda64e3cdf3282fd387bdd8faaf53c603", size = 47584, upload-time = "2025-04-30T22:59:07.953Z" }, + { url = "https://files.pythonhosted.org/packages/4b/4b/d56b51da08d168c2315cd092faa47bc83388b116756dbd6995026ec9ba3f/langgraph_sdk-0.1.72-py3-none-any.whl", hash = "sha256:925d3fcc7a26361db04f9c4beb3ec05bc36361b2a836d181ff2ab145071ec3ce", size = 50129, upload-time = "2025-06-27T01:12:02.449Z" }, ] [[package]] name = "langsmith" -version = "0.4.2" +version = "0.4.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx", marker = "python_full_version >= '3.11'" }, @@ -605,9 +627,9 @@ dependencies = [ { name = "requests-toolbelt", marker = "python_full_version >= '3.11'" }, { name = "zstandard", marker = "python_full_version >= '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8a/b6/0ebc396baf6b69aeb9eb466bbeaccd504c901615e744b0ecf33b0d39a8a5/langsmith-0.4.2.tar.gz", hash = "sha256:51df086a9ae17ffa16538f52ef3bb8b3d85b0e52c84958980553cb6cadd9e565", size = 352208, upload-time = "2025-06-25T11:29:00.408Z" } +sdist = { url = "https://files.pythonhosted.org/packages/20/c8/8d2e0fc438d2d3d8d4300f7684ea30a754344ed00d7ba9cc2705241d2a5f/langsmith-0.4.4.tar.gz", hash = "sha256:70c53bbff24a7872e88e6fa0af98270f4986a6e364f9e85db1cc5636defa4d66", size = 352105, upload-time = "2025-06-27T19:20:36.207Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/58/06/fdcc2e8de8934595e7fd7b3f7c93065ff25c03ddeda566823882379b66b2/langsmith-0.4.2-py3-none-any.whl", hash = "sha256:2b1a3f889e134546dc5d67e23e5e8c6be5f91fd86827276ac874e3a25a04498a", size = 367715, upload-time = "2025-06-25T11:28:58.124Z" }, + { url = "https://files.pythonhosted.org/packages/1d/33/a3337eb70d795495a299a1640d7a75f17fb917155a64309b96106e7b9452/langsmith-0.4.4-py3-none-any.whl", hash = "sha256:014c68329bd085bd6c770a6405c61bb6881f82eb554ce8c4d1984b0035fd1716", size = 367687, upload-time = "2025-06-27T19:20:33.839Z" }, ] [[package]] @@ -655,46 +677,47 @@ wheels = [ [[package]] name = "mypy" -version = "1.15.0" +version = "1.16.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "mypy-extensions" }, + { name = "pathspec" }, { name = "tomli", marker = "python_full_version < '3.11'" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ce/43/d5e49a86afa64bd3839ea0d5b9c7103487007d728e1293f52525d6d5486a/mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43", size = 3239717, upload-time = "2025-02-05T03:50:34.655Z" } +sdist = { url = "https://files.pythonhosted.org/packages/81/69/92c7fa98112e4d9eb075a239caa4ef4649ad7d441545ccffbd5e34607cbb/mypy-1.16.1.tar.gz", hash = "sha256:6bd00a0a2094841c5e47e7374bb42b83d64c527a502e3334e1173a0c24437bab", size = 3324747, upload-time = "2025-06-16T16:51:35.145Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/68/f8/65a7ce8d0e09b6329ad0c8d40330d100ea343bd4dd04c4f8ae26462d0a17/mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13", size = 10738433, upload-time = "2025-02-05T03:49:29.145Z" }, - { url = "https://files.pythonhosted.org/packages/b4/95/9c0ecb8eacfe048583706249439ff52105b3f552ea9c4024166c03224270/mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559", size = 9861472, upload-time = "2025-02-05T03:49:16.986Z" }, - { url = "https://files.pythonhosted.org/packages/84/09/9ec95e982e282e20c0d5407bc65031dfd0f0f8ecc66b69538296e06fcbee/mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b", size = 11611424, upload-time = "2025-02-05T03:49:46.908Z" }, - { url = "https://files.pythonhosted.org/packages/78/13/f7d14e55865036a1e6a0a69580c240f43bc1f37407fe9235c0d4ef25ffb0/mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3", size = 12365450, upload-time = "2025-02-05T03:50:05.89Z" }, - { url = "https://files.pythonhosted.org/packages/48/e1/301a73852d40c241e915ac6d7bcd7fedd47d519246db2d7b86b9d7e7a0cb/mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b", size = 12551765, upload-time = "2025-02-05T03:49:33.56Z" }, - { url = "https://files.pythonhosted.org/packages/77/ba/c37bc323ae5fe7f3f15a28e06ab012cd0b7552886118943e90b15af31195/mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828", size = 9274701, upload-time = "2025-02-05T03:49:38.981Z" }, - { url = "https://files.pythonhosted.org/packages/03/bc/f6339726c627bd7ca1ce0fa56c9ae2d0144604a319e0e339bdadafbbb599/mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f", size = 10662338, upload-time = "2025-02-05T03:50:17.287Z" }, - { url = "https://files.pythonhosted.org/packages/e2/90/8dcf506ca1a09b0d17555cc00cd69aee402c203911410136cd716559efe7/mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5", size = 9787540, upload-time = "2025-02-05T03:49:51.21Z" }, - { url = "https://files.pythonhosted.org/packages/05/05/a10f9479681e5da09ef2f9426f650d7b550d4bafbef683b69aad1ba87457/mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e", size = 11538051, upload-time = "2025-02-05T03:50:20.885Z" }, - { url = "https://files.pythonhosted.org/packages/e9/9a/1f7d18b30edd57441a6411fcbc0c6869448d1a4bacbaee60656ac0fc29c8/mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c", size = 12286751, upload-time = "2025-02-05T03:49:42.408Z" }, - { url = "https://files.pythonhosted.org/packages/72/af/19ff499b6f1dafcaf56f9881f7a965ac2f474f69f6f618b5175b044299f5/mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f", size = 12421783, upload-time = "2025-02-05T03:49:07.707Z" }, - { url = "https://files.pythonhosted.org/packages/96/39/11b57431a1f686c1aed54bf794870efe0f6aeca11aca281a0bd87a5ad42c/mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f", size = 9265618, upload-time = "2025-02-05T03:49:54.581Z" }, - { url = "https://files.pythonhosted.org/packages/98/3a/03c74331c5eb8bd025734e04c9840532226775c47a2c39b56a0c8d4f128d/mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd", size = 10793981, upload-time = "2025-02-05T03:50:28.25Z" }, - { url = "https://files.pythonhosted.org/packages/f0/1a/41759b18f2cfd568848a37c89030aeb03534411eef981df621d8fad08a1d/mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f", size = 9749175, upload-time = "2025-02-05T03:50:13.411Z" }, - { url = "https://files.pythonhosted.org/packages/12/7e/873481abf1ef112c582db832740f4c11b2bfa510e829d6da29b0ab8c3f9c/mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464", size = 11455675, upload-time = "2025-02-05T03:50:31.421Z" }, - { url = "https://files.pythonhosted.org/packages/b3/d0/92ae4cde706923a2d3f2d6c39629134063ff64b9dedca9c1388363da072d/mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee", size = 12410020, upload-time = "2025-02-05T03:48:48.705Z" }, - { url = "https://files.pythonhosted.org/packages/46/8b/df49974b337cce35f828ba6fda228152d6db45fed4c86ba56ffe442434fd/mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e", size = 12498582, upload-time = "2025-02-05T03:49:03.628Z" }, - { url = "https://files.pythonhosted.org/packages/13/50/da5203fcf6c53044a0b699939f31075c45ae8a4cadf538a9069b165c1050/mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22", size = 9366614, upload-time = "2025-02-05T03:50:00.313Z" }, - { url = "https://files.pythonhosted.org/packages/6a/9b/fd2e05d6ffff24d912f150b87db9e364fa8282045c875654ce7e32fffa66/mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445", size = 10788592, upload-time = "2025-02-05T03:48:55.789Z" }, - { url = "https://files.pythonhosted.org/packages/74/37/b246d711c28a03ead1fd906bbc7106659aed7c089d55fe40dd58db812628/mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d", size = 9753611, upload-time = "2025-02-05T03:48:44.581Z" }, - { url = "https://files.pythonhosted.org/packages/a6/ac/395808a92e10cfdac8003c3de9a2ab6dc7cde6c0d2a4df3df1b815ffd067/mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5", size = 11438443, upload-time = "2025-02-05T03:49:25.514Z" }, - { url = "https://files.pythonhosted.org/packages/d2/8b/801aa06445d2de3895f59e476f38f3f8d610ef5d6908245f07d002676cbf/mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036", size = 12402541, upload-time = "2025-02-05T03:49:57.623Z" }, - { url = "https://files.pythonhosted.org/packages/c7/67/5a4268782eb77344cc613a4cf23540928e41f018a9a1ec4c6882baf20ab8/mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357", size = 12494348, upload-time = "2025-02-05T03:48:52.361Z" }, - { url = "https://files.pythonhosted.org/packages/83/3e/57bb447f7bbbfaabf1712d96f9df142624a386d98fb026a761532526057e/mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf", size = 9373648, upload-time = "2025-02-05T03:49:11.395Z" }, - { url = "https://files.pythonhosted.org/packages/5a/fa/79cf41a55b682794abe71372151dbbf856e3008f6767057229e6649d294a/mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078", size = 10737129, upload-time = "2025-02-05T03:50:24.509Z" }, - { url = "https://files.pythonhosted.org/packages/d3/33/dd8feb2597d648de29e3da0a8bf4e1afbda472964d2a4a0052203a6f3594/mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba", size = 9856335, upload-time = "2025-02-05T03:49:36.398Z" }, - { url = "https://files.pythonhosted.org/packages/e4/b5/74508959c1b06b96674b364ffeb7ae5802646b32929b7701fc6b18447592/mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5", size = 11611935, upload-time = "2025-02-05T03:49:14.154Z" }, - { url = "https://files.pythonhosted.org/packages/6c/53/da61b9d9973efcd6507183fdad96606996191657fe79701b2c818714d573/mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b", size = 12365827, upload-time = "2025-02-05T03:48:59.458Z" }, - { url = "https://files.pythonhosted.org/packages/c1/72/965bd9ee89540c79a25778cc080c7e6ef40aa1eeac4d52cec7eae6eb5228/mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2", size = 12541924, upload-time = "2025-02-05T03:50:03.12Z" }, - { url = "https://files.pythonhosted.org/packages/46/d0/f41645c2eb263e6c77ada7d76f894c580c9ddb20d77f0c24d34273a4dab2/mypy-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980", size = 9271176, upload-time = "2025-02-05T03:50:10.86Z" }, - { url = "https://files.pythonhosted.org/packages/09/4e/a7d65c7322c510de2c409ff3828b03354a7c43f5a8ed458a7a131b41c7b9/mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e", size = 2221777, upload-time = "2025-02-05T03:50:08.348Z" }, + { url = "https://files.pythonhosted.org/packages/8e/12/2bf23a80fcef5edb75de9a1e295d778e0f46ea89eb8b115818b663eff42b/mypy-1.16.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b4f0fed1022a63c6fec38f28b7fc77fca47fd490445c69d0a66266c59dd0b88a", size = 10958644, upload-time = "2025-06-16T16:51:11.649Z" }, + { url = "https://files.pythonhosted.org/packages/08/50/bfe47b3b278eacf348291742fd5e6613bbc4b3434b72ce9361896417cfe5/mypy-1.16.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:86042bbf9f5a05ea000d3203cf87aa9d0ccf9a01f73f71c58979eb9249f46d72", size = 10087033, upload-time = "2025-06-16T16:35:30.089Z" }, + { url = "https://files.pythonhosted.org/packages/21/de/40307c12fe25675a0776aaa2cdd2879cf30d99eec91b898de00228dc3ab5/mypy-1.16.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ea7469ee5902c95542bea7ee545f7006508c65c8c54b06dc2c92676ce526f3ea", size = 11875645, upload-time = "2025-06-16T16:35:48.49Z" }, + { url = "https://files.pythonhosted.org/packages/a6/d8/85bdb59e4a98b7a31495bd8f1a4445d8ffc86cde4ab1f8c11d247c11aedc/mypy-1.16.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:352025753ef6a83cb9e7f2427319bb7875d1fdda8439d1e23de12ab164179574", size = 12616986, upload-time = "2025-06-16T16:48:39.526Z" }, + { url = "https://files.pythonhosted.org/packages/0e/d0/bb25731158fa8f8ee9e068d3e94fcceb4971fedf1424248496292512afe9/mypy-1.16.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ff9fa5b16e4c1364eb89a4d16bcda9987f05d39604e1e6c35378a2987c1aac2d", size = 12878632, upload-time = "2025-06-16T16:36:08.195Z" }, + { url = "https://files.pythonhosted.org/packages/2d/11/822a9beb7a2b825c0cb06132ca0a5183f8327a5e23ef89717c9474ba0bc6/mypy-1.16.1-cp310-cp310-win_amd64.whl", hash = "sha256:1256688e284632382f8f3b9e2123df7d279f603c561f099758e66dd6ed4e8bd6", size = 9484391, upload-time = "2025-06-16T16:37:56.151Z" }, + { url = "https://files.pythonhosted.org/packages/9a/61/ec1245aa1c325cb7a6c0f8570a2eee3bfc40fa90d19b1267f8e50b5c8645/mypy-1.16.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:472e4e4c100062488ec643f6162dd0d5208e33e2f34544e1fc931372e806c0cc", size = 10890557, upload-time = "2025-06-16T16:37:21.421Z" }, + { url = "https://files.pythonhosted.org/packages/6b/bb/6eccc0ba0aa0c7a87df24e73f0ad34170514abd8162eb0c75fd7128171fb/mypy-1.16.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea16e2a7d2714277e349e24d19a782a663a34ed60864006e8585db08f8ad1782", size = 10012921, upload-time = "2025-06-16T16:51:28.659Z" }, + { url = "https://files.pythonhosted.org/packages/5f/80/b337a12e2006715f99f529e732c5f6a8c143bb58c92bb142d5ab380963a5/mypy-1.16.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:08e850ea22adc4d8a4014651575567b0318ede51e8e9fe7a68f25391af699507", size = 11802887, upload-time = "2025-06-16T16:50:53.627Z" }, + { url = "https://files.pythonhosted.org/packages/d9/59/f7af072d09793d581a745a25737c7c0a945760036b16aeb620f658a017af/mypy-1.16.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22d76a63a42619bfb90122889b903519149879ddbf2ba4251834727944c8baca", size = 12531658, upload-time = "2025-06-16T16:33:55.002Z" }, + { url = "https://files.pythonhosted.org/packages/82/c4/607672f2d6c0254b94a646cfc45ad589dd71b04aa1f3d642b840f7cce06c/mypy-1.16.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2c7ce0662b6b9dc8f4ed86eb7a5d505ee3298c04b40ec13b30e572c0e5ae17c4", size = 12732486, upload-time = "2025-06-16T16:37:03.301Z" }, + { url = "https://files.pythonhosted.org/packages/b6/5e/136555ec1d80df877a707cebf9081bd3a9f397dedc1ab9750518d87489ec/mypy-1.16.1-cp311-cp311-win_amd64.whl", hash = "sha256:211287e98e05352a2e1d4e8759c5490925a7c784ddc84207f4714822f8cf99b6", size = 9479482, upload-time = "2025-06-16T16:47:37.48Z" }, + { url = "https://files.pythonhosted.org/packages/b4/d6/39482e5fcc724c15bf6280ff5806548c7185e0c090712a3736ed4d07e8b7/mypy-1.16.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:af4792433f09575d9eeca5c63d7d90ca4aeceda9d8355e136f80f8967639183d", size = 11066493, upload-time = "2025-06-16T16:47:01.683Z" }, + { url = "https://files.pythonhosted.org/packages/e6/e5/26c347890efc6b757f4d5bb83f4a0cf5958b8cf49c938ac99b8b72b420a6/mypy-1.16.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:66df38405fd8466ce3517eda1f6640611a0b8e70895e2a9462d1d4323c5eb4b9", size = 10081687, upload-time = "2025-06-16T16:48:19.367Z" }, + { url = "https://files.pythonhosted.org/packages/44/c7/b5cb264c97b86914487d6a24bd8688c0172e37ec0f43e93b9691cae9468b/mypy-1.16.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44e7acddb3c48bd2713994d098729494117803616e116032af192871aed80b79", size = 11839723, upload-time = "2025-06-16T16:49:20.912Z" }, + { url = "https://files.pythonhosted.org/packages/15/f8/491997a9b8a554204f834ed4816bda813aefda31cf873bb099deee3c9a99/mypy-1.16.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0ab5eca37b50188163fa7c1b73c685ac66c4e9bdee4a85c9adac0e91d8895e15", size = 12722980, upload-time = "2025-06-16T16:37:40.929Z" }, + { url = "https://files.pythonhosted.org/packages/df/f0/2bd41e174b5fd93bc9de9a28e4fb673113633b8a7f3a607fa4a73595e468/mypy-1.16.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb6229b2c9086247e21a83c309754b9058b438704ad2f6807f0d8227f6ebdd", size = 12903328, upload-time = "2025-06-16T16:34:35.099Z" }, + { url = "https://files.pythonhosted.org/packages/61/81/5572108a7bec2c46b8aff7e9b524f371fe6ab5efb534d38d6b37b5490da8/mypy-1.16.1-cp312-cp312-win_amd64.whl", hash = "sha256:1f0435cf920e287ff68af3d10a118a73f212deb2ce087619eb4e648116d1fe9b", size = 9562321, upload-time = "2025-06-16T16:48:58.823Z" }, + { url = "https://files.pythonhosted.org/packages/28/e3/96964af4a75a949e67df4b95318fe2b7427ac8189bbc3ef28f92a1c5bc56/mypy-1.16.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ddc91eb318c8751c69ddb200a5937f1232ee8efb4e64e9f4bc475a33719de438", size = 11063480, upload-time = "2025-06-16T16:47:56.205Z" }, + { url = "https://files.pythonhosted.org/packages/f5/4d/cd1a42b8e5be278fab7010fb289d9307a63e07153f0ae1510a3d7b703193/mypy-1.16.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:87ff2c13d58bdc4bbe7dc0dedfe622c0f04e2cb2a492269f3b418df2de05c536", size = 10090538, upload-time = "2025-06-16T16:46:43.92Z" }, + { url = "https://files.pythonhosted.org/packages/c9/4f/c3c6b4b66374b5f68bab07c8cabd63a049ff69796b844bc759a0ca99bb2a/mypy-1.16.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a7cfb0fe29fe5a9841b7c8ee6dffb52382c45acdf68f032145b75620acfbd6f", size = 11836839, upload-time = "2025-06-16T16:36:28.039Z" }, + { url = "https://files.pythonhosted.org/packages/b4/7e/81ca3b074021ad9775e5cb97ebe0089c0f13684b066a750b7dc208438403/mypy-1.16.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:051e1677689c9d9578b9c7f4d206d763f9bbd95723cd1416fad50db49d52f359", size = 12715634, upload-time = "2025-06-16T16:50:34.441Z" }, + { url = "https://files.pythonhosted.org/packages/e9/95/bdd40c8be346fa4c70edb4081d727a54d0a05382d84966869738cfa8a497/mypy-1.16.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d5d2309511cc56c021b4b4e462907c2b12f669b2dbeb68300110ec27723971be", size = 12895584, upload-time = "2025-06-16T16:34:54.857Z" }, + { url = "https://files.pythonhosted.org/packages/5a/fd/d486a0827a1c597b3b48b1bdef47228a6e9ee8102ab8c28f944cb83b65dc/mypy-1.16.1-cp313-cp313-win_amd64.whl", hash = "sha256:4f58ac32771341e38a853c5d0ec0dfe27e18e27da9cdb8bbc882d2249c71a3ee", size = 9573886, upload-time = "2025-06-16T16:36:43.589Z" }, + { url = "https://files.pythonhosted.org/packages/49/5e/ed1e6a7344005df11dfd58b0fdd59ce939a0ba9f7ed37754bf20670b74db/mypy-1.16.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7fc688329af6a287567f45cc1cefb9db662defeb14625213a5b7da6e692e2069", size = 10959511, upload-time = "2025-06-16T16:47:21.945Z" }, + { url = "https://files.pythonhosted.org/packages/30/88/a7cbc2541e91fe04f43d9e4577264b260fecedb9bccb64ffb1a34b7e6c22/mypy-1.16.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e198ab3f55924c03ead626ff424cad1732d0d391478dfbf7bb97b34602395da", size = 10075555, upload-time = "2025-06-16T16:50:14.084Z" }, + { url = "https://files.pythonhosted.org/packages/93/f7/c62b1e31a32fbd1546cca5e0a2e5f181be5761265ad1f2e94f2a306fa906/mypy-1.16.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:09aa4f91ada245f0a45dbc47e548fd94e0dd5a8433e0114917dc3b526912a30c", size = 11874169, upload-time = "2025-06-16T16:49:42.276Z" }, + { url = "https://files.pythonhosted.org/packages/c8/15/db580a28034657fb6cb87af2f8996435a5b19d429ea4dcd6e1c73d418e60/mypy-1.16.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13c7cd5b1cb2909aa318a90fd1b7e31f17c50b242953e7dd58345b2a814f6383", size = 12610060, upload-time = "2025-06-16T16:34:15.215Z" }, + { url = "https://files.pythonhosted.org/packages/ec/78/c17f48f6843048fa92d1489d3095e99324f2a8c420f831a04ccc454e2e51/mypy-1.16.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:58e07fb958bc5d752a280da0e890c538f1515b79a65757bbdc54252ba82e0b40", size = 12875199, upload-time = "2025-06-16T16:35:14.448Z" }, + { url = "https://files.pythonhosted.org/packages/bc/d6/ed42167d0a42680381653fd251d877382351e1bd2c6dd8a818764be3beb1/mypy-1.16.1-cp39-cp39-win_amd64.whl", hash = "sha256:f895078594d918f93337a505f8add9bd654d1a24962b4c6ed9390e12531eb31b", size = 9487033, upload-time = "2025-06-16T16:49:57.907Z" }, + { url = "https://files.pythonhosted.org/packages/cf/d3/53e684e78e07c1a2bf7105715e5edd09ce951fc3f47cf9ed095ec1b7a037/mypy-1.16.1-py3-none-any.whl", hash = "sha256:5fc2ac4027d0ef28d6ba69a0343737a23c4d1b83672bf38d1fe237bdc0643b37", size = 2265923, upload-time = "2025-06-16T16:48:02.366Z" }, ] [[package]] @@ -787,50 +810,50 @@ wheels = [ [[package]] name = "ormsgpack" -version = "1.9.1" +version = "1.10.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/25/a7/462cf8ff5e29241868b82d3a5ec124d690eb6a6a5c6fa5bb1367b839e027/ormsgpack-1.9.1.tar.gz", hash = "sha256:3da6e63d82565e590b98178545e64f0f8506137b92bd31a2d04fd7c82baf5794", size = 56887, upload-time = "2025-03-28T07:14:38.843Z" } +sdist = { url = "https://files.pythonhosted.org/packages/92/36/44eed5ef8ce93cded76a576780bab16425ce7876f10d3e2e6265e46c21ea/ormsgpack-1.10.0.tar.gz", hash = "sha256:7f7a27efd67ef22d7182ec3b7fa7e9d147c3ad9be2a24656b23c989077e08b16", size = 58629, upload-time = "2025-05-24T19:07:53.944Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7f/32/5f504c0695ff96aaaf0452bee522d79b5a3ee809f22fd77fdb0dd5756d86/ormsgpack-1.9.1-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:f1f804fd9c0fd84213a6022c34172f82323b34afa7052a4af18797582cf56365", size = 382793, upload-time = "2025-03-28T07:13:32.067Z" }, - { url = "https://files.pythonhosted.org/packages/1e/c6/64fe1270271b61495611f1d3068baedb57d76e0f93ce7156f3763fb79b32/ormsgpack-1.9.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eab5cec99c46276b37071d570aab98603f3d0309b3818da3247eb64bb95e5cfc", size = 213974, upload-time = "2025-03-28T07:13:33.92Z" }, - { url = "https://files.pythonhosted.org/packages/13/56/6666d6a9b82c7d2021fce6823ff823bc373a4e7280979c1b453317678fbc/ormsgpack-1.9.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1c12c6bb30e6df6fc0213b77f0a5e143f371d618be2e8eb4d555340ce01c6900", size = 217200, upload-time = "2025-03-28T07:13:35.793Z" }, - { url = "https://files.pythonhosted.org/packages/5f/fb/b844ed1e69d8615163525a8403d7abd3548b3fbfa0f3a973808f36145a0f/ormsgpack-1.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:994d4bbb7ee333264a3e55e30ccee063df6635d785f21a08bf52f67821454a51", size = 223648, upload-time = "2025-03-28T07:13:37.538Z" }, - { url = "https://files.pythonhosted.org/packages/f2/26/c40c3e300f9c61a5ed7a6921656dd0d2907a8174936e1e643677585e497c/ormsgpack-1.9.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a668a584cf4bb6e1a6ef5a35f3f0d0fdae80cfb7237344ad19a50cce8c79317b", size = 394197, upload-time = "2025-03-28T07:13:39.682Z" }, - { url = "https://files.pythonhosted.org/packages/2d/4c/7a4ae187f18e7abf7ab0662b473264a60a5aa4e9bff266f541a8855df163/ormsgpack-1.9.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:aaf77699203822638014c604d100f132583844d4fd01eb639a2266970c02cfdf", size = 480550, upload-time = "2025-03-28T07:13:41.156Z" }, - { url = "https://files.pythonhosted.org/packages/b1/33/5c465dfd5571f816835bb9e371987bf081b529c64ef28a72d18b0b59902d/ormsgpack-1.9.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:003d7e1992b447898caf25a820b3037ec68a57864b3e2f34b64693b7d60a9984", size = 396955, upload-time = "2025-03-28T07:13:43.185Z" }, - { url = "https://files.pythonhosted.org/packages/8f/fd/8f64f477b5c6d66e9c6343d7d3f32d7063ba20ab151dd36884e6504899ab/ormsgpack-1.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:67fefc77e4ba9469f79426769eb4c78acf21f22bef3ab1239a72dd728036ffc2", size = 125102, upload-time = "2025-03-28T07:13:44.878Z" }, - { url = "https://files.pythonhosted.org/packages/d8/3b/388e7915a28db6ab3daedfd4937bd7b063c50dd1543068daa31c0a3b70ed/ormsgpack-1.9.1-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:16eaf32c33ab4249e242181d59e2509b8e0330d6f65c1d8bf08c3dea38fd7c02", size = 382794, upload-time = "2025-03-28T07:13:46.72Z" }, - { url = "https://files.pythonhosted.org/packages/0f/b4/3f4afba058822bf69b274e0defe507056be0340e65363c3ebcd312b01b84/ormsgpack-1.9.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c70f2e5b2f9975536e8f7936a9721601dc54febe363d2d82f74c9b31d4fe1c65", size = 213974, upload-time = "2025-03-28T07:13:48.488Z" }, - { url = "https://files.pythonhosted.org/packages/bf/be/f0e21366d51b6e28fc3a55425be6a125545370d3479bf25be081e83ee236/ormsgpack-1.9.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:17c9e18b07d69e3db2e0f8af4731040175e11bdfde78ad8e28126e9e66ec5167", size = 217200, upload-time = "2025-03-28T07:13:50.449Z" }, - { url = "https://files.pythonhosted.org/packages/cc/90/67a23c1c880a6e5552acb45f9555b642528f89c8bcf75283a2ea64ef7175/ormsgpack-1.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:73538d749096bb6470328601a2be8f7bdec28849ec6fd19595c232a5848d7124", size = 223649, upload-time = "2025-03-28T07:13:52.281Z" }, - { url = "https://files.pythonhosted.org/packages/80/ad/116c1f970b5b4453e4faa52645517a2e5eaf1ab385ba09a5c54253d07d0e/ormsgpack-1.9.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:827ff71de228cfd6d07b9d6b47911aa61b1e8dc995dec3caf8fdcdf4f874bcd0", size = 394200, upload-time = "2025-03-28T07:13:53.691Z" }, - { url = "https://files.pythonhosted.org/packages/c5/a2/b224a5ef193628a15205e473179276b87e8290d321693e4934a05cbd6ccf/ormsgpack-1.9.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:7307f808b3df282c8e8ed92c6ebceeb3eea3d8eeec808438f3f212226b25e217", size = 480551, upload-time = "2025-03-28T07:13:55.442Z" }, - { url = "https://files.pythonhosted.org/packages/b5/f4/a0f528196af6ab46e6c3f3051cf7403016bdc7b7d3e673ea5b04b145be98/ormsgpack-1.9.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f30aad7fb083bed1c540a3c163c6a9f63a94e3c538860bf8f13386c29b560ad5", size = 396959, upload-time = "2025-03-28T07:13:56.907Z" }, - { url = "https://files.pythonhosted.org/packages/bc/6b/60c6f4787e3e93f5eb34fccb163753a8771465983a579e3405152f2422fd/ormsgpack-1.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:829a1b4c5bc3c38ece0c55cf91ebc09c3b987fceb24d3f680c2bcd03fd3789a4", size = 125100, upload-time = "2025-03-28T07:13:58.607Z" }, - { url = "https://files.pythonhosted.org/packages/dd/f1/155a598cc8030526ccaaf91ba4d61530f87900645559487edba58b0a90a2/ormsgpack-1.9.1-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:1ede445fc3fdba219bb0e0d1f289df26a9c7602016b7daac6fafe8fe4e91548f", size = 383225, upload-time = "2025-03-28T07:14:00.811Z" }, - { url = "https://files.pythonhosted.org/packages/23/1c/ef3097ba550fad55c79525f461febdd4e0d9cc18d065248044536f09488e/ormsgpack-1.9.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db50b9f918e25b289114312ed775794d0978b469831b992bdc65bfe20b91fe30", size = 214056, upload-time = "2025-03-28T07:14:02.861Z" }, - { url = "https://files.pythonhosted.org/packages/27/77/64d0da25896b2cbb99505ca518c109d7dd1964d7fde14c10943731738b60/ormsgpack-1.9.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8c7d8fc58e4333308f58ec720b1ee6b12b2b3fe2d2d8f0766ab751cb351e8757", size = 217339, upload-time = "2025-03-28T07:14:04.278Z" }, - { url = "https://files.pythonhosted.org/packages/6c/10/c3a7fd0a0068b0bb52cccbfeb5656db895d69e895a3abbc210c4b3f98ff8/ormsgpack-1.9.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aeee6d08c040db265cb8563444aba343ecb32cbdbe2414a489dcead9f70c6765", size = 223816, upload-time = "2025-03-28T07:14:05.969Z" }, - { url = "https://files.pythonhosted.org/packages/43/e7/aee1238dba652f2116c2523d36fd1c5f9775436032be5c233108fd2a1415/ormsgpack-1.9.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2fbb8181c198bdc413a4e889e5200f010724eea4b6d5a9a7eee2df039ac04aca", size = 394287, upload-time = "2025-03-28T07:14:07.635Z" }, - { url = "https://files.pythonhosted.org/packages/c7/09/1b452a92376f29d7a2da7c18fb01cf09978197a8eccbb8b204e72fd5a970/ormsgpack-1.9.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:16488f094ac0e2250cceea6caf72962614aa432ee11dd57ef45e1ad25ece3eff", size = 480709, upload-time = "2025-03-28T07:14:09.41Z" }, - { url = "https://files.pythonhosted.org/packages/de/13/7fa9fee5a73af8a73a42bf8c2e69489605714f65f5a41454400a05e84a3b/ormsgpack-1.9.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:422d960bfd6ad88be20794f50ec7953d8f7a0f2df60e19d0e8feb994e2ed64ee", size = 397247, upload-time = "2025-03-28T07:14:11.261Z" }, - { url = "https://files.pythonhosted.org/packages/a1/2d/2e87cb28110db0d3bb750edd4d8719b5068852a2eef5e96b0bf376bb8a81/ormsgpack-1.9.1-cp312-cp312-win_amd64.whl", hash = "sha256:e6e2f9eab527cf43fb4a4293e493370276b1c8716cf305689202d646c6a782ef", size = 125368, upload-time = "2025-03-28T07:14:12.665Z" }, - { url = "https://files.pythonhosted.org/packages/b8/54/0390d5d092831e4df29dbafe32402891fc14b3e6ffe5a644b16cbbc9d9bc/ormsgpack-1.9.1-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:ac61c18d9dd085e8519b949f7e655f7fb07909fd09c53b4338dd33309012e289", size = 383226, upload-time = "2025-03-28T07:14:13.868Z" }, - { url = "https://files.pythonhosted.org/packages/47/64/8b15d262d1caefead8fb22ec144f5ff7d9505fc31c22bc34598053d46fbe/ormsgpack-1.9.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:134840b8c6615da2c24ce77bd12a46098015c808197a9995c7a2d991e1904eec", size = 214057, upload-time = "2025-03-28T07:14:15.307Z" }, - { url = "https://files.pythonhosted.org/packages/57/00/65823609266bad4d5ed29ea753d24a3bdb01c7edaf923da80967fc31f9c5/ormsgpack-1.9.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:38fd42618f626394b2c7713c5d4bcbc917254e9753d5d4cde460658b51b11a74", size = 217340, upload-time = "2025-03-28T07:14:16.69Z" }, - { url = "https://files.pythonhosted.org/packages/a0/51/e535c50f7f87b49110233647f55300d7975139ef5e51f1adb4c55f58c124/ormsgpack-1.9.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d36397333ad07b9eba4c2e271fa78951bd81afc059c85a6e9f6c0eb2de07cda", size = 223815, upload-time = "2025-03-28T07:14:18.651Z" }, - { url = "https://files.pythonhosted.org/packages/0c/ee/393e4a6de2a62124bf589602648f295a9fb3907a0e2fe80061b88899d072/ormsgpack-1.9.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:603063089597917d04e4c1b1d53988a34f7dc2ff1a03adcfd1cf4ae966d5fba6", size = 394287, upload-time = "2025-03-28T07:14:20.569Z" }, - { url = "https://files.pythonhosted.org/packages/c6/d8/e56d7c3cb73a0e533e3e2a21ae5838b2aa36a9dac1ca9c861af6bae5a369/ormsgpack-1.9.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:94bbf2b185e0cb721ceaba20e64b7158e6caf0cecd140ca29b9f05a8d5e91e2f", size = 480707, upload-time = "2025-03-28T07:14:22.006Z" }, - { url = "https://files.pythonhosted.org/packages/e6/e0/6a3c6a6dc98583a721c54b02f5195bde8f801aebdeda9b601fa2ab30ad39/ormsgpack-1.9.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c38f380b1e8c96a712eb302b9349347385161a8e29046868ae2bfdfcb23e2692", size = 397246, upload-time = "2025-03-28T07:14:23.868Z" }, - { url = "https://files.pythonhosted.org/packages/b0/60/0ee5d790f13507e1f75ac21fc82dc1ef29afe1f520bd0f249d65b2f4839b/ormsgpack-1.9.1-cp313-cp313-win_amd64.whl", hash = "sha256:a4bc63fb30db94075611cedbbc3d261dd17cf2aa8ff75a0fd684cd45ca29cb1b", size = 125371, upload-time = "2025-03-28T07:14:25.176Z" }, - { url = "https://files.pythonhosted.org/packages/85/02/ac4a2263c9aad0d455f240e1bdd41b443e5452257cf13bc188177b0dfd1f/ormsgpack-1.9.1-cp39-cp39-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:e95909248bece8e88a310a913838f17ff5a39190aa4e61de909c3cd27f59744b", size = 382789, upload-time = "2025-03-28T07:14:26.774Z" }, - { url = "https://files.pythonhosted.org/packages/81/6f/e50d070ae3a6aa7cb50849d0796ac6d72c0f8f01d5a42438c9567ab352e3/ormsgpack-1.9.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3939188810c5c641d6b207f29994142ae2b1c70534f7839bbd972d857ac2072", size = 213967, upload-time = "2025-03-28T07:14:28.473Z" }, - { url = "https://files.pythonhosted.org/packages/55/1d/379734bca4f2d71ce11c7096d85276280cf13d1bb7243bf809b171c25cda/ormsgpack-1.9.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:25b6476344a585aea00a2acc9fd07355bf2daac04062cfdd480fa83ec3e2403b", size = 217183, upload-time = "2025-03-28T07:14:29.822Z" }, - { url = "https://files.pythonhosted.org/packages/9a/f6/036a44ada8659b1729db5f20ba50dc1945a84a50cd4fa6b3a74d0f16fab9/ormsgpack-1.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a7d8b9d53da82b31662ce5a3834b65479cf794a34befb9fc50baa51518383250", size = 223647, upload-time = "2025-03-28T07:14:31.487Z" }, - { url = "https://files.pythonhosted.org/packages/b9/61/5c8671ab3b7cac21076169972bad9f4faa1fdda1f70e0ae78b365894b164/ormsgpack-1.9.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:3933d4b0c0d404ee234dbc372836d6f2d2f4b6330c2a2fb9709ba4eaebfae7ba", size = 394232, upload-time = "2025-03-28T07:14:33.254Z" }, - { url = "https://files.pythonhosted.org/packages/7b/70/6e9ba8c8c405dee5dffd86edf1188ef1a116421598e18df89dac0c499aae/ormsgpack-1.9.1-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:f824e94a7969f0aee9a6847ec232cf731a03b8734951c2a774dd4762308ea2d2", size = 480582, upload-time = "2025-03-28T07:14:34.704Z" }, - { url = "https://files.pythonhosted.org/packages/a6/e1/2113022dd9236cea13f0ba850a5f8a640c0c9e3b07bfbbaf01409190068b/ormsgpack-1.9.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c1f3f2295374020f9650e4aa7af6403ff016a0d92778b4a48bb3901fd801232d", size = 396952, upload-time = "2025-03-28T07:14:36.128Z" }, - { url = "https://files.pythonhosted.org/packages/01/d4/58ca5de3124ac975dae1a96a475c3cb9ed70c70dfba39fd4ceca53838ee6/ormsgpack-1.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:92eb1b4f7b168da47f547329b4b58d16d8f19508a97ce5266567385d42d81968", size = 125107, upload-time = "2025-03-28T07:14:37.621Z" }, + { url = "https://files.pythonhosted.org/packages/fc/74/c2dd5daf069e3798d09d5746000f9b210de04df83834e5cb47f0ace51892/ormsgpack-1.10.0-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:8a52c7ce7659459f3dc8dec9fd6a6c76f855a0a7e2b61f26090982ac10b95216", size = 376280, upload-time = "2025-05-24T19:06:51.3Z" }, + { url = "https://files.pythonhosted.org/packages/78/7b/30ff4bffb709e8a242005a8c4d65714fd96308ad640d31cff1b85c0d8cc4/ormsgpack-1.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:060f67fe927582f4f63a1260726d019204b72f460cf20930e6c925a1d129f373", size = 204335, upload-time = "2025-05-24T19:06:53.442Z" }, + { url = "https://files.pythonhosted.org/packages/8f/3f/c95b7d142819f801a0acdbd04280e8132e43b6e5a8920173e8eb92ea0e6a/ormsgpack-1.10.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7058ef6092f995561bf9f71d6c9a4da867b6cc69d2e94cb80184f579a3ceed5", size = 215373, upload-time = "2025-05-24T19:06:55.153Z" }, + { url = "https://files.pythonhosted.org/packages/ef/1a/e30f4bcf386db2015d1686d1da6110c95110294d8ea04f86091dd5eb3361/ormsgpack-1.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10f6f3509c1b0e51b15552d314b1d409321718122e90653122ce4b997f01453a", size = 216469, upload-time = "2025-05-24T19:06:56.555Z" }, + { url = "https://files.pythonhosted.org/packages/96/fc/7e44aeade22b91883586f45b7278c118fd210834c069774891447f444fc9/ormsgpack-1.10.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:51c1edafd5c72b863b1f875ec31c529f09c872a5ff6fe473b9dfaf188ccc3227", size = 384590, upload-time = "2025-05-24T19:06:58.286Z" }, + { url = "https://files.pythonhosted.org/packages/ec/78/f92c24e8446697caa83c122f10b6cf5e155eddf81ce63905c8223a260482/ormsgpack-1.10.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:c780b44107a547a9e9327270f802fa4d6b0f6667c9c03c3338c0ce812259a0f7", size = 478891, upload-time = "2025-05-24T19:07:00.126Z" }, + { url = "https://files.pythonhosted.org/packages/5a/75/87449690253c64bea2b663c7c8f2dbc9ad39d73d0b38db74bdb0f3947b16/ormsgpack-1.10.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:137aab0d5cdb6df702da950a80405eb2b7038509585e32b4e16289604ac7cb84", size = 390121, upload-time = "2025-05-24T19:07:01.777Z" }, + { url = "https://files.pythonhosted.org/packages/69/cc/c83257faf3a5169ec29dd87121317a25711da9412ee8c1e82f2e1a00c0be/ormsgpack-1.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:3e666cb63030538fa5cd74b1e40cb55b6fdb6e2981f024997a288bf138ebad07", size = 121196, upload-time = "2025-05-24T19:07:03.47Z" }, + { url = "https://files.pythonhosted.org/packages/30/27/7da748bc0d7d567950a378dee5a32477ed5d15462ab186918b5f25cac1ad/ormsgpack-1.10.0-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:4bb7df307e17b36cbf7959cd642c47a7f2046ae19408c564e437f0ec323a7775", size = 376275, upload-time = "2025-05-24T19:07:05.128Z" }, + { url = "https://files.pythonhosted.org/packages/7b/65/c082cc8c74a914dbd05af0341c761c73c3d9960b7432bbf9b8e1e20811af/ormsgpack-1.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8817ae439c671779e1127ee62f0ac67afdeaeeacb5f0db45703168aa74a2e4af", size = 204335, upload-time = "2025-05-24T19:07:06.423Z" }, + { url = "https://files.pythonhosted.org/packages/46/62/17ef7e5d9766c79355b9c594cc9328c204f1677bc35da0595cc4e46449f0/ormsgpack-1.10.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f345f81e852035d80232e64374d3a104139d60f8f43c6c5eade35c4bac5590e", size = 215372, upload-time = "2025-05-24T19:07:08.149Z" }, + { url = "https://files.pythonhosted.org/packages/4e/92/7c91e8115fc37e88d1a35e13200fda3054ff5d2e5adf017345e58cea4834/ormsgpack-1.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21de648a1c7ef692bdd287fb08f047bd5371d7462504c0a7ae1553c39fee35e3", size = 216470, upload-time = "2025-05-24T19:07:09.903Z" }, + { url = "https://files.pythonhosted.org/packages/2c/86/ce053c52e2517b90e390792d83e926a7a523c1bce5cc63d0a7cd05ce6cf6/ormsgpack-1.10.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3a7d844ae9cbf2112c16086dd931b2acefce14cefd163c57db161170c2bfa22b", size = 384591, upload-time = "2025-05-24T19:07:11.24Z" }, + { url = "https://files.pythonhosted.org/packages/07/e8/2ad59f2ab222c6029e500bc966bfd2fe5cb099f8ab6b7ebeb50ddb1a6fe5/ormsgpack-1.10.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:e4d80585403d86d7f800cf3d0aafac1189b403941e84e90dd5102bb2b92bf9d5", size = 478892, upload-time = "2025-05-24T19:07:13.147Z" }, + { url = "https://files.pythonhosted.org/packages/f4/73/f55e4b47b7b18fd8e7789680051bf830f1e39c03f1d9ed993cd0c3e97215/ormsgpack-1.10.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:da1de515a87e339e78a3ccf60e39f5fb740edac3e9e82d3c3d209e217a13ac08", size = 390122, upload-time = "2025-05-24T19:07:14.557Z" }, + { url = "https://files.pythonhosted.org/packages/f7/87/073251cdb93d4c6241748568b3ad1b2a76281fb2002eed16a3a4043d61cf/ormsgpack-1.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:57c4601812684024132cbb32c17a7d4bb46ffc7daf2fddf5b697391c2c4f142a", size = 121197, upload-time = "2025-05-24T19:07:15.981Z" }, + { url = "https://files.pythonhosted.org/packages/99/95/f3ab1a7638f6aa9362e87916bb96087fbbc5909db57e19f12ad127560e1e/ormsgpack-1.10.0-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:4e159d50cd4064d7540e2bc6a0ab66eab70b0cc40c618b485324ee17037527c0", size = 376806, upload-time = "2025-05-24T19:07:17.221Z" }, + { url = "https://files.pythonhosted.org/packages/6c/2b/42f559f13c0b0f647b09d749682851d47c1a7e48308c43612ae6833499c8/ormsgpack-1.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eeb47c85f3a866e29279d801115b554af0fefc409e2ed8aa90aabfa77efe5cc6", size = 204433, upload-time = "2025-05-24T19:07:18.569Z" }, + { url = "https://files.pythonhosted.org/packages/45/42/1ca0cb4d8c80340a89a4af9e6d8951fb8ba0d076a899d2084eadf536f677/ormsgpack-1.10.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c28249574934534c9bd5dce5485c52f21bcea0ee44d13ece3def6e3d2c3798b5", size = 215547, upload-time = "2025-05-24T19:07:20.245Z" }, + { url = "https://files.pythonhosted.org/packages/0a/38/184a570d7c44c0260bc576d1daaac35b2bfd465a50a08189518505748b9a/ormsgpack-1.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1957dcadbb16e6a981cd3f9caef9faf4c2df1125e2a1b702ee8236a55837ce07", size = 216746, upload-time = "2025-05-24T19:07:21.83Z" }, + { url = "https://files.pythonhosted.org/packages/69/2f/1aaffd08f6b7fdc2a57336a80bdfb8df24e6a65ada5aa769afecfcbc6cc6/ormsgpack-1.10.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3b29412558c740bf6bac156727aa85ac67f9952cd6f071318f29ee72e1a76044", size = 384783, upload-time = "2025-05-24T19:07:23.674Z" }, + { url = "https://files.pythonhosted.org/packages/a9/63/3e53d6f43bb35e00c98f2b8ab2006d5138089ad254bc405614fbf0213502/ormsgpack-1.10.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:6933f350c2041ec189fe739f0ba7d6117c8772f5bc81f45b97697a84d03020dd", size = 479076, upload-time = "2025-05-24T19:07:25.047Z" }, + { url = "https://files.pythonhosted.org/packages/b8/19/fa1121b03b61402bb4d04e35d164e2320ef73dfb001b57748110319dd014/ormsgpack-1.10.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9a86de06d368fcc2e58b79dece527dc8ca831e0e8b9cec5d6e633d2777ec93d0", size = 390447, upload-time = "2025-05-24T19:07:26.568Z" }, + { url = "https://files.pythonhosted.org/packages/b0/0d/73143ecb94ac4a5dcba223402139240a75dee0cc6ba8a543788a5646407a/ormsgpack-1.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:35fa9f81e5b9a0dab42e09a73f7339ecffdb978d6dbf9deb2ecf1e9fc7808722", size = 121401, upload-time = "2025-05-24T19:07:28.308Z" }, + { url = "https://files.pythonhosted.org/packages/61/f8/ec5f4e03268d0097545efaab2893aa63f171cf2959cb0ea678a5690e16a1/ormsgpack-1.10.0-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:8d816d45175a878993b7372bd5408e0f3ec5a40f48e2d5b9d8f1cc5d31b61f1f", size = 376806, upload-time = "2025-05-24T19:07:29.555Z" }, + { url = "https://files.pythonhosted.org/packages/c1/19/b3c53284aad1e90d4d7ed8c881a373d218e16675b8b38e3569d5b40cc9b8/ormsgpack-1.10.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a90345ccb058de0f35262893751c603b6376b05f02be2b6f6b7e05d9dd6d5643", size = 204433, upload-time = "2025-05-24T19:07:30.977Z" }, + { url = "https://files.pythonhosted.org/packages/09/0b/845c258f59df974a20a536c06cace593698491defdd3d026a8a5f9b6e745/ormsgpack-1.10.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:144b5e88f1999433e54db9d637bae6fe21e935888be4e3ac3daecd8260bd454e", size = 215549, upload-time = "2025-05-24T19:07:32.345Z" }, + { url = "https://files.pythonhosted.org/packages/61/56/57fce8fb34ca6c9543c026ebebf08344c64dbb7b6643d6ddd5355d37e724/ormsgpack-1.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2190b352509d012915921cca76267db136cd026ddee42f1b0d9624613cc7058c", size = 216747, upload-time = "2025-05-24T19:07:34.075Z" }, + { url = "https://files.pythonhosted.org/packages/b8/3f/655b5f6a2475c8d209f5348cfbaaf73ce26237b92d79ef2ad439407dd0fa/ormsgpack-1.10.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:86fd9c1737eaba43d3bb2730add9c9e8b5fbed85282433705dd1b1e88ea7e6fb", size = 384785, upload-time = "2025-05-24T19:07:35.83Z" }, + { url = "https://files.pythonhosted.org/packages/4b/94/687a0ad8afd17e4bce1892145d6a1111e58987ddb176810d02a1f3f18686/ormsgpack-1.10.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:33afe143a7b61ad21bb60109a86bb4e87fec70ef35db76b89c65b17e32da7935", size = 479076, upload-time = "2025-05-24T19:07:37.533Z" }, + { url = "https://files.pythonhosted.org/packages/c8/34/68925232e81e0e062a2f0ac678f62aa3b6f7009d6a759e19324dbbaebae7/ormsgpack-1.10.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f23d45080846a7b90feabec0d330a9cc1863dc956728412e4f7986c80ab3a668", size = 390446, upload-time = "2025-05-24T19:07:39.469Z" }, + { url = "https://files.pythonhosted.org/packages/12/ad/f4e1a36a6d1714afb7ffb74b3ababdcb96529cf4e7a216f9f7c8eda837b6/ormsgpack-1.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:534d18acb805c75e5fba09598bf40abe1851c853247e61dda0c01f772234da69", size = 121399, upload-time = "2025-05-24T19:07:40.854Z" }, + { url = "https://files.pythonhosted.org/packages/75/8f/bb80469db9d5b10708cba6997463d140486ca7053a5d18f99b5739cfecf7/ormsgpack-1.10.0-cp39-cp39-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:efdb25cf6d54085f7ae557268d59fd2d956f1a09a340856e282d2960fe929f32", size = 376272, upload-time = "2025-05-24T19:07:42.16Z" }, + { url = "https://files.pythonhosted.org/packages/08/9c/48f714ed3d5a153f25e3b490496e6ba214aee265a82be1b61e39019ea146/ormsgpack-1.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ddfcb30d4b1be2439836249d675f297947f4fb8efcd3eeb6fd83021d773cadc4", size = 204314, upload-time = "2025-05-24T19:07:43.444Z" }, + { url = "https://files.pythonhosted.org/packages/27/42/7f9edf6e5511120b5304c76c5d3a8b4719ff927555a6dba41b6f9d041b30/ormsgpack-1.10.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ee0944b6ccfd880beb1ca29f9442a774683c366f17f4207f8b81c5e24cadb453", size = 215386, upload-time = "2025-05-24T19:07:45.232Z" }, + { url = "https://files.pythonhosted.org/packages/40/87/41e14485857fbe4ed5a530677fe60dd6910a254825c0b1cb5b04baaa4be0/ormsgpack-1.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35cdff6a0d3ba04e40a751129763c3b9b57a602c02944138e4b760ec99ae80a1", size = 216466, upload-time = "2025-05-24T19:07:46.548Z" }, + { url = "https://files.pythonhosted.org/packages/cb/68/769fa1c721d8aa6799c0ce98b1711ae57de3e6379b554ebf9a11be4c62ff/ormsgpack-1.10.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:599ccdabc19c618ef5de6e6f2e7f5d48c1f531a625fa6772313b8515bc710681", size = 384600, upload-time = "2025-05-24T19:07:47.945Z" }, + { url = "https://files.pythonhosted.org/packages/4e/f9/b57fd387fe16753783a3cea0ed2471c727bbed4356d8a08e3f0340251870/ormsgpack-1.10.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:bf46f57da9364bd5eefd92365c1b78797f56c6f780581eecd60cd7b367f9b4d3", size = 478888, upload-time = "2025-05-24T19:07:49.801Z" }, + { url = "https://files.pythonhosted.org/packages/3e/0f/464cdfa7f9ee817c2d94485880b6c3c4b9f22df9fcbf21c303bbfebcb3ed/ormsgpack-1.10.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b796f64fdf823dedb1e35436a4a6f889cf78b1aa42d3097c66e5adfd8c3bd72d", size = 390118, upload-time = "2025-05-24T19:07:51.193Z" }, + { url = "https://files.pythonhosted.org/packages/ad/03/b9146dff5458def4c0a2b1e35c1c24e4d5e8083899aa0718b6eccba39317/ormsgpack-1.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:106253ac9dc08520951e556b3c270220fcb8b4fef0d30b71eedac4befa4de749", size = 121199, upload-time = "2025-05-24T19:07:52.639Z" }, ] [[package]] @@ -843,12 +866,21 @@ wheels = [ ] [[package]] -name = "pluggy" -version = "1.5.0" +name = "pathspec" +version = "0.12.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955, upload-time = "2024-04-20T21:34:42.531Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556, upload-time = "2024-04-20T21:34:40.434Z" }, + { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" }, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, ] [[package]] @@ -862,7 +894,7 @@ wheels = [ [[package]] name = "pydantic" -version = "2.11.4" +version = "2.11.7" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-types", marker = "python_full_version >= '3.11'" }, @@ -870,9 +902,9 @@ dependencies = [ { name = "typing-extensions", marker = "python_full_version >= '3.11'" }, { name = "typing-inspection", marker = "python_full_version >= '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/77/ab/5250d56ad03884ab5efd07f734203943c8a8ab40d551e208af81d0257bf2/pydantic-2.11.4.tar.gz", hash = "sha256:32738d19d63a226a52eed76645a98ee07c1f410ee41d93b4afbfa85ed8111c2d", size = 786540, upload-time = "2025-04-29T20:38:55.02Z" } +sdist = { url = "https://files.pythonhosted.org/packages/00/dd/4325abf92c39ba8623b5af936ddb36ffcfe0beae70405d456ab1fb2f5b8c/pydantic-2.11.7.tar.gz", hash = "sha256:d989c3c6cb79469287b1569f7447a17848c998458d49ebe294e975b9baf0f0db", size = 788350, upload-time = "2025-06-14T08:33:17.137Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e7/12/46b65f3534d099349e38ef6ec98b1a5a81f42536d17e0ba382c28c67ba67/pydantic-2.11.4-py3-none-any.whl", hash = "sha256:d9615eaa9ac5a063471da949c8fc16376a84afb5024688b3ff885693506764eb", size = 443900, upload-time = "2025-04-29T20:38:52.724Z" }, + { url = "https://files.pythonhosted.org/packages/6a/c0/ec2b1c8712ca690e5d61979dee872603e92b8a32f94cc1b72d53beab008a/pydantic-2.11.7-py3-none-any.whl", hash = "sha256:dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b", size = 444782, upload-time = "2025-06-14T08:33:14.905Z" }, ] [[package]] @@ -984,6 +1016,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d4/29/3cade8a924a61f60ccfa10842f75eb12787e1440e2b8660ceffeb26685e7/pydantic_core-2.33.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2807668ba86cb38c6817ad9bc66215ab8584d1d304030ce4f0887336f28a5e27", size = 2066661, upload-time = "2025-04-23T18:33:49.995Z" }, ] +[[package]] +name = "pygments" +version = "2.19.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, +] + [[package]] name = "pyjwt" version = "2.10.1" @@ -995,7 +1036,7 @@ wheels = [ [[package]] name = "pytest" -version = "7.4.4" +version = "8.4.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, @@ -1003,35 +1044,37 @@ dependencies = [ { name = "iniconfig" }, { name = "packaging" }, { name = "pluggy" }, + { name = "pygments" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/80/1f/9d8e98e4133ffb16c90f3b405c43e38d3abb715bb5d7a63a5a684f7e46a3/pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280", size = 1357116, upload-time = "2023-12-31T12:00:18.035Z" } +sdist = { url = "https://files.pythonhosted.org/packages/08/ba/45911d754e8eba3d5a841a5ce61a65a685ff1798421ac054f85aa8747dfb/pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c", size = 1517714, upload-time = "2025-06-18T05:48:06.109Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/51/ff/f6e8b8f39e08547faece4bd80f89d5a8de68a38b2d179cc1c4490ffa3286/pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8", size = 325287, upload-time = "2023-12-31T12:00:13.963Z" }, + { url = "https://files.pythonhosted.org/packages/29/16/c8a903f4c4dffe7a12843191437d7cd8e32751d5de349d45d3fe69544e87/pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7", size = 365474, upload-time = "2025-06-18T05:48:03.955Z" }, ] [[package]] name = "pytest-asyncio" -version = "0.21.2" +version = "1.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pytest" }, + { name = "typing-extensions", marker = "python_full_version < '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ae/53/57663d99acaac2fcdafdc697e52a9b1b7d6fcf36616281ff9768a44e7ff3/pytest_asyncio-0.21.2.tar.gz", hash = "sha256:d67738fc232b94b326b9d060750beb16e0074210b98dd8b58a5239fa2a154f45", size = 30656, upload-time = "2024-04-29T13:23:24.738Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/d4/14f53324cb1a6381bef29d698987625d80052bb33932d8e7cbf9b337b17c/pytest_asyncio-1.0.0.tar.gz", hash = "sha256:d15463d13f4456e1ead2594520216b225a16f781e144f8fdf6c5bb4667c48b3f", size = 46960, upload-time = "2025-05-26T04:54:40.484Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9c/ce/1e4b53c213dce25d6e8b163697fbce2d43799d76fa08eea6ad270451c370/pytest_asyncio-0.21.2-py3-none-any.whl", hash = "sha256:ab664c88bb7998f711d8039cacd4884da6430886ae8bbd4eded552ed2004f16b", size = 13368, upload-time = "2024-04-29T13:23:23.126Z" }, + { url = "https://files.pythonhosted.org/packages/30/05/ce271016e351fddc8399e546f6e23761967ee09c8c568bbfbecb0c150171/pytest_asyncio-1.0.0-py3-none-any.whl", hash = "sha256:4f024da9f1ef945e680dc68610b52550e36590a67fd31bb3b4943979a1f90ef3", size = 15976, upload-time = "2025-05-26T04:54:39.035Z" }, ] [[package]] name = "pytest-mock" -version = "3.14.0" +version = "3.14.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c6/90/a955c3ab35ccd41ad4de556596fa86685bf4fc5ffcc62d22d856cfd4e29a/pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0", size = 32814, upload-time = "2024-03-21T22:14:04.964Z" } +sdist = { url = "https://files.pythonhosted.org/packages/71/28/67172c96ba684058a4d24ffe144d64783d2a270d0af0d9e792737bddc75c/pytest_mock-3.14.1.tar.gz", hash = "sha256:159e9edac4c451ce77a5cdb9fc5d1100708d2dd4ba3c3df572f14097351af80e", size = 33241, upload-time = "2025-05-26T13:58:45.167Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f2/3b/b26f90f74e2986a82df6e7ac7e319b8ea7ccece1caec9f8ab6104dc70603/pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f", size = 9863, upload-time = "2024-03-21T22:14:02.694Z" }, + { url = "https://files.pythonhosted.org/packages/b2/05/77b60e520511c53d1c1ca75f1930c7dd8e971d0c4379b7f4b3f9644685ba/pytest_mock-3.14.1-py3-none-any.whl", hash = "sha256:178aefcd11307d874b4cd3100344e7e2d888d9791a6a1d9bfe90fbc1b74fd1d0", size = 9923, upload-time = "2025-05-26T13:58:43.487Z" }, ] [[package]] @@ -1048,11 +1091,11 @@ sdist = { url = "https://files.pythonhosted.org/packages/36/47/ab65fc1d682befc31 [[package]] name = "python-dotenv" -version = "1.1.0" +version = "1.1.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/88/2c/7bb1416c5620485aa793f2de31d3df393d3686aa8a8506d11e10e13c5baf/python_dotenv-1.1.0.tar.gz", hash = "sha256:41f90bc6f5f177fb41f53e87666db362025010eb28f60a01c9143bfa33a2b2d5", size = 39920, upload-time = "2025-03-25T10:14:56.835Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/b0/4bc07ccd3572a2f9df7e6782f52b0c6c90dcbb803ac4a167702d7d0dfe1e/python_dotenv-1.1.1.tar.gz", hash = "sha256:a8a6399716257f45be6a007360200409fce5cda2661e3dec71d23dc15f6189ab", size = 41978, upload-time = "2025-06-24T04:21:07.341Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1e/18/98a99ad95133c6a6e2005fe89faedf294a748bd5dc803008059409ac9b1e/python_dotenv-1.1.0-py3-none-any.whl", hash = "sha256:d7c01d9e2293916c18baf562d95698754b0dbbb5e74d457c45d4f6561fb9d55d", size = 20256, upload-time = "2025-03-25T10:14:55.034Z" }, + { url = "https://files.pythonhosted.org/packages/5f/ed/539768cf28c661b5b068d66d96a2f155c4971a5d55684a514c1a0e0dec2f/python_dotenv-1.1.1-py3-none-any.whl", hash = "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc", size = 20556, upload-time = "2025-06-24T04:21:06.073Z" }, ] [[package]] @@ -1110,7 +1153,7 @@ wheels = [ [[package]] name = "requests" -version = "2.32.3" +version = "2.32.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi", marker = "python_full_version >= '3.11'" }, @@ -1118,9 +1161,9 @@ dependencies = [ { name = "idna", marker = "python_full_version >= '3.11'" }, { name = "urllib3", marker = "python_full_version >= '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218, upload-time = "2024-05-29T15:37:49.536Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e1/0a/929373653770d8a0d7ea76c37de6e41f11eb07559b103b1c02cafb3f7cf8/requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422", size = 135258, upload-time = "2025-06-09T16:43:07.34Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928, upload-time = "2024-05-29T15:37:47.027Z" }, + { url = "https://files.pythonhosted.org/packages/7c/e4/56027c4a6b4ae70ca9de302488c5ca95ad4a39e190093d6c1a8ace08341b/requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", size = 64847, upload-time = "2025-06-09T16:43:05.728Z" }, ] [[package]] @@ -1137,27 +1180,27 @@ wheels = [ [[package]] name = "ruff" -version = "0.6.9" +version = "0.12.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/26/0d/6148a48dab5662ca1d5a93b7c0d13c03abd3cc7e2f35db08410e47cef15d/ruff-0.6.9.tar.gz", hash = "sha256:b076ef717a8e5bc819514ee1d602bbdca5b4420ae13a9cf61a0c0a4f53a2baa2", size = 3095355, upload-time = "2024-10-04T13:40:28.594Z" } +sdist = { url = "https://files.pythonhosted.org/packages/6c/3d/d9a195676f25d00dbfcf3cf95fdd4c685c497fcfa7e862a44ac5e4e96480/ruff-0.12.2.tar.gz", hash = "sha256:d7b4f55cd6f325cb7621244f19c873c565a08aff5a4ba9c69aa7355f3f7afd3e", size = 4432239, upload-time = "2025-07-03T16:40:19.566Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6e/8f/f7a0a0ef1818662efb32ed6df16078c95da7a0a3248d64c2410c1e27799f/ruff-0.6.9-py3-none-linux_armv6l.whl", hash = "sha256:064df58d84ccc0ac0fcd63bc3090b251d90e2a372558c0f057c3f75ed73e1ccd", size = 10440526, upload-time = "2024-10-04T13:39:21.747Z" }, - { url = "https://files.pythonhosted.org/packages/8b/69/b179a5faf936a9e2ab45bb412a668e4661eded964ccfa19d533f29463ef6/ruff-0.6.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:140d4b5c9f5fc7a7b074908a78ab8d384dd7f6510402267bc76c37195c02a7ec", size = 10034612, upload-time = "2024-10-04T13:39:26.301Z" }, - { url = "https://files.pythonhosted.org/packages/c7/ef/fd1b4be979c579d191eeac37b5cfc0ec906de72c8bcd8595e2c81bb700c1/ruff-0.6.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:53fd8ca5e82bdee8da7f506d7b03a261f24cd43d090ea9db9a1dc59d9313914c", size = 9706197, upload-time = "2024-10-04T13:39:29.297Z" }, - { url = "https://files.pythonhosted.org/packages/29/61/b376d775deb5851cb48d893c568b511a6d3625ef2c129ad5698b64fb523c/ruff-0.6.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:645d7d8761f915e48a00d4ecc3686969761df69fb561dd914a773c1a8266e14e", size = 10751855, upload-time = "2024-10-04T13:39:33.175Z" }, - { url = "https://files.pythonhosted.org/packages/13/d7/def9e5f446d75b9a9c19b24231a3a658c075d79163b08582e56fa5dcfa38/ruff-0.6.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eae02b700763e3847595b9d2891488989cac00214da7f845f4bcf2989007d577", size = 10200889, upload-time = "2024-10-04T13:39:36.867Z" }, - { url = "https://files.pythonhosted.org/packages/6c/d6/7f34160818bcb6e84ce293a5966cba368d9112ff0289b273fbb689046047/ruff-0.6.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d5ccc9e58112441de8ad4b29dcb7a86dc25c5f770e3c06a9d57e0e5eba48829", size = 11038678, upload-time = "2024-10-04T13:39:40.428Z" }, - { url = "https://files.pythonhosted.org/packages/13/34/a40ff8ae62fb1b26fb8e6fa7e64bc0e0a834b47317880de22edd6bfb54fb/ruff-0.6.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:417b81aa1c9b60b2f8edc463c58363075412866ae4e2b9ab0f690dc1e87ac1b5", size = 11808682, upload-time = "2024-10-04T13:39:52.141Z" }, - { url = "https://files.pythonhosted.org/packages/2e/6d/25a4386ae4009fc798bd10ba48c942d1b0b3e459b5403028f1214b6dd161/ruff-0.6.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3c866b631f5fbce896a74a6e4383407ba7507b815ccc52bcedabb6810fdb3ef7", size = 11330446, upload-time = "2024-10-04T13:39:55.783Z" }, - { url = "https://files.pythonhosted.org/packages/f7/f6/bdf891a9200d692c94ebcd06ae5a2fa5894e522f2c66c2a12dd5d8cb2654/ruff-0.6.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7b118afbb3202f5911486ad52da86d1d52305b59e7ef2031cea3425142b97d6f", size = 12483048, upload-time = "2024-10-04T13:39:58.845Z" }, - { url = "https://files.pythonhosted.org/packages/a7/86/96f4252f41840e325b3fa6c48297e661abb9f564bd7dcc0572398c8daa42/ruff-0.6.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a67267654edc23c97335586774790cde402fb6bbdb3c2314f1fc087dee320bfa", size = 10936855, upload-time = "2024-10-04T13:40:01.818Z" }, - { url = "https://files.pythonhosted.org/packages/45/87/801a52d26c8dbf73424238e9908b9ceac430d903c8ef35eab1b44fcfa2bd/ruff-0.6.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:3ef0cc774b00fec123f635ce5c547dac263f6ee9fb9cc83437c5904183b55ceb", size = 10713007, upload-time = "2024-10-04T13:40:05.384Z" }, - { url = "https://files.pythonhosted.org/packages/be/27/6f7161d90320a389695e32b6ebdbfbedde28ccbf52451e4b723d7ce744ad/ruff-0.6.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:12edd2af0c60fa61ff31cefb90aef4288ac4d372b4962c2864aeea3a1a2460c0", size = 10274594, upload-time = "2024-10-04T13:40:08.801Z" }, - { url = "https://files.pythonhosted.org/packages/00/52/dc311775e7b5f5b19831563cb1572ecce63e62681bccc609867711fae317/ruff-0.6.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:55bb01caeaf3a60b2b2bba07308a02fca6ab56233302406ed5245180a05c5625", size = 10608024, upload-time = "2024-10-04T13:40:11.923Z" }, - { url = "https://files.pythonhosted.org/packages/98/b6/be0a1ddcbac65a30c985cf7224c4fce786ba2c51e7efeb5178fe410ed3cf/ruff-0.6.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:925d26471fa24b0ce5a6cdfab1bb526fb4159952385f386bdcc643813d472039", size = 10982085, upload-time = "2024-10-04T13:40:15.539Z" }, - { url = "https://files.pythonhosted.org/packages/bb/a4/c84bc13d0b573cf7bb7d17b16d6d29f84267c92d79b2f478d4ce322e8e72/ruff-0.6.9-py3-none-win32.whl", hash = "sha256:eb61ec9bdb2506cffd492e05ac40e5bc6284873aceb605503d8494180d6fc84d", size = 8522088, upload-time = "2024-10-04T13:40:19.168Z" }, - { url = "https://files.pythonhosted.org/packages/74/be/fc352bd8ca40daae8740b54c1c3e905a7efe470d420a268cd62150248c91/ruff-0.6.9-py3-none-win_amd64.whl", hash = "sha256:785d31851c1ae91f45b3d8fe23b8ae4b5170089021fbb42402d811135f0b7117", size = 9359275, upload-time = "2024-10-04T13:40:22.852Z" }, - { url = "https://files.pythonhosted.org/packages/3e/14/fd026bc74ded05e2351681545a5f626e78ef831f8edce064d61acd2e6ec7/ruff-0.6.9-py3-none-win_arm64.whl", hash = "sha256:a9641e31476d601f83cd602608739a0840e348bda93fec9f1ee816f8b6798b93", size = 8679879, upload-time = "2024-10-04T13:40:25.797Z" }, + { url = "https://files.pythonhosted.org/packages/74/b6/2098d0126d2d3318fd5bec3ad40d06c25d377d95749f7a0c5af17129b3b1/ruff-0.12.2-py3-none-linux_armv6l.whl", hash = "sha256:093ea2b221df1d2b8e7ad92fc6ffdca40a2cb10d8564477a987b44fd4008a7be", size = 10369761, upload-time = "2025-07-03T16:39:38.847Z" }, + { url = "https://files.pythonhosted.org/packages/b1/4b/5da0142033dbe155dc598cfb99262d8ee2449d76920ea92c4eeb9547c208/ruff-0.12.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:09e4cf27cc10f96b1708100fa851e0daf21767e9709e1649175355280e0d950e", size = 11155659, upload-time = "2025-07-03T16:39:42.294Z" }, + { url = "https://files.pythonhosted.org/packages/3e/21/967b82550a503d7c5c5c127d11c935344b35e8c521f52915fc858fb3e473/ruff-0.12.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:8ae64755b22f4ff85e9c52d1f82644abd0b6b6b6deedceb74bd71f35c24044cc", size = 10537769, upload-time = "2025-07-03T16:39:44.75Z" }, + { url = "https://files.pythonhosted.org/packages/33/91/00cff7102e2ec71a4890fb7ba1803f2cdb122d82787c7d7cf8041fe8cbc1/ruff-0.12.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3eb3a6b2db4d6e2c77e682f0b988d4d61aff06860158fdb413118ca133d57922", size = 10717602, upload-time = "2025-07-03T16:39:47.652Z" }, + { url = "https://files.pythonhosted.org/packages/9b/eb/928814daec4e1ba9115858adcda44a637fb9010618721937491e4e2283b8/ruff-0.12.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:73448de992d05517170fc37169cbca857dfeaeaa8c2b9be494d7bcb0d36c8f4b", size = 10198772, upload-time = "2025-07-03T16:39:49.641Z" }, + { url = "https://files.pythonhosted.org/packages/50/fa/f15089bc20c40f4f72334f9145dde55ab2b680e51afb3b55422effbf2fb6/ruff-0.12.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b8b94317cbc2ae4a2771af641739f933934b03555e51515e6e021c64441532d", size = 11845173, upload-time = "2025-07-03T16:39:52.069Z" }, + { url = "https://files.pythonhosted.org/packages/43/9f/1f6f98f39f2b9302acc161a4a2187b1e3a97634fe918a8e731e591841cf4/ruff-0.12.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:45fc42c3bf1d30d2008023a0a9a0cfb06bf9835b147f11fe0679f21ae86d34b1", size = 12553002, upload-time = "2025-07-03T16:39:54.551Z" }, + { url = "https://files.pythonhosted.org/packages/d8/70/08991ac46e38ddd231c8f4fd05ef189b1b94be8883e8c0c146a025c20a19/ruff-0.12.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce48f675c394c37e958bf229fb5c1e843e20945a6d962cf3ea20b7a107dcd9f4", size = 12171330, upload-time = "2025-07-03T16:39:57.55Z" }, + { url = "https://files.pythonhosted.org/packages/88/a9/5a55266fec474acfd0a1c73285f19dd22461d95a538f29bba02edd07a5d9/ruff-0.12.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:793d8859445ea47591272021a81391350205a4af65a9392401f418a95dfb75c9", size = 11774717, upload-time = "2025-07-03T16:39:59.78Z" }, + { url = "https://files.pythonhosted.org/packages/87/e5/0c270e458fc73c46c0d0f7cf970bb14786e5fdb88c87b5e423a4bd65232b/ruff-0.12.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6932323db80484dda89153da3d8e58164d01d6da86857c79f1961934354992da", size = 11646659, upload-time = "2025-07-03T16:40:01.934Z" }, + { url = "https://files.pythonhosted.org/packages/b7/b6/45ab96070c9752af37f0be364d849ed70e9ccede07675b0ec4e3ef76b63b/ruff-0.12.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6aa7e623a3a11538108f61e859ebf016c4f14a7e6e4eba1980190cacb57714ce", size = 10604012, upload-time = "2025-07-03T16:40:04.363Z" }, + { url = "https://files.pythonhosted.org/packages/86/91/26a6e6a424eb147cc7627eebae095cfa0b4b337a7c1c413c447c9ebb72fd/ruff-0.12.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:2a4a20aeed74671b2def096bdf2eac610c7d8ffcbf4fb0e627c06947a1d7078d", size = 10176799, upload-time = "2025-07-03T16:40:06.514Z" }, + { url = "https://files.pythonhosted.org/packages/f5/0c/9f344583465a61c8918a7cda604226e77b2c548daf8ef7c2bfccf2b37200/ruff-0.12.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:71a4c550195612f486c9d1f2b045a600aeba851b298c667807ae933478fcef04", size = 11241507, upload-time = "2025-07-03T16:40:08.708Z" }, + { url = "https://files.pythonhosted.org/packages/1c/b7/99c34ded8fb5f86c0280278fa89a0066c3760edc326e935ce0b1550d315d/ruff-0.12.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:4987b8f4ceadf597c927beee65a5eaf994c6e2b631df963f86d8ad1bdea99342", size = 11717609, upload-time = "2025-07-03T16:40:10.836Z" }, + { url = "https://files.pythonhosted.org/packages/51/de/8589fa724590faa057e5a6d171e7f2f6cffe3287406ef40e49c682c07d89/ruff-0.12.2-py3-none-win32.whl", hash = "sha256:369ffb69b70cd55b6c3fc453b9492d98aed98062db9fec828cdfd069555f5f1a", size = 10523823, upload-time = "2025-07-03T16:40:13.203Z" }, + { url = "https://files.pythonhosted.org/packages/94/47/8abf129102ae4c90cba0c2199a1a9b0fa896f6f806238d6f8c14448cc748/ruff-0.12.2-py3-none-win_amd64.whl", hash = "sha256:dca8a3b6d6dc9810ed8f328d406516bf4d660c00caeaef36eb831cf4871b0639", size = 11629831, upload-time = "2025-07-03T16:40:15.478Z" }, + { url = "https://files.pythonhosted.org/packages/e2/1f/72d2946e3cc7456bb837e88000eb3437e55f80db339c840c04015a11115d/ruff-0.12.2-py3-none-win_arm64.whl", hash = "sha256:48d6c6bfb4761df68bc05ae630e24f506755e702d4fb08f08460be778c7ccb12", size = 10735334, upload-time = "2025-07-03T16:40:17.677Z" }, ] [[package]] @@ -1185,23 +1228,24 @@ wheels = [ [[package]] name = "starlette" -version = "0.46.2" +version = "0.47.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio", marker = "python_full_version >= '3.11'" }, + { name = "typing-extensions", marker = "python_full_version >= '3.11' and python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ce/20/08dfcd9c983f6a6f4a1000d934b9e6d626cff8d2eeb77a89a68eef20a2b7/starlette-0.46.2.tar.gz", hash = "sha256:7f7361f34eed179294600af672f565727419830b54b7b084efe44bb82d2fccd5", size = 2580846, upload-time = "2025-04-13T13:56:17.942Z" } +sdist = { url = "https://files.pythonhosted.org/packages/0a/69/662169fdb92fb96ec3eaee218cf540a629d629c86d7993d9651226a6789b/starlette-0.47.1.tar.gz", hash = "sha256:aef012dd2b6be325ffa16698f9dc533614fb1cebd593a906b90dc1025529a79b", size = 2583072, upload-time = "2025-06-21T04:03:17.337Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8b/0c/9d30a4ebeb6db2b25a841afbb80f6ef9a854fc3b41be131d249a977b4959/starlette-0.46.2-py3-none-any.whl", hash = "sha256:595633ce89f8ffa71a015caed34a5b2dc1c0cdb3f0f1fbd1e69339cf2abeec35", size = 72037, upload-time = "2025-04-13T13:56:16.21Z" }, + { url = "https://files.pythonhosted.org/packages/82/95/38ef0cd7fa11eaba6a99b3c4f5ac948d8bc6ff199aabd327a29cc000840c/starlette-0.47.1-py3-none-any.whl", hash = "sha256:5e11c9f5c7c3f24959edbf2dffdc01bba860228acf657129467d8a7468591527", size = 72747, upload-time = "2025-06-21T04:03:15.705Z" }, ] [[package]] name = "structlog" -version = "25.3.0" +version = "25.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ff/6a/b0b6d440e429d2267076c4819300d9929563b1da959cf1f68afbcd69fe45/structlog-25.3.0.tar.gz", hash = "sha256:8dab497e6f6ca962abad0c283c46744185e0c9ba900db52a423cb6db99f7abeb", size = 1367514, upload-time = "2025-04-25T16:00:39.167Z" } +sdist = { url = "https://files.pythonhosted.org/packages/79/b9/6e672db4fec07349e7a8a8172c1a6ae235c58679ca29c3f86a61b5e59ff3/structlog-25.4.0.tar.gz", hash = "sha256:186cd1b0a8ae762e29417095664adf1d6a31702160a46dacb7796ea82f7409e4", size = 1369138, upload-time = "2025-06-02T08:21:12.971Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f5/52/7a2c7a317b254af857464da3d60a0d3730c44f912f8c510c76a738a207fd/structlog-25.3.0-py3-none-any.whl", hash = "sha256:a341f5524004c158498c3127eecded091eb67d3a611e7a3093deca30db06e172", size = 68240, upload-time = "2025-04-25T16:00:37.295Z" }, + { url = "https://files.pythonhosted.org/packages/a0/4a/97ee6973e3a73c74c8120d59829c3861ea52210667ec3e7a16045c62b64d/structlog-25.4.0-py3-none-any.whl", hash = "sha256:fe809ff5c27e557d14e613f45ca441aabda051d119ee5a0102aaba6ce40eed2c", size = 68720, upload-time = "2025-06-02T08:21:11.43Z" }, ] [[package]] @@ -1263,45 +1307,45 @@ wheels = [ [[package]] name = "typing-extensions" -version = "4.13.2" +version = "4.14.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f6/37/23083fcd6e35492953e8d2aaaa68b860eb422b34627b13f2ce3eb6106061/typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef", size = 106967, upload-time = "2025-04-10T14:19:05.416Z" } +sdist = { url = "https://files.pythonhosted.org/packages/98/5a/da40306b885cc8c09109dc2e1abd358d5684b1425678151cdaed4731c822/typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36", size = 107673, upload-time = "2025-07-04T13:28:34.16Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806, upload-time = "2025-04-10T14:19:03.967Z" }, + { url = "https://files.pythonhosted.org/packages/b5/00/d631e67a838026495268c2f6884f3711a15a9a2a96cd244fdaea53b823fb/typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76", size = 43906, upload-time = "2025-07-04T13:28:32.743Z" }, ] [[package]] name = "typing-inspection" -version = "0.4.0" +version = "0.4.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions", marker = "python_full_version >= '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/82/5c/e6082df02e215b846b4b8c0b887a64d7d08ffaba30605502639d44c06b82/typing_inspection-0.4.0.tar.gz", hash = "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122", size = 76222, upload-time = "2025-02-25T17:27:59.638Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/b1/0c11f5058406b3af7609f121aaa6b609744687f1d158b3c3a5bf4cc94238/typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28", size = 75726, upload-time = "2025-05-21T18:55:23.885Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/31/08/aa4fdfb71f7de5176385bd9e90852eaf6b5d622735020ad600f2bab54385/typing_inspection-0.4.0-py3-none-any.whl", hash = "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f", size = 14125, upload-time = "2025-02-25T17:27:57.754Z" }, + { url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552, upload-time = "2025-05-21T18:55:22.152Z" }, ] [[package]] name = "urllib3" -version = "2.4.0" +version = "2.5.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8a/78/16493d9c386d8e60e442a35feac5e00f0913c0f4b7c217c11e8ec2ff53e0/urllib3-2.4.0.tar.gz", hash = "sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466", size = 390672, upload-time = "2025-04-10T15:23:39.232Z" } +sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6b/11/cc635220681e93a0183390e26485430ca2c7b5f9d33b15c74c2861cb8091/urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813", size = 128680, upload-time = "2025-04-10T15:23:37.377Z" }, + { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" }, ] [[package]] name = "uvicorn" -version = "0.34.2" +version = "0.35.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "click", marker = "python_full_version >= '3.11'" }, + { name = "click", version = "8.2.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "h11", marker = "python_full_version >= '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a6/ae/9bbb19b9e1c450cf9ecaef06463e40234d98d95bf572fab11b4f19ae5ded/uvicorn-0.34.2.tar.gz", hash = "sha256:0e929828f6186353a80b58ea719861d2629d766293b6d19baf086ba31d4f3328", size = 76815, upload-time = "2025-04-19T06:02:50.101Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5e/42/e0e305207bb88c6b8d3061399c6a961ffe5fbb7e2aa63c9234df7259e9cd/uvicorn-0.35.0.tar.gz", hash = "sha256:bc662f087f7cf2ce11a1d7fd70b90c9f98ef2e2831556dd078d131b96cc94a01", size = 78473, upload-time = "2025-06-28T16:15:46.058Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b1/4b/4cef6ce21a2aaca9d852a6e84ef4f135d99fcd74fa75105e2fc0c8308acd/uvicorn-0.34.2-py3-none-any.whl", hash = "sha256:deb49af569084536d269fe0a6d67e3754f104cf03aba7c11c40f01aadf33c403", size = 62483, upload-time = "2025-04-19T06:02:48.42Z" }, + { url = "https://files.pythonhosted.org/packages/d2/e2/dc81b1bd1dcfe91735810265e9d26bc8ec5da45b4c0f6237e286819194c3/uvicorn-0.35.0-py3-none-any.whl", hash = "sha256:197535216b25ff9b785e29a0b79199f55222193d47f820816e7da751e9bc8d4a", size = 66406, upload-time = "2025-06-28T16:15:44.816Z" }, ] [[package]] @@ -1343,83 +1387,118 @@ wheels = [ [[package]] name = "watchfiles" -version = "1.0.5" +version = "1.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio", marker = "python_full_version >= '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/03/e2/8ed598c42057de7aa5d97c472254af4906ff0a59a66699d426fc9ef795d7/watchfiles-1.0.5.tar.gz", hash = "sha256:b7529b5dcc114679d43827d8c35a07c493ad6f083633d573d81c660abc5979e9", size = 94537, upload-time = "2025-04-08T10:36:26.722Z" } +sdist = { url = "https://files.pythonhosted.org/packages/2a/9a/d451fcc97d029f5812e898fd30a53fd8c15c7bbd058fd75cfc6beb9bd761/watchfiles-1.1.0.tar.gz", hash = "sha256:693ed7ec72cbfcee399e92c895362b6e66d63dac6b91e2c11ae03d10d503e575", size = 94406, upload-time = "2025-06-15T19:06:59.42Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/af/4d/d02e6ea147bb7fff5fd109c694a95109612f419abed46548a930e7f7afa3/watchfiles-1.0.5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:5c40fe7dd9e5f81e0847b1ea64e1f5dd79dd61afbedb57759df06767ac719b40", size = 405632, upload-time = "2025-04-08T10:34:41.832Z" }, - { url = "https://files.pythonhosted.org/packages/60/31/9ee50e29129d53a9a92ccf1d3992751dc56fc3c8f6ee721be1c7b9c81763/watchfiles-1.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8c0db396e6003d99bb2d7232c957b5f0b5634bbd1b24e381a5afcc880f7373fb", size = 395734, upload-time = "2025-04-08T10:34:44.236Z" }, - { url = "https://files.pythonhosted.org/packages/ad/8c/759176c97195306f028024f878e7f1c776bda66ccc5c68fa51e699cf8f1d/watchfiles-1.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b551d4fb482fc57d852b4541f911ba28957d051c8776e79c3b4a51eb5e2a1b11", size = 455008, upload-time = "2025-04-08T10:34:45.617Z" }, - { url = "https://files.pythonhosted.org/packages/55/1a/5e977250c795ee79a0229e3b7f5e3a1b664e4e450756a22da84d2f4979fe/watchfiles-1.0.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:830aa432ba5c491d52a15b51526c29e4a4b92bf4f92253787f9726fe01519487", size = 459029, upload-time = "2025-04-08T10:34:46.814Z" }, - { url = "https://files.pythonhosted.org/packages/e6/17/884cf039333605c1d6e296cf5be35fad0836953c3dfd2adb71b72f9dbcd0/watchfiles-1.0.5-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a16512051a822a416b0d477d5f8c0e67b67c1a20d9acecb0aafa3aa4d6e7d256", size = 488916, upload-time = "2025-04-08T10:34:48.571Z" }, - { url = "https://files.pythonhosted.org/packages/ef/e0/bcb6e64b45837056c0a40f3a2db3ef51c2ced19fda38484fa7508e00632c/watchfiles-1.0.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bfe0cbc787770e52a96c6fda6726ace75be7f840cb327e1b08d7d54eadc3bc85", size = 523763, upload-time = "2025-04-08T10:34:50.268Z" }, - { url = "https://files.pythonhosted.org/packages/24/e9/f67e9199f3bb35c1837447ecf07e9830ec00ff5d35a61e08c2cd67217949/watchfiles-1.0.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d363152c5e16b29d66cbde8fa614f9e313e6f94a8204eaab268db52231fe5358", size = 502891, upload-time = "2025-04-08T10:34:51.419Z" }, - { url = "https://files.pythonhosted.org/packages/23/ed/a6cf815f215632f5c8065e9c41fe872025ffea35aa1f80499f86eae922db/watchfiles-1.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ee32c9a9bee4d0b7bd7cbeb53cb185cf0b622ac761efaa2eba84006c3b3a614", size = 454921, upload-time = "2025-04-08T10:34:52.67Z" }, - { url = "https://files.pythonhosted.org/packages/92/4c/e14978599b80cde8486ab5a77a821e8a982ae8e2fcb22af7b0886a033ec8/watchfiles-1.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:29c7fd632ccaf5517c16a5188e36f6612d6472ccf55382db6c7fe3fcccb7f59f", size = 631422, upload-time = "2025-04-08T10:34:53.985Z" }, - { url = "https://files.pythonhosted.org/packages/b2/1a/9263e34c3458f7614b657f974f4ee61fd72f58adce8b436e16450e054efd/watchfiles-1.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8e637810586e6fe380c8bc1b3910accd7f1d3a9a7262c8a78d4c8fb3ba6a2b3d", size = 625675, upload-time = "2025-04-08T10:34:55.173Z" }, - { url = "https://files.pythonhosted.org/packages/96/1f/1803a18bd6ab04a0766386a19bcfe64641381a04939efdaa95f0e3b0eb58/watchfiles-1.0.5-cp310-cp310-win32.whl", hash = "sha256:cd47d063fbeabd4c6cae1d4bcaa38f0902f8dc5ed168072874ea11d0c7afc1ff", size = 277921, upload-time = "2025-04-08T10:34:56.318Z" }, - { url = "https://files.pythonhosted.org/packages/c2/3b/29a89de074a7d6e8b4dc67c26e03d73313e4ecf0d6e97e942a65fa7c195e/watchfiles-1.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:86c0df05b47a79d80351cd179893f2f9c1b1cae49d96e8b3290c7f4bd0ca0a92", size = 291526, upload-time = "2025-04-08T10:34:57.95Z" }, - { url = "https://files.pythonhosted.org/packages/39/f4/41b591f59021786ef517e1cdc3b510383551846703e03f204827854a96f8/watchfiles-1.0.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:237f9be419e977a0f8f6b2e7b0475ababe78ff1ab06822df95d914a945eac827", size = 405336, upload-time = "2025-04-08T10:34:59.359Z" }, - { url = "https://files.pythonhosted.org/packages/ae/06/93789c135be4d6d0e4f63e96eea56dc54050b243eacc28439a26482b5235/watchfiles-1.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0da39ff917af8b27a4bdc5a97ac577552a38aac0d260a859c1517ea3dc1a7c4", size = 395977, upload-time = "2025-04-08T10:35:00.522Z" }, - { url = "https://files.pythonhosted.org/packages/d2/db/1cd89bd83728ca37054512d4d35ab69b5f12b8aa2ac9be3b0276b3bf06cc/watchfiles-1.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cfcb3952350e95603f232a7a15f6c5f86c5375e46f0bd4ae70d43e3e063c13d", size = 455232, upload-time = "2025-04-08T10:35:01.698Z" }, - { url = "https://files.pythonhosted.org/packages/40/90/d8a4d44ffe960517e487c9c04f77b06b8abf05eb680bed71c82b5f2cad62/watchfiles-1.0.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:68b2dddba7a4e6151384e252a5632efcaa9bc5d1c4b567f3cb621306b2ca9f63", size = 459151, upload-time = "2025-04-08T10:35:03.358Z" }, - { url = "https://files.pythonhosted.org/packages/6c/da/267a1546f26465dead1719caaba3ce660657f83c9d9c052ba98fb8856e13/watchfiles-1.0.5-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:95cf944fcfc394c5f9de794ce581914900f82ff1f855326f25ebcf24d5397418", size = 489054, upload-time = "2025-04-08T10:35:04.561Z" }, - { url = "https://files.pythonhosted.org/packages/b1/31/33850dfd5c6efb6f27d2465cc4c6b27c5a6f5ed53c6fa63b7263cf5f60f6/watchfiles-1.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ecf6cd9f83d7c023b1aba15d13f705ca7b7d38675c121f3cc4a6e25bd0857ee9", size = 523955, upload-time = "2025-04-08T10:35:05.786Z" }, - { url = "https://files.pythonhosted.org/packages/09/84/b7d7b67856efb183a421f1416b44ca975cb2ea6c4544827955dfb01f7dc2/watchfiles-1.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:852de68acd6212cd6d33edf21e6f9e56e5d98c6add46f48244bd479d97c967c6", size = 502234, upload-time = "2025-04-08T10:35:07.187Z" }, - { url = "https://files.pythonhosted.org/packages/71/87/6dc5ec6882a2254cfdd8b0718b684504e737273903b65d7338efaba08b52/watchfiles-1.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5730f3aa35e646103b53389d5bc77edfbf578ab6dab2e005142b5b80a35ef25", size = 454750, upload-time = "2025-04-08T10:35:08.859Z" }, - { url = "https://files.pythonhosted.org/packages/3d/6c/3786c50213451a0ad15170d091570d4a6554976cf0df19878002fc96075a/watchfiles-1.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:18b3bd29954bc4abeeb4e9d9cf0b30227f0f206c86657674f544cb032296acd5", size = 631591, upload-time = "2025-04-08T10:35:10.64Z" }, - { url = "https://files.pythonhosted.org/packages/1b/b3/1427425ade4e359a0deacce01a47a26024b2ccdb53098f9d64d497f6684c/watchfiles-1.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ba5552a1b07c8edbf197055bc9d518b8f0d98a1c6a73a293bc0726dce068ed01", size = 625370, upload-time = "2025-04-08T10:35:12.412Z" }, - { url = "https://files.pythonhosted.org/packages/15/ba/f60e053b0b5b8145d682672024aa91370a29c5c921a88977eb565de34086/watchfiles-1.0.5-cp311-cp311-win32.whl", hash = "sha256:2f1fefb2e90e89959447bc0420fddd1e76f625784340d64a2f7d5983ef9ad246", size = 277791, upload-time = "2025-04-08T10:35:13.719Z" }, - { url = "https://files.pythonhosted.org/packages/50/ed/7603c4e164225c12c0d4e8700b64bb00e01a6c4eeea372292a3856be33a4/watchfiles-1.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:b6e76ceb1dd18c8e29c73f47d41866972e891fc4cc7ba014f487def72c1cf096", size = 291622, upload-time = "2025-04-08T10:35:15.071Z" }, - { url = "https://files.pythonhosted.org/packages/a2/c2/99bb7c96b4450e36877fde33690ded286ff555b5a5c1d925855d556968a1/watchfiles-1.0.5-cp311-cp311-win_arm64.whl", hash = "sha256:266710eb6fddc1f5e51843c70e3bebfb0f5e77cf4f27129278c70554104d19ed", size = 283699, upload-time = "2025-04-08T10:35:16.732Z" }, - { url = "https://files.pythonhosted.org/packages/2a/8c/4f0b9bdb75a1bfbd9c78fad7d8854369283f74fe7cf03eb16be77054536d/watchfiles-1.0.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:b5eb568c2aa6018e26da9e6c86f3ec3fd958cee7f0311b35c2630fa4217d17f2", size = 401511, upload-time = "2025-04-08T10:35:17.956Z" }, - { url = "https://files.pythonhosted.org/packages/dc/4e/7e15825def77f8bd359b6d3f379f0c9dac4eb09dd4ddd58fd7d14127179c/watchfiles-1.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0a04059f4923ce4e856b4b4e5e783a70f49d9663d22a4c3b3298165996d1377f", size = 392715, upload-time = "2025-04-08T10:35:19.202Z" }, - { url = "https://files.pythonhosted.org/packages/58/65/b72fb817518728e08de5840d5d38571466c1b4a3f724d190cec909ee6f3f/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e380c89983ce6e6fe2dd1e1921b9952fb4e6da882931abd1824c092ed495dec", size = 454138, upload-time = "2025-04-08T10:35:20.586Z" }, - { url = "https://files.pythonhosted.org/packages/3e/a4/86833fd2ea2e50ae28989f5950b5c3f91022d67092bfec08f8300d8b347b/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fe43139b2c0fdc4a14d4f8d5b5d967f7a2777fd3d38ecf5b1ec669b0d7e43c21", size = 458592, upload-time = "2025-04-08T10:35:21.87Z" }, - { url = "https://files.pythonhosted.org/packages/38/7e/42cb8df8be9a37e50dd3a818816501cf7a20d635d76d6bd65aae3dbbff68/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee0822ce1b8a14fe5a066f93edd20aada932acfe348bede8aa2149f1a4489512", size = 487532, upload-time = "2025-04-08T10:35:23.143Z" }, - { url = "https://files.pythonhosted.org/packages/fc/fd/13d26721c85d7f3df6169d8b495fcac8ab0dc8f0945ebea8845de4681dab/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a0dbcb1c2d8f2ab6e0a81c6699b236932bd264d4cef1ac475858d16c403de74d", size = 522865, upload-time = "2025-04-08T10:35:24.702Z" }, - { url = "https://files.pythonhosted.org/packages/a1/0d/7f9ae243c04e96c5455d111e21b09087d0eeaf9a1369e13a01c7d3d82478/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a2014a2b18ad3ca53b1f6c23f8cd94a18ce930c1837bd891262c182640eb40a6", size = 499887, upload-time = "2025-04-08T10:35:25.969Z" }, - { url = "https://files.pythonhosted.org/packages/8e/0f/a257766998e26aca4b3acf2ae97dff04b57071e991a510857d3799247c67/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10f6ae86d5cb647bf58f9f655fcf577f713915a5d69057a0371bc257e2553234", size = 454498, upload-time = "2025-04-08T10:35:27.353Z" }, - { url = "https://files.pythonhosted.org/packages/81/79/8bf142575a03e0af9c3d5f8bcae911ee6683ae93a625d349d4ecf4c8f7df/watchfiles-1.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1a7bac2bde1d661fb31f4d4e8e539e178774b76db3c2c17c4bb3e960a5de07a2", size = 630663, upload-time = "2025-04-08T10:35:28.685Z" }, - { url = "https://files.pythonhosted.org/packages/f1/80/abe2e79f610e45c63a70d271caea90c49bbf93eb00fa947fa9b803a1d51f/watchfiles-1.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ab626da2fc1ac277bbf752446470b367f84b50295264d2d313e28dc4405d663", size = 625410, upload-time = "2025-04-08T10:35:30.42Z" }, - { url = "https://files.pythonhosted.org/packages/91/6f/bc7fbecb84a41a9069c2c6eb6319f7f7df113adf113e358c57fc1aff7ff5/watchfiles-1.0.5-cp312-cp312-win32.whl", hash = "sha256:9f4571a783914feda92018ef3901dab8caf5b029325b5fe4558c074582815249", size = 277965, upload-time = "2025-04-08T10:35:32.023Z" }, - { url = "https://files.pythonhosted.org/packages/99/a5/bf1c297ea6649ec59e935ab311f63d8af5faa8f0b86993e3282b984263e3/watchfiles-1.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:360a398c3a19672cf93527f7e8d8b60d8275119c5d900f2e184d32483117a705", size = 291693, upload-time = "2025-04-08T10:35:33.225Z" }, - { url = "https://files.pythonhosted.org/packages/7f/7b/fd01087cc21db5c47e5beae507b87965db341cce8a86f9eb12bf5219d4e0/watchfiles-1.0.5-cp312-cp312-win_arm64.whl", hash = "sha256:1a2902ede862969077b97523987c38db28abbe09fb19866e711485d9fbf0d417", size = 283287, upload-time = "2025-04-08T10:35:34.568Z" }, - { url = "https://files.pythonhosted.org/packages/c7/62/435766874b704f39b2fecd8395a29042db2b5ec4005bd34523415e9bd2e0/watchfiles-1.0.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:0b289572c33a0deae62daa57e44a25b99b783e5f7aed81b314232b3d3c81a11d", size = 401531, upload-time = "2025-04-08T10:35:35.792Z" }, - { url = "https://files.pythonhosted.org/packages/6e/a6/e52a02c05411b9cb02823e6797ef9bbba0bfaf1bb627da1634d44d8af833/watchfiles-1.0.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a056c2f692d65bf1e99c41045e3bdcaea3cb9e6b5a53dcaf60a5f3bd95fc9763", size = 392417, upload-time = "2025-04-08T10:35:37.048Z" }, - { url = "https://files.pythonhosted.org/packages/3f/53/c4af6819770455932144e0109d4854437769672d7ad897e76e8e1673435d/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9dca99744991fc9850d18015c4f0438865414e50069670f5f7eee08340d8b40", size = 453423, upload-time = "2025-04-08T10:35:38.357Z" }, - { url = "https://files.pythonhosted.org/packages/cb/d1/8e88df58bbbf819b8bc5cfbacd3c79e01b40261cad0fc84d1e1ebd778a07/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:894342d61d355446d02cd3988a7326af344143eb33a2fd5d38482a92072d9563", size = 458185, upload-time = "2025-04-08T10:35:39.708Z" }, - { url = "https://files.pythonhosted.org/packages/ff/70/fffaa11962dd5429e47e478a18736d4e42bec42404f5ee3b92ef1b87ad60/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ab44e1580924d1ffd7b3938e02716d5ad190441965138b4aa1d1f31ea0877f04", size = 486696, upload-time = "2025-04-08T10:35:41.469Z" }, - { url = "https://files.pythonhosted.org/packages/39/db/723c0328e8b3692d53eb273797d9a08be6ffb1d16f1c0ba2bdbdc2a3852c/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d6f9367b132078b2ceb8d066ff6c93a970a18c3029cea37bfd7b2d3dd2e5db8f", size = 522327, upload-time = "2025-04-08T10:35:43.289Z" }, - { url = "https://files.pythonhosted.org/packages/cd/05/9fccc43c50c39a76b68343484b9da7b12d42d0859c37c61aec018c967a32/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2e55a9b162e06e3f862fb61e399fe9f05d908d019d87bf5b496a04ef18a970a", size = 499741, upload-time = "2025-04-08T10:35:44.574Z" }, - { url = "https://files.pythonhosted.org/packages/23/14/499e90c37fa518976782b10a18b18db9f55ea73ca14641615056f8194bb3/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0125f91f70e0732a9f8ee01e49515c35d38ba48db507a50c5bdcad9503af5827", size = 453995, upload-time = "2025-04-08T10:35:46.336Z" }, - { url = "https://files.pythonhosted.org/packages/61/d9/f75d6840059320df5adecd2c687fbc18960a7f97b55c300d20f207d48aef/watchfiles-1.0.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:13bb21f8ba3248386337c9fa51c528868e6c34a707f729ab041c846d52a0c69a", size = 629693, upload-time = "2025-04-08T10:35:48.161Z" }, - { url = "https://files.pythonhosted.org/packages/fc/17/180ca383f5061b61406477218c55d66ec118e6c0c51f02d8142895fcf0a9/watchfiles-1.0.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:839ebd0df4a18c5b3c1b890145b5a3f5f64063c2a0d02b13c76d78fe5de34936", size = 624677, upload-time = "2025-04-08T10:35:49.65Z" }, - { url = "https://files.pythonhosted.org/packages/bf/15/714d6ef307f803f236d69ee9d421763707899d6298d9f3183e55e366d9af/watchfiles-1.0.5-cp313-cp313-win32.whl", hash = "sha256:4a8ec1e4e16e2d5bafc9ba82f7aaecfeec990ca7cd27e84fb6f191804ed2fcfc", size = 277804, upload-time = "2025-04-08T10:35:51.093Z" }, - { url = "https://files.pythonhosted.org/packages/a8/b4/c57b99518fadf431f3ef47a610839e46e5f8abf9814f969859d1c65c02c7/watchfiles-1.0.5-cp313-cp313-win_amd64.whl", hash = "sha256:f436601594f15bf406518af922a89dcaab416568edb6f65c4e5bbbad1ea45c11", size = 291087, upload-time = "2025-04-08T10:35:52.458Z" }, - { url = "https://files.pythonhosted.org/packages/c5/95/94f3dd15557f5553261e407551c5e4d340e50161c55aa30812c79da6cb04/watchfiles-1.0.5-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:2cfb371be97d4db374cba381b9f911dd35bb5f4c58faa7b8b7106c8853e5d225", size = 405686, upload-time = "2025-04-08T10:35:53.86Z" }, - { url = "https://files.pythonhosted.org/packages/f4/aa/b99e968153f8b70159ecca7b3daf46a6f46d97190bdaa3a449ad31b921d7/watchfiles-1.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a3904d88955fda461ea2531fcf6ef73584ca921415d5cfa44457a225f4a42bc1", size = 396047, upload-time = "2025-04-08T10:35:55.232Z" }, - { url = "https://files.pythonhosted.org/packages/23/cb/90d3d760ad4bc7290e313fb9236c7d60598627a25a5a72764e48d9652064/watchfiles-1.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2b7a21715fb12274a71d335cff6c71fe7f676b293d322722fe708a9ec81d91f5", size = 456081, upload-time = "2025-04-08T10:35:57.102Z" }, - { url = "https://files.pythonhosted.org/packages/3e/65/79c6cebe5bcb695cdac145946ad5a09b9f66762549e82fb2d064ea960c95/watchfiles-1.0.5-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dfd6ae1c385ab481766b3c61c44aca2b3cd775f6f7c0fa93d979ddec853d29d5", size = 459838, upload-time = "2025-04-08T10:35:58.867Z" }, - { url = "https://files.pythonhosted.org/packages/3f/84/699f52632cdaa777f6df7f6f1cc02a23a75b41071b7e6765b9a412495f61/watchfiles-1.0.5-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b659576b950865fdad31fa491d31d37cf78b27113a7671d39f919828587b429b", size = 489753, upload-time = "2025-04-08T10:36:00.237Z" }, - { url = "https://files.pythonhosted.org/packages/25/68/3241f82ad414fd969de6bf3a93805682e5eb589aeab510322f2aa14462f8/watchfiles-1.0.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1909e0a9cd95251b15bff4261de5dd7550885bd172e3536824bf1cf6b121e200", size = 525015, upload-time = "2025-04-08T10:36:02.159Z" }, - { url = "https://files.pythonhosted.org/packages/85/c4/30d879e252f52b01660f545c193e6b81c48aac2e0eeec71263af3add905b/watchfiles-1.0.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:832ccc221927c860e7286c55c9b6ebcc0265d5e072f49c7f6456c7798d2b39aa", size = 503816, upload-time = "2025-04-08T10:36:03.869Z" }, - { url = "https://files.pythonhosted.org/packages/6b/7d/fa34750f6f4b1a70d96fa6b685fe2948d01e3936328ea528f182943eb373/watchfiles-1.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85fbb6102b3296926d0c62cfc9347f6237fb9400aecd0ba6bbda94cae15f2b3b", size = 456137, upload-time = "2025-04-08T10:36:05.226Z" }, - { url = "https://files.pythonhosted.org/packages/8f/0c/a1569709aaeccb1dd74b0dd304d0de29e3ea1fdf11e08c78f489628f9ebb/watchfiles-1.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:15ac96dd567ad6c71c71f7b2c658cb22b7734901546cd50a475128ab557593ca", size = 632673, upload-time = "2025-04-08T10:36:06.752Z" }, - { url = "https://files.pythonhosted.org/packages/90/b6/645eaaca11f3ac625cf3b6e008e543acf0bf2581f68b5e205a13b05618b6/watchfiles-1.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4b6227351e11c57ae997d222e13f5b6f1f0700d84b8c52304e8675d33a808382", size = 626659, upload-time = "2025-04-08T10:36:08.18Z" }, - { url = "https://files.pythonhosted.org/packages/3a/c4/e741d9b92b0a2c74b976ff78bbc9a1276b4d904c590878e8fe0ec9fecca5/watchfiles-1.0.5-cp39-cp39-win32.whl", hash = "sha256:974866e0db748ebf1eccab17862bc0f0303807ed9cda465d1324625b81293a18", size = 278471, upload-time = "2025-04-08T10:36:10.546Z" }, - { url = "https://files.pythonhosted.org/packages/50/1b/36b0cb6add99105f78931994b30bc1dd24118c0e659ab6a3ffe0dd8734d4/watchfiles-1.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:9848b21ae152fe79c10dd0197304ada8f7b586d3ebc3f27f43c506e5a52a863c", size = 292027, upload-time = "2025-04-08T10:36:11.901Z" }, - { url = "https://files.pythonhosted.org/packages/1a/03/81f9fcc3963b3fc415cd4b0b2b39ee8cc136c42fb10a36acf38745e9d283/watchfiles-1.0.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f59b870db1f1ae5a9ac28245707d955c8721dd6565e7f411024fa374b5362d1d", size = 405947, upload-time = "2025-04-08T10:36:13.721Z" }, - { url = "https://files.pythonhosted.org/packages/54/97/8c4213a852feb64807ec1d380f42d4fc8bfaef896bdbd94318f8fd7f3e4e/watchfiles-1.0.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9475b0093767e1475095f2aeb1d219fb9664081d403d1dff81342df8cd707034", size = 397276, upload-time = "2025-04-08T10:36:15.131Z" }, - { url = "https://files.pythonhosted.org/packages/78/12/d4464d19860cb9672efa45eec1b08f8472c478ed67dcd30647c51ada7aef/watchfiles-1.0.5-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc533aa50664ebd6c628b2f30591956519462f5d27f951ed03d6c82b2dfd9965", size = 455550, upload-time = "2025-04-08T10:36:16.635Z" }, - { url = "https://files.pythonhosted.org/packages/90/fb/b07bcdf1034d8edeaef4c22f3e9e3157d37c5071b5f9492ffdfa4ad4bed7/watchfiles-1.0.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fed1cd825158dcaae36acce7b2db33dcbfd12b30c34317a88b8ed80f0541cc57", size = 455542, upload-time = "2025-04-08T10:36:18.655Z" }, - { url = "https://files.pythonhosted.org/packages/5b/84/7b69282c0df2bf2dff4e50be2c54669cddf219a5a5fb077891c00c00e5c8/watchfiles-1.0.5-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:554389562c29c2c182e3908b149095051f81d28c2fec79ad6c8997d7d63e0009", size = 405783, upload-time = "2025-04-08T10:36:20.553Z" }, - { url = "https://files.pythonhosted.org/packages/dd/ae/03fca0545d99b7ea21df49bead7b51e7dca9ce3b45bb6d34530aa18c16a2/watchfiles-1.0.5-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a74add8d7727e6404d5dc4dcd7fac65d4d82f95928bbee0cf5414c900e86773e", size = 397133, upload-time = "2025-04-08T10:36:22.439Z" }, - { url = "https://files.pythonhosted.org/packages/1a/07/c2b6390003e933b2e187a3f7070c00bd87da8a58d6f2393e039b06a88c2e/watchfiles-1.0.5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb1489f25b051a89fae574505cc26360c8e95e227a9500182a7fe0afcc500ce0", size = 456198, upload-time = "2025-04-08T10:36:23.884Z" }, - { url = "https://files.pythonhosted.org/packages/46/d3/ecc62cbd7054f0812f3a7ca7c1c9f7ba99ba45efcfc8297a9fcd2c87b31c/watchfiles-1.0.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0901429650652d3f0da90bad42bdafc1f9143ff3605633c455c999a2d786cac", size = 456511, upload-time = "2025-04-08T10:36:25.42Z" }, + { url = "https://files.pythonhosted.org/packages/b9/dd/579d1dc57f0f895426a1211c4ef3b0cb37eb9e642bb04bdcd962b5df206a/watchfiles-1.1.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:27f30e14aa1c1e91cb653f03a63445739919aef84c8d2517997a83155e7a2fcc", size = 405757, upload-time = "2025-06-15T19:04:51.058Z" }, + { url = "https://files.pythonhosted.org/packages/1c/a0/7a0318cd874393344d48c34d53b3dd419466adf59a29ba5b51c88dd18b86/watchfiles-1.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3366f56c272232860ab45c77c3ca7b74ee819c8e1f6f35a7125556b198bbc6df", size = 397511, upload-time = "2025-06-15T19:04:52.79Z" }, + { url = "https://files.pythonhosted.org/packages/06/be/503514656d0555ec2195f60d810eca29b938772e9bfb112d5cd5ad6f6a9e/watchfiles-1.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8412eacef34cae2836d891836a7fff7b754d6bcac61f6c12ba5ca9bc7e427b68", size = 450739, upload-time = "2025-06-15T19:04:54.203Z" }, + { url = "https://files.pythonhosted.org/packages/4e/0d/a05dd9e5f136cdc29751816d0890d084ab99f8c17b86f25697288ca09bc7/watchfiles-1.1.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:df670918eb7dd719642e05979fc84704af913d563fd17ed636f7c4783003fdcc", size = 458106, upload-time = "2025-06-15T19:04:55.607Z" }, + { url = "https://files.pythonhosted.org/packages/f1/fa/9cd16e4dfdb831072b7ac39e7bea986e52128526251038eb481effe9f48e/watchfiles-1.1.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d7642b9bc4827b5518ebdb3b82698ada8c14c7661ddec5fe719f3e56ccd13c97", size = 484264, upload-time = "2025-06-15T19:04:57.009Z" }, + { url = "https://files.pythonhosted.org/packages/32/04/1da8a637c7e2b70e750a0308e9c8e662ada0cca46211fa9ef24a23937e0b/watchfiles-1.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:199207b2d3eeaeb80ef4411875a6243d9ad8bc35b07fc42daa6b801cc39cc41c", size = 597612, upload-time = "2025-06-15T19:04:58.409Z" }, + { url = "https://files.pythonhosted.org/packages/30/01/109f2762e968d3e58c95731a206e5d7d2a7abaed4299dd8a94597250153c/watchfiles-1.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a479466da6db5c1e8754caee6c262cd373e6e6c363172d74394f4bff3d84d7b5", size = 477242, upload-time = "2025-06-15T19:04:59.786Z" }, + { url = "https://files.pythonhosted.org/packages/b5/b8/46f58cf4969d3b7bc3ca35a98e739fa4085b0657a1540ccc29a1a0bc016f/watchfiles-1.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:935f9edd022ec13e447e5723a7d14456c8af254544cefbc533f6dd276c9aa0d9", size = 453148, upload-time = "2025-06-15T19:05:01.103Z" }, + { url = "https://files.pythonhosted.org/packages/a5/cd/8267594263b1770f1eb76914940d7b2d03ee55eca212302329608208e061/watchfiles-1.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8076a5769d6bdf5f673a19d51da05fc79e2bbf25e9fe755c47595785c06a8c72", size = 626574, upload-time = "2025-06-15T19:05:02.582Z" }, + { url = "https://files.pythonhosted.org/packages/a1/2f/7f2722e85899bed337cba715723e19185e288ef361360718973f891805be/watchfiles-1.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:86b1e28d4c37e89220e924305cd9f82866bb0ace666943a6e4196c5df4d58dcc", size = 624378, upload-time = "2025-06-15T19:05:03.719Z" }, + { url = "https://files.pythonhosted.org/packages/bf/20/64c88ec43d90a568234d021ab4b2a6f42a5230d772b987c3f9c00cc27b8b/watchfiles-1.1.0-cp310-cp310-win32.whl", hash = "sha256:d1caf40c1c657b27858f9774d5c0e232089bca9cb8ee17ce7478c6e9264d2587", size = 279829, upload-time = "2025-06-15T19:05:04.822Z" }, + { url = "https://files.pythonhosted.org/packages/39/5c/a9c1ed33de7af80935e4eac09570de679c6e21c07070aa99f74b4431f4d6/watchfiles-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:a89c75a5b9bc329131115a409d0acc16e8da8dfd5867ba59f1dd66ae7ea8fa82", size = 292192, upload-time = "2025-06-15T19:05:06.348Z" }, + { url = "https://files.pythonhosted.org/packages/8b/78/7401154b78ab484ccaaeef970dc2af0cb88b5ba8a1b415383da444cdd8d3/watchfiles-1.1.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:c9649dfc57cc1f9835551deb17689e8d44666315f2e82d337b9f07bd76ae3aa2", size = 405751, upload-time = "2025-06-15T19:05:07.679Z" }, + { url = "https://files.pythonhosted.org/packages/76/63/e6c3dbc1f78d001589b75e56a288c47723de28c580ad715eb116639152b5/watchfiles-1.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:406520216186b99374cdb58bc48e34bb74535adec160c8459894884c983a149c", size = 397313, upload-time = "2025-06-15T19:05:08.764Z" }, + { url = "https://files.pythonhosted.org/packages/6c/a2/8afa359ff52e99af1632f90cbf359da46184207e893a5f179301b0c8d6df/watchfiles-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb45350fd1dc75cd68d3d72c47f5b513cb0578da716df5fba02fff31c69d5f2d", size = 450792, upload-time = "2025-06-15T19:05:09.869Z" }, + { url = "https://files.pythonhosted.org/packages/1d/bf/7446b401667f5c64972a57a0233be1104157fc3abf72c4ef2666c1bd09b2/watchfiles-1.1.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:11ee4444250fcbeb47459a877e5e80ed994ce8e8d20283857fc128be1715dac7", size = 458196, upload-time = "2025-06-15T19:05:11.91Z" }, + { url = "https://files.pythonhosted.org/packages/58/2f/501ddbdfa3fa874ea5597c77eeea3d413579c29af26c1091b08d0c792280/watchfiles-1.1.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bda8136e6a80bdea23e5e74e09df0362744d24ffb8cd59c4a95a6ce3d142f79c", size = 484788, upload-time = "2025-06-15T19:05:13.373Z" }, + { url = "https://files.pythonhosted.org/packages/61/1e/9c18eb2eb5c953c96bc0e5f626f0e53cfef4bd19bd50d71d1a049c63a575/watchfiles-1.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b915daeb2d8c1f5cee4b970f2e2c988ce6514aace3c9296e58dd64dc9aa5d575", size = 597879, upload-time = "2025-06-15T19:05:14.725Z" }, + { url = "https://files.pythonhosted.org/packages/8b/6c/1467402e5185d89388b4486745af1e0325007af0017c3384cc786fff0542/watchfiles-1.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ed8fc66786de8d0376f9f913c09e963c66e90ced9aa11997f93bdb30f7c872a8", size = 477447, upload-time = "2025-06-15T19:05:15.775Z" }, + { url = "https://files.pythonhosted.org/packages/2b/a1/ec0a606bde4853d6c4a578f9391eeb3684a9aea736a8eb217e3e00aa89a1/watchfiles-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe4371595edf78c41ef8ac8df20df3943e13defd0efcb732b2e393b5a8a7a71f", size = 453145, upload-time = "2025-06-15T19:05:17.17Z" }, + { url = "https://files.pythonhosted.org/packages/90/b9/ef6f0c247a6a35d689fc970dc7f6734f9257451aefb30def5d100d6246a5/watchfiles-1.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b7c5f6fe273291f4d414d55b2c80d33c457b8a42677ad14b4b47ff025d0893e4", size = 626539, upload-time = "2025-06-15T19:05:18.557Z" }, + { url = "https://files.pythonhosted.org/packages/34/44/6ffda5537085106ff5aaa762b0d130ac6c75a08015dd1621376f708c94de/watchfiles-1.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7738027989881e70e3723c75921f1efa45225084228788fc59ea8c6d732eb30d", size = 624472, upload-time = "2025-06-15T19:05:19.588Z" }, + { url = "https://files.pythonhosted.org/packages/c3/e3/71170985c48028fa3f0a50946916a14055e741db11c2e7bc2f3b61f4d0e3/watchfiles-1.1.0-cp311-cp311-win32.whl", hash = "sha256:622d6b2c06be19f6e89b1d951485a232e3b59618def88dbeda575ed8f0d8dbf2", size = 279348, upload-time = "2025-06-15T19:05:20.856Z" }, + { url = "https://files.pythonhosted.org/packages/89/1b/3e39c68b68a7a171070f81fc2561d23ce8d6859659406842a0e4bebf3bba/watchfiles-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:48aa25e5992b61debc908a61ab4d3f216b64f44fdaa71eb082d8b2de846b7d12", size = 292607, upload-time = "2025-06-15T19:05:21.937Z" }, + { url = "https://files.pythonhosted.org/packages/61/9f/2973b7539f2bdb6ea86d2c87f70f615a71a1fc2dba2911795cea25968aea/watchfiles-1.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:00645eb79a3faa70d9cb15c8d4187bb72970b2470e938670240c7998dad9f13a", size = 285056, upload-time = "2025-06-15T19:05:23.12Z" }, + { url = "https://files.pythonhosted.org/packages/f6/b8/858957045a38a4079203a33aaa7d23ea9269ca7761c8a074af3524fbb240/watchfiles-1.1.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9dc001c3e10de4725c749d4c2f2bdc6ae24de5a88a339c4bce32300a31ede179", size = 402339, upload-time = "2025-06-15T19:05:24.516Z" }, + { url = "https://files.pythonhosted.org/packages/80/28/98b222cca751ba68e88521fabd79a4fab64005fc5976ea49b53fa205d1fa/watchfiles-1.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d9ba68ec283153dead62cbe81872d28e053745f12335d037de9cbd14bd1877f5", size = 394409, upload-time = "2025-06-15T19:05:25.469Z" }, + { url = "https://files.pythonhosted.org/packages/86/50/dee79968566c03190677c26f7f47960aff738d32087087bdf63a5473e7df/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:130fc497b8ee68dce163e4254d9b0356411d1490e868bd8790028bc46c5cc297", size = 450939, upload-time = "2025-06-15T19:05:26.494Z" }, + { url = "https://files.pythonhosted.org/packages/40/45/a7b56fb129700f3cfe2594a01aa38d033b92a33dddce86c8dfdfc1247b72/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:50a51a90610d0845a5931a780d8e51d7bd7f309ebc25132ba975aca016b576a0", size = 457270, upload-time = "2025-06-15T19:05:27.466Z" }, + { url = "https://files.pythonhosted.org/packages/b5/c8/fa5ef9476b1d02dc6b5e258f515fcaaecf559037edf8b6feffcbc097c4b8/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc44678a72ac0910bac46fa6a0de6af9ba1355669b3dfaf1ce5f05ca7a74364e", size = 483370, upload-time = "2025-06-15T19:05:28.548Z" }, + { url = "https://files.pythonhosted.org/packages/98/68/42cfcdd6533ec94f0a7aab83f759ec11280f70b11bfba0b0f885e298f9bd/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a543492513a93b001975ae283a51f4b67973662a375a403ae82f420d2c7205ee", size = 598654, upload-time = "2025-06-15T19:05:29.997Z" }, + { url = "https://files.pythonhosted.org/packages/d3/74/b2a1544224118cc28df7e59008a929e711f9c68ce7d554e171b2dc531352/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ac164e20d17cc285f2b94dc31c384bc3aa3dd5e7490473b3db043dd70fbccfd", size = 478667, upload-time = "2025-06-15T19:05:31.172Z" }, + { url = "https://files.pythonhosted.org/packages/8c/77/e3362fe308358dc9f8588102481e599c83e1b91c2ae843780a7ded939a35/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7590d5a455321e53857892ab8879dce62d1f4b04748769f5adf2e707afb9d4f", size = 452213, upload-time = "2025-06-15T19:05:32.299Z" }, + { url = "https://files.pythonhosted.org/packages/6e/17/c8f1a36540c9a1558d4faf08e909399e8133599fa359bf52ec8fcee5be6f/watchfiles-1.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:37d3d3f7defb13f62ece99e9be912afe9dd8a0077b7c45ee5a57c74811d581a4", size = 626718, upload-time = "2025-06-15T19:05:33.415Z" }, + { url = "https://files.pythonhosted.org/packages/26/45/fb599be38b4bd38032643783d7496a26a6f9ae05dea1a42e58229a20ac13/watchfiles-1.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:7080c4bb3efd70a07b1cc2df99a7aa51d98685be56be6038c3169199d0a1c69f", size = 623098, upload-time = "2025-06-15T19:05:34.534Z" }, + { url = "https://files.pythonhosted.org/packages/a1/e7/fdf40e038475498e160cd167333c946e45d8563ae4dd65caf757e9ffe6b4/watchfiles-1.1.0-cp312-cp312-win32.whl", hash = "sha256:cbcf8630ef4afb05dc30107bfa17f16c0896bb30ee48fc24bf64c1f970f3b1fd", size = 279209, upload-time = "2025-06-15T19:05:35.577Z" }, + { url = "https://files.pythonhosted.org/packages/3f/d3/3ae9d5124ec75143bdf088d436cba39812122edc47709cd2caafeac3266f/watchfiles-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:cbd949bdd87567b0ad183d7676feb98136cde5bb9025403794a4c0db28ed3a47", size = 292786, upload-time = "2025-06-15T19:05:36.559Z" }, + { url = "https://files.pythonhosted.org/packages/26/2f/7dd4fc8b5f2b34b545e19629b4a018bfb1de23b3a496766a2c1165ca890d/watchfiles-1.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:0a7d40b77f07be87c6faa93d0951a0fcd8cbca1ddff60a1b65d741bac6f3a9f6", size = 284343, upload-time = "2025-06-15T19:05:37.5Z" }, + { url = "https://files.pythonhosted.org/packages/d3/42/fae874df96595556a9089ade83be34a2e04f0f11eb53a8dbf8a8a5e562b4/watchfiles-1.1.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5007f860c7f1f8df471e4e04aaa8c43673429047d63205d1630880f7637bca30", size = 402004, upload-time = "2025-06-15T19:05:38.499Z" }, + { url = "https://files.pythonhosted.org/packages/fa/55/a77e533e59c3003d9803c09c44c3651224067cbe7fb5d574ddbaa31e11ca/watchfiles-1.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:20ecc8abbd957046f1fe9562757903f5eaf57c3bce70929fda6c7711bb58074a", size = 393671, upload-time = "2025-06-15T19:05:39.52Z" }, + { url = "https://files.pythonhosted.org/packages/05/68/b0afb3f79c8e832e6571022611adbdc36e35a44e14f129ba09709aa4bb7a/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2f0498b7d2a3c072766dba3274fe22a183dbea1f99d188f1c6c72209a1063dc", size = 449772, upload-time = "2025-06-15T19:05:40.897Z" }, + { url = "https://files.pythonhosted.org/packages/ff/05/46dd1f6879bc40e1e74c6c39a1b9ab9e790bf1f5a2fe6c08b463d9a807f4/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:239736577e848678e13b201bba14e89718f5c2133dfd6b1f7846fa1b58a8532b", size = 456789, upload-time = "2025-06-15T19:05:42.045Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ca/0eeb2c06227ca7f12e50a47a3679df0cd1ba487ea19cf844a905920f8e95/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eff4b8d89f444f7e49136dc695599a591ff769300734446c0a86cba2eb2f9895", size = 482551, upload-time = "2025-06-15T19:05:43.781Z" }, + { url = "https://files.pythonhosted.org/packages/31/47/2cecbd8694095647406645f822781008cc524320466ea393f55fe70eed3b/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:12b0a02a91762c08f7264e2e79542f76870c3040bbc847fb67410ab81474932a", size = 597420, upload-time = "2025-06-15T19:05:45.244Z" }, + { url = "https://files.pythonhosted.org/packages/d9/7e/82abc4240e0806846548559d70f0b1a6dfdca75c1b4f9fa62b504ae9b083/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:29e7bc2eee15cbb339c68445959108803dc14ee0c7b4eea556400131a8de462b", size = 477950, upload-time = "2025-06-15T19:05:46.332Z" }, + { url = "https://files.pythonhosted.org/packages/25/0d/4d564798a49bf5482a4fa9416dea6b6c0733a3b5700cb8a5a503c4b15853/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9481174d3ed982e269c090f780122fb59cee6c3796f74efe74e70f7780ed94c", size = 451706, upload-time = "2025-06-15T19:05:47.459Z" }, + { url = "https://files.pythonhosted.org/packages/81/b5/5516cf46b033192d544102ea07c65b6f770f10ed1d0a6d388f5d3874f6e4/watchfiles-1.1.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:80f811146831c8c86ab17b640801c25dc0a88c630e855e2bef3568f30434d52b", size = 625814, upload-time = "2025-06-15T19:05:48.654Z" }, + { url = "https://files.pythonhosted.org/packages/0c/dd/7c1331f902f30669ac3e754680b6edb9a0dd06dea5438e61128111fadd2c/watchfiles-1.1.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:60022527e71d1d1fda67a33150ee42869042bce3d0fcc9cc49be009a9cded3fb", size = 622820, upload-time = "2025-06-15T19:05:50.088Z" }, + { url = "https://files.pythonhosted.org/packages/1b/14/36d7a8e27cd128d7b1009e7715a7c02f6c131be9d4ce1e5c3b73d0e342d8/watchfiles-1.1.0-cp313-cp313-win32.whl", hash = "sha256:32d6d4e583593cb8576e129879ea0991660b935177c0f93c6681359b3654bfa9", size = 279194, upload-time = "2025-06-15T19:05:51.186Z" }, + { url = "https://files.pythonhosted.org/packages/25/41/2dd88054b849aa546dbeef5696019c58f8e0774f4d1c42123273304cdb2e/watchfiles-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:f21af781a4a6fbad54f03c598ab620e3a77032c5878f3d780448421a6e1818c7", size = 292349, upload-time = "2025-06-15T19:05:52.201Z" }, + { url = "https://files.pythonhosted.org/packages/c8/cf/421d659de88285eb13941cf11a81f875c176f76a6d99342599be88e08d03/watchfiles-1.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:5366164391873ed76bfdf618818c82084c9db7fac82b64a20c44d335eec9ced5", size = 283836, upload-time = "2025-06-15T19:05:53.265Z" }, + { url = "https://files.pythonhosted.org/packages/45/10/6faf6858d527e3599cc50ec9fcae73590fbddc1420bd4fdccfebffeedbc6/watchfiles-1.1.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:17ab167cca6339c2b830b744eaf10803d2a5b6683be4d79d8475d88b4a8a4be1", size = 400343, upload-time = "2025-06-15T19:05:54.252Z" }, + { url = "https://files.pythonhosted.org/packages/03/20/5cb7d3966f5e8c718006d0e97dfe379a82f16fecd3caa7810f634412047a/watchfiles-1.1.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:328dbc9bff7205c215a7807da7c18dce37da7da718e798356212d22696404339", size = 392916, upload-time = "2025-06-15T19:05:55.264Z" }, + { url = "https://files.pythonhosted.org/packages/8c/07/d8f1176328fa9e9581b6f120b017e286d2a2d22ae3f554efd9515c8e1b49/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7208ab6e009c627b7557ce55c465c98967e8caa8b11833531fdf95799372633", size = 449582, upload-time = "2025-06-15T19:05:56.317Z" }, + { url = "https://files.pythonhosted.org/packages/66/e8/80a14a453cf6038e81d072a86c05276692a1826471fef91df7537dba8b46/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a8f6f72974a19efead54195bc9bed4d850fc047bb7aa971268fd9a8387c89011", size = 456752, upload-time = "2025-06-15T19:05:57.359Z" }, + { url = "https://files.pythonhosted.org/packages/5a/25/0853b3fe0e3c2f5af9ea60eb2e781eade939760239a72c2d38fc4cc335f6/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d181ef50923c29cf0450c3cd47e2f0557b62218c50b2ab8ce2ecaa02bd97e670", size = 481436, upload-time = "2025-06-15T19:05:58.447Z" }, + { url = "https://files.pythonhosted.org/packages/fe/9e/4af0056c258b861fbb29dcb36258de1e2b857be4a9509e6298abcf31e5c9/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:adb4167043d3a78280d5d05ce0ba22055c266cf8655ce942f2fb881262ff3cdf", size = 596016, upload-time = "2025-06-15T19:05:59.59Z" }, + { url = "https://files.pythonhosted.org/packages/c5/fa/95d604b58aa375e781daf350897aaaa089cff59d84147e9ccff2447c8294/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c5701dc474b041e2934a26d31d39f90fac8a3dee2322b39f7729867f932b1d4", size = 476727, upload-time = "2025-06-15T19:06:01.086Z" }, + { url = "https://files.pythonhosted.org/packages/65/95/fe479b2664f19be4cf5ceeb21be05afd491d95f142e72d26a42f41b7c4f8/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b067915e3c3936966a8607f6fe5487df0c9c4afb85226613b520890049deea20", size = 451864, upload-time = "2025-06-15T19:06:02.144Z" }, + { url = "https://files.pythonhosted.org/packages/d3/8a/3c4af14b93a15ce55901cd7a92e1a4701910f1768c78fb30f61d2b79785b/watchfiles-1.1.0-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:9c733cda03b6d636b4219625a4acb5c6ffb10803338e437fb614fef9516825ef", size = 625626, upload-time = "2025-06-15T19:06:03.578Z" }, + { url = "https://files.pythonhosted.org/packages/da/f5/cf6aa047d4d9e128f4b7cde615236a915673775ef171ff85971d698f3c2c/watchfiles-1.1.0-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:cc08ef8b90d78bfac66f0def80240b0197008e4852c9f285907377b2947ffdcb", size = 622744, upload-time = "2025-06-15T19:06:05.066Z" }, + { url = "https://files.pythonhosted.org/packages/2c/00/70f75c47f05dea6fd30df90f047765f6fc2d6eb8b5a3921379b0b04defa2/watchfiles-1.1.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:9974d2f7dc561cce3bb88dfa8eb309dab64c729de85fba32e98d75cf24b66297", size = 402114, upload-time = "2025-06-15T19:06:06.186Z" }, + { url = "https://files.pythonhosted.org/packages/53/03/acd69c48db4a1ed1de26b349d94077cca2238ff98fd64393f3e97484cae6/watchfiles-1.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c68e9f1fcb4d43798ad8814c4c1b61547b014b667216cb754e606bfade587018", size = 393879, upload-time = "2025-06-15T19:06:07.369Z" }, + { url = "https://files.pythonhosted.org/packages/2f/c8/a9a2a6f9c8baa4eceae5887fecd421e1b7ce86802bcfc8b6a942e2add834/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95ab1594377effac17110e1352989bdd7bdfca9ff0e5eeccd8c69c5389b826d0", size = 450026, upload-time = "2025-06-15T19:06:08.476Z" }, + { url = "https://files.pythonhosted.org/packages/fe/51/d572260d98388e6e2b967425c985e07d47ee6f62e6455cefb46a6e06eda5/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fba9b62da882c1be1280a7584ec4515d0a6006a94d6e5819730ec2eab60ffe12", size = 457917, upload-time = "2025-06-15T19:06:09.988Z" }, + { url = "https://files.pythonhosted.org/packages/c6/2d/4258e52917bf9f12909b6ec314ff9636276f3542f9d3807d143f27309104/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3434e401f3ce0ed6b42569128b3d1e3af773d7ec18751b918b89cd49c14eaafb", size = 483602, upload-time = "2025-06-15T19:06:11.088Z" }, + { url = "https://files.pythonhosted.org/packages/84/99/bee17a5f341a4345fe7b7972a475809af9e528deba056f8963d61ea49f75/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fa257a4d0d21fcbca5b5fcba9dca5a78011cb93c0323fb8855c6d2dfbc76eb77", size = 596758, upload-time = "2025-06-15T19:06:12.197Z" }, + { url = "https://files.pythonhosted.org/packages/40/76/e4bec1d59b25b89d2b0716b41b461ed655a9a53c60dc78ad5771fda5b3e6/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7fd1b3879a578a8ec2076c7961076df540b9af317123f84569f5a9ddee64ce92", size = 477601, upload-time = "2025-06-15T19:06:13.391Z" }, + { url = "https://files.pythonhosted.org/packages/1f/fa/a514292956f4a9ce3c567ec0c13cce427c158e9f272062685a8a727d08fc/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:62cc7a30eeb0e20ecc5f4bd113cd69dcdb745a07c68c0370cea919f373f65d9e", size = 451936, upload-time = "2025-06-15T19:06:14.656Z" }, + { url = "https://files.pythonhosted.org/packages/32/5d/c3bf927ec3bbeb4566984eba8dd7a8eb69569400f5509904545576741f88/watchfiles-1.1.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:891c69e027748b4a73847335d208e374ce54ca3c335907d381fde4e41661b13b", size = 626243, upload-time = "2025-06-15T19:06:16.232Z" }, + { url = "https://files.pythonhosted.org/packages/e6/65/6e12c042f1a68c556802a84d54bb06d35577c81e29fba14019562479159c/watchfiles-1.1.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:12fe8eaffaf0faa7906895b4f8bb88264035b3f0243275e0bf24af0436b27259", size = 623073, upload-time = "2025-06-15T19:06:17.457Z" }, + { url = "https://files.pythonhosted.org/packages/89/ab/7f79d9bf57329e7cbb0a6fd4c7bd7d0cee1e4a8ef0041459f5409da3506c/watchfiles-1.1.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:bfe3c517c283e484843cb2e357dd57ba009cff351edf45fb455b5fbd1f45b15f", size = 400872, upload-time = "2025-06-15T19:06:18.57Z" }, + { url = "https://files.pythonhosted.org/packages/df/d5/3f7bf9912798e9e6c516094db6b8932df53b223660c781ee37607030b6d3/watchfiles-1.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a9ccbf1f129480ed3044f540c0fdbc4ee556f7175e5ab40fe077ff6baf286d4e", size = 392877, upload-time = "2025-06-15T19:06:19.55Z" }, + { url = "https://files.pythonhosted.org/packages/0d/c5/54ec7601a2798604e01c75294770dbee8150e81c6e471445d7601610b495/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba0e3255b0396cac3cc7bbace76404dd72b5438bf0d8e7cefa2f79a7f3649caa", size = 449645, upload-time = "2025-06-15T19:06:20.66Z" }, + { url = "https://files.pythonhosted.org/packages/0a/04/c2f44afc3b2fce21ca0b7802cbd37ed90a29874f96069ed30a36dfe57c2b/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4281cd9fce9fc0a9dbf0fc1217f39bf9cf2b4d315d9626ef1d4e87b84699e7e8", size = 457424, upload-time = "2025-06-15T19:06:21.712Z" }, + { url = "https://files.pythonhosted.org/packages/9f/b0/eec32cb6c14d248095261a04f290636da3df3119d4040ef91a4a50b29fa5/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6d2404af8db1329f9a3c9b79ff63e0ae7131986446901582067d9304ae8aaf7f", size = 481584, upload-time = "2025-06-15T19:06:22.777Z" }, + { url = "https://files.pythonhosted.org/packages/d1/e2/ca4bb71c68a937d7145aa25709e4f5d68eb7698a25ce266e84b55d591bbd/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e78b6ed8165996013165eeabd875c5dfc19d41b54f94b40e9fff0eb3193e5e8e", size = 596675, upload-time = "2025-06-15T19:06:24.226Z" }, + { url = "https://files.pythonhosted.org/packages/a1/dd/b0e4b7fb5acf783816bc950180a6cd7c6c1d2cf7e9372c0ea634e722712b/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:249590eb75ccc117f488e2fabd1bfa33c580e24b96f00658ad88e38844a040bb", size = 477363, upload-time = "2025-06-15T19:06:25.42Z" }, + { url = "https://files.pythonhosted.org/packages/69/c4/088825b75489cb5b6a761a4542645718893d395d8c530b38734f19da44d2/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d05686b5487cfa2e2c28ff1aa370ea3e6c5accfe6435944ddea1e10d93872147", size = 452240, upload-time = "2025-06-15T19:06:26.552Z" }, + { url = "https://files.pythonhosted.org/packages/10/8c/22b074814970eeef43b7c44df98c3e9667c1f7bf5b83e0ff0201b0bd43f9/watchfiles-1.1.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:d0e10e6f8f6dc5762adee7dece33b722282e1f59aa6a55da5d493a97282fedd8", size = 625607, upload-time = "2025-06-15T19:06:27.606Z" }, + { url = "https://files.pythonhosted.org/packages/32/fa/a4f5c2046385492b2273213ef815bf71a0d4c1943b784fb904e184e30201/watchfiles-1.1.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:af06c863f152005c7592df1d6a7009c836a247c9d8adb78fef8575a5a98699db", size = 623315, upload-time = "2025-06-15T19:06:29.076Z" }, + { url = "https://files.pythonhosted.org/packages/47/8a/a45db804b9f0740f8408626ab2bca89c3136432e57c4673b50180bf85dd9/watchfiles-1.1.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:865c8e95713744cf5ae261f3067861e9da5f1370ba91fc536431e29b418676fa", size = 406400, upload-time = "2025-06-15T19:06:30.233Z" }, + { url = "https://files.pythonhosted.org/packages/64/06/a08684f628fb41addd451845aceedc2407dc3d843b4b060a7c4350ddee0c/watchfiles-1.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:42f92befc848bb7a19658f21f3e7bae80d7d005d13891c62c2cd4d4d0abb3433", size = 397920, upload-time = "2025-06-15T19:06:31.315Z" }, + { url = "https://files.pythonhosted.org/packages/79/e6/e10d5675af653b1b07d4156906858041149ca222edaf8995877f2605ba9e/watchfiles-1.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa0cc8365ab29487eb4f9979fd41b22549853389e22d5de3f134a6796e1b05a4", size = 451196, upload-time = "2025-06-15T19:06:32.435Z" }, + { url = "https://files.pythonhosted.org/packages/f6/8a/facd6988100cd0f39e89f6c550af80edb28e3a529e1ee662e750663e6b36/watchfiles-1.1.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:90ebb429e933645f3da534c89b29b665e285048973b4d2b6946526888c3eb2c7", size = 458218, upload-time = "2025-06-15T19:06:33.503Z" }, + { url = "https://files.pythonhosted.org/packages/90/26/34cbcbc4d0f2f8f9cc243007e65d741ae039f7a11ef8ec6e9cd25bee08d1/watchfiles-1.1.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c588c45da9b08ab3da81d08d7987dae6d2a3badd63acdb3e206a42dbfa7cb76f", size = 484851, upload-time = "2025-06-15T19:06:34.541Z" }, + { url = "https://files.pythonhosted.org/packages/d7/1f/f59faa9fc4b0e36dbcdd28a18c430416443b309d295d8b82e18192d120ad/watchfiles-1.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7c55b0f9f68590115c25272b06e63f0824f03d4fc7d6deed43d8ad5660cabdbf", size = 599520, upload-time = "2025-06-15T19:06:35.785Z" }, + { url = "https://files.pythonhosted.org/packages/83/72/3637abecb3bf590529f5154ca000924003e5f4bbb9619744feeaf6f0b70b/watchfiles-1.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd17a1e489f02ce9117b0de3c0b1fab1c3e2eedc82311b299ee6b6faf6c23a29", size = 477956, upload-time = "2025-06-15T19:06:36.965Z" }, + { url = "https://files.pythonhosted.org/packages/f7/f3/d14ffd9acc0c1bd4790378995e320981423263a5d70bd3929e2e0dc87fff/watchfiles-1.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da71945c9ace018d8634822f16cbc2a78323ef6c876b1d34bbf5d5222fd6a72e", size = 453196, upload-time = "2025-06-15T19:06:38.024Z" }, + { url = "https://files.pythonhosted.org/packages/7f/38/78ad77bd99e20c0fdc82262be571ef114fc0beef9b43db52adb939768c38/watchfiles-1.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:51556d5004887045dba3acdd1fdf61dddea2be0a7e18048b5e853dcd37149b86", size = 627479, upload-time = "2025-06-15T19:06:39.442Z" }, + { url = "https://files.pythonhosted.org/packages/e6/cf/549d50a22fcc83f1017c6427b1c76c053233f91b526f4ad7a45971e70c0b/watchfiles-1.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04e4ed5d1cd3eae68c89bcc1a485a109f39f2fd8de05f705e98af6b5f1861f1f", size = 624414, upload-time = "2025-06-15T19:06:40.859Z" }, + { url = "https://files.pythonhosted.org/packages/72/de/57d6e40dc9140af71c12f3a9fc2d3efc5529d93981cd4d265d484d7c9148/watchfiles-1.1.0-cp39-cp39-win32.whl", hash = "sha256:c600e85f2ffd9f1035222b1a312aff85fd11ea39baff1d705b9b047aad2ce267", size = 280020, upload-time = "2025-06-15T19:06:41.89Z" }, + { url = "https://files.pythonhosted.org/packages/88/bb/7d287fc2a762396b128a0fca2dbae29386e0a242b81d1046daf389641db3/watchfiles-1.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:3aba215958d88182e8d2acba0fdaf687745180974946609119953c0e112397dc", size = 292758, upload-time = "2025-06-15T19:06:43.251Z" }, + { url = "https://files.pythonhosted.org/packages/be/7c/a3d7c55cfa377c2f62c4ae3c6502b997186bc5e38156bafcb9b653de9a6d/watchfiles-1.1.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3a6fd40bbb50d24976eb275ccb55cd1951dfb63dbc27cae3066a6ca5f4beabd5", size = 406748, upload-time = "2025-06-15T19:06:44.2Z" }, + { url = "https://files.pythonhosted.org/packages/38/d0/c46f1b2c0ca47f3667b144de6f0515f6d1c670d72f2ca29861cac78abaa1/watchfiles-1.1.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9f811079d2f9795b5d48b55a37aa7773680a5659afe34b54cc1d86590a51507d", size = 398801, upload-time = "2025-06-15T19:06:45.774Z" }, + { url = "https://files.pythonhosted.org/packages/70/9c/9a6a42e97f92eeed77c3485a43ea96723900aefa3ac739a8c73f4bff2cd7/watchfiles-1.1.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a2726d7bfd9f76158c84c10a409b77a320426540df8c35be172444394b17f7ea", size = 451528, upload-time = "2025-06-15T19:06:46.791Z" }, + { url = "https://files.pythonhosted.org/packages/51/7b/98c7f4f7ce7ff03023cf971cd84a3ee3b790021ae7584ffffa0eb2554b96/watchfiles-1.1.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df32d59cb9780f66d165a9a7a26f19df2c7d24e3bd58713108b41d0ff4f929c6", size = 454095, upload-time = "2025-06-15T19:06:48.211Z" }, + { url = "https://files.pythonhosted.org/packages/8c/6b/686dcf5d3525ad17b384fd94708e95193529b460a1b7bf40851f1328ec6e/watchfiles-1.1.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0ece16b563b17ab26eaa2d52230c9a7ae46cf01759621f4fbbca280e438267b3", size = 406910, upload-time = "2025-06-15T19:06:49.335Z" }, + { url = "https://files.pythonhosted.org/packages/f3/d3/71c2dcf81dc1edcf8af9f4d8d63b1316fb0a2dd90cbfd427e8d9dd584a90/watchfiles-1.1.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:51b81e55d40c4b4aa8658427a3ee7ea847c591ae9e8b81ef94a90b668999353c", size = 398816, upload-time = "2025-06-15T19:06:50.433Z" }, + { url = "https://files.pythonhosted.org/packages/b8/fa/12269467b2fc006f8fce4cd6c3acfa77491dd0777d2a747415f28ccc8c60/watchfiles-1.1.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2bcdc54ea267fe72bfc7d83c041e4eb58d7d8dc6f578dfddb52f037ce62f432", size = 451584, upload-time = "2025-06-15T19:06:51.834Z" }, + { url = "https://files.pythonhosted.org/packages/bd/d3/254cea30f918f489db09d6a8435a7de7047f8cb68584477a515f160541d6/watchfiles-1.1.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:923fec6e5461c42bd7e3fd5ec37492c6f3468be0499bc0707b4bbbc16ac21792", size = 454009, upload-time = "2025-06-15T19:06:52.896Z" }, + { url = "https://files.pythonhosted.org/packages/48/93/5c96bdb65e7f88f7da40645f34c0a3c317a2931ed82161e93c91e8eddd27/watchfiles-1.1.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7b3443f4ec3ba5aa00b0e9fa90cf31d98321cbff8b925a7c7b84161619870bc9", size = 406640, upload-time = "2025-06-15T19:06:54.868Z" }, + { url = "https://files.pythonhosted.org/packages/e3/25/09204836e93e1b99cce88802ce87264a1d20610c7a8f6de24def27ad95b1/watchfiles-1.1.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7049e52167fc75fc3cc418fc13d39a8e520cbb60ca08b47f6cedb85e181d2f2a", size = 398543, upload-time = "2025-06-15T19:06:55.95Z" }, + { url = "https://files.pythonhosted.org/packages/5e/dc/6f324a6f32c5ab73b54311b5f393a79df34c1584b8d2404cf7e6d780aa5d/watchfiles-1.1.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54062ef956807ba806559b3c3d52105ae1827a0d4ab47b621b31132b6b7e2866", size = 451787, upload-time = "2025-06-15T19:06:56.998Z" }, + { url = "https://files.pythonhosted.org/packages/45/5d/1d02ef4caa4ec02389e72d5594cdf9c67f1800a7c380baa55063c30c6598/watchfiles-1.1.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a7bd57a1bb02f9d5c398c0c1675384e7ab1dd39da0ca50b7f09af45fa435277", size = 454272, upload-time = "2025-06-15T19:06:58.055Z" }, ] [[package]] diff --git a/libs/langgraph/tests/test_runnable.py b/libs/langgraph/tests/test_runnable.py index 1dd8e35cc..d36755416 100644 --- a/libs/langgraph/tests/test_runnable.py +++ b/libs/langgraph/tests/test_runnable.py @@ -85,7 +85,7 @@ def test_runnable_callable_injectable_arguments() -> None: """ # Test Optional[BaseStore] annotation. - def func_optional_store(inputs: Any, store: Optional[BaseStore]) -> str: # noqa: UP007 + def func_optional_store(inputs: Any, store: Optional[BaseStore]) -> str: # noqa: UP045 """Test function that accepts an optional store parameter.""" assert store is None return "success" @@ -159,7 +159,7 @@ async def test_runnable_callable_injectable_arguments_async() -> None: """ # Test Optional[BaseStore] annotation. - def func_optional_store(inputs: Any, store: Optional[BaseStore]) -> str: # noqa: UP007 + def func_optional_store(inputs: Any, store: Optional[BaseStore]) -> str: # noqa: UP045 """Test function that accepts an optional store parameter.""" assert store is None return "success" diff --git a/libs/langgraph/uv.lock b/libs/langgraph/uv.lock index 897d89862..2762e3fe1 100644 --- a/libs/langgraph/uv.lock +++ b/libs/langgraph/uv.lock @@ -2,10 +2,7 @@ version = 1 revision = 2 requires-python = ">=3.9" resolution-markers = [ - "python_full_version >= '3.13' and python_full_version < '4.0'", - "python_full_version >= '3.12.4' and python_full_version < '3.13'", - "python_full_version >= '3.11' and python_full_version < '3.12.4'", - "python_full_version >= '4.0'", + "python_full_version >= '3.11'", "python_full_version == '3.10.*'", "python_full_version < '3.10'", ] @@ -57,14 +54,14 @@ wheels = [ [[package]] name = "argon2-cffi" -version = "23.1.0" +version = "25.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "argon2-cffi-bindings" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/31/fa/57ec2c6d16ecd2ba0cf15f3c7d1c3c2e7b5fcb83555ff56d7ab10888ec8f/argon2_cffi-23.1.0.tar.gz", hash = "sha256:879c3e79a2729ce768ebb7d36d4609e3a78a4ca2ec3a9f12286ca057e3d0db08", size = 42798, upload-time = "2023-08-15T14:13:12.711Z" } +sdist = { url = "https://files.pythonhosted.org/packages/0e/89/ce5af8a7d472a67cc819d5d998aa8c82c5d860608c4db9f46f1162d7dab9/argon2_cffi-25.1.0.tar.gz", hash = "sha256:694ae5cc8a42f4c4e2bf2ca0e64e51e23a040c6a517a85074683d3959e1346c1", size = 45706, upload-time = "2025-06-03T06:55:32.073Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a4/6a/e8a041599e78b6b3752da48000b14c8d1e8a04ded09c88c714ba047f34f5/argon2_cffi-23.1.0-py3-none-any.whl", hash = "sha256:c670642b78ba29641818ab2e68bd4e6a78ba53b7eff7b4c3815ae16abf91c7ea", size = 15124, upload-time = "2023-08-15T14:13:10.752Z" }, + { url = "https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl", hash = "sha256:fdc8b074db390fccb6eb4a3604ae7231f219aa669a2652e0f20e16ba513d5741", size = 14657, upload-time = "2025-06-03T06:55:30.804Z" }, ] [[package]] @@ -175,7 +172,7 @@ name = "blockbuster" version = "1.5.24" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "forbiddenfruit", marker = "python_full_version >= '3.11' and python_full_version < '4.0' and implementation_name == 'cpython'" }, + { name = "forbiddenfruit", marker = "python_full_version >= '3.11' and implementation_name == 'cpython'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/35/c8/1e456a043179f2aef10bcaafea79f6d06c0ac45cc994767a54f680509f3b/blockbuster-1.5.24.tar.gz", hash = "sha256:97645775761a5d425666ec0bc99629b65c7eccdc2f770d2439850682567af4ec", size = 51245, upload-time = "2025-03-18T10:12:06.398Z" } wheels = [ @@ -184,11 +181,11 @@ wheels = [ [[package]] name = "certifi" -version = "2025.4.26" +version = "2025.6.15" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e8/9e/c05b3920a3b7d20d3d3310465f50348e5b3694f4f88c6daf736eef3024c4/certifi-2025.4.26.tar.gz", hash = "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6", size = 160705, upload-time = "2025-04-26T02:12:29.51Z" } +sdist = { url = "https://files.pythonhosted.org/packages/73/f7/f14b46d4bcd21092d7d3ccef689615220d8a08fb25e564b65d20738e672e/certifi-2025.6.15.tar.gz", hash = "sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b", size = 158753, upload-time = "2025-06-15T02:45:51.329Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4a/7e/3db2bd1b1f9e95f7cddca6d6e75e2f2bd9f51b1246e546d88addca0106bd/certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3", size = 159618, upload-time = "2025-04-26T02:12:27.662Z" }, + { url = "https://files.pythonhosted.org/packages/84/ae/320161bd181fc06471eed047ecce67b693fd7515b16d495d8932db763426/certifi-2025.6.15-py3-none-any.whl", hash = "sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057", size = 157650, upload-time = "2025-06-15T02:45:49.977Z" }, ] [[package]] @@ -354,10 +351,7 @@ name = "click" version = "8.2.1" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version >= '3.13' and python_full_version < '4.0'", - "python_full_version >= '3.12.4' and python_full_version < '3.13'", - "python_full_version >= '3.11' and python_full_version < '3.12.4'", - "python_full_version >= '4.0'", + "python_full_version >= '3.11'", "python_full_version == '3.10.*'", ] dependencies = [ @@ -400,76 +394,76 @@ wheels = [ [[package]] name = "coverage" -version = "7.8.2" +version = "7.9.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ba/07/998afa4a0ecdf9b1981ae05415dad2d4e7716e1b1f00abbd91691ac09ac9/coverage-7.8.2.tar.gz", hash = "sha256:a886d531373a1f6ff9fad2a2ba4a045b68467b779ae729ee0b3b10ac20033b27", size = 812759, upload-time = "2025-05-23T11:39:57.856Z" } +sdist = { url = "https://files.pythonhosted.org/packages/04/b7/c0465ca253df10a9e8dae0692a4ae6e9726d245390aaef92360e1d6d3832/coverage-7.9.2.tar.gz", hash = "sha256:997024fa51e3290264ffd7492ec97d0690293ccd2b45a6cd7d82d945a4a80c8b", size = 813556, upload-time = "2025-07-03T10:54:15.101Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/26/6b/7dd06399a5c0b81007e3a6af0395cd60e6a30f959f8d407d3ee04642e896/coverage-7.8.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bd8ec21e1443fd7a447881332f7ce9d35b8fbd2849e761bb290b584535636b0a", size = 211573, upload-time = "2025-05-23T11:37:47.207Z" }, - { url = "https://files.pythonhosted.org/packages/f0/df/2b24090820a0bac1412955fb1a4dade6bc3b8dcef7b899c277ffaf16916d/coverage-7.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4c26c2396674816deaeae7ded0e2b42c26537280f8fe313335858ffff35019be", size = 212006, upload-time = "2025-05-23T11:37:50.289Z" }, - { url = "https://files.pythonhosted.org/packages/c5/c4/e4e3b998e116625562a872a342419652fa6ca73f464d9faf9f52f1aff427/coverage-7.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1aec326ed237e5880bfe69ad41616d333712c7937bcefc1343145e972938f9b3", size = 241128, upload-time = "2025-05-23T11:37:52.229Z" }, - { url = "https://files.pythonhosted.org/packages/b1/67/b28904afea3e87a895da850ba587439a61699bf4b73d04d0dfd99bbd33b4/coverage-7.8.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5e818796f71702d7a13e50c70de2a1924f729228580bcba1607cccf32eea46e6", size = 239026, upload-time = "2025-05-23T11:37:53.846Z" }, - { url = "https://files.pythonhosted.org/packages/8c/0f/47bf7c5630d81bc2cd52b9e13043685dbb7c79372a7f5857279cc442b37c/coverage-7.8.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:546e537d9e24efc765c9c891328f30f826e3e4808e31f5d0f87c4ba12bbd1622", size = 240172, upload-time = "2025-05-23T11:37:55.711Z" }, - { url = "https://files.pythonhosted.org/packages/ba/38/af3eb9d36d85abc881f5aaecf8209383dbe0fa4cac2d804c55d05c51cb04/coverage-7.8.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ab9b09a2349f58e73f8ebc06fac546dd623e23b063e5398343c5270072e3201c", size = 240086, upload-time = "2025-05-23T11:37:57.724Z" }, - { url = "https://files.pythonhosted.org/packages/9e/64/c40c27c2573adeba0fe16faf39a8aa57368a1f2148865d6bb24c67eadb41/coverage-7.8.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fd51355ab8a372d89fb0e6a31719e825cf8df8b6724bee942fb5b92c3f016ba3", size = 238792, upload-time = "2025-05-23T11:37:59.737Z" }, - { url = "https://files.pythonhosted.org/packages/8e/ab/b7c85146f15457671c1412afca7c25a5696d7625e7158002aa017e2d7e3c/coverage-7.8.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0774df1e093acb6c9e4d58bce7f86656aeed6c132a16e2337692c12786b32404", size = 239096, upload-time = "2025-05-23T11:38:01.693Z" }, - { url = "https://files.pythonhosted.org/packages/d3/50/9446dad1310905fb1dc284d60d4320a5b25d4e3e33f9ea08b8d36e244e23/coverage-7.8.2-cp310-cp310-win32.whl", hash = "sha256:00f2e2f2e37f47e5f54423aeefd6c32a7dbcedc033fcd3928a4f4948e8b96af7", size = 214144, upload-time = "2025-05-23T11:38:03.68Z" }, - { url = "https://files.pythonhosted.org/packages/23/ed/792e66ad7b8b0df757db8d47af0c23659cdb5a65ef7ace8b111cacdbee89/coverage-7.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:145b07bea229821d51811bf15eeab346c236d523838eda395ea969d120d13347", size = 215043, upload-time = "2025-05-23T11:38:05.217Z" }, - { url = "https://files.pythonhosted.org/packages/6a/4d/1ff618ee9f134d0de5cc1661582c21a65e06823f41caf801aadf18811a8e/coverage-7.8.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b99058eef42e6a8dcd135afb068b3d53aff3921ce699e127602efff9956457a9", size = 211692, upload-time = "2025-05-23T11:38:08.485Z" }, - { url = "https://files.pythonhosted.org/packages/96/fa/c3c1b476de96f2bc7a8ca01a9f1fcb51c01c6b60a9d2c3e66194b2bdb4af/coverage-7.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5feb7f2c3e6ea94d3b877def0270dff0947b8d8c04cfa34a17be0a4dc1836879", size = 212115, upload-time = "2025-05-23T11:38:09.989Z" }, - { url = "https://files.pythonhosted.org/packages/f7/c2/5414c5a1b286c0f3881ae5adb49be1854ac5b7e99011501f81c8c1453065/coverage-7.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:670a13249b957bb9050fab12d86acef7bf8f6a879b9d1a883799276e0d4c674a", size = 244740, upload-time = "2025-05-23T11:38:11.947Z" }, - { url = "https://files.pythonhosted.org/packages/cd/46/1ae01912dfb06a642ef3dd9cf38ed4996fda8fe884dab8952da616f81a2b/coverage-7.8.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0bdc8bf760459a4a4187b452213e04d039990211f98644c7292adf1e471162b5", size = 242429, upload-time = "2025-05-23T11:38:13.955Z" }, - { url = "https://files.pythonhosted.org/packages/06/58/38c676aec594bfe2a87c7683942e5a30224791d8df99bcc8439fde140377/coverage-7.8.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07a989c867986c2a75f158f03fdb413128aad29aca9d4dbce5fc755672d96f11", size = 244218, upload-time = "2025-05-23T11:38:15.631Z" }, - { url = "https://files.pythonhosted.org/packages/80/0c/95b1023e881ce45006d9abc250f76c6cdab7134a1c182d9713878dfefcb2/coverage-7.8.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2db10dedeb619a771ef0e2949ccba7b75e33905de959c2643a4607bef2f3fb3a", size = 243865, upload-time = "2025-05-23T11:38:17.622Z" }, - { url = "https://files.pythonhosted.org/packages/57/37/0ae95989285a39e0839c959fe854a3ae46c06610439350d1ab860bf020ac/coverage-7.8.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e6ea7dba4e92926b7b5f0990634b78ea02f208d04af520c73a7c876d5a8d36cb", size = 242038, upload-time = "2025-05-23T11:38:19.966Z" }, - { url = "https://files.pythonhosted.org/packages/4d/82/40e55f7c0eb5e97cc62cbd9d0746fd24e8caf57be5a408b87529416e0c70/coverage-7.8.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ef2f22795a7aca99fc3c84393a55a53dd18ab8c93fb431004e4d8f0774150f54", size = 242567, upload-time = "2025-05-23T11:38:21.912Z" }, - { url = "https://files.pythonhosted.org/packages/f9/35/66a51adc273433a253989f0d9cc7aa6bcdb4855382cf0858200afe578861/coverage-7.8.2-cp311-cp311-win32.whl", hash = "sha256:641988828bc18a6368fe72355df5f1703e44411adbe49bba5644b941ce6f2e3a", size = 214194, upload-time = "2025-05-23T11:38:23.571Z" }, - { url = "https://files.pythonhosted.org/packages/f6/8f/a543121f9f5f150eae092b08428cb4e6b6d2d134152c3357b77659d2a605/coverage-7.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:8ab4a51cb39dc1933ba627e0875046d150e88478dbe22ce145a68393e9652975", size = 215109, upload-time = "2025-05-23T11:38:25.137Z" }, - { url = "https://files.pythonhosted.org/packages/77/65/6cc84b68d4f35186463cd7ab1da1169e9abb59870c0f6a57ea6aba95f861/coverage-7.8.2-cp311-cp311-win_arm64.whl", hash = "sha256:8966a821e2083c74d88cca5b7dcccc0a3a888a596a04c0b9668a891de3a0cc53", size = 213521, upload-time = "2025-05-23T11:38:27.123Z" }, - { url = "https://files.pythonhosted.org/packages/8d/2a/1da1ada2e3044fcd4a3254fb3576e160b8fe5b36d705c8a31f793423f763/coverage-7.8.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e2f6fe3654468d061942591aef56686131335b7a8325684eda85dacdf311356c", size = 211876, upload-time = "2025-05-23T11:38:29.01Z" }, - { url = "https://files.pythonhosted.org/packages/70/e9/3d715ffd5b6b17a8be80cd14a8917a002530a99943cc1939ad5bb2aa74b9/coverage-7.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76090fab50610798cc05241bf83b603477c40ee87acd358b66196ab0ca44ffa1", size = 212130, upload-time = "2025-05-23T11:38:30.675Z" }, - { url = "https://files.pythonhosted.org/packages/a0/02/fdce62bb3c21649abfd91fbdcf041fb99be0d728ff00f3f9d54d97ed683e/coverage-7.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bd0a0a5054be160777a7920b731a0570284db5142abaaf81bcbb282b8d99279", size = 246176, upload-time = "2025-05-23T11:38:32.395Z" }, - { url = "https://files.pythonhosted.org/packages/a7/52/decbbed61e03b6ffe85cd0fea360a5e04a5a98a7423f292aae62423b8557/coverage-7.8.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da23ce9a3d356d0affe9c7036030b5c8f14556bd970c9b224f9c8205505e3b99", size = 243068, upload-time = "2025-05-23T11:38:33.989Z" }, - { url = "https://files.pythonhosted.org/packages/38/6c/d0e9c0cce18faef79a52778219a3c6ee8e336437da8eddd4ab3dbd8fadff/coverage-7.8.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9392773cffeb8d7e042a7b15b82a414011e9d2b5fdbbd3f7e6a6b17d5e21b20", size = 245328, upload-time = "2025-05-23T11:38:35.568Z" }, - { url = "https://files.pythonhosted.org/packages/f0/70/f703b553a2f6b6c70568c7e398ed0789d47f953d67fbba36a327714a7bca/coverage-7.8.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:876cbfd0b09ce09d81585d266c07a32657beb3eaec896f39484b631555be0fe2", size = 245099, upload-time = "2025-05-23T11:38:37.627Z" }, - { url = "https://files.pythonhosted.org/packages/ec/fb/4cbb370dedae78460c3aacbdad9d249e853f3bc4ce5ff0e02b1983d03044/coverage-7.8.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3da9b771c98977a13fbc3830f6caa85cae6c9c83911d24cb2d218e9394259c57", size = 243314, upload-time = "2025-05-23T11:38:39.238Z" }, - { url = "https://files.pythonhosted.org/packages/39/9f/1afbb2cb9c8699b8bc38afdce00a3b4644904e6a38c7bf9005386c9305ec/coverage-7.8.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9a990f6510b3292686713bfef26d0049cd63b9c7bb17e0864f133cbfd2e6167f", size = 244489, upload-time = "2025-05-23T11:38:40.845Z" }, - { url = "https://files.pythonhosted.org/packages/79/fa/f3e7ec7d220bff14aba7a4786ae47043770cbdceeea1803083059c878837/coverage-7.8.2-cp312-cp312-win32.whl", hash = "sha256:bf8111cddd0f2b54d34e96613e7fbdd59a673f0cf5574b61134ae75b6f5a33b8", size = 214366, upload-time = "2025-05-23T11:38:43.551Z" }, - { url = "https://files.pythonhosted.org/packages/54/aa/9cbeade19b7e8e853e7ffc261df885d66bf3a782c71cba06c17df271f9e6/coverage-7.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:86a323a275e9e44cdf228af9b71c5030861d4d2610886ab920d9945672a81223", size = 215165, upload-time = "2025-05-23T11:38:45.148Z" }, - { url = "https://files.pythonhosted.org/packages/c4/73/e2528bf1237d2448f882bbebaec5c3500ef07301816c5c63464b9da4d88a/coverage-7.8.2-cp312-cp312-win_arm64.whl", hash = "sha256:820157de3a589e992689ffcda8639fbabb313b323d26388d02e154164c57b07f", size = 213548, upload-time = "2025-05-23T11:38:46.74Z" }, - { url = "https://files.pythonhosted.org/packages/1a/93/eb6400a745ad3b265bac36e8077fdffcf0268bdbbb6c02b7220b624c9b31/coverage-7.8.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ea561010914ec1c26ab4188aef8b1567272ef6de096312716f90e5baa79ef8ca", size = 211898, upload-time = "2025-05-23T11:38:49.066Z" }, - { url = "https://files.pythonhosted.org/packages/1b/7c/bdbf113f92683024406a1cd226a199e4200a2001fc85d6a6e7e299e60253/coverage-7.8.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cb86337a4fcdd0e598ff2caeb513ac604d2f3da6d53df2c8e368e07ee38e277d", size = 212171, upload-time = "2025-05-23T11:38:51.207Z" }, - { url = "https://files.pythonhosted.org/packages/91/22/594513f9541a6b88eb0dba4d5da7d71596dadef6b17a12dc2c0e859818a9/coverage-7.8.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26a4636ddb666971345541b59899e969f3b301143dd86b0ddbb570bd591f1e85", size = 245564, upload-time = "2025-05-23T11:38:52.857Z" }, - { url = "https://files.pythonhosted.org/packages/1f/f4/2860fd6abeebd9f2efcfe0fd376226938f22afc80c1943f363cd3c28421f/coverage-7.8.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5040536cf9b13fb033f76bcb5e1e5cb3b57c4807fef37db9e0ed129c6a094257", size = 242719, upload-time = "2025-05-23T11:38:54.529Z" }, - { url = "https://files.pythonhosted.org/packages/89/60/f5f50f61b6332451520e6cdc2401700c48310c64bc2dd34027a47d6ab4ca/coverage-7.8.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc67994df9bcd7e0150a47ef41278b9e0a0ea187caba72414b71dc590b99a108", size = 244634, upload-time = "2025-05-23T11:38:57.326Z" }, - { url = "https://files.pythonhosted.org/packages/3b/70/7f4e919039ab7d944276c446b603eea84da29ebcf20984fb1fdf6e602028/coverage-7.8.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6e6c86888fd076d9e0fe848af0a2142bf606044dc5ceee0aa9eddb56e26895a0", size = 244824, upload-time = "2025-05-23T11:38:59.421Z" }, - { url = "https://files.pythonhosted.org/packages/26/45/36297a4c0cea4de2b2c442fe32f60c3991056c59cdc3cdd5346fbb995c97/coverage-7.8.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:684ca9f58119b8e26bef860db33524ae0365601492e86ba0b71d513f525e7050", size = 242872, upload-time = "2025-05-23T11:39:01.049Z" }, - { url = "https://files.pythonhosted.org/packages/a4/71/e041f1b9420f7b786b1367fa2a375703889ef376e0d48de9f5723fb35f11/coverage-7.8.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8165584ddedb49204c4e18da083913bdf6a982bfb558632a79bdaadcdafd0d48", size = 244179, upload-time = "2025-05-23T11:39:02.709Z" }, - { url = "https://files.pythonhosted.org/packages/bd/db/3c2bf49bdc9de76acf2491fc03130c4ffc51469ce2f6889d2640eb563d77/coverage-7.8.2-cp313-cp313-win32.whl", hash = "sha256:34759ee2c65362163699cc917bdb2a54114dd06d19bab860725f94ef45a3d9b7", size = 214393, upload-time = "2025-05-23T11:39:05.457Z" }, - { url = "https://files.pythonhosted.org/packages/c6/dc/947e75d47ebbb4b02d8babb1fad4ad381410d5bc9da7cfca80b7565ef401/coverage-7.8.2-cp313-cp313-win_amd64.whl", hash = "sha256:2f9bc608fbafaee40eb60a9a53dbfb90f53cc66d3d32c2849dc27cf5638a21e3", size = 215194, upload-time = "2025-05-23T11:39:07.171Z" }, - { url = "https://files.pythonhosted.org/packages/90/31/a980f7df8a37eaf0dc60f932507fda9656b3a03f0abf188474a0ea188d6d/coverage-7.8.2-cp313-cp313-win_arm64.whl", hash = "sha256:9fe449ee461a3b0c7105690419d0b0aba1232f4ff6d120a9e241e58a556733f7", size = 213580, upload-time = "2025-05-23T11:39:08.862Z" }, - { url = "https://files.pythonhosted.org/packages/8a/6a/25a37dd90f6c95f59355629417ebcb74e1c34e38bb1eddf6ca9b38b0fc53/coverage-7.8.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8369a7c8ef66bded2b6484053749ff220dbf83cba84f3398c84c51a6f748a008", size = 212734, upload-time = "2025-05-23T11:39:11.109Z" }, - { url = "https://files.pythonhosted.org/packages/36/8b/3a728b3118988725f40950931abb09cd7f43b3c740f4640a59f1db60e372/coverage-7.8.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:159b81df53a5fcbc7d45dae3adad554fdbde9829a994e15227b3f9d816d00b36", size = 212959, upload-time = "2025-05-23T11:39:12.751Z" }, - { url = "https://files.pythonhosted.org/packages/53/3c/212d94e6add3a3c3f412d664aee452045ca17a066def8b9421673e9482c4/coverage-7.8.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6fcbbd35a96192d042c691c9e0c49ef54bd7ed865846a3c9d624c30bb67ce46", size = 257024, upload-time = "2025-05-23T11:39:15.569Z" }, - { url = "https://files.pythonhosted.org/packages/a4/40/afc03f0883b1e51bbe804707aae62e29c4e8c8bbc365c75e3e4ddeee9ead/coverage-7.8.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:05364b9cc82f138cc86128dc4e2e1251c2981a2218bfcd556fe6b0fbaa3501be", size = 252867, upload-time = "2025-05-23T11:39:17.64Z" }, - { url = "https://files.pythonhosted.org/packages/18/a2/3699190e927b9439c6ded4998941a3c1d6fa99e14cb28d8536729537e307/coverage-7.8.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46d532db4e5ff3979ce47d18e2fe8ecad283eeb7367726da0e5ef88e4fe64740", size = 255096, upload-time = "2025-05-23T11:39:19.328Z" }, - { url = "https://files.pythonhosted.org/packages/b4/06/16e3598b9466456b718eb3e789457d1a5b8bfb22e23b6e8bbc307df5daf0/coverage-7.8.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4000a31c34932e7e4fa0381a3d6deb43dc0c8f458e3e7ea6502e6238e10be625", size = 256276, upload-time = "2025-05-23T11:39:21.077Z" }, - { url = "https://files.pythonhosted.org/packages/a7/d5/4b5a120d5d0223050a53d2783c049c311eea1709fa9de12d1c358e18b707/coverage-7.8.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:43ff5033d657cd51f83015c3b7a443287250dc14e69910577c3e03bd2e06f27b", size = 254478, upload-time = "2025-05-23T11:39:22.838Z" }, - { url = "https://files.pythonhosted.org/packages/ba/85/f9ecdb910ecdb282b121bfcaa32fa8ee8cbd7699f83330ee13ff9bbf1a85/coverage-7.8.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:94316e13f0981cbbba132c1f9f365cac1d26716aaac130866ca812006f662199", size = 255255, upload-time = "2025-05-23T11:39:24.644Z" }, - { url = "https://files.pythonhosted.org/packages/50/63/2d624ac7d7ccd4ebbd3c6a9eba9d7fc4491a1226071360d59dd84928ccb2/coverage-7.8.2-cp313-cp313t-win32.whl", hash = "sha256:3f5673888d3676d0a745c3d0e16da338c5eea300cb1f4ada9c872981265e76d8", size = 215109, upload-time = "2025-05-23T11:39:26.722Z" }, - { url = "https://files.pythonhosted.org/packages/22/5e/7053b71462e970e869111c1853afd642212568a350eba796deefdfbd0770/coverage-7.8.2-cp313-cp313t-win_amd64.whl", hash = "sha256:2c08b05ee8d7861e45dc5a2cc4195c8c66dca5ac613144eb6ebeaff2d502e73d", size = 216268, upload-time = "2025-05-23T11:39:28.429Z" }, - { url = "https://files.pythonhosted.org/packages/07/69/afa41aa34147655543dbe96994f8a246daf94b361ccf5edfd5df62ce066a/coverage-7.8.2-cp313-cp313t-win_arm64.whl", hash = "sha256:1e1448bb72b387755e1ff3ef1268a06617afd94188164960dba8d0245a46004b", size = 214071, upload-time = "2025-05-23T11:39:30.55Z" }, - { url = "https://files.pythonhosted.org/packages/71/1e/388267ad9c6aa126438acc1ceafede3bb746afa9872e3ec5f0691b7d5efa/coverage-7.8.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:496948261eaac5ac9cf43f5d0a9f6eb7a6d4cb3bedb2c5d294138142f5c18f2a", size = 211566, upload-time = "2025-05-23T11:39:32.333Z" }, - { url = "https://files.pythonhosted.org/packages/8f/a5/acc03e5cf0bba6357f5e7c676343de40fbf431bb1e115fbebf24b2f7f65e/coverage-7.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:eacd2de0d30871eff893bab0b67840a96445edcb3c8fd915e6b11ac4b2f3fa6d", size = 211996, upload-time = "2025-05-23T11:39:34.512Z" }, - { url = "https://files.pythonhosted.org/packages/5b/a2/0fc0a9f6b7c24fa4f1d7210d782c38cb0d5e692666c36eaeae9a441b6755/coverage-7.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b039ffddc99ad65d5078ef300e0c7eed08c270dc26570440e3ef18beb816c1ca", size = 240741, upload-time = "2025-05-23T11:39:36.252Z" }, - { url = "https://files.pythonhosted.org/packages/e6/da/1c6ba2cf259710eed8916d4fd201dccc6be7380ad2b3b9f63ece3285d809/coverage-7.8.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e49824808d4375ede9dd84e9961a59c47f9113039f1a525e6be170aa4f5c34d", size = 238672, upload-time = "2025-05-23T11:39:38.03Z" }, - { url = "https://files.pythonhosted.org/packages/ac/51/c8fae0dc3ca421e6e2509503696f910ff333258db672800c3bdef256265a/coverage-7.8.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b069938961dfad881dc2f8d02b47645cd2f455d3809ba92a8a687bf513839787", size = 239769, upload-time = "2025-05-23T11:39:40.24Z" }, - { url = "https://files.pythonhosted.org/packages/59/8e/b97042ae92c59f40be0c989df090027377ba53f2d6cef73c9ca7685c26a6/coverage-7.8.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:de77c3ba8bb686d1c411e78ee1b97e6e0b963fb98b1637658dd9ad2c875cf9d7", size = 239555, upload-time = "2025-05-23T11:39:42.3Z" }, - { url = "https://files.pythonhosted.org/packages/47/35/b8893e682d6e96b1db2af5997fc13ef62219426fb17259d6844c693c5e00/coverage-7.8.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1676628065a498943bd3f64f099bb573e08cf1bc6088bbe33cf4424e0876f4b3", size = 237768, upload-time = "2025-05-23T11:39:44.069Z" }, - { url = "https://files.pythonhosted.org/packages/03/6c/023b0b9a764cb52d6243a4591dcb53c4caf4d7340445113a1f452bb80591/coverage-7.8.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:8e1a26e7e50076e35f7afafde570ca2b4d7900a491174ca357d29dece5aacee7", size = 238757, upload-time = "2025-05-23T11:39:46.195Z" }, - { url = "https://files.pythonhosted.org/packages/03/ed/3af7e4d721bd61a8df7de6de9e8a4271e67f3d9e086454558fd9f48eb4f6/coverage-7.8.2-cp39-cp39-win32.whl", hash = "sha256:6782a12bf76fa61ad9350d5a6ef5f3f020b57f5e6305cbc663803f2ebd0f270a", size = 214166, upload-time = "2025-05-23T11:39:47.934Z" }, - { url = "https://files.pythonhosted.org/packages/9d/30/ee774b626773750dc6128354884652507df3c59d6aa8431526107e595227/coverage-7.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:1efa4166ba75ccefd647f2d78b64f53f14fb82622bc94c5a5cb0a622f50f1c9e", size = 215050, upload-time = "2025-05-23T11:39:50.252Z" }, - { url = "https://files.pythonhosted.org/packages/69/2f/572b29496d8234e4a7773200dd835a0d32d9e171f2d974f3fe04a9dbc271/coverage-7.8.2-pp39.pp310.pp311-none-any.whl", hash = "sha256:ec455eedf3ba0bbdf8f5a570012617eb305c63cb9f03428d39bf544cb2b94837", size = 203636, upload-time = "2025-05-23T11:39:52.002Z" }, - { url = "https://files.pythonhosted.org/packages/a0/1a/0b9c32220ad694d66062f571cc5cedfa9997b64a591e8a500bb63de1bd40/coverage-7.8.2-py3-none-any.whl", hash = "sha256:726f32ee3713f7359696331a18daf0c3b3a70bb0ae71141b9d3c52be7c595e32", size = 203623, upload-time = "2025-05-23T11:39:53.846Z" }, + { url = "https://files.pythonhosted.org/packages/a1/0d/5c2114fd776c207bd55068ae8dc1bef63ecd1b767b3389984a8e58f2b926/coverage-7.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:66283a192a14a3854b2e7f3418d7db05cdf411012ab7ff5db98ff3b181e1f912", size = 212039, upload-time = "2025-07-03T10:52:38.955Z" }, + { url = "https://files.pythonhosted.org/packages/cf/ad/dc51f40492dc2d5fcd31bb44577bc0cc8920757d6bc5d3e4293146524ef9/coverage-7.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4e01d138540ef34fcf35c1aa24d06c3de2a4cffa349e29a10056544f35cca15f", size = 212428, upload-time = "2025-07-03T10:52:41.36Z" }, + { url = "https://files.pythonhosted.org/packages/a2/a3/55cb3ff1b36f00df04439c3993d8529193cdf165a2467bf1402539070f16/coverage-7.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f22627c1fe2745ee98d3ab87679ca73a97e75ca75eb5faee48660d060875465f", size = 241534, upload-time = "2025-07-03T10:52:42.956Z" }, + { url = "https://files.pythonhosted.org/packages/eb/c9/a8410b91b6be4f6e9c2e9f0dce93749b6b40b751d7065b4410bf89cb654b/coverage-7.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b1c2d8363247b46bd51f393f86c94096e64a1cf6906803fa8d5a9d03784bdbf", size = 239408, upload-time = "2025-07-03T10:52:44.199Z" }, + { url = "https://files.pythonhosted.org/packages/ff/c4/6f3e56d467c612b9070ae71d5d3b114c0b899b5788e1ca3c93068ccb7018/coverage-7.9.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c10c882b114faf82dbd33e876d0cbd5e1d1ebc0d2a74ceef642c6152f3f4d547", size = 240552, upload-time = "2025-07-03T10:52:45.477Z" }, + { url = "https://files.pythonhosted.org/packages/fd/20/04eda789d15af1ce79bce5cc5fd64057c3a0ac08fd0576377a3096c24663/coverage-7.9.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:de3c0378bdf7066c3988d66cd5232d161e933b87103b014ab1b0b4676098fa45", size = 240464, upload-time = "2025-07-03T10:52:46.809Z" }, + { url = "https://files.pythonhosted.org/packages/a9/5a/217b32c94cc1a0b90f253514815332d08ec0812194a1ce9cca97dda1cd20/coverage-7.9.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:1e2f097eae0e5991e7623958a24ced3282676c93c013dde41399ff63e230fcf2", size = 239134, upload-time = "2025-07-03T10:52:48.149Z" }, + { url = "https://files.pythonhosted.org/packages/34/73/1d019c48f413465eb5d3b6898b6279e87141c80049f7dbf73fd020138549/coverage-7.9.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:28dc1f67e83a14e7079b6cea4d314bc8b24d1aed42d3582ff89c0295f09b181e", size = 239405, upload-time = "2025-07-03T10:52:49.687Z" }, + { url = "https://files.pythonhosted.org/packages/49/6c/a2beca7aa2595dad0c0d3f350382c381c92400efe5261e2631f734a0e3fe/coverage-7.9.2-cp310-cp310-win32.whl", hash = "sha256:bf7d773da6af9e10dbddacbf4e5cab13d06d0ed93561d44dae0188a42c65be7e", size = 214519, upload-time = "2025-07-03T10:52:51.036Z" }, + { url = "https://files.pythonhosted.org/packages/fc/c8/91e5e4a21f9a51e2c7cdd86e587ae01a4fcff06fc3fa8cde4d6f7cf68df4/coverage-7.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:0c0378ba787681ab1897f7c89b415bd56b0b2d9a47e5a3d8dc0ea55aac118d6c", size = 215400, upload-time = "2025-07-03T10:52:52.313Z" }, + { url = "https://files.pythonhosted.org/packages/39/40/916786453bcfafa4c788abee4ccd6f592b5b5eca0cd61a32a4e5a7ef6e02/coverage-7.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a7a56a2964a9687b6aba5b5ced6971af308ef6f79a91043c05dd4ee3ebc3e9ba", size = 212152, upload-time = "2025-07-03T10:52:53.562Z" }, + { url = "https://files.pythonhosted.org/packages/9f/66/cc13bae303284b546a030762957322bbbff1ee6b6cb8dc70a40f8a78512f/coverage-7.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:123d589f32c11d9be7fe2e66d823a236fe759b0096f5db3fb1b75b2fa414a4fa", size = 212540, upload-time = "2025-07-03T10:52:55.196Z" }, + { url = "https://files.pythonhosted.org/packages/0f/3c/d56a764b2e5a3d43257c36af4a62c379df44636817bb5f89265de4bf8bd7/coverage-7.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:333b2e0ca576a7dbd66e85ab402e35c03b0b22f525eed82681c4b866e2e2653a", size = 245097, upload-time = "2025-07-03T10:52:56.509Z" }, + { url = "https://files.pythonhosted.org/packages/b1/46/bd064ea8b3c94eb4ca5d90e34d15b806cba091ffb2b8e89a0d7066c45791/coverage-7.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:326802760da234baf9f2f85a39e4a4b5861b94f6c8d95251f699e4f73b1835dc", size = 242812, upload-time = "2025-07-03T10:52:57.842Z" }, + { url = "https://files.pythonhosted.org/packages/43/02/d91992c2b29bc7afb729463bc918ebe5f361be7f1daae93375a5759d1e28/coverage-7.9.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19e7be4cfec248df38ce40968c95d3952fbffd57b400d4b9bb580f28179556d2", size = 244617, upload-time = "2025-07-03T10:52:59.239Z" }, + { url = "https://files.pythonhosted.org/packages/b7/4f/8fadff6bf56595a16d2d6e33415841b0163ac660873ed9a4e9046194f779/coverage-7.9.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0b4a4cb73b9f2b891c1788711408ef9707666501ba23684387277ededab1097c", size = 244263, upload-time = "2025-07-03T10:53:00.601Z" }, + { url = "https://files.pythonhosted.org/packages/9b/d2/e0be7446a2bba11739edb9f9ba4eff30b30d8257370e237418eb44a14d11/coverage-7.9.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:2c8937fa16c8c9fbbd9f118588756e7bcdc7e16a470766a9aef912dd3f117dbd", size = 242314, upload-time = "2025-07-03T10:53:01.932Z" }, + { url = "https://files.pythonhosted.org/packages/9d/7d/dcbac9345000121b8b57a3094c2dfcf1ccc52d8a14a40c1d4bc89f936f80/coverage-7.9.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:42da2280c4d30c57a9b578bafd1d4494fa6c056d4c419d9689e66d775539be74", size = 242904, upload-time = "2025-07-03T10:53:03.478Z" }, + { url = "https://files.pythonhosted.org/packages/41/58/11e8db0a0c0510cf31bbbdc8caf5d74a358b696302a45948d7c768dfd1cf/coverage-7.9.2-cp311-cp311-win32.whl", hash = "sha256:14fa8d3da147f5fdf9d298cacc18791818f3f1a9f542c8958b80c228320e90c6", size = 214553, upload-time = "2025-07-03T10:53:05.174Z" }, + { url = "https://files.pythonhosted.org/packages/3a/7d/751794ec8907a15e257136e48dc1021b1f671220ecccfd6c4eaf30802714/coverage-7.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:549cab4892fc82004f9739963163fd3aac7a7b0df430669b75b86d293d2df2a7", size = 215441, upload-time = "2025-07-03T10:53:06.472Z" }, + { url = "https://files.pythonhosted.org/packages/62/5b/34abcedf7b946c1c9e15b44f326cb5b0da852885312b30e916f674913428/coverage-7.9.2-cp311-cp311-win_arm64.whl", hash = "sha256:c2667a2b913e307f06aa4e5677f01a9746cd08e4b35e14ebcde6420a9ebb4c62", size = 213873, upload-time = "2025-07-03T10:53:07.699Z" }, + { url = "https://files.pythonhosted.org/packages/53/d7/7deefc6fd4f0f1d4c58051f4004e366afc9e7ab60217ac393f247a1de70a/coverage-7.9.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ae9eb07f1cfacd9cfe8eaee6f4ff4b8a289a668c39c165cd0c8548484920ffc0", size = 212344, upload-time = "2025-07-03T10:53:09.3Z" }, + { url = "https://files.pythonhosted.org/packages/95/0c/ee03c95d32be4d519e6a02e601267769ce2e9a91fc8faa1b540e3626c680/coverage-7.9.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9ce85551f9a1119f02adc46d3014b5ee3f765deac166acf20dbb851ceb79b6f3", size = 212580, upload-time = "2025-07-03T10:53:11.52Z" }, + { url = "https://files.pythonhosted.org/packages/8b/9f/826fa4b544b27620086211b87a52ca67592622e1f3af9e0a62c87aea153a/coverage-7.9.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8f6389ac977c5fb322e0e38885fbbf901743f79d47f50db706e7644dcdcb6e1", size = 246383, upload-time = "2025-07-03T10:53:13.134Z" }, + { url = "https://files.pythonhosted.org/packages/7f/b3/4477aafe2a546427b58b9c540665feff874f4db651f4d3cb21b308b3a6d2/coverage-7.9.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff0d9eae8cdfcd58fe7893b88993723583a6ce4dfbfd9f29e001922544f95615", size = 243400, upload-time = "2025-07-03T10:53:14.614Z" }, + { url = "https://files.pythonhosted.org/packages/f8/c2/efffa43778490c226d9d434827702f2dfbc8041d79101a795f11cbb2cf1e/coverage-7.9.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fae939811e14e53ed8a9818dad51d434a41ee09df9305663735f2e2d2d7d959b", size = 245591, upload-time = "2025-07-03T10:53:15.872Z" }, + { url = "https://files.pythonhosted.org/packages/c6/e7/a59888e882c9a5f0192d8627a30ae57910d5d449c80229b55e7643c078c4/coverage-7.9.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:31991156251ec202c798501e0a42bbdf2169dcb0f137b1f5c0f4267f3fc68ef9", size = 245402, upload-time = "2025-07-03T10:53:17.124Z" }, + { url = "https://files.pythonhosted.org/packages/92/a5/72fcd653ae3d214927edc100ce67440ed8a0a1e3576b8d5e6d066ed239db/coverage-7.9.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d0d67963f9cbfc7c7f96d4ac74ed60ecbebd2ea6eeb51887af0f8dce205e545f", size = 243583, upload-time = "2025-07-03T10:53:18.781Z" }, + { url = "https://files.pythonhosted.org/packages/5c/f5/84e70e4df28f4a131d580d7d510aa1ffd95037293da66fd20d446090a13b/coverage-7.9.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:49b752a2858b10580969ec6af6f090a9a440a64a301ac1528d7ca5f7ed497f4d", size = 244815, upload-time = "2025-07-03T10:53:20.168Z" }, + { url = "https://files.pythonhosted.org/packages/39/e7/d73d7cbdbd09fdcf4642655ae843ad403d9cbda55d725721965f3580a314/coverage-7.9.2-cp312-cp312-win32.whl", hash = "sha256:88d7598b8ee130f32f8a43198ee02edd16d7f77692fa056cb779616bbea1b355", size = 214719, upload-time = "2025-07-03T10:53:21.521Z" }, + { url = "https://files.pythonhosted.org/packages/9f/d6/7486dcc3474e2e6ad26a2af2db7e7c162ccd889c4c68fa14ea8ec189c9e9/coverage-7.9.2-cp312-cp312-win_amd64.whl", hash = "sha256:9dfb070f830739ee49d7c83e4941cc767e503e4394fdecb3b54bfdac1d7662c0", size = 215509, upload-time = "2025-07-03T10:53:22.853Z" }, + { url = "https://files.pythonhosted.org/packages/b7/34/0439f1ae2593b0346164d907cdf96a529b40b7721a45fdcf8b03c95fcd90/coverage-7.9.2-cp312-cp312-win_arm64.whl", hash = "sha256:4e2c058aef613e79df00e86b6d42a641c877211384ce5bd07585ed7ba71ab31b", size = 213910, upload-time = "2025-07-03T10:53:24.472Z" }, + { url = "https://files.pythonhosted.org/packages/94/9d/7a8edf7acbcaa5e5c489a646226bed9591ee1c5e6a84733c0140e9ce1ae1/coverage-7.9.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:985abe7f242e0d7bba228ab01070fde1d6c8fa12f142e43debe9ed1dde686038", size = 212367, upload-time = "2025-07-03T10:53:25.811Z" }, + { url = "https://files.pythonhosted.org/packages/e8/9e/5cd6f130150712301f7e40fb5865c1bc27b97689ec57297e568d972eec3c/coverage-7.9.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82c3939264a76d44fde7f213924021ed31f55ef28111a19649fec90c0f109e6d", size = 212632, upload-time = "2025-07-03T10:53:27.075Z" }, + { url = "https://files.pythonhosted.org/packages/a8/de/6287a2c2036f9fd991c61cefa8c64e57390e30c894ad3aa52fac4c1e14a8/coverage-7.9.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae5d563e970dbe04382f736ec214ef48103d1b875967c89d83c6e3f21706d5b3", size = 245793, upload-time = "2025-07-03T10:53:28.408Z" }, + { url = "https://files.pythonhosted.org/packages/06/cc/9b5a9961d8160e3cb0b558c71f8051fe08aa2dd4b502ee937225da564ed1/coverage-7.9.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bdd612e59baed2a93c8843c9a7cb902260f181370f1d772f4842987535071d14", size = 243006, upload-time = "2025-07-03T10:53:29.754Z" }, + { url = "https://files.pythonhosted.org/packages/49/d9/4616b787d9f597d6443f5588619c1c9f659e1f5fc9eebf63699eb6d34b78/coverage-7.9.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:256ea87cb2a1ed992bcdfc349d8042dcea1b80436f4ddf6e246d6bee4b5d73b6", size = 244990, upload-time = "2025-07-03T10:53:31.098Z" }, + { url = "https://files.pythonhosted.org/packages/48/83/801cdc10f137b2d02b005a761661649ffa60eb173dcdaeb77f571e4dc192/coverage-7.9.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f44ae036b63c8ea432f610534a2668b0c3aee810e7037ab9d8ff6883de480f5b", size = 245157, upload-time = "2025-07-03T10:53:32.717Z" }, + { url = "https://files.pythonhosted.org/packages/c8/a4/41911ed7e9d3ceb0ffb019e7635468df7499f5cc3edca5f7dfc078e9c5ec/coverage-7.9.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:82d76ad87c932935417a19b10cfe7abb15fd3f923cfe47dbdaa74ef4e503752d", size = 243128, upload-time = "2025-07-03T10:53:34.009Z" }, + { url = "https://files.pythonhosted.org/packages/10/41/344543b71d31ac9cb00a664d5d0c9ef134a0fe87cb7d8430003b20fa0b7d/coverage-7.9.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:619317bb86de4193debc712b9e59d5cffd91dc1d178627ab2a77b9870deb2868", size = 244511, upload-time = "2025-07-03T10:53:35.434Z" }, + { url = "https://files.pythonhosted.org/packages/d5/81/3b68c77e4812105e2a060f6946ba9e6f898ddcdc0d2bfc8b4b152a9ae522/coverage-7.9.2-cp313-cp313-win32.whl", hash = "sha256:0a07757de9feb1dfafd16ab651e0f628fd7ce551604d1bf23e47e1ddca93f08a", size = 214765, upload-time = "2025-07-03T10:53:36.787Z" }, + { url = "https://files.pythonhosted.org/packages/06/a2/7fac400f6a346bb1a4004eb2a76fbff0e242cd48926a2ce37a22a6a1d917/coverage-7.9.2-cp313-cp313-win_amd64.whl", hash = "sha256:115db3d1f4d3f35f5bb021e270edd85011934ff97c8797216b62f461dd69374b", size = 215536, upload-time = "2025-07-03T10:53:38.188Z" }, + { url = "https://files.pythonhosted.org/packages/08/47/2c6c215452b4f90d87017e61ea0fd9e0486bb734cb515e3de56e2c32075f/coverage-7.9.2-cp313-cp313-win_arm64.whl", hash = "sha256:48f82f889c80af8b2a7bb6e158d95a3fbec6a3453a1004d04e4f3b5945a02694", size = 213943, upload-time = "2025-07-03T10:53:39.492Z" }, + { url = "https://files.pythonhosted.org/packages/a3/46/e211e942b22d6af5e0f323faa8a9bc7c447a1cf1923b64c47523f36ed488/coverage-7.9.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:55a28954545f9d2f96870b40f6c3386a59ba8ed50caf2d949676dac3ecab99f5", size = 213088, upload-time = "2025-07-03T10:53:40.874Z" }, + { url = "https://files.pythonhosted.org/packages/d2/2f/762551f97e124442eccd907bf8b0de54348635b8866a73567eb4e6417acf/coverage-7.9.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:cdef6504637731a63c133bb2e6f0f0214e2748495ec15fe42d1e219d1b133f0b", size = 213298, upload-time = "2025-07-03T10:53:42.218Z" }, + { url = "https://files.pythonhosted.org/packages/7a/b7/76d2d132b7baf7360ed69be0bcab968f151fa31abe6d067f0384439d9edb/coverage-7.9.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcd5ebe66c7a97273d5d2ddd4ad0ed2e706b39630ed4b53e713d360626c3dbb3", size = 256541, upload-time = "2025-07-03T10:53:43.823Z" }, + { url = "https://files.pythonhosted.org/packages/a0/17/392b219837d7ad47d8e5974ce5f8dc3deb9f99a53b3bd4d123602f960c81/coverage-7.9.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9303aed20872d7a3c9cb39c5d2b9bdbe44e3a9a1aecb52920f7e7495410dfab8", size = 252761, upload-time = "2025-07-03T10:53:45.19Z" }, + { url = "https://files.pythonhosted.org/packages/d5/77/4256d3577fe1b0daa8d3836a1ebe68eaa07dd2cbaf20cf5ab1115d6949d4/coverage-7.9.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc18ea9e417a04d1920a9a76fe9ebd2f43ca505b81994598482f938d5c315f46", size = 254917, upload-time = "2025-07-03T10:53:46.931Z" }, + { url = "https://files.pythonhosted.org/packages/53/99/fc1a008eef1805e1ddb123cf17af864743354479ea5129a8f838c433cc2c/coverage-7.9.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6406cff19880aaaadc932152242523e892faff224da29e241ce2fca329866584", size = 256147, upload-time = "2025-07-03T10:53:48.289Z" }, + { url = "https://files.pythonhosted.org/packages/92/c0/f63bf667e18b7f88c2bdb3160870e277c4874ced87e21426128d70aa741f/coverage-7.9.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:2d0d4f6ecdf37fcc19c88fec3e2277d5dee740fb51ffdd69b9579b8c31e4232e", size = 254261, upload-time = "2025-07-03T10:53:49.99Z" }, + { url = "https://files.pythonhosted.org/packages/8c/32/37dd1c42ce3016ff8ec9e4b607650d2e34845c0585d3518b2a93b4830c1a/coverage-7.9.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c33624f50cf8de418ab2b4d6ca9eda96dc45b2c4231336bac91454520e8d1fac", size = 255099, upload-time = "2025-07-03T10:53:51.354Z" }, + { url = "https://files.pythonhosted.org/packages/da/2e/af6b86f7c95441ce82f035b3affe1cd147f727bbd92f563be35e2d585683/coverage-7.9.2-cp313-cp313t-win32.whl", hash = "sha256:1df6b76e737c6a92210eebcb2390af59a141f9e9430210595251fbaf02d46926", size = 215440, upload-time = "2025-07-03T10:53:52.808Z" }, + { url = "https://files.pythonhosted.org/packages/4d/bb/8a785d91b308867f6b2e36e41c569b367c00b70c17f54b13ac29bcd2d8c8/coverage-7.9.2-cp313-cp313t-win_amd64.whl", hash = "sha256:f5fd54310b92741ebe00d9c0d1d7b2b27463952c022da6d47c175d246a98d1bd", size = 216537, upload-time = "2025-07-03T10:53:54.273Z" }, + { url = "https://files.pythonhosted.org/packages/1d/a0/a6bffb5e0f41a47279fd45a8f3155bf193f77990ae1c30f9c224b61cacb0/coverage-7.9.2-cp313-cp313t-win_arm64.whl", hash = "sha256:c48c2375287108c887ee87d13b4070a381c6537d30e8487b24ec721bf2a781cb", size = 214398, upload-time = "2025-07-03T10:53:56.715Z" }, + { url = "https://files.pythonhosted.org/packages/62/ab/b4b06662ccaa00ca7bbee967b7035a33a58b41efb92d8c89a6c523a2ccd5/coverage-7.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ddc39510ac922a5c4c27849b739f875d3e1d9e590d1e7b64c98dadf037a16cce", size = 212037, upload-time = "2025-07-03T10:53:58.055Z" }, + { url = "https://files.pythonhosted.org/packages/bb/5e/04619995657acc898d15bfad42b510344b3a74d4d5bc34f2e279d46c781c/coverage-7.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a535c0c7364acd55229749c2b3e5eebf141865de3a8f697076a3291985f02d30", size = 212412, upload-time = "2025-07-03T10:53:59.451Z" }, + { url = "https://files.pythonhosted.org/packages/14/e7/1465710224dc6d31c534e7714cbd907210622a044adc81c810e72eea873f/coverage-7.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df0f9ef28e0f20c767ccdccfc5ae5f83a6f4a2fbdfbcbcc8487a8a78771168c8", size = 241164, upload-time = "2025-07-03T10:54:00.852Z" }, + { url = "https://files.pythonhosted.org/packages/ab/f2/44c6fbd2794afeb9ab6c0a14d3c088ab1dae3dff3df2624609981237bbb4/coverage-7.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f3da12e0ccbcb348969221d29441ac714bbddc4d74e13923d3d5a7a0bebef7a", size = 239032, upload-time = "2025-07-03T10:54:02.25Z" }, + { url = "https://files.pythonhosted.org/packages/6a/d2/7a79845429c0aa2e6788bc45c26a2e3052fa91082c9ea1dea56fb531952c/coverage-7.9.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a17eaf46f56ae0f870f14a3cbc2e4632fe3771eab7f687eda1ee59b73d09fe4", size = 240148, upload-time = "2025-07-03T10:54:03.618Z" }, + { url = "https://files.pythonhosted.org/packages/9c/7d/2731d1b4c9c672d82d30d218224dfc62939cf3800bc8aba0258fefb191f5/coverage-7.9.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:669135a9d25df55d1ed56a11bf555f37c922cf08d80799d4f65d77d7d6123fcf", size = 239875, upload-time = "2025-07-03T10:54:05.022Z" }, + { url = "https://files.pythonhosted.org/packages/1b/83/685958715429a9da09cf172c15750ca5c795dd7259466f2645403696557b/coverage-7.9.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:9d3a700304d01a627df9db4322dc082a0ce1e8fc74ac238e2af39ced4c083193", size = 238127, upload-time = "2025-07-03T10:54:06.366Z" }, + { url = "https://files.pythonhosted.org/packages/34/ff/161a4313308b3783126790adfae1970adbe4886fda8788792e435249910a/coverage-7.9.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:71ae8b53855644a0b1579d4041304ddc9995c7b21c8a1f16753c4d8903b4dfed", size = 239064, upload-time = "2025-07-03T10:54:07.878Z" }, + { url = "https://files.pythonhosted.org/packages/17/14/fe33f41b2e80811021de059621f44c01ebe4d6b08bdb82d54a514488e933/coverage-7.9.2-cp39-cp39-win32.whl", hash = "sha256:dd7a57b33b5cf27acb491e890720af45db05589a80c1ffc798462a765be6d4d7", size = 214522, upload-time = "2025-07-03T10:54:09.331Z" }, + { url = "https://files.pythonhosted.org/packages/6e/30/63d850ec31b5c6f6a7b4e853016375b846258300320eda29376e2786ceeb/coverage-7.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:f65bb452e579d5540c8b37ec105dd54d8b9307b07bcaa186818c104ffda22441", size = 215419, upload-time = "2025-07-03T10:54:10.681Z" }, + { url = "https://files.pythonhosted.org/packages/d7/85/f8bbefac27d286386961c25515431482a425967e23d3698b75a250872924/coverage-7.9.2-pp39.pp310.pp311-none-any.whl", hash = "sha256:8a1166db2fb62473285bcb092f586e081e92656c7dfa8e9f62b4d39d7e6b5050", size = 204013, upload-time = "2025-07-03T10:54:12.084Z" }, + { url = "https://files.pythonhosted.org/packages/3c/38/bbe2e63902847cf79036ecc75550d0698af31c91c7575352eb25190d0fb3/coverage-7.9.2-py3-none-any.whl", hash = "sha256:e425cd5b00f6fc0ed7cdbd766c70be8baab4b7839e4d4fe5fac48581dd968ea4", size = 204005, upload-time = "2025-07-03T10:54:13.491Z" }, ] [package.optional-dependencies] @@ -482,7 +476,7 @@ name = "cryptography" version = "44.0.3" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "cffi", marker = "python_full_version >= '3.11' and python_full_version < '4.0' and platform_python_implementation != 'PyPy'" }, + { name = "cffi", marker = "python_full_version >= '3.11' and platform_python_implementation != 'PyPy'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/53/d6/1411ab4d6108ab167d06254c5be517681f1e331f90edf1379895bcb87020/cryptography-44.0.3.tar.gz", hash = "sha256:fe19d8bc5536a91a24a8133328880a41831b6c5df54599a8417b62fe015d3053", size = 711096, upload-time = "2025-05-02T19:36:04.667Z" } wheels = [ @@ -676,7 +670,7 @@ name = "importlib-metadata" version = "8.7.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "zipp", marker = "python_full_version < '3.10'" }, + { name = "zipp", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/76/66/650a33bd90f786193e4de4b3ad86ea60b53c89b669a5c7be931fac31cdb0/importlib_metadata-8.7.0.tar.gz", hash = "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000", size = 56641, upload-time = "2025-04-27T15:29:01.736Z" } wheels = [ @@ -701,8 +695,8 @@ dependencies = [ { name = "comm" }, { name = "debugpy" }, { name = "ipython", version = "8.18.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "ipython", version = "8.36.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, - { name = "ipython", version = "9.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "ipython", version = "8.37.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, + { name = "ipython", version = "9.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "jupyter-client" }, { name = "jupyter-core" }, { name = "matplotlib-inline" }, @@ -745,7 +739,7 @@ wheels = [ [[package]] name = "ipython" -version = "8.36.0" +version = "8.37.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version == '3.10.*'", @@ -763,20 +757,17 @@ dependencies = [ { name = "traitlets", marker = "python_full_version == '3.10.*'" }, { name = "typing-extensions", marker = "python_full_version == '3.10.*'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a2/9f/d9a73710df947b7804bd9d93509463fb3a89e0ddc99c9fcc67279cddbeb6/ipython-8.36.0.tar.gz", hash = "sha256:24658e9fe5c5c819455043235ba59cfffded4a35936eefceceab6b192f7092ff", size = 5604997, upload-time = "2025-04-25T18:03:38.031Z" } +sdist = { url = "https://files.pythonhosted.org/packages/85/31/10ac88f3357fc276dc8a64e8880c82e80e7459326ae1d0a211b40abf6665/ipython-8.37.0.tar.gz", hash = "sha256:ca815841e1a41a1e6b73a0b08f3038af9b2252564d01fc405356d34033012216", size = 5606088, upload-time = "2025-05-31T16:39:09.613Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d6/d7/c1c9f371790b3a181e343c4815a361e5a0cc7d90ef6642d64ba5d05de289/ipython-8.36.0-py3-none-any.whl", hash = "sha256:12b913914d010dcffa2711505ec8be4bf0180742d97f1e5175e51f22086428c1", size = 831074, upload-time = "2025-04-25T18:03:34.951Z" }, + { url = "https://files.pythonhosted.org/packages/91/d0/274fbf7b0b12643cbbc001ce13e6a5b1607ac4929d1b11c72460152c9fc3/ipython-8.37.0-py3-none-any.whl", hash = "sha256:ed87326596b878932dbcb171e3e698845434d8c61b8d8cd474bf663041a9dcf2", size = 831864, upload-time = "2025-05-31T16:39:06.38Z" }, ] [[package]] name = "ipython" -version = "9.2.0" +version = "9.4.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version >= '3.13' and python_full_version < '4.0'", - "python_full_version >= '3.12.4' and python_full_version < '3.13'", - "python_full_version >= '3.11' and python_full_version < '3.12.4'", - "python_full_version >= '4.0'", + "python_full_version >= '3.11'", ] dependencies = [ { name = "colorama", marker = "python_full_version >= '3.11' and sys_platform == 'win32'" }, @@ -791,9 +782,9 @@ dependencies = [ { name = "traitlets", marker = "python_full_version >= '3.11'" }, { name = "typing-extensions", marker = "python_full_version == '3.11.*'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9d/02/63a84444a7409b3c0acd1de9ffe524660e0e5d82ee473e78b45e5bfb64a4/ipython-9.2.0.tar.gz", hash = "sha256:62a9373dbc12f28f9feaf4700d052195bf89806279fc8ca11f3f54017d04751b", size = 4424394, upload-time = "2025-04-25T17:55:40.498Z" } +sdist = { url = "https://files.pythonhosted.org/packages/54/80/406f9e3bde1c1fd9bf5a0be9d090f8ae623e401b7670d8f6fdf2ab679891/ipython-9.4.0.tar.gz", hash = "sha256:c033c6d4e7914c3d9768aabe76bbe87ba1dc66a92a05db6bfa1125d81f2ee270", size = 4385338, upload-time = "2025-07-01T11:11:30.606Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/78/ce/5e897ee51b7d26ab4e47e5105e7368d40ce6cfae2367acdf3165396d50be/ipython-9.2.0-py3-none-any.whl", hash = "sha256:fef5e33c4a1ae0759e0bba5917c9db4eb8c53fee917b6a526bd973e1ca5159f6", size = 604277, upload-time = "2025-04-25T17:55:37.625Z" }, + { url = "https://files.pythonhosted.org/packages/63/f8/0031ee2b906a15a33d6bfc12dd09c3dfa966b3cb5b284ecfb7549e6ac3c4/ipython-9.4.0-py3-none-any.whl", hash = "sha256:25850f025a446d9b359e8d296ba175a36aedd32e83ca9b5060430fe16801f066", size = 611021, upload-time = "2025-07-01T11:11:27.85Z" }, ] [[package]] @@ -815,8 +806,8 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "comm" }, { name = "ipython", version = "8.18.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "ipython", version = "8.36.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, - { name = "ipython", version = "9.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "ipython", version = "8.37.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, + { name = "ipython", version = "9.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "jupyterlab-widgets" }, { name = "traitlets" }, { name = "widgetsnbextension" }, @@ -1015,8 +1006,8 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "ipykernel" }, { name = "ipython", version = "8.18.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "ipython", version = "8.36.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, - { name = "ipython", version = "9.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "ipython", version = "8.37.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, + { name = "ipython", version = "9.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "jupyter-client" }, { name = "jupyter-core" }, { name = "prompt-toolkit" }, @@ -1120,7 +1111,7 @@ wheels = [ [[package]] name = "jupyterlab" -version = "4.4.3" +version = "4.4.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "async-lru" }, @@ -1139,9 +1130,9 @@ dependencies = [ { name = "tornado" }, { name = "traitlets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d3/2d/d1678dcf2db66cb4a38a80d9e5fcf48c349f3ac12f2d38882993353ae768/jupyterlab-4.4.3.tar.gz", hash = "sha256:a94c32fd7f8b93e82a49dc70a6ec45a5c18281ca2a7228d12765e4e210e5bca2", size = 23032376, upload-time = "2025-05-26T11:18:00.996Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e2/4d/7ca5b46ea56742880d71a768a9e6fb8f8482228427eb89492d55c5d0bb7d/jupyterlab-4.4.4.tar.gz", hash = "sha256:163fee1ef702e0a057f75d2eed3ed1da8a986d59eb002cbeb6f0c2779e6cd153", size = 23044296, upload-time = "2025-06-28T13:07:20.708Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c6/4d/7dd5c2ffbb960930452a031dc8410746183c924580f2ab4e68ceb5b3043f/jupyterlab-4.4.3-py3-none-any.whl", hash = "sha256:164302f6d4b6c44773dfc38d585665a4db401a16e5296c37df5cba63904fbdea", size = 12295480, upload-time = "2025-05-26T11:17:56.607Z" }, + { url = "https://files.pythonhosted.org/packages/f8/82/66910ce0995dbfdb33609f41c99fe32ce483b9624a3e7d672af14ff63b9f/jupyterlab-4.4.4-py3-none-any.whl", hash = "sha256:711611e4f59851152eb93316c3547c3ec6291f16bb455f1f4fa380d25637e0dd", size = 12296310, upload-time = "2025-06-28T13:07:15.676Z" }, ] [[package]] @@ -1183,7 +1174,7 @@ wheels = [ [[package]] name = "langchain-core" -version = "0.3.67" +version = "0.3.68" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jsonpatch" }, @@ -1194,9 +1185,9 @@ dependencies = [ { name = "tenacity" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c2/40/875af0194024d0006874f061958fa417d3500bbfdc9a57e1bd1c2f4e6ed2/langchain_core-0.3.67.tar.gz", hash = "sha256:2c14aa44a0e78e014e96d7f2f8916ac109d0a0ba87ed67ee25bf7296bed7e7ba", size = 561952, upload-time = "2025-06-30T17:09:35.142Z" } +sdist = { url = "https://files.pythonhosted.org/packages/23/20/f5b18a17bfbe3416177e702ab2fd230b7d168abb17be31fb48f43f0bb772/langchain_core-0.3.68.tar.gz", hash = "sha256:312e1932ac9aa2eaf111b70fdc171776fa571d1a86c1f873dcac88a094b19c6f", size = 563041, upload-time = "2025-07-03T17:02:28.704Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9f/2b/a0d283089c6d08c12d47dca39a55029ff714e939ec04f4560420426ab613/langchain_core-0.3.67-py3-none-any.whl", hash = "sha256:b699f1f24b24fa2747c05e2daa280aa64478a51e01a4e82c7f8e20b6167dfa99", size = 440237, upload-time = "2025-06-30T17:09:33.323Z" }, + { url = "https://files.pythonhosted.org/packages/f9/da/c89be0a272993bfcb762b2a356b9f55de507784c2755ad63caec25d183bf/langchain_core-0.3.68-py3-none-any.whl", hash = "sha256:5e5c1fbef419590537c91b8c2d86af896fbcbaf0d5ed7fdcdd77f7d8f3467ba0", size = 441405, upload-time = "2025-07-03T17:02:27.115Z" }, ] [[package]] @@ -1280,32 +1271,32 @@ dev = [ [[package]] name = "langgraph-api" -version = "0.2.36" +version = "0.2.78" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "cloudpickle", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, - { name = "cryptography", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, - { name = "httpx", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, - { name = "jsonschema-rs", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, - { name = "langchain-core", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, - { name = "langgraph", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, - { name = "langgraph-checkpoint", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, - { name = "langgraph-runtime-inmem", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, - { name = "langgraph-sdk", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, - { name = "langsmith", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, - { name = "orjson", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, - { name = "pyjwt", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, - { name = "sse-starlette", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, - { name = "starlette", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, - { name = "structlog", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, - { name = "tenacity", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, - { name = "truststore", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, - { name = "uvicorn", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, - { name = "watchfiles", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, + { name = "cloudpickle", marker = "python_full_version >= '3.11'" }, + { name = "cryptography", marker = "python_full_version >= '3.11'" }, + { name = "httpx", marker = "python_full_version >= '3.11'" }, + { name = "jsonschema-rs", marker = "python_full_version >= '3.11'" }, + { name = "langchain-core", marker = "python_full_version >= '3.11'" }, + { name = "langgraph", marker = "python_full_version >= '3.11'" }, + { name = "langgraph-checkpoint", marker = "python_full_version >= '3.11'" }, + { name = "langgraph-runtime-inmem", marker = "python_full_version >= '3.11'" }, + { name = "langgraph-sdk", marker = "python_full_version >= '3.11'" }, + { name = "langsmith", marker = "python_full_version >= '3.11'" }, + { name = "orjson", marker = "python_full_version >= '3.11'" }, + { name = "pyjwt", marker = "python_full_version >= '3.11'" }, + { name = "sse-starlette", marker = "python_full_version >= '3.11'" }, + { name = "starlette", marker = "python_full_version >= '3.11'" }, + { name = "structlog", marker = "python_full_version >= '3.11'" }, + { name = "tenacity", marker = "python_full_version >= '3.11'" }, + { name = "truststore", marker = "python_full_version >= '3.11'" }, + { name = "uvicorn", marker = "python_full_version >= '3.11'" }, + { name = "watchfiles", marker = "python_full_version >= '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0c/57/ea1a163198909f0e8713584d49858ef8884f2d1f14273fd3c40344480606/langgraph_api-0.2.36.tar.gz", hash = "sha256:5d45dce8733b954e61b142abc28d0962a37b03ffc578e20f2ccbc98d48579ece", size = 213623, upload-time = "2025-05-29T20:55:34.628Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ba/88/1aa91bede22d1393a53605ff13a57d6cb3ce2831eb250a8a8f814c548d2e/langgraph_api-0.2.78.tar.gz", hash = "sha256:37aad4fe764934f358dbb26d50b4acbf4180aac673499d1502b5b468cc7acba4", size = 233581, upload-time = "2025-07-02T19:11:01.154Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b6/b7/0d05bbcd42a9070aa200e6001b466ef29d274c4715b654d4f6741a7ed8f5/langgraph_api-0.2.36-py3-none-any.whl", hash = "sha256:e01579d4322c9ce65d0eb8361092a301bcd12d375adb2e806274c7692fe3d8da", size = 177962, upload-time = "2025-05-29T20:55:33.446Z" }, + { url = "https://files.pythonhosted.org/packages/7e/76/46626d99c36fce0c1ee1e1581f54b29acbed5e9f2e7cf9a198c825547d91/langgraph_api-0.2.78-py3-none-any.whl", hash = "sha256:57abe7fff9763d6f4eaf4419d103f75e77dca6d271db3816777c04bd67db4449", size = 190222, upload-time = "2025-07-02T19:10:59.793Z" }, ] [[package]] @@ -1403,21 +1394,22 @@ dev = [ [[package]] name = "langgraph-cli" -version = "0.2.10" +version = "0.3.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "click", version = "8.2.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "langgraph-sdk", marker = "python_full_version >= '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8d/5e/b12bc8140cd4f797ad7f596bf90558994fd6891df8974bc3fc4747eabdc7/langgraph_cli-0.2.10.tar.gz", hash = "sha256:0c215b364daeaf10de681e4960ecaafc7c9cd2a4100b41052d78d95cababf422", size = 31690, upload-time = "2025-05-09T20:18:27.542Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f0/c2/53aaae208a3a08f727ef9d03edfd8f499403e017fc451c8ca5b52e95c930/langgraph_cli-0.3.3.tar.gz", hash = "sha256:120adc44064786bb11f1376a7b324b2125276a2e2c3a04bbfab7b8c1622ad4d7", size = 722842, upload-time = "2025-06-13T20:17:52.639Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e1/06/7151d7c8d6c2bccc0919ddb35a63caf3707b96c94561f47f14b08d73ef5e/langgraph_cli-0.2.10-py3-none-any.whl", hash = "sha256:4aaa8d828d8d3bf0f55d2b2a36b2d9944021d65a4b06ed708c6d5eea725f65a7", size = 34833, upload-time = "2025-05-09T20:18:26.173Z" }, + { url = "https://files.pythonhosted.org/packages/50/aa/f52742987a30f9f2d80c00e1caccb310185dd511d07b56c3e611fe31adb5/langgraph_cli-0.3.3-py3-none-any.whl", hash = "sha256:a0c6b04d6a37191431ede17f7a358f1944c6e5ac9e1b7d2004b9f973fe940094", size = 35880, upload-time = "2025-06-13T20:17:51.437Z" }, ] [package.optional-dependencies] inmem = [ - { name = "langgraph-api", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, - { name = "langgraph-runtime-inmem", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, + { name = "langgraph-api", marker = "python_full_version >= '3.11'" }, + { name = "langgraph-runtime-inmem", marker = "python_full_version >= '3.11'" }, { name = "python-dotenv" }, ] @@ -1454,19 +1446,19 @@ dev = [ [[package]] name = "langgraph-runtime-inmem" -version = "0.2.0" +version = "0.3.4" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "blockbuster", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, - { name = "langgraph", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, - { name = "langgraph-checkpoint", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, - { name = "sse-starlette", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, - { name = "starlette", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, - { name = "structlog", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, + { name = "blockbuster", marker = "python_full_version >= '3.11'" }, + { name = "langgraph", marker = "python_full_version >= '3.11'" }, + { name = "langgraph-checkpoint", marker = "python_full_version >= '3.11'" }, + { name = "sse-starlette", marker = "python_full_version >= '3.11'" }, + { name = "starlette", marker = "python_full_version >= '3.11'" }, + { name = "structlog", marker = "python_full_version >= '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/76/8b/54452b0336674afe0ddbba0d5f52ddb323d9fa838e5bab694e1947697323/langgraph_runtime_inmem-0.2.0.tar.gz", hash = "sha256:3eed0bd7e241fbad6c7954e8494ddb133af7587f110c7eb4e3be15df5731a05a", size = 72666, upload-time = "2025-05-21T21:22:12.022Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c1/17/7ff669ff44a53ab342903c2996fff75a77494af9fe56abcfbca64fe2342b/langgraph_runtime_inmem-0.3.4.tar.gz", hash = "sha256:eda7828f3ea07126e5265024b74a3fa9bf611633ad83ba3296ab9f51d89b7c0c", size = 77424, upload-time = "2025-07-01T14:45:07.465Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d4/1f/5676d5237b0682257957338f5f7ee1f063f6d33fa158f878ad926800e95d/langgraph_runtime_inmem-0.2.0-py3-none-any.whl", hash = "sha256:6ad30c493d5963afbeac3136560303fba205b3850c5181f57f1794d8ecb8a461", size = 28406, upload-time = "2025-05-21T21:22:10.674Z" }, + { url = "https://files.pythonhosted.org/packages/95/0e/39c13ca7229a9425a0e5744a1d3817f80d38dd5ca7703494fb9cf836ba45/langgraph_runtime_inmem-0.3.4-py3-none-any.whl", hash = "sha256:dcb9ac68ac90b3fb1ddaf666d14a367ab70e69d5bb5589b77a72c318e29104ae", size = 29139, upload-time = "2025-07-01T14:45:06.472Z" }, ] [[package]] @@ -1607,7 +1599,7 @@ wheels = [ [[package]] name = "mypy" -version = "1.16.0" +version = "1.16.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "mypy-extensions" }, @@ -1615,39 +1607,39 @@ dependencies = [ { name = "tomli", marker = "python_full_version < '3.11'" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d4/38/13c2f1abae94d5ea0354e146b95a1be9b2137a0d506728e0da037c4276f6/mypy-1.16.0.tar.gz", hash = "sha256:84b94283f817e2aa6350a14b4a8fb2a35a53c286f97c9d30f53b63620e7af8ab", size = 3323139, upload-time = "2025-05-29T13:46:12.532Z" } +sdist = { url = "https://files.pythonhosted.org/packages/81/69/92c7fa98112e4d9eb075a239caa4ef4649ad7d441545ccffbd5e34607cbb/mypy-1.16.1.tar.gz", hash = "sha256:6bd00a0a2094841c5e47e7374bb42b83d64c527a502e3334e1173a0c24437bab", size = 3324747, upload-time = "2025-06-16T16:51:35.145Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/64/5e/a0485f0608a3d67029d3d73cec209278b025e3493a3acfda3ef3a88540fd/mypy-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7909541fef256527e5ee9c0a7e2aeed78b6cda72ba44298d1334fe7881b05c5c", size = 10967416, upload-time = "2025-05-29T13:34:17.783Z" }, - { url = "https://files.pythonhosted.org/packages/4b/53/5837c221f74c0d53a4bfc3003296f8179c3a2a7f336d7de7bbafbe96b688/mypy-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e71d6f0090c2256c713ed3d52711d01859c82608b5d68d4fa01a3fe30df95571", size = 10087654, upload-time = "2025-05-29T13:32:37.878Z" }, - { url = "https://files.pythonhosted.org/packages/29/59/5fd2400352c3093bed4c09017fe671d26bc5bb7e6ef2d4bf85f2a2488104/mypy-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:936ccfdd749af4766be824268bfe22d1db9eb2f34a3ea1d00ffbe5b5265f5491", size = 11875192, upload-time = "2025-05-29T13:34:54.281Z" }, - { url = "https://files.pythonhosted.org/packages/ad/3e/4bfec74663a64c2012f3e278dbc29ffe82b121bc551758590d1b6449ec0c/mypy-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4086883a73166631307fdd330c4a9080ce24913d4f4c5ec596c601b3a4bdd777", size = 12612939, upload-time = "2025-05-29T13:33:14.766Z" }, - { url = "https://files.pythonhosted.org/packages/88/1f/fecbe3dcba4bf2ca34c26ca016383a9676711907f8db4da8354925cbb08f/mypy-1.16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:feec38097f71797da0231997e0de3a58108c51845399669ebc532c815f93866b", size = 12874719, upload-time = "2025-05-29T13:21:52.09Z" }, - { url = "https://files.pythonhosted.org/packages/f3/51/c2d280601cd816c43dfa512a759270d5a5ef638d7ac9bea9134c8305a12f/mypy-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:09a8da6a0ee9a9770b8ff61b39c0bb07971cda90e7297f4213741b48a0cc8d93", size = 9487053, upload-time = "2025-05-29T13:33:29.797Z" }, - { url = "https://files.pythonhosted.org/packages/24/c4/ff2f79db7075c274fe85b5fff8797d29c6b61b8854c39e3b7feb556aa377/mypy-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9f826aaa7ff8443bac6a494cf743f591488ea940dd360e7dd330e30dd772a5ab", size = 10884498, upload-time = "2025-05-29T13:18:54.066Z" }, - { url = "https://files.pythonhosted.org/packages/02/07/12198e83006235f10f6a7808917376b5d6240a2fd5dce740fe5d2ebf3247/mypy-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:82d056e6faa508501af333a6af192c700b33e15865bda49611e3d7d8358ebea2", size = 10011755, upload-time = "2025-05-29T13:34:00.851Z" }, - { url = "https://files.pythonhosted.org/packages/f1/9b/5fd5801a72b5d6fb6ec0105ea1d0e01ab2d4971893076e558d4b6d6b5f80/mypy-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:089bedc02307c2548eb51f426e085546db1fa7dd87fbb7c9fa561575cf6eb1ff", size = 11800138, upload-time = "2025-05-29T13:32:55.082Z" }, - { url = "https://files.pythonhosted.org/packages/2e/81/a117441ea5dfc3746431e51d78a4aca569c677aa225bca2cc05a7c239b61/mypy-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6a2322896003ba66bbd1318c10d3afdfe24e78ef12ea10e2acd985e9d684a666", size = 12533156, upload-time = "2025-05-29T13:19:12.963Z" }, - { url = "https://files.pythonhosted.org/packages/3f/38/88ec57c6c86014d3f06251e00f397b5a7daa6888884d0abf187e4f5f587f/mypy-1.16.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:021a68568082c5b36e977d54e8f1de978baf401a33884ffcea09bd8e88a98f4c", size = 12742426, upload-time = "2025-05-29T13:20:22.72Z" }, - { url = "https://files.pythonhosted.org/packages/bd/53/7e9d528433d56e6f6f77ccf24af6ce570986c2d98a5839e4c2009ef47283/mypy-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:54066fed302d83bf5128632d05b4ec68412e1f03ef2c300434057d66866cea4b", size = 9478319, upload-time = "2025-05-29T13:21:17.582Z" }, - { url = "https://files.pythonhosted.org/packages/70/cf/158e5055e60ca2be23aec54a3010f89dcffd788732634b344fc9cb1e85a0/mypy-1.16.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c5436d11e89a3ad16ce8afe752f0f373ae9620841c50883dc96f8b8805620b13", size = 11062927, upload-time = "2025-05-29T13:35:52.328Z" }, - { url = "https://files.pythonhosted.org/packages/94/34/cfff7a56be1609f5d10ef386342ce3494158e4d506516890142007e6472c/mypy-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f2622af30bf01d8fc36466231bdd203d120d7a599a6d88fb22bdcb9dbff84090", size = 10083082, upload-time = "2025-05-29T13:35:33.378Z" }, - { url = "https://files.pythonhosted.org/packages/b3/7f/7242062ec6288c33d8ad89574df87c3903d394870e5e6ba1699317a65075/mypy-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d045d33c284e10a038f5e29faca055b90eee87da3fc63b8889085744ebabb5a1", size = 11828306, upload-time = "2025-05-29T13:21:02.164Z" }, - { url = "https://files.pythonhosted.org/packages/6f/5f/b392f7b4f659f5b619ce5994c5c43caab3d80df2296ae54fa888b3d17f5a/mypy-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b4968f14f44c62e2ec4a038c8797a87315be8df7740dc3ee8d3bfe1c6bf5dba8", size = 12702764, upload-time = "2025-05-29T13:20:42.826Z" }, - { url = "https://files.pythonhosted.org/packages/9b/c0/7646ef3a00fa39ac9bc0938626d9ff29d19d733011be929cfea59d82d136/mypy-1.16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:eb14a4a871bb8efb1e4a50360d4e3c8d6c601e7a31028a2c79f9bb659b63d730", size = 12896233, upload-time = "2025-05-29T13:18:37.446Z" }, - { url = "https://files.pythonhosted.org/packages/6d/38/52f4b808b3fef7f0ef840ee8ff6ce5b5d77381e65425758d515cdd4f5bb5/mypy-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:bd4e1ebe126152a7bbaa4daedd781c90c8f9643c79b9748caa270ad542f12bec", size = 9565547, upload-time = "2025-05-29T13:20:02.836Z" }, - { url = "https://files.pythonhosted.org/packages/97/9c/ca03bdbefbaa03b264b9318a98950a9c683e06472226b55472f96ebbc53d/mypy-1.16.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a9e056237c89f1587a3be1a3a70a06a698d25e2479b9a2f57325ddaaffc3567b", size = 11059753, upload-time = "2025-05-29T13:18:18.167Z" }, - { url = "https://files.pythonhosted.org/packages/36/92/79a969b8302cfe316027c88f7dc6fee70129490a370b3f6eb11d777749d0/mypy-1.16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0b07e107affb9ee6ce1f342c07f51552d126c32cd62955f59a7db94a51ad12c0", size = 10073338, upload-time = "2025-05-29T13:19:48.079Z" }, - { url = "https://files.pythonhosted.org/packages/14/9b/a943f09319167da0552d5cd722104096a9c99270719b1afeea60d11610aa/mypy-1.16.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c6fb60cbd85dc65d4d63d37cb5c86f4e3a301ec605f606ae3a9173e5cf34997b", size = 11827764, upload-time = "2025-05-29T13:46:04.47Z" }, - { url = "https://files.pythonhosted.org/packages/ec/64/ff75e71c65a0cb6ee737287c7913ea155845a556c64144c65b811afdb9c7/mypy-1.16.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a7e32297a437cc915599e0578fa6bc68ae6a8dc059c9e009c628e1c47f91495d", size = 12701356, upload-time = "2025-05-29T13:35:13.553Z" }, - { url = "https://files.pythonhosted.org/packages/0a/ad/0e93c18987a1182c350f7a5fab70550852f9fabe30ecb63bfbe51b602074/mypy-1.16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:afe420c9380ccec31e744e8baff0d406c846683681025db3531b32db56962d52", size = 12900745, upload-time = "2025-05-29T13:17:24.409Z" }, - { url = "https://files.pythonhosted.org/packages/28/5d/036c278d7a013e97e33f08c047fe5583ab4f1fc47c9a49f985f1cdd2a2d7/mypy-1.16.0-cp313-cp313-win_amd64.whl", hash = "sha256:55f9076c6ce55dd3f8cd0c6fff26a008ca8e5131b89d5ba6d86bd3f47e736eeb", size = 9572200, upload-time = "2025-05-29T13:33:44.92Z" }, - { url = "https://files.pythonhosted.org/packages/bd/eb/c0759617fe2159aee7a653f13cceafbf7f0b6323b4197403f2e587ca947d/mypy-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f56236114c425620875c7cf71700e3d60004858da856c6fc78998ffe767b73d3", size = 10956081, upload-time = "2025-05-29T13:19:32.264Z" }, - { url = "https://files.pythonhosted.org/packages/70/35/df3c74a2967bdf86edea58b265feeec181d693432faed1c3b688b7c231e3/mypy-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:15486beea80be24ff067d7d0ede673b001d0d684d0095803b3e6e17a886a2a92", size = 10084422, upload-time = "2025-05-29T13:18:01.437Z" }, - { url = "https://files.pythonhosted.org/packages/b3/07/145ffe29f4b577219943b7b1dc0a71df7ead3c5bed4898686bd87c5b5cc2/mypy-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f2ed0e0847a80655afa2c121835b848ed101cc7b8d8d6ecc5205aedc732b1436", size = 11879670, upload-time = "2025-05-29T13:17:45.971Z" }, - { url = "https://files.pythonhosted.org/packages/c6/94/0421562d6b046e22986758c9ae31865d10ea0ba607ae99b32c9d18b16f66/mypy-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eb5fbc8063cb4fde7787e4c0406aa63094a34a2daf4673f359a1fb64050e9cb2", size = 12610528, upload-time = "2025-05-29T13:34:36.983Z" }, - { url = "https://files.pythonhosted.org/packages/1a/f1/39a22985b78c766a594ae1e0bbb6f8bdf5f31ea8d0c52291a3c211fd3cd5/mypy-1.16.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a5fcfdb7318c6a8dd127b14b1052743b83e97a970f0edb6c913211507a255e20", size = 12871923, upload-time = "2025-05-29T13:32:21.823Z" }, - { url = "https://files.pythonhosted.org/packages/f3/8e/84db4fb0d01f43d2c82fa9072ca72a42c49e52d58f44307bbd747c977bc2/mypy-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:2e7e0ad35275e02797323a5aa1be0b14a4d03ffdb2e5f2b0489fa07b89c67b21", size = 9482931, upload-time = "2025-05-29T13:21:32.326Z" }, - { url = "https://files.pythonhosted.org/packages/99/a3/6ed10530dec8e0fdc890d81361260c9ef1f5e5c217ad8c9b21ecb2b8366b/mypy-1.16.0-py3-none-any.whl", hash = "sha256:29e1499864a3888bca5c1542f2d7232c6e586295183320caa95758fc84034031", size = 2265773, upload-time = "2025-05-29T13:35:18.762Z" }, + { url = "https://files.pythonhosted.org/packages/8e/12/2bf23a80fcef5edb75de9a1e295d778e0f46ea89eb8b115818b663eff42b/mypy-1.16.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b4f0fed1022a63c6fec38f28b7fc77fca47fd490445c69d0a66266c59dd0b88a", size = 10958644, upload-time = "2025-06-16T16:51:11.649Z" }, + { url = "https://files.pythonhosted.org/packages/08/50/bfe47b3b278eacf348291742fd5e6613bbc4b3434b72ce9361896417cfe5/mypy-1.16.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:86042bbf9f5a05ea000d3203cf87aa9d0ccf9a01f73f71c58979eb9249f46d72", size = 10087033, upload-time = "2025-06-16T16:35:30.089Z" }, + { url = "https://files.pythonhosted.org/packages/21/de/40307c12fe25675a0776aaa2cdd2879cf30d99eec91b898de00228dc3ab5/mypy-1.16.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ea7469ee5902c95542bea7ee545f7006508c65c8c54b06dc2c92676ce526f3ea", size = 11875645, upload-time = "2025-06-16T16:35:48.49Z" }, + { url = "https://files.pythonhosted.org/packages/a6/d8/85bdb59e4a98b7a31495bd8f1a4445d8ffc86cde4ab1f8c11d247c11aedc/mypy-1.16.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:352025753ef6a83cb9e7f2427319bb7875d1fdda8439d1e23de12ab164179574", size = 12616986, upload-time = "2025-06-16T16:48:39.526Z" }, + { url = "https://files.pythonhosted.org/packages/0e/d0/bb25731158fa8f8ee9e068d3e94fcceb4971fedf1424248496292512afe9/mypy-1.16.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ff9fa5b16e4c1364eb89a4d16bcda9987f05d39604e1e6c35378a2987c1aac2d", size = 12878632, upload-time = "2025-06-16T16:36:08.195Z" }, + { url = "https://files.pythonhosted.org/packages/2d/11/822a9beb7a2b825c0cb06132ca0a5183f8327a5e23ef89717c9474ba0bc6/mypy-1.16.1-cp310-cp310-win_amd64.whl", hash = "sha256:1256688e284632382f8f3b9e2123df7d279f603c561f099758e66dd6ed4e8bd6", size = 9484391, upload-time = "2025-06-16T16:37:56.151Z" }, + { url = "https://files.pythonhosted.org/packages/9a/61/ec1245aa1c325cb7a6c0f8570a2eee3bfc40fa90d19b1267f8e50b5c8645/mypy-1.16.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:472e4e4c100062488ec643f6162dd0d5208e33e2f34544e1fc931372e806c0cc", size = 10890557, upload-time = "2025-06-16T16:37:21.421Z" }, + { url = "https://files.pythonhosted.org/packages/6b/bb/6eccc0ba0aa0c7a87df24e73f0ad34170514abd8162eb0c75fd7128171fb/mypy-1.16.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea16e2a7d2714277e349e24d19a782a663a34ed60864006e8585db08f8ad1782", size = 10012921, upload-time = "2025-06-16T16:51:28.659Z" }, + { url = "https://files.pythonhosted.org/packages/5f/80/b337a12e2006715f99f529e732c5f6a8c143bb58c92bb142d5ab380963a5/mypy-1.16.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:08e850ea22adc4d8a4014651575567b0318ede51e8e9fe7a68f25391af699507", size = 11802887, upload-time = "2025-06-16T16:50:53.627Z" }, + { url = "https://files.pythonhosted.org/packages/d9/59/f7af072d09793d581a745a25737c7c0a945760036b16aeb620f658a017af/mypy-1.16.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22d76a63a42619bfb90122889b903519149879ddbf2ba4251834727944c8baca", size = 12531658, upload-time = "2025-06-16T16:33:55.002Z" }, + { url = "https://files.pythonhosted.org/packages/82/c4/607672f2d6c0254b94a646cfc45ad589dd71b04aa1f3d642b840f7cce06c/mypy-1.16.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2c7ce0662b6b9dc8f4ed86eb7a5d505ee3298c04b40ec13b30e572c0e5ae17c4", size = 12732486, upload-time = "2025-06-16T16:37:03.301Z" }, + { url = "https://files.pythonhosted.org/packages/b6/5e/136555ec1d80df877a707cebf9081bd3a9f397dedc1ab9750518d87489ec/mypy-1.16.1-cp311-cp311-win_amd64.whl", hash = "sha256:211287e98e05352a2e1d4e8759c5490925a7c784ddc84207f4714822f8cf99b6", size = 9479482, upload-time = "2025-06-16T16:47:37.48Z" }, + { url = "https://files.pythonhosted.org/packages/b4/d6/39482e5fcc724c15bf6280ff5806548c7185e0c090712a3736ed4d07e8b7/mypy-1.16.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:af4792433f09575d9eeca5c63d7d90ca4aeceda9d8355e136f80f8967639183d", size = 11066493, upload-time = "2025-06-16T16:47:01.683Z" }, + { url = "https://files.pythonhosted.org/packages/e6/e5/26c347890efc6b757f4d5bb83f4a0cf5958b8cf49c938ac99b8b72b420a6/mypy-1.16.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:66df38405fd8466ce3517eda1f6640611a0b8e70895e2a9462d1d4323c5eb4b9", size = 10081687, upload-time = "2025-06-16T16:48:19.367Z" }, + { url = "https://files.pythonhosted.org/packages/44/c7/b5cb264c97b86914487d6a24bd8688c0172e37ec0f43e93b9691cae9468b/mypy-1.16.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44e7acddb3c48bd2713994d098729494117803616e116032af192871aed80b79", size = 11839723, upload-time = "2025-06-16T16:49:20.912Z" }, + { url = "https://files.pythonhosted.org/packages/15/f8/491997a9b8a554204f834ed4816bda813aefda31cf873bb099deee3c9a99/mypy-1.16.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0ab5eca37b50188163fa7c1b73c685ac66c4e9bdee4a85c9adac0e91d8895e15", size = 12722980, upload-time = "2025-06-16T16:37:40.929Z" }, + { url = "https://files.pythonhosted.org/packages/df/f0/2bd41e174b5fd93bc9de9a28e4fb673113633b8a7f3a607fa4a73595e468/mypy-1.16.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb6229b2c9086247e21a83c309754b9058b438704ad2f6807f0d8227f6ebdd", size = 12903328, upload-time = "2025-06-16T16:34:35.099Z" }, + { url = "https://files.pythonhosted.org/packages/61/81/5572108a7bec2c46b8aff7e9b524f371fe6ab5efb534d38d6b37b5490da8/mypy-1.16.1-cp312-cp312-win_amd64.whl", hash = "sha256:1f0435cf920e287ff68af3d10a118a73f212deb2ce087619eb4e648116d1fe9b", size = 9562321, upload-time = "2025-06-16T16:48:58.823Z" }, + { url = "https://files.pythonhosted.org/packages/28/e3/96964af4a75a949e67df4b95318fe2b7427ac8189bbc3ef28f92a1c5bc56/mypy-1.16.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ddc91eb318c8751c69ddb200a5937f1232ee8efb4e64e9f4bc475a33719de438", size = 11063480, upload-time = "2025-06-16T16:47:56.205Z" }, + { url = "https://files.pythonhosted.org/packages/f5/4d/cd1a42b8e5be278fab7010fb289d9307a63e07153f0ae1510a3d7b703193/mypy-1.16.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:87ff2c13d58bdc4bbe7dc0dedfe622c0f04e2cb2a492269f3b418df2de05c536", size = 10090538, upload-time = "2025-06-16T16:46:43.92Z" }, + { url = "https://files.pythonhosted.org/packages/c9/4f/c3c6b4b66374b5f68bab07c8cabd63a049ff69796b844bc759a0ca99bb2a/mypy-1.16.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a7cfb0fe29fe5a9841b7c8ee6dffb52382c45acdf68f032145b75620acfbd6f", size = 11836839, upload-time = "2025-06-16T16:36:28.039Z" }, + { url = "https://files.pythonhosted.org/packages/b4/7e/81ca3b074021ad9775e5cb97ebe0089c0f13684b066a750b7dc208438403/mypy-1.16.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:051e1677689c9d9578b9c7f4d206d763f9bbd95723cd1416fad50db49d52f359", size = 12715634, upload-time = "2025-06-16T16:50:34.441Z" }, + { url = "https://files.pythonhosted.org/packages/e9/95/bdd40c8be346fa4c70edb4081d727a54d0a05382d84966869738cfa8a497/mypy-1.16.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d5d2309511cc56c021b4b4e462907c2b12f669b2dbeb68300110ec27723971be", size = 12895584, upload-time = "2025-06-16T16:34:54.857Z" }, + { url = "https://files.pythonhosted.org/packages/5a/fd/d486a0827a1c597b3b48b1bdef47228a6e9ee8102ab8c28f944cb83b65dc/mypy-1.16.1-cp313-cp313-win_amd64.whl", hash = "sha256:4f58ac32771341e38a853c5d0ec0dfe27e18e27da9cdb8bbc882d2249c71a3ee", size = 9573886, upload-time = "2025-06-16T16:36:43.589Z" }, + { url = "https://files.pythonhosted.org/packages/49/5e/ed1e6a7344005df11dfd58b0fdd59ce939a0ba9f7ed37754bf20670b74db/mypy-1.16.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7fc688329af6a287567f45cc1cefb9db662defeb14625213a5b7da6e692e2069", size = 10959511, upload-time = "2025-06-16T16:47:21.945Z" }, + { url = "https://files.pythonhosted.org/packages/30/88/a7cbc2541e91fe04f43d9e4577264b260fecedb9bccb64ffb1a34b7e6c22/mypy-1.16.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e198ab3f55924c03ead626ff424cad1732d0d391478dfbf7bb97b34602395da", size = 10075555, upload-time = "2025-06-16T16:50:14.084Z" }, + { url = "https://files.pythonhosted.org/packages/93/f7/c62b1e31a32fbd1546cca5e0a2e5f181be5761265ad1f2e94f2a306fa906/mypy-1.16.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:09aa4f91ada245f0a45dbc47e548fd94e0dd5a8433e0114917dc3b526912a30c", size = 11874169, upload-time = "2025-06-16T16:49:42.276Z" }, + { url = "https://files.pythonhosted.org/packages/c8/15/db580a28034657fb6cb87af2f8996435a5b19d429ea4dcd6e1c73d418e60/mypy-1.16.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13c7cd5b1cb2909aa318a90fd1b7e31f17c50b242953e7dd58345b2a814f6383", size = 12610060, upload-time = "2025-06-16T16:34:15.215Z" }, + { url = "https://files.pythonhosted.org/packages/ec/78/c17f48f6843048fa92d1489d3095e99324f2a8c420f831a04ccc454e2e51/mypy-1.16.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:58e07fb958bc5d752a280da0e890c538f1515b79a65757bbdc54252ba82e0b40", size = 12875199, upload-time = "2025-06-16T16:35:14.448Z" }, + { url = "https://files.pythonhosted.org/packages/bc/d6/ed42167d0a42680381653fd251d877382351e1bd2c6dd8a818764be3beb1/mypy-1.16.1-cp39-cp39-win_amd64.whl", hash = "sha256:f895078594d918f93337a505f8add9bd654d1a24962b4c6ed9390e12531eb31b", size = 9487033, upload-time = "2025-06-16T16:49:57.907Z" }, + { url = "https://files.pythonhosted.org/packages/cf/d3/53e684e78e07c1a2bf7105715e5edd09ce951fc3f47cf9ed095ec1b7a037/mypy-1.16.1-py3-none-any.whl", hash = "sha256:5fc2ac4027d0ef28d6ba69a0343737a23c4d1b83672bf38d1fe237bdc0643b37", size = 2265923, upload-time = "2025-06-16T16:48:02.366Z" }, ] [[package]] @@ -1726,7 +1718,7 @@ wheels = [ [[package]] name = "notebook" -version = "7.4.3" +version = "7.4.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jupyter-server" }, @@ -1735,9 +1727,9 @@ dependencies = [ { name = "notebook-shim" }, { name = "tornado" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/dc/21/4f83b15e483da4f4f63928edd0cb08b6e7d33f8a15c23b116a90c44c6235/notebook-7.4.3.tar.gz", hash = "sha256:a1567481cd3853f2610ee0ecf5dfa12bb508e878ee8f92152c134ef7f0568a76", size = 13881668, upload-time = "2025-05-26T14:27:21.656Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b1/4e/a40b5a94eb01fc51746db7854296d88b84905ab18ee0fcef853a60d708a3/notebook-7.4.4.tar.gz", hash = "sha256:392fd501e266f2fb3466c6fcd3331163a2184968cb5c5accf90292e01dfe528c", size = 13883628, upload-time = "2025-06-30T13:04:18.099Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/76/1b/16c809d799e3ddd7a97c8b43734f79624b74ddef9707e7d92275a13777bc/notebook-7.4.3-py3-none-any.whl", hash = "sha256:9cdeee954e04101cadb195d90e2ab62b7c9286c1d4f858bf3bb54e40df16c0c3", size = 14286402, upload-time = "2025-05-26T14:27:17.339Z" }, + { url = "https://files.pythonhosted.org/packages/b3/c0/e64d2047fd752249b0b69f6aee2a7049eb94e7273e5baabc8b8ad05cc068/notebook-7.4.4-py3-none-any.whl", hash = "sha256:32840f7f777b6bff79bb101159336e9b332bdbfba1495b8739e34d1d65cbc1c0", size = 14288000, upload-time = "2025-06-30T13:04:14.584Z" }, ] [[package]] @@ -1956,11 +1948,11 @@ wheels = [ [[package]] name = "prometheus-client" -version = "0.22.0" +version = "0.22.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/5b/5a/3fa1fa7e91a203759aaf316be394f70f2ef598d589b9785a8611b6094c00/prometheus_client-0.22.0.tar.gz", hash = "sha256:18da1d2241ac2d10c8d2110f13eedcd5c7c0c8af18c926e8731f04fc10cd575c", size = 74443, upload-time = "2025-05-16T20:50:18.333Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5e/cf/40dde0a2be27cc1eb41e333d1a674a74ce8b8b0457269cc640fd42b07cf7/prometheus_client-0.22.1.tar.gz", hash = "sha256:190f1331e783cf21eb60bca559354e0a4d4378facecf78f5428c39b675d20d28", size = 69746, upload-time = "2025-06-02T14:29:01.152Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/50/c7/cee159ba3d7192e84a4c166ec1752f44a5fa859ac0eeda2d73a1da65ab47/prometheus_client-0.22.0-py3-none-any.whl", hash = "sha256:c8951bbe64e62b96cd8e8f5d917279d1b9b91ab766793f33d4dce6c228558713", size = 62658, upload-time = "2025-05-16T20:50:16.978Z" }, + { url = "https://files.pythonhosted.org/packages/32/ae/ec06af4fe3ee72d16973474f122541746196aaa16cea6f66d18b963c6177/prometheus_client-0.22.1-py3-none-any.whl", hash = "sha256:cca895342e308174341b2cbf99a56bef291fbc0ef7b9e5412a0f26d653ba7094", size = 58694, upload-time = "2025-06-02T14:29:00.068Z" }, ] [[package]] @@ -2290,11 +2282,11 @@ wheels = [ [[package]] name = "pygments" -version = "2.19.1" +version = "2.19.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581, upload-time = "2025-01-06T17:26:30.443Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293, upload-time = "2025-01-06T17:26:25.553Z" }, + { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, ] [[package]] @@ -2320,7 +2312,7 @@ wheels = [ [[package]] name = "pytest" -version = "8.3.5" +version = "8.4.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, @@ -2328,24 +2320,26 @@ dependencies = [ { name = "iniconfig" }, { name = "packaging" }, { name = "pluggy" }, + { name = "pygments" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ae/3c/c9d525a414d506893f0cd8a8d0de7706446213181570cdbd766691164e40/pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845", size = 1450891, upload-time = "2025-03-02T12:54:54.503Z" } +sdist = { url = "https://files.pythonhosted.org/packages/08/ba/45911d754e8eba3d5a841a5ce61a65a685ff1798421ac054f85aa8747dfb/pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c", size = 1517714, upload-time = "2025-06-18T05:48:06.109Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/30/3d/64ad57c803f1fa1e963a7946b6e0fea4a70df53c1a7fed304586539c2bac/pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", size = 343634, upload-time = "2025-03-02T12:54:52.069Z" }, + { url = "https://files.pythonhosted.org/packages/29/16/c8a903f4c4dffe7a12843191437d7cd8e32751d5de349d45d3fe69544e87/pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7", size = 365474, upload-time = "2025-06-18T05:48:03.955Z" }, ] [[package]] name = "pytest-cov" -version = "6.1.1" +version = "6.2.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "coverage", extra = ["toml"] }, + { name = "pluggy" }, { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/25/69/5f1e57f6c5a39f81411b550027bf72842c4567ff5fd572bed1edc9e4b5d9/pytest_cov-6.1.1.tar.gz", hash = "sha256:46935f7aaefba760e716c2ebfbe1c216240b9592966e7da99ea8292d4d3e2a0a", size = 66857, upload-time = "2025-04-05T14:07:51.592Z" } +sdist = { url = "https://files.pythonhosted.org/packages/18/99/668cade231f434aaa59bbfbf49469068d2ddd945000621d3d165d2e7dd7b/pytest_cov-6.2.1.tar.gz", hash = "sha256:25cc6cc0a5358204b8108ecedc51a9b57b34cc6b8c967cc2c01a4e00d8a67da2", size = 69432, upload-time = "2025-06-12T10:47:47.684Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/28/d0/def53b4a790cfb21483016430ed828f64830dd981ebe1089971cd10cab25/pytest_cov-6.1.1-py3-none-any.whl", hash = "sha256:bddf29ed2d0ab6f4df17b4c55b0a657287db8684af9c42ea546b21b1041b3dde", size = 23841, upload-time = "2025-04-05T14:07:49.641Z" }, + { url = "https://files.pythonhosted.org/packages/bc/16/4ea354101abb1287856baa4af2732be351c7bee728065aed451b678153fd/pytest_cov-6.2.1-py3-none-any.whl", hash = "sha256:f5bc4c23f42f1cdd23c70b1dab1bbaef4fc505ba950d53e0081d0730dd7e86d5", size = 24644, upload-time = "2025-06-12T10:47:45.932Z" }, ] [[package]] @@ -2400,15 +2394,15 @@ wheels = [ [[package]] name = "pytest-xdist" -version = "3.7.0" +version = "3.8.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "execnet" }, { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/49/dc/865845cfe987b21658e871d16e0a24e871e00884c545f246dd8f6f69edda/pytest_xdist-3.7.0.tar.gz", hash = "sha256:f9248c99a7c15b7d2f90715df93610353a485827bc06eefb6566d23f6400f126", size = 87550, upload-time = "2025-05-26T21:18:20.251Z" } +sdist = { url = "https://files.pythonhosted.org/packages/78/b4/439b179d1ff526791eb921115fca8e44e596a13efeda518b9d845a619450/pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1", size = 88069, upload-time = "2025-07-01T13:30:59.346Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0d/b2/0e802fde6f1c5b2f7ae7e9ad42b83fd4ecebac18a8a8c2f2f14e39dce6e1/pytest_xdist-3.7.0-py3-none-any.whl", hash = "sha256:7d3fbd255998265052435eb9daa4e99b62e6fb9cfb6efd1f858d4d8c0c7f0ca0", size = 46142, upload-time = "2025-05-26T21:18:18.759Z" }, + { url = "https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88", size = 46396, upload-time = "2025-07-01T13:30:56.632Z" }, ] [package.optional-dependencies] @@ -2430,11 +2424,11 @@ wheels = [ [[package]] name = "python-dotenv" -version = "1.1.0" +version = "1.1.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/88/2c/7bb1416c5620485aa793f2de31d3df393d3686aa8a8506d11e10e13c5baf/python_dotenv-1.1.0.tar.gz", hash = "sha256:41f90bc6f5f177fb41f53e87666db362025010eb28f60a01c9143bfa33a2b2d5", size = 39920, upload-time = "2025-03-25T10:14:56.835Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/b0/4bc07ccd3572a2f9df7e6782f52b0c6c90dcbb803ac4a167702d7d0dfe1e/python_dotenv-1.1.1.tar.gz", hash = "sha256:a8a6399716257f45be6a007360200409fce5cda2661e3dec71d23dc15f6189ab", size = 41978, upload-time = "2025-06-24T04:21:07.341Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1e/18/98a99ad95133c6a6e2005fe89faedf294a748bd5dc803008059409ac9b1e/python_dotenv-1.1.0-py3-none-any.whl", hash = "sha256:d7c01d9e2293916c18baf562d95698754b0dbbb5e74d457c45d4f6561fb9d55d", size = 20256, upload-time = "2025-03-25T10:14:55.034Z" }, + { url = "https://files.pythonhosted.org/packages/5f/ed/539768cf28c661b5b068d66d96a2f155c4971a5d55684a514c1a0e0dec2f/python_dotenv-1.1.1-py3-none-any.whl", hash = "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc", size = 20556, upload-time = "2025-06-24T04:21:06.073Z" }, ] [[package]] @@ -2539,91 +2533,77 @@ wheels = [ [[package]] name = "pyzmq" -version = "26.4.0" +version = "27.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cffi", marker = "implementation_name == 'pypy'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b1/11/b9213d25230ac18a71b39b3723494e57adebe36e066397b961657b3b41c1/pyzmq-26.4.0.tar.gz", hash = "sha256:4bd13f85f80962f91a651a7356fe0472791a5f7a92f227822b5acf44795c626d", size = 278293, upload-time = "2025-04-04T12:05:44.049Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f1/06/50a4e9648b3e8b992bef8eb632e457307553a89d294103213cfd47b3da69/pyzmq-27.0.0.tar.gz", hash = "sha256:b1f08eeb9ce1510e6939b6e5dcd46a17765e2333daae78ecf4606808442e52cf", size = 280478, upload-time = "2025-06-13T14:09:07.087Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/38/b8/af1d814ffc3ff9730f9a970cbf216b6f078e5d251a25ef5201d7bc32a37c/pyzmq-26.4.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:0329bdf83e170ac133f44a233fc651f6ed66ef8e66693b5af7d54f45d1ef5918", size = 1339238, upload-time = "2025-04-04T12:03:07.022Z" }, - { url = "https://files.pythonhosted.org/packages/ee/e4/5aafed4886c264f2ea6064601ad39c5fc4e9b6539c6ebe598a859832eeee/pyzmq-26.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:398a825d2dea96227cf6460ce0a174cf7657d6f6827807d4d1ae9d0f9ae64315", size = 672848, upload-time = "2025-04-04T12:03:08.591Z" }, - { url = "https://files.pythonhosted.org/packages/79/39/026bf49c721cb42f1ef3ae0ee3d348212a7621d2adb739ba97599b6e4d50/pyzmq-26.4.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6d52d62edc96787f5c1dfa6c6ccff9b581cfae5a70d94ec4c8da157656c73b5b", size = 911299, upload-time = "2025-04-04T12:03:10Z" }, - { url = "https://files.pythonhosted.org/packages/03/23/b41f936a9403b8f92325c823c0f264c6102a0687a99c820f1aaeb99c1def/pyzmq-26.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1410c3a3705db68d11eb2424d75894d41cff2f64d948ffe245dd97a9debfebf4", size = 867920, upload-time = "2025-04-04T12:03:11.311Z" }, - { url = "https://files.pythonhosted.org/packages/c1/3e/2de5928cdadc2105e7c8f890cc5f404136b41ce5b6eae5902167f1d5641c/pyzmq-26.4.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:7dacb06a9c83b007cc01e8e5277f94c95c453c5851aac5e83efe93e72226353f", size = 862514, upload-time = "2025-04-04T12:03:13.013Z" }, - { url = "https://files.pythonhosted.org/packages/ce/57/109569514dd32e05a61d4382bc88980c95bfd2f02e58fea47ec0ccd96de1/pyzmq-26.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6bab961c8c9b3a4dc94d26e9b2cdf84de9918931d01d6ff38c721a83ab3c0ef5", size = 1204494, upload-time = "2025-04-04T12:03:14.795Z" }, - { url = "https://files.pythonhosted.org/packages/aa/02/dc51068ff2ca70350d1151833643a598625feac7b632372d229ceb4de3e1/pyzmq-26.4.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7a5c09413b924d96af2aa8b57e76b9b0058284d60e2fc3730ce0f979031d162a", size = 1514525, upload-time = "2025-04-04T12:03:16.246Z" }, - { url = "https://files.pythonhosted.org/packages/48/2a/a7d81873fff0645eb60afaec2b7c78a85a377af8f1d911aff045d8955bc7/pyzmq-26.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7d489ac234d38e57f458fdbd12a996bfe990ac028feaf6f3c1e81ff766513d3b", size = 1414659, upload-time = "2025-04-04T12:03:17.652Z" }, - { url = "https://files.pythonhosted.org/packages/ef/ea/813af9c42ae21845c1ccfe495bd29c067622a621e85d7cda6bc437de8101/pyzmq-26.4.0-cp310-cp310-win32.whl", hash = "sha256:dea1c8db78fb1b4b7dc9f8e213d0af3fc8ecd2c51a1d5a3ca1cde1bda034a980", size = 580348, upload-time = "2025-04-04T12:03:19.384Z" }, - { url = "https://files.pythonhosted.org/packages/20/68/318666a89a565252c81d3fed7f3b4c54bd80fd55c6095988dfa2cd04a62b/pyzmq-26.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:fa59e1f5a224b5e04dc6c101d7186058efa68288c2d714aa12d27603ae93318b", size = 643838, upload-time = "2025-04-04T12:03:20.795Z" }, - { url = "https://files.pythonhosted.org/packages/91/f8/fb1a15b5f4ecd3e588bfde40c17d32ed84b735195b5c7d1d7ce88301a16f/pyzmq-26.4.0-cp310-cp310-win_arm64.whl", hash = "sha256:a651fe2f447672f4a815e22e74630b6b1ec3a1ab670c95e5e5e28dcd4e69bbb5", size = 559565, upload-time = "2025-04-04T12:03:22.676Z" }, - { url = "https://files.pythonhosted.org/packages/32/6d/234e3b0aa82fd0290b1896e9992f56bdddf1f97266110be54d0177a9d2d9/pyzmq-26.4.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:bfcf82644c9b45ddd7cd2a041f3ff8dce4a0904429b74d73a439e8cab1bd9e54", size = 1339723, upload-time = "2025-04-04T12:03:24.358Z" }, - { url = "https://files.pythonhosted.org/packages/4f/11/6d561efe29ad83f7149a7cd48e498e539ed09019c6cd7ecc73f4cc725028/pyzmq-26.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9bcae3979b2654d5289d3490742378b2f3ce804b0b5fd42036074e2bf35b030", size = 672645, upload-time = "2025-04-04T12:03:25.693Z" }, - { url = "https://files.pythonhosted.org/packages/19/fd/81bfe3e23f418644660bad1a90f0d22f0b3eebe33dd65a79385530bceb3d/pyzmq-26.4.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ccdff8ac4246b6fb60dcf3982dfaeeff5dd04f36051fe0632748fc0aa0679c01", size = 910133, upload-time = "2025-04-04T12:03:27.625Z" }, - { url = "https://files.pythonhosted.org/packages/97/68/321b9c775595ea3df832a9516252b653fe32818db66fdc8fa31c9b9fce37/pyzmq-26.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4550af385b442dc2d55ab7717837812799d3674cb12f9a3aa897611839c18e9e", size = 867428, upload-time = "2025-04-04T12:03:29.004Z" }, - { url = "https://files.pythonhosted.org/packages/4e/6e/159cbf2055ef36aa2aa297e01b24523176e5b48ead283c23a94179fb2ba2/pyzmq-26.4.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:2f9f7ffe9db1187a253fca95191854b3fda24696f086e8789d1d449308a34b88", size = 862409, upload-time = "2025-04-04T12:03:31.032Z" }, - { url = "https://files.pythonhosted.org/packages/05/1c/45fb8db7be5a7d0cadea1070a9cbded5199a2d578de2208197e592f219bd/pyzmq-26.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3709c9ff7ba61589b7372923fd82b99a81932b592a5c7f1a24147c91da9a68d6", size = 1205007, upload-time = "2025-04-04T12:03:32.687Z" }, - { url = "https://files.pythonhosted.org/packages/f8/fa/658c7f583af6498b463f2fa600f34e298e1b330886f82f1feba0dc2dd6c3/pyzmq-26.4.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:f8f3c30fb2d26ae5ce36b59768ba60fb72507ea9efc72f8f69fa088450cff1df", size = 1514599, upload-time = "2025-04-04T12:03:34.084Z" }, - { url = "https://files.pythonhosted.org/packages/4d/d7/44d641522353ce0a2bbd150379cb5ec32f7120944e6bfba4846586945658/pyzmq-26.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:382a4a48c8080e273427fc692037e3f7d2851959ffe40864f2db32646eeb3cef", size = 1414546, upload-time = "2025-04-04T12:03:35.478Z" }, - { url = "https://files.pythonhosted.org/packages/72/76/c8ed7263218b3d1e9bce07b9058502024188bd52cc0b0a267a9513b431fc/pyzmq-26.4.0-cp311-cp311-win32.whl", hash = "sha256:d56aad0517d4c09e3b4f15adebba8f6372c5102c27742a5bdbfc74a7dceb8fca", size = 579247, upload-time = "2025-04-04T12:03:36.846Z" }, - { url = "https://files.pythonhosted.org/packages/c3/d0/2d9abfa2571a0b1a67c0ada79a8aa1ba1cce57992d80f771abcdf99bb32c/pyzmq-26.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:963977ac8baed7058c1e126014f3fe58b3773f45c78cce7af5c26c09b6823896", size = 644727, upload-time = "2025-04-04T12:03:38.578Z" }, - { url = "https://files.pythonhosted.org/packages/0d/d1/c8ad82393be6ccedfc3c9f3adb07f8f3976e3c4802640fe3f71441941e70/pyzmq-26.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:c0c8e8cadc81e44cc5088fcd53b9b3b4ce9344815f6c4a03aec653509296fae3", size = 559942, upload-time = "2025-04-04T12:03:40.143Z" }, - { url = "https://files.pythonhosted.org/packages/10/44/a778555ebfdf6c7fc00816aad12d185d10a74d975800341b1bc36bad1187/pyzmq-26.4.0-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:5227cb8da4b6f68acfd48d20c588197fd67745c278827d5238c707daf579227b", size = 1341586, upload-time = "2025-04-04T12:03:41.954Z" }, - { url = "https://files.pythonhosted.org/packages/9c/4f/f3a58dc69ac757e5103be3bd41fb78721a5e17da7cc617ddb56d973a365c/pyzmq-26.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1c07a7fa7f7ba86554a2b1bef198c9fed570c08ee062fd2fd6a4dcacd45f905", size = 665880, upload-time = "2025-04-04T12:03:43.45Z" }, - { url = "https://files.pythonhosted.org/packages/fe/45/50230bcfb3ae5cb98bee683b6edeba1919f2565d7cc1851d3c38e2260795/pyzmq-26.4.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae775fa83f52f52de73183f7ef5395186f7105d5ed65b1ae65ba27cb1260de2b", size = 902216, upload-time = "2025-04-04T12:03:45.572Z" }, - { url = "https://files.pythonhosted.org/packages/41/59/56bbdc5689be5e13727491ad2ba5efd7cd564365750514f9bc8f212eef82/pyzmq-26.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66c760d0226ebd52f1e6b644a9e839b5db1e107a23f2fcd46ec0569a4fdd4e63", size = 859814, upload-time = "2025-04-04T12:03:47.188Z" }, - { url = "https://files.pythonhosted.org/packages/81/b1/57db58cfc8af592ce94f40649bd1804369c05b2190e4cbc0a2dad572baeb/pyzmq-26.4.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:ef8c6ecc1d520debc147173eaa3765d53f06cd8dbe7bd377064cdbc53ab456f5", size = 855889, upload-time = "2025-04-04T12:03:49.223Z" }, - { url = "https://files.pythonhosted.org/packages/e8/92/47542e629cbac8f221c230a6d0f38dd3d9cff9f6f589ed45fdf572ffd726/pyzmq-26.4.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3150ef4084e163dec29ae667b10d96aad309b668fac6810c9e8c27cf543d6e0b", size = 1197153, upload-time = "2025-04-04T12:03:50.591Z" }, - { url = "https://files.pythonhosted.org/packages/07/e5/b10a979d1d565d54410afc87499b16c96b4a181af46e7645ab4831b1088c/pyzmq-26.4.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:4448c9e55bf8329fa1dcedd32f661bf611214fa70c8e02fee4347bc589d39a84", size = 1507352, upload-time = "2025-04-04T12:03:52.473Z" }, - { url = "https://files.pythonhosted.org/packages/ab/58/5a23db84507ab9c01c04b1232a7a763be66e992aa2e66498521bbbc72a71/pyzmq-26.4.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e07dde3647afb084d985310d067a3efa6efad0621ee10826f2cb2f9a31b89d2f", size = 1406834, upload-time = "2025-04-04T12:03:54Z" }, - { url = "https://files.pythonhosted.org/packages/22/74/aaa837b331580c13b79ac39396601fb361454ee184ca85e8861914769b99/pyzmq-26.4.0-cp312-cp312-win32.whl", hash = "sha256:ba034a32ecf9af72adfa5ee383ad0fd4f4e38cdb62b13624278ef768fe5b5b44", size = 577992, upload-time = "2025-04-04T12:03:55.815Z" }, - { url = "https://files.pythonhosted.org/packages/30/0f/55f8c02c182856743b82dde46b2dc3e314edda7f1098c12a8227eeda0833/pyzmq-26.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:056a97aab4064f526ecb32f4343917a4022a5d9efb6b9df990ff72e1879e40be", size = 640466, upload-time = "2025-04-04T12:03:57.231Z" }, - { url = "https://files.pythonhosted.org/packages/e4/29/073779afc3ef6f830b8de95026ef20b2d1ec22d0324d767748d806e57379/pyzmq-26.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:2f23c750e485ce1eb639dbd576d27d168595908aa2d60b149e2d9e34c9df40e0", size = 556342, upload-time = "2025-04-04T12:03:59.218Z" }, - { url = "https://files.pythonhosted.org/packages/d7/20/fb2c92542488db70f833b92893769a569458311a76474bda89dc4264bd18/pyzmq-26.4.0-cp313-cp313-macosx_10_15_universal2.whl", hash = "sha256:c43fac689880f5174d6fc864857d1247fe5cfa22b09ed058a344ca92bf5301e3", size = 1339484, upload-time = "2025-04-04T12:04:00.671Z" }, - { url = "https://files.pythonhosted.org/packages/58/29/2f06b9cabda3a6ea2c10f43e67ded3e47fc25c54822e2506dfb8325155d4/pyzmq-26.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:902aca7eba477657c5fb81c808318460328758e8367ecdd1964b6330c73cae43", size = 666106, upload-time = "2025-04-04T12:04:02.366Z" }, - { url = "https://files.pythonhosted.org/packages/77/e4/dcf62bd29e5e190bd21bfccaa4f3386e01bf40d948c239239c2f1e726729/pyzmq-26.4.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5e48a830bfd152fe17fbdeaf99ac5271aa4122521bf0d275b6b24e52ef35eb6", size = 902056, upload-time = "2025-04-04T12:04:03.919Z" }, - { url = "https://files.pythonhosted.org/packages/1a/cf/b36b3d7aea236087d20189bec1a87eeb2b66009731d7055e5c65f845cdba/pyzmq-26.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31be2b6de98c824c06f5574331f805707c667dc8f60cb18580b7de078479891e", size = 860148, upload-time = "2025-04-04T12:04:05.581Z" }, - { url = "https://files.pythonhosted.org/packages/18/a6/f048826bc87528c208e90604c3bf573801e54bd91e390cbd2dfa860e82dc/pyzmq-26.4.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:6332452034be001bbf3206ac59c0d2a7713de5f25bb38b06519fc6967b7cf771", size = 855983, upload-time = "2025-04-04T12:04:07.096Z" }, - { url = "https://files.pythonhosted.org/packages/0a/27/454d34ab6a1d9772a36add22f17f6b85baf7c16e14325fa29e7202ca8ee8/pyzmq-26.4.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:da8c0f5dd352136853e6a09b1b986ee5278dfddfebd30515e16eae425c872b30", size = 1197274, upload-time = "2025-04-04T12:04:08.523Z" }, - { url = "https://files.pythonhosted.org/packages/f4/3d/7abfeab6b83ad38aa34cbd57c6fc29752c391e3954fd12848bd8d2ec0df6/pyzmq-26.4.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:f4ccc1a0a2c9806dda2a2dd118a3b7b681e448f3bb354056cad44a65169f6d86", size = 1507120, upload-time = "2025-04-04T12:04:10.58Z" }, - { url = "https://files.pythonhosted.org/packages/13/ff/bc8d21dbb9bc8705126e875438a1969c4f77e03fc8565d6901c7933a3d01/pyzmq-26.4.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:1c0b5fceadbab461578daf8d1dcc918ebe7ddd2952f748cf30c7cf2de5d51101", size = 1406738, upload-time = "2025-04-04T12:04:12.509Z" }, - { url = "https://files.pythonhosted.org/packages/f5/5d/d4cd85b24de71d84d81229e3bbb13392b2698432cf8fdcea5afda253d587/pyzmq-26.4.0-cp313-cp313-win32.whl", hash = "sha256:28e2b0ff5ba4b3dd11062d905682bad33385cfa3cc03e81abd7f0822263e6637", size = 577826, upload-time = "2025-04-04T12:04:14.289Z" }, - { url = "https://files.pythonhosted.org/packages/c6/6c/f289c1789d7bb6e5a3b3bef7b2a55089b8561d17132be7d960d3ff33b14e/pyzmq-26.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:23ecc9d241004c10e8b4f49d12ac064cd7000e1643343944a10df98e57bc544b", size = 640406, upload-time = "2025-04-04T12:04:15.757Z" }, - { url = "https://files.pythonhosted.org/packages/b3/99/676b8851cb955eb5236a0c1e9ec679ea5ede092bf8bf2c8a68d7e965cac3/pyzmq-26.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:1edb0385c7f025045d6e0f759d4d3afe43c17a3d898914ec6582e6f464203c08", size = 556216, upload-time = "2025-04-04T12:04:17.212Z" }, - { url = "https://files.pythonhosted.org/packages/65/c2/1fac340de9d7df71efc59d9c50fc7a635a77b103392d1842898dd023afcb/pyzmq-26.4.0-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:93a29e882b2ba1db86ba5dd5e88e18e0ac6b627026c5cfbec9983422011b82d4", size = 1333769, upload-time = "2025-04-04T12:04:18.665Z" }, - { url = "https://files.pythonhosted.org/packages/5c/c7/6c03637e8d742c3b00bec4f5e4cd9d1c01b2f3694c6f140742e93ca637ed/pyzmq-26.4.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb45684f276f57110bb89e4300c00f1233ca631f08f5f42528a5c408a79efc4a", size = 658826, upload-time = "2025-04-04T12:04:20.405Z" }, - { url = "https://files.pythonhosted.org/packages/a5/97/a8dca65913c0f78e0545af2bb5078aebfc142ca7d91cdaffa1fbc73e5dbd/pyzmq-26.4.0-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f72073e75260cb301aad4258ad6150fa7f57c719b3f498cb91e31df16784d89b", size = 891650, upload-time = "2025-04-04T12:04:22.413Z" }, - { url = "https://files.pythonhosted.org/packages/7d/7e/f63af1031eb060bf02d033732b910fe48548dcfdbe9c785e9f74a6cc6ae4/pyzmq-26.4.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be37e24b13026cfedd233bcbbccd8c0bcd2fdd186216094d095f60076201538d", size = 849776, upload-time = "2025-04-04T12:04:23.959Z" }, - { url = "https://files.pythonhosted.org/packages/f6/fa/1a009ce582802a895c0d5fe9413f029c940a0a8ee828657a3bb0acffd88b/pyzmq-26.4.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:237b283044934d26f1eeff4075f751b05d2f3ed42a257fc44386d00df6a270cf", size = 842516, upload-time = "2025-04-04T12:04:25.449Z" }, - { url = "https://files.pythonhosted.org/packages/6e/bc/f88b0bad0f7a7f500547d71e99f10336f2314e525d4ebf576a1ea4a1d903/pyzmq-26.4.0-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:b30f862f6768b17040929a68432c8a8be77780317f45a353cb17e423127d250c", size = 1189183, upload-time = "2025-04-04T12:04:27.035Z" }, - { url = "https://files.pythonhosted.org/packages/d9/8c/db446a3dd9cf894406dec2e61eeffaa3c07c3abb783deaebb9812c4af6a5/pyzmq-26.4.0-cp313-cp313t-musllinux_1_1_i686.whl", hash = "sha256:c80fcd3504232f13617c6ab501124d373e4895424e65de8b72042333316f64a8", size = 1495501, upload-time = "2025-04-04T12:04:28.833Z" }, - { url = "https://files.pythonhosted.org/packages/05/4c/bf3cad0d64c3214ac881299c4562b815f05d503bccc513e3fd4fdc6f67e4/pyzmq-26.4.0-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:26a2a7451606b87f67cdeca2c2789d86f605da08b4bd616b1a9981605ca3a364", size = 1395540, upload-time = "2025-04-04T12:04:30.562Z" }, - { url = "https://files.pythonhosted.org/packages/06/91/21d3af57bc77e86e9d1e5384f256fd25cdb4c8eed4c45c8119da8120915f/pyzmq-26.4.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:a88643de8abd000ce99ca72056a1a2ae15881ee365ecb24dd1d9111e43d57842", size = 1340634, upload-time = "2025-04-04T12:04:47.661Z" }, - { url = "https://files.pythonhosted.org/packages/54/e6/58cd825023e998a0e49db7322b3211e6cf93f0796710b77d1496304c10d1/pyzmq-26.4.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0a744ce209ecb557406fb928f3c8c55ce79b16c3eeb682da38ef5059a9af0848", size = 907880, upload-time = "2025-04-04T12:04:49.294Z" }, - { url = "https://files.pythonhosted.org/packages/72/83/619e44a766ef738cb7e8ed8e5a54565627801bdb027ca6dfb70762385617/pyzmq-26.4.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9434540f333332224ecb02ee6278b6c6f11ea1266b48526e73c903119b2f420f", size = 863003, upload-time = "2025-04-04T12:04:51Z" }, - { url = "https://files.pythonhosted.org/packages/b6/6a/a59af31320598bdc63d2c5a3181d14a89673c2c794540678285482e8a342/pyzmq-26.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6c6f0a23e55cd38d27d4c89add963294ea091ebcb104d7fdab0f093bc5abb1c", size = 673432, upload-time = "2025-04-04T12:04:52.611Z" }, - { url = "https://files.pythonhosted.org/packages/29/ae/64dd6c18b08ce2cb009c60f11cf01c87f323acd80344d8b059c0304a7370/pyzmq-26.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:6145df55dc2309f6ef72d70576dcd5aabb0fd373311613fe85a5e547c722b780", size = 1205221, upload-time = "2025-04-04T12:04:54.31Z" }, - { url = "https://files.pythonhosted.org/packages/d0/0b/c583ab750957b025244a66948831bc9ca486d11c820da4626caf6480ee1a/pyzmq-26.4.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2ea81823840ef8c56e5d2f9918e4d571236294fea4d1842b302aebffb9e40997", size = 1515299, upload-time = "2025-04-04T12:04:56.063Z" }, - { url = "https://files.pythonhosted.org/packages/22/ba/95ba76292c49dd9c6dff1f127b4867033020b708d101cba6e4fc5a3d166d/pyzmq-26.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:cc2abc385dc37835445abe206524fbc0c9e3fce87631dfaa90918a1ba8f425eb", size = 1415366, upload-time = "2025-04-04T12:04:58.241Z" }, - { url = "https://files.pythonhosted.org/packages/6e/65/51abe36169effda26ac7400ffac96f463e09dff40d344cdc2629d9a59162/pyzmq-26.4.0-cp39-cp39-win32.whl", hash = "sha256:41a2508fe7bed4c76b4cf55aacfb8733926f59d440d9ae2b81ee8220633b4d12", size = 580773, upload-time = "2025-04-04T12:04:59.786Z" }, - { url = "https://files.pythonhosted.org/packages/89/68/d9ac94086c63a0ed8d73e9e8aec54b39f481696698a5a939a7207629fb30/pyzmq-26.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:d4000e8255d6cbce38982e5622ebb90823f3409b7ffe8aeae4337ef7d6d2612a", size = 644340, upload-time = "2025-04-04T12:05:01.389Z" }, - { url = "https://files.pythonhosted.org/packages/dc/8f/66c261d657c1b0791ee5b372c90b1646b453adb581fcdc1dc5c94e5b03e3/pyzmq-26.4.0-cp39-cp39-win_arm64.whl", hash = "sha256:b4f6919d9c120488246bdc2a2f96662fa80d67b35bd6d66218f457e722b3ff64", size = 560075, upload-time = "2025-04-04T12:05:02.975Z" }, - { url = "https://files.pythonhosted.org/packages/47/03/96004704a84095f493be8d2b476641f5c967b269390173f85488a53c1c13/pyzmq-26.4.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:98d948288ce893a2edc5ec3c438fe8de2daa5bbbd6e2e865ec5f966e237084ba", size = 834408, upload-time = "2025-04-04T12:05:04.569Z" }, - { url = "https://files.pythonhosted.org/packages/e4/7f/68d8f3034a20505db7551cb2260248be28ca66d537a1ac9a257913d778e4/pyzmq-26.4.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9f34f5c9e0203ece706a1003f1492a56c06c0632d86cb77bcfe77b56aacf27b", size = 569580, upload-time = "2025-04-04T12:05:06.283Z" }, - { url = "https://files.pythonhosted.org/packages/9b/a6/2b0d6801ec33f2b2a19dd8d02e0a1e8701000fec72926e6787363567d30c/pyzmq-26.4.0-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:80c9b48aef586ff8b698359ce22f9508937c799cc1d2c9c2f7c95996f2300c94", size = 798250, upload-time = "2025-04-04T12:05:07.88Z" }, - { url = "https://files.pythonhosted.org/packages/96/2a/0322b3437de977dcac8a755d6d7ce6ec5238de78e2e2d9353730b297cf12/pyzmq-26.4.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3f2a5b74009fd50b53b26f65daff23e9853e79aa86e0aa08a53a7628d92d44a", size = 756758, upload-time = "2025-04-04T12:05:09.483Z" }, - { url = "https://files.pythonhosted.org/packages/c2/33/43704f066369416d65549ccee366cc19153911bec0154da7c6b41fca7e78/pyzmq-26.4.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:61c5f93d7622d84cb3092d7f6398ffc77654c346545313a3737e266fc11a3beb", size = 555371, upload-time = "2025-04-04T12:05:11.062Z" }, - { url = "https://files.pythonhosted.org/packages/04/52/a70fcd5592715702248306d8e1729c10742c2eac44529984413b05c68658/pyzmq-26.4.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:4478b14cb54a805088299c25a79f27eaf530564a7a4f72bf432a040042b554eb", size = 834405, upload-time = "2025-04-04T12:05:13.3Z" }, - { url = "https://files.pythonhosted.org/packages/25/f9/1a03f1accff16b3af1a6fa22cbf7ced074776abbf688b2e9cb4629700c62/pyzmq-26.4.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a28ac29c60e4ba84b5f58605ace8ad495414a724fe7aceb7cf06cd0598d04e1", size = 569578, upload-time = "2025-04-04T12:05:15.36Z" }, - { url = "https://files.pythonhosted.org/packages/76/0c/3a633acd762aa6655fcb71fa841907eae0ab1e8582ff494b137266de341d/pyzmq-26.4.0-pp311-pypy311_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43b03c1ceea27c6520124f4fb2ba9c647409b9abdf9a62388117148a90419494", size = 798248, upload-time = "2025-04-04T12:05:17.376Z" }, - { url = "https://files.pythonhosted.org/packages/cd/cc/6c99c84aa60ac1cc56747bed6be8ce6305b9b861d7475772e7a25ce019d3/pyzmq-26.4.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7731abd23a782851426d4e37deb2057bf9410848a4459b5ede4fe89342e687a9", size = 756757, upload-time = "2025-04-04T12:05:19.19Z" }, - { url = "https://files.pythonhosted.org/packages/13/9c/d8073bd898eb896e94c679abe82e47506e2b750eb261cf6010ced869797c/pyzmq-26.4.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:a222ad02fbe80166b0526c038776e8042cd4e5f0dec1489a006a1df47e9040e0", size = 555371, upload-time = "2025-04-04T12:05:20.702Z" }, - { url = "https://files.pythonhosted.org/packages/af/b2/71a644b629e1a93ccae9e22a45aec9d23065dfcc24c399cb837f81cd08c2/pyzmq-26.4.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:552b0d2e39987733e1e9e948a0ced6ff75e0ea39ab1a1db2fc36eb60fd8760db", size = 834397, upload-time = "2025-04-04T12:05:31.217Z" }, - { url = "https://files.pythonhosted.org/packages/a9/dd/052a25651eaaff8f5fd652fb40a3abb400e71207db2d605cf6faf0eac598/pyzmq-26.4.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd670a8aa843f2ee637039bbd412e0d7294a5e588e1ecc9ad98b0cdc050259a4", size = 569571, upload-time = "2025-04-04T12:05:32.877Z" }, - { url = "https://files.pythonhosted.org/packages/a5/5d/201ca10b5d12ab187a418352c06d70c3e2087310af038b11056aba1359be/pyzmq-26.4.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d367b7b775a0e1e54a59a2ba3ed4d5e0a31566af97cc9154e34262777dab95ed", size = 798243, upload-time = "2025-04-04T12:05:34.91Z" }, - { url = "https://files.pythonhosted.org/packages/bd/d4/2c64e54749536ad1633400f28d71e71e19375d00ce1fe9bb1123364dc927/pyzmq-26.4.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8112af16c406e4a93df2caef49f884f4c2bb2b558b0b5577ef0b2465d15c1abc", size = 756751, upload-time = "2025-04-04T12:05:37.12Z" }, - { url = "https://files.pythonhosted.org/packages/08/e6/34d119af43d06a8dcd88bf7a62dac69597eaba52b49ecce76ff06b40f1fd/pyzmq-26.4.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c76c298683f82669cab0b6da59071f55238c039738297c69f187a542c6d40099", size = 745400, upload-time = "2025-04-04T12:05:40.694Z" }, - { url = "https://files.pythonhosted.org/packages/f8/49/b5e471d74a63318e51f30d329b17d2550bdededaab55baed2e2499de7ce4/pyzmq-26.4.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:49b6ca2e625b46f499fb081aaf7819a177f41eeb555acb05758aa97f4f95d147", size = 555367, upload-time = "2025-04-04T12:05:42.356Z" }, + { url = "https://files.pythonhosted.org/packages/9c/09/1681d4b047626d352c083770618ac29655ab1f5c20eee31dc94c000b9b7b/pyzmq-27.0.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:b973ee650e8f442ce482c1d99ca7ab537c69098d53a3d046676a484fd710c87a", size = 1329291, upload-time = "2025-06-13T14:06:57.945Z" }, + { url = "https://files.pythonhosted.org/packages/9d/b2/9c9385225fdd54db9506ed8accbb9ea63ca813ba59d43d7f282a6a16a30b/pyzmq-27.0.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:661942bc7cd0223d569d808f2e5696d9cc120acc73bf3e88a1f1be7ab648a7e4", size = 905952, upload-time = "2025-06-13T14:07:03.232Z" }, + { url = "https://files.pythonhosted.org/packages/41/73/333c72c7ec182cdffe25649e3da1c3b9f3cf1cede63cfdc23d1384d4a601/pyzmq-27.0.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:50360fb2a056ffd16e5f4177eee67f1dd1017332ea53fb095fe7b5bf29c70246", size = 666165, upload-time = "2025-06-13T14:07:04.667Z" }, + { url = "https://files.pythonhosted.org/packages/a5/fe/fc7b9c1a50981928e25635a926653cb755364316db59ccd6e79cfb9a0b4f/pyzmq-27.0.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cf209a6dc4b420ed32a7093642843cbf8703ed0a7d86c16c0b98af46762ebefb", size = 853755, upload-time = "2025-06-13T14:07:06.93Z" }, + { url = "https://files.pythonhosted.org/packages/8c/4c/740ed4b6e8fa160cd19dc5abec8db68f440564b2d5b79c1d697d9862a2f7/pyzmq-27.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c2dace4a7041cca2fba5357a2d7c97c5effdf52f63a1ef252cfa496875a3762d", size = 1654868, upload-time = "2025-06-13T14:07:08.224Z" }, + { url = "https://files.pythonhosted.org/packages/97/00/875b2ecfcfc78ab962a59bd384995186818524ea957dc8ad3144611fae12/pyzmq-27.0.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:63af72b2955fc77caf0a77444baa2431fcabb4370219da38e1a9f8d12aaebe28", size = 2033443, upload-time = "2025-06-13T14:07:09.653Z" }, + { url = "https://files.pythonhosted.org/packages/60/55/6dd9c470c42d713297c5f2a56f7903dc1ebdb4ab2edda996445c21651900/pyzmq-27.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e8c4adce8e37e75c4215297d7745551b8dcfa5f728f23ce09bf4e678a9399413", size = 1891288, upload-time = "2025-06-13T14:07:11.099Z" }, + { url = "https://files.pythonhosted.org/packages/28/5d/54b0ef50d40d7c65a627f4a4b4127024ba9820f2af8acd933a4d30ae192e/pyzmq-27.0.0-cp310-cp310-win32.whl", hash = "sha256:5d5ef4718ecab24f785794e0e7536436698b459bfbc19a1650ef55280119d93b", size = 567936, upload-time = "2025-06-13T14:07:12.468Z" }, + { url = "https://files.pythonhosted.org/packages/18/ea/dedca4321de748ca48d3bcdb72274d4d54e8d84ea49088d3de174bd45d88/pyzmq-27.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:e40609380480b3d12c30f841323f42451c755b8fece84235236f5fe5ffca8c1c", size = 628686, upload-time = "2025-06-13T14:07:14.051Z" }, + { url = "https://files.pythonhosted.org/packages/d4/a7/fcdeedc306e71e94ac262cba2d02337d885f5cdb7e8efced8e5ffe327808/pyzmq-27.0.0-cp310-cp310-win_arm64.whl", hash = "sha256:6b0397b0be277b46762956f576e04dc06ced265759e8c2ff41a0ee1aa0064198", size = 559039, upload-time = "2025-06-13T14:07:15.289Z" }, + { url = "https://files.pythonhosted.org/packages/44/df/84c630654106d9bd9339cdb564aa941ed41b023a0264251d6743766bb50e/pyzmq-27.0.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:21457825249b2a53834fa969c69713f8b5a79583689387a5e7aed880963ac564", size = 1332718, upload-time = "2025-06-13T14:07:16.555Z" }, + { url = "https://files.pythonhosted.org/packages/c1/8e/f6a5461a07654d9840d256476434ae0ff08340bba562a455f231969772cb/pyzmq-27.0.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1958947983fef513e6e98eff9cb487b60bf14f588dc0e6bf35fa13751d2c8251", size = 908248, upload-time = "2025-06-13T14:07:18.033Z" }, + { url = "https://files.pythonhosted.org/packages/7c/93/82863e8d695a9a3ae424b63662733ae204a295a2627d52af2f62c2cd8af9/pyzmq-27.0.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0dc628b5493f9a8cd9844b8bee9732ef587ab00002157c9329e4fc0ef4d3afa", size = 668647, upload-time = "2025-06-13T14:07:19.378Z" }, + { url = "https://files.pythonhosted.org/packages/f3/85/15278769b348121eacdbfcbd8c4d40f1102f32fa6af5be1ffc032ed684be/pyzmq-27.0.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f7bbe9e1ed2c8d3da736a15694d87c12493e54cc9dc9790796f0321794bbc91f", size = 856600, upload-time = "2025-06-13T14:07:20.906Z" }, + { url = "https://files.pythonhosted.org/packages/d4/af/1c469b3d479bd095edb28e27f12eee10b8f00b356acbefa6aeb14dd295d1/pyzmq-27.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dc1091f59143b471d19eb64f54bae4f54bcf2a466ffb66fe45d94d8d734eb495", size = 1657748, upload-time = "2025-06-13T14:07:22.549Z" }, + { url = "https://files.pythonhosted.org/packages/8c/f4/17f965d0ee6380b1d6326da842a50e4b8b9699745161207945f3745e8cb5/pyzmq-27.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7011ade88c8e535cf140f8d1a59428676fbbce7c6e54fefce58bf117aefb6667", size = 2034311, upload-time = "2025-06-13T14:07:23.966Z" }, + { url = "https://files.pythonhosted.org/packages/e0/6e/7c391d81fa3149fd759de45d298003de6cfab343fb03e92c099821c448db/pyzmq-27.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2c386339d7e3f064213aede5d03d054b237937fbca6dd2197ac8cf3b25a6b14e", size = 1893630, upload-time = "2025-06-13T14:07:25.899Z" }, + { url = "https://files.pythonhosted.org/packages/0e/e0/eaffe7a86f60e556399e224229e7769b717f72fec0706b70ab2c03aa04cb/pyzmq-27.0.0-cp311-cp311-win32.whl", hash = "sha256:0546a720c1f407b2172cb04b6b094a78773491497e3644863cf5c96c42df8cff", size = 567706, upload-time = "2025-06-13T14:07:27.595Z" }, + { url = "https://files.pythonhosted.org/packages/c9/05/89354a8cffdcce6e547d48adaaf7be17007fc75572123ff4ca90a4ca04fc/pyzmq-27.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:15f39d50bd6c9091c67315ceb878a4f531957b121d2a05ebd077eb35ddc5efed", size = 630322, upload-time = "2025-06-13T14:07:28.938Z" }, + { url = "https://files.pythonhosted.org/packages/fa/07/4ab976d5e1e63976719389cc4f3bfd248a7f5f2bb2ebe727542363c61b5f/pyzmq-27.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:c5817641eebb391a2268c27fecd4162448e03538387093cdbd8bf3510c316b38", size = 558435, upload-time = "2025-06-13T14:07:30.256Z" }, + { url = "https://files.pythonhosted.org/packages/93/a7/9ad68f55b8834ede477842214feba6a4c786d936c022a67625497aacf61d/pyzmq-27.0.0-cp312-abi3-macosx_10_15_universal2.whl", hash = "sha256:cbabc59dcfaac66655c040dfcb8118f133fb5dde185e5fc152628354c1598e52", size = 1305438, upload-time = "2025-06-13T14:07:31.676Z" }, + { url = "https://files.pythonhosted.org/packages/ba/ee/26aa0f98665a22bc90ebe12dced1de5f3eaca05363b717f6fb229b3421b3/pyzmq-27.0.0-cp312-abi3-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:cb0ac5179cba4b2f94f1aa208fbb77b62c4c9bf24dd446278b8b602cf85fcda3", size = 895095, upload-time = "2025-06-13T14:07:33.104Z" }, + { url = "https://files.pythonhosted.org/packages/cf/85/c57e7ab216ecd8aa4cc7e3b83b06cc4e9cf45c87b0afc095f10cd5ce87c1/pyzmq-27.0.0-cp312-abi3-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:53a48f0228eab6cbf69fde3aa3c03cbe04e50e623ef92ae395fce47ef8a76152", size = 651826, upload-time = "2025-06-13T14:07:34.831Z" }, + { url = "https://files.pythonhosted.org/packages/69/9a/9ea7e230feda9400fb0ae0d61d7d6ddda635e718d941c44eeab22a179d34/pyzmq-27.0.0-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:111db5f395e09f7e775f759d598f43cb815fc58e0147623c4816486e1a39dc22", size = 839750, upload-time = "2025-06-13T14:07:36.553Z" }, + { url = "https://files.pythonhosted.org/packages/08/66/4cebfbe71f3dfbd417011daca267539f62ed0fbc68105357b68bbb1a25b7/pyzmq-27.0.0-cp312-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c8878011653dcdc27cc2c57e04ff96f0471e797f5c19ac3d7813a245bcb24371", size = 1641357, upload-time = "2025-06-13T14:07:38.21Z" }, + { url = "https://files.pythonhosted.org/packages/ac/f6/b0f62578c08d2471c791287149cb8c2aaea414ae98c6e995c7dbe008adfb/pyzmq-27.0.0-cp312-abi3-musllinux_1_2_i686.whl", hash = "sha256:c0ed2c1f335ba55b5fdc964622254917d6b782311c50e138863eda409fbb3b6d", size = 2020281, upload-time = "2025-06-13T14:07:39.599Z" }, + { url = "https://files.pythonhosted.org/packages/37/b9/4f670b15c7498495da9159edc374ec09c88a86d9cd5a47d892f69df23450/pyzmq-27.0.0-cp312-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:e918d70862d4cfd4b1c187310015646a14e1f5917922ab45b29f28f345eeb6be", size = 1877110, upload-time = "2025-06-13T14:07:41.027Z" }, + { url = "https://files.pythonhosted.org/packages/66/31/9dee25c226295b740609f0d46db2fe972b23b6f5cf786360980524a3ba92/pyzmq-27.0.0-cp312-abi3-win32.whl", hash = "sha256:88b4e43cab04c3c0f0d55df3b1eef62df2b629a1a369b5289a58f6fa8b07c4f4", size = 559297, upload-time = "2025-06-13T14:07:42.533Z" }, + { url = "https://files.pythonhosted.org/packages/9b/12/52da5509800f7ff2d287b2f2b4e636e7ea0f001181cba6964ff6c1537778/pyzmq-27.0.0-cp312-abi3-win_amd64.whl", hash = "sha256:dce4199bf5f648a902ce37e7b3afa286f305cd2ef7a8b6ec907470ccb6c8b371", size = 619203, upload-time = "2025-06-13T14:07:43.843Z" }, + { url = "https://files.pythonhosted.org/packages/93/6d/7f2e53b19d1edb1eb4f09ec7c3a1f945ca0aac272099eab757d15699202b/pyzmq-27.0.0-cp312-abi3-win_arm64.whl", hash = "sha256:56e46bbb85d52c1072b3f809cc1ce77251d560bc036d3a312b96db1afe76db2e", size = 551927, upload-time = "2025-06-13T14:07:45.51Z" }, + { url = "https://files.pythonhosted.org/packages/19/62/876b27c4ff777db4ceba1c69ea90d3c825bb4f8d5e7cd987ce5802e33c55/pyzmq-27.0.0-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:c36ad534c0c29b4afa088dc53543c525b23c0797e01b69fef59b1a9c0e38b688", size = 1340826, upload-time = "2025-06-13T14:07:46.881Z" }, + { url = "https://files.pythonhosted.org/packages/43/69/58ef8f4f59d3bcd505260c73bee87b008850f45edca40ddaba54273c35f4/pyzmq-27.0.0-cp313-cp313t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:67855c14173aec36395d7777aaba3cc527b393821f30143fd20b98e1ff31fd38", size = 897283, upload-time = "2025-06-13T14:07:49.562Z" }, + { url = "https://files.pythonhosted.org/packages/43/15/93a0d0396700a60475ad3c5d42c5f1c308d3570bc94626b86c71ef9953e0/pyzmq-27.0.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8617c7d43cd8ccdb62aebe984bfed77ca8f036e6c3e46dd3dddda64b10f0ab7a", size = 660567, upload-time = "2025-06-13T14:07:51.364Z" }, + { url = "https://files.pythonhosted.org/packages/0e/b3/fe055513e498ca32f64509abae19b9c9eb4d7c829e02bd8997dd51b029eb/pyzmq-27.0.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:67bfbcbd0a04c575e8103a6061d03e393d9f80ffdb9beb3189261e9e9bc5d5e9", size = 847681, upload-time = "2025-06-13T14:07:52.77Z" }, + { url = "https://files.pythonhosted.org/packages/b6/4f/ff15300b00b5b602191f3df06bbc8dd4164e805fdd65bb77ffbb9c5facdc/pyzmq-27.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5cd11d46d7b7e5958121b3eaf4cd8638eff3a720ec527692132f05a57f14341d", size = 1650148, upload-time = "2025-06-13T14:07:54.178Z" }, + { url = "https://files.pythonhosted.org/packages/c4/6f/84bdfff2a224a6f26a24249a342e5906993c50b0761e311e81b39aef52a7/pyzmq-27.0.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:b801c2e40c5aa6072c2f4876de8dccd100af6d9918d4d0d7aa54a1d982fd4f44", size = 2023768, upload-time = "2025-06-13T14:07:55.714Z" }, + { url = "https://files.pythonhosted.org/packages/64/39/dc2db178c26a42228c5ac94a9cc595030458aa64c8d796a7727947afbf55/pyzmq-27.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:20d5cb29e8c5f76a127c75b6e7a77e846bc4b655c373baa098c26a61b7ecd0ef", size = 1885199, upload-time = "2025-06-13T14:07:57.166Z" }, + { url = "https://files.pythonhosted.org/packages/c7/21/dae7b06a1f8cdee5d8e7a63d99c5d129c401acc40410bef2cbf42025e26f/pyzmq-27.0.0-cp313-cp313t-win32.whl", hash = "sha256:a20528da85c7ac7a19b7384e8c3f8fa707841fd85afc4ed56eda59d93e3d98ad", size = 575439, upload-time = "2025-06-13T14:07:58.959Z" }, + { url = "https://files.pythonhosted.org/packages/eb/bc/1709dc55f0970cf4cb8259e435e6773f9946f41a045c2cb90e870b7072da/pyzmq-27.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:d8229f2efece6a660ee211d74d91dbc2a76b95544d46c74c615e491900dc107f", size = 639933, upload-time = "2025-06-13T14:08:00.777Z" }, + { url = "https://files.pythonhosted.org/packages/19/dc/95210fe17e5d7dba89bd663e1d88f50a8003f296284731b09f1d95309a42/pyzmq-27.0.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:100f6e5052ba42b2533011d34a018a5ace34f8cac67cb03cfa37c8bdae0ca617", size = 1330656, upload-time = "2025-06-13T14:08:17.414Z" }, + { url = "https://files.pythonhosted.org/packages/d3/7e/63f742b578316258e03ecb393d35c0964348d80834bdec8a100ed7bb9c91/pyzmq-27.0.0-cp39-cp39-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:bf6c6b061efd00404b9750e2cfbd9507492c8d4b3721ded76cb03786131be2ed", size = 906522, upload-time = "2025-06-13T14:08:18.945Z" }, + { url = "https://files.pythonhosted.org/packages/1f/bf/f0b2b67f5a9bfe0fbd0e978a2becd901f802306aa8e29161cb0963094352/pyzmq-27.0.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ee05728c0b0b2484a9fc20466fa776fffb65d95f7317a3419985b8c908563861", size = 863545, upload-time = "2025-06-13T14:08:20.386Z" }, + { url = "https://files.pythonhosted.org/packages/87/0e/7d90ccd2ef577c8bae7f926acd2011a6d960eea8a068c5fd52b419206960/pyzmq-27.0.0-cp39-cp39-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7cdf07fe0a557b131366f80727ec8ccc4b70d89f1e3f920d94a594d598d754f0", size = 666796, upload-time = "2025-06-13T14:08:21.836Z" }, + { url = "https://files.pythonhosted.org/packages/4f/6d/ca8007a313baa73361778773aef210f4902e68f468d1f93b6c8b908fabbd/pyzmq-27.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:90252fa2ff3a104219db1f5ced7032a7b5fc82d7c8d2fec2b9a3e6fd4e25576b", size = 1655599, upload-time = "2025-06-13T14:08:23.343Z" }, + { url = "https://files.pythonhosted.org/packages/46/de/5cb4f99d6c0dd8f33d729c9ebd49af279586e5ab127e93aa6ef0ecd08c4c/pyzmq-27.0.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ea6d441c513bf18c578c73c323acf7b4184507fc244762193aa3a871333c9045", size = 2034119, upload-time = "2025-06-13T14:08:26.369Z" }, + { url = "https://files.pythonhosted.org/packages/d0/8d/57cc90c8b5f30a97a7e86ec91a3b9822ec7859d477e9c30f531fb78f4a97/pyzmq-27.0.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ae2b34bcfaae20c064948a4113bf8709eee89fd08317eb293ae4ebd69b4d9740", size = 1891955, upload-time = "2025-06-13T14:08:28.39Z" }, + { url = "https://files.pythonhosted.org/packages/24/f5/a7012022573188903802ab75b5314b00e5c629228f3a36fadb421a42ebff/pyzmq-27.0.0-cp39-cp39-win32.whl", hash = "sha256:5b10bd6f008937705cf6e7bf8b6ece5ca055991e3eb130bca8023e20b86aa9a3", size = 568497, upload-time = "2025-06-13T14:08:30.089Z" }, + { url = "https://files.pythonhosted.org/packages/9b/f3/2a4b2798275a574801221d94d599ed3e26d19f6378a7364cdfa3bee53944/pyzmq-27.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:00387d12a8af4b24883895f7e6b9495dc20a66027b696536edac35cb988c38f3", size = 629315, upload-time = "2025-06-13T14:08:31.877Z" }, + { url = "https://files.pythonhosted.org/packages/da/eb/386a70314f305816142d6e8537f5557e5fd9614c03698d6c88cbd6c41190/pyzmq-27.0.0-cp39-cp39-win_arm64.whl", hash = "sha256:4c19d39c04c29a6619adfeb19e3735c421b3bfee082f320662f52e59c47202ba", size = 559596, upload-time = "2025-06-13T14:08:33.357Z" }, + { url = "https://files.pythonhosted.org/packages/09/6f/be6523a7f3821c0b5370912ef02822c028611360e0d206dd945bdbf9eaef/pyzmq-27.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:656c1866505a5735d0660b7da6d7147174bbf59d4975fc2b7f09f43c9bc25745", size = 835950, upload-time = "2025-06-13T14:08:35Z" }, + { url = "https://files.pythonhosted.org/packages/c6/1e/a50fdd5c15018de07ab82a61bc460841be967ee7bbe7abee3b714d66f7ac/pyzmq-27.0.0-pp310-pypy310_pp73-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:74175b9e12779382432dd1d1f5960ebe7465d36649b98a06c6b26be24d173fab", size = 799876, upload-time = "2025-06-13T14:08:36.849Z" }, + { url = "https://files.pythonhosted.org/packages/88/a1/89eb5b71f5a504f8f887aceb8e1eb3626e00c00aa8085381cdff475440dc/pyzmq-27.0.0-pp310-pypy310_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8c6de908465697a8708e4d6843a1e884f567962fc61eb1706856545141d0cbb", size = 567400, upload-time = "2025-06-13T14:08:38.95Z" }, + { url = "https://files.pythonhosted.org/packages/56/aa/4571dbcff56cfb034bac73fde8294e123c975ce3eea89aff31bf6dc6382b/pyzmq-27.0.0-pp310-pypy310_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c644aaacc01d0df5c7072826df45e67301f191c55f68d7b2916d83a9ddc1b551", size = 747031, upload-time = "2025-06-13T14:08:40.413Z" }, + { url = "https://files.pythonhosted.org/packages/46/e0/d25f30fe0991293c5b2f5ef3b070d35fa6d57c0c7428898c3ab4913d0297/pyzmq-27.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:10f70c1d9a446a85013a36871a296007f6fe4232b530aa254baf9da3f8328bc0", size = 544726, upload-time = "2025-06-13T14:08:41.997Z" }, + { url = "https://files.pythonhosted.org/packages/98/a6/92394373b8dbc1edc9d53c951e8d3989d518185174ee54492ec27711779d/pyzmq-27.0.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:cd1dc59763effd1576f8368047c9c31468fce0af89d76b5067641137506792ae", size = 835948, upload-time = "2025-06-13T14:08:43.516Z" }, + { url = "https://files.pythonhosted.org/packages/56/f3/4dc38d75d9995bfc18773df3e41f2a2ca9b740b06f1a15dbf404077e7588/pyzmq-27.0.0-pp311-pypy311_pp73-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:60e8cc82d968174650c1860d7b716366caab9973787a1c060cf8043130f7d0f7", size = 799874, upload-time = "2025-06-13T14:08:45.017Z" }, + { url = "https://files.pythonhosted.org/packages/ab/ba/64af397e0f421453dc68e31d5e0784d554bf39013a2de0872056e96e58af/pyzmq-27.0.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:14fe7aaac86e4e93ea779a821967360c781d7ac5115b3f1a171ced77065a0174", size = 567400, upload-time = "2025-06-13T14:08:46.855Z" }, + { url = "https://files.pythonhosted.org/packages/63/87/ec956cbe98809270b59a22891d5758edae147a258e658bf3024a8254c855/pyzmq-27.0.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6ad0562d4e6abb785be3e4dd68599c41be821b521da38c402bc9ab2a8e7ebc7e", size = 747031, upload-time = "2025-06-13T14:08:48.419Z" }, + { url = "https://files.pythonhosted.org/packages/be/8a/4a3764a68abc02e2fbb0668d225b6fda5cd39586dd099cee8b2ed6ab0452/pyzmq-27.0.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:9df43a2459cd3a3563404c1456b2c4c69564daa7dbaf15724c09821a3329ce46", size = 544726, upload-time = "2025-06-13T14:08:49.903Z" }, + { url = "https://files.pythonhosted.org/packages/03/f6/11b2a6c8cd13275c31cddc3f89981a1b799a3c41dec55289fa18dede96b5/pyzmq-27.0.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:39ddd3ba0a641f01d8f13a3cfd4c4924eb58e660d8afe87e9061d6e8ca6f7ac3", size = 835944, upload-time = "2025-06-13T14:08:59.189Z" }, + { url = "https://files.pythonhosted.org/packages/73/34/aa39076f4e07ae1912fa4b966fe24e831e01d736d4c1c7e8a3aa28a555b5/pyzmq-27.0.0-pp39-pypy39_pp73-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:8ca7e6a0388dd9e1180b14728051068f4efe83e0d2de058b5ff92c63f399a73f", size = 799869, upload-time = "2025-06-13T14:09:00.758Z" }, + { url = "https://files.pythonhosted.org/packages/65/f3/81ed6b3dd242408ee79c0d8a88734644acf208baee8666ecd7e52664cf55/pyzmq-27.0.0-pp39-pypy39_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2524c40891be6a3106885a3935d58452dd83eb7a5742a33cc780a1ad4c49dec0", size = 758371, upload-time = "2025-06-13T14:09:02.461Z" }, + { url = "https://files.pythonhosted.org/packages/e1/04/dac4ca674764281caf744e8adefd88f7e325e1605aba0f9a322094b903fa/pyzmq-27.0.0-pp39-pypy39_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6a56e3e5bd2d62a01744fd2f1ce21d760c7c65f030e9522738d75932a14ab62a", size = 567393, upload-time = "2025-06-13T14:09:04.037Z" }, + { url = "https://files.pythonhosted.org/packages/51/8b/619a9ee2fa4d3c724fbadde946427735ade64da03894b071bbdc3b789d83/pyzmq-27.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:096af9e133fec3a72108ddefba1e42985cb3639e9de52cfd336b6fc23aa083e9", size = 544715, upload-time = "2025-06-13T14:09:05.579Z" }, ] [[package]] @@ -2642,7 +2622,7 @@ wheels = [ [[package]] name = "requests" -version = "2.32.3" +version = "2.32.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, @@ -2650,9 +2630,9 @@ dependencies = [ { name = "idna" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218, upload-time = "2024-05-29T15:37:49.536Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e1/0a/929373653770d8a0d7ea76c37de6e41f11eb07559b103b1c02cafb3f7cf8/requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422", size = 135258, upload-time = "2025-06-09T16:43:07.34Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928, upload-time = "2024-05-29T15:37:47.027Z" }, + { url = "https://files.pythonhosted.org/packages/7c/e4/56027c4a6b4ae70ca9de302488c5ca95ad4a39e190093d6c1a8ace08341b/requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", size = 64847, upload-time = "2025-06-09T16:43:05.728Z" }, ] [[package]] @@ -2690,151 +2670,178 @@ wheels = [ [[package]] name = "rpds-py" -version = "0.25.1" +version = "0.26.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8c/a6/60184b7fc00dd3ca80ac635dd5b8577d444c57e8e8742cecabfacb829921/rpds_py-0.25.1.tar.gz", hash = "sha256:8960b6dac09b62dac26e75d7e2c4a22efb835d827a7278c34f72b2b84fa160e3", size = 27304, upload-time = "2025-05-21T12:46:12.502Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a5/aa/4456d84bbb54adc6a916fb10c9b374f78ac840337644e4a5eda229c81275/rpds_py-0.26.0.tar.gz", hash = "sha256:20dae58a859b0906f0685642e591056f1e787f3a8b39c8e8749a45dc7d26bdb0", size = 27385, upload-time = "2025-07-01T15:57:13.958Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cb/09/e1158988e50905b7f8306487a576b52d32aa9a87f79f7ab24ee8db8b6c05/rpds_py-0.25.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:f4ad628b5174d5315761b67f212774a32f5bad5e61396d38108bd801c0a8f5d9", size = 373140, upload-time = "2025-05-21T12:42:38.834Z" }, - { url = "https://files.pythonhosted.org/packages/e0/4b/a284321fb3c45c02fc74187171504702b2934bfe16abab89713eedfe672e/rpds_py-0.25.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8c742af695f7525e559c16f1562cf2323db0e3f0fbdcabdf6865b095256b2d40", size = 358860, upload-time = "2025-05-21T12:42:41.394Z" }, - { url = "https://files.pythonhosted.org/packages/4e/46/8ac9811150c75edeae9fc6fa0e70376c19bc80f8e1f7716981433905912b/rpds_py-0.25.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:605ffe7769e24b1800b4d024d24034405d9404f0bc2f55b6db3362cd34145a6f", size = 386179, upload-time = "2025-05-21T12:42:43.213Z" }, - { url = "https://files.pythonhosted.org/packages/f3/ec/87eb42d83e859bce91dcf763eb9f2ab117142a49c9c3d17285440edb5b69/rpds_py-0.25.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ccc6f3ddef93243538be76f8e47045b4aad7a66a212cd3a0f23e34469473d36b", size = 400282, upload-time = "2025-05-21T12:42:44.92Z" }, - { url = "https://files.pythonhosted.org/packages/68/c8/2a38e0707d7919c8c78e1d582ab15cf1255b380bcb086ca265b73ed6db23/rpds_py-0.25.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f70316f760174ca04492b5ab01be631a8ae30cadab1d1081035136ba12738cfa", size = 521824, upload-time = "2025-05-21T12:42:46.856Z" }, - { url = "https://files.pythonhosted.org/packages/5e/2c/6a92790243569784dde84d144bfd12bd45102f4a1c897d76375076d730ab/rpds_py-0.25.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1dafef8df605fdb46edcc0bf1573dea0d6d7b01ba87f85cd04dc855b2b4479e", size = 411644, upload-time = "2025-05-21T12:42:48.838Z" }, - { url = "https://files.pythonhosted.org/packages/eb/76/66b523ffc84cf47db56efe13ae7cf368dee2bacdec9d89b9baca5e2e6301/rpds_py-0.25.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0701942049095741a8aeb298a31b203e735d1c61f4423511d2b1a41dcd8a16da", size = 386955, upload-time = "2025-05-21T12:42:50.835Z" }, - { url = "https://files.pythonhosted.org/packages/b6/b9/a362d7522feaa24dc2b79847c6175daa1c642817f4a19dcd5c91d3e2c316/rpds_py-0.25.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e87798852ae0b37c88babb7f7bbbb3e3fecc562a1c340195b44c7e24d403e380", size = 421039, upload-time = "2025-05-21T12:42:52.348Z" }, - { url = "https://files.pythonhosted.org/packages/0f/c4/b5b6f70b4d719b6584716889fd3413102acf9729540ee76708d56a76fa97/rpds_py-0.25.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3bcce0edc1488906c2d4c75c94c70a0417e83920dd4c88fec1078c94843a6ce9", size = 563290, upload-time = "2025-05-21T12:42:54.404Z" }, - { url = "https://files.pythonhosted.org/packages/87/a3/2e6e816615c12a8f8662c9d8583a12eb54c52557521ef218cbe3095a8afa/rpds_py-0.25.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e2f6a2347d3440ae789505693a02836383426249d5293541cd712e07e7aecf54", size = 592089, upload-time = "2025-05-21T12:42:55.976Z" }, - { url = "https://files.pythonhosted.org/packages/c0/08/9b8e1050e36ce266135994e2c7ec06e1841f1c64da739daeb8afe9cb77a4/rpds_py-0.25.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:4fd52d3455a0aa997734f3835cbc4c9f32571345143960e7d7ebfe7b5fbfa3b2", size = 558400, upload-time = "2025-05-21T12:42:58.032Z" }, - { url = "https://files.pythonhosted.org/packages/f2/df/b40b8215560b8584baccd839ff5c1056f3c57120d79ac41bd26df196da7e/rpds_py-0.25.1-cp310-cp310-win32.whl", hash = "sha256:3f0b1798cae2bbbc9b9db44ee068c556d4737911ad53a4e5093d09d04b3bbc24", size = 219741, upload-time = "2025-05-21T12:42:59.479Z" }, - { url = "https://files.pythonhosted.org/packages/10/99/e4c58be18cf5d8b40b8acb4122bc895486230b08f978831b16a3916bd24d/rpds_py-0.25.1-cp310-cp310-win_amd64.whl", hash = "sha256:3ebd879ab996537fc510a2be58c59915b5dd63bccb06d1ef514fee787e05984a", size = 231553, upload-time = "2025-05-21T12:43:01.425Z" }, - { url = "https://files.pythonhosted.org/packages/95/e1/df13fe3ddbbea43567e07437f097863b20c99318ae1f58a0fe389f763738/rpds_py-0.25.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:5f048bbf18b1f9120685c6d6bb70cc1a52c8cc11bdd04e643d28d3be0baf666d", size = 373341, upload-time = "2025-05-21T12:43:02.978Z" }, - { url = "https://files.pythonhosted.org/packages/7a/58/deef4d30fcbcbfef3b6d82d17c64490d5c94585a2310544ce8e2d3024f83/rpds_py-0.25.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4fbb0dbba559959fcb5d0735a0f87cdbca9e95dac87982e9b95c0f8f7ad10255", size = 359111, upload-time = "2025-05-21T12:43:05.128Z" }, - { url = "https://files.pythonhosted.org/packages/bb/7e/39f1f4431b03e96ebaf159e29a0f82a77259d8f38b2dd474721eb3a8ac9b/rpds_py-0.25.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4ca54b9cf9d80b4016a67a0193ebe0bcf29f6b0a96f09db942087e294d3d4c2", size = 386112, upload-time = "2025-05-21T12:43:07.13Z" }, - { url = "https://files.pythonhosted.org/packages/db/e7/847068a48d63aec2ae695a1646089620b3b03f8ccf9f02c122ebaf778f3c/rpds_py-0.25.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1ee3e26eb83d39b886d2cb6e06ea701bba82ef30a0de044d34626ede51ec98b0", size = 400362, upload-time = "2025-05-21T12:43:08.693Z" }, - { url = "https://files.pythonhosted.org/packages/3b/3d/9441d5db4343d0cee759a7ab4d67420a476cebb032081763de934719727b/rpds_py-0.25.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:89706d0683c73a26f76a5315d893c051324d771196ae8b13e6ffa1ffaf5e574f", size = 522214, upload-time = "2025-05-21T12:43:10.694Z" }, - { url = "https://files.pythonhosted.org/packages/a2/ec/2cc5b30d95f9f1a432c79c7a2f65d85e52812a8f6cbf8768724571710786/rpds_py-0.25.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c2013ee878c76269c7b557a9a9c042335d732e89d482606990b70a839635feb7", size = 411491, upload-time = "2025-05-21T12:43:12.739Z" }, - { url = "https://files.pythonhosted.org/packages/dc/6c/44695c1f035077a017dd472b6a3253553780837af2fac9b6ac25f6a5cb4d/rpds_py-0.25.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45e484db65e5380804afbec784522de84fa95e6bb92ef1bd3325d33d13efaebd", size = 386978, upload-time = "2025-05-21T12:43:14.25Z" }, - { url = "https://files.pythonhosted.org/packages/b1/74/b4357090bb1096db5392157b4e7ed8bb2417dc7799200fcbaee633a032c9/rpds_py-0.25.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:48d64155d02127c249695abb87d39f0faf410733428d499867606be138161d65", size = 420662, upload-time = "2025-05-21T12:43:15.8Z" }, - { url = "https://files.pythonhosted.org/packages/26/dd/8cadbebf47b96e59dfe8b35868e5c38a42272699324e95ed522da09d3a40/rpds_py-0.25.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:048893e902132fd6548a2e661fb38bf4896a89eea95ac5816cf443524a85556f", size = 563385, upload-time = "2025-05-21T12:43:17.78Z" }, - { url = "https://files.pythonhosted.org/packages/c3/ea/92960bb7f0e7a57a5ab233662f12152085c7dc0d5468534c65991a3d48c9/rpds_py-0.25.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0317177b1e8691ab5879f4f33f4b6dc55ad3b344399e23df2e499de7b10a548d", size = 592047, upload-time = "2025-05-21T12:43:19.457Z" }, - { url = "https://files.pythonhosted.org/packages/61/ad/71aabc93df0d05dabcb4b0c749277881f8e74548582d96aa1bf24379493a/rpds_py-0.25.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bffcf57826d77a4151962bf1701374e0fc87f536e56ec46f1abdd6a903354042", size = 557863, upload-time = "2025-05-21T12:43:21.69Z" }, - { url = "https://files.pythonhosted.org/packages/93/0f/89df0067c41f122b90b76f3660028a466eb287cbe38efec3ea70e637ca78/rpds_py-0.25.1-cp311-cp311-win32.whl", hash = "sha256:cda776f1967cb304816173b30994faaf2fd5bcb37e73118a47964a02c348e1bc", size = 219627, upload-time = "2025-05-21T12:43:23.311Z" }, - { url = "https://files.pythonhosted.org/packages/7c/8d/93b1a4c1baa903d0229374d9e7aa3466d751f1d65e268c52e6039c6e338e/rpds_py-0.25.1-cp311-cp311-win_amd64.whl", hash = "sha256:dc3c1ff0abc91444cd20ec643d0f805df9a3661fcacf9c95000329f3ddf268a4", size = 231603, upload-time = "2025-05-21T12:43:25.145Z" }, - { url = "https://files.pythonhosted.org/packages/cb/11/392605e5247bead2f23e6888e77229fbd714ac241ebbebb39a1e822c8815/rpds_py-0.25.1-cp311-cp311-win_arm64.whl", hash = "sha256:5a3ddb74b0985c4387719fc536faced33cadf2172769540c62e2a94b7b9be1c4", size = 223967, upload-time = "2025-05-21T12:43:26.566Z" }, - { url = "https://files.pythonhosted.org/packages/7f/81/28ab0408391b1dc57393653b6a0cf2014cc282cc2909e4615e63e58262be/rpds_py-0.25.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:b5ffe453cde61f73fea9430223c81d29e2fbf412a6073951102146c84e19e34c", size = 364647, upload-time = "2025-05-21T12:43:28.559Z" }, - { url = "https://files.pythonhosted.org/packages/2c/9a/7797f04cad0d5e56310e1238434f71fc6939d0bc517192a18bb99a72a95f/rpds_py-0.25.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:115874ae5e2fdcfc16b2aedc95b5eef4aebe91b28e7e21951eda8a5dc0d3461b", size = 350454, upload-time = "2025-05-21T12:43:30.615Z" }, - { url = "https://files.pythonhosted.org/packages/69/3c/93d2ef941b04898011e5d6eaa56a1acf46a3b4c9f4b3ad1bbcbafa0bee1f/rpds_py-0.25.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a714bf6e5e81b0e570d01f56e0c89c6375101b8463999ead3a93a5d2a4af91fa", size = 389665, upload-time = "2025-05-21T12:43:32.629Z" }, - { url = "https://files.pythonhosted.org/packages/c1/57/ad0e31e928751dde8903a11102559628d24173428a0f85e25e187defb2c1/rpds_py-0.25.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:35634369325906bcd01577da4c19e3b9541a15e99f31e91a02d010816b49bfda", size = 403873, upload-time = "2025-05-21T12:43:34.576Z" }, - { url = "https://files.pythonhosted.org/packages/16/ad/c0c652fa9bba778b4f54980a02962748479dc09632e1fd34e5282cf2556c/rpds_py-0.25.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d4cb2b3ddc16710548801c6fcc0cfcdeeff9dafbc983f77265877793f2660309", size = 525866, upload-time = "2025-05-21T12:43:36.123Z" }, - { url = "https://files.pythonhosted.org/packages/2a/39/3e1839bc527e6fcf48d5fec4770070f872cdee6c6fbc9b259932f4e88a38/rpds_py-0.25.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9ceca1cf097ed77e1a51f1dbc8d174d10cb5931c188a4505ff9f3e119dfe519b", size = 416886, upload-time = "2025-05-21T12:43:38.034Z" }, - { url = "https://files.pythonhosted.org/packages/7a/95/dd6b91cd4560da41df9d7030a038298a67d24f8ca38e150562644c829c48/rpds_py-0.25.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c2cd1a4b0c2b8c5e31ffff50d09f39906fe351389ba143c195566056c13a7ea", size = 390666, upload-time = "2025-05-21T12:43:40.065Z" }, - { url = "https://files.pythonhosted.org/packages/64/48/1be88a820e7494ce0a15c2d390ccb7c52212370badabf128e6a7bb4cb802/rpds_py-0.25.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1de336a4b164c9188cb23f3703adb74a7623ab32d20090d0e9bf499a2203ad65", size = 425109, upload-time = "2025-05-21T12:43:42.263Z" }, - { url = "https://files.pythonhosted.org/packages/cf/07/3e2a17927ef6d7720b9949ec1b37d1e963b829ad0387f7af18d923d5cfa5/rpds_py-0.25.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9fca84a15333e925dd59ce01da0ffe2ffe0d6e5d29a9eeba2148916d1824948c", size = 567244, upload-time = "2025-05-21T12:43:43.846Z" }, - { url = "https://files.pythonhosted.org/packages/d2/e5/76cf010998deccc4f95305d827847e2eae9c568099c06b405cf96384762b/rpds_py-0.25.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:88ec04afe0c59fa64e2f6ea0dd9657e04fc83e38de90f6de201954b4d4eb59bd", size = 596023, upload-time = "2025-05-21T12:43:45.932Z" }, - { url = "https://files.pythonhosted.org/packages/52/9a/df55efd84403736ba37a5a6377b70aad0fd1cb469a9109ee8a1e21299a1c/rpds_py-0.25.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a8bd2f19e312ce3e1d2c635618e8a8d8132892bb746a7cf74780a489f0f6cdcb", size = 561634, upload-time = "2025-05-21T12:43:48.263Z" }, - { url = "https://files.pythonhosted.org/packages/ab/aa/dc3620dd8db84454aaf9374bd318f1aa02578bba5e567f5bf6b79492aca4/rpds_py-0.25.1-cp312-cp312-win32.whl", hash = "sha256:e5e2f7280d8d0d3ef06f3ec1b4fd598d386cc6f0721e54f09109a8132182fbfe", size = 222713, upload-time = "2025-05-21T12:43:49.897Z" }, - { url = "https://files.pythonhosted.org/packages/a3/7f/7cef485269a50ed5b4e9bae145f512d2a111ca638ae70cc101f661b4defd/rpds_py-0.25.1-cp312-cp312-win_amd64.whl", hash = "sha256:db58483f71c5db67d643857404da360dce3573031586034b7d59f245144cc192", size = 235280, upload-time = "2025-05-21T12:43:51.893Z" }, - { url = "https://files.pythonhosted.org/packages/99/f2/c2d64f6564f32af913bf5f3f7ae41c7c263c5ae4c4e8f1a17af8af66cd46/rpds_py-0.25.1-cp312-cp312-win_arm64.whl", hash = "sha256:6d50841c425d16faf3206ddbba44c21aa3310a0cebc3c1cdfc3e3f4f9f6f5728", size = 225399, upload-time = "2025-05-21T12:43:53.351Z" }, - { url = "https://files.pythonhosted.org/packages/2b/da/323848a2b62abe6a0fec16ebe199dc6889c5d0a332458da8985b2980dffe/rpds_py-0.25.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:659d87430a8c8c704d52d094f5ba6fa72ef13b4d385b7e542a08fc240cb4a559", size = 364498, upload-time = "2025-05-21T12:43:54.841Z" }, - { url = "https://files.pythonhosted.org/packages/1f/b4/4d3820f731c80fd0cd823b3e95b9963fec681ae45ba35b5281a42382c67d/rpds_py-0.25.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:68f6f060f0bbdfb0245267da014d3a6da9be127fe3e8cc4a68c6f833f8a23bb1", size = 350083, upload-time = "2025-05-21T12:43:56.428Z" }, - { url = "https://files.pythonhosted.org/packages/d5/b1/3a8ee1c9d480e8493619a437dec685d005f706b69253286f50f498cbdbcf/rpds_py-0.25.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:083a9513a33e0b92cf6e7a6366036c6bb43ea595332c1ab5c8ae329e4bcc0a9c", size = 389023, upload-time = "2025-05-21T12:43:57.995Z" }, - { url = "https://files.pythonhosted.org/packages/3b/31/17293edcfc934dc62c3bf74a0cb449ecd549531f956b72287203e6880b87/rpds_py-0.25.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:816568614ecb22b18a010c7a12559c19f6fe993526af88e95a76d5a60b8b75fb", size = 403283, upload-time = "2025-05-21T12:43:59.546Z" }, - { url = "https://files.pythonhosted.org/packages/d1/ca/e0f0bc1a75a8925024f343258c8ecbd8828f8997ea2ac71e02f67b6f5299/rpds_py-0.25.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3c6564c0947a7f52e4792983f8e6cf9bac140438ebf81f527a21d944f2fd0a40", size = 524634, upload-time = "2025-05-21T12:44:01.087Z" }, - { url = "https://files.pythonhosted.org/packages/3e/03/5d0be919037178fff33a6672ffc0afa04ea1cfcb61afd4119d1b5280ff0f/rpds_py-0.25.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c4a128527fe415d73cf1f70a9a688d06130d5810be69f3b553bf7b45e8acf79", size = 416233, upload-time = "2025-05-21T12:44:02.604Z" }, - { url = "https://files.pythonhosted.org/packages/05/7c/8abb70f9017a231c6c961a8941403ed6557664c0913e1bf413cbdc039e75/rpds_py-0.25.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a49e1d7a4978ed554f095430b89ecc23f42014a50ac385eb0c4d163ce213c325", size = 390375, upload-time = "2025-05-21T12:44:04.162Z" }, - { url = "https://files.pythonhosted.org/packages/7a/ac/a87f339f0e066b9535074a9f403b9313fd3892d4a164d5d5f5875ac9f29f/rpds_py-0.25.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d74ec9bc0e2feb81d3f16946b005748119c0f52a153f6db6a29e8cd68636f295", size = 424537, upload-time = "2025-05-21T12:44:06.175Z" }, - { url = "https://files.pythonhosted.org/packages/1f/8f/8d5c1567eaf8c8afe98a838dd24de5013ce6e8f53a01bd47fe8bb06b5533/rpds_py-0.25.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3af5b4cc10fa41e5bc64e5c198a1b2d2864337f8fcbb9a67e747e34002ce812b", size = 566425, upload-time = "2025-05-21T12:44:08.242Z" }, - { url = "https://files.pythonhosted.org/packages/95/33/03016a6be5663b389c8ab0bbbcca68d9e96af14faeff0a04affcb587e776/rpds_py-0.25.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:79dc317a5f1c51fd9c6a0c4f48209c6b8526d0524a6904fc1076476e79b00f98", size = 595197, upload-time = "2025-05-21T12:44:10.449Z" }, - { url = "https://files.pythonhosted.org/packages/33/8d/da9f4d3e208c82fda311bff0cf0a19579afceb77cf456e46c559a1c075ba/rpds_py-0.25.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1521031351865e0181bc585147624d66b3b00a84109b57fcb7a779c3ec3772cd", size = 561244, upload-time = "2025-05-21T12:44:12.387Z" }, - { url = "https://files.pythonhosted.org/packages/e2/b3/39d5dcf7c5f742ecd6dbc88f6f84ae54184b92f5f387a4053be2107b17f1/rpds_py-0.25.1-cp313-cp313-win32.whl", hash = "sha256:5d473be2b13600b93a5675d78f59e63b51b1ba2d0476893415dfbb5477e65b31", size = 222254, upload-time = "2025-05-21T12:44:14.261Z" }, - { url = "https://files.pythonhosted.org/packages/5f/19/2d6772c8eeb8302c5f834e6d0dfd83935a884e7c5ce16340c7eaf89ce925/rpds_py-0.25.1-cp313-cp313-win_amd64.whl", hash = "sha256:a7b74e92a3b212390bdce1d93da9f6488c3878c1d434c5e751cbc202c5e09500", size = 234741, upload-time = "2025-05-21T12:44:16.236Z" }, - { url = "https://files.pythonhosted.org/packages/5b/5a/145ada26cfaf86018d0eb304fe55eafdd4f0b6b84530246bb4a7c4fb5c4b/rpds_py-0.25.1-cp313-cp313-win_arm64.whl", hash = "sha256:dd326a81afe332ede08eb39ab75b301d5676802cdffd3a8f287a5f0b694dc3f5", size = 224830, upload-time = "2025-05-21T12:44:17.749Z" }, - { url = "https://files.pythonhosted.org/packages/4b/ca/d435844829c384fd2c22754ff65889c5c556a675d2ed9eb0e148435c6690/rpds_py-0.25.1-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:a58d1ed49a94d4183483a3ce0af22f20318d4a1434acee255d683ad90bf78129", size = 359668, upload-time = "2025-05-21T12:44:19.322Z" }, - { url = "https://files.pythonhosted.org/packages/1f/01/b056f21db3a09f89410d493d2f6614d87bb162499f98b649d1dbd2a81988/rpds_py-0.25.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f251bf23deb8332823aef1da169d5d89fa84c89f67bdfb566c49dea1fccfd50d", size = 345649, upload-time = "2025-05-21T12:44:20.962Z" }, - { url = "https://files.pythonhosted.org/packages/e0/0f/e0d00dc991e3d40e03ca36383b44995126c36b3eafa0ccbbd19664709c88/rpds_py-0.25.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8dbd586bfa270c1103ece2109314dd423df1fa3d9719928b5d09e4840cec0d72", size = 384776, upload-time = "2025-05-21T12:44:22.516Z" }, - { url = "https://files.pythonhosted.org/packages/9f/a2/59374837f105f2ca79bde3c3cd1065b2f8c01678900924949f6392eab66d/rpds_py-0.25.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6d273f136e912aa101a9274c3145dcbddbe4bac560e77e6d5b3c9f6e0ed06d34", size = 395131, upload-time = "2025-05-21T12:44:24.147Z" }, - { url = "https://files.pythonhosted.org/packages/9c/dc/48e8d84887627a0fe0bac53f0b4631e90976fd5d35fff8be66b8e4f3916b/rpds_py-0.25.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:666fa7b1bd0a3810a7f18f6d3a25ccd8866291fbbc3c9b912b917a6715874bb9", size = 520942, upload-time = "2025-05-21T12:44:25.915Z" }, - { url = "https://files.pythonhosted.org/packages/7c/f5/ee056966aeae401913d37befeeab57a4a43a4f00099e0a20297f17b8f00c/rpds_py-0.25.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:921954d7fbf3fccc7de8f717799304b14b6d9a45bbeec5a8d7408ccbf531faf5", size = 411330, upload-time = "2025-05-21T12:44:27.638Z" }, - { url = "https://files.pythonhosted.org/packages/ab/74/b2cffb46a097cefe5d17f94ede7a174184b9d158a0aeb195f39f2c0361e8/rpds_py-0.25.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3d86373ff19ca0441ebeb696ef64cb58b8b5cbacffcda5a0ec2f3911732a194", size = 387339, upload-time = "2025-05-21T12:44:29.292Z" }, - { url = "https://files.pythonhosted.org/packages/7f/9a/0ff0b375dcb5161c2b7054e7d0b7575f1680127505945f5cabaac890bc07/rpds_py-0.25.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c8980cde3bb8575e7c956a530f2c217c1d6aac453474bf3ea0f9c89868b531b6", size = 418077, upload-time = "2025-05-21T12:44:30.877Z" }, - { url = "https://files.pythonhosted.org/packages/0d/a1/fda629bf20d6b698ae84c7c840cfb0e9e4200f664fc96e1f456f00e4ad6e/rpds_py-0.25.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:8eb8c84ecea987a2523e057c0d950bcb3f789696c0499290b8d7b3107a719d78", size = 562441, upload-time = "2025-05-21T12:44:32.541Z" }, - { url = "https://files.pythonhosted.org/packages/20/15/ce4b5257f654132f326f4acd87268e1006cc071e2c59794c5bdf4bebbb51/rpds_py-0.25.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:e43a005671a9ed5a650f3bc39e4dbccd6d4326b24fb5ea8be5f3a43a6f576c72", size = 590750, upload-time = "2025-05-21T12:44:34.557Z" }, - { url = "https://files.pythonhosted.org/packages/fb/ab/e04bf58a8d375aeedb5268edcc835c6a660ebf79d4384d8e0889439448b0/rpds_py-0.25.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:58f77c60956501a4a627749a6dcb78dac522f249dd96b5c9f1c6af29bfacfb66", size = 558891, upload-time = "2025-05-21T12:44:37.358Z" }, - { url = "https://files.pythonhosted.org/packages/90/82/cb8c6028a6ef6cd2b7991e2e4ced01c854b6236ecf51e81b64b569c43d73/rpds_py-0.25.1-cp313-cp313t-win32.whl", hash = "sha256:2cb9e5b5e26fc02c8a4345048cd9998c2aca7c2712bd1b36da0c72ee969a3523", size = 218718, upload-time = "2025-05-21T12:44:38.969Z" }, - { url = "https://files.pythonhosted.org/packages/b6/97/5a4b59697111c89477d20ba8a44df9ca16b41e737fa569d5ae8bff99e650/rpds_py-0.25.1-cp313-cp313t-win_amd64.whl", hash = "sha256:401ca1c4a20cc0510d3435d89c069fe0a9ae2ee6495135ac46bdd49ec0495763", size = 232218, upload-time = "2025-05-21T12:44:40.512Z" }, - { url = "https://files.pythonhosted.org/packages/89/74/716d42058ef501e2c08f27aa3ff455f6fc1bbbd19a6ab8dea07e6322d217/rpds_py-0.25.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:ce4c8e485a3c59593f1a6f683cf0ea5ab1c1dc94d11eea5619e4fb5228b40fbd", size = 373475, upload-time = "2025-05-21T12:44:42.136Z" }, - { url = "https://files.pythonhosted.org/packages/e1/21/3faa9c523e2496a2505d7440b6f24c9166f37cb7ac027cac6cfbda9b4b5f/rpds_py-0.25.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d8222acdb51a22929c3b2ddb236b69c59c72af4019d2cba961e2f9add9b6e634", size = 359349, upload-time = "2025-05-21T12:44:43.813Z" }, - { url = "https://files.pythonhosted.org/packages/6a/1c/c747fe568d21b1d679079b52b926ebc4d1497457510a1773dc5fd4b7b4e2/rpds_py-0.25.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4593c4eae9b27d22df41cde518b4b9e4464d139e4322e2127daa9b5b981b76be", size = 386526, upload-time = "2025-05-21T12:44:45.452Z" }, - { url = "https://files.pythonhosted.org/packages/0b/cc/4a41703de4fb291f13660fa3d882cbd39db5d60497c6e7fa7f5142e5e69f/rpds_py-0.25.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd035756830c712b64725a76327ce80e82ed12ebab361d3a1cdc0f51ea21acb0", size = 400526, upload-time = "2025-05-21T12:44:47.011Z" }, - { url = "https://files.pythonhosted.org/packages/f1/78/60c980bedcad8418b614f0b4d6d420ecf11225b579cec0cb4e84d168b4da/rpds_py-0.25.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:114a07e85f32b125404f28f2ed0ba431685151c037a26032b213c882f26eb908", size = 525726, upload-time = "2025-05-21T12:44:48.838Z" }, - { url = "https://files.pythonhosted.org/packages/3f/37/f2f36b7f1314b3c3200d663decf2f8e29480492a39ab22447112aead4693/rpds_py-0.25.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dec21e02e6cc932538b5203d3a8bd6aa1480c98c4914cb88eea064ecdbc6396a", size = 412045, upload-time = "2025-05-21T12:44:50.433Z" }, - { url = "https://files.pythonhosted.org/packages/df/96/e03783e87a775b1242477ccbc35895f8e9b2bbdb60e199034a6da03c2687/rpds_py-0.25.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:09eab132f41bf792c7a0ea1578e55df3f3e7f61888e340779b06050a9a3f16e9", size = 386953, upload-time = "2025-05-21T12:44:52.092Z" }, - { url = "https://files.pythonhosted.org/packages/7c/7d/1418f4b69bfb4b40481a3d84782113ad7d4cca0b38ae70b982dd5b20102a/rpds_py-0.25.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c98f126c4fc697b84c423e387337d5b07e4a61e9feac494362a59fd7a2d9ed80", size = 421144, upload-time = "2025-05-21T12:44:53.734Z" }, - { url = "https://files.pythonhosted.org/packages/b3/0e/61469912c6493ee3808012e60f4930344b974fcb6b35c4348e70b6be7bc7/rpds_py-0.25.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0e6a327af8ebf6baba1c10fadd04964c1965d375d318f4435d5f3f9651550f4a", size = 563730, upload-time = "2025-05-21T12:44:55.846Z" }, - { url = "https://files.pythonhosted.org/packages/f6/86/6d0a5cc56481ac61977b7c839677ed5c63d38cf0fcb3e2280843a8a6f476/rpds_py-0.25.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:bc120d1132cff853ff617754196d0ac0ae63befe7c8498bd67731ba368abe451", size = 592321, upload-time = "2025-05-21T12:44:57.514Z" }, - { url = "https://files.pythonhosted.org/packages/5d/87/d1e2453fe336f71e6aa296452a8c85c2118b587b1d25ce98014f75838a60/rpds_py-0.25.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:140f61d9bed7839446bdd44852e30195c8e520f81329b4201ceead4d64eb3a9f", size = 558162, upload-time = "2025-05-21T12:44:59.564Z" }, - { url = "https://files.pythonhosted.org/packages/ad/92/349f04b1644c5cef3e2e6c53b7168a28531945f9e6fca7425f6d20ddbc3c/rpds_py-0.25.1-cp39-cp39-win32.whl", hash = "sha256:9c006f3aadeda131b438c3092124bd196b66312f0caa5823ef09585a669cf449", size = 219920, upload-time = "2025-05-21T12:45:01.186Z" }, - { url = "https://files.pythonhosted.org/packages/f2/84/3969bef883a3f37ff2213795257cb7b7e93a115829670befb8de0e003031/rpds_py-0.25.1-cp39-cp39-win_amd64.whl", hash = "sha256:a61d0b2c7c9a0ae45732a77844917b427ff16ad5464b4d4f5e4adb955f582890", size = 231452, upload-time = "2025-05-21T12:45:02.85Z" }, - { url = "https://files.pythonhosted.org/packages/78/ff/566ce53529b12b4f10c0a348d316bd766970b7060b4fd50f888be3b3b281/rpds_py-0.25.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b24bf3cd93d5b6ecfbedec73b15f143596c88ee249fa98cefa9a9dc9d92c6f28", size = 373931, upload-time = "2025-05-21T12:45:05.01Z" }, - { url = "https://files.pythonhosted.org/packages/83/5d/deba18503f7c7878e26aa696e97f051175788e19d5336b3b0e76d3ef9256/rpds_py-0.25.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:0eb90e94f43e5085623932b68840b6f379f26db7b5c2e6bcef3179bd83c9330f", size = 359074, upload-time = "2025-05-21T12:45:06.714Z" }, - { url = "https://files.pythonhosted.org/packages/0d/74/313415c5627644eb114df49c56a27edba4d40cfd7c92bd90212b3604ca84/rpds_py-0.25.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d50e4864498a9ab639d6d8854b25e80642bd362ff104312d9770b05d66e5fb13", size = 387255, upload-time = "2025-05-21T12:45:08.669Z" }, - { url = "https://files.pythonhosted.org/packages/8c/c8/c723298ed6338963d94e05c0f12793acc9b91d04ed7c4ba7508e534b7385/rpds_py-0.25.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7c9409b47ba0650544b0bb3c188243b83654dfe55dcc173a86832314e1a6a35d", size = 400714, upload-time = "2025-05-21T12:45:10.39Z" }, - { url = "https://files.pythonhosted.org/packages/33/8a/51f1f6aa653c2e110ed482ef2ae94140d56c910378752a1b483af11019ee/rpds_py-0.25.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:796ad874c89127c91970652a4ee8b00d56368b7e00d3477f4415fe78164c8000", size = 523105, upload-time = "2025-05-21T12:45:12.273Z" }, - { url = "https://files.pythonhosted.org/packages/c7/a4/7873d15c088ad3bff36910b29ceb0f178e4b3232c2adbe9198de68a41e63/rpds_py-0.25.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:85608eb70a659bf4c1142b2781083d4b7c0c4e2c90eff11856a9754e965b2540", size = 411499, upload-time = "2025-05-21T12:45:13.95Z" }, - { url = "https://files.pythonhosted.org/packages/90/f3/0ce1437befe1410766d11d08239333ac1b2d940f8a64234ce48a7714669c/rpds_py-0.25.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4feb9211d15d9160bc85fa72fed46432cdc143eb9cf6d5ca377335a921ac37b", size = 387918, upload-time = "2025-05-21T12:45:15.649Z" }, - { url = "https://files.pythonhosted.org/packages/94/d4/5551247988b2a3566afb8a9dba3f1d4a3eea47793fd83000276c1a6c726e/rpds_py-0.25.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ccfa689b9246c48947d31dd9d8b16d89a0ecc8e0e26ea5253068efb6c542b76e", size = 421705, upload-time = "2025-05-21T12:45:17.788Z" }, - { url = "https://files.pythonhosted.org/packages/b0/25/5960f28f847bf736cc7ee3c545a7e1d2f3b5edaf82c96fb616c2f5ed52d0/rpds_py-0.25.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:3c5b317ecbd8226887994852e85de562f7177add602514d4ac40f87de3ae45a8", size = 564489, upload-time = "2025-05-21T12:45:19.466Z" }, - { url = "https://files.pythonhosted.org/packages/02/66/1c99884a0d44e8c2904d3c4ec302f995292d5dde892c3bf7685ac1930146/rpds_py-0.25.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:454601988aab2c6e8fd49e7634c65476b2b919647626208e376afcd22019eeb8", size = 592557, upload-time = "2025-05-21T12:45:21.362Z" }, - { url = "https://files.pythonhosted.org/packages/55/ae/4aeac84ebeffeac14abb05b3bb1d2f728d00adb55d3fb7b51c9fa772e760/rpds_py-0.25.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:1c0c434a53714358532d13539272db75a5ed9df75a4a090a753ac7173ec14e11", size = 558691, upload-time = "2025-05-21T12:45:23.084Z" }, - { url = "https://files.pythonhosted.org/packages/41/b3/728a08ff6f5e06fe3bb9af2e770e9d5fd20141af45cff8dfc62da4b2d0b3/rpds_py-0.25.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:f73ce1512e04fbe2bc97836e89830d6b4314c171587a99688082d090f934d20a", size = 231651, upload-time = "2025-05-21T12:45:24.72Z" }, - { url = "https://files.pythonhosted.org/packages/49/74/48f3df0715a585cbf5d34919c9c757a4c92c1a9eba059f2d334e72471f70/rpds_py-0.25.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ee86d81551ec68a5c25373c5643d343150cc54672b5e9a0cafc93c1870a53954", size = 374208, upload-time = "2025-05-21T12:45:26.306Z" }, - { url = "https://files.pythonhosted.org/packages/55/b0/9b01bb11ce01ec03d05e627249cc2c06039d6aa24ea5a22a39c312167c10/rpds_py-0.25.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:89c24300cd4a8e4a51e55c31a8ff3918e6651b241ee8876a42cc2b2a078533ba", size = 359262, upload-time = "2025-05-21T12:45:28.322Z" }, - { url = "https://files.pythonhosted.org/packages/a9/eb/5395621618f723ebd5116c53282052943a726dba111b49cd2071f785b665/rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:771c16060ff4e79584dc48902a91ba79fd93eade3aa3a12d6d2a4aadaf7d542b", size = 387366, upload-time = "2025-05-21T12:45:30.42Z" }, - { url = "https://files.pythonhosted.org/packages/68/73/3d51442bdb246db619d75039a50ea1cf8b5b4ee250c3e5cd5c3af5981cd4/rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:785ffacd0ee61c3e60bdfde93baa6d7c10d86f15655bd706c89da08068dc5038", size = 400759, upload-time = "2025-05-21T12:45:32.516Z" }, - { url = "https://files.pythonhosted.org/packages/b7/4c/3a32d5955d7e6cb117314597bc0f2224efc798428318b13073efe306512a/rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2a40046a529cc15cef88ac5ab589f83f739e2d332cb4d7399072242400ed68c9", size = 523128, upload-time = "2025-05-21T12:45:34.396Z" }, - { url = "https://files.pythonhosted.org/packages/be/95/1ffccd3b0bb901ae60b1dd4b1be2ab98bb4eb834cd9b15199888f5702f7b/rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:85fc223d9c76cabe5d0bff82214459189720dc135db45f9f66aa7cffbf9ff6c1", size = 411597, upload-time = "2025-05-21T12:45:36.164Z" }, - { url = "https://files.pythonhosted.org/packages/ef/6d/6e6cd310180689db8b0d2de7f7d1eabf3fb013f239e156ae0d5a1a85c27f/rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b0be9965f93c222fb9b4cc254235b3b2b215796c03ef5ee64f995b1b69af0762", size = 388053, upload-time = "2025-05-21T12:45:38.45Z" }, - { url = "https://files.pythonhosted.org/packages/4a/87/ec4186b1fe6365ced6fa470960e68fc7804bafbe7c0cf5a36237aa240efa/rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8378fa4a940f3fb509c081e06cb7f7f2adae8cf46ef258b0e0ed7519facd573e", size = 421821, upload-time = "2025-05-21T12:45:40.732Z" }, - { url = "https://files.pythonhosted.org/packages/7a/60/84f821f6bf4e0e710acc5039d91f8f594fae0d93fc368704920d8971680d/rpds_py-0.25.1-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:33358883a4490287e67a2c391dfaea4d9359860281db3292b6886bf0be3d8692", size = 564534, upload-time = "2025-05-21T12:45:42.672Z" }, - { url = "https://files.pythonhosted.org/packages/41/3a/bc654eb15d3b38f9330fe0f545016ba154d89cdabc6177b0295910cd0ebe/rpds_py-0.25.1-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:1d1fadd539298e70cac2f2cb36f5b8a65f742b9b9f1014dd4ea1f7785e2470bf", size = 592674, upload-time = "2025-05-21T12:45:44.533Z" }, - { url = "https://files.pythonhosted.org/packages/2e/ba/31239736f29e4dfc7a58a45955c5db852864c306131fd6320aea214d5437/rpds_py-0.25.1-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:9a46c2fb2545e21181445515960006e85d22025bd2fe6db23e76daec6eb689fe", size = 558781, upload-time = "2025-05-21T12:45:46.281Z" }, - { url = "https://files.pythonhosted.org/packages/78/b2/198266f070c6760e0e8cd00f9f2b9c86133ceebbe7c6d114bdcfea200180/rpds_py-0.25.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:50f2c501a89c9a5f4e454b126193c5495b9fb441a75b298c60591d8a2eb92e1b", size = 373973, upload-time = "2025-05-21T12:45:48.081Z" }, - { url = "https://files.pythonhosted.org/packages/13/79/1265eae618f88aa5d5e7122bd32dd41700bafe5a8bcea404e998848cd844/rpds_py-0.25.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7d779b325cc8238227c47fbc53964c8cc9a941d5dbae87aa007a1f08f2f77b23", size = 359326, upload-time = "2025-05-21T12:45:49.825Z" }, - { url = "https://files.pythonhosted.org/packages/30/ab/6913b96f3ac072e87e76e45fe938263b0ab0d78b6b2cef3f2e56067befc0/rpds_py-0.25.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:036ded36bedb727beeabc16dc1dad7cb154b3fa444e936a03b67a86dc6a5066e", size = 387544, upload-time = "2025-05-21T12:45:51.764Z" }, - { url = "https://files.pythonhosted.org/packages/b0/23/129ed12d25229acc6deb8cbe90baadd8762e563c267c9594eb2fcc15be0c/rpds_py-0.25.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:245550f5a1ac98504147cba96ffec8fabc22b610742e9150138e5d60774686d7", size = 400240, upload-time = "2025-05-21T12:45:54.061Z" }, - { url = "https://files.pythonhosted.org/packages/b5/e0/6811a38a5efa46b7ee6ed2103c95cb9abb16991544c3b69007aa679b6944/rpds_py-0.25.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ff7c23ba0a88cb7b104281a99476cccadf29de2a0ef5ce864959a52675b1ca83", size = 525599, upload-time = "2025-05-21T12:45:56.457Z" }, - { url = "https://files.pythonhosted.org/packages/6c/10/2dc88bcaa0d86bdb59e017a330b1972ffeeb7f5061bb5a180c9a2bb73bbf/rpds_py-0.25.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e37caa8cdb3b7cf24786451a0bdb853f6347b8b92005eeb64225ae1db54d1c2b", size = 411154, upload-time = "2025-05-21T12:45:58.525Z" }, - { url = "https://files.pythonhosted.org/packages/cf/d1/a72d522eb7d934fb33e9c501e6ecae00e2035af924d4ff37d964e9a3959b/rpds_py-0.25.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f2f48ab00181600ee266a095fe815134eb456163f7d6699f525dee471f312cf", size = 388297, upload-time = "2025-05-21T12:46:00.264Z" }, - { url = "https://files.pythonhosted.org/packages/55/90/0dd7169ec74f042405b6b73512200d637a3088c156f64e1c07c18aa2fe59/rpds_py-0.25.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9e5fc7484fa7dce57e25063b0ec9638ff02a908304f861d81ea49273e43838c1", size = 421894, upload-time = "2025-05-21T12:46:02.065Z" }, - { url = "https://files.pythonhosted.org/packages/37/e9/45170894add451783ed839c5c4a495e050aa8baa06d720364d9dff394dac/rpds_py-0.25.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:d3c10228d6cf6fe2b63d2e7985e94f6916fa46940df46b70449e9ff9297bd3d1", size = 564409, upload-time = "2025-05-21T12:46:03.891Z" }, - { url = "https://files.pythonhosted.org/packages/59/d0/31cece9090e76fbdb50c758c165d40da604b03b37c3ba53f010bbfeb130a/rpds_py-0.25.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:5d9e40f32745db28c1ef7aad23f6fc458dc1e29945bd6781060f0d15628b8ddf", size = 592681, upload-time = "2025-05-21T12:46:06.009Z" }, - { url = "https://files.pythonhosted.org/packages/f1/4c/22ef535efb2beec614ba7be83e62b439eb83b0b0d7b1775e22d35af3f9b5/rpds_py-0.25.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:35a8d1a24b5936b35c5003313bc177403d8bdef0f8b24f28b1c4a255f94ea992", size = 558744, upload-time = "2025-05-21T12:46:07.78Z" }, - { url = "https://files.pythonhosted.org/packages/79/ff/f2150efc8daf0581d4dfaf0a2a30b08088b6df900230ee5ae4f7c8cd5163/rpds_py-0.25.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:6099263f526efff9cf3883dfef505518730f7a7a93049b1d90d42e50a22b4793", size = 231305, upload-time = "2025-05-21T12:46:10.52Z" }, + { url = "https://files.pythonhosted.org/packages/b9/31/1459645f036c3dfeacef89e8e5825e430c77dde8489f3b99eaafcd4a60f5/rpds_py-0.26.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:4c70c70f9169692b36307a95f3d8c0a9fcd79f7b4a383aad5eaa0e9718b79b37", size = 372466, upload-time = "2025-07-01T15:53:40.55Z" }, + { url = "https://files.pythonhosted.org/packages/dd/ff/3d0727f35836cc8773d3eeb9a46c40cc405854e36a8d2e951f3a8391c976/rpds_py-0.26.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:777c62479d12395bfb932944e61e915741e364c843afc3196b694db3d669fcd0", size = 357825, upload-time = "2025-07-01T15:53:42.247Z" }, + { url = "https://files.pythonhosted.org/packages/bf/ce/badc5e06120a54099ae287fa96d82cbb650a5f85cf247ffe19c7b157fd1f/rpds_py-0.26.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec671691e72dff75817386aa02d81e708b5a7ec0dec6669ec05213ff6b77e1bd", size = 381530, upload-time = "2025-07-01T15:53:43.585Z" }, + { url = "https://files.pythonhosted.org/packages/1e/a5/fa5d96a66c95d06c62d7a30707b6a4cfec696ab8ae280ee7be14e961e118/rpds_py-0.26.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6a1cb5d6ce81379401bbb7f6dbe3d56de537fb8235979843f0d53bc2e9815a79", size = 396933, upload-time = "2025-07-01T15:53:45.78Z" }, + { url = "https://files.pythonhosted.org/packages/00/a7/7049d66750f18605c591a9db47d4a059e112a0c9ff8de8daf8fa0f446bba/rpds_py-0.26.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4f789e32fa1fb6a7bf890e0124e7b42d1e60d28ebff57fe806719abb75f0e9a3", size = 513973, upload-time = "2025-07-01T15:53:47.085Z" }, + { url = "https://files.pythonhosted.org/packages/0e/f1/528d02c7d6b29d29fac8fd784b354d3571cc2153f33f842599ef0cf20dd2/rpds_py-0.26.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c55b0a669976cf258afd718de3d9ad1b7d1fe0a91cd1ab36f38b03d4d4aeaaf", size = 402293, upload-time = "2025-07-01T15:53:48.117Z" }, + { url = "https://files.pythonhosted.org/packages/15/93/fde36cd6e4685df2cd08508f6c45a841e82f5bb98c8d5ecf05649522acb5/rpds_py-0.26.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c70d9ec912802ecfd6cd390dadb34a9578b04f9bcb8e863d0a7598ba5e9e7ccc", size = 383787, upload-time = "2025-07-01T15:53:50.874Z" }, + { url = "https://files.pythonhosted.org/packages/69/f2/5007553aaba1dcae5d663143683c3dfd03d9395289f495f0aebc93e90f24/rpds_py-0.26.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3021933c2cb7def39d927b9862292e0f4c75a13d7de70eb0ab06efed4c508c19", size = 416312, upload-time = "2025-07-01T15:53:52.046Z" }, + { url = "https://files.pythonhosted.org/packages/8f/a7/ce52c75c1e624a79e48a69e611f1c08844564e44c85db2b6f711d76d10ce/rpds_py-0.26.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8a7898b6ca3b7d6659e55cdac825a2e58c638cbf335cde41f4619e290dd0ad11", size = 558403, upload-time = "2025-07-01T15:53:53.192Z" }, + { url = "https://files.pythonhosted.org/packages/79/d5/e119db99341cc75b538bf4cb80504129fa22ce216672fb2c28e4a101f4d9/rpds_py-0.26.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:12bff2ad9447188377f1b2794772f91fe68bb4bbfa5a39d7941fbebdbf8c500f", size = 588323, upload-time = "2025-07-01T15:53:54.336Z" }, + { url = "https://files.pythonhosted.org/packages/93/94/d28272a0b02f5fe24c78c20e13bbcb95f03dc1451b68e7830ca040c60bd6/rpds_py-0.26.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:191aa858f7d4902e975d4cf2f2d9243816c91e9605070aeb09c0a800d187e323", size = 554541, upload-time = "2025-07-01T15:53:55.469Z" }, + { url = "https://files.pythonhosted.org/packages/93/e0/8c41166602f1b791da892d976057eba30685486d2e2c061ce234679c922b/rpds_py-0.26.0-cp310-cp310-win32.whl", hash = "sha256:b37a04d9f52cb76b6b78f35109b513f6519efb481d8ca4c321f6a3b9580b3f45", size = 220442, upload-time = "2025-07-01T15:53:56.524Z" }, + { url = "https://files.pythonhosted.org/packages/87/f0/509736bb752a7ab50fb0270c2a4134d671a7b3038030837e5536c3de0e0b/rpds_py-0.26.0-cp310-cp310-win_amd64.whl", hash = "sha256:38721d4c9edd3eb6670437d8d5e2070063f305bfa2d5aa4278c51cedcd508a84", size = 231314, upload-time = "2025-07-01T15:53:57.842Z" }, + { url = "https://files.pythonhosted.org/packages/09/4c/4ee8f7e512030ff79fda1df3243c88d70fc874634e2dbe5df13ba4210078/rpds_py-0.26.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:9e8cb77286025bdb21be2941d64ac6ca016130bfdcd228739e8ab137eb4406ed", size = 372610, upload-time = "2025-07-01T15:53:58.844Z" }, + { url = "https://files.pythonhosted.org/packages/fa/9d/3dc16be00f14fc1f03c71b1d67c8df98263ab2710a2fbd65a6193214a527/rpds_py-0.26.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5e09330b21d98adc8ccb2dbb9fc6cb434e8908d4c119aeaa772cb1caab5440a0", size = 358032, upload-time = "2025-07-01T15:53:59.985Z" }, + { url = "https://files.pythonhosted.org/packages/e7/5a/7f1bf8f045da2866324a08ae80af63e64e7bfaf83bd31f865a7b91a58601/rpds_py-0.26.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c9c1b92b774b2e68d11193dc39620d62fd8ab33f0a3c77ecdabe19c179cdbc1", size = 381525, upload-time = "2025-07-01T15:54:01.162Z" }, + { url = "https://files.pythonhosted.org/packages/45/8a/04479398c755a066ace10e3d158866beb600867cacae194c50ffa783abd0/rpds_py-0.26.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:824e6d3503ab990d7090768e4dfd9e840837bae057f212ff9f4f05ec6d1975e7", size = 397089, upload-time = "2025-07-01T15:54:02.319Z" }, + { url = "https://files.pythonhosted.org/packages/72/88/9203f47268db488a1b6d469d69c12201ede776bb728b9d9f29dbfd7df406/rpds_py-0.26.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8ad7fd2258228bf288f2331f0a6148ad0186b2e3643055ed0db30990e59817a6", size = 514255, upload-time = "2025-07-01T15:54:03.38Z" }, + { url = "https://files.pythonhosted.org/packages/f5/b4/01ce5d1e853ddf81fbbd4311ab1eff0b3cf162d559288d10fd127e2588b5/rpds_py-0.26.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0dc23bbb3e06ec1ea72d515fb572c1fea59695aefbffb106501138762e1e915e", size = 402283, upload-time = "2025-07-01T15:54:04.923Z" }, + { url = "https://files.pythonhosted.org/packages/34/a2/004c99936997bfc644d590a9defd9e9c93f8286568f9c16cdaf3e14429a7/rpds_py-0.26.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d80bf832ac7b1920ee29a426cdca335f96a2b5caa839811803e999b41ba9030d", size = 383881, upload-time = "2025-07-01T15:54:06.482Z" }, + { url = "https://files.pythonhosted.org/packages/05/1b/ef5fba4a8f81ce04c427bfd96223f92f05e6cd72291ce9d7523db3b03a6c/rpds_py-0.26.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0919f38f5542c0a87e7b4afcafab6fd2c15386632d249e9a087498571250abe3", size = 415822, upload-time = "2025-07-01T15:54:07.605Z" }, + { url = "https://files.pythonhosted.org/packages/16/80/5c54195aec456b292f7bd8aa61741c8232964063fd8a75fdde9c1e982328/rpds_py-0.26.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d422b945683e409000c888e384546dbab9009bb92f7c0b456e217988cf316107", size = 558347, upload-time = "2025-07-01T15:54:08.591Z" }, + { url = "https://files.pythonhosted.org/packages/f2/1c/1845c1b1fd6d827187c43afe1841d91678d7241cbdb5420a4c6de180a538/rpds_py-0.26.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:77a7711fa562ba2da1aa757e11024ad6d93bad6ad7ede5afb9af144623e5f76a", size = 587956, upload-time = "2025-07-01T15:54:09.963Z" }, + { url = "https://files.pythonhosted.org/packages/2e/ff/9e979329dd131aa73a438c077252ddabd7df6d1a7ad7b9aacf6261f10faa/rpds_py-0.26.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:238e8c8610cb7c29460e37184f6799547f7e09e6a9bdbdab4e8edb90986a2318", size = 554363, upload-time = "2025-07-01T15:54:11.073Z" }, + { url = "https://files.pythonhosted.org/packages/00/8b/d78cfe034b71ffbe72873a136e71acc7a831a03e37771cfe59f33f6de8a2/rpds_py-0.26.0-cp311-cp311-win32.whl", hash = "sha256:893b022bfbdf26d7bedb083efeea624e8550ca6eb98bf7fea30211ce95b9201a", size = 220123, upload-time = "2025-07-01T15:54:12.382Z" }, + { url = "https://files.pythonhosted.org/packages/94/c1/3c8c94c7dd3905dbfde768381ce98778500a80db9924731d87ddcdb117e9/rpds_py-0.26.0-cp311-cp311-win_amd64.whl", hash = "sha256:87a5531de9f71aceb8af041d72fc4cab4943648d91875ed56d2e629bef6d4c03", size = 231732, upload-time = "2025-07-01T15:54:13.434Z" }, + { url = "https://files.pythonhosted.org/packages/67/93/e936fbed1b734eabf36ccb5d93c6a2e9246fbb13c1da011624b7286fae3e/rpds_py-0.26.0-cp311-cp311-win_arm64.whl", hash = "sha256:de2713f48c1ad57f89ac25b3cb7daed2156d8e822cf0eca9b96a6f990718cc41", size = 221917, upload-time = "2025-07-01T15:54:14.559Z" }, + { url = "https://files.pythonhosted.org/packages/ea/86/90eb87c6f87085868bd077c7a9938006eb1ce19ed4d06944a90d3560fce2/rpds_py-0.26.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:894514d47e012e794f1350f076c427d2347ebf82f9b958d554d12819849a369d", size = 363933, upload-time = "2025-07-01T15:54:15.734Z" }, + { url = "https://files.pythonhosted.org/packages/63/78/4469f24d34636242c924626082b9586f064ada0b5dbb1e9d096ee7a8e0c6/rpds_py-0.26.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc921b96fa95a097add244da36a1d9e4f3039160d1d30f1b35837bf108c21136", size = 350447, upload-time = "2025-07-01T15:54:16.922Z" }, + { url = "https://files.pythonhosted.org/packages/ad/91/c448ed45efdfdade82348d5e7995e15612754826ea640afc20915119734f/rpds_py-0.26.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e1157659470aa42a75448b6e943c895be8c70531c43cb78b9ba990778955582", size = 384711, upload-time = "2025-07-01T15:54:18.101Z" }, + { url = "https://files.pythonhosted.org/packages/ec/43/e5c86fef4be7f49828bdd4ecc8931f0287b1152c0bb0163049b3218740e7/rpds_py-0.26.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:521ccf56f45bb3a791182dc6b88ae5f8fa079dd705ee42138c76deb1238e554e", size = 400865, upload-time = "2025-07-01T15:54:19.295Z" }, + { url = "https://files.pythonhosted.org/packages/55/34/e00f726a4d44f22d5c5fe2e5ddd3ac3d7fd3f74a175607781fbdd06fe375/rpds_py-0.26.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9def736773fd56b305c0eef698be5192c77bfa30d55a0e5885f80126c4831a15", size = 517763, upload-time = "2025-07-01T15:54:20.858Z" }, + { url = "https://files.pythonhosted.org/packages/52/1c/52dc20c31b147af724b16104500fba13e60123ea0334beba7b40e33354b4/rpds_py-0.26.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cdad4ea3b4513b475e027be79e5a0ceac8ee1c113a1a11e5edc3c30c29f964d8", size = 406651, upload-time = "2025-07-01T15:54:22.508Z" }, + { url = "https://files.pythonhosted.org/packages/2e/77/87d7bfabfc4e821caa35481a2ff6ae0b73e6a391bb6b343db2c91c2b9844/rpds_py-0.26.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82b165b07f416bdccf5c84546a484cc8f15137ca38325403864bfdf2b5b72f6a", size = 386079, upload-time = "2025-07-01T15:54:23.987Z" }, + { url = "https://files.pythonhosted.org/packages/e3/d4/7f2200c2d3ee145b65b3cddc4310d51f7da6a26634f3ac87125fd789152a/rpds_py-0.26.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d04cab0a54b9dba4d278fe955a1390da3cf71f57feb78ddc7cb67cbe0bd30323", size = 421379, upload-time = "2025-07-01T15:54:25.073Z" }, + { url = "https://files.pythonhosted.org/packages/ae/13/9fdd428b9c820869924ab62236b8688b122baa22d23efdd1c566938a39ba/rpds_py-0.26.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:79061ba1a11b6a12743a2b0f72a46aa2758613d454aa6ba4f5a265cc48850158", size = 562033, upload-time = "2025-07-01T15:54:26.225Z" }, + { url = "https://files.pythonhosted.org/packages/f3/e1/b69686c3bcbe775abac3a4c1c30a164a2076d28df7926041f6c0eb5e8d28/rpds_py-0.26.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:f405c93675d8d4c5ac87364bb38d06c988e11028a64b52a47158a355079661f3", size = 591639, upload-time = "2025-07-01T15:54:27.424Z" }, + { url = "https://files.pythonhosted.org/packages/5c/c9/1e3d8c8863c84a90197ac577bbc3d796a92502124c27092413426f670990/rpds_py-0.26.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dafd4c44b74aa4bed4b250f1aed165b8ef5de743bcca3b88fc9619b6087093d2", size = 557105, upload-time = "2025-07-01T15:54:29.93Z" }, + { url = "https://files.pythonhosted.org/packages/9f/c5/90c569649057622959f6dcc40f7b516539608a414dfd54b8d77e3b201ac0/rpds_py-0.26.0-cp312-cp312-win32.whl", hash = "sha256:3da5852aad63fa0c6f836f3359647870e21ea96cf433eb393ffa45263a170d44", size = 223272, upload-time = "2025-07-01T15:54:31.128Z" }, + { url = "https://files.pythonhosted.org/packages/7d/16/19f5d9f2a556cfed454eebe4d354c38d51c20f3db69e7b4ce6cff904905d/rpds_py-0.26.0-cp312-cp312-win_amd64.whl", hash = "sha256:cf47cfdabc2194a669dcf7a8dbba62e37a04c5041d2125fae0233b720da6f05c", size = 234995, upload-time = "2025-07-01T15:54:32.195Z" }, + { url = "https://files.pythonhosted.org/packages/83/f0/7935e40b529c0e752dfaa7880224771b51175fce08b41ab4a92eb2fbdc7f/rpds_py-0.26.0-cp312-cp312-win_arm64.whl", hash = "sha256:20ab1ae4fa534f73647aad289003f1104092890849e0266271351922ed5574f8", size = 223198, upload-time = "2025-07-01T15:54:33.271Z" }, + { url = "https://files.pythonhosted.org/packages/6a/67/bb62d0109493b12b1c6ab00de7a5566aa84c0e44217c2d94bee1bd370da9/rpds_py-0.26.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:696764a5be111b036256c0b18cd29783fab22154690fc698062fc1b0084b511d", size = 363917, upload-time = "2025-07-01T15:54:34.755Z" }, + { url = "https://files.pythonhosted.org/packages/4b/f3/34e6ae1925a5706c0f002a8d2d7f172373b855768149796af87bd65dcdb9/rpds_py-0.26.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1e6c15d2080a63aaed876e228efe4f814bc7889c63b1e112ad46fdc8b368b9e1", size = 350073, upload-time = "2025-07-01T15:54:36.292Z" }, + { url = "https://files.pythonhosted.org/packages/75/83/1953a9d4f4e4de7fd0533733e041c28135f3c21485faaef56a8aadbd96b5/rpds_py-0.26.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:390e3170babf42462739a93321e657444f0862c6d722a291accc46f9d21ed04e", size = 384214, upload-time = "2025-07-01T15:54:37.469Z" }, + { url = "https://files.pythonhosted.org/packages/48/0e/983ed1b792b3322ea1d065e67f4b230f3b96025f5ce3878cc40af09b7533/rpds_py-0.26.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7da84c2c74c0f5bc97d853d9e17bb83e2dcafcff0dc48286916001cc114379a1", size = 400113, upload-time = "2025-07-01T15:54:38.954Z" }, + { url = "https://files.pythonhosted.org/packages/69/7f/36c0925fff6f660a80be259c5b4f5e53a16851f946eb080351d057698528/rpds_py-0.26.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4c5fe114a6dd480a510b6d3661d09d67d1622c4bf20660a474507aaee7eeeee9", size = 515189, upload-time = "2025-07-01T15:54:40.57Z" }, + { url = "https://files.pythonhosted.org/packages/13/45/cbf07fc03ba7a9b54662c9badb58294ecfb24f828b9732970bd1a431ed5c/rpds_py-0.26.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3100b3090269f3a7ea727b06a6080d4eb7439dca4c0e91a07c5d133bb1727ea7", size = 406998, upload-time = "2025-07-01T15:54:43.025Z" }, + { url = "https://files.pythonhosted.org/packages/6c/b0/8fa5e36e58657997873fd6a1cf621285ca822ca75b4b3434ead047daa307/rpds_py-0.26.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c03c9b0c64afd0320ae57de4c982801271c0c211aa2d37f3003ff5feb75bb04", size = 385903, upload-time = "2025-07-01T15:54:44.752Z" }, + { url = "https://files.pythonhosted.org/packages/4b/f7/b25437772f9f57d7a9fbd73ed86d0dcd76b4c7c6998348c070d90f23e315/rpds_py-0.26.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5963b72ccd199ade6ee493723d18a3f21ba7d5b957017607f815788cef50eaf1", size = 419785, upload-time = "2025-07-01T15:54:46.043Z" }, + { url = "https://files.pythonhosted.org/packages/a7/6b/63ffa55743dfcb4baf2e9e77a0b11f7f97ed96a54558fcb5717a4b2cd732/rpds_py-0.26.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9da4e873860ad5bab3291438525cae80169daecbfafe5657f7f5fb4d6b3f96b9", size = 561329, upload-time = "2025-07-01T15:54:47.64Z" }, + { url = "https://files.pythonhosted.org/packages/2f/07/1f4f5e2886c480a2346b1e6759c00278b8a69e697ae952d82ae2e6ee5db0/rpds_py-0.26.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5afaddaa8e8c7f1f7b4c5c725c0070b6eed0228f705b90a1732a48e84350f4e9", size = 590875, upload-time = "2025-07-01T15:54:48.9Z" }, + { url = "https://files.pythonhosted.org/packages/cc/bc/e6639f1b91c3a55f8c41b47d73e6307051b6e246254a827ede730624c0f8/rpds_py-0.26.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4916dc96489616a6f9667e7526af8fa693c0fdb4f3acb0e5d9f4400eb06a47ba", size = 556636, upload-time = "2025-07-01T15:54:50.619Z" }, + { url = "https://files.pythonhosted.org/packages/05/4c/b3917c45566f9f9a209d38d9b54a1833f2bb1032a3e04c66f75726f28876/rpds_py-0.26.0-cp313-cp313-win32.whl", hash = "sha256:2a343f91b17097c546b93f7999976fd6c9d5900617aa848c81d794e062ab302b", size = 222663, upload-time = "2025-07-01T15:54:52.023Z" }, + { url = "https://files.pythonhosted.org/packages/e0/0b/0851bdd6025775aaa2365bb8de0697ee2558184c800bfef8d7aef5ccde58/rpds_py-0.26.0-cp313-cp313-win_amd64.whl", hash = "sha256:0a0b60701f2300c81b2ac88a5fb893ccfa408e1c4a555a77f908a2596eb875a5", size = 234428, upload-time = "2025-07-01T15:54:53.692Z" }, + { url = "https://files.pythonhosted.org/packages/ed/e8/a47c64ed53149c75fb581e14a237b7b7cd18217e969c30d474d335105622/rpds_py-0.26.0-cp313-cp313-win_arm64.whl", hash = "sha256:257d011919f133a4746958257f2c75238e3ff54255acd5e3e11f3ff41fd14256", size = 222571, upload-time = "2025-07-01T15:54:54.822Z" }, + { url = "https://files.pythonhosted.org/packages/89/bf/3d970ba2e2bcd17d2912cb42874107390f72873e38e79267224110de5e61/rpds_py-0.26.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:529c8156d7506fba5740e05da8795688f87119cce330c244519cf706a4a3d618", size = 360475, upload-time = "2025-07-01T15:54:56.228Z" }, + { url = "https://files.pythonhosted.org/packages/82/9f/283e7e2979fc4ec2d8ecee506d5a3675fce5ed9b4b7cb387ea5d37c2f18d/rpds_py-0.26.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f53ec51f9d24e9638a40cabb95078ade8c99251945dad8d57bf4aabe86ecee35", size = 346692, upload-time = "2025-07-01T15:54:58.561Z" }, + { url = "https://files.pythonhosted.org/packages/e3/03/7e50423c04d78daf391da3cc4330bdb97042fc192a58b186f2d5deb7befd/rpds_py-0.26.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab504c4d654e4a29558eaa5bb8cea5fdc1703ea60a8099ffd9c758472cf913f", size = 379415, upload-time = "2025-07-01T15:54:59.751Z" }, + { url = "https://files.pythonhosted.org/packages/57/00/d11ee60d4d3b16808432417951c63df803afb0e0fc672b5e8d07e9edaaae/rpds_py-0.26.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fd0641abca296bc1a00183fe44f7fced8807ed49d501f188faa642d0e4975b83", size = 391783, upload-time = "2025-07-01T15:55:00.898Z" }, + { url = "https://files.pythonhosted.org/packages/08/b3/1069c394d9c0d6d23c5b522e1f6546b65793a22950f6e0210adcc6f97c3e/rpds_py-0.26.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:69b312fecc1d017b5327afa81d4da1480f51c68810963a7336d92203dbb3d4f1", size = 512844, upload-time = "2025-07-01T15:55:02.201Z" }, + { url = "https://files.pythonhosted.org/packages/08/3b/c4fbf0926800ed70b2c245ceca99c49f066456755f5d6eb8863c2c51e6d0/rpds_py-0.26.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c741107203954f6fc34d3066d213d0a0c40f7bb5aafd698fb39888af277c70d8", size = 402105, upload-time = "2025-07-01T15:55:03.698Z" }, + { url = "https://files.pythonhosted.org/packages/1c/b0/db69b52ca07413e568dae9dc674627a22297abb144c4d6022c6d78f1e5cc/rpds_py-0.26.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc3e55a7db08dc9a6ed5fb7103019d2c1a38a349ac41901f9f66d7f95750942f", size = 383440, upload-time = "2025-07-01T15:55:05.398Z" }, + { url = "https://files.pythonhosted.org/packages/4c/e1/c65255ad5b63903e56b3bb3ff9dcc3f4f5c3badde5d08c741ee03903e951/rpds_py-0.26.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9e851920caab2dbcae311fd28f4313c6953993893eb5c1bb367ec69d9a39e7ed", size = 412759, upload-time = "2025-07-01T15:55:08.316Z" }, + { url = "https://files.pythonhosted.org/packages/e4/22/bb731077872377a93c6e93b8a9487d0406c70208985831034ccdeed39c8e/rpds_py-0.26.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:dfbf280da5f876d0b00c81f26bedce274e72a678c28845453885a9b3c22ae632", size = 556032, upload-time = "2025-07-01T15:55:09.52Z" }, + { url = "https://files.pythonhosted.org/packages/e0/8b/393322ce7bac5c4530fb96fc79cc9ea2f83e968ff5f6e873f905c493e1c4/rpds_py-0.26.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:1cc81d14ddfa53d7f3906694d35d54d9d3f850ef8e4e99ee68bc0d1e5fed9a9c", size = 585416, upload-time = "2025-07-01T15:55:11.216Z" }, + { url = "https://files.pythonhosted.org/packages/49/ae/769dc372211835bf759319a7aae70525c6eb523e3371842c65b7ef41c9c6/rpds_py-0.26.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dca83c498b4650a91efcf7b88d669b170256bf8017a5db6f3e06c2bf031f57e0", size = 554049, upload-time = "2025-07-01T15:55:13.004Z" }, + { url = "https://files.pythonhosted.org/packages/6b/f9/4c43f9cc203d6ba44ce3146246cdc38619d92c7bd7bad4946a3491bd5b70/rpds_py-0.26.0-cp313-cp313t-win32.whl", hash = "sha256:4d11382bcaf12f80b51d790dee295c56a159633a8e81e6323b16e55d81ae37e9", size = 218428, upload-time = "2025-07-01T15:55:14.486Z" }, + { url = "https://files.pythonhosted.org/packages/7e/8b/9286b7e822036a4a977f2f1e851c7345c20528dbd56b687bb67ed68a8ede/rpds_py-0.26.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ff110acded3c22c033e637dd8896e411c7d3a11289b2edf041f86663dbc791e9", size = 231524, upload-time = "2025-07-01T15:55:15.745Z" }, + { url = "https://files.pythonhosted.org/packages/55/07/029b7c45db910c74e182de626dfdae0ad489a949d84a468465cd0ca36355/rpds_py-0.26.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:da619979df60a940cd434084355c514c25cf8eb4cf9a508510682f6c851a4f7a", size = 364292, upload-time = "2025-07-01T15:55:17.001Z" }, + { url = "https://files.pythonhosted.org/packages/13/d1/9b3d3f986216b4d1f584878dca15ce4797aaf5d372d738974ba737bf68d6/rpds_py-0.26.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ea89a2458a1a75f87caabefe789c87539ea4e43b40f18cff526052e35bbb4fdf", size = 350334, upload-time = "2025-07-01T15:55:18.922Z" }, + { url = "https://files.pythonhosted.org/packages/18/98/16d5e7bc9ec715fa9668731d0cf97f6b032724e61696e2db3d47aeb89214/rpds_py-0.26.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feac1045b3327a45944e7dcbeb57530339f6b17baff154df51ef8b0da34c8c12", size = 384875, upload-time = "2025-07-01T15:55:20.399Z" }, + { url = "https://files.pythonhosted.org/packages/f9/13/aa5e2b1ec5ab0e86a5c464d53514c0467bec6ba2507027d35fc81818358e/rpds_py-0.26.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b818a592bd69bfe437ee8368603d4a2d928c34cffcdf77c2e761a759ffd17d20", size = 399993, upload-time = "2025-07-01T15:55:21.729Z" }, + { url = "https://files.pythonhosted.org/packages/17/03/8021810b0e97923abdbab6474c8b77c69bcb4b2c58330777df9ff69dc559/rpds_py-0.26.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a8b0dd8648709b62d9372fc00a57466f5fdeefed666afe3fea5a6c9539a0331", size = 516683, upload-time = "2025-07-01T15:55:22.918Z" }, + { url = "https://files.pythonhosted.org/packages/dc/b1/da8e61c87c2f3d836954239fdbbfb477bb7b54d74974d8f6fcb34342d166/rpds_py-0.26.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6d3498ad0df07d81112aa6ec6c95a7e7b1ae00929fb73e7ebee0f3faaeabad2f", size = 408825, upload-time = "2025-07-01T15:55:24.207Z" }, + { url = "https://files.pythonhosted.org/packages/38/bc/1fc173edaaa0e52c94b02a655db20697cb5fa954ad5a8e15a2c784c5cbdd/rpds_py-0.26.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24a4146ccb15be237fdef10f331c568e1b0e505f8c8c9ed5d67759dac58ac246", size = 387292, upload-time = "2025-07-01T15:55:25.554Z" }, + { url = "https://files.pythonhosted.org/packages/7c/eb/3a9bb4bd90867d21916f253caf4f0d0be7098671b6715ad1cead9fe7bab9/rpds_py-0.26.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a9a63785467b2d73635957d32a4f6e73d5e4df497a16a6392fa066b753e87387", size = 420435, upload-time = "2025-07-01T15:55:27.798Z" }, + { url = "https://files.pythonhosted.org/packages/cd/16/e066dcdb56f5632713445271a3f8d3d0b426d51ae9c0cca387799df58b02/rpds_py-0.26.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:de4ed93a8c91debfd5a047be327b7cc8b0cc6afe32a716bbbc4aedca9e2a83af", size = 562410, upload-time = "2025-07-01T15:55:29.057Z" }, + { url = "https://files.pythonhosted.org/packages/60/22/ddbdec7eb82a0dc2e455be44c97c71c232983e21349836ce9f272e8a3c29/rpds_py-0.26.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:caf51943715b12af827696ec395bfa68f090a4c1a1d2509eb4e2cb69abbbdb33", size = 590724, upload-time = "2025-07-01T15:55:30.719Z" }, + { url = "https://files.pythonhosted.org/packages/2c/b4/95744085e65b7187d83f2fcb0bef70716a1ea0a9e5d8f7f39a86e5d83424/rpds_py-0.26.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4a59e5bc386de021f56337f757301b337d7ab58baa40174fb150accd480bc953", size = 558285, upload-time = "2025-07-01T15:55:31.981Z" }, + { url = "https://files.pythonhosted.org/packages/37/37/6309a75e464d1da2559446f9c811aa4d16343cebe3dbb73701e63f760caa/rpds_py-0.26.0-cp314-cp314-win32.whl", hash = "sha256:92c8db839367ef16a662478f0a2fe13e15f2227da3c1430a782ad0f6ee009ec9", size = 223459, upload-time = "2025-07-01T15:55:33.312Z" }, + { url = "https://files.pythonhosted.org/packages/d9/6f/8e9c11214c46098b1d1391b7e02b70bb689ab963db3b19540cba17315291/rpds_py-0.26.0-cp314-cp314-win_amd64.whl", hash = "sha256:b0afb8cdd034150d4d9f53926226ed27ad15b7f465e93d7468caaf5eafae0d37", size = 236083, upload-time = "2025-07-01T15:55:34.933Z" }, + { url = "https://files.pythonhosted.org/packages/47/af/9c4638994dd623d51c39892edd9d08e8be8220a4b7e874fa02c2d6e91955/rpds_py-0.26.0-cp314-cp314-win_arm64.whl", hash = "sha256:ca3f059f4ba485d90c8dc75cb5ca897e15325e4e609812ce57f896607c1c0867", size = 223291, upload-time = "2025-07-01T15:55:36.202Z" }, + { url = "https://files.pythonhosted.org/packages/4d/db/669a241144460474aab03e254326b32c42def83eb23458a10d163cb9b5ce/rpds_py-0.26.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:5afea17ab3a126006dc2f293b14ffc7ef3c85336cf451564a0515ed7648033da", size = 361445, upload-time = "2025-07-01T15:55:37.483Z" }, + { url = "https://files.pythonhosted.org/packages/3b/2d/133f61cc5807c6c2fd086a46df0eb8f63a23f5df8306ff9f6d0fd168fecc/rpds_py-0.26.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:69f0c0a3df7fd3a7eec50a00396104bb9a843ea6d45fcc31c2d5243446ffd7a7", size = 347206, upload-time = "2025-07-01T15:55:38.828Z" }, + { url = "https://files.pythonhosted.org/packages/05/bf/0e8fb4c05f70273469eecf82f6ccf37248558526a45321644826555db31b/rpds_py-0.26.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:801a71f70f9813e82d2513c9a96532551fce1e278ec0c64610992c49c04c2dad", size = 380330, upload-time = "2025-07-01T15:55:40.175Z" }, + { url = "https://files.pythonhosted.org/packages/d4/a8/060d24185d8b24d3923322f8d0ede16df4ade226a74e747b8c7c978e3dd3/rpds_py-0.26.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:df52098cde6d5e02fa75c1f6244f07971773adb4a26625edd5c18fee906fa84d", size = 392254, upload-time = "2025-07-01T15:55:42.015Z" }, + { url = "https://files.pythonhosted.org/packages/b9/7b/7c2e8a9ee3e6bc0bae26bf29f5219955ca2fbb761dca996a83f5d2f773fe/rpds_py-0.26.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bc596b30f86dc6f0929499c9e574601679d0341a0108c25b9b358a042f51bca", size = 516094, upload-time = "2025-07-01T15:55:43.603Z" }, + { url = "https://files.pythonhosted.org/packages/75/d6/f61cafbed8ba1499b9af9f1777a2a199cd888f74a96133d8833ce5eaa9c5/rpds_py-0.26.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9dfbe56b299cf5875b68eb6f0ebaadc9cac520a1989cac0db0765abfb3709c19", size = 402889, upload-time = "2025-07-01T15:55:45.275Z" }, + { url = "https://files.pythonhosted.org/packages/92/19/c8ac0a8a8df2dd30cdec27f69298a5c13e9029500d6d76718130f5e5be10/rpds_py-0.26.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac64f4b2bdb4ea622175c9ab7cf09444e412e22c0e02e906978b3b488af5fde8", size = 384301, upload-time = "2025-07-01T15:55:47.098Z" }, + { url = "https://files.pythonhosted.org/packages/41/e1/6b1859898bc292a9ce5776016c7312b672da00e25cec74d7beced1027286/rpds_py-0.26.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:181ef9b6bbf9845a264f9aa45c31836e9f3c1f13be565d0d010e964c661d1e2b", size = 412891, upload-time = "2025-07-01T15:55:48.412Z" }, + { url = "https://files.pythonhosted.org/packages/ef/b9/ceb39af29913c07966a61367b3c08b4f71fad841e32c6b59a129d5974698/rpds_py-0.26.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:49028aa684c144ea502a8e847d23aed5e4c2ef7cadfa7d5eaafcb40864844b7a", size = 557044, upload-time = "2025-07-01T15:55:49.816Z" }, + { url = "https://files.pythonhosted.org/packages/2f/27/35637b98380731a521f8ec4f3fd94e477964f04f6b2f8f7af8a2d889a4af/rpds_py-0.26.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:e5d524d68a474a9688336045bbf76cb0def88549c1b2ad9dbfec1fb7cfbe9170", size = 585774, upload-time = "2025-07-01T15:55:51.192Z" }, + { url = "https://files.pythonhosted.org/packages/52/d9/3f0f105420fecd18551b678c9a6ce60bd23986098b252a56d35781b3e7e9/rpds_py-0.26.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c1851f429b822831bd2edcbe0cfd12ee9ea77868f8d3daf267b189371671c80e", size = 554886, upload-time = "2025-07-01T15:55:52.541Z" }, + { url = "https://files.pythonhosted.org/packages/6b/c5/347c056a90dc8dd9bc240a08c527315008e1b5042e7a4cf4ac027be9d38a/rpds_py-0.26.0-cp314-cp314t-win32.whl", hash = "sha256:7bdb17009696214c3b66bb3590c6d62e14ac5935e53e929bcdbc5a495987a84f", size = 219027, upload-time = "2025-07-01T15:55:53.874Z" }, + { url = "https://files.pythonhosted.org/packages/75/04/5302cea1aa26d886d34cadbf2dc77d90d7737e576c0065f357b96dc7a1a6/rpds_py-0.26.0-cp314-cp314t-win_amd64.whl", hash = "sha256:f14440b9573a6f76b4ee4770c13f0b5921f71dde3b6fcb8dabbefd13b7fe05d7", size = 232821, upload-time = "2025-07-01T15:55:55.167Z" }, + { url = "https://files.pythonhosted.org/packages/fb/74/846ab687119c9d31fc21ab1346ef9233c31035ce53c0e2d43a130a0c5a5e/rpds_py-0.26.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:7a48af25d9b3c15684059d0d1fc0bc30e8eee5ca521030e2bffddcab5be40226", size = 372786, upload-time = "2025-07-01T15:55:56.512Z" }, + { url = "https://files.pythonhosted.org/packages/33/02/1f9e465cb1a6032d02b17cd117c7bd9fb6156bc5b40ffeb8053d8a2aa89c/rpds_py-0.26.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0c71c2f6bf36e61ee5c47b2b9b5d47e4d1baad6426bfed9eea3e858fc6ee8806", size = 358062, upload-time = "2025-07-01T15:55:58.084Z" }, + { url = "https://files.pythonhosted.org/packages/2a/49/81a38e3c67ac943907a9711882da3d87758c82cf26b2120b8128e45d80df/rpds_py-0.26.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d815d48b1804ed7867b539236b6dd62997850ca1c91cad187f2ddb1b7bbef19", size = 381576, upload-time = "2025-07-01T15:55:59.422Z" }, + { url = "https://files.pythonhosted.org/packages/14/37/418f030a76ef59f41e55f9dc916af8afafa3c9e3be38df744b2014851474/rpds_py-0.26.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:84cfbd4d4d2cdeb2be61a057a258d26b22877266dd905809e94172dff01a42ae", size = 397062, upload-time = "2025-07-01T15:56:00.868Z" }, + { url = "https://files.pythonhosted.org/packages/47/e3/9090817a8f4388bfe58e28136e9682fa7872a06daff2b8a2f8c78786a6e1/rpds_py-0.26.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fbaa70553ca116c77717f513e08815aec458e6b69a028d4028d403b3bc84ff37", size = 516277, upload-time = "2025-07-01T15:56:02.672Z" }, + { url = "https://files.pythonhosted.org/packages/3f/3a/1ec3dd93250fb8023f27d49b3f92e13f679141f2e59a61563f88922c2821/rpds_py-0.26.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39bfea47c375f379d8e87ab4bb9eb2c836e4f2069f0f65731d85e55d74666387", size = 402604, upload-time = "2025-07-01T15:56:04.453Z" }, + { url = "https://files.pythonhosted.org/packages/f2/98/9133c06e42ec3ce637936263c50ac647f879b40a35cfad2f5d4ad418a439/rpds_py-0.26.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1533b7eb683fb5f38c1d68a3c78f5fdd8f1412fa6b9bf03b40f450785a0ab915", size = 383664, upload-time = "2025-07-01T15:56:05.823Z" }, + { url = "https://files.pythonhosted.org/packages/a9/10/a59ce64099cc77c81adb51f06909ac0159c19a3e2c9d9613bab171f4730f/rpds_py-0.26.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c5ab0ee51f560d179b057555b4f601b7df909ed31312d301b99f8b9fc6028284", size = 415944, upload-time = "2025-07-01T15:56:07.132Z" }, + { url = "https://files.pythonhosted.org/packages/c3/f1/ae0c60b3be9df9d5bef3527d83b8eb4b939e3619f6dd8382840e220a27df/rpds_py-0.26.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e5162afc9e0d1f9cae3b577d9c29ddbab3505ab39012cb794d94a005825bde21", size = 558311, upload-time = "2025-07-01T15:56:08.484Z" }, + { url = "https://files.pythonhosted.org/packages/fb/2b/bf1498ebb3ddc5eff2fe3439da88963d1fc6e73d1277fa7ca0c72620d167/rpds_py-0.26.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:43f10b007033f359bc3fa9cd5e6c1e76723f056ffa9a6b5c117cc35720a80292", size = 587928, upload-time = "2025-07-01T15:56:09.946Z" }, + { url = "https://files.pythonhosted.org/packages/b6/eb/e6b949edf7af5629848c06d6e544a36c9f2781e2d8d03b906de61ada04d0/rpds_py-0.26.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e3730a48e5622e598293eee0762b09cff34dd3f271530f47b0894891281f051d", size = 554554, upload-time = "2025-07-01T15:56:11.775Z" }, + { url = "https://files.pythonhosted.org/packages/0a/1c/aa0298372ea898620d4706ad26b5b9e975550a4dd30bd042b0fe9ae72cce/rpds_py-0.26.0-cp39-cp39-win32.whl", hash = "sha256:4b1f66eb81eab2e0ff5775a3a312e5e2e16bf758f7b06be82fb0d04078c7ac51", size = 220273, upload-time = "2025-07-01T15:56:13.273Z" }, + { url = "https://files.pythonhosted.org/packages/b8/b0/8b3bef6ad0b35c172d1c87e2e5c2bb027d99e2a7bc7a16f744e66cf318f3/rpds_py-0.26.0-cp39-cp39-win_amd64.whl", hash = "sha256:519067e29f67b5c90e64fb1a6b6e9d2ec0ba28705c51956637bac23a2f4ddae1", size = 231627, upload-time = "2025-07-01T15:56:14.853Z" }, + { url = "https://files.pythonhosted.org/packages/ef/9a/1f033b0b31253d03d785b0cd905bc127e555ab496ea6b4c7c2e1f951f2fd/rpds_py-0.26.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3c0909c5234543ada2515c05dc08595b08d621ba919629e94427e8e03539c958", size = 373226, upload-time = "2025-07-01T15:56:16.578Z" }, + { url = "https://files.pythonhosted.org/packages/58/29/5f88023fd6aaaa8ca3c4a6357ebb23f6f07da6079093ccf27c99efce87db/rpds_py-0.26.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:c1fb0cda2abcc0ac62f64e2ea4b4e64c57dfd6b885e693095460c61bde7bb18e", size = 359230, upload-time = "2025-07-01T15:56:17.978Z" }, + { url = "https://files.pythonhosted.org/packages/6c/6c/13eaebd28b439da6964dde22712b52e53fe2824af0223b8e403249d10405/rpds_py-0.26.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84d142d2d6cf9b31c12aa4878d82ed3b2324226270b89b676ac62ccd7df52d08", size = 382363, upload-time = "2025-07-01T15:56:19.977Z" }, + { url = "https://files.pythonhosted.org/packages/55/fc/3bb9c486b06da19448646f96147796de23c5811ef77cbfc26f17307b6a9d/rpds_py-0.26.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a547e21c5610b7e9093d870be50682a6a6cf180d6da0f42c47c306073bfdbbf6", size = 397146, upload-time = "2025-07-01T15:56:21.39Z" }, + { url = "https://files.pythonhosted.org/packages/15/18/9d1b79eb4d18e64ba8bba9e7dec6f9d6920b639f22f07ee9368ca35d4673/rpds_py-0.26.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:35e9a70a0f335371275cdcd08bc5b8051ac494dd58bff3bbfb421038220dc871", size = 514804, upload-time = "2025-07-01T15:56:22.78Z" }, + { url = "https://files.pythonhosted.org/packages/4f/5a/175ad7191bdbcd28785204621b225ad70e85cdfd1e09cc414cb554633b21/rpds_py-0.26.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0dfa6115c6def37905344d56fb54c03afc49104e2ca473d5dedec0f6606913b4", size = 402820, upload-time = "2025-07-01T15:56:24.584Z" }, + { url = "https://files.pythonhosted.org/packages/11/45/6a67ecf6d61c4d4aff4bc056e864eec4b2447787e11d1c2c9a0242c6e92a/rpds_py-0.26.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:313cfcd6af1a55a286a3c9a25f64af6d0e46cf60bc5798f1db152d97a216ff6f", size = 384567, upload-time = "2025-07-01T15:56:26.064Z" }, + { url = "https://files.pythonhosted.org/packages/a1/ba/16589da828732b46454c61858950a78fe4c931ea4bf95f17432ffe64b241/rpds_py-0.26.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f7bf2496fa563c046d05e4d232d7b7fd61346e2402052064b773e5c378bf6f73", size = 416520, upload-time = "2025-07-01T15:56:27.608Z" }, + { url = "https://files.pythonhosted.org/packages/81/4b/00092999fc7c0c266045e984d56b7314734cc400a6c6dc4d61a35f135a9d/rpds_py-0.26.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:aa81873e2c8c5aa616ab8e017a481a96742fdf9313c40f14338ca7dbf50cb55f", size = 559362, upload-time = "2025-07-01T15:56:29.078Z" }, + { url = "https://files.pythonhosted.org/packages/96/0c/43737053cde1f93ac4945157f7be1428724ab943e2132a0d235a7e161d4e/rpds_py-0.26.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:68ffcf982715f5b5b7686bdd349ff75d422e8f22551000c24b30eaa1b7f7ae84", size = 588113, upload-time = "2025-07-01T15:56:30.485Z" }, + { url = "https://files.pythonhosted.org/packages/46/46/8e38f6161466e60a997ed7e9951ae5de131dedc3cf778ad35994b4af823d/rpds_py-0.26.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:6188de70e190847bb6db3dc3981cbadff87d27d6fe9b4f0e18726d55795cee9b", size = 555429, upload-time = "2025-07-01T15:56:31.956Z" }, + { url = "https://files.pythonhosted.org/packages/2c/ac/65da605e9f1dd643ebe615d5bbd11b6efa1d69644fc4bf623ea5ae385a82/rpds_py-0.26.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:1c962145c7473723df9722ba4c058de12eb5ebedcb4e27e7d902920aa3831ee8", size = 231950, upload-time = "2025-07-01T15:56:33.337Z" }, + { url = "https://files.pythonhosted.org/packages/51/f2/b5c85b758a00c513bb0389f8fc8e61eb5423050c91c958cdd21843faa3e6/rpds_py-0.26.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f61a9326f80ca59214d1cceb0a09bb2ece5b2563d4e0cd37bfd5515c28510674", size = 373505, upload-time = "2025-07-01T15:56:34.716Z" }, + { url = "https://files.pythonhosted.org/packages/23/e0/25db45e391251118e915e541995bb5f5ac5691a3b98fb233020ba53afc9b/rpds_py-0.26.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:183f857a53bcf4b1b42ef0f57ca553ab56bdd170e49d8091e96c51c3d69ca696", size = 359468, upload-time = "2025-07-01T15:56:36.219Z" }, + { url = "https://files.pythonhosted.org/packages/0b/73/dd5ee6075bb6491be3a646b301dfd814f9486d924137a5098e61f0487e16/rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:941c1cfdf4799d623cf3aa1d326a6b4fdb7a5799ee2687f3516738216d2262fb", size = 382680, upload-time = "2025-07-01T15:56:37.644Z" }, + { url = "https://files.pythonhosted.org/packages/2f/10/84b522ff58763a5c443f5bcedc1820240e454ce4e620e88520f04589e2ea/rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72a8d9564a717ee291f554eeb4bfeafe2309d5ec0aa6c475170bdab0f9ee8e88", size = 397035, upload-time = "2025-07-01T15:56:39.241Z" }, + { url = "https://files.pythonhosted.org/packages/06/ea/8667604229a10a520fcbf78b30ccc278977dcc0627beb7ea2c96b3becef0/rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:511d15193cbe013619dd05414c35a7dedf2088fcee93c6bbb7c77859765bd4e8", size = 514922, upload-time = "2025-07-01T15:56:40.645Z" }, + { url = "https://files.pythonhosted.org/packages/24/e6/9ed5b625c0661c4882fc8cdf302bf8e96c73c40de99c31e0b95ed37d508c/rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aea1f9741b603a8d8fedb0ed5502c2bc0accbc51f43e2ad1337fe7259c2b77a5", size = 402822, upload-time = "2025-07-01T15:56:42.137Z" }, + { url = "https://files.pythonhosted.org/packages/8a/58/212c7b6fd51946047fb45d3733da27e2fa8f7384a13457c874186af691b1/rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4019a9d473c708cf2f16415688ef0b4639e07abaa569d72f74745bbeffafa2c7", size = 384336, upload-time = "2025-07-01T15:56:44.239Z" }, + { url = "https://files.pythonhosted.org/packages/aa/f5/a40ba78748ae8ebf4934d4b88e77b98497378bc2c24ba55ebe87a4e87057/rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:093d63b4b0f52d98ebae33b8c50900d3d67e0666094b1be7a12fffd7f65de74b", size = 416871, upload-time = "2025-07-01T15:56:46.284Z" }, + { url = "https://files.pythonhosted.org/packages/d5/a6/33b1fc0c9f7dcfcfc4a4353daa6308b3ece22496ceece348b3e7a7559a09/rpds_py-0.26.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:2abe21d8ba64cded53a2a677e149ceb76dcf44284202d737178afe7ba540c1eb", size = 559439, upload-time = "2025-07-01T15:56:48.549Z" }, + { url = "https://files.pythonhosted.org/packages/71/2d/ceb3f9c12f8cfa56d34995097f6cd99da1325642c60d1b6680dd9df03ed8/rpds_py-0.26.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:4feb7511c29f8442cbbc28149a92093d32e815a28aa2c50d333826ad2a20fdf0", size = 588380, upload-time = "2025-07-01T15:56:50.086Z" }, + { url = "https://files.pythonhosted.org/packages/c8/ed/9de62c2150ca8e2e5858acf3f4f4d0d180a38feef9fdab4078bea63d8dba/rpds_py-0.26.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:e99685fc95d386da368013e7fb4269dd39c30d99f812a8372d62f244f662709c", size = 555334, upload-time = "2025-07-01T15:56:51.703Z" }, + { url = "https://files.pythonhosted.org/packages/7e/78/a08e2f28e91c7e45db1150813c6d760a0fb114d5652b1373897073369e0d/rpds_py-0.26.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a90a13408a7a856b87be8a9f008fff53c5080eea4e4180f6c2e546e4a972fb5d", size = 373157, upload-time = "2025-07-01T15:56:53.291Z" }, + { url = "https://files.pythonhosted.org/packages/52/01/ddf51517497c8224fb0287e9842b820ed93748bc28ea74cab56a71e3dba4/rpds_py-0.26.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:3ac51b65e8dc76cf4949419c54c5528adb24fc721df722fd452e5fbc236f5c40", size = 358827, upload-time = "2025-07-01T15:56:54.963Z" }, + { url = "https://files.pythonhosted.org/packages/4d/f4/acaefa44b83705a4fcadd68054280127c07cdb236a44a1c08b7c5adad40b/rpds_py-0.26.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59b2093224a18c6508d95cfdeba8db9cbfd6f3494e94793b58972933fcee4c6d", size = 382182, upload-time = "2025-07-01T15:56:56.474Z" }, + { url = "https://files.pythonhosted.org/packages/e9/a2/d72ac03d37d33f6ff4713ca4c704da0c3b1b3a959f0bf5eb738c0ad94ea2/rpds_py-0.26.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4f01a5d6444a3258b00dc07b6ea4733e26f8072b788bef750baa37b370266137", size = 397123, upload-time = "2025-07-01T15:56:58.272Z" }, + { url = "https://files.pythonhosted.org/packages/74/58/c053e9d1da1d3724434dd7a5f506623913e6404d396ff3cf636a910c0789/rpds_py-0.26.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b6e2c12160c72aeda9d1283e612f68804621f448145a210f1bf1d79151c47090", size = 516285, upload-time = "2025-07-01T15:57:00.283Z" }, + { url = "https://files.pythonhosted.org/packages/94/41/c81e97ee88b38b6d1847c75f2274dee8d67cb8d5ed7ca8c6b80442dead75/rpds_py-0.26.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cb28c1f569f8d33b2b5dcd05d0e6ef7005d8639c54c2f0be824f05aedf715255", size = 402182, upload-time = "2025-07-01T15:57:02.587Z" }, + { url = "https://files.pythonhosted.org/packages/74/74/38a176b34ce5197b4223e295f36350dd90713db13cf3c3b533e8e8f7484e/rpds_py-0.26.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1766b5724c3f779317d5321664a343c07773c8c5fd1532e4039e6cc7d1a815be", size = 384436, upload-time = "2025-07-01T15:57:04.125Z" }, + { url = "https://files.pythonhosted.org/packages/e4/21/f40b9a5709d7078372c87fd11335469dc4405245528b60007cd4078ed57a/rpds_py-0.26.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b6d9e5a2ed9c4988c8f9b28b3bc0e3e5b1aaa10c28d210a594ff3a8c02742daf", size = 417039, upload-time = "2025-07-01T15:57:05.608Z" }, + { url = "https://files.pythonhosted.org/packages/02/ee/ed835925731c7e87306faa80a3a5e17b4d0f532083155e7e00fe1cd4e242/rpds_py-0.26.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:b5f7a446ddaf6ca0fad9a5535b56fbfc29998bf0e0b450d174bbec0d600e1d72", size = 559111, upload-time = "2025-07-01T15:57:07.371Z" }, + { url = "https://files.pythonhosted.org/packages/ce/88/d6e9e686b8ffb6139b82eb1c319ef32ae99aeb21f7e4bf45bba44a760d09/rpds_py-0.26.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:eed5ac260dd545fbc20da5f4f15e7efe36a55e0e7cf706e4ec005b491a9546a0", size = 588609, upload-time = "2025-07-01T15:57:09.319Z" }, + { url = "https://files.pythonhosted.org/packages/e5/96/09bcab08fa12a69672716b7f86c672ee7f79c5319f1890c5a79dcb8e0df2/rpds_py-0.26.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:582462833ba7cee52e968b0341b85e392ae53d44c0f9af6a5927c80e539a8b67", size = 555212, upload-time = "2025-07-01T15:57:10.905Z" }, + { url = "https://files.pythonhosted.org/packages/2c/07/c554b6ed0064b6e0350a622714298e930b3cf5a3d445a2e25c412268abcf/rpds_py-0.26.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:69a607203441e07e9a8a529cff1d5b73f6a160f22db1097211e6212a68567d11", size = 232048, upload-time = "2025-07-01T15:57:12.473Z" }, ] [[package]] name = "ruff" -version = "0.11.12" +version = "0.12.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/15/0a/92416b159ec00cdf11e5882a9d80d29bf84bba3dbebc51c4898bfbca1da6/ruff-0.11.12.tar.gz", hash = "sha256:43cf7f69c7d7c7d7513b9d59c5d8cafd704e05944f978614aa9faff6ac202603", size = 4202289, upload-time = "2025-05-29T13:31:40.037Z" } +sdist = { url = "https://files.pythonhosted.org/packages/6c/3d/d9a195676f25d00dbfcf3cf95fdd4c685c497fcfa7e862a44ac5e4e96480/ruff-0.12.2.tar.gz", hash = "sha256:d7b4f55cd6f325cb7621244f19c873c565a08aff5a4ba9c69aa7355f3f7afd3e", size = 4432239, upload-time = "2025-07-03T16:40:19.566Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/60/cc/53eb79f012d15e136d40a8e8fc519ba8f55a057f60b29c2df34efd47c6e3/ruff-0.11.12-py3-none-linux_armv6l.whl", hash = "sha256:c7680aa2f0d4c4f43353d1e72123955c7a2159b8646cd43402de6d4a3a25d7cc", size = 10285597, upload-time = "2025-05-29T13:30:57.539Z" }, - { url = "https://files.pythonhosted.org/packages/e7/d7/73386e9fb0232b015a23f62fea7503f96e29c29e6c45461d4a73bac74df9/ruff-0.11.12-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:2cad64843da9f134565c20bcc430642de897b8ea02e2e79e6e02a76b8dcad7c3", size = 11053154, upload-time = "2025-05-29T13:31:00.865Z" }, - { url = "https://files.pythonhosted.org/packages/4e/eb/3eae144c5114e92deb65a0cb2c72326c8469e14991e9bc3ec0349da1331c/ruff-0.11.12-py3-none-macosx_11_0_arm64.whl", hash = "sha256:9b6886b524a1c659cee1758140138455d3c029783d1b9e643f3624a5ee0cb0aa", size = 10403048, upload-time = "2025-05-29T13:31:03.413Z" }, - { url = "https://files.pythonhosted.org/packages/29/64/20c54b20e58b1058db6689e94731f2a22e9f7abab74e1a758dfba058b6ca/ruff-0.11.12-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cc3a3690aad6e86c1958d3ec3c38c4594b6ecec75c1f531e84160bd827b2012", size = 10597062, upload-time = "2025-05-29T13:31:05.539Z" }, - { url = "https://files.pythonhosted.org/packages/29/3a/79fa6a9a39422a400564ca7233a689a151f1039110f0bbbabcb38106883a/ruff-0.11.12-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f97fdbc2549f456c65b3b0048560d44ddd540db1f27c778a938371424b49fe4a", size = 10155152, upload-time = "2025-05-29T13:31:07.986Z" }, - { url = "https://files.pythonhosted.org/packages/e5/a4/22c2c97b2340aa968af3a39bc38045e78d36abd4ed3fa2bde91c31e712e3/ruff-0.11.12-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:74adf84960236961090e2d1348c1a67d940fd12e811a33fb3d107df61eef8fc7", size = 11723067, upload-time = "2025-05-29T13:31:10.57Z" }, - { url = "https://files.pythonhosted.org/packages/bc/cf/3e452fbd9597bcd8058856ecd42b22751749d07935793a1856d988154151/ruff-0.11.12-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:b56697e5b8bcf1d61293ccfe63873aba08fdbcbbba839fc046ec5926bdb25a3a", size = 12460807, upload-time = "2025-05-29T13:31:12.88Z" }, - { url = "https://files.pythonhosted.org/packages/2f/ec/8f170381a15e1eb7d93cb4feef8d17334d5a1eb33fee273aee5d1f8241a3/ruff-0.11.12-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4d47afa45e7b0eaf5e5969c6b39cbd108be83910b5c74626247e366fd7a36a13", size = 12063261, upload-time = "2025-05-29T13:31:15.236Z" }, - { url = "https://files.pythonhosted.org/packages/0d/bf/57208f8c0a8153a14652a85f4116c0002148e83770d7a41f2e90b52d2b4e/ruff-0.11.12-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:692bf9603fe1bf949de8b09a2da896f05c01ed7a187f4a386cdba6760e7f61be", size = 11329601, upload-time = "2025-05-29T13:31:18.68Z" }, - { url = "https://files.pythonhosted.org/packages/c3/56/edf942f7fdac5888094d9ffa303f12096f1a93eb46570bcf5f14c0c70880/ruff-0.11.12-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:08033320e979df3b20dba567c62f69c45e01df708b0f9c83912d7abd3e0801cd", size = 11522186, upload-time = "2025-05-29T13:31:21.216Z" }, - { url = "https://files.pythonhosted.org/packages/ed/63/79ffef65246911ed7e2290aeece48739d9603b3a35f9529fec0fc6c26400/ruff-0.11.12-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:929b7706584f5bfd61d67d5070f399057d07c70585fa8c4491d78ada452d3bef", size = 10449032, upload-time = "2025-05-29T13:31:23.417Z" }, - { url = "https://files.pythonhosted.org/packages/88/19/8c9d4d8a1c2a3f5a1ea45a64b42593d50e28b8e038f1aafd65d6b43647f3/ruff-0.11.12-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:7de4a73205dc5756b8e09ee3ed67c38312dce1aa28972b93150f5751199981b5", size = 10129370, upload-time = "2025-05-29T13:31:25.777Z" }, - { url = "https://files.pythonhosted.org/packages/bc/0f/2d15533eaa18f460530a857e1778900cd867ded67f16c85723569d54e410/ruff-0.11.12-py3-none-musllinux_1_2_i686.whl", hash = "sha256:2635c2a90ac1b8ca9e93b70af59dfd1dd2026a40e2d6eebaa3efb0465dd9cf02", size = 11123529, upload-time = "2025-05-29T13:31:28.396Z" }, - { url = "https://files.pythonhosted.org/packages/4f/e2/4c2ac669534bdded835356813f48ea33cfb3a947dc47f270038364587088/ruff-0.11.12-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:d05d6a78a89166f03f03a198ecc9d18779076ad0eec476819467acb401028c0c", size = 11577642, upload-time = "2025-05-29T13:31:30.647Z" }, - { url = "https://files.pythonhosted.org/packages/a7/9b/c9ddf7f924d5617a1c94a93ba595f4b24cb5bc50e98b94433ab3f7ad27e5/ruff-0.11.12-py3-none-win32.whl", hash = "sha256:f5a07f49767c4be4772d161bfc049c1f242db0cfe1bd976e0f0886732a4765d6", size = 10475511, upload-time = "2025-05-29T13:31:32.917Z" }, - { url = "https://files.pythonhosted.org/packages/fd/d6/74fb6d3470c1aada019ffff33c0f9210af746cca0a4de19a1f10ce54968a/ruff-0.11.12-py3-none-win_amd64.whl", hash = "sha256:5a4d9f8030d8c3a45df201d7fb3ed38d0219bccd7955268e863ee4a115fa0832", size = 11523573, upload-time = "2025-05-29T13:31:35.782Z" }, - { url = "https://files.pythonhosted.org/packages/44/42/d58086ec20f52d2b0140752ae54b355ea2be2ed46f914231136dd1effcc7/ruff-0.11.12-py3-none-win_arm64.whl", hash = "sha256:65194e37853158d368e333ba282217941029a28ea90913c67e558c611d04daa5", size = 10697770, upload-time = "2025-05-29T13:31:38.009Z" }, + { url = "https://files.pythonhosted.org/packages/74/b6/2098d0126d2d3318fd5bec3ad40d06c25d377d95749f7a0c5af17129b3b1/ruff-0.12.2-py3-none-linux_armv6l.whl", hash = "sha256:093ea2b221df1d2b8e7ad92fc6ffdca40a2cb10d8564477a987b44fd4008a7be", size = 10369761, upload-time = "2025-07-03T16:39:38.847Z" }, + { url = "https://files.pythonhosted.org/packages/b1/4b/5da0142033dbe155dc598cfb99262d8ee2449d76920ea92c4eeb9547c208/ruff-0.12.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:09e4cf27cc10f96b1708100fa851e0daf21767e9709e1649175355280e0d950e", size = 11155659, upload-time = "2025-07-03T16:39:42.294Z" }, + { url = "https://files.pythonhosted.org/packages/3e/21/967b82550a503d7c5c5c127d11c935344b35e8c521f52915fc858fb3e473/ruff-0.12.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:8ae64755b22f4ff85e9c52d1f82644abd0b6b6b6deedceb74bd71f35c24044cc", size = 10537769, upload-time = "2025-07-03T16:39:44.75Z" }, + { url = "https://files.pythonhosted.org/packages/33/91/00cff7102e2ec71a4890fb7ba1803f2cdb122d82787c7d7cf8041fe8cbc1/ruff-0.12.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3eb3a6b2db4d6e2c77e682f0b988d4d61aff06860158fdb413118ca133d57922", size = 10717602, upload-time = "2025-07-03T16:39:47.652Z" }, + { url = "https://files.pythonhosted.org/packages/9b/eb/928814daec4e1ba9115858adcda44a637fb9010618721937491e4e2283b8/ruff-0.12.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:73448de992d05517170fc37169cbca857dfeaeaa8c2b9be494d7bcb0d36c8f4b", size = 10198772, upload-time = "2025-07-03T16:39:49.641Z" }, + { url = "https://files.pythonhosted.org/packages/50/fa/f15089bc20c40f4f72334f9145dde55ab2b680e51afb3b55422effbf2fb6/ruff-0.12.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b8b94317cbc2ae4a2771af641739f933934b03555e51515e6e021c64441532d", size = 11845173, upload-time = "2025-07-03T16:39:52.069Z" }, + { url = "https://files.pythonhosted.org/packages/43/9f/1f6f98f39f2b9302acc161a4a2187b1e3a97634fe918a8e731e591841cf4/ruff-0.12.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:45fc42c3bf1d30d2008023a0a9a0cfb06bf9835b147f11fe0679f21ae86d34b1", size = 12553002, upload-time = "2025-07-03T16:39:54.551Z" }, + { url = "https://files.pythonhosted.org/packages/d8/70/08991ac46e38ddd231c8f4fd05ef189b1b94be8883e8c0c146a025c20a19/ruff-0.12.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce48f675c394c37e958bf229fb5c1e843e20945a6d962cf3ea20b7a107dcd9f4", size = 12171330, upload-time = "2025-07-03T16:39:57.55Z" }, + { url = "https://files.pythonhosted.org/packages/88/a9/5a55266fec474acfd0a1c73285f19dd22461d95a538f29bba02edd07a5d9/ruff-0.12.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:793d8859445ea47591272021a81391350205a4af65a9392401f418a95dfb75c9", size = 11774717, upload-time = "2025-07-03T16:39:59.78Z" }, + { url = "https://files.pythonhosted.org/packages/87/e5/0c270e458fc73c46c0d0f7cf970bb14786e5fdb88c87b5e423a4bd65232b/ruff-0.12.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6932323db80484dda89153da3d8e58164d01d6da86857c79f1961934354992da", size = 11646659, upload-time = "2025-07-03T16:40:01.934Z" }, + { url = "https://files.pythonhosted.org/packages/b7/b6/45ab96070c9752af37f0be364d849ed70e9ccede07675b0ec4e3ef76b63b/ruff-0.12.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6aa7e623a3a11538108f61e859ebf016c4f14a7e6e4eba1980190cacb57714ce", size = 10604012, upload-time = "2025-07-03T16:40:04.363Z" }, + { url = "https://files.pythonhosted.org/packages/86/91/26a6e6a424eb147cc7627eebae095cfa0b4b337a7c1c413c447c9ebb72fd/ruff-0.12.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:2a4a20aeed74671b2def096bdf2eac610c7d8ffcbf4fb0e627c06947a1d7078d", size = 10176799, upload-time = "2025-07-03T16:40:06.514Z" }, + { url = "https://files.pythonhosted.org/packages/f5/0c/9f344583465a61c8918a7cda604226e77b2c548daf8ef7c2bfccf2b37200/ruff-0.12.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:71a4c550195612f486c9d1f2b045a600aeba851b298c667807ae933478fcef04", size = 11241507, upload-time = "2025-07-03T16:40:08.708Z" }, + { url = "https://files.pythonhosted.org/packages/1c/b7/99c34ded8fb5f86c0280278fa89a0066c3760edc326e935ce0b1550d315d/ruff-0.12.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:4987b8f4ceadf597c927beee65a5eaf994c6e2b631df963f86d8ad1bdea99342", size = 11717609, upload-time = "2025-07-03T16:40:10.836Z" }, + { url = "https://files.pythonhosted.org/packages/51/de/8589fa724590faa057e5a6d171e7f2f6cffe3287406ef40e49c682c07d89/ruff-0.12.2-py3-none-win32.whl", hash = "sha256:369ffb69b70cd55b6c3fc453b9492d98aed98062db9fec828cdfd069555f5f1a", size = 10523823, upload-time = "2025-07-03T16:40:13.203Z" }, + { url = "https://files.pythonhosted.org/packages/94/47/8abf129102ae4c90cba0c2199a1a9b0fa896f6f806238d6f8c14448cc748/ruff-0.12.2-py3-none-win_amd64.whl", hash = "sha256:dca8a3b6d6dc9810ed8f328d406516bf4d660c00caeaef36eb831cf4871b0639", size = 11629831, upload-time = "2025-07-03T16:40:15.478Z" }, + { url = "https://files.pythonhosted.org/packages/e2/1f/72d2946e3cc7456bb837e88000eb3437e55f80db339c840c04015a11115d/ruff-0.12.2-py3-none-win_arm64.whl", hash = "sha256:48d6c6bfb4761df68bc05ae630e24f506755e702d4fb08f08460be778c7ccb12", size = 10735334, upload-time = "2025-07-03T16:40:17.677Z" }, ] [[package]] @@ -2899,9 +2906,9 @@ name = "sse-starlette" version = "2.1.3" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "anyio", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, - { name = "starlette", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, - { name = "uvicorn", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, + { name = "anyio", marker = "python_full_version >= '3.11'" }, + { name = "starlette", marker = "python_full_version >= '3.11'" }, + { name = "uvicorn", marker = "python_full_version >= '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/72/fc/56ab9f116b2133521f532fce8d03194cf04dcac25f583cf3d839be4c0496/sse_starlette-2.1.3.tar.gz", hash = "sha256:9cd27eb35319e1414e3d2558ee7414487f9529ce3b3cf9b21434fd110e017169", size = 19678, upload-time = "2024-08-01T08:52:50.248Z" } wheels = [ @@ -2924,23 +2931,24 @@ wheels = [ [[package]] name = "starlette" -version = "0.47.0" +version = "0.47.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "anyio", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, + { name = "anyio", marker = "python_full_version >= '3.11'" }, + { name = "typing-extensions", marker = "python_full_version >= '3.11' and python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8b/d0/0332bd8a25779a0e2082b0e179805ad39afad642938b371ae0882e7f880d/starlette-0.47.0.tar.gz", hash = "sha256:1f64887e94a447fed5f23309fb6890ef23349b7e478faa7b24a851cd4eb844af", size = 2582856, upload-time = "2025-05-29T15:45:27.628Z" } +sdist = { url = "https://files.pythonhosted.org/packages/0a/69/662169fdb92fb96ec3eaee218cf540a629d629c86d7993d9651226a6789b/starlette-0.47.1.tar.gz", hash = "sha256:aef012dd2b6be325ffa16698f9dc533614fb1cebd593a906b90dc1025529a79b", size = 2583072, upload-time = "2025-06-21T04:03:17.337Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e3/81/c60b35fe9674f63b38a8feafc414fca0da378a9dbd5fa1e0b8d23fcc7a9b/starlette-0.47.0-py3-none-any.whl", hash = "sha256:9d052d4933683af40ffd47c7465433570b4949dc937e20ad1d73b34e72f10c37", size = 72796, upload-time = "2025-05-29T15:45:26.305Z" }, + { url = "https://files.pythonhosted.org/packages/82/95/38ef0cd7fa11eaba6a99b3c4f5ac948d8bc6ff199aabd327a29cc000840c/starlette-0.47.1-py3-none-any.whl", hash = "sha256:5e11c9f5c7c3f24959edbf2dffdc01bba860228acf657129467d8a7468591527", size = 72747, upload-time = "2025-06-21T04:03:15.705Z" }, ] [[package]] name = "structlog" -version = "25.3.0" +version = "25.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ff/6a/b0b6d440e429d2267076c4819300d9929563b1da959cf1f68afbcd69fe45/structlog-25.3.0.tar.gz", hash = "sha256:8dab497e6f6ca962abad0c283c46744185e0c9ba900db52a423cb6db99f7abeb", size = 1367514, upload-time = "2025-04-25T16:00:39.167Z" } +sdist = { url = "https://files.pythonhosted.org/packages/79/b9/6e672db4fec07349e7a8a8172c1a6ae235c58679ca29c3f86a61b5e59ff3/structlog-25.4.0.tar.gz", hash = "sha256:186cd1b0a8ae762e29417095664adf1d6a31702160a46dacb7796ea82f7409e4", size = 1369138, upload-time = "2025-06-02T08:21:12.971Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f5/52/7a2c7a317b254af857464da3d60a0d3730c44f912f8c510c76a738a207fd/structlog-25.3.0-py3-none-any.whl", hash = "sha256:a341f5524004c158498c3127eecded091eb67d3a611e7a3093deca30db06e172", size = 68240, upload-time = "2025-04-25T16:00:37.295Z" }, + { url = "https://files.pythonhosted.org/packages/a0/4a/97ee6973e3a73c74c8120d59829c3861ea52210667ec3e7a16045c62b64d/structlog-25.4.0-py3-none-any.whl", hash = "sha256:fe809ff5c27e557d14e613f45ca441aabda051d119ee5a0102aaba6ce40eed2c", size = 68720, upload-time = "2025-06-02T08:21:11.43Z" }, ] [[package]] @@ -3077,23 +3085,23 @@ wheels = [ [[package]] name = "types-requests" -version = "2.32.0.20250515" +version = "2.32.4.20250611" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/06/c1/cdc4f9b8cfd9130fbe6276db574f114541f4231fcc6fb29648289e6e3390/types_requests-2.32.0.20250515.tar.gz", hash = "sha256:09c8b63c11318cb2460813871aaa48b671002e59fda67ca909e9883777787581", size = 23012, upload-time = "2025-05-15T03:04:31.817Z" } +sdist = { url = "https://files.pythonhosted.org/packages/6d/7f/73b3a04a53b0fd2a911d4ec517940ecd6600630b559e4505cc7b68beb5a0/types_requests-2.32.4.20250611.tar.gz", hash = "sha256:741c8777ed6425830bf51e54d6abe245f79b4dcb9019f1622b773463946bf826", size = 23118, upload-time = "2025-06-11T03:11:41.272Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fe/0f/68a997c73a129287785f418c1ebb6004f81e46b53b3caba88c0e03fcd04a/types_requests-2.32.0.20250515-py3-none-any.whl", hash = "sha256:f8eba93b3a892beee32643ff836993f15a785816acca21ea0ffa006f05ef0fb2", size = 20635, upload-time = "2025-05-15T03:04:30.5Z" }, + { url = "https://files.pythonhosted.org/packages/3d/ea/0be9258c5a4fa1ba2300111aa5a0767ee6d18eb3fd20e91616c12082284d/types_requests-2.32.4.20250611-py3-none-any.whl", hash = "sha256:ad2fe5d3b0cb3c2c902c8815a70e7fb2302c4b8c1f77bdcd738192cdb3878072", size = 20643, upload-time = "2025-06-11T03:11:40.186Z" }, ] [[package]] name = "typing-extensions" -version = "4.13.2" +version = "4.14.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f6/37/23083fcd6e35492953e8d2aaaa68b860eb422b34627b13f2ce3eb6106061/typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef", size = 106967, upload-time = "2025-04-10T14:19:05.416Z" } +sdist = { url = "https://files.pythonhosted.org/packages/98/5a/da40306b885cc8c09109dc2e1abd358d5684b1425678151cdaed4731c822/typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36", size = 107673, upload-time = "2025-07-04T13:28:34.16Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806, upload-time = "2025-04-10T14:19:03.967Z" }, + { url = "https://files.pythonhosted.org/packages/b5/00/d631e67a838026495268c2f6884f3711a15a9a2a96cd244fdaea53b823fb/typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76", size = 43906, upload-time = "2025-07-04T13:28:32.743Z" }, ] [[package]] @@ -3128,24 +3136,24 @@ wheels = [ [[package]] name = "urllib3" -version = "2.4.0" +version = "2.5.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8a/78/16493d9c386d8e60e442a35feac5e00f0913c0f4b7c217c11e8ec2ff53e0/urllib3-2.4.0.tar.gz", hash = "sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466", size = 390672, upload-time = "2025-04-10T15:23:39.232Z" } +sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6b/11/cc635220681e93a0183390e26485430ca2c7b5f9d33b15c74c2861cb8091/urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813", size = 128680, upload-time = "2025-04-10T15:23:37.377Z" }, + { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" }, ] [[package]] name = "uvicorn" -version = "0.34.2" +version = "0.35.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "click", version = "8.2.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, - { name = "h11", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, + { name = "click", version = "8.2.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "h11", marker = "python_full_version >= '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a6/ae/9bbb19b9e1c450cf9ecaef06463e40234d98d95bf572fab11b4f19ae5ded/uvicorn-0.34.2.tar.gz", hash = "sha256:0e929828f6186353a80b58ea719861d2629d766293b6d19baf086ba31d4f3328", size = 76815, upload-time = "2025-04-19T06:02:50.101Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5e/42/e0e305207bb88c6b8d3061399c6a961ffe5fbb7e2aa63c9234df7259e9cd/uvicorn-0.35.0.tar.gz", hash = "sha256:bc662f087f7cf2ce11a1d7fd70b90c9f98ef2e2831556dd078d131b96cc94a01", size = 78473, upload-time = "2025-06-28T16:15:46.058Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b1/4b/4cef6ce21a2aaca9d852a6e84ef4f135d99fcd74fa75105e2fc0c8308acd/uvicorn-0.34.2-py3-none-any.whl", hash = "sha256:deb49af569084536d269fe0a6d67e3754f104cf03aba7c11c40f01aadf33c403", size = 62483, upload-time = "2025-04-19T06:02:48.42Z" }, + { url = "https://files.pythonhosted.org/packages/d2/e2/dc81b1bd1dcfe91735810265e9d26bc8ec5da45b4c0f6237e286819194c3/uvicorn-0.35.0-py3-none-any.whl", hash = "sha256:197535216b25ff9b785e29a0b79199f55222193d47f820816e7da751e9bc8d4a", size = 66406, upload-time = "2025-06-28T16:15:44.816Z" }, ] [[package]] @@ -3225,83 +3233,118 @@ wheels = [ [[package]] name = "watchfiles" -version = "1.0.5" +version = "1.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "anyio", marker = "python_full_version >= '3.11' and python_full_version < '4.0'" }, + { name = "anyio", marker = "python_full_version >= '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/03/e2/8ed598c42057de7aa5d97c472254af4906ff0a59a66699d426fc9ef795d7/watchfiles-1.0.5.tar.gz", hash = "sha256:b7529b5dcc114679d43827d8c35a07c493ad6f083633d573d81c660abc5979e9", size = 94537, upload-time = "2025-04-08T10:36:26.722Z" } +sdist = { url = "https://files.pythonhosted.org/packages/2a/9a/d451fcc97d029f5812e898fd30a53fd8c15c7bbd058fd75cfc6beb9bd761/watchfiles-1.1.0.tar.gz", hash = "sha256:693ed7ec72cbfcee399e92c895362b6e66d63dac6b91e2c11ae03d10d503e575", size = 94406, upload-time = "2025-06-15T19:06:59.42Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/af/4d/d02e6ea147bb7fff5fd109c694a95109612f419abed46548a930e7f7afa3/watchfiles-1.0.5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:5c40fe7dd9e5f81e0847b1ea64e1f5dd79dd61afbedb57759df06767ac719b40", size = 405632, upload-time = "2025-04-08T10:34:41.832Z" }, - { url = "https://files.pythonhosted.org/packages/60/31/9ee50e29129d53a9a92ccf1d3992751dc56fc3c8f6ee721be1c7b9c81763/watchfiles-1.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8c0db396e6003d99bb2d7232c957b5f0b5634bbd1b24e381a5afcc880f7373fb", size = 395734, upload-time = "2025-04-08T10:34:44.236Z" }, - { url = "https://files.pythonhosted.org/packages/ad/8c/759176c97195306f028024f878e7f1c776bda66ccc5c68fa51e699cf8f1d/watchfiles-1.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b551d4fb482fc57d852b4541f911ba28957d051c8776e79c3b4a51eb5e2a1b11", size = 455008, upload-time = "2025-04-08T10:34:45.617Z" }, - { url = "https://files.pythonhosted.org/packages/55/1a/5e977250c795ee79a0229e3b7f5e3a1b664e4e450756a22da84d2f4979fe/watchfiles-1.0.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:830aa432ba5c491d52a15b51526c29e4a4b92bf4f92253787f9726fe01519487", size = 459029, upload-time = "2025-04-08T10:34:46.814Z" }, - { url = "https://files.pythonhosted.org/packages/e6/17/884cf039333605c1d6e296cf5be35fad0836953c3dfd2adb71b72f9dbcd0/watchfiles-1.0.5-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a16512051a822a416b0d477d5f8c0e67b67c1a20d9acecb0aafa3aa4d6e7d256", size = 488916, upload-time = "2025-04-08T10:34:48.571Z" }, - { url = "https://files.pythonhosted.org/packages/ef/e0/bcb6e64b45837056c0a40f3a2db3ef51c2ced19fda38484fa7508e00632c/watchfiles-1.0.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bfe0cbc787770e52a96c6fda6726ace75be7f840cb327e1b08d7d54eadc3bc85", size = 523763, upload-time = "2025-04-08T10:34:50.268Z" }, - { url = "https://files.pythonhosted.org/packages/24/e9/f67e9199f3bb35c1837447ecf07e9830ec00ff5d35a61e08c2cd67217949/watchfiles-1.0.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d363152c5e16b29d66cbde8fa614f9e313e6f94a8204eaab268db52231fe5358", size = 502891, upload-time = "2025-04-08T10:34:51.419Z" }, - { url = "https://files.pythonhosted.org/packages/23/ed/a6cf815f215632f5c8065e9c41fe872025ffea35aa1f80499f86eae922db/watchfiles-1.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ee32c9a9bee4d0b7bd7cbeb53cb185cf0b622ac761efaa2eba84006c3b3a614", size = 454921, upload-time = "2025-04-08T10:34:52.67Z" }, - { url = "https://files.pythonhosted.org/packages/92/4c/e14978599b80cde8486ab5a77a821e8a982ae8e2fcb22af7b0886a033ec8/watchfiles-1.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:29c7fd632ccaf5517c16a5188e36f6612d6472ccf55382db6c7fe3fcccb7f59f", size = 631422, upload-time = "2025-04-08T10:34:53.985Z" }, - { url = "https://files.pythonhosted.org/packages/b2/1a/9263e34c3458f7614b657f974f4ee61fd72f58adce8b436e16450e054efd/watchfiles-1.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8e637810586e6fe380c8bc1b3910accd7f1d3a9a7262c8a78d4c8fb3ba6a2b3d", size = 625675, upload-time = "2025-04-08T10:34:55.173Z" }, - { url = "https://files.pythonhosted.org/packages/96/1f/1803a18bd6ab04a0766386a19bcfe64641381a04939efdaa95f0e3b0eb58/watchfiles-1.0.5-cp310-cp310-win32.whl", hash = "sha256:cd47d063fbeabd4c6cae1d4bcaa38f0902f8dc5ed168072874ea11d0c7afc1ff", size = 277921, upload-time = "2025-04-08T10:34:56.318Z" }, - { url = "https://files.pythonhosted.org/packages/c2/3b/29a89de074a7d6e8b4dc67c26e03d73313e4ecf0d6e97e942a65fa7c195e/watchfiles-1.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:86c0df05b47a79d80351cd179893f2f9c1b1cae49d96e8b3290c7f4bd0ca0a92", size = 291526, upload-time = "2025-04-08T10:34:57.95Z" }, - { url = "https://files.pythonhosted.org/packages/39/f4/41b591f59021786ef517e1cdc3b510383551846703e03f204827854a96f8/watchfiles-1.0.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:237f9be419e977a0f8f6b2e7b0475ababe78ff1ab06822df95d914a945eac827", size = 405336, upload-time = "2025-04-08T10:34:59.359Z" }, - { url = "https://files.pythonhosted.org/packages/ae/06/93789c135be4d6d0e4f63e96eea56dc54050b243eacc28439a26482b5235/watchfiles-1.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0da39ff917af8b27a4bdc5a97ac577552a38aac0d260a859c1517ea3dc1a7c4", size = 395977, upload-time = "2025-04-08T10:35:00.522Z" }, - { url = "https://files.pythonhosted.org/packages/d2/db/1cd89bd83728ca37054512d4d35ab69b5f12b8aa2ac9be3b0276b3bf06cc/watchfiles-1.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cfcb3952350e95603f232a7a15f6c5f86c5375e46f0bd4ae70d43e3e063c13d", size = 455232, upload-time = "2025-04-08T10:35:01.698Z" }, - { url = "https://files.pythonhosted.org/packages/40/90/d8a4d44ffe960517e487c9c04f77b06b8abf05eb680bed71c82b5f2cad62/watchfiles-1.0.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:68b2dddba7a4e6151384e252a5632efcaa9bc5d1c4b567f3cb621306b2ca9f63", size = 459151, upload-time = "2025-04-08T10:35:03.358Z" }, - { url = "https://files.pythonhosted.org/packages/6c/da/267a1546f26465dead1719caaba3ce660657f83c9d9c052ba98fb8856e13/watchfiles-1.0.5-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:95cf944fcfc394c5f9de794ce581914900f82ff1f855326f25ebcf24d5397418", size = 489054, upload-time = "2025-04-08T10:35:04.561Z" }, - { url = "https://files.pythonhosted.org/packages/b1/31/33850dfd5c6efb6f27d2465cc4c6b27c5a6f5ed53c6fa63b7263cf5f60f6/watchfiles-1.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ecf6cd9f83d7c023b1aba15d13f705ca7b7d38675c121f3cc4a6e25bd0857ee9", size = 523955, upload-time = "2025-04-08T10:35:05.786Z" }, - { url = "https://files.pythonhosted.org/packages/09/84/b7d7b67856efb183a421f1416b44ca975cb2ea6c4544827955dfb01f7dc2/watchfiles-1.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:852de68acd6212cd6d33edf21e6f9e56e5d98c6add46f48244bd479d97c967c6", size = 502234, upload-time = "2025-04-08T10:35:07.187Z" }, - { url = "https://files.pythonhosted.org/packages/71/87/6dc5ec6882a2254cfdd8b0718b684504e737273903b65d7338efaba08b52/watchfiles-1.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5730f3aa35e646103b53389d5bc77edfbf578ab6dab2e005142b5b80a35ef25", size = 454750, upload-time = "2025-04-08T10:35:08.859Z" }, - { url = "https://files.pythonhosted.org/packages/3d/6c/3786c50213451a0ad15170d091570d4a6554976cf0df19878002fc96075a/watchfiles-1.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:18b3bd29954bc4abeeb4e9d9cf0b30227f0f206c86657674f544cb032296acd5", size = 631591, upload-time = "2025-04-08T10:35:10.64Z" }, - { url = "https://files.pythonhosted.org/packages/1b/b3/1427425ade4e359a0deacce01a47a26024b2ccdb53098f9d64d497f6684c/watchfiles-1.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ba5552a1b07c8edbf197055bc9d518b8f0d98a1c6a73a293bc0726dce068ed01", size = 625370, upload-time = "2025-04-08T10:35:12.412Z" }, - { url = "https://files.pythonhosted.org/packages/15/ba/f60e053b0b5b8145d682672024aa91370a29c5c921a88977eb565de34086/watchfiles-1.0.5-cp311-cp311-win32.whl", hash = "sha256:2f1fefb2e90e89959447bc0420fddd1e76f625784340d64a2f7d5983ef9ad246", size = 277791, upload-time = "2025-04-08T10:35:13.719Z" }, - { url = "https://files.pythonhosted.org/packages/50/ed/7603c4e164225c12c0d4e8700b64bb00e01a6c4eeea372292a3856be33a4/watchfiles-1.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:b6e76ceb1dd18c8e29c73f47d41866972e891fc4cc7ba014f487def72c1cf096", size = 291622, upload-time = "2025-04-08T10:35:15.071Z" }, - { url = "https://files.pythonhosted.org/packages/a2/c2/99bb7c96b4450e36877fde33690ded286ff555b5a5c1d925855d556968a1/watchfiles-1.0.5-cp311-cp311-win_arm64.whl", hash = "sha256:266710eb6fddc1f5e51843c70e3bebfb0f5e77cf4f27129278c70554104d19ed", size = 283699, upload-time = "2025-04-08T10:35:16.732Z" }, - { url = "https://files.pythonhosted.org/packages/2a/8c/4f0b9bdb75a1bfbd9c78fad7d8854369283f74fe7cf03eb16be77054536d/watchfiles-1.0.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:b5eb568c2aa6018e26da9e6c86f3ec3fd958cee7f0311b35c2630fa4217d17f2", size = 401511, upload-time = "2025-04-08T10:35:17.956Z" }, - { url = "https://files.pythonhosted.org/packages/dc/4e/7e15825def77f8bd359b6d3f379f0c9dac4eb09dd4ddd58fd7d14127179c/watchfiles-1.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0a04059f4923ce4e856b4b4e5e783a70f49d9663d22a4c3b3298165996d1377f", size = 392715, upload-time = "2025-04-08T10:35:19.202Z" }, - { url = "https://files.pythonhosted.org/packages/58/65/b72fb817518728e08de5840d5d38571466c1b4a3f724d190cec909ee6f3f/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e380c89983ce6e6fe2dd1e1921b9952fb4e6da882931abd1824c092ed495dec", size = 454138, upload-time = "2025-04-08T10:35:20.586Z" }, - { url = "https://files.pythonhosted.org/packages/3e/a4/86833fd2ea2e50ae28989f5950b5c3f91022d67092bfec08f8300d8b347b/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fe43139b2c0fdc4a14d4f8d5b5d967f7a2777fd3d38ecf5b1ec669b0d7e43c21", size = 458592, upload-time = "2025-04-08T10:35:21.87Z" }, - { url = "https://files.pythonhosted.org/packages/38/7e/42cb8df8be9a37e50dd3a818816501cf7a20d635d76d6bd65aae3dbbff68/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee0822ce1b8a14fe5a066f93edd20aada932acfe348bede8aa2149f1a4489512", size = 487532, upload-time = "2025-04-08T10:35:23.143Z" }, - { url = "https://files.pythonhosted.org/packages/fc/fd/13d26721c85d7f3df6169d8b495fcac8ab0dc8f0945ebea8845de4681dab/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a0dbcb1c2d8f2ab6e0a81c6699b236932bd264d4cef1ac475858d16c403de74d", size = 522865, upload-time = "2025-04-08T10:35:24.702Z" }, - { url = "https://files.pythonhosted.org/packages/a1/0d/7f9ae243c04e96c5455d111e21b09087d0eeaf9a1369e13a01c7d3d82478/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a2014a2b18ad3ca53b1f6c23f8cd94a18ce930c1837bd891262c182640eb40a6", size = 499887, upload-time = "2025-04-08T10:35:25.969Z" }, - { url = "https://files.pythonhosted.org/packages/8e/0f/a257766998e26aca4b3acf2ae97dff04b57071e991a510857d3799247c67/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10f6ae86d5cb647bf58f9f655fcf577f713915a5d69057a0371bc257e2553234", size = 454498, upload-time = "2025-04-08T10:35:27.353Z" }, - { url = "https://files.pythonhosted.org/packages/81/79/8bf142575a03e0af9c3d5f8bcae911ee6683ae93a625d349d4ecf4c8f7df/watchfiles-1.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1a7bac2bde1d661fb31f4d4e8e539e178774b76db3c2c17c4bb3e960a5de07a2", size = 630663, upload-time = "2025-04-08T10:35:28.685Z" }, - { url = "https://files.pythonhosted.org/packages/f1/80/abe2e79f610e45c63a70d271caea90c49bbf93eb00fa947fa9b803a1d51f/watchfiles-1.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ab626da2fc1ac277bbf752446470b367f84b50295264d2d313e28dc4405d663", size = 625410, upload-time = "2025-04-08T10:35:30.42Z" }, - { url = "https://files.pythonhosted.org/packages/91/6f/bc7fbecb84a41a9069c2c6eb6319f7f7df113adf113e358c57fc1aff7ff5/watchfiles-1.0.5-cp312-cp312-win32.whl", hash = "sha256:9f4571a783914feda92018ef3901dab8caf5b029325b5fe4558c074582815249", size = 277965, upload-time = "2025-04-08T10:35:32.023Z" }, - { url = "https://files.pythonhosted.org/packages/99/a5/bf1c297ea6649ec59e935ab311f63d8af5faa8f0b86993e3282b984263e3/watchfiles-1.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:360a398c3a19672cf93527f7e8d8b60d8275119c5d900f2e184d32483117a705", size = 291693, upload-time = "2025-04-08T10:35:33.225Z" }, - { url = "https://files.pythonhosted.org/packages/7f/7b/fd01087cc21db5c47e5beae507b87965db341cce8a86f9eb12bf5219d4e0/watchfiles-1.0.5-cp312-cp312-win_arm64.whl", hash = "sha256:1a2902ede862969077b97523987c38db28abbe09fb19866e711485d9fbf0d417", size = 283287, upload-time = "2025-04-08T10:35:34.568Z" }, - { url = "https://files.pythonhosted.org/packages/c7/62/435766874b704f39b2fecd8395a29042db2b5ec4005bd34523415e9bd2e0/watchfiles-1.0.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:0b289572c33a0deae62daa57e44a25b99b783e5f7aed81b314232b3d3c81a11d", size = 401531, upload-time = "2025-04-08T10:35:35.792Z" }, - { url = "https://files.pythonhosted.org/packages/6e/a6/e52a02c05411b9cb02823e6797ef9bbba0bfaf1bb627da1634d44d8af833/watchfiles-1.0.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a056c2f692d65bf1e99c41045e3bdcaea3cb9e6b5a53dcaf60a5f3bd95fc9763", size = 392417, upload-time = "2025-04-08T10:35:37.048Z" }, - { url = "https://files.pythonhosted.org/packages/3f/53/c4af6819770455932144e0109d4854437769672d7ad897e76e8e1673435d/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9dca99744991fc9850d18015c4f0438865414e50069670f5f7eee08340d8b40", size = 453423, upload-time = "2025-04-08T10:35:38.357Z" }, - { url = "https://files.pythonhosted.org/packages/cb/d1/8e88df58bbbf819b8bc5cfbacd3c79e01b40261cad0fc84d1e1ebd778a07/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:894342d61d355446d02cd3988a7326af344143eb33a2fd5d38482a92072d9563", size = 458185, upload-time = "2025-04-08T10:35:39.708Z" }, - { url = "https://files.pythonhosted.org/packages/ff/70/fffaa11962dd5429e47e478a18736d4e42bec42404f5ee3b92ef1b87ad60/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ab44e1580924d1ffd7b3938e02716d5ad190441965138b4aa1d1f31ea0877f04", size = 486696, upload-time = "2025-04-08T10:35:41.469Z" }, - { url = "https://files.pythonhosted.org/packages/39/db/723c0328e8b3692d53eb273797d9a08be6ffb1d16f1c0ba2bdbdc2a3852c/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d6f9367b132078b2ceb8d066ff6c93a970a18c3029cea37bfd7b2d3dd2e5db8f", size = 522327, upload-time = "2025-04-08T10:35:43.289Z" }, - { url = "https://files.pythonhosted.org/packages/cd/05/9fccc43c50c39a76b68343484b9da7b12d42d0859c37c61aec018c967a32/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2e55a9b162e06e3f862fb61e399fe9f05d908d019d87bf5b496a04ef18a970a", size = 499741, upload-time = "2025-04-08T10:35:44.574Z" }, - { url = "https://files.pythonhosted.org/packages/23/14/499e90c37fa518976782b10a18b18db9f55ea73ca14641615056f8194bb3/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0125f91f70e0732a9f8ee01e49515c35d38ba48db507a50c5bdcad9503af5827", size = 453995, upload-time = "2025-04-08T10:35:46.336Z" }, - { url = "https://files.pythonhosted.org/packages/61/d9/f75d6840059320df5adecd2c687fbc18960a7f97b55c300d20f207d48aef/watchfiles-1.0.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:13bb21f8ba3248386337c9fa51c528868e6c34a707f729ab041c846d52a0c69a", size = 629693, upload-time = "2025-04-08T10:35:48.161Z" }, - { url = "https://files.pythonhosted.org/packages/fc/17/180ca383f5061b61406477218c55d66ec118e6c0c51f02d8142895fcf0a9/watchfiles-1.0.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:839ebd0df4a18c5b3c1b890145b5a3f5f64063c2a0d02b13c76d78fe5de34936", size = 624677, upload-time = "2025-04-08T10:35:49.65Z" }, - { url = "https://files.pythonhosted.org/packages/bf/15/714d6ef307f803f236d69ee9d421763707899d6298d9f3183e55e366d9af/watchfiles-1.0.5-cp313-cp313-win32.whl", hash = "sha256:4a8ec1e4e16e2d5bafc9ba82f7aaecfeec990ca7cd27e84fb6f191804ed2fcfc", size = 277804, upload-time = "2025-04-08T10:35:51.093Z" }, - { url = "https://files.pythonhosted.org/packages/a8/b4/c57b99518fadf431f3ef47a610839e46e5f8abf9814f969859d1c65c02c7/watchfiles-1.0.5-cp313-cp313-win_amd64.whl", hash = "sha256:f436601594f15bf406518af922a89dcaab416568edb6f65c4e5bbbad1ea45c11", size = 291087, upload-time = "2025-04-08T10:35:52.458Z" }, - { url = "https://files.pythonhosted.org/packages/c5/95/94f3dd15557f5553261e407551c5e4d340e50161c55aa30812c79da6cb04/watchfiles-1.0.5-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:2cfb371be97d4db374cba381b9f911dd35bb5f4c58faa7b8b7106c8853e5d225", size = 405686, upload-time = "2025-04-08T10:35:53.86Z" }, - { url = "https://files.pythonhosted.org/packages/f4/aa/b99e968153f8b70159ecca7b3daf46a6f46d97190bdaa3a449ad31b921d7/watchfiles-1.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a3904d88955fda461ea2531fcf6ef73584ca921415d5cfa44457a225f4a42bc1", size = 396047, upload-time = "2025-04-08T10:35:55.232Z" }, - { url = "https://files.pythonhosted.org/packages/23/cb/90d3d760ad4bc7290e313fb9236c7d60598627a25a5a72764e48d9652064/watchfiles-1.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2b7a21715fb12274a71d335cff6c71fe7f676b293d322722fe708a9ec81d91f5", size = 456081, upload-time = "2025-04-08T10:35:57.102Z" }, - { url = "https://files.pythonhosted.org/packages/3e/65/79c6cebe5bcb695cdac145946ad5a09b9f66762549e82fb2d064ea960c95/watchfiles-1.0.5-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dfd6ae1c385ab481766b3c61c44aca2b3cd775f6f7c0fa93d979ddec853d29d5", size = 459838, upload-time = "2025-04-08T10:35:58.867Z" }, - { url = "https://files.pythonhosted.org/packages/3f/84/699f52632cdaa777f6df7f6f1cc02a23a75b41071b7e6765b9a412495f61/watchfiles-1.0.5-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b659576b950865fdad31fa491d31d37cf78b27113a7671d39f919828587b429b", size = 489753, upload-time = "2025-04-08T10:36:00.237Z" }, - { url = "https://files.pythonhosted.org/packages/25/68/3241f82ad414fd969de6bf3a93805682e5eb589aeab510322f2aa14462f8/watchfiles-1.0.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1909e0a9cd95251b15bff4261de5dd7550885bd172e3536824bf1cf6b121e200", size = 525015, upload-time = "2025-04-08T10:36:02.159Z" }, - { url = "https://files.pythonhosted.org/packages/85/c4/30d879e252f52b01660f545c193e6b81c48aac2e0eeec71263af3add905b/watchfiles-1.0.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:832ccc221927c860e7286c55c9b6ebcc0265d5e072f49c7f6456c7798d2b39aa", size = 503816, upload-time = "2025-04-08T10:36:03.869Z" }, - { url = "https://files.pythonhosted.org/packages/6b/7d/fa34750f6f4b1a70d96fa6b685fe2948d01e3936328ea528f182943eb373/watchfiles-1.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85fbb6102b3296926d0c62cfc9347f6237fb9400aecd0ba6bbda94cae15f2b3b", size = 456137, upload-time = "2025-04-08T10:36:05.226Z" }, - { url = "https://files.pythonhosted.org/packages/8f/0c/a1569709aaeccb1dd74b0dd304d0de29e3ea1fdf11e08c78f489628f9ebb/watchfiles-1.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:15ac96dd567ad6c71c71f7b2c658cb22b7734901546cd50a475128ab557593ca", size = 632673, upload-time = "2025-04-08T10:36:06.752Z" }, - { url = "https://files.pythonhosted.org/packages/90/b6/645eaaca11f3ac625cf3b6e008e543acf0bf2581f68b5e205a13b05618b6/watchfiles-1.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4b6227351e11c57ae997d222e13f5b6f1f0700d84b8c52304e8675d33a808382", size = 626659, upload-time = "2025-04-08T10:36:08.18Z" }, - { url = "https://files.pythonhosted.org/packages/3a/c4/e741d9b92b0a2c74b976ff78bbc9a1276b4d904c590878e8fe0ec9fecca5/watchfiles-1.0.5-cp39-cp39-win32.whl", hash = "sha256:974866e0db748ebf1eccab17862bc0f0303807ed9cda465d1324625b81293a18", size = 278471, upload-time = "2025-04-08T10:36:10.546Z" }, - { url = "https://files.pythonhosted.org/packages/50/1b/36b0cb6add99105f78931994b30bc1dd24118c0e659ab6a3ffe0dd8734d4/watchfiles-1.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:9848b21ae152fe79c10dd0197304ada8f7b586d3ebc3f27f43c506e5a52a863c", size = 292027, upload-time = "2025-04-08T10:36:11.901Z" }, - { url = "https://files.pythonhosted.org/packages/1a/03/81f9fcc3963b3fc415cd4b0b2b39ee8cc136c42fb10a36acf38745e9d283/watchfiles-1.0.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f59b870db1f1ae5a9ac28245707d955c8721dd6565e7f411024fa374b5362d1d", size = 405947, upload-time = "2025-04-08T10:36:13.721Z" }, - { url = "https://files.pythonhosted.org/packages/54/97/8c4213a852feb64807ec1d380f42d4fc8bfaef896bdbd94318f8fd7f3e4e/watchfiles-1.0.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9475b0093767e1475095f2aeb1d219fb9664081d403d1dff81342df8cd707034", size = 397276, upload-time = "2025-04-08T10:36:15.131Z" }, - { url = "https://files.pythonhosted.org/packages/78/12/d4464d19860cb9672efa45eec1b08f8472c478ed67dcd30647c51ada7aef/watchfiles-1.0.5-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc533aa50664ebd6c628b2f30591956519462f5d27f951ed03d6c82b2dfd9965", size = 455550, upload-time = "2025-04-08T10:36:16.635Z" }, - { url = "https://files.pythonhosted.org/packages/90/fb/b07bcdf1034d8edeaef4c22f3e9e3157d37c5071b5f9492ffdfa4ad4bed7/watchfiles-1.0.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fed1cd825158dcaae36acce7b2db33dcbfd12b30c34317a88b8ed80f0541cc57", size = 455542, upload-time = "2025-04-08T10:36:18.655Z" }, - { url = "https://files.pythonhosted.org/packages/5b/84/7b69282c0df2bf2dff4e50be2c54669cddf219a5a5fb077891c00c00e5c8/watchfiles-1.0.5-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:554389562c29c2c182e3908b149095051f81d28c2fec79ad6c8997d7d63e0009", size = 405783, upload-time = "2025-04-08T10:36:20.553Z" }, - { url = "https://files.pythonhosted.org/packages/dd/ae/03fca0545d99b7ea21df49bead7b51e7dca9ce3b45bb6d34530aa18c16a2/watchfiles-1.0.5-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a74add8d7727e6404d5dc4dcd7fac65d4d82f95928bbee0cf5414c900e86773e", size = 397133, upload-time = "2025-04-08T10:36:22.439Z" }, - { url = "https://files.pythonhosted.org/packages/1a/07/c2b6390003e933b2e187a3f7070c00bd87da8a58d6f2393e039b06a88c2e/watchfiles-1.0.5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb1489f25b051a89fae574505cc26360c8e95e227a9500182a7fe0afcc500ce0", size = 456198, upload-time = "2025-04-08T10:36:23.884Z" }, - { url = "https://files.pythonhosted.org/packages/46/d3/ecc62cbd7054f0812f3a7ca7c1c9f7ba99ba45efcfc8297a9fcd2c87b31c/watchfiles-1.0.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0901429650652d3f0da90bad42bdafc1f9143ff3605633c455c999a2d786cac", size = 456511, upload-time = "2025-04-08T10:36:25.42Z" }, + { url = "https://files.pythonhosted.org/packages/b9/dd/579d1dc57f0f895426a1211c4ef3b0cb37eb9e642bb04bdcd962b5df206a/watchfiles-1.1.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:27f30e14aa1c1e91cb653f03a63445739919aef84c8d2517997a83155e7a2fcc", size = 405757, upload-time = "2025-06-15T19:04:51.058Z" }, + { url = "https://files.pythonhosted.org/packages/1c/a0/7a0318cd874393344d48c34d53b3dd419466adf59a29ba5b51c88dd18b86/watchfiles-1.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3366f56c272232860ab45c77c3ca7b74ee819c8e1f6f35a7125556b198bbc6df", size = 397511, upload-time = "2025-06-15T19:04:52.79Z" }, + { url = "https://files.pythonhosted.org/packages/06/be/503514656d0555ec2195f60d810eca29b938772e9bfb112d5cd5ad6f6a9e/watchfiles-1.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8412eacef34cae2836d891836a7fff7b754d6bcac61f6c12ba5ca9bc7e427b68", size = 450739, upload-time = "2025-06-15T19:04:54.203Z" }, + { url = "https://files.pythonhosted.org/packages/4e/0d/a05dd9e5f136cdc29751816d0890d084ab99f8c17b86f25697288ca09bc7/watchfiles-1.1.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:df670918eb7dd719642e05979fc84704af913d563fd17ed636f7c4783003fdcc", size = 458106, upload-time = "2025-06-15T19:04:55.607Z" }, + { url = "https://files.pythonhosted.org/packages/f1/fa/9cd16e4dfdb831072b7ac39e7bea986e52128526251038eb481effe9f48e/watchfiles-1.1.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d7642b9bc4827b5518ebdb3b82698ada8c14c7661ddec5fe719f3e56ccd13c97", size = 484264, upload-time = "2025-06-15T19:04:57.009Z" }, + { url = "https://files.pythonhosted.org/packages/32/04/1da8a637c7e2b70e750a0308e9c8e662ada0cca46211fa9ef24a23937e0b/watchfiles-1.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:199207b2d3eeaeb80ef4411875a6243d9ad8bc35b07fc42daa6b801cc39cc41c", size = 597612, upload-time = "2025-06-15T19:04:58.409Z" }, + { url = "https://files.pythonhosted.org/packages/30/01/109f2762e968d3e58c95731a206e5d7d2a7abaed4299dd8a94597250153c/watchfiles-1.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a479466da6db5c1e8754caee6c262cd373e6e6c363172d74394f4bff3d84d7b5", size = 477242, upload-time = "2025-06-15T19:04:59.786Z" }, + { url = "https://files.pythonhosted.org/packages/b5/b8/46f58cf4969d3b7bc3ca35a98e739fa4085b0657a1540ccc29a1a0bc016f/watchfiles-1.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:935f9edd022ec13e447e5723a7d14456c8af254544cefbc533f6dd276c9aa0d9", size = 453148, upload-time = "2025-06-15T19:05:01.103Z" }, + { url = "https://files.pythonhosted.org/packages/a5/cd/8267594263b1770f1eb76914940d7b2d03ee55eca212302329608208e061/watchfiles-1.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8076a5769d6bdf5f673a19d51da05fc79e2bbf25e9fe755c47595785c06a8c72", size = 626574, upload-time = "2025-06-15T19:05:02.582Z" }, + { url = "https://files.pythonhosted.org/packages/a1/2f/7f2722e85899bed337cba715723e19185e288ef361360718973f891805be/watchfiles-1.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:86b1e28d4c37e89220e924305cd9f82866bb0ace666943a6e4196c5df4d58dcc", size = 624378, upload-time = "2025-06-15T19:05:03.719Z" }, + { url = "https://files.pythonhosted.org/packages/bf/20/64c88ec43d90a568234d021ab4b2a6f42a5230d772b987c3f9c00cc27b8b/watchfiles-1.1.0-cp310-cp310-win32.whl", hash = "sha256:d1caf40c1c657b27858f9774d5c0e232089bca9cb8ee17ce7478c6e9264d2587", size = 279829, upload-time = "2025-06-15T19:05:04.822Z" }, + { url = "https://files.pythonhosted.org/packages/39/5c/a9c1ed33de7af80935e4eac09570de679c6e21c07070aa99f74b4431f4d6/watchfiles-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:a89c75a5b9bc329131115a409d0acc16e8da8dfd5867ba59f1dd66ae7ea8fa82", size = 292192, upload-time = "2025-06-15T19:05:06.348Z" }, + { url = "https://files.pythonhosted.org/packages/8b/78/7401154b78ab484ccaaeef970dc2af0cb88b5ba8a1b415383da444cdd8d3/watchfiles-1.1.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:c9649dfc57cc1f9835551deb17689e8d44666315f2e82d337b9f07bd76ae3aa2", size = 405751, upload-time = "2025-06-15T19:05:07.679Z" }, + { url = "https://files.pythonhosted.org/packages/76/63/e6c3dbc1f78d001589b75e56a288c47723de28c580ad715eb116639152b5/watchfiles-1.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:406520216186b99374cdb58bc48e34bb74535adec160c8459894884c983a149c", size = 397313, upload-time = "2025-06-15T19:05:08.764Z" }, + { url = "https://files.pythonhosted.org/packages/6c/a2/8afa359ff52e99af1632f90cbf359da46184207e893a5f179301b0c8d6df/watchfiles-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb45350fd1dc75cd68d3d72c47f5b513cb0578da716df5fba02fff31c69d5f2d", size = 450792, upload-time = "2025-06-15T19:05:09.869Z" }, + { url = "https://files.pythonhosted.org/packages/1d/bf/7446b401667f5c64972a57a0233be1104157fc3abf72c4ef2666c1bd09b2/watchfiles-1.1.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:11ee4444250fcbeb47459a877e5e80ed994ce8e8d20283857fc128be1715dac7", size = 458196, upload-time = "2025-06-15T19:05:11.91Z" }, + { url = "https://files.pythonhosted.org/packages/58/2f/501ddbdfa3fa874ea5597c77eeea3d413579c29af26c1091b08d0c792280/watchfiles-1.1.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bda8136e6a80bdea23e5e74e09df0362744d24ffb8cd59c4a95a6ce3d142f79c", size = 484788, upload-time = "2025-06-15T19:05:13.373Z" }, + { url = "https://files.pythonhosted.org/packages/61/1e/9c18eb2eb5c953c96bc0e5f626f0e53cfef4bd19bd50d71d1a049c63a575/watchfiles-1.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b915daeb2d8c1f5cee4b970f2e2c988ce6514aace3c9296e58dd64dc9aa5d575", size = 597879, upload-time = "2025-06-15T19:05:14.725Z" }, + { url = "https://files.pythonhosted.org/packages/8b/6c/1467402e5185d89388b4486745af1e0325007af0017c3384cc786fff0542/watchfiles-1.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ed8fc66786de8d0376f9f913c09e963c66e90ced9aa11997f93bdb30f7c872a8", size = 477447, upload-time = "2025-06-15T19:05:15.775Z" }, + { url = "https://files.pythonhosted.org/packages/2b/a1/ec0a606bde4853d6c4a578f9391eeb3684a9aea736a8eb217e3e00aa89a1/watchfiles-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe4371595edf78c41ef8ac8df20df3943e13defd0efcb732b2e393b5a8a7a71f", size = 453145, upload-time = "2025-06-15T19:05:17.17Z" }, + { url = "https://files.pythonhosted.org/packages/90/b9/ef6f0c247a6a35d689fc970dc7f6734f9257451aefb30def5d100d6246a5/watchfiles-1.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b7c5f6fe273291f4d414d55b2c80d33c457b8a42677ad14b4b47ff025d0893e4", size = 626539, upload-time = "2025-06-15T19:05:18.557Z" }, + { url = "https://files.pythonhosted.org/packages/34/44/6ffda5537085106ff5aaa762b0d130ac6c75a08015dd1621376f708c94de/watchfiles-1.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7738027989881e70e3723c75921f1efa45225084228788fc59ea8c6d732eb30d", size = 624472, upload-time = "2025-06-15T19:05:19.588Z" }, + { url = "https://files.pythonhosted.org/packages/c3/e3/71170985c48028fa3f0a50946916a14055e741db11c2e7bc2f3b61f4d0e3/watchfiles-1.1.0-cp311-cp311-win32.whl", hash = "sha256:622d6b2c06be19f6e89b1d951485a232e3b59618def88dbeda575ed8f0d8dbf2", size = 279348, upload-time = "2025-06-15T19:05:20.856Z" }, + { url = "https://files.pythonhosted.org/packages/89/1b/3e39c68b68a7a171070f81fc2561d23ce8d6859659406842a0e4bebf3bba/watchfiles-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:48aa25e5992b61debc908a61ab4d3f216b64f44fdaa71eb082d8b2de846b7d12", size = 292607, upload-time = "2025-06-15T19:05:21.937Z" }, + { url = "https://files.pythonhosted.org/packages/61/9f/2973b7539f2bdb6ea86d2c87f70f615a71a1fc2dba2911795cea25968aea/watchfiles-1.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:00645eb79a3faa70d9cb15c8d4187bb72970b2470e938670240c7998dad9f13a", size = 285056, upload-time = "2025-06-15T19:05:23.12Z" }, + { url = "https://files.pythonhosted.org/packages/f6/b8/858957045a38a4079203a33aaa7d23ea9269ca7761c8a074af3524fbb240/watchfiles-1.1.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9dc001c3e10de4725c749d4c2f2bdc6ae24de5a88a339c4bce32300a31ede179", size = 402339, upload-time = "2025-06-15T19:05:24.516Z" }, + { url = "https://files.pythonhosted.org/packages/80/28/98b222cca751ba68e88521fabd79a4fab64005fc5976ea49b53fa205d1fa/watchfiles-1.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d9ba68ec283153dead62cbe81872d28e053745f12335d037de9cbd14bd1877f5", size = 394409, upload-time = "2025-06-15T19:05:25.469Z" }, + { url = "https://files.pythonhosted.org/packages/86/50/dee79968566c03190677c26f7f47960aff738d32087087bdf63a5473e7df/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:130fc497b8ee68dce163e4254d9b0356411d1490e868bd8790028bc46c5cc297", size = 450939, upload-time = "2025-06-15T19:05:26.494Z" }, + { url = "https://files.pythonhosted.org/packages/40/45/a7b56fb129700f3cfe2594a01aa38d033b92a33dddce86c8dfdfc1247b72/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:50a51a90610d0845a5931a780d8e51d7bd7f309ebc25132ba975aca016b576a0", size = 457270, upload-time = "2025-06-15T19:05:27.466Z" }, + { url = "https://files.pythonhosted.org/packages/b5/c8/fa5ef9476b1d02dc6b5e258f515fcaaecf559037edf8b6feffcbc097c4b8/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc44678a72ac0910bac46fa6a0de6af9ba1355669b3dfaf1ce5f05ca7a74364e", size = 483370, upload-time = "2025-06-15T19:05:28.548Z" }, + { url = "https://files.pythonhosted.org/packages/98/68/42cfcdd6533ec94f0a7aab83f759ec11280f70b11bfba0b0f885e298f9bd/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a543492513a93b001975ae283a51f4b67973662a375a403ae82f420d2c7205ee", size = 598654, upload-time = "2025-06-15T19:05:29.997Z" }, + { url = "https://files.pythonhosted.org/packages/d3/74/b2a1544224118cc28df7e59008a929e711f9c68ce7d554e171b2dc531352/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ac164e20d17cc285f2b94dc31c384bc3aa3dd5e7490473b3db043dd70fbccfd", size = 478667, upload-time = "2025-06-15T19:05:31.172Z" }, + { url = "https://files.pythonhosted.org/packages/8c/77/e3362fe308358dc9f8588102481e599c83e1b91c2ae843780a7ded939a35/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7590d5a455321e53857892ab8879dce62d1f4b04748769f5adf2e707afb9d4f", size = 452213, upload-time = "2025-06-15T19:05:32.299Z" }, + { url = "https://files.pythonhosted.org/packages/6e/17/c8f1a36540c9a1558d4faf08e909399e8133599fa359bf52ec8fcee5be6f/watchfiles-1.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:37d3d3f7defb13f62ece99e9be912afe9dd8a0077b7c45ee5a57c74811d581a4", size = 626718, upload-time = "2025-06-15T19:05:33.415Z" }, + { url = "https://files.pythonhosted.org/packages/26/45/fb599be38b4bd38032643783d7496a26a6f9ae05dea1a42e58229a20ac13/watchfiles-1.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:7080c4bb3efd70a07b1cc2df99a7aa51d98685be56be6038c3169199d0a1c69f", size = 623098, upload-time = "2025-06-15T19:05:34.534Z" }, + { url = "https://files.pythonhosted.org/packages/a1/e7/fdf40e038475498e160cd167333c946e45d8563ae4dd65caf757e9ffe6b4/watchfiles-1.1.0-cp312-cp312-win32.whl", hash = "sha256:cbcf8630ef4afb05dc30107bfa17f16c0896bb30ee48fc24bf64c1f970f3b1fd", size = 279209, upload-time = "2025-06-15T19:05:35.577Z" }, + { url = "https://files.pythonhosted.org/packages/3f/d3/3ae9d5124ec75143bdf088d436cba39812122edc47709cd2caafeac3266f/watchfiles-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:cbd949bdd87567b0ad183d7676feb98136cde5bb9025403794a4c0db28ed3a47", size = 292786, upload-time = "2025-06-15T19:05:36.559Z" }, + { url = "https://files.pythonhosted.org/packages/26/2f/7dd4fc8b5f2b34b545e19629b4a018bfb1de23b3a496766a2c1165ca890d/watchfiles-1.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:0a7d40b77f07be87c6faa93d0951a0fcd8cbca1ddff60a1b65d741bac6f3a9f6", size = 284343, upload-time = "2025-06-15T19:05:37.5Z" }, + { url = "https://files.pythonhosted.org/packages/d3/42/fae874df96595556a9089ade83be34a2e04f0f11eb53a8dbf8a8a5e562b4/watchfiles-1.1.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5007f860c7f1f8df471e4e04aaa8c43673429047d63205d1630880f7637bca30", size = 402004, upload-time = "2025-06-15T19:05:38.499Z" }, + { url = "https://files.pythonhosted.org/packages/fa/55/a77e533e59c3003d9803c09c44c3651224067cbe7fb5d574ddbaa31e11ca/watchfiles-1.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:20ecc8abbd957046f1fe9562757903f5eaf57c3bce70929fda6c7711bb58074a", size = 393671, upload-time = "2025-06-15T19:05:39.52Z" }, + { url = "https://files.pythonhosted.org/packages/05/68/b0afb3f79c8e832e6571022611adbdc36e35a44e14f129ba09709aa4bb7a/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2f0498b7d2a3c072766dba3274fe22a183dbea1f99d188f1c6c72209a1063dc", size = 449772, upload-time = "2025-06-15T19:05:40.897Z" }, + { url = "https://files.pythonhosted.org/packages/ff/05/46dd1f6879bc40e1e74c6c39a1b9ab9e790bf1f5a2fe6c08b463d9a807f4/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:239736577e848678e13b201bba14e89718f5c2133dfd6b1f7846fa1b58a8532b", size = 456789, upload-time = "2025-06-15T19:05:42.045Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ca/0eeb2c06227ca7f12e50a47a3679df0cd1ba487ea19cf844a905920f8e95/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eff4b8d89f444f7e49136dc695599a591ff769300734446c0a86cba2eb2f9895", size = 482551, upload-time = "2025-06-15T19:05:43.781Z" }, + { url = "https://files.pythonhosted.org/packages/31/47/2cecbd8694095647406645f822781008cc524320466ea393f55fe70eed3b/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:12b0a02a91762c08f7264e2e79542f76870c3040bbc847fb67410ab81474932a", size = 597420, upload-time = "2025-06-15T19:05:45.244Z" }, + { url = "https://files.pythonhosted.org/packages/d9/7e/82abc4240e0806846548559d70f0b1a6dfdca75c1b4f9fa62b504ae9b083/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:29e7bc2eee15cbb339c68445959108803dc14ee0c7b4eea556400131a8de462b", size = 477950, upload-time = "2025-06-15T19:05:46.332Z" }, + { url = "https://files.pythonhosted.org/packages/25/0d/4d564798a49bf5482a4fa9416dea6b6c0733a3b5700cb8a5a503c4b15853/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9481174d3ed982e269c090f780122fb59cee6c3796f74efe74e70f7780ed94c", size = 451706, upload-time = "2025-06-15T19:05:47.459Z" }, + { url = "https://files.pythonhosted.org/packages/81/b5/5516cf46b033192d544102ea07c65b6f770f10ed1d0a6d388f5d3874f6e4/watchfiles-1.1.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:80f811146831c8c86ab17b640801c25dc0a88c630e855e2bef3568f30434d52b", size = 625814, upload-time = "2025-06-15T19:05:48.654Z" }, + { url = "https://files.pythonhosted.org/packages/0c/dd/7c1331f902f30669ac3e754680b6edb9a0dd06dea5438e61128111fadd2c/watchfiles-1.1.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:60022527e71d1d1fda67a33150ee42869042bce3d0fcc9cc49be009a9cded3fb", size = 622820, upload-time = "2025-06-15T19:05:50.088Z" }, + { url = "https://files.pythonhosted.org/packages/1b/14/36d7a8e27cd128d7b1009e7715a7c02f6c131be9d4ce1e5c3b73d0e342d8/watchfiles-1.1.0-cp313-cp313-win32.whl", hash = "sha256:32d6d4e583593cb8576e129879ea0991660b935177c0f93c6681359b3654bfa9", size = 279194, upload-time = "2025-06-15T19:05:51.186Z" }, + { url = "https://files.pythonhosted.org/packages/25/41/2dd88054b849aa546dbeef5696019c58f8e0774f4d1c42123273304cdb2e/watchfiles-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:f21af781a4a6fbad54f03c598ab620e3a77032c5878f3d780448421a6e1818c7", size = 292349, upload-time = "2025-06-15T19:05:52.201Z" }, + { url = "https://files.pythonhosted.org/packages/c8/cf/421d659de88285eb13941cf11a81f875c176f76a6d99342599be88e08d03/watchfiles-1.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:5366164391873ed76bfdf618818c82084c9db7fac82b64a20c44d335eec9ced5", size = 283836, upload-time = "2025-06-15T19:05:53.265Z" }, + { url = "https://files.pythonhosted.org/packages/45/10/6faf6858d527e3599cc50ec9fcae73590fbddc1420bd4fdccfebffeedbc6/watchfiles-1.1.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:17ab167cca6339c2b830b744eaf10803d2a5b6683be4d79d8475d88b4a8a4be1", size = 400343, upload-time = "2025-06-15T19:05:54.252Z" }, + { url = "https://files.pythonhosted.org/packages/03/20/5cb7d3966f5e8c718006d0e97dfe379a82f16fecd3caa7810f634412047a/watchfiles-1.1.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:328dbc9bff7205c215a7807da7c18dce37da7da718e798356212d22696404339", size = 392916, upload-time = "2025-06-15T19:05:55.264Z" }, + { url = "https://files.pythonhosted.org/packages/8c/07/d8f1176328fa9e9581b6f120b017e286d2a2d22ae3f554efd9515c8e1b49/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7208ab6e009c627b7557ce55c465c98967e8caa8b11833531fdf95799372633", size = 449582, upload-time = "2025-06-15T19:05:56.317Z" }, + { url = "https://files.pythonhosted.org/packages/66/e8/80a14a453cf6038e81d072a86c05276692a1826471fef91df7537dba8b46/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a8f6f72974a19efead54195bc9bed4d850fc047bb7aa971268fd9a8387c89011", size = 456752, upload-time = "2025-06-15T19:05:57.359Z" }, + { url = "https://files.pythonhosted.org/packages/5a/25/0853b3fe0e3c2f5af9ea60eb2e781eade939760239a72c2d38fc4cc335f6/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d181ef50923c29cf0450c3cd47e2f0557b62218c50b2ab8ce2ecaa02bd97e670", size = 481436, upload-time = "2025-06-15T19:05:58.447Z" }, + { url = "https://files.pythonhosted.org/packages/fe/9e/4af0056c258b861fbb29dcb36258de1e2b857be4a9509e6298abcf31e5c9/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:adb4167043d3a78280d5d05ce0ba22055c266cf8655ce942f2fb881262ff3cdf", size = 596016, upload-time = "2025-06-15T19:05:59.59Z" }, + { url = "https://files.pythonhosted.org/packages/c5/fa/95d604b58aa375e781daf350897aaaa089cff59d84147e9ccff2447c8294/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c5701dc474b041e2934a26d31d39f90fac8a3dee2322b39f7729867f932b1d4", size = 476727, upload-time = "2025-06-15T19:06:01.086Z" }, + { url = "https://files.pythonhosted.org/packages/65/95/fe479b2664f19be4cf5ceeb21be05afd491d95f142e72d26a42f41b7c4f8/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b067915e3c3936966a8607f6fe5487df0c9c4afb85226613b520890049deea20", size = 451864, upload-time = "2025-06-15T19:06:02.144Z" }, + { url = "https://files.pythonhosted.org/packages/d3/8a/3c4af14b93a15ce55901cd7a92e1a4701910f1768c78fb30f61d2b79785b/watchfiles-1.1.0-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:9c733cda03b6d636b4219625a4acb5c6ffb10803338e437fb614fef9516825ef", size = 625626, upload-time = "2025-06-15T19:06:03.578Z" }, + { url = "https://files.pythonhosted.org/packages/da/f5/cf6aa047d4d9e128f4b7cde615236a915673775ef171ff85971d698f3c2c/watchfiles-1.1.0-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:cc08ef8b90d78bfac66f0def80240b0197008e4852c9f285907377b2947ffdcb", size = 622744, upload-time = "2025-06-15T19:06:05.066Z" }, + { url = "https://files.pythonhosted.org/packages/2c/00/70f75c47f05dea6fd30df90f047765f6fc2d6eb8b5a3921379b0b04defa2/watchfiles-1.1.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:9974d2f7dc561cce3bb88dfa8eb309dab64c729de85fba32e98d75cf24b66297", size = 402114, upload-time = "2025-06-15T19:06:06.186Z" }, + { url = "https://files.pythonhosted.org/packages/53/03/acd69c48db4a1ed1de26b349d94077cca2238ff98fd64393f3e97484cae6/watchfiles-1.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c68e9f1fcb4d43798ad8814c4c1b61547b014b667216cb754e606bfade587018", size = 393879, upload-time = "2025-06-15T19:06:07.369Z" }, + { url = "https://files.pythonhosted.org/packages/2f/c8/a9a2a6f9c8baa4eceae5887fecd421e1b7ce86802bcfc8b6a942e2add834/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95ab1594377effac17110e1352989bdd7bdfca9ff0e5eeccd8c69c5389b826d0", size = 450026, upload-time = "2025-06-15T19:06:08.476Z" }, + { url = "https://files.pythonhosted.org/packages/fe/51/d572260d98388e6e2b967425c985e07d47ee6f62e6455cefb46a6e06eda5/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fba9b62da882c1be1280a7584ec4515d0a6006a94d6e5819730ec2eab60ffe12", size = 457917, upload-time = "2025-06-15T19:06:09.988Z" }, + { url = "https://files.pythonhosted.org/packages/c6/2d/4258e52917bf9f12909b6ec314ff9636276f3542f9d3807d143f27309104/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3434e401f3ce0ed6b42569128b3d1e3af773d7ec18751b918b89cd49c14eaafb", size = 483602, upload-time = "2025-06-15T19:06:11.088Z" }, + { url = "https://files.pythonhosted.org/packages/84/99/bee17a5f341a4345fe7b7972a475809af9e528deba056f8963d61ea49f75/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fa257a4d0d21fcbca5b5fcba9dca5a78011cb93c0323fb8855c6d2dfbc76eb77", size = 596758, upload-time = "2025-06-15T19:06:12.197Z" }, + { url = "https://files.pythonhosted.org/packages/40/76/e4bec1d59b25b89d2b0716b41b461ed655a9a53c60dc78ad5771fda5b3e6/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7fd1b3879a578a8ec2076c7961076df540b9af317123f84569f5a9ddee64ce92", size = 477601, upload-time = "2025-06-15T19:06:13.391Z" }, + { url = "https://files.pythonhosted.org/packages/1f/fa/a514292956f4a9ce3c567ec0c13cce427c158e9f272062685a8a727d08fc/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:62cc7a30eeb0e20ecc5f4bd113cd69dcdb745a07c68c0370cea919f373f65d9e", size = 451936, upload-time = "2025-06-15T19:06:14.656Z" }, + { url = "https://files.pythonhosted.org/packages/32/5d/c3bf927ec3bbeb4566984eba8dd7a8eb69569400f5509904545576741f88/watchfiles-1.1.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:891c69e027748b4a73847335d208e374ce54ca3c335907d381fde4e41661b13b", size = 626243, upload-time = "2025-06-15T19:06:16.232Z" }, + { url = "https://files.pythonhosted.org/packages/e6/65/6e12c042f1a68c556802a84d54bb06d35577c81e29fba14019562479159c/watchfiles-1.1.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:12fe8eaffaf0faa7906895b4f8bb88264035b3f0243275e0bf24af0436b27259", size = 623073, upload-time = "2025-06-15T19:06:17.457Z" }, + { url = "https://files.pythonhosted.org/packages/89/ab/7f79d9bf57329e7cbb0a6fd4c7bd7d0cee1e4a8ef0041459f5409da3506c/watchfiles-1.1.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:bfe3c517c283e484843cb2e357dd57ba009cff351edf45fb455b5fbd1f45b15f", size = 400872, upload-time = "2025-06-15T19:06:18.57Z" }, + { url = "https://files.pythonhosted.org/packages/df/d5/3f7bf9912798e9e6c516094db6b8932df53b223660c781ee37607030b6d3/watchfiles-1.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a9ccbf1f129480ed3044f540c0fdbc4ee556f7175e5ab40fe077ff6baf286d4e", size = 392877, upload-time = "2025-06-15T19:06:19.55Z" }, + { url = "https://files.pythonhosted.org/packages/0d/c5/54ec7601a2798604e01c75294770dbee8150e81c6e471445d7601610b495/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba0e3255b0396cac3cc7bbace76404dd72b5438bf0d8e7cefa2f79a7f3649caa", size = 449645, upload-time = "2025-06-15T19:06:20.66Z" }, + { url = "https://files.pythonhosted.org/packages/0a/04/c2f44afc3b2fce21ca0b7802cbd37ed90a29874f96069ed30a36dfe57c2b/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4281cd9fce9fc0a9dbf0fc1217f39bf9cf2b4d315d9626ef1d4e87b84699e7e8", size = 457424, upload-time = "2025-06-15T19:06:21.712Z" }, + { url = "https://files.pythonhosted.org/packages/9f/b0/eec32cb6c14d248095261a04f290636da3df3119d4040ef91a4a50b29fa5/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6d2404af8db1329f9a3c9b79ff63e0ae7131986446901582067d9304ae8aaf7f", size = 481584, upload-time = "2025-06-15T19:06:22.777Z" }, + { url = "https://files.pythonhosted.org/packages/d1/e2/ca4bb71c68a937d7145aa25709e4f5d68eb7698a25ce266e84b55d591bbd/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e78b6ed8165996013165eeabd875c5dfc19d41b54f94b40e9fff0eb3193e5e8e", size = 596675, upload-time = "2025-06-15T19:06:24.226Z" }, + { url = "https://files.pythonhosted.org/packages/a1/dd/b0e4b7fb5acf783816bc950180a6cd7c6c1d2cf7e9372c0ea634e722712b/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:249590eb75ccc117f488e2fabd1bfa33c580e24b96f00658ad88e38844a040bb", size = 477363, upload-time = "2025-06-15T19:06:25.42Z" }, + { url = "https://files.pythonhosted.org/packages/69/c4/088825b75489cb5b6a761a4542645718893d395d8c530b38734f19da44d2/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d05686b5487cfa2e2c28ff1aa370ea3e6c5accfe6435944ddea1e10d93872147", size = 452240, upload-time = "2025-06-15T19:06:26.552Z" }, + { url = "https://files.pythonhosted.org/packages/10/8c/22b074814970eeef43b7c44df98c3e9667c1f7bf5b83e0ff0201b0bd43f9/watchfiles-1.1.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:d0e10e6f8f6dc5762adee7dece33b722282e1f59aa6a55da5d493a97282fedd8", size = 625607, upload-time = "2025-06-15T19:06:27.606Z" }, + { url = "https://files.pythonhosted.org/packages/32/fa/a4f5c2046385492b2273213ef815bf71a0d4c1943b784fb904e184e30201/watchfiles-1.1.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:af06c863f152005c7592df1d6a7009c836a247c9d8adb78fef8575a5a98699db", size = 623315, upload-time = "2025-06-15T19:06:29.076Z" }, + { url = "https://files.pythonhosted.org/packages/47/8a/a45db804b9f0740f8408626ab2bca89c3136432e57c4673b50180bf85dd9/watchfiles-1.1.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:865c8e95713744cf5ae261f3067861e9da5f1370ba91fc536431e29b418676fa", size = 406400, upload-time = "2025-06-15T19:06:30.233Z" }, + { url = "https://files.pythonhosted.org/packages/64/06/a08684f628fb41addd451845aceedc2407dc3d843b4b060a7c4350ddee0c/watchfiles-1.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:42f92befc848bb7a19658f21f3e7bae80d7d005d13891c62c2cd4d4d0abb3433", size = 397920, upload-time = "2025-06-15T19:06:31.315Z" }, + { url = "https://files.pythonhosted.org/packages/79/e6/e10d5675af653b1b07d4156906858041149ca222edaf8995877f2605ba9e/watchfiles-1.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa0cc8365ab29487eb4f9979fd41b22549853389e22d5de3f134a6796e1b05a4", size = 451196, upload-time = "2025-06-15T19:06:32.435Z" }, + { url = "https://files.pythonhosted.org/packages/f6/8a/facd6988100cd0f39e89f6c550af80edb28e3a529e1ee662e750663e6b36/watchfiles-1.1.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:90ebb429e933645f3da534c89b29b665e285048973b4d2b6946526888c3eb2c7", size = 458218, upload-time = "2025-06-15T19:06:33.503Z" }, + { url = "https://files.pythonhosted.org/packages/90/26/34cbcbc4d0f2f8f9cc243007e65d741ae039f7a11ef8ec6e9cd25bee08d1/watchfiles-1.1.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c588c45da9b08ab3da81d08d7987dae6d2a3badd63acdb3e206a42dbfa7cb76f", size = 484851, upload-time = "2025-06-15T19:06:34.541Z" }, + { url = "https://files.pythonhosted.org/packages/d7/1f/f59faa9fc4b0e36dbcdd28a18c430416443b309d295d8b82e18192d120ad/watchfiles-1.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7c55b0f9f68590115c25272b06e63f0824f03d4fc7d6deed43d8ad5660cabdbf", size = 599520, upload-time = "2025-06-15T19:06:35.785Z" }, + { url = "https://files.pythonhosted.org/packages/83/72/3637abecb3bf590529f5154ca000924003e5f4bbb9619744feeaf6f0b70b/watchfiles-1.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd17a1e489f02ce9117b0de3c0b1fab1c3e2eedc82311b299ee6b6faf6c23a29", size = 477956, upload-time = "2025-06-15T19:06:36.965Z" }, + { url = "https://files.pythonhosted.org/packages/f7/f3/d14ffd9acc0c1bd4790378995e320981423263a5d70bd3929e2e0dc87fff/watchfiles-1.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da71945c9ace018d8634822f16cbc2a78323ef6c876b1d34bbf5d5222fd6a72e", size = 453196, upload-time = "2025-06-15T19:06:38.024Z" }, + { url = "https://files.pythonhosted.org/packages/7f/38/78ad77bd99e20c0fdc82262be571ef114fc0beef9b43db52adb939768c38/watchfiles-1.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:51556d5004887045dba3acdd1fdf61dddea2be0a7e18048b5e853dcd37149b86", size = 627479, upload-time = "2025-06-15T19:06:39.442Z" }, + { url = "https://files.pythonhosted.org/packages/e6/cf/549d50a22fcc83f1017c6427b1c76c053233f91b526f4ad7a45971e70c0b/watchfiles-1.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04e4ed5d1cd3eae68c89bcc1a485a109f39f2fd8de05f705e98af6b5f1861f1f", size = 624414, upload-time = "2025-06-15T19:06:40.859Z" }, + { url = "https://files.pythonhosted.org/packages/72/de/57d6e40dc9140af71c12f3a9fc2d3efc5529d93981cd4d265d484d7c9148/watchfiles-1.1.0-cp39-cp39-win32.whl", hash = "sha256:c600e85f2ffd9f1035222b1a312aff85fd11ea39baff1d705b9b047aad2ce267", size = 280020, upload-time = "2025-06-15T19:06:41.89Z" }, + { url = "https://files.pythonhosted.org/packages/88/bb/7d287fc2a762396b128a0fca2dbae29386e0a242b81d1046daf389641db3/watchfiles-1.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:3aba215958d88182e8d2acba0fdaf687745180974946609119953c0e112397dc", size = 292758, upload-time = "2025-06-15T19:06:43.251Z" }, + { url = "https://files.pythonhosted.org/packages/be/7c/a3d7c55cfa377c2f62c4ae3c6502b997186bc5e38156bafcb9b653de9a6d/watchfiles-1.1.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3a6fd40bbb50d24976eb275ccb55cd1951dfb63dbc27cae3066a6ca5f4beabd5", size = 406748, upload-time = "2025-06-15T19:06:44.2Z" }, + { url = "https://files.pythonhosted.org/packages/38/d0/c46f1b2c0ca47f3667b144de6f0515f6d1c670d72f2ca29861cac78abaa1/watchfiles-1.1.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9f811079d2f9795b5d48b55a37aa7773680a5659afe34b54cc1d86590a51507d", size = 398801, upload-time = "2025-06-15T19:06:45.774Z" }, + { url = "https://files.pythonhosted.org/packages/70/9c/9a6a42e97f92eeed77c3485a43ea96723900aefa3ac739a8c73f4bff2cd7/watchfiles-1.1.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a2726d7bfd9f76158c84c10a409b77a320426540df8c35be172444394b17f7ea", size = 451528, upload-time = "2025-06-15T19:06:46.791Z" }, + { url = "https://files.pythonhosted.org/packages/51/7b/98c7f4f7ce7ff03023cf971cd84a3ee3b790021ae7584ffffa0eb2554b96/watchfiles-1.1.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df32d59cb9780f66d165a9a7a26f19df2c7d24e3bd58713108b41d0ff4f929c6", size = 454095, upload-time = "2025-06-15T19:06:48.211Z" }, + { url = "https://files.pythonhosted.org/packages/8c/6b/686dcf5d3525ad17b384fd94708e95193529b460a1b7bf40851f1328ec6e/watchfiles-1.1.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0ece16b563b17ab26eaa2d52230c9a7ae46cf01759621f4fbbca280e438267b3", size = 406910, upload-time = "2025-06-15T19:06:49.335Z" }, + { url = "https://files.pythonhosted.org/packages/f3/d3/71c2dcf81dc1edcf8af9f4d8d63b1316fb0a2dd90cbfd427e8d9dd584a90/watchfiles-1.1.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:51b81e55d40c4b4aa8658427a3ee7ea847c591ae9e8b81ef94a90b668999353c", size = 398816, upload-time = "2025-06-15T19:06:50.433Z" }, + { url = "https://files.pythonhosted.org/packages/b8/fa/12269467b2fc006f8fce4cd6c3acfa77491dd0777d2a747415f28ccc8c60/watchfiles-1.1.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2bcdc54ea267fe72bfc7d83c041e4eb58d7d8dc6f578dfddb52f037ce62f432", size = 451584, upload-time = "2025-06-15T19:06:51.834Z" }, + { url = "https://files.pythonhosted.org/packages/bd/d3/254cea30f918f489db09d6a8435a7de7047f8cb68584477a515f160541d6/watchfiles-1.1.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:923fec6e5461c42bd7e3fd5ec37492c6f3468be0499bc0707b4bbbc16ac21792", size = 454009, upload-time = "2025-06-15T19:06:52.896Z" }, + { url = "https://files.pythonhosted.org/packages/48/93/5c96bdb65e7f88f7da40645f34c0a3c317a2931ed82161e93c91e8eddd27/watchfiles-1.1.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7b3443f4ec3ba5aa00b0e9fa90cf31d98321cbff8b925a7c7b84161619870bc9", size = 406640, upload-time = "2025-06-15T19:06:54.868Z" }, + { url = "https://files.pythonhosted.org/packages/e3/25/09204836e93e1b99cce88802ce87264a1d20610c7a8f6de24def27ad95b1/watchfiles-1.1.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7049e52167fc75fc3cc418fc13d39a8e520cbb60ca08b47f6cedb85e181d2f2a", size = 398543, upload-time = "2025-06-15T19:06:55.95Z" }, + { url = "https://files.pythonhosted.org/packages/5e/dc/6f324a6f32c5ab73b54311b5f393a79df34c1584b8d2404cf7e6d780aa5d/watchfiles-1.1.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54062ef956807ba806559b3c3d52105ae1827a0d4ab47b621b31132b6b7e2866", size = 451787, upload-time = "2025-06-15T19:06:56.998Z" }, + { url = "https://files.pythonhosted.org/packages/45/5d/1d02ef4caa4ec02389e72d5594cdf9c67f1800a7c380baa55063c30c6598/watchfiles-1.1.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a7bd57a1bb02f9d5c398c0c1675384e7ab1dd39da0ca50b7f09af45fa435277", size = 454272, upload-time = "2025-06-15T19:06:58.055Z" }, ] [[package]] @@ -3444,11 +3487,11 @@ wheels = [ [[package]] name = "zipp" -version = "3.22.0" +version = "3.23.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/12/b6/7b3d16792fdf94f146bed92be90b4eb4563569eca91513c8609aebf0c167/zipp-3.22.0.tar.gz", hash = "sha256:dd2f28c3ce4bc67507bfd3781d21b7bb2be31103b51a4553ad7d90b84e57ace5", size = 25257, upload-time = "2025-05-26T14:46:32.217Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e3/02/0f2892c661036d50ede074e376733dca2ae7c6eb617489437771209d4180/zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166", size = 25547, upload-time = "2025-06-08T17:06:39.4Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ad/da/f64669af4cae46f17b90798a827519ce3737d31dbafad65d391e49643dc4/zipp-3.22.0-py3-none-any.whl", hash = "sha256:fe208f65f2aca48b81f9e6fd8cf7b8b32c26375266b009b413d45306b6148343", size = 9796, upload-time = "2025-05-26T14:46:30.775Z" }, + { url = "https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e", size = 10276, upload-time = "2025-06-08T17:06:38.034Z" }, ] [[package]] diff --git a/libs/prebuilt/uv.lock b/libs/prebuilt/uv.lock index 7d399a39f..4fbe095ef 100644 --- a/libs/prebuilt/uv.lock +++ b/libs/prebuilt/uv.lock @@ -1,10 +1,6 @@ version = 1 revision = 2 requires-python = ">=3.9" -resolution-markers = [ - "python_full_version >= '3.12.4'", - "python_full_version < '3.12.4'", -] [[package]] name = "aiosqlite" @@ -44,11 +40,11 @@ wheels = [ [[package]] name = "certifi" -version = "2025.4.26" +version = "2025.6.15" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e8/9e/c05b3920a3b7d20d3d3310465f50348e5b3694f4f88c6daf736eef3024c4/certifi-2025.4.26.tar.gz", hash = "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6", size = 160705, upload-time = "2025-04-26T02:12:29.51Z" } +sdist = { url = "https://files.pythonhosted.org/packages/73/f7/f14b46d4bcd21092d7d3ccef689615220d8a08fb25e564b65d20738e672e/certifi-2025.6.15.tar.gz", hash = "sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b", size = 158753, upload-time = "2025-06-15T02:45:51.329Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4a/7e/3db2bd1b1f9e95f7cddca6d6e75e2f2bd9f51b1246e546d88addca0106bd/certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3", size = 159618, upload-time = "2025-04-26T02:12:27.662Z" }, + { url = "https://files.pythonhosted.org/packages/84/ae/320161bd181fc06471eed047ecce67b693fd7515b16d495d8932db763426/certifi-2025.6.15-py3-none-any.whl", hash = "sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057", size = 157650, upload-time = "2025-06-15T02:45:49.977Z" }, ] [[package]] @@ -217,7 +213,7 @@ name = "exceptiongroup" version = "1.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.12.4'" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" } wheels = [ @@ -302,7 +298,7 @@ wheels = [ [[package]] name = "langchain-core" -version = "0.3.67" +version = "0.3.68" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jsonpatch" }, @@ -313,9 +309,9 @@ dependencies = [ { name = "tenacity" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c2/40/875af0194024d0006874f061958fa417d3500bbfdc9a57e1bd1c2f4e6ed2/langchain_core-0.3.67.tar.gz", hash = "sha256:2c14aa44a0e78e014e96d7f2f8916ac109d0a0ba87ed67ee25bf7296bed7e7ba", size = 561952, upload-time = "2025-06-30T17:09:35.142Z" } +sdist = { url = "https://files.pythonhosted.org/packages/23/20/f5b18a17bfbe3416177e702ab2fd230b7d168abb17be31fb48f43f0bb772/langchain_core-0.3.68.tar.gz", hash = "sha256:312e1932ac9aa2eaf111b70fdc171776fa571d1a86c1f873dcac88a094b19c6f", size = 563041, upload-time = "2025-07-03T17:02:28.704Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9f/2b/a0d283089c6d08c12d47dca39a55029ff714e939ec04f4560420426ab613/langchain_core-0.3.67-py3-none-any.whl", hash = "sha256:b699f1f24b24fa2747c05e2daa280aa64478a51e01a4e82c7f8e20b6167dfa99", size = 440237, upload-time = "2025-06-30T17:09:33.323Z" }, + { url = "https://files.pythonhosted.org/packages/f9/da/c89be0a272993bfcb762b2a356b9f55de507784c2755ad63caec25d183bf/langchain_core-0.3.68-py3-none-any.whl", hash = "sha256:5e5c1fbef419590537c91b8c2d86af896fbcbaf0d5ed7fdcdd77f7d8f3467ba0", size = 441405, upload-time = "2025-07-03T17:02:27.115Z" }, ] [[package]] @@ -555,46 +551,47 @@ wheels = [ [[package]] name = "mypy" -version = "1.15.0" +version = "1.16.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "mypy-extensions" }, + { name = "pathspec" }, { name = "tomli", marker = "python_full_version < '3.11'" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ce/43/d5e49a86afa64bd3839ea0d5b9c7103487007d728e1293f52525d6d5486a/mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43", size = 3239717, upload-time = "2025-02-05T03:50:34.655Z" } +sdist = { url = "https://files.pythonhosted.org/packages/81/69/92c7fa98112e4d9eb075a239caa4ef4649ad7d441545ccffbd5e34607cbb/mypy-1.16.1.tar.gz", hash = "sha256:6bd00a0a2094841c5e47e7374bb42b83d64c527a502e3334e1173a0c24437bab", size = 3324747, upload-time = "2025-06-16T16:51:35.145Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/68/f8/65a7ce8d0e09b6329ad0c8d40330d100ea343bd4dd04c4f8ae26462d0a17/mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13", size = 10738433, upload-time = "2025-02-05T03:49:29.145Z" }, - { url = "https://files.pythonhosted.org/packages/b4/95/9c0ecb8eacfe048583706249439ff52105b3f552ea9c4024166c03224270/mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559", size = 9861472, upload-time = "2025-02-05T03:49:16.986Z" }, - { url = "https://files.pythonhosted.org/packages/84/09/9ec95e982e282e20c0d5407bc65031dfd0f0f8ecc66b69538296e06fcbee/mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b", size = 11611424, upload-time = "2025-02-05T03:49:46.908Z" }, - { url = "https://files.pythonhosted.org/packages/78/13/f7d14e55865036a1e6a0a69580c240f43bc1f37407fe9235c0d4ef25ffb0/mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3", size = 12365450, upload-time = "2025-02-05T03:50:05.89Z" }, - { url = "https://files.pythonhosted.org/packages/48/e1/301a73852d40c241e915ac6d7bcd7fedd47d519246db2d7b86b9d7e7a0cb/mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b", size = 12551765, upload-time = "2025-02-05T03:49:33.56Z" }, - { url = "https://files.pythonhosted.org/packages/77/ba/c37bc323ae5fe7f3f15a28e06ab012cd0b7552886118943e90b15af31195/mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828", size = 9274701, upload-time = "2025-02-05T03:49:38.981Z" }, - { url = "https://files.pythonhosted.org/packages/03/bc/f6339726c627bd7ca1ce0fa56c9ae2d0144604a319e0e339bdadafbbb599/mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f", size = 10662338, upload-time = "2025-02-05T03:50:17.287Z" }, - { url = "https://files.pythonhosted.org/packages/e2/90/8dcf506ca1a09b0d17555cc00cd69aee402c203911410136cd716559efe7/mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5", size = 9787540, upload-time = "2025-02-05T03:49:51.21Z" }, - { url = "https://files.pythonhosted.org/packages/05/05/a10f9479681e5da09ef2f9426f650d7b550d4bafbef683b69aad1ba87457/mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e", size = 11538051, upload-time = "2025-02-05T03:50:20.885Z" }, - { url = "https://files.pythonhosted.org/packages/e9/9a/1f7d18b30edd57441a6411fcbc0c6869448d1a4bacbaee60656ac0fc29c8/mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c", size = 12286751, upload-time = "2025-02-05T03:49:42.408Z" }, - { url = "https://files.pythonhosted.org/packages/72/af/19ff499b6f1dafcaf56f9881f7a965ac2f474f69f6f618b5175b044299f5/mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f", size = 12421783, upload-time = "2025-02-05T03:49:07.707Z" }, - { url = "https://files.pythonhosted.org/packages/96/39/11b57431a1f686c1aed54bf794870efe0f6aeca11aca281a0bd87a5ad42c/mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f", size = 9265618, upload-time = "2025-02-05T03:49:54.581Z" }, - { url = "https://files.pythonhosted.org/packages/98/3a/03c74331c5eb8bd025734e04c9840532226775c47a2c39b56a0c8d4f128d/mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd", size = 10793981, upload-time = "2025-02-05T03:50:28.25Z" }, - { url = "https://files.pythonhosted.org/packages/f0/1a/41759b18f2cfd568848a37c89030aeb03534411eef981df621d8fad08a1d/mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f", size = 9749175, upload-time = "2025-02-05T03:50:13.411Z" }, - { url = "https://files.pythonhosted.org/packages/12/7e/873481abf1ef112c582db832740f4c11b2bfa510e829d6da29b0ab8c3f9c/mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464", size = 11455675, upload-time = "2025-02-05T03:50:31.421Z" }, - { url = "https://files.pythonhosted.org/packages/b3/d0/92ae4cde706923a2d3f2d6c39629134063ff64b9dedca9c1388363da072d/mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee", size = 12410020, upload-time = "2025-02-05T03:48:48.705Z" }, - { url = "https://files.pythonhosted.org/packages/46/8b/df49974b337cce35f828ba6fda228152d6db45fed4c86ba56ffe442434fd/mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e", size = 12498582, upload-time = "2025-02-05T03:49:03.628Z" }, - { url = "https://files.pythonhosted.org/packages/13/50/da5203fcf6c53044a0b699939f31075c45ae8a4cadf538a9069b165c1050/mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22", size = 9366614, upload-time = "2025-02-05T03:50:00.313Z" }, - { url = "https://files.pythonhosted.org/packages/6a/9b/fd2e05d6ffff24d912f150b87db9e364fa8282045c875654ce7e32fffa66/mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445", size = 10788592, upload-time = "2025-02-05T03:48:55.789Z" }, - { url = "https://files.pythonhosted.org/packages/74/37/b246d711c28a03ead1fd906bbc7106659aed7c089d55fe40dd58db812628/mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d", size = 9753611, upload-time = "2025-02-05T03:48:44.581Z" }, - { url = "https://files.pythonhosted.org/packages/a6/ac/395808a92e10cfdac8003c3de9a2ab6dc7cde6c0d2a4df3df1b815ffd067/mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5", size = 11438443, upload-time = "2025-02-05T03:49:25.514Z" }, - { url = "https://files.pythonhosted.org/packages/d2/8b/801aa06445d2de3895f59e476f38f3f8d610ef5d6908245f07d002676cbf/mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036", size = 12402541, upload-time = "2025-02-05T03:49:57.623Z" }, - { url = "https://files.pythonhosted.org/packages/c7/67/5a4268782eb77344cc613a4cf23540928e41f018a9a1ec4c6882baf20ab8/mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357", size = 12494348, upload-time = "2025-02-05T03:48:52.361Z" }, - { url = "https://files.pythonhosted.org/packages/83/3e/57bb447f7bbbfaabf1712d96f9df142624a386d98fb026a761532526057e/mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf", size = 9373648, upload-time = "2025-02-05T03:49:11.395Z" }, - { url = "https://files.pythonhosted.org/packages/5a/fa/79cf41a55b682794abe71372151dbbf856e3008f6767057229e6649d294a/mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078", size = 10737129, upload-time = "2025-02-05T03:50:24.509Z" }, - { url = "https://files.pythonhosted.org/packages/d3/33/dd8feb2597d648de29e3da0a8bf4e1afbda472964d2a4a0052203a6f3594/mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba", size = 9856335, upload-time = "2025-02-05T03:49:36.398Z" }, - { url = "https://files.pythonhosted.org/packages/e4/b5/74508959c1b06b96674b364ffeb7ae5802646b32929b7701fc6b18447592/mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5", size = 11611935, upload-time = "2025-02-05T03:49:14.154Z" }, - { url = "https://files.pythonhosted.org/packages/6c/53/da61b9d9973efcd6507183fdad96606996191657fe79701b2c818714d573/mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b", size = 12365827, upload-time = "2025-02-05T03:48:59.458Z" }, - { url = "https://files.pythonhosted.org/packages/c1/72/965bd9ee89540c79a25778cc080c7e6ef40aa1eeac4d52cec7eae6eb5228/mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2", size = 12541924, upload-time = "2025-02-05T03:50:03.12Z" }, - { url = "https://files.pythonhosted.org/packages/46/d0/f41645c2eb263e6c77ada7d76f894c580c9ddb20d77f0c24d34273a4dab2/mypy-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980", size = 9271176, upload-time = "2025-02-05T03:50:10.86Z" }, - { url = "https://files.pythonhosted.org/packages/09/4e/a7d65c7322c510de2c409ff3828b03354a7c43f5a8ed458a7a131b41c7b9/mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e", size = 2221777, upload-time = "2025-02-05T03:50:08.348Z" }, + { url = "https://files.pythonhosted.org/packages/8e/12/2bf23a80fcef5edb75de9a1e295d778e0f46ea89eb8b115818b663eff42b/mypy-1.16.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b4f0fed1022a63c6fec38f28b7fc77fca47fd490445c69d0a66266c59dd0b88a", size = 10958644, upload-time = "2025-06-16T16:51:11.649Z" }, + { url = "https://files.pythonhosted.org/packages/08/50/bfe47b3b278eacf348291742fd5e6613bbc4b3434b72ce9361896417cfe5/mypy-1.16.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:86042bbf9f5a05ea000d3203cf87aa9d0ccf9a01f73f71c58979eb9249f46d72", size = 10087033, upload-time = "2025-06-16T16:35:30.089Z" }, + { url = "https://files.pythonhosted.org/packages/21/de/40307c12fe25675a0776aaa2cdd2879cf30d99eec91b898de00228dc3ab5/mypy-1.16.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ea7469ee5902c95542bea7ee545f7006508c65c8c54b06dc2c92676ce526f3ea", size = 11875645, upload-time = "2025-06-16T16:35:48.49Z" }, + { url = "https://files.pythonhosted.org/packages/a6/d8/85bdb59e4a98b7a31495bd8f1a4445d8ffc86cde4ab1f8c11d247c11aedc/mypy-1.16.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:352025753ef6a83cb9e7f2427319bb7875d1fdda8439d1e23de12ab164179574", size = 12616986, upload-time = "2025-06-16T16:48:39.526Z" }, + { url = "https://files.pythonhosted.org/packages/0e/d0/bb25731158fa8f8ee9e068d3e94fcceb4971fedf1424248496292512afe9/mypy-1.16.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ff9fa5b16e4c1364eb89a4d16bcda9987f05d39604e1e6c35378a2987c1aac2d", size = 12878632, upload-time = "2025-06-16T16:36:08.195Z" }, + { url = "https://files.pythonhosted.org/packages/2d/11/822a9beb7a2b825c0cb06132ca0a5183f8327a5e23ef89717c9474ba0bc6/mypy-1.16.1-cp310-cp310-win_amd64.whl", hash = "sha256:1256688e284632382f8f3b9e2123df7d279f603c561f099758e66dd6ed4e8bd6", size = 9484391, upload-time = "2025-06-16T16:37:56.151Z" }, + { url = "https://files.pythonhosted.org/packages/9a/61/ec1245aa1c325cb7a6c0f8570a2eee3bfc40fa90d19b1267f8e50b5c8645/mypy-1.16.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:472e4e4c100062488ec643f6162dd0d5208e33e2f34544e1fc931372e806c0cc", size = 10890557, upload-time = "2025-06-16T16:37:21.421Z" }, + { url = "https://files.pythonhosted.org/packages/6b/bb/6eccc0ba0aa0c7a87df24e73f0ad34170514abd8162eb0c75fd7128171fb/mypy-1.16.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea16e2a7d2714277e349e24d19a782a663a34ed60864006e8585db08f8ad1782", size = 10012921, upload-time = "2025-06-16T16:51:28.659Z" }, + { url = "https://files.pythonhosted.org/packages/5f/80/b337a12e2006715f99f529e732c5f6a8c143bb58c92bb142d5ab380963a5/mypy-1.16.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:08e850ea22adc4d8a4014651575567b0318ede51e8e9fe7a68f25391af699507", size = 11802887, upload-time = "2025-06-16T16:50:53.627Z" }, + { url = "https://files.pythonhosted.org/packages/d9/59/f7af072d09793d581a745a25737c7c0a945760036b16aeb620f658a017af/mypy-1.16.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22d76a63a42619bfb90122889b903519149879ddbf2ba4251834727944c8baca", size = 12531658, upload-time = "2025-06-16T16:33:55.002Z" }, + { url = "https://files.pythonhosted.org/packages/82/c4/607672f2d6c0254b94a646cfc45ad589dd71b04aa1f3d642b840f7cce06c/mypy-1.16.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2c7ce0662b6b9dc8f4ed86eb7a5d505ee3298c04b40ec13b30e572c0e5ae17c4", size = 12732486, upload-time = "2025-06-16T16:37:03.301Z" }, + { url = "https://files.pythonhosted.org/packages/b6/5e/136555ec1d80df877a707cebf9081bd3a9f397dedc1ab9750518d87489ec/mypy-1.16.1-cp311-cp311-win_amd64.whl", hash = "sha256:211287e98e05352a2e1d4e8759c5490925a7c784ddc84207f4714822f8cf99b6", size = 9479482, upload-time = "2025-06-16T16:47:37.48Z" }, + { url = "https://files.pythonhosted.org/packages/b4/d6/39482e5fcc724c15bf6280ff5806548c7185e0c090712a3736ed4d07e8b7/mypy-1.16.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:af4792433f09575d9eeca5c63d7d90ca4aeceda9d8355e136f80f8967639183d", size = 11066493, upload-time = "2025-06-16T16:47:01.683Z" }, + { url = "https://files.pythonhosted.org/packages/e6/e5/26c347890efc6b757f4d5bb83f4a0cf5958b8cf49c938ac99b8b72b420a6/mypy-1.16.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:66df38405fd8466ce3517eda1f6640611a0b8e70895e2a9462d1d4323c5eb4b9", size = 10081687, upload-time = "2025-06-16T16:48:19.367Z" }, + { url = "https://files.pythonhosted.org/packages/44/c7/b5cb264c97b86914487d6a24bd8688c0172e37ec0f43e93b9691cae9468b/mypy-1.16.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44e7acddb3c48bd2713994d098729494117803616e116032af192871aed80b79", size = 11839723, upload-time = "2025-06-16T16:49:20.912Z" }, + { url = "https://files.pythonhosted.org/packages/15/f8/491997a9b8a554204f834ed4816bda813aefda31cf873bb099deee3c9a99/mypy-1.16.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0ab5eca37b50188163fa7c1b73c685ac66c4e9bdee4a85c9adac0e91d8895e15", size = 12722980, upload-time = "2025-06-16T16:37:40.929Z" }, + { url = "https://files.pythonhosted.org/packages/df/f0/2bd41e174b5fd93bc9de9a28e4fb673113633b8a7f3a607fa4a73595e468/mypy-1.16.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb6229b2c9086247e21a83c309754b9058b438704ad2f6807f0d8227f6ebdd", size = 12903328, upload-time = "2025-06-16T16:34:35.099Z" }, + { url = "https://files.pythonhosted.org/packages/61/81/5572108a7bec2c46b8aff7e9b524f371fe6ab5efb534d38d6b37b5490da8/mypy-1.16.1-cp312-cp312-win_amd64.whl", hash = "sha256:1f0435cf920e287ff68af3d10a118a73f212deb2ce087619eb4e648116d1fe9b", size = 9562321, upload-time = "2025-06-16T16:48:58.823Z" }, + { url = "https://files.pythonhosted.org/packages/28/e3/96964af4a75a949e67df4b95318fe2b7427ac8189bbc3ef28f92a1c5bc56/mypy-1.16.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ddc91eb318c8751c69ddb200a5937f1232ee8efb4e64e9f4bc475a33719de438", size = 11063480, upload-time = "2025-06-16T16:47:56.205Z" }, + { url = "https://files.pythonhosted.org/packages/f5/4d/cd1a42b8e5be278fab7010fb289d9307a63e07153f0ae1510a3d7b703193/mypy-1.16.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:87ff2c13d58bdc4bbe7dc0dedfe622c0f04e2cb2a492269f3b418df2de05c536", size = 10090538, upload-time = "2025-06-16T16:46:43.92Z" }, + { url = "https://files.pythonhosted.org/packages/c9/4f/c3c6b4b66374b5f68bab07c8cabd63a049ff69796b844bc759a0ca99bb2a/mypy-1.16.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a7cfb0fe29fe5a9841b7c8ee6dffb52382c45acdf68f032145b75620acfbd6f", size = 11836839, upload-time = "2025-06-16T16:36:28.039Z" }, + { url = "https://files.pythonhosted.org/packages/b4/7e/81ca3b074021ad9775e5cb97ebe0089c0f13684b066a750b7dc208438403/mypy-1.16.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:051e1677689c9d9578b9c7f4d206d763f9bbd95723cd1416fad50db49d52f359", size = 12715634, upload-time = "2025-06-16T16:50:34.441Z" }, + { url = "https://files.pythonhosted.org/packages/e9/95/bdd40c8be346fa4c70edb4081d727a54d0a05382d84966869738cfa8a497/mypy-1.16.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d5d2309511cc56c021b4b4e462907c2b12f669b2dbeb68300110ec27723971be", size = 12895584, upload-time = "2025-06-16T16:34:54.857Z" }, + { url = "https://files.pythonhosted.org/packages/5a/fd/d486a0827a1c597b3b48b1bdef47228a6e9ee8102ab8c28f944cb83b65dc/mypy-1.16.1-cp313-cp313-win_amd64.whl", hash = "sha256:4f58ac32771341e38a853c5d0ec0dfe27e18e27da9cdb8bbc882d2249c71a3ee", size = 9573886, upload-time = "2025-06-16T16:36:43.589Z" }, + { url = "https://files.pythonhosted.org/packages/49/5e/ed1e6a7344005df11dfd58b0fdd59ce939a0ba9f7ed37754bf20670b74db/mypy-1.16.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7fc688329af6a287567f45cc1cefb9db662defeb14625213a5b7da6e692e2069", size = 10959511, upload-time = "2025-06-16T16:47:21.945Z" }, + { url = "https://files.pythonhosted.org/packages/30/88/a7cbc2541e91fe04f43d9e4577264b260fecedb9bccb64ffb1a34b7e6c22/mypy-1.16.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e198ab3f55924c03ead626ff424cad1732d0d391478dfbf7bb97b34602395da", size = 10075555, upload-time = "2025-06-16T16:50:14.084Z" }, + { url = "https://files.pythonhosted.org/packages/93/f7/c62b1e31a32fbd1546cca5e0a2e5f181be5761265ad1f2e94f2a306fa906/mypy-1.16.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:09aa4f91ada245f0a45dbc47e548fd94e0dd5a8433e0114917dc3b526912a30c", size = 11874169, upload-time = "2025-06-16T16:49:42.276Z" }, + { url = "https://files.pythonhosted.org/packages/c8/15/db580a28034657fb6cb87af2f8996435a5b19d429ea4dcd6e1c73d418e60/mypy-1.16.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13c7cd5b1cb2909aa318a90fd1b7e31f17c50b242953e7dd58345b2a814f6383", size = 12610060, upload-time = "2025-06-16T16:34:15.215Z" }, + { url = "https://files.pythonhosted.org/packages/ec/78/c17f48f6843048fa92d1489d3095e99324f2a8c420f831a04ccc454e2e51/mypy-1.16.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:58e07fb958bc5d752a280da0e890c538f1515b79a65757bbdc54252ba82e0b40", size = 12875199, upload-time = "2025-06-16T16:35:14.448Z" }, + { url = "https://files.pythonhosted.org/packages/bc/d6/ed42167d0a42680381653fd251d877382351e1bd2c6dd8a818764be3beb1/mypy-1.16.1-cp39-cp39-win_amd64.whl", hash = "sha256:f895078594d918f93337a505f8add9bd654d1a24962b4c6ed9390e12531eb31b", size = 9487033, upload-time = "2025-06-16T16:49:57.907Z" }, + { url = "https://files.pythonhosted.org/packages/cf/d3/53e684e78e07c1a2bf7105715e5edd09ce951fc3f47cf9ed095ec1b7a037/mypy-1.16.1-py3-none-any.whl", hash = "sha256:5fc2ac4027d0ef28d6ba69a0343737a23c4d1b83672bf38d1fe237bdc0643b37", size = 2265923, upload-time = "2025-06-16T16:48:02.366Z" }, ] [[package]] @@ -742,6 +739,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451, upload-time = "2024-11-08T09:47:44.722Z" }, ] +[[package]] +name = "pathspec" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" }, +] + [[package]] name = "pluggy" version = "1.6.0" @@ -787,7 +793,7 @@ wheels = [ [[package]] name = "pydantic" -version = "2.11.4" +version = "2.11.7" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-types" }, @@ -795,9 +801,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/77/ab/5250d56ad03884ab5efd07f734203943c8a8ab40d551e208af81d0257bf2/pydantic-2.11.4.tar.gz", hash = "sha256:32738d19d63a226a52eed76645a98ee07c1f410ee41d93b4afbfa85ed8111c2d", size = 786540, upload-time = "2025-04-29T20:38:55.02Z" } +sdist = { url = "https://files.pythonhosted.org/packages/00/dd/4325abf92c39ba8623b5af936ddb36ffcfe0beae70405d456ab1fb2f5b8c/pydantic-2.11.7.tar.gz", hash = "sha256:d989c3c6cb79469287b1569f7447a17848c998458d49ebe294e975b9baf0f0db", size = 788350, upload-time = "2025-06-14T08:33:17.137Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e7/12/46b65f3534d099349e38ef6ec98b1a5a81f42536d17e0ba382c28c67ba67/pydantic-2.11.4-py3-none-any.whl", hash = "sha256:d9615eaa9ac5a063471da949c8fc16376a84afb5024688b3ff885693506764eb", size = 443900, upload-time = "2025-04-29T20:38:52.724Z" }, + { url = "https://files.pythonhosted.org/packages/6a/c0/ec2b1c8712ca690e5d61979dee872603e92b8a32f94cc1b72d53beab008a/pydantic-2.11.7-py3-none-any.whl", hash = "sha256:dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b", size = 444782, upload-time = "2025-06-14T08:33:14.905Z" }, ] [[package]] @@ -909,9 +915,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d4/29/3cade8a924a61f60ccfa10842f75eb12787e1440e2b8660ceffeb26685e7/pydantic_core-2.33.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2807668ba86cb38c6817ad9bc66215ab8584d1d304030ce4f0887336f28a5e27", size = 2066661, upload-time = "2025-04-23T18:33:49.995Z" }, ] +[[package]] +name = "pygments" +version = "2.19.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, +] + [[package]] name = "pytest" -version = "8.3.5" +version = "8.4.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, @@ -919,36 +934,37 @@ dependencies = [ { name = "iniconfig" }, { name = "packaging" }, { name = "pluggy" }, + { name = "pygments" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ae/3c/c9d525a414d506893f0cd8a8d0de7706446213181570cdbd766691164e40/pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845", size = 1450891, upload-time = "2025-03-02T12:54:54.503Z" } +sdist = { url = "https://files.pythonhosted.org/packages/08/ba/45911d754e8eba3d5a841a5ce61a65a685ff1798421ac054f85aa8747dfb/pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c", size = 1517714, upload-time = "2025-06-18T05:48:06.109Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/30/3d/64ad57c803f1fa1e963a7946b6e0fea4a70df53c1a7fed304586539c2bac/pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", size = 343634, upload-time = "2025-03-02T12:54:52.069Z" }, + { url = "https://files.pythonhosted.org/packages/29/16/c8a903f4c4dffe7a12843191437d7cd8e32751d5de349d45d3fe69544e87/pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7", size = 365474, upload-time = "2025-06-18T05:48:03.955Z" }, ] [[package]] name = "pytest-asyncio" -version = "0.26.0" +version = "1.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pytest" }, { name = "typing-extensions", marker = "python_full_version < '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8e/c4/453c52c659521066969523e87d85d54139bbd17b78f09532fb8eb8cdb58e/pytest_asyncio-0.26.0.tar.gz", hash = "sha256:c4df2a697648241ff39e7f0e4a73050b03f123f760673956cf0d72a4990e312f", size = 54156, upload-time = "2025-03-25T06:22:28.883Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/d4/14f53324cb1a6381bef29d698987625d80052bb33932d8e7cbf9b337b17c/pytest_asyncio-1.0.0.tar.gz", hash = "sha256:d15463d13f4456e1ead2594520216b225a16f781e144f8fdf6c5bb4667c48b3f", size = 46960, upload-time = "2025-05-26T04:54:40.484Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/20/7f/338843f449ace853647ace35870874f69a764d251872ed1b4de9f234822c/pytest_asyncio-0.26.0-py3-none-any.whl", hash = "sha256:7b51ed894f4fbea1340262bdae5135797ebbe21d8638978e35d31c6d19f72fb0", size = 19694, upload-time = "2025-03-25T06:22:27.807Z" }, + { url = "https://files.pythonhosted.org/packages/30/05/ce271016e351fddc8399e546f6e23761967ee09c8c568bbfbecb0c150171/pytest_asyncio-1.0.0-py3-none-any.whl", hash = "sha256:4f024da9f1ef945e680dc68610b52550e36590a67fd31bb3b4943979a1f90ef3", size = 15976, upload-time = "2025-05-26T04:54:39.035Z" }, ] [[package]] name = "pytest-mock" -version = "3.14.0" +version = "3.14.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c6/90/a955c3ab35ccd41ad4de556596fa86685bf4fc5ffcc62d22d856cfd4e29a/pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0", size = 32814, upload-time = "2024-03-21T22:14:04.964Z" } +sdist = { url = "https://files.pythonhosted.org/packages/71/28/67172c96ba684058a4d24ffe144d64783d2a270d0af0d9e792737bddc75c/pytest_mock-3.14.1.tar.gz", hash = "sha256:159e9edac4c451ce77a5cdb9fc5d1100708d2dd4ba3c3df572f14097351af80e", size = 33241, upload-time = "2025-05-26T13:58:45.167Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f2/3b/b26f90f74e2986a82df6e7ac7e319b8ea7ccece1caec9f8ab6104dc70603/pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f", size = 9863, upload-time = "2024-03-21T22:14:02.694Z" }, + { url = "https://files.pythonhosted.org/packages/b2/05/77b60e520511c53d1c1ca75f1930c7dd8e971d0c4379b7f4b3f9644685ba/pytest_mock-3.14.1-py3-none-any.whl", hash = "sha256:178aefcd11307d874b4cd3100344e7e2d888d9791a6a1d9bfe90fbc1b74fd1d0", size = 9923, upload-time = "2025-05-26T13:58:43.487Z" }, ] [[package]] @@ -1019,7 +1035,7 @@ wheels = [ [[package]] name = "requests" -version = "2.32.3" +version = "2.32.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, @@ -1027,9 +1043,9 @@ dependencies = [ { name = "idna" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218, upload-time = "2024-05-29T15:37:49.536Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e1/0a/929373653770d8a0d7ea76c37de6e41f11eb07559b103b1c02cafb3f7cf8/requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422", size = 135258, upload-time = "2025-06-09T16:43:07.34Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928, upload-time = "2024-05-29T15:37:47.027Z" }, + { url = "https://files.pythonhosted.org/packages/7c/e4/56027c4a6b4ae70ca9de302488c5ca95ad4a39e190093d6c1a8ace08341b/requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", size = 64847, upload-time = "2025-06-09T16:43:05.728Z" }, ] [[package]] @@ -1046,27 +1062,27 @@ wheels = [ [[package]] name = "ruff" -version = "0.11.10" +version = "0.12.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e8/4c/4a3c5a97faaae6b428b336dcca81d03ad04779f8072c267ad2bd860126bf/ruff-0.11.10.tar.gz", hash = "sha256:d522fb204b4959909ecac47da02830daec102eeb100fb50ea9554818d47a5fa6", size = 4165632, upload-time = "2025-05-15T14:08:56.76Z" } +sdist = { url = "https://files.pythonhosted.org/packages/6c/3d/d9a195676f25d00dbfcf3cf95fdd4c685c497fcfa7e862a44ac5e4e96480/ruff-0.12.2.tar.gz", hash = "sha256:d7b4f55cd6f325cb7621244f19c873c565a08aff5a4ba9c69aa7355f3f7afd3e", size = 4432239, upload-time = "2025-07-03T16:40:19.566Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2f/9f/596c628f8824a2ce4cd12b0f0b4c0629a62dfffc5d0f742c19a1d71be108/ruff-0.11.10-py3-none-linux_armv6l.whl", hash = "sha256:859a7bfa7bc8888abbea31ef8a2b411714e6a80f0d173c2a82f9041ed6b50f58", size = 10316243, upload-time = "2025-05-15T14:08:12.884Z" }, - { url = "https://files.pythonhosted.org/packages/3c/38/c1e0b77ab58b426f8c332c1d1d3432d9fc9a9ea622806e208220cb133c9e/ruff-0.11.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:968220a57e09ea5e4fd48ed1c646419961a0570727c7e069842edd018ee8afed", size = 11083636, upload-time = "2025-05-15T14:08:16.551Z" }, - { url = "https://files.pythonhosted.org/packages/23/41/b75e15961d6047d7fe1b13886e56e8413be8467a4e1be0a07f3b303cd65a/ruff-0.11.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1067245bad978e7aa7b22f67113ecc6eb241dca0d9b696144256c3a879663bca", size = 10441624, upload-time = "2025-05-15T14:08:19.032Z" }, - { url = "https://files.pythonhosted.org/packages/b6/2c/e396b6703f131406db1811ea3d746f29d91b41bbd43ad572fea30da1435d/ruff-0.11.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4854fd09c7aed5b1590e996a81aeff0c9ff51378b084eb5a0b9cd9518e6cff2", size = 10624358, upload-time = "2025-05-15T14:08:21.542Z" }, - { url = "https://files.pythonhosted.org/packages/bd/8c/ee6cca8bdaf0f9a3704796022851a33cd37d1340bceaf4f6e991eb164e2e/ruff-0.11.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8b4564e9f99168c0f9195a0fd5fa5928004b33b377137f978055e40008a082c5", size = 10176850, upload-time = "2025-05-15T14:08:23.682Z" }, - { url = "https://files.pythonhosted.org/packages/e9/ce/4e27e131a434321b3b7c66512c3ee7505b446eb1c8a80777c023f7e876e6/ruff-0.11.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b6a9cc5b62c03cc1fea0044ed8576379dbaf751d5503d718c973d5418483641", size = 11759787, upload-time = "2025-05-15T14:08:25.733Z" }, - { url = "https://files.pythonhosted.org/packages/58/de/1e2e77fc72adc7cf5b5123fd04a59ed329651d3eab9825674a9e640b100b/ruff-0.11.10-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:607ecbb6f03e44c9e0a93aedacb17b4eb4f3563d00e8b474298a201622677947", size = 12430479, upload-time = "2025-05-15T14:08:28.013Z" }, - { url = "https://files.pythonhosted.org/packages/07/ed/af0f2340f33b70d50121628ef175523cc4c37619e98d98748c85764c8d88/ruff-0.11.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7b3a522fa389402cd2137df9ddefe848f727250535c70dafa840badffb56b7a4", size = 11919760, upload-time = "2025-05-15T14:08:30.956Z" }, - { url = "https://files.pythonhosted.org/packages/24/09/d7b3d3226d535cb89234390f418d10e00a157b6c4a06dfbe723e9322cb7d/ruff-0.11.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f071b0deed7e9245d5820dac235cbdd4ef99d7b12ff04c330a241ad3534319f", size = 14041747, upload-time = "2025-05-15T14:08:33.297Z" }, - { url = "https://files.pythonhosted.org/packages/62/b3/a63b4e91850e3f47f78795e6630ee9266cb6963de8f0191600289c2bb8f4/ruff-0.11.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a60e3a0a617eafba1f2e4186d827759d65348fa53708ca547e384db28406a0b", size = 11550657, upload-time = "2025-05-15T14:08:35.639Z" }, - { url = "https://files.pythonhosted.org/packages/46/63/a4f95c241d79402ccdbdb1d823d156c89fbb36ebfc4289dce092e6c0aa8f/ruff-0.11.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:da8ec977eaa4b7bf75470fb575bea2cb41a0e07c7ea9d5a0a97d13dbca697bf2", size = 10489671, upload-time = "2025-05-15T14:08:38.437Z" }, - { url = "https://files.pythonhosted.org/packages/6a/9b/c2238bfebf1e473495659c523d50b1685258b6345d5ab0b418ca3f010cd7/ruff-0.11.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ddf8967e08227d1bd95cc0851ef80d2ad9c7c0c5aab1eba31db49cf0a7b99523", size = 10160135, upload-time = "2025-05-15T14:08:41.247Z" }, - { url = "https://files.pythonhosted.org/packages/ba/ef/ba7251dd15206688dbfba7d413c0312e94df3b31b08f5d695580b755a899/ruff-0.11.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5a94acf798a82db188f6f36575d80609072b032105d114b0f98661e1679c9125", size = 11170179, upload-time = "2025-05-15T14:08:43.762Z" }, - { url = "https://files.pythonhosted.org/packages/73/9f/5c336717293203ba275dbfa2ea16e49b29a9fd9a0ea8b6febfc17e133577/ruff-0.11.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:3afead355f1d16d95630df28d4ba17fb2cb9c8dfac8d21ced14984121f639bad", size = 11626021, upload-time = "2025-05-15T14:08:46.451Z" }, - { url = "https://files.pythonhosted.org/packages/d9/2b/162fa86d2639076667c9aa59196c020dc6d7023ac8f342416c2f5ec4bda0/ruff-0.11.10-py3-none-win32.whl", hash = "sha256:dc061a98d32a97211af7e7f3fa1d4ca2fcf919fb96c28f39551f35fc55bdbc19", size = 10494958, upload-time = "2025-05-15T14:08:49.601Z" }, - { url = "https://files.pythonhosted.org/packages/24/f3/66643d8f32f50a4b0d09a4832b7d919145ee2b944d43e604fbd7c144d175/ruff-0.11.10-py3-none-win_amd64.whl", hash = "sha256:5cc725fbb4d25b0f185cb42df07ab6b76c4489b4bfb740a175f3a59c70e8a224", size = 11650285, upload-time = "2025-05-15T14:08:52.392Z" }, - { url = "https://files.pythonhosted.org/packages/95/3a/2e8704d19f376c799748ff9cb041225c1d59f3e7711bc5596c8cfdc24925/ruff-0.11.10-py3-none-win_arm64.whl", hash = "sha256:ef69637b35fb8b210743926778d0e45e1bffa850a7c61e428c6b971549b5f5d1", size = 10765278, upload-time = "2025-05-15T14:08:54.56Z" }, + { url = "https://files.pythonhosted.org/packages/74/b6/2098d0126d2d3318fd5bec3ad40d06c25d377d95749f7a0c5af17129b3b1/ruff-0.12.2-py3-none-linux_armv6l.whl", hash = "sha256:093ea2b221df1d2b8e7ad92fc6ffdca40a2cb10d8564477a987b44fd4008a7be", size = 10369761, upload-time = "2025-07-03T16:39:38.847Z" }, + { url = "https://files.pythonhosted.org/packages/b1/4b/5da0142033dbe155dc598cfb99262d8ee2449d76920ea92c4eeb9547c208/ruff-0.12.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:09e4cf27cc10f96b1708100fa851e0daf21767e9709e1649175355280e0d950e", size = 11155659, upload-time = "2025-07-03T16:39:42.294Z" }, + { url = "https://files.pythonhosted.org/packages/3e/21/967b82550a503d7c5c5c127d11c935344b35e8c521f52915fc858fb3e473/ruff-0.12.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:8ae64755b22f4ff85e9c52d1f82644abd0b6b6b6deedceb74bd71f35c24044cc", size = 10537769, upload-time = "2025-07-03T16:39:44.75Z" }, + { url = "https://files.pythonhosted.org/packages/33/91/00cff7102e2ec71a4890fb7ba1803f2cdb122d82787c7d7cf8041fe8cbc1/ruff-0.12.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3eb3a6b2db4d6e2c77e682f0b988d4d61aff06860158fdb413118ca133d57922", size = 10717602, upload-time = "2025-07-03T16:39:47.652Z" }, + { url = "https://files.pythonhosted.org/packages/9b/eb/928814daec4e1ba9115858adcda44a637fb9010618721937491e4e2283b8/ruff-0.12.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:73448de992d05517170fc37169cbca857dfeaeaa8c2b9be494d7bcb0d36c8f4b", size = 10198772, upload-time = "2025-07-03T16:39:49.641Z" }, + { url = "https://files.pythonhosted.org/packages/50/fa/f15089bc20c40f4f72334f9145dde55ab2b680e51afb3b55422effbf2fb6/ruff-0.12.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b8b94317cbc2ae4a2771af641739f933934b03555e51515e6e021c64441532d", size = 11845173, upload-time = "2025-07-03T16:39:52.069Z" }, + { url = "https://files.pythonhosted.org/packages/43/9f/1f6f98f39f2b9302acc161a4a2187b1e3a97634fe918a8e731e591841cf4/ruff-0.12.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:45fc42c3bf1d30d2008023a0a9a0cfb06bf9835b147f11fe0679f21ae86d34b1", size = 12553002, upload-time = "2025-07-03T16:39:54.551Z" }, + { url = "https://files.pythonhosted.org/packages/d8/70/08991ac46e38ddd231c8f4fd05ef189b1b94be8883e8c0c146a025c20a19/ruff-0.12.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce48f675c394c37e958bf229fb5c1e843e20945a6d962cf3ea20b7a107dcd9f4", size = 12171330, upload-time = "2025-07-03T16:39:57.55Z" }, + { url = "https://files.pythonhosted.org/packages/88/a9/5a55266fec474acfd0a1c73285f19dd22461d95a538f29bba02edd07a5d9/ruff-0.12.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:793d8859445ea47591272021a81391350205a4af65a9392401f418a95dfb75c9", size = 11774717, upload-time = "2025-07-03T16:39:59.78Z" }, + { url = "https://files.pythonhosted.org/packages/87/e5/0c270e458fc73c46c0d0f7cf970bb14786e5fdb88c87b5e423a4bd65232b/ruff-0.12.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6932323db80484dda89153da3d8e58164d01d6da86857c79f1961934354992da", size = 11646659, upload-time = "2025-07-03T16:40:01.934Z" }, + { url = "https://files.pythonhosted.org/packages/b7/b6/45ab96070c9752af37f0be364d849ed70e9ccede07675b0ec4e3ef76b63b/ruff-0.12.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6aa7e623a3a11538108f61e859ebf016c4f14a7e6e4eba1980190cacb57714ce", size = 10604012, upload-time = "2025-07-03T16:40:04.363Z" }, + { url = "https://files.pythonhosted.org/packages/86/91/26a6e6a424eb147cc7627eebae095cfa0b4b337a7c1c413c447c9ebb72fd/ruff-0.12.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:2a4a20aeed74671b2def096bdf2eac610c7d8ffcbf4fb0e627c06947a1d7078d", size = 10176799, upload-time = "2025-07-03T16:40:06.514Z" }, + { url = "https://files.pythonhosted.org/packages/f5/0c/9f344583465a61c8918a7cda604226e77b2c548daf8ef7c2bfccf2b37200/ruff-0.12.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:71a4c550195612f486c9d1f2b045a600aeba851b298c667807ae933478fcef04", size = 11241507, upload-time = "2025-07-03T16:40:08.708Z" }, + { url = "https://files.pythonhosted.org/packages/1c/b7/99c34ded8fb5f86c0280278fa89a0066c3760edc326e935ce0b1550d315d/ruff-0.12.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:4987b8f4ceadf597c927beee65a5eaf994c6e2b631df963f86d8ad1bdea99342", size = 11717609, upload-time = "2025-07-03T16:40:10.836Z" }, + { url = "https://files.pythonhosted.org/packages/51/de/8589fa724590faa057e5a6d171e7f2f6cffe3287406ef40e49c682c07d89/ruff-0.12.2-py3-none-win32.whl", hash = "sha256:369ffb69b70cd55b6c3fc453b9492d98aed98062db9fec828cdfd069555f5f1a", size = 10523823, upload-time = "2025-07-03T16:40:13.203Z" }, + { url = "https://files.pythonhosted.org/packages/94/47/8abf129102ae4c90cba0c2199a1a9b0fa896f6f806238d6f8c14448cc748/ruff-0.12.2-py3-none-win_amd64.whl", hash = "sha256:dca8a3b6d6dc9810ed8f328d406516bf4d660c00caeaef36eb831cf4871b0639", size = 11629831, upload-time = "2025-07-03T16:40:15.478Z" }, + { url = "https://files.pythonhosted.org/packages/e2/1f/72d2946e3cc7456bb837e88000eb3437e55f80db339c840c04015a11115d/ruff-0.12.2-py3-none-win_arm64.whl", hash = "sha256:48d6c6bfb4761df68bc05ae630e24f506755e702d4fb08f08460be778c7ccb12", size = 10735334, upload-time = "2025-07-03T16:40:17.677Z" }, ] [[package]] @@ -1152,23 +1168,23 @@ wheels = [ [[package]] name = "typing-extensions" -version = "4.13.2" +version = "4.14.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f6/37/23083fcd6e35492953e8d2aaaa68b860eb422b34627b13f2ce3eb6106061/typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef", size = 106967, upload-time = "2025-04-10T14:19:05.416Z" } +sdist = { url = "https://files.pythonhosted.org/packages/98/5a/da40306b885cc8c09109dc2e1abd358d5684b1425678151cdaed4731c822/typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36", size = 107673, upload-time = "2025-07-04T13:28:34.16Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806, upload-time = "2025-04-10T14:19:03.967Z" }, + { url = "https://files.pythonhosted.org/packages/b5/00/d631e67a838026495268c2f6884f3711a15a9a2a96cd244fdaea53b823fb/typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76", size = 43906, upload-time = "2025-07-04T13:28:32.743Z" }, ] [[package]] name = "typing-inspection" -version = "0.4.0" +version = "0.4.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/82/5c/e6082df02e215b846b4b8c0b887a64d7d08ffaba30605502639d44c06b82/typing_inspection-0.4.0.tar.gz", hash = "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122", size = 76222, upload-time = "2025-02-25T17:27:59.638Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/b1/0c11f5058406b3af7609f121aaa6b609744687f1d158b3c3a5bf4cc94238/typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28", size = 75726, upload-time = "2025-05-21T18:55:23.885Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/31/08/aa4fdfb71f7de5176385bd9e90852eaf6b5d622735020ad600f2bab54385/typing_inspection-0.4.0-py3-none-any.whl", hash = "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f", size = 14125, upload-time = "2025-02-25T17:27:57.754Z" }, + { url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552, upload-time = "2025-05-21T18:55:22.152Z" }, ] [[package]] @@ -1182,11 +1198,11 @@ wheels = [ [[package]] name = "urllib3" -version = "2.4.0" +version = "2.5.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8a/78/16493d9c386d8e60e442a35feac5e00f0913c0f4b7c217c11e8ec2ff53e0/urllib3-2.4.0.tar.gz", hash = "sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466", size = 390672, upload-time = "2025-04-10T15:23:39.232Z" } +sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6b/11/cc635220681e93a0183390e26485430ca2c7b5f9d33b15c74c2861cb8091/urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813", size = 128680, upload-time = "2025-04-10T15:23:37.377Z" }, + { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" }, ] [[package]] diff --git a/libs/sdk-py/uv.lock b/libs/sdk-py/uv.lock index 7a53ab5ec..71015876c 100644 --- a/libs/sdk-py/uv.lock +++ b/libs/sdk-py/uv.lock @@ -19,11 +19,11 @@ wheels = [ [[package]] name = "certifi" -version = "2025.4.26" +version = "2025.6.15" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e8/9e/c05b3920a3b7d20d3d3310465f50348e5b3694f4f88c6daf736eef3024c4/certifi-2025.4.26.tar.gz", hash = "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6", size = 160705, upload-time = "2025-04-26T02:12:29.51Z" } +sdist = { url = "https://files.pythonhosted.org/packages/73/f7/f14b46d4bcd21092d7d3ccef689615220d8a08fb25e564b65d20738e672e/certifi-2025.6.15.tar.gz", hash = "sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b", size = 158753, upload-time = "2025-06-15T02:45:51.329Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4a/7e/3db2bd1b1f9e95f7cddca6d6e75e2f2bd9f51b1246e546d88addca0106bd/certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3", size = 159618, upload-time = "2025-04-26T02:12:27.662Z" }, + { url = "https://files.pythonhosted.org/packages/84/ae/320161bd181fc06471eed047ecce67b693fd7515b16d495d8932db763426/certifi-2025.6.15-py3-none-any.whl", hash = "sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057", size = 157650, upload-time = "2025-06-15T02:45:49.977Z" }, ] [[package]] @@ -156,46 +156,47 @@ dev = [ [[package]] name = "mypy" -version = "1.15.0" +version = "1.16.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "mypy-extensions" }, + { name = "pathspec" }, { name = "tomli", marker = "python_full_version < '3.11'" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ce/43/d5e49a86afa64bd3839ea0d5b9c7103487007d728e1293f52525d6d5486a/mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43", size = 3239717, upload-time = "2025-02-05T03:50:34.655Z" } +sdist = { url = "https://files.pythonhosted.org/packages/81/69/92c7fa98112e4d9eb075a239caa4ef4649ad7d441545ccffbd5e34607cbb/mypy-1.16.1.tar.gz", hash = "sha256:6bd00a0a2094841c5e47e7374bb42b83d64c527a502e3334e1173a0c24437bab", size = 3324747, upload-time = "2025-06-16T16:51:35.145Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/68/f8/65a7ce8d0e09b6329ad0c8d40330d100ea343bd4dd04c4f8ae26462d0a17/mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13", size = 10738433, upload-time = "2025-02-05T03:49:29.145Z" }, - { url = "https://files.pythonhosted.org/packages/b4/95/9c0ecb8eacfe048583706249439ff52105b3f552ea9c4024166c03224270/mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559", size = 9861472, upload-time = "2025-02-05T03:49:16.986Z" }, - { url = "https://files.pythonhosted.org/packages/84/09/9ec95e982e282e20c0d5407bc65031dfd0f0f8ecc66b69538296e06fcbee/mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b", size = 11611424, upload-time = "2025-02-05T03:49:46.908Z" }, - { url = "https://files.pythonhosted.org/packages/78/13/f7d14e55865036a1e6a0a69580c240f43bc1f37407fe9235c0d4ef25ffb0/mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3", size = 12365450, upload-time = "2025-02-05T03:50:05.89Z" }, - { url = "https://files.pythonhosted.org/packages/48/e1/301a73852d40c241e915ac6d7bcd7fedd47d519246db2d7b86b9d7e7a0cb/mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b", size = 12551765, upload-time = "2025-02-05T03:49:33.56Z" }, - { url = "https://files.pythonhosted.org/packages/77/ba/c37bc323ae5fe7f3f15a28e06ab012cd0b7552886118943e90b15af31195/mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828", size = 9274701, upload-time = "2025-02-05T03:49:38.981Z" }, - { url = "https://files.pythonhosted.org/packages/03/bc/f6339726c627bd7ca1ce0fa56c9ae2d0144604a319e0e339bdadafbbb599/mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f", size = 10662338, upload-time = "2025-02-05T03:50:17.287Z" }, - { url = "https://files.pythonhosted.org/packages/e2/90/8dcf506ca1a09b0d17555cc00cd69aee402c203911410136cd716559efe7/mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5", size = 9787540, upload-time = "2025-02-05T03:49:51.21Z" }, - { url = "https://files.pythonhosted.org/packages/05/05/a10f9479681e5da09ef2f9426f650d7b550d4bafbef683b69aad1ba87457/mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e", size = 11538051, upload-time = "2025-02-05T03:50:20.885Z" }, - { url = "https://files.pythonhosted.org/packages/e9/9a/1f7d18b30edd57441a6411fcbc0c6869448d1a4bacbaee60656ac0fc29c8/mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c", size = 12286751, upload-time = "2025-02-05T03:49:42.408Z" }, - { url = "https://files.pythonhosted.org/packages/72/af/19ff499b6f1dafcaf56f9881f7a965ac2f474f69f6f618b5175b044299f5/mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f", size = 12421783, upload-time = "2025-02-05T03:49:07.707Z" }, - { url = "https://files.pythonhosted.org/packages/96/39/11b57431a1f686c1aed54bf794870efe0f6aeca11aca281a0bd87a5ad42c/mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f", size = 9265618, upload-time = "2025-02-05T03:49:54.581Z" }, - { url = "https://files.pythonhosted.org/packages/98/3a/03c74331c5eb8bd025734e04c9840532226775c47a2c39b56a0c8d4f128d/mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd", size = 10793981, upload-time = "2025-02-05T03:50:28.25Z" }, - { url = "https://files.pythonhosted.org/packages/f0/1a/41759b18f2cfd568848a37c89030aeb03534411eef981df621d8fad08a1d/mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f", size = 9749175, upload-time = "2025-02-05T03:50:13.411Z" }, - { url = "https://files.pythonhosted.org/packages/12/7e/873481abf1ef112c582db832740f4c11b2bfa510e829d6da29b0ab8c3f9c/mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464", size = 11455675, upload-time = "2025-02-05T03:50:31.421Z" }, - { url = "https://files.pythonhosted.org/packages/b3/d0/92ae4cde706923a2d3f2d6c39629134063ff64b9dedca9c1388363da072d/mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee", size = 12410020, upload-time = "2025-02-05T03:48:48.705Z" }, - { url = "https://files.pythonhosted.org/packages/46/8b/df49974b337cce35f828ba6fda228152d6db45fed4c86ba56ffe442434fd/mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e", size = 12498582, upload-time = "2025-02-05T03:49:03.628Z" }, - { url = "https://files.pythonhosted.org/packages/13/50/da5203fcf6c53044a0b699939f31075c45ae8a4cadf538a9069b165c1050/mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22", size = 9366614, upload-time = "2025-02-05T03:50:00.313Z" }, - { url = "https://files.pythonhosted.org/packages/6a/9b/fd2e05d6ffff24d912f150b87db9e364fa8282045c875654ce7e32fffa66/mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445", size = 10788592, upload-time = "2025-02-05T03:48:55.789Z" }, - { url = "https://files.pythonhosted.org/packages/74/37/b246d711c28a03ead1fd906bbc7106659aed7c089d55fe40dd58db812628/mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d", size = 9753611, upload-time = "2025-02-05T03:48:44.581Z" }, - { url = "https://files.pythonhosted.org/packages/a6/ac/395808a92e10cfdac8003c3de9a2ab6dc7cde6c0d2a4df3df1b815ffd067/mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5", size = 11438443, upload-time = "2025-02-05T03:49:25.514Z" }, - { url = "https://files.pythonhosted.org/packages/d2/8b/801aa06445d2de3895f59e476f38f3f8d610ef5d6908245f07d002676cbf/mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036", size = 12402541, upload-time = "2025-02-05T03:49:57.623Z" }, - { url = "https://files.pythonhosted.org/packages/c7/67/5a4268782eb77344cc613a4cf23540928e41f018a9a1ec4c6882baf20ab8/mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357", size = 12494348, upload-time = "2025-02-05T03:48:52.361Z" }, - { url = "https://files.pythonhosted.org/packages/83/3e/57bb447f7bbbfaabf1712d96f9df142624a386d98fb026a761532526057e/mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf", size = 9373648, upload-time = "2025-02-05T03:49:11.395Z" }, - { url = "https://files.pythonhosted.org/packages/5a/fa/79cf41a55b682794abe71372151dbbf856e3008f6767057229e6649d294a/mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078", size = 10737129, upload-time = "2025-02-05T03:50:24.509Z" }, - { url = "https://files.pythonhosted.org/packages/d3/33/dd8feb2597d648de29e3da0a8bf4e1afbda472964d2a4a0052203a6f3594/mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba", size = 9856335, upload-time = "2025-02-05T03:49:36.398Z" }, - { url = "https://files.pythonhosted.org/packages/e4/b5/74508959c1b06b96674b364ffeb7ae5802646b32929b7701fc6b18447592/mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5", size = 11611935, upload-time = "2025-02-05T03:49:14.154Z" }, - { url = "https://files.pythonhosted.org/packages/6c/53/da61b9d9973efcd6507183fdad96606996191657fe79701b2c818714d573/mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b", size = 12365827, upload-time = "2025-02-05T03:48:59.458Z" }, - { url = "https://files.pythonhosted.org/packages/c1/72/965bd9ee89540c79a25778cc080c7e6ef40aa1eeac4d52cec7eae6eb5228/mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2", size = 12541924, upload-time = "2025-02-05T03:50:03.12Z" }, - { url = "https://files.pythonhosted.org/packages/46/d0/f41645c2eb263e6c77ada7d76f894c580c9ddb20d77f0c24d34273a4dab2/mypy-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980", size = 9271176, upload-time = "2025-02-05T03:50:10.86Z" }, - { url = "https://files.pythonhosted.org/packages/09/4e/a7d65c7322c510de2c409ff3828b03354a7c43f5a8ed458a7a131b41c7b9/mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e", size = 2221777, upload-time = "2025-02-05T03:50:08.348Z" }, + { url = "https://files.pythonhosted.org/packages/8e/12/2bf23a80fcef5edb75de9a1e295d778e0f46ea89eb8b115818b663eff42b/mypy-1.16.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b4f0fed1022a63c6fec38f28b7fc77fca47fd490445c69d0a66266c59dd0b88a", size = 10958644, upload-time = "2025-06-16T16:51:11.649Z" }, + { url = "https://files.pythonhosted.org/packages/08/50/bfe47b3b278eacf348291742fd5e6613bbc4b3434b72ce9361896417cfe5/mypy-1.16.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:86042bbf9f5a05ea000d3203cf87aa9d0ccf9a01f73f71c58979eb9249f46d72", size = 10087033, upload-time = "2025-06-16T16:35:30.089Z" }, + { url = "https://files.pythonhosted.org/packages/21/de/40307c12fe25675a0776aaa2cdd2879cf30d99eec91b898de00228dc3ab5/mypy-1.16.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ea7469ee5902c95542bea7ee545f7006508c65c8c54b06dc2c92676ce526f3ea", size = 11875645, upload-time = "2025-06-16T16:35:48.49Z" }, + { url = "https://files.pythonhosted.org/packages/a6/d8/85bdb59e4a98b7a31495bd8f1a4445d8ffc86cde4ab1f8c11d247c11aedc/mypy-1.16.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:352025753ef6a83cb9e7f2427319bb7875d1fdda8439d1e23de12ab164179574", size = 12616986, upload-time = "2025-06-16T16:48:39.526Z" }, + { url = "https://files.pythonhosted.org/packages/0e/d0/bb25731158fa8f8ee9e068d3e94fcceb4971fedf1424248496292512afe9/mypy-1.16.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ff9fa5b16e4c1364eb89a4d16bcda9987f05d39604e1e6c35378a2987c1aac2d", size = 12878632, upload-time = "2025-06-16T16:36:08.195Z" }, + { url = "https://files.pythonhosted.org/packages/2d/11/822a9beb7a2b825c0cb06132ca0a5183f8327a5e23ef89717c9474ba0bc6/mypy-1.16.1-cp310-cp310-win_amd64.whl", hash = "sha256:1256688e284632382f8f3b9e2123df7d279f603c561f099758e66dd6ed4e8bd6", size = 9484391, upload-time = "2025-06-16T16:37:56.151Z" }, + { url = "https://files.pythonhosted.org/packages/9a/61/ec1245aa1c325cb7a6c0f8570a2eee3bfc40fa90d19b1267f8e50b5c8645/mypy-1.16.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:472e4e4c100062488ec643f6162dd0d5208e33e2f34544e1fc931372e806c0cc", size = 10890557, upload-time = "2025-06-16T16:37:21.421Z" }, + { url = "https://files.pythonhosted.org/packages/6b/bb/6eccc0ba0aa0c7a87df24e73f0ad34170514abd8162eb0c75fd7128171fb/mypy-1.16.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea16e2a7d2714277e349e24d19a782a663a34ed60864006e8585db08f8ad1782", size = 10012921, upload-time = "2025-06-16T16:51:28.659Z" }, + { url = "https://files.pythonhosted.org/packages/5f/80/b337a12e2006715f99f529e732c5f6a8c143bb58c92bb142d5ab380963a5/mypy-1.16.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:08e850ea22adc4d8a4014651575567b0318ede51e8e9fe7a68f25391af699507", size = 11802887, upload-time = "2025-06-16T16:50:53.627Z" }, + { url = "https://files.pythonhosted.org/packages/d9/59/f7af072d09793d581a745a25737c7c0a945760036b16aeb620f658a017af/mypy-1.16.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22d76a63a42619bfb90122889b903519149879ddbf2ba4251834727944c8baca", size = 12531658, upload-time = "2025-06-16T16:33:55.002Z" }, + { url = "https://files.pythonhosted.org/packages/82/c4/607672f2d6c0254b94a646cfc45ad589dd71b04aa1f3d642b840f7cce06c/mypy-1.16.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2c7ce0662b6b9dc8f4ed86eb7a5d505ee3298c04b40ec13b30e572c0e5ae17c4", size = 12732486, upload-time = "2025-06-16T16:37:03.301Z" }, + { url = "https://files.pythonhosted.org/packages/b6/5e/136555ec1d80df877a707cebf9081bd3a9f397dedc1ab9750518d87489ec/mypy-1.16.1-cp311-cp311-win_amd64.whl", hash = "sha256:211287e98e05352a2e1d4e8759c5490925a7c784ddc84207f4714822f8cf99b6", size = 9479482, upload-time = "2025-06-16T16:47:37.48Z" }, + { url = "https://files.pythonhosted.org/packages/b4/d6/39482e5fcc724c15bf6280ff5806548c7185e0c090712a3736ed4d07e8b7/mypy-1.16.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:af4792433f09575d9eeca5c63d7d90ca4aeceda9d8355e136f80f8967639183d", size = 11066493, upload-time = "2025-06-16T16:47:01.683Z" }, + { url = "https://files.pythonhosted.org/packages/e6/e5/26c347890efc6b757f4d5bb83f4a0cf5958b8cf49c938ac99b8b72b420a6/mypy-1.16.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:66df38405fd8466ce3517eda1f6640611a0b8e70895e2a9462d1d4323c5eb4b9", size = 10081687, upload-time = "2025-06-16T16:48:19.367Z" }, + { url = "https://files.pythonhosted.org/packages/44/c7/b5cb264c97b86914487d6a24bd8688c0172e37ec0f43e93b9691cae9468b/mypy-1.16.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44e7acddb3c48bd2713994d098729494117803616e116032af192871aed80b79", size = 11839723, upload-time = "2025-06-16T16:49:20.912Z" }, + { url = "https://files.pythonhosted.org/packages/15/f8/491997a9b8a554204f834ed4816bda813aefda31cf873bb099deee3c9a99/mypy-1.16.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0ab5eca37b50188163fa7c1b73c685ac66c4e9bdee4a85c9adac0e91d8895e15", size = 12722980, upload-time = "2025-06-16T16:37:40.929Z" }, + { url = "https://files.pythonhosted.org/packages/df/f0/2bd41e174b5fd93bc9de9a28e4fb673113633b8a7f3a607fa4a73595e468/mypy-1.16.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb6229b2c9086247e21a83c309754b9058b438704ad2f6807f0d8227f6ebdd", size = 12903328, upload-time = "2025-06-16T16:34:35.099Z" }, + { url = "https://files.pythonhosted.org/packages/61/81/5572108a7bec2c46b8aff7e9b524f371fe6ab5efb534d38d6b37b5490da8/mypy-1.16.1-cp312-cp312-win_amd64.whl", hash = "sha256:1f0435cf920e287ff68af3d10a118a73f212deb2ce087619eb4e648116d1fe9b", size = 9562321, upload-time = "2025-06-16T16:48:58.823Z" }, + { url = "https://files.pythonhosted.org/packages/28/e3/96964af4a75a949e67df4b95318fe2b7427ac8189bbc3ef28f92a1c5bc56/mypy-1.16.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ddc91eb318c8751c69ddb200a5937f1232ee8efb4e64e9f4bc475a33719de438", size = 11063480, upload-time = "2025-06-16T16:47:56.205Z" }, + { url = "https://files.pythonhosted.org/packages/f5/4d/cd1a42b8e5be278fab7010fb289d9307a63e07153f0ae1510a3d7b703193/mypy-1.16.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:87ff2c13d58bdc4bbe7dc0dedfe622c0f04e2cb2a492269f3b418df2de05c536", size = 10090538, upload-time = "2025-06-16T16:46:43.92Z" }, + { url = "https://files.pythonhosted.org/packages/c9/4f/c3c6b4b66374b5f68bab07c8cabd63a049ff69796b844bc759a0ca99bb2a/mypy-1.16.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a7cfb0fe29fe5a9841b7c8ee6dffb52382c45acdf68f032145b75620acfbd6f", size = 11836839, upload-time = "2025-06-16T16:36:28.039Z" }, + { url = "https://files.pythonhosted.org/packages/b4/7e/81ca3b074021ad9775e5cb97ebe0089c0f13684b066a750b7dc208438403/mypy-1.16.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:051e1677689c9d9578b9c7f4d206d763f9bbd95723cd1416fad50db49d52f359", size = 12715634, upload-time = "2025-06-16T16:50:34.441Z" }, + { url = "https://files.pythonhosted.org/packages/e9/95/bdd40c8be346fa4c70edb4081d727a54d0a05382d84966869738cfa8a497/mypy-1.16.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d5d2309511cc56c021b4b4e462907c2b12f669b2dbeb68300110ec27723971be", size = 12895584, upload-time = "2025-06-16T16:34:54.857Z" }, + { url = "https://files.pythonhosted.org/packages/5a/fd/d486a0827a1c597b3b48b1bdef47228a6e9ee8102ab8c28f944cb83b65dc/mypy-1.16.1-cp313-cp313-win_amd64.whl", hash = "sha256:4f58ac32771341e38a853c5d0ec0dfe27e18e27da9cdb8bbc882d2249c71a3ee", size = 9573886, upload-time = "2025-06-16T16:36:43.589Z" }, + { url = "https://files.pythonhosted.org/packages/49/5e/ed1e6a7344005df11dfd58b0fdd59ce939a0ba9f7ed37754bf20670b74db/mypy-1.16.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7fc688329af6a287567f45cc1cefb9db662defeb14625213a5b7da6e692e2069", size = 10959511, upload-time = "2025-06-16T16:47:21.945Z" }, + { url = "https://files.pythonhosted.org/packages/30/88/a7cbc2541e91fe04f43d9e4577264b260fecedb9bccb64ffb1a34b7e6c22/mypy-1.16.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e198ab3f55924c03ead626ff424cad1732d0d391478dfbf7bb97b34602395da", size = 10075555, upload-time = "2025-06-16T16:50:14.084Z" }, + { url = "https://files.pythonhosted.org/packages/93/f7/c62b1e31a32fbd1546cca5e0a2e5f181be5761265ad1f2e94f2a306fa906/mypy-1.16.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:09aa4f91ada245f0a45dbc47e548fd94e0dd5a8433e0114917dc3b526912a30c", size = 11874169, upload-time = "2025-06-16T16:49:42.276Z" }, + { url = "https://files.pythonhosted.org/packages/c8/15/db580a28034657fb6cb87af2f8996435a5b19d429ea4dcd6e1c73d418e60/mypy-1.16.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13c7cd5b1cb2909aa318a90fd1b7e31f17c50b242953e7dd58345b2a814f6383", size = 12610060, upload-time = "2025-06-16T16:34:15.215Z" }, + { url = "https://files.pythonhosted.org/packages/ec/78/c17f48f6843048fa92d1489d3095e99324f2a8c420f831a04ccc454e2e51/mypy-1.16.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:58e07fb958bc5d752a280da0e890c538f1515b79a65757bbdc54252ba82e0b40", size = 12875199, upload-time = "2025-06-16T16:35:14.448Z" }, + { url = "https://files.pythonhosted.org/packages/bc/d6/ed42167d0a42680381653fd251d877382351e1bd2c6dd8a818764be3beb1/mypy-1.16.1-cp39-cp39-win_amd64.whl", hash = "sha256:f895078594d918f93337a505f8add9bd654d1a24962b4c6ed9390e12531eb31b", size = 9487033, upload-time = "2025-06-16T16:49:57.907Z" }, + { url = "https://files.pythonhosted.org/packages/cf/d3/53e684e78e07c1a2bf7105715e5edd09ce951fc3f47cf9ed095ec1b7a037/mypy-1.16.1-py3-none-any.whl", hash = "sha256:5fc2ac4027d0ef28d6ba69a0343737a23c4d1b83672bf38d1fe237bdc0643b37", size = 2265923, upload-time = "2025-06-16T16:48:02.366Z" }, ] [[package]] @@ -295,6 +296,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, ] +[[package]] +name = "pathspec" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" }, +] + [[package]] name = "pluggy" version = "1.6.0" @@ -304,9 +314,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, ] +[[package]] +name = "pygments" +version = "2.19.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, +] + [[package]] name = "pytest" -version = "8.3.5" +version = "8.4.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, @@ -314,36 +333,37 @@ dependencies = [ { name = "iniconfig" }, { name = "packaging" }, { name = "pluggy" }, + { name = "pygments" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ae/3c/c9d525a414d506893f0cd8a8d0de7706446213181570cdbd766691164e40/pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845", size = 1450891, upload-time = "2025-03-02T12:54:54.503Z" } +sdist = { url = "https://files.pythonhosted.org/packages/08/ba/45911d754e8eba3d5a841a5ce61a65a685ff1798421ac054f85aa8747dfb/pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c", size = 1517714, upload-time = "2025-06-18T05:48:06.109Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/30/3d/64ad57c803f1fa1e963a7946b6e0fea4a70df53c1a7fed304586539c2bac/pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", size = 343634, upload-time = "2025-03-02T12:54:52.069Z" }, + { url = "https://files.pythonhosted.org/packages/29/16/c8a903f4c4dffe7a12843191437d7cd8e32751d5de349d45d3fe69544e87/pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7", size = 365474, upload-time = "2025-06-18T05:48:03.955Z" }, ] [[package]] name = "pytest-asyncio" -version = "0.26.0" +version = "1.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pytest" }, { name = "typing-extensions", marker = "python_full_version < '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8e/c4/453c52c659521066969523e87d85d54139bbd17b78f09532fb8eb8cdb58e/pytest_asyncio-0.26.0.tar.gz", hash = "sha256:c4df2a697648241ff39e7f0e4a73050b03f123f760673956cf0d72a4990e312f", size = 54156, upload-time = "2025-03-25T06:22:28.883Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/d4/14f53324cb1a6381bef29d698987625d80052bb33932d8e7cbf9b337b17c/pytest_asyncio-1.0.0.tar.gz", hash = "sha256:d15463d13f4456e1ead2594520216b225a16f781e144f8fdf6c5bb4667c48b3f", size = 46960, upload-time = "2025-05-26T04:54:40.484Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/20/7f/338843f449ace853647ace35870874f69a764d251872ed1b4de9f234822c/pytest_asyncio-0.26.0-py3-none-any.whl", hash = "sha256:7b51ed894f4fbea1340262bdae5135797ebbe21d8638978e35d31c6d19f72fb0", size = 19694, upload-time = "2025-03-25T06:22:27.807Z" }, + { url = "https://files.pythonhosted.org/packages/30/05/ce271016e351fddc8399e546f6e23761967ee09c8c568bbfbecb0c150171/pytest_asyncio-1.0.0-py3-none-any.whl", hash = "sha256:4f024da9f1ef945e680dc68610b52550e36590a67fd31bb3b4943979a1f90ef3", size = 15976, upload-time = "2025-05-26T04:54:39.035Z" }, ] [[package]] name = "pytest-mock" -version = "3.14.0" +version = "3.14.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c6/90/a955c3ab35ccd41ad4de556596fa86685bf4fc5ffcc62d22d856cfd4e29a/pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0", size = 32814, upload-time = "2024-03-21T22:14:04.964Z" } +sdist = { url = "https://files.pythonhosted.org/packages/71/28/67172c96ba684058a4d24ffe144d64783d2a270d0af0d9e792737bddc75c/pytest_mock-3.14.1.tar.gz", hash = "sha256:159e9edac4c451ce77a5cdb9fc5d1100708d2dd4ba3c3df572f14097351af80e", size = 33241, upload-time = "2025-05-26T13:58:45.167Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f2/3b/b26f90f74e2986a82df6e7ac7e319b8ea7ccece1caec9f8ab6104dc70603/pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f", size = 9863, upload-time = "2024-03-21T22:14:02.694Z" }, + { url = "https://files.pythonhosted.org/packages/b2/05/77b60e520511c53d1c1ca75f1930c7dd8e971d0c4379b7f4b3f9644685ba/pytest_mock-3.14.1-py3-none-any.whl", hash = "sha256:178aefcd11307d874b4cd3100344e7e2d888d9791a6a1d9bfe90fbc1b74fd1d0", size = 9923, upload-time = "2025-05-26T13:58:43.487Z" }, ] [[package]] @@ -360,27 +380,27 @@ sdist = { url = "https://files.pythonhosted.org/packages/36/47/ab65fc1d682befc31 [[package]] name = "ruff" -version = "0.11.10" +version = "0.12.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e8/4c/4a3c5a97faaae6b428b336dcca81d03ad04779f8072c267ad2bd860126bf/ruff-0.11.10.tar.gz", hash = "sha256:d522fb204b4959909ecac47da02830daec102eeb100fb50ea9554818d47a5fa6", size = 4165632, upload-time = "2025-05-15T14:08:56.76Z" } +sdist = { url = "https://files.pythonhosted.org/packages/6c/3d/d9a195676f25d00dbfcf3cf95fdd4c685c497fcfa7e862a44ac5e4e96480/ruff-0.12.2.tar.gz", hash = "sha256:d7b4f55cd6f325cb7621244f19c873c565a08aff5a4ba9c69aa7355f3f7afd3e", size = 4432239, upload-time = "2025-07-03T16:40:19.566Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2f/9f/596c628f8824a2ce4cd12b0f0b4c0629a62dfffc5d0f742c19a1d71be108/ruff-0.11.10-py3-none-linux_armv6l.whl", hash = "sha256:859a7bfa7bc8888abbea31ef8a2b411714e6a80f0d173c2a82f9041ed6b50f58", size = 10316243, upload-time = "2025-05-15T14:08:12.884Z" }, - { url = "https://files.pythonhosted.org/packages/3c/38/c1e0b77ab58b426f8c332c1d1d3432d9fc9a9ea622806e208220cb133c9e/ruff-0.11.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:968220a57e09ea5e4fd48ed1c646419961a0570727c7e069842edd018ee8afed", size = 11083636, upload-time = "2025-05-15T14:08:16.551Z" }, - { url = "https://files.pythonhosted.org/packages/23/41/b75e15961d6047d7fe1b13886e56e8413be8467a4e1be0a07f3b303cd65a/ruff-0.11.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1067245bad978e7aa7b22f67113ecc6eb241dca0d9b696144256c3a879663bca", size = 10441624, upload-time = "2025-05-15T14:08:19.032Z" }, - { url = "https://files.pythonhosted.org/packages/b6/2c/e396b6703f131406db1811ea3d746f29d91b41bbd43ad572fea30da1435d/ruff-0.11.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4854fd09c7aed5b1590e996a81aeff0c9ff51378b084eb5a0b9cd9518e6cff2", size = 10624358, upload-time = "2025-05-15T14:08:21.542Z" }, - { url = "https://files.pythonhosted.org/packages/bd/8c/ee6cca8bdaf0f9a3704796022851a33cd37d1340bceaf4f6e991eb164e2e/ruff-0.11.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8b4564e9f99168c0f9195a0fd5fa5928004b33b377137f978055e40008a082c5", size = 10176850, upload-time = "2025-05-15T14:08:23.682Z" }, - { url = "https://files.pythonhosted.org/packages/e9/ce/4e27e131a434321b3b7c66512c3ee7505b446eb1c8a80777c023f7e876e6/ruff-0.11.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b6a9cc5b62c03cc1fea0044ed8576379dbaf751d5503d718c973d5418483641", size = 11759787, upload-time = "2025-05-15T14:08:25.733Z" }, - { url = "https://files.pythonhosted.org/packages/58/de/1e2e77fc72adc7cf5b5123fd04a59ed329651d3eab9825674a9e640b100b/ruff-0.11.10-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:607ecbb6f03e44c9e0a93aedacb17b4eb4f3563d00e8b474298a201622677947", size = 12430479, upload-time = "2025-05-15T14:08:28.013Z" }, - { url = "https://files.pythonhosted.org/packages/07/ed/af0f2340f33b70d50121628ef175523cc4c37619e98d98748c85764c8d88/ruff-0.11.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7b3a522fa389402cd2137df9ddefe848f727250535c70dafa840badffb56b7a4", size = 11919760, upload-time = "2025-05-15T14:08:30.956Z" }, - { url = "https://files.pythonhosted.org/packages/24/09/d7b3d3226d535cb89234390f418d10e00a157b6c4a06dfbe723e9322cb7d/ruff-0.11.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f071b0deed7e9245d5820dac235cbdd4ef99d7b12ff04c330a241ad3534319f", size = 14041747, upload-time = "2025-05-15T14:08:33.297Z" }, - { url = "https://files.pythonhosted.org/packages/62/b3/a63b4e91850e3f47f78795e6630ee9266cb6963de8f0191600289c2bb8f4/ruff-0.11.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a60e3a0a617eafba1f2e4186d827759d65348fa53708ca547e384db28406a0b", size = 11550657, upload-time = "2025-05-15T14:08:35.639Z" }, - { url = "https://files.pythonhosted.org/packages/46/63/a4f95c241d79402ccdbdb1d823d156c89fbb36ebfc4289dce092e6c0aa8f/ruff-0.11.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:da8ec977eaa4b7bf75470fb575bea2cb41a0e07c7ea9d5a0a97d13dbca697bf2", size = 10489671, upload-time = "2025-05-15T14:08:38.437Z" }, - { url = "https://files.pythonhosted.org/packages/6a/9b/c2238bfebf1e473495659c523d50b1685258b6345d5ab0b418ca3f010cd7/ruff-0.11.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ddf8967e08227d1bd95cc0851ef80d2ad9c7c0c5aab1eba31db49cf0a7b99523", size = 10160135, upload-time = "2025-05-15T14:08:41.247Z" }, - { url = "https://files.pythonhosted.org/packages/ba/ef/ba7251dd15206688dbfba7d413c0312e94df3b31b08f5d695580b755a899/ruff-0.11.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5a94acf798a82db188f6f36575d80609072b032105d114b0f98661e1679c9125", size = 11170179, upload-time = "2025-05-15T14:08:43.762Z" }, - { url = "https://files.pythonhosted.org/packages/73/9f/5c336717293203ba275dbfa2ea16e49b29a9fd9a0ea8b6febfc17e133577/ruff-0.11.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:3afead355f1d16d95630df28d4ba17fb2cb9c8dfac8d21ced14984121f639bad", size = 11626021, upload-time = "2025-05-15T14:08:46.451Z" }, - { url = "https://files.pythonhosted.org/packages/d9/2b/162fa86d2639076667c9aa59196c020dc6d7023ac8f342416c2f5ec4bda0/ruff-0.11.10-py3-none-win32.whl", hash = "sha256:dc061a98d32a97211af7e7f3fa1d4ca2fcf919fb96c28f39551f35fc55bdbc19", size = 10494958, upload-time = "2025-05-15T14:08:49.601Z" }, - { url = "https://files.pythonhosted.org/packages/24/f3/66643d8f32f50a4b0d09a4832b7d919145ee2b944d43e604fbd7c144d175/ruff-0.11.10-py3-none-win_amd64.whl", hash = "sha256:5cc725fbb4d25b0f185cb42df07ab6b76c4489b4bfb740a175f3a59c70e8a224", size = 11650285, upload-time = "2025-05-15T14:08:52.392Z" }, - { url = "https://files.pythonhosted.org/packages/95/3a/2e8704d19f376c799748ff9cb041225c1d59f3e7711bc5596c8cfdc24925/ruff-0.11.10-py3-none-win_arm64.whl", hash = "sha256:ef69637b35fb8b210743926778d0e45e1bffa850a7c61e428c6b971549b5f5d1", size = 10765278, upload-time = "2025-05-15T14:08:54.56Z" }, + { url = "https://files.pythonhosted.org/packages/74/b6/2098d0126d2d3318fd5bec3ad40d06c25d377d95749f7a0c5af17129b3b1/ruff-0.12.2-py3-none-linux_armv6l.whl", hash = "sha256:093ea2b221df1d2b8e7ad92fc6ffdca40a2cb10d8564477a987b44fd4008a7be", size = 10369761, upload-time = "2025-07-03T16:39:38.847Z" }, + { url = "https://files.pythonhosted.org/packages/b1/4b/5da0142033dbe155dc598cfb99262d8ee2449d76920ea92c4eeb9547c208/ruff-0.12.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:09e4cf27cc10f96b1708100fa851e0daf21767e9709e1649175355280e0d950e", size = 11155659, upload-time = "2025-07-03T16:39:42.294Z" }, + { url = "https://files.pythonhosted.org/packages/3e/21/967b82550a503d7c5c5c127d11c935344b35e8c521f52915fc858fb3e473/ruff-0.12.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:8ae64755b22f4ff85e9c52d1f82644abd0b6b6b6deedceb74bd71f35c24044cc", size = 10537769, upload-time = "2025-07-03T16:39:44.75Z" }, + { url = "https://files.pythonhosted.org/packages/33/91/00cff7102e2ec71a4890fb7ba1803f2cdb122d82787c7d7cf8041fe8cbc1/ruff-0.12.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3eb3a6b2db4d6e2c77e682f0b988d4d61aff06860158fdb413118ca133d57922", size = 10717602, upload-time = "2025-07-03T16:39:47.652Z" }, + { url = "https://files.pythonhosted.org/packages/9b/eb/928814daec4e1ba9115858adcda44a637fb9010618721937491e4e2283b8/ruff-0.12.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:73448de992d05517170fc37169cbca857dfeaeaa8c2b9be494d7bcb0d36c8f4b", size = 10198772, upload-time = "2025-07-03T16:39:49.641Z" }, + { url = "https://files.pythonhosted.org/packages/50/fa/f15089bc20c40f4f72334f9145dde55ab2b680e51afb3b55422effbf2fb6/ruff-0.12.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b8b94317cbc2ae4a2771af641739f933934b03555e51515e6e021c64441532d", size = 11845173, upload-time = "2025-07-03T16:39:52.069Z" }, + { url = "https://files.pythonhosted.org/packages/43/9f/1f6f98f39f2b9302acc161a4a2187b1e3a97634fe918a8e731e591841cf4/ruff-0.12.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:45fc42c3bf1d30d2008023a0a9a0cfb06bf9835b147f11fe0679f21ae86d34b1", size = 12553002, upload-time = "2025-07-03T16:39:54.551Z" }, + { url = "https://files.pythonhosted.org/packages/d8/70/08991ac46e38ddd231c8f4fd05ef189b1b94be8883e8c0c146a025c20a19/ruff-0.12.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce48f675c394c37e958bf229fb5c1e843e20945a6d962cf3ea20b7a107dcd9f4", size = 12171330, upload-time = "2025-07-03T16:39:57.55Z" }, + { url = "https://files.pythonhosted.org/packages/88/a9/5a55266fec474acfd0a1c73285f19dd22461d95a538f29bba02edd07a5d9/ruff-0.12.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:793d8859445ea47591272021a81391350205a4af65a9392401f418a95dfb75c9", size = 11774717, upload-time = "2025-07-03T16:39:59.78Z" }, + { url = "https://files.pythonhosted.org/packages/87/e5/0c270e458fc73c46c0d0f7cf970bb14786e5fdb88c87b5e423a4bd65232b/ruff-0.12.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6932323db80484dda89153da3d8e58164d01d6da86857c79f1961934354992da", size = 11646659, upload-time = "2025-07-03T16:40:01.934Z" }, + { url = "https://files.pythonhosted.org/packages/b7/b6/45ab96070c9752af37f0be364d849ed70e9ccede07675b0ec4e3ef76b63b/ruff-0.12.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6aa7e623a3a11538108f61e859ebf016c4f14a7e6e4eba1980190cacb57714ce", size = 10604012, upload-time = "2025-07-03T16:40:04.363Z" }, + { url = "https://files.pythonhosted.org/packages/86/91/26a6e6a424eb147cc7627eebae095cfa0b4b337a7c1c413c447c9ebb72fd/ruff-0.12.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:2a4a20aeed74671b2def096bdf2eac610c7d8ffcbf4fb0e627c06947a1d7078d", size = 10176799, upload-time = "2025-07-03T16:40:06.514Z" }, + { url = "https://files.pythonhosted.org/packages/f5/0c/9f344583465a61c8918a7cda604226e77b2c548daf8ef7c2bfccf2b37200/ruff-0.12.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:71a4c550195612f486c9d1f2b045a600aeba851b298c667807ae933478fcef04", size = 11241507, upload-time = "2025-07-03T16:40:08.708Z" }, + { url = "https://files.pythonhosted.org/packages/1c/b7/99c34ded8fb5f86c0280278fa89a0066c3760edc326e935ce0b1550d315d/ruff-0.12.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:4987b8f4ceadf597c927beee65a5eaf994c6e2b631df963f86d8ad1bdea99342", size = 11717609, upload-time = "2025-07-03T16:40:10.836Z" }, + { url = "https://files.pythonhosted.org/packages/51/de/8589fa724590faa057e5a6d171e7f2f6cffe3287406ef40e49c682c07d89/ruff-0.12.2-py3-none-win32.whl", hash = "sha256:369ffb69b70cd55b6c3fc453b9492d98aed98062db9fec828cdfd069555f5f1a", size = 10523823, upload-time = "2025-07-03T16:40:13.203Z" }, + { url = "https://files.pythonhosted.org/packages/94/47/8abf129102ae4c90cba0c2199a1a9b0fa896f6f806238d6f8c14448cc748/ruff-0.12.2-py3-none-win_amd64.whl", hash = "sha256:dca8a3b6d6dc9810ed8f328d406516bf4d660c00caeaef36eb831cf4871b0639", size = 11629831, upload-time = "2025-07-03T16:40:15.478Z" }, + { url = "https://files.pythonhosted.org/packages/e2/1f/72d2946e3cc7456bb837e88000eb3437e55f80db339c840c04015a11115d/ruff-0.12.2-py3-none-win_arm64.whl", hash = "sha256:48d6c6bfb4761df68bc05ae630e24f506755e702d4fb08f08460be778c7ccb12", size = 10735334, upload-time = "2025-07-03T16:40:17.677Z" }, ] [[package]] @@ -433,11 +453,11 @@ wheels = [ [[package]] name = "typing-extensions" -version = "4.13.2" +version = "4.14.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f6/37/23083fcd6e35492953e8d2aaaa68b860eb422b34627b13f2ce3eb6106061/typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef", size = 106967, upload-time = "2025-04-10T14:19:05.416Z" } +sdist = { url = "https://files.pythonhosted.org/packages/98/5a/da40306b885cc8c09109dc2e1abd358d5684b1425678151cdaed4731c822/typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36", size = 107673, upload-time = "2025-07-04T13:28:34.16Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806, upload-time = "2025-04-10T14:19:03.967Z" }, + { url = "https://files.pythonhosted.org/packages/b5/00/d631e67a838026495268c2f6884f3711a15a9a2a96cd244fdaea53b823fb/typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76", size = 43906, upload-time = "2025-07-04T13:28:32.743Z" }, ] [[package]] From d5ab8b42e081d04a3e78c6c9d9d1ecc01688680d Mon Sep 17 00:00:00 2001 From: Nick Riley Date: Mon, 7 Jul 2025 16:31:55 -0700 Subject: [PATCH 044/129] Updated examples for SummarizationNode to account for serde with persistence layers (#5257) --- docs/docs/how-tos/memory/add-memory.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/docs/how-tos/memory/add-memory.md b/docs/docs/how-tos/memory/add-memory.md index 4aaf8ec69..408c260aa 100644 --- a/docs/docs/how-tos/memory/add-memory.md +++ b/docs/docs/how-tos/memory/add-memory.md @@ -1351,7 +1351,7 @@ The problem with trimming or removing messages, as shown above, is that you may ```python from langchain_anthropic import ChatAnthropic - from langmem.short_term import SummarizationNode + from langmem.short_term import SummarizationNode, RunningSummary from langchain_core.messages.utils import count_tokens_approximately from langgraph.prebuilt import create_react_agent from langgraph.prebuilt.chat_agent_executor import AgentState @@ -1372,7 +1372,7 @@ The problem with trimming or removing messages, as shown above, is that you may # NOTE: we're adding this key to keep track of previous summary information # to make sure we're not summarizing on every LLM call # highlight-next-line - context: dict[str, Any] # (2)! + context: dict[str, RunningSummary] # (2)! checkpointer = InMemorySaver() # (3)! @@ -1447,18 +1447,18 @@ The problem with trimming or removing messages, as shown above, is that you may from langgraph.graph import StateGraph, START, MessagesState from langgraph.checkpoint.memory import InMemorySaver # highlight-next-line - from langmem.short_term import SummarizationNode + from langmem.short_term import SummarizationNode, RunningSummary model = init_chat_model("anthropic:claude-3-7-sonnet-latest") summarization_model = model.bind(max_tokens=128) class State(MessagesState): # highlight-next-line - context: dict[str, Any] # (1)! + context: dict[str, RunningSummary] # (1)! class LLMInputState(TypedDict): # (2)! summarized_messages: list[AnyMessage] - context: dict[str, Any] + context: dict[str, RunningSummary] # highlight-next-line summarization_node = SummarizationNode( From 6f86a8c4cbbe04e98d980eae59e7c12bf89377ad Mon Sep 17 00:00:00 2001 From: lc-arjun Date: Tue, 8 Jul 2025 06:49:13 -0700 Subject: [PATCH 045/129] Revert "docs: add -tunnel flag for node server" (#5397) Revert "docs: add -tunnel flag for node server (#5373)" This reverts commit 4abf94846241f3546a0194efd40e109745e7d005. --- docs/docs/troubleshooting/studio.md | 4 +- libs/sdk-js/client.cjs | 1 - libs/sdk-js/client.d.cts | 1 - libs/sdk-js/client.d.ts | 1 - libs/sdk-js/client.js | 1 - libs/sdk-js/docs/README.md | 26 - libs/sdk-js/docs/auth/README.md | 18 - libs/sdk-js/docs/auth/classes/Auth.md | 75 --- .../sdk-js/docs/auth/classes/HTTPException.md | 185 ------- .../docs/auth/interfaces/AuthEventValueMap.md | 481 ------------------ .../docs/auth/type-aliases/AuthFilters.md | 15 - libs/sdk-js/docs/classes/AssistantsClient.md | 385 -------------- libs/sdk-js/docs/classes/Client.md | 98 ---- libs/sdk-js/docs/classes/CronsClient.md | 151 ------ libs/sdk-js/docs/classes/RunsClient.md | 469 ----------------- libs/sdk-js/docs/classes/StoreClient.md | 314 ------------ libs/sdk-js/docs/classes/ThreadsClient.md | 433 ---------------- libs/sdk-js/docs/functions/getApiKey.md | 32 -- libs/sdk-js/docs/interfaces/ClientConfig.md | 57 --- libs/sdk-js/docs/react/README.md | 18 - libs/sdk-js/docs/react/functions/useStream.md | 27 - .../sdk-js/docs/react/interfaces/UseStream.md | 227 --------- .../docs/react/interfaces/UseStreamOptions.md | 343 ------------- .../react/type-aliases/MessageMetadata.md | 42 -- libs/sdk-js/docs/type-aliases/RequestHook.md | 25 - libs/sdk-js/index.cjs | 1 - libs/sdk-js/index.d.cts | 1 - libs/sdk-js/index.d.ts | 1 - libs/sdk-js/index.js | 1 - libs/sdk-js/react.cjs | 1 - libs/sdk-js/react.d.cts | 1 - libs/sdk-js/react.d.ts | 1 - libs/sdk-js/react.js | 1 - 33 files changed, 2 insertions(+), 3435 deletions(-) delete mode 100644 libs/sdk-js/client.cjs delete mode 100644 libs/sdk-js/client.d.cts delete mode 100644 libs/sdk-js/client.d.ts delete mode 100644 libs/sdk-js/client.js delete mode 100644 libs/sdk-js/docs/README.md delete mode 100644 libs/sdk-js/docs/auth/README.md delete mode 100644 libs/sdk-js/docs/auth/classes/Auth.md delete mode 100644 libs/sdk-js/docs/auth/classes/HTTPException.md delete mode 100644 libs/sdk-js/docs/auth/interfaces/AuthEventValueMap.md delete mode 100644 libs/sdk-js/docs/auth/type-aliases/AuthFilters.md delete mode 100644 libs/sdk-js/docs/classes/AssistantsClient.md delete mode 100644 libs/sdk-js/docs/classes/Client.md delete mode 100644 libs/sdk-js/docs/classes/CronsClient.md delete mode 100644 libs/sdk-js/docs/classes/RunsClient.md delete mode 100644 libs/sdk-js/docs/classes/StoreClient.md delete mode 100644 libs/sdk-js/docs/classes/ThreadsClient.md delete mode 100644 libs/sdk-js/docs/functions/getApiKey.md delete mode 100644 libs/sdk-js/docs/interfaces/ClientConfig.md delete mode 100644 libs/sdk-js/docs/react/README.md delete mode 100644 libs/sdk-js/docs/react/functions/useStream.md delete mode 100644 libs/sdk-js/docs/react/interfaces/UseStream.md delete mode 100644 libs/sdk-js/docs/react/interfaces/UseStreamOptions.md delete mode 100644 libs/sdk-js/docs/react/type-aliases/MessageMetadata.md delete mode 100644 libs/sdk-js/docs/type-aliases/RequestHook.md delete mode 100644 libs/sdk-js/index.cjs delete mode 100644 libs/sdk-js/index.d.cts delete mode 100644 libs/sdk-js/index.d.ts delete mode 100644 libs/sdk-js/index.js delete mode 100644 libs/sdk-js/react.cjs delete mode 100644 libs/sdk-js/react.d.cts delete mode 100644 libs/sdk-js/react.d.ts delete mode 100644 libs/sdk-js/react.js diff --git a/docs/docs/troubleshooting/studio.md b/docs/docs/troubleshooting/studio.md index 3fcbdea7f..b06f325de 100644 --- a/docs/docs/troubleshooting/studio.md +++ b/docs/docs/troubleshooting/studio.md @@ -17,7 +17,7 @@ Safari blocks plain-HTTP traffic on localhost. When running Studio with `langgra ```shell # Requires @langchain/langgraph-cli>=0.0.26 - npx @langchain/langgraph-cli dev --tunnel + npx @langchain/langgraph-cli dev ``` The command outputs a URL in this format: @@ -55,7 +55,7 @@ Disable Brave Shields for LangSmith using the Brave icon in the URL bar. ```shell # Requires @langchain/langgraph-cli>=0.0.26 - npx @langchain/langgraph-cli dev --tunnel + npx @langchain/langgraph-cli dev ``` The command outputs a URL in this format: diff --git a/libs/sdk-js/client.cjs b/libs/sdk-js/client.cjs deleted file mode 100644 index 680e5bd38..000000000 --- a/libs/sdk-js/client.cjs +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./dist/client.cjs'); \ No newline at end of file diff --git a/libs/sdk-js/client.d.cts b/libs/sdk-js/client.d.cts deleted file mode 100644 index 1c03ff9cb..000000000 --- a/libs/sdk-js/client.d.cts +++ /dev/null @@ -1 +0,0 @@ -export * from './dist/client.js' \ No newline at end of file diff --git a/libs/sdk-js/client.d.ts b/libs/sdk-js/client.d.ts deleted file mode 100644 index 1c03ff9cb..000000000 --- a/libs/sdk-js/client.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './dist/client.js' \ No newline at end of file diff --git a/libs/sdk-js/client.js b/libs/sdk-js/client.js deleted file mode 100644 index 1c03ff9cb..000000000 --- a/libs/sdk-js/client.js +++ /dev/null @@ -1 +0,0 @@ -export * from './dist/client.js' \ No newline at end of file diff --git a/libs/sdk-js/docs/README.md b/libs/sdk-js/docs/README.md deleted file mode 100644 index a1627b448..000000000 --- a/libs/sdk-js/docs/README.md +++ /dev/null @@ -1,26 +0,0 @@ -**@langchain/langgraph-sdk** - -*** - -# @langchain/langgraph-sdk - -## Classes - -- [AssistantsClient](classes/AssistantsClient.md) -- [Client](classes/Client.md) -- [CronsClient](classes/CronsClient.md) -- [RunsClient](classes/RunsClient.md) -- [StoreClient](classes/StoreClient.md) -- [ThreadsClient](classes/ThreadsClient.md) - -## Interfaces - -- [ClientConfig](interfaces/ClientConfig.md) - -## Type Aliases - -- [RequestHook](type-aliases/RequestHook.md) - -## Functions - -- [getApiKey](functions/getApiKey.md) diff --git a/libs/sdk-js/docs/auth/README.md b/libs/sdk-js/docs/auth/README.md deleted file mode 100644 index 351cb8490..000000000 --- a/libs/sdk-js/docs/auth/README.md +++ /dev/null @@ -1,18 +0,0 @@ -**@langchain/langgraph-sdk** - -*** - -# @langchain/langgraph-sdk/auth - -## Classes - -- [Auth](classes/Auth.md) -- [HTTPException](classes/HTTPException.md) - -## Interfaces - -- [AuthEventValueMap](interfaces/AuthEventValueMap.md) - -## Type Aliases - -- [AuthFilters](type-aliases/AuthFilters.md) diff --git a/libs/sdk-js/docs/auth/classes/Auth.md b/libs/sdk-js/docs/auth/classes/Auth.md deleted file mode 100644 index 4b4cc618a..000000000 --- a/libs/sdk-js/docs/auth/classes/Auth.md +++ /dev/null @@ -1,75 +0,0 @@ -[**@langchain/langgraph-sdk**](../README.md) - -*** - -[@langchain/langgraph-sdk](../README.md) / Auth - -# Class: Auth\ - -Defined in: [src/auth/index.ts:11](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/index.ts#L11) - -## Type Parameters - -• **TExtra** = \{\} - -• **TAuthReturn** *extends* `BaseAuthReturn` = `BaseAuthReturn` - -• **TUser** *extends* `BaseUser` = `ToUserLike`\<`TAuthReturn`\> - -## Constructors - -### new Auth() - -> **new Auth**\<`TExtra`, `TAuthReturn`, `TUser`\>(): [`Auth`](Auth.md)\<`TExtra`, `TAuthReturn`, `TUser`\> - -#### Returns - -[`Auth`](Auth.md)\<`TExtra`, `TAuthReturn`, `TUser`\> - -## Methods - -### authenticate() - -> **authenticate**\<`T`\>(`cb`): [`Auth`](Auth.md)\<`TExtra`, `T`\> - -Defined in: [src/auth/index.ts:25](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/index.ts#L25) - -#### Type Parameters - -• **T** *extends* `BaseAuthReturn` - -#### Parameters - -##### cb - -`AuthenticateCallback`\<`T`\> - -#### Returns - -[`Auth`](Auth.md)\<`TExtra`, `T`\> - -*** - -### on() - -> **on**\<`T`\>(`event`, `callback`): `this` - -Defined in: [src/auth/index.ts:32](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/index.ts#L32) - -#### Type Parameters - -• **T** *extends* `CallbackEvent` - -#### Parameters - -##### event - -`T` - -##### callback - -`OnCallback`\<`T`, `TUser`\> - -#### Returns - -`this` diff --git a/libs/sdk-js/docs/auth/classes/HTTPException.md b/libs/sdk-js/docs/auth/classes/HTTPException.md deleted file mode 100644 index 0db191af5..000000000 --- a/libs/sdk-js/docs/auth/classes/HTTPException.md +++ /dev/null @@ -1,185 +0,0 @@ -[**@langchain/langgraph-sdk**](../README.md) - -*** - -[@langchain/langgraph-sdk](../README.md) / HTTPException - -# Class: HTTPException - -Defined in: [src/auth/error.ts:66](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/error.ts#L66) - -## Extends - -- `Error` - -## Constructors - -### new HTTPException() - -> **new HTTPException**(`status`, `options`?): [`HTTPException`](HTTPException.md) - -Defined in: [src/auth/error.ts:70](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/error.ts#L70) - -#### Parameters - -##### status - -`number` - -##### options? - -###### cause? - -`unknown` - -###### headers? - -`HeadersInit` - -###### message? - -`string` - -#### Returns - -[`HTTPException`](HTTPException.md) - -#### Overrides - -`Error.constructor` - -## Properties - -### cause? - -> `optional` **cause**: `unknown` - -Defined in: node\_modules/typescript/lib/lib.es2022.error.d.ts:24 - -#### Inherited from - -`Error.cause` - -*** - -### headers - -> **headers**: `HeadersInit` - -Defined in: [src/auth/error.ts:68](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/error.ts#L68) - -*** - -### message - -> **message**: `string` - -Defined in: node\_modules/typescript/lib/lib.es5.d.ts:1077 - -#### Inherited from - -`Error.message` - -*** - -### name - -> **name**: `string` - -Defined in: node\_modules/typescript/lib/lib.es5.d.ts:1076 - -#### Inherited from - -`Error.name` - -*** - -### stack? - -> `optional` **stack**: `string` - -Defined in: node\_modules/typescript/lib/lib.es5.d.ts:1078 - -#### Inherited from - -`Error.stack` - -*** - -### status - -> **status**: `number` - -Defined in: [src/auth/error.ts:67](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/error.ts#L67) - -*** - -### prepareStackTrace()? - -> `static` `optional` **prepareStackTrace**: (`err`, `stackTraces`) => `any` - -Defined in: node\_modules/@types/node/globals.d.ts:28 - -Optional override for formatting stack traces - -#### Parameters - -##### err - -`Error` - -##### stackTraces - -`CallSite`[] - -#### Returns - -`any` - -#### See - -https://v8.dev/docs/stack-trace-api#customizing-stack-traces - -#### Inherited from - -`Error.prepareStackTrace` - -*** - -### stackTraceLimit - -> `static` **stackTraceLimit**: `number` - -Defined in: node\_modules/@types/node/globals.d.ts:30 - -#### Inherited from - -`Error.stackTraceLimit` - -## Methods - -### captureStackTrace() - -> `static` **captureStackTrace**(`targetObject`, `constructorOpt`?): `void` - -Defined in: node\_modules/@types/node/globals.d.ts:21 - -Create .stack property on a target object - -#### Parameters - -##### targetObject - -`object` - -##### constructorOpt? - -`Function` - -#### Returns - -`void` - -#### Inherited from - -`Error.captureStackTrace` diff --git a/libs/sdk-js/docs/auth/interfaces/AuthEventValueMap.md b/libs/sdk-js/docs/auth/interfaces/AuthEventValueMap.md deleted file mode 100644 index 686e1a39b..000000000 --- a/libs/sdk-js/docs/auth/interfaces/AuthEventValueMap.md +++ /dev/null @@ -1,481 +0,0 @@ -[**@langchain/langgraph-sdk**](../README.md) - -*** - -[@langchain/langgraph-sdk](../README.md) / AuthEventValueMap - -# Interface: AuthEventValueMap - -Defined in: [src/auth/types.ts:218](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L218) - -## Properties - -### assistants:create - -> **assistants:create**: `object` - -Defined in: [src/auth/types.ts:226](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L226) - -#### assistant\_id? - -> `optional` **assistant\_id**: `Maybe`\<`string`\> - -#### config? - -> `optional` **config**: `Maybe`\<`AssistantConfig`\> - -#### graph\_id - -> **graph\_id**: `string` - -#### if\_exists? - -> `optional` **if\_exists**: `Maybe`\<`"raise"` \| `"do_nothing"`\> - -#### metadata? - -> `optional` **metadata**: `Maybe`\<`Record`\<`string`, `unknown`\>\> - -#### name? - -> `optional` **name**: `Maybe`\<`string`\> - -*** - -### assistants:delete - -> **assistants:delete**: `object` - -Defined in: [src/auth/types.ts:229](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L229) - -#### assistant\_id - -> **assistant\_id**: `string` - -*** - -### assistants:read - -> **assistants:read**: `object` - -Defined in: [src/auth/types.ts:227](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L227) - -#### assistant\_id - -> **assistant\_id**: `string` - -#### metadata? - -> `optional` **metadata**: `Maybe`\<`Record`\<`string`, `unknown`\>\> - -*** - -### assistants:search - -> **assistants:search**: `object` - -Defined in: [src/auth/types.ts:230](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L230) - -#### graph\_id? - -> `optional` **graph\_id**: `Maybe`\<`string`\> - -#### limit? - -> `optional` **limit**: `Maybe`\<`number`\> - -#### metadata? - -> `optional` **metadata**: `Maybe`\<`Record`\<`string`, `unknown`\>\> - -#### offset? - -> `optional` **offset**: `Maybe`\<`number`\> - -*** - -### assistants:update - -> **assistants:update**: `object` - -Defined in: [src/auth/types.ts:228](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L228) - -#### assistant\_id - -> **assistant\_id**: `string` - -#### config? - -> `optional` **config**: `Maybe`\<`AssistantConfig`\> - -#### graph\_id? - -> `optional` **graph\_id**: `Maybe`\<`string`\> - -#### metadata? - -> `optional` **metadata**: `Maybe`\<`Record`\<`string`, `unknown`\>\> - -#### name? - -> `optional` **name**: `Maybe`\<`string`\> - -#### version? - -> `optional` **version**: `Maybe`\<`number`\> - -*** - -### crons:create - -> **crons:create**: `object` - -Defined in: [src/auth/types.ts:232](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L232) - -#### cron\_id? - -> `optional` **cron\_id**: `Maybe`\<`string`\> - -#### end\_time? - -> `optional` **end\_time**: `Maybe`\<`string`\> - -#### payload? - -> `optional` **payload**: `Maybe`\<`Record`\<`string`, `unknown`\>\> - -#### schedule - -> **schedule**: `string` - -#### thread\_id? - -> `optional` **thread\_id**: `Maybe`\<`string`\> - -#### user\_id? - -> `optional` **user\_id**: `Maybe`\<`string`\> - -*** - -### crons:delete - -> **crons:delete**: `object` - -Defined in: [src/auth/types.ts:235](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L235) - -#### cron\_id - -> **cron\_id**: `string` - -*** - -### crons:read - -> **crons:read**: `object` - -Defined in: [src/auth/types.ts:233](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L233) - -#### cron\_id - -> **cron\_id**: `string` - -*** - -### crons:search - -> **crons:search**: `object` - -Defined in: [src/auth/types.ts:236](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L236) - -#### assistant\_id? - -> `optional` **assistant\_id**: `Maybe`\<`string`\> - -#### limit? - -> `optional` **limit**: `Maybe`\<`number`\> - -#### offset? - -> `optional` **offset**: `Maybe`\<`number`\> - -#### thread\_id? - -> `optional` **thread\_id**: `Maybe`\<`string`\> - -*** - -### crons:update - -> **crons:update**: `object` - -Defined in: [src/auth/types.ts:234](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L234) - -#### cron\_id - -> **cron\_id**: `string` - -#### payload? - -> `optional` **payload**: `Maybe`\<`Record`\<`string`, `unknown`\>\> - -#### schedule? - -> `optional` **schedule**: `Maybe`\<`string`\> - -*** - -### store:delete - -> **store:delete**: `object` - -Defined in: [src/auth/types.ts:242](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L242) - -#### key - -> **key**: `string` - -#### namespace? - -> `optional` **namespace**: `Maybe`\<`string`[]\> - -*** - -### store:get - -> **store:get**: `object` - -Defined in: [src/auth/types.ts:239](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L239) - -#### key - -> **key**: `string` - -#### namespace - -> **namespace**: `Maybe`\<`string`[]\> - -*** - -### store:list\_namespaces - -> **store:list\_namespaces**: `object` - -Defined in: [src/auth/types.ts:241](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L241) - -#### limit? - -> `optional` **limit**: `Maybe`\<`number`\> - -#### max\_depth? - -> `optional` **max\_depth**: `Maybe`\<`number`\> - -#### namespace? - -> `optional` **namespace**: `Maybe`\<`string`[]\> - -#### offset? - -> `optional` **offset**: `Maybe`\<`number`\> - -#### suffix? - -> `optional` **suffix**: `Maybe`\<`string`[]\> - -*** - -### store:put - -> **store:put**: `object` - -Defined in: [src/auth/types.ts:238](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L238) - -#### key - -> **key**: `string` - -#### namespace - -> **namespace**: `string`[] - -#### value - -> **value**: `Record`\<`string`, `unknown`\> - -*** - -### store:search - -> **store:search**: `object` - -Defined in: [src/auth/types.ts:240](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L240) - -#### filter? - -> `optional` **filter**: `Maybe`\<`Record`\<`string`, `unknown`\>\> - -#### limit? - -> `optional` **limit**: `Maybe`\<`number`\> - -#### namespace? - -> `optional` **namespace**: `Maybe`\<`string`[]\> - -#### offset? - -> `optional` **offset**: `Maybe`\<`number`\> - -#### query? - -> `optional` **query**: `Maybe`\<`string`\> - -*** - -### threads:create - -> **threads:create**: `object` - -Defined in: [src/auth/types.ts:219](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L219) - -#### if\_exists? - -> `optional` **if\_exists**: `Maybe`\<`"raise"` \| `"do_nothing"`\> - -#### metadata? - -> `optional` **metadata**: `Maybe`\<`Record`\<`string`, `unknown`\>\> - -#### thread\_id? - -> `optional` **thread\_id**: `Maybe`\<`string`\> - -*** - -### threads:create\_run - -> **threads:create\_run**: `object` - -Defined in: [src/auth/types.ts:224](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L224) - -#### after\_seconds? - -> `optional` **after\_seconds**: `Maybe`\<`number`\> - -#### assistant\_id - -> **assistant\_id**: `string` - -#### if\_not\_exists? - -> `optional` **if\_not\_exists**: `Maybe`\<`"reject"` \| `"create"`\> - -#### kwargs - -> **kwargs**: `Record`\<`string`, `unknown`\> - -#### metadata? - -> `optional` **metadata**: `Maybe`\<`Record`\<`string`, `unknown`\>\> - -#### multitask\_strategy? - -> `optional` **multitask\_strategy**: `Maybe`\<`"reject"` \| `"interrupt"` \| `"rollback"` \| `"enqueue"`\> - -#### prevent\_insert\_if\_inflight? - -> `optional` **prevent\_insert\_if\_inflight**: `Maybe`\<`boolean`\> - -#### run\_id - -> **run\_id**: `string` - -#### status - -> **status**: `Maybe`\<`"pending"` \| `"running"` \| `"error"` \| `"success"` \| `"timeout"` \| `"interrupted"`\> - -#### thread\_id? - -> `optional` **thread\_id**: `Maybe`\<`string`\> - -*** - -### threads:delete - -> **threads:delete**: `object` - -Defined in: [src/auth/types.ts:222](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L222) - -#### run\_id? - -> `optional` **run\_id**: `Maybe`\<`string`\> - -#### thread\_id? - -> `optional` **thread\_id**: `Maybe`\<`string`\> - -*** - -### threads:read - -> **threads:read**: `object` - -Defined in: [src/auth/types.ts:220](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L220) - -#### thread\_id? - -> `optional` **thread\_id**: `Maybe`\<`string`\> - -*** - -### threads:search - -> **threads:search**: `object` - -Defined in: [src/auth/types.ts:223](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L223) - -#### limit? - -> `optional` **limit**: `Maybe`\<`number`\> - -#### metadata? - -> `optional` **metadata**: `Maybe`\<`Record`\<`string`, `unknown`\>\> - -#### offset? - -> `optional` **offset**: `Maybe`\<`number`\> - -#### status? - -> `optional` **status**: `Maybe`\<`"error"` \| `"interrupted"` \| `"idle"` \| `"busy"` \| `string` & `object`\> - -#### thread\_id? - -> `optional` **thread\_id**: `Maybe`\<`string`\> - -#### values? - -> `optional` **values**: `Maybe`\<`Record`\<`string`, `unknown`\>\> - -*** - -### threads:update - -> **threads:update**: `object` - -Defined in: [src/auth/types.ts:221](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L221) - -#### action? - -> `optional` **action**: `Maybe`\<`"interrupt"` \| `"rollback"`\> - -#### metadata? - -> `optional` **metadata**: `Maybe`\<`Record`\<`string`, `unknown`\>\> - -#### thread\_id? - -> `optional` **thread\_id**: `Maybe`\<`string`\> diff --git a/libs/sdk-js/docs/auth/type-aliases/AuthFilters.md b/libs/sdk-js/docs/auth/type-aliases/AuthFilters.md deleted file mode 100644 index b9b2e1fb2..000000000 --- a/libs/sdk-js/docs/auth/type-aliases/AuthFilters.md +++ /dev/null @@ -1,15 +0,0 @@ -[**@langchain/langgraph-sdk**](../README.md) - -*** - -[@langchain/langgraph-sdk](../README.md) / AuthFilters - -# Type Alias: AuthFilters\ - -> **AuthFilters**\<`TKey`\>: \{ \[key in TKey\]: string \| \{ \[op in "$contains" \| "$eq"\]?: string \} \} - -Defined in: [src/auth/types.ts:367](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/auth/types.ts#L367) - -## Type Parameters - -• **TKey** *extends* `string` \| `number` \| `symbol` diff --git a/libs/sdk-js/docs/classes/AssistantsClient.md b/libs/sdk-js/docs/classes/AssistantsClient.md deleted file mode 100644 index 571dc16e8..000000000 --- a/libs/sdk-js/docs/classes/AssistantsClient.md +++ /dev/null @@ -1,385 +0,0 @@ -[**@langchain/langgraph-sdk**](../README.md) - -*** - -[@langchain/langgraph-sdk](../README.md) / AssistantsClient - -# Class: AssistantsClient - -Defined in: [client.ts:431](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L431) - -## Extends - -- `BaseClient` - -## Constructors - -### new AssistantsClient() - -> **new AssistantsClient**(`config`?): [`AssistantsClient`](AssistantsClient.md) - -Defined in: [client.ts:183](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L183) - -#### Parameters - -##### config? - -[`ClientConfig`](../interfaces/ClientConfig.md) - -#### Returns - -[`AssistantsClient`](AssistantsClient.md) - -#### Inherited from - -`BaseClient.constructor` - -## Methods - -### create() - -> **create**(`payload`): `Promise`\<`Assistant`\> - -Defined in: [client.ts:496](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L496) - -Create a new assistant. - -#### Parameters - -##### payload - -Payload for creating an assistant. - -###### assistantId? - -`string` - -###### config? - -`Config` - -###### description? - -`string` - -###### graphId - -`string` - -###### ifExists? - -`OnConflictBehavior` - -###### metadata? - -`Metadata` - -###### name? - -`string` - -#### Returns - -`Promise`\<`Assistant`\> - -The created assistant. - -*** - -### delete() - -> **delete**(`assistantId`): `Promise`\<`void`\> - -Defined in: [client.ts:552](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L552) - -Delete an assistant. - -#### Parameters - -##### assistantId - -`string` - -ID of the assistant. - -#### Returns - -`Promise`\<`void`\> - -*** - -### get() - -> **get**(`assistantId`): `Promise`\<`Assistant`\> - -Defined in: [client.ts:438](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L438) - -Get an assistant by ID. - -#### Parameters - -##### assistantId - -`string` - -The ID of the assistant. - -#### Returns - -`Promise`\<`Assistant`\> - -Assistant - -*** - -### getGraph() - -> **getGraph**(`assistantId`, `options`?): `Promise`\<`AssistantGraph`\> - -Defined in: [client.ts:448](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L448) - -Get the JSON representation of the graph assigned to a runnable - -#### Parameters - -##### assistantId - -`string` - -The ID of the assistant. - -##### options? - -###### xray? - -`number` \| `boolean` - -Whether to include subgraphs in the serialized graph representation. If an integer value is provided, only subgraphs with a depth less than or equal to the value will be included. - -#### Returns - -`Promise`\<`AssistantGraph`\> - -Serialized graph - -*** - -### getSchemas() - -> **getSchemas**(`assistantId`): `Promise`\<`GraphSchema`\> - -Defined in: [client.ts:462](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L462) - -Get the state and config schema of the graph assigned to a runnable - -#### Parameters - -##### assistantId - -`string` - -The ID of the assistant. - -#### Returns - -`Promise`\<`GraphSchema`\> - -Graph schema - -*** - -### getSubgraphs() - -> **getSubgraphs**(`assistantId`, `options`?): `Promise`\<`Subgraphs`\> - -Defined in: [client.ts:473](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L473) - -Get the schemas of an assistant by ID. - -#### Parameters - -##### assistantId - -`string` - -The ID of the assistant to get the schema of. - -##### options? - -Additional options for getting subgraphs, such as namespace or recursion extraction. - -###### namespace? - -`string` - -###### recurse? - -`boolean` - -#### Returns - -`Promise`\<`Subgraphs`\> - -The subgraphs of the assistant. - -*** - -### getVersions() - -> **getVersions**(`assistantId`, `payload`?): `Promise`\<`AssistantVersion`[]\> - -Defined in: [client.ts:590](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L590) - -List all versions of an assistant. - -#### Parameters - -##### assistantId - -`string` - -ID of the assistant. - -##### payload? - -###### limit? - -`number` - -###### metadata? - -`Metadata` - -###### offset? - -`number` - -#### Returns - -`Promise`\<`AssistantVersion`[]\> - -List of assistant versions. - -*** - -### search() - -> **search**(`query`?): `Promise`\<`Assistant`[]\> - -Defined in: [client.ts:563](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L563) - -List assistants. - -#### Parameters - -##### query? - -Query options. - -###### graphId? - -`string` - -###### limit? - -`number` - -###### metadata? - -`Metadata` - -###### offset? - -`number` - -###### sortBy? - -`AssistantSortBy` - -###### sortOrder? - -`SortOrder` - -#### Returns - -`Promise`\<`Assistant`[]\> - -List of assistants. - -*** - -### setLatest() - -> **setLatest**(`assistantId`, `version`): `Promise`\<`Assistant`\> - -Defined in: [client.ts:618](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L618) - -Change the version of an assistant. - -#### Parameters - -##### assistantId - -`string` - -ID of the assistant. - -##### version - -`number` - -The version to change to. - -#### Returns - -`Promise`\<`Assistant`\> - -The updated assistant. - -*** - -### update() - -> **update**(`assistantId`, `payload`): `Promise`\<`Assistant`\> - -Defined in: [client.ts:525](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L525) - -Update an assistant. - -#### Parameters - -##### assistantId - -`string` - -ID of the assistant. - -##### payload - -Payload for updating the assistant. - -###### config? - -`Config` - -###### description? - -`string` - -###### graphId? - -`string` - -###### metadata? - -`Metadata` - -###### name? - -`string` - -#### Returns - -`Promise`\<`Assistant`\> - -The updated assistant. diff --git a/libs/sdk-js/docs/classes/Client.md b/libs/sdk-js/docs/classes/Client.md deleted file mode 100644 index b0afc23de..000000000 --- a/libs/sdk-js/docs/classes/Client.md +++ /dev/null @@ -1,98 +0,0 @@ -[**@langchain/langgraph-sdk**](../README.md) - -*** - -[@langchain/langgraph-sdk](../README.md) / Client - -# Class: Client\ - -Defined in: [client.ts:1620](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1620) - -## Type Parameters - -• **TStateType** = `DefaultValues` - -• **TUpdateType** = `TStateType` - -• **TCustomEventType** = `unknown` - -## Constructors - -### new Client() - -> **new Client**\<`TStateType`, `TUpdateType`, `TCustomEventType`\>(`config`?): [`Client`](Client.md)\<`TStateType`, `TUpdateType`, `TCustomEventType`\> - -Defined in: [client.ts:1656](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1656) - -#### Parameters - -##### config? - -[`ClientConfig`](../interfaces/ClientConfig.md) - -#### Returns - -[`Client`](Client.md)\<`TStateType`, `TUpdateType`, `TCustomEventType`\> - -## Properties - -### ~ui - -> **~ui**: `UiClient` - -Defined in: [client.ts:1654](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1654) - -**`Internal`** - -The client for interacting with the UI. - Used by LoadExternalComponent and the API might change in the future. - -*** - -### assistants - -> **assistants**: [`AssistantsClient`](AssistantsClient.md) - -Defined in: [client.ts:1628](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1628) - -The client for interacting with assistants. - -*** - -### crons - -> **crons**: [`CronsClient`](CronsClient.md) - -Defined in: [client.ts:1643](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1643) - -The client for interacting with cron runs. - -*** - -### runs - -> **runs**: [`RunsClient`](RunsClient.md)\<`TStateType`, `TUpdateType`, `TCustomEventType`\> - -Defined in: [client.ts:1638](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1638) - -The client for interacting with runs. - -*** - -### store - -> **store**: [`StoreClient`](StoreClient.md) - -Defined in: [client.ts:1648](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1648) - -The client for interacting with the KV store. - -*** - -### threads - -> **threads**: [`ThreadsClient`](ThreadsClient.md)\<`TStateType`, `TUpdateType`\> - -Defined in: [client.ts:1633](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1633) - -The client for interacting with threads. diff --git a/libs/sdk-js/docs/classes/CronsClient.md b/libs/sdk-js/docs/classes/CronsClient.md deleted file mode 100644 index ae0017d9c..000000000 --- a/libs/sdk-js/docs/classes/CronsClient.md +++ /dev/null @@ -1,151 +0,0 @@ -[**@langchain/langgraph-sdk**](../README.md) - -*** - -[@langchain/langgraph-sdk](../README.md) / CronsClient - -# Class: CronsClient - -Defined in: [client.ts:334](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L334) - -## Extends - -- `BaseClient` - -## Constructors - -### new CronsClient() - -> **new CronsClient**(`config`?): [`CronsClient`](CronsClient.md) - -Defined in: [client.ts:183](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L183) - -#### Parameters - -##### config? - -[`ClientConfig`](../interfaces/ClientConfig.md) - -#### Returns - -[`CronsClient`](CronsClient.md) - -#### Inherited from - -`BaseClient.constructor` - -## Methods - -### create() - -> **create**(`assistantId`, `payload`?): `Promise`\<`CronCreateResponse`\> - -Defined in: [client.ts:375](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L375) - -#### Parameters - -##### assistantId - -`string` - -Assistant ID to use for this cron job. - -##### payload? - -`CronsCreatePayload` - -Payload for creating a cron job. - -#### Returns - -`Promise`\<`CronCreateResponse`\> - -*** - -### createForThread() - -> **createForThread**(`threadId`, `assistantId`, `payload`?): `Promise`\<`CronCreateForThreadResponse`\> - -Defined in: [client.ts:342](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L342) - -#### Parameters - -##### threadId - -`string` - -The ID of the thread. - -##### assistantId - -`string` - -Assistant ID to use for this cron job. - -##### payload? - -`CronsCreatePayload` - -Payload for creating a cron job. - -#### Returns - -`Promise`\<`CronCreateForThreadResponse`\> - -The created background run. - -*** - -### delete() - -> **delete**(`cronId`): `Promise`\<`void`\> - -Defined in: [client.ts:402](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L402) - -#### Parameters - -##### cronId - -`string` - -Cron ID of Cron job to delete. - -#### Returns - -`Promise`\<`void`\> - -*** - -### search() - -> **search**(`query`?): `Promise`\<`Cron`[]\> - -Defined in: [client.ts:413](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L413) - -#### Parameters - -##### query? - -Query options. - -###### assistantId? - -`string` - -###### limit? - -`number` - -###### offset? - -`number` - -###### threadId? - -`string` - -#### Returns - -`Promise`\<`Cron`[]\> - -List of crons. diff --git a/libs/sdk-js/docs/classes/RunsClient.md b/libs/sdk-js/docs/classes/RunsClient.md deleted file mode 100644 index 15f666453..000000000 --- a/libs/sdk-js/docs/classes/RunsClient.md +++ /dev/null @@ -1,469 +0,0 @@ -[**@langchain/langgraph-sdk**](../README.md) - -*** - -[@langchain/langgraph-sdk](../README.md) / RunsClient - -# Class: RunsClient\ - -Defined in: [client.ts:912](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L912) - -## Extends - -- `BaseClient` - -## Type Parameters - -• **TStateType** = `DefaultValues` - -• **TUpdateType** = `TStateType` - -• **TCustomEventType** = `unknown` - -## Constructors - -### new RunsClient() - -> **new RunsClient**\<`TStateType`, `TUpdateType`, `TCustomEventType`\>(`config`?): [`RunsClient`](RunsClient.md)\<`TStateType`, `TUpdateType`, `TCustomEventType`\> - -Defined in: [client.ts:183](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L183) - -#### Parameters - -##### config? - -[`ClientConfig`](../interfaces/ClientConfig.md) - -#### Returns - -[`RunsClient`](RunsClient.md)\<`TStateType`, `TUpdateType`, `TCustomEventType`\> - -#### Inherited from - -`BaseClient.constructor` - -## Methods - -### cancel() - -> **cancel**(`threadId`, `runId`, `wait`, `action`): `Promise`\<`void`\> - -Defined in: [client.ts:1227](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1227) - -Cancel a run. - -#### Parameters - -##### threadId - -`string` - -The ID of the thread. - -##### runId - -`string` - -The ID of the run. - -##### wait - -`boolean` = `false` - -Whether to block when canceling - -##### action - -`CancelAction` = `"interrupt"` - -Action to take when cancelling the run. Possible values are `interrupt` or `rollback`. Default is `interrupt`. - -#### Returns - -`Promise`\<`void`\> - -*** - -### create() - -> **create**(`threadId`, `assistantId`, `payload`?): `Promise`\<`Run`\> - -Defined in: [client.ts:1026](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1026) - -Create a run. - -#### Parameters - -##### threadId - -`string` - -The ID of the thread. - -##### assistantId - -`string` - -Assistant ID to use for this run. - -##### payload? - -`RunsCreatePayload` - -Payload for creating a run. - -#### Returns - -`Promise`\<`Run`\> - -The created run. - -*** - -### createBatch() - -> **createBatch**(`payloads`): `Promise`\<`Run`[]\> - -Defined in: [client.ts:1076](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1076) - -Create a batch of stateless background runs. - -#### Parameters - -##### payloads - -`RunsCreatePayload` & `object`[] - -An array of payloads for creating runs. - -#### Returns - -`Promise`\<`Run`[]\> - -An array of created runs. - -*** - -### delete() - -> **delete**(`threadId`, `runId`): `Promise`\<`void`\> - -Defined in: [client.ts:1329](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1329) - -Delete a run. - -#### Parameters - -##### threadId - -`string` - -The ID of the thread. - -##### runId - -`string` - -The ID of the run. - -#### Returns - -`Promise`\<`void`\> - -*** - -### get() - -> **get**(`threadId`, `runId`): `Promise`\<`Run`\> - -Defined in: [client.ts:1214](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1214) - -Get a run by ID. - -#### Parameters - -##### threadId - -`string` - -The ID of the thread. - -##### runId - -`string` - -The ID of the run. - -#### Returns - -`Promise`\<`Run`\> - -The run. - -*** - -### join() - -> **join**(`threadId`, `runId`, `options`?): `Promise`\<`void`\> - -Defined in: [client.ts:1249](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1249) - -Block until a run is done. - -#### Parameters - -##### threadId - -`string` - -The ID of the thread. - -##### runId - -`string` - -The ID of the run. - -##### options? - -###### signal? - -`AbortSignal` - -#### Returns - -`Promise`\<`void`\> - -*** - -### joinStream() - -> **joinStream**(`threadId`, `runId`, `options`?): `AsyncGenerator`\<\{ `data`: `any`; `event`: `StreamEvent`; `id`: `string`; \}\> - -Defined in: [client.ts:1274](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1274) - -Stream output from a run in real-time, until the run is done. - -#### Parameters - -##### threadId - -The ID of the thread. Can be set to `null` | `undefined` for stateless runs. - -`undefined` | `null` | `string` - -##### runId - -`string` - -The ID of the run. - -##### options? - -Additional options for controlling the stream behavior: - - signal: An AbortSignal that can be used to cancel the stream request - - lastEventId: The ID of the last event received. Can be used to reconnect to a stream without losing events. - - cancelOnDisconnect: When true, automatically cancels the run if the client disconnects from the stream - - streamMode: Controls what types of events to receive from the stream (can be a single mode or array of modes) - Must be a subset of the stream modes passed when creating the run. Background runs default to having the union of all - stream modes enabled. - -`AbortSignal` | \{ `cancelOnDisconnect`: `boolean`; `lastEventId`: `string`; `signal`: `AbortSignal`; `streamMode`: `StreamMode` \| `StreamMode`[]; \} - -#### Returns - -`AsyncGenerator`\<\{ `data`: `any`; `event`: `StreamEvent`; `id`: `string`; \}\> - -An async generator yielding stream parts. - -*** - -### list() - -> **list**(`threadId`, `options`?): `Promise`\<`Run`[]\> - -Defined in: [client.ts:1177](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1177) - -List all runs for a thread. - -#### Parameters - -##### threadId - -`string` - -The ID of the thread. - -##### options? - -Filtering and pagination options. - -###### limit? - -`number` - -Maximum number of runs to return. -Defaults to 10 - -###### offset? - -`number` - -Offset to start from. -Defaults to 0. - -###### status? - -`RunStatus` - -Status of the run to filter by. - -#### Returns - -`Promise`\<`Run`[]\> - -List of runs. - -*** - -### stream() - -Create a run and stream the results. - -#### Param - -The ID of the thread. - -#### Param - -Assistant ID to use for this run. - -#### Param - -Payload for creating a run. - -#### Call Signature - -> **stream**\<`TStreamMode`, `TSubgraphs`\>(`threadId`, `assistantId`, `payload`?): `TypedAsyncGenerator`\<`TStreamMode`, `TSubgraphs`, `TStateType`, `TUpdateType`, `TCustomEventType`\> - -Defined in: [client.ts:917](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L917) - -##### Type Parameters - -• **TStreamMode** *extends* `StreamMode` \| `StreamMode`[] = `StreamMode` - -• **TSubgraphs** *extends* `boolean` = `false` - -##### Parameters - -###### threadId - -`null` - -###### assistantId - -`string` - -###### payload? - -`Omit`\<`RunsStreamPayload`\<`TStreamMode`, `TSubgraphs`\>, `"multitaskStrategy"` \| `"onCompletion"`\> - -##### Returns - -`TypedAsyncGenerator`\<`TStreamMode`, `TSubgraphs`, `TStateType`, `TUpdateType`, `TCustomEventType`\> - -#### Call Signature - -> **stream**\<`TStreamMode`, `TSubgraphs`\>(`threadId`, `assistantId`, `payload`?): `TypedAsyncGenerator`\<`TStreamMode`, `TSubgraphs`, `TStateType`, `TUpdateType`, `TCustomEventType`\> - -Defined in: [client.ts:935](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L935) - -##### Type Parameters - -• **TStreamMode** *extends* `StreamMode` \| `StreamMode`[] = `StreamMode` - -• **TSubgraphs** *extends* `boolean` = `false` - -##### Parameters - -###### threadId - -`string` - -###### assistantId - -`string` - -###### payload? - -`RunsStreamPayload`\<`TStreamMode`, `TSubgraphs`\> - -##### Returns - -`TypedAsyncGenerator`\<`TStreamMode`, `TSubgraphs`, `TStateType`, `TUpdateType`, `TCustomEventType`\> - -*** - -### wait() - -Create a run and wait for it to complete. - -#### Param - -The ID of the thread. - -#### Param - -Assistant ID to use for this run. - -#### Param - -Payload for creating a run. - -#### Call Signature - -> **wait**(`threadId`, `assistantId`, `payload`?): `Promise`\<`DefaultValues`\> - -Defined in: [client.ts:1093](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1093) - -##### Parameters - -###### threadId - -`null` - -###### assistantId - -`string` - -###### payload? - -`Omit`\<`RunsWaitPayload`, `"multitaskStrategy"` \| `"onCompletion"`\> - -##### Returns - -`Promise`\<`DefaultValues`\> - -#### Call Signature - -> **wait**(`threadId`, `assistantId`, `payload`?): `Promise`\<`DefaultValues`\> - -Defined in: [client.ts:1099](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1099) - -##### Parameters - -###### threadId - -`string` - -###### assistantId - -`string` - -###### payload? - -`RunsWaitPayload` - -##### Returns - -`Promise`\<`DefaultValues`\> diff --git a/libs/sdk-js/docs/classes/StoreClient.md b/libs/sdk-js/docs/classes/StoreClient.md deleted file mode 100644 index 97e223da3..000000000 --- a/libs/sdk-js/docs/classes/StoreClient.md +++ /dev/null @@ -1,314 +0,0 @@ -[**@langchain/langgraph-sdk**](../README.md) - -*** - -[@langchain/langgraph-sdk](../README.md) / StoreClient - -# Class: StoreClient - -Defined in: [client.ts:1347](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1347) - -## Extends - -- `BaseClient` - -## Constructors - -### new StoreClient() - -> **new StoreClient**(`config`?): [`StoreClient`](StoreClient.md) - -Defined in: [client.ts:183](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L183) - -#### Parameters - -##### config? - -[`ClientConfig`](../interfaces/ClientConfig.md) - -#### Returns - -[`StoreClient`](StoreClient.md) - -#### Inherited from - -`BaseClient.constructor` - -## Methods - -### deleteItem() - -> **deleteItem**(`namespace`, `key`): `Promise`\<`void`\> - -Defined in: [client.ts:1468](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1468) - -Delete an item. - -#### Parameters - -##### namespace - -`string`[] - -A list of strings representing the namespace path. - -##### key - -`string` - -The unique identifier for the item. - -#### Returns - -`Promise`\<`void`\> - -Promise - -*** - -### getItem() - -> **getItem**(`namespace`, `key`, `options`?): `Promise`\<`null` \| `Item`\> - -Defined in: [client.ts:1424](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1424) - -Retrieve a single item. - -#### Parameters - -##### namespace - -`string`[] - -A list of strings representing the namespace path. - -##### key - -`string` - -The unique identifier for the item. - -##### options? - -###### refreshTtl? - -`null` \| `boolean` - -Whether to refresh the TTL on this read operation. If null, uses the store's default behavior. - -#### Returns - -`Promise`\<`null` \| `Item`\> - -Promise - -#### Example - -```typescript -const item = await client.store.getItem( - ["documents", "user123"], - "item456", - { refreshTtl: true } -); -console.log(item); -// { -// namespace: ["documents", "user123"], -// key: "item456", -// value: { title: "My Document", content: "Hello World" }, -// createdAt: "2024-07-30T12:00:00Z", -// updatedAt: "2024-07-30T12:00:00Z" -// } -``` - -*** - -### listNamespaces() - -> **listNamespaces**(`options`?): `Promise`\<`ListNamespaceResponse`\> - -Defined in: [client.ts:1564](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1564) - -List namespaces with optional match conditions. - -#### Parameters - -##### options? - -###### limit? - -`number` - -Maximum number of namespaces to return (default is 100). - -###### maxDepth? - -`number` - -Optional integer specifying the maximum depth of namespaces to return. - -###### offset? - -`number` - -Number of namespaces to skip before returning results (default is 0). - -###### prefix? - -`string`[] - -Optional list of strings representing the prefix to filter namespaces. - -###### suffix? - -`string`[] - -Optional list of strings representing the suffix to filter namespaces. - -#### Returns - -`Promise`\<`ListNamespaceResponse`\> - -Promise - -*** - -### putItem() - -> **putItem**(`namespace`, `key`, `value`, `options`?): `Promise`\<`void`\> - -Defined in: [client.ts:1368](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1368) - -Store or update an item. - -#### Parameters - -##### namespace - -`string`[] - -A list of strings representing the namespace path. - -##### key - -`string` - -The unique identifier for the item within the namespace. - -##### value - -`Record`\<`string`, `any`\> - -A dictionary containing the item's data. - -##### options? - -###### index? - -`null` \| `false` \| `string`[] - -Controls search indexing - null (use defaults), false (disable), or list of field paths to index. - -###### ttl? - -`null` \| `number` - -Optional time-to-live in minutes for the item, or null for no expiration. - -#### Returns - -`Promise`\<`void`\> - -Promise - -#### Example - -```typescript -await client.store.putItem( - ["documents", "user123"], - "item456", - { title: "My Document", content: "Hello World" }, - { ttl: 60 } // expires in 60 minutes -); -``` - -*** - -### searchItems() - -> **searchItems**(`namespacePrefix`, `options`?): `Promise`\<`SearchItemsResponse`\> - -Defined in: [client.ts:1519](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L1519) - -Search for items within a namespace prefix. - -#### Parameters - -##### namespacePrefix - -`string`[] - -List of strings representing the namespace prefix. - -##### options? - -###### filter? - -`Record`\<`string`, `any`\> - -Optional dictionary of key-value pairs to filter results. - -###### limit? - -`number` - -Maximum number of items to return (default is 10). - -###### offset? - -`number` - -Number of items to skip before returning results (default is 0). - -###### query? - -`string` - -Optional search query. - -###### refreshTtl? - -`null` \| `boolean` - -Whether to refresh the TTL on items returned by this search. If null, uses the store's default behavior. - -#### Returns - -`Promise`\<`SearchItemsResponse`\> - -Promise - -#### Example - -```typescript -const results = await client.store.searchItems( - ["documents"], - { - filter: { author: "John Doe" }, - limit: 5, - refreshTtl: true - } -); -console.log(results); -// { -// items: [ -// { -// namespace: ["documents", "user123"], -// key: "item789", -// value: { title: "Another Document", author: "John Doe" }, -// createdAt: "2024-07-30T12:00:00Z", -// updatedAt: "2024-07-30T12:00:00Z" -// }, -// // ... additional items ... -// ] -// } -``` diff --git a/libs/sdk-js/docs/classes/ThreadsClient.md b/libs/sdk-js/docs/classes/ThreadsClient.md deleted file mode 100644 index 7dc422c98..000000000 --- a/libs/sdk-js/docs/classes/ThreadsClient.md +++ /dev/null @@ -1,433 +0,0 @@ -[**@langchain/langgraph-sdk**](../README.md) - -*** - -[@langchain/langgraph-sdk](../README.md) / ThreadsClient - -# Class: ThreadsClient\ - -Defined in: [client.ts:626](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L626) - -## Extends - -- `BaseClient` - -## Type Parameters - -• **TStateType** = `DefaultValues` - -• **TUpdateType** = `TStateType` - -## Constructors - -### new ThreadsClient() - -> **new ThreadsClient**\<`TStateType`, `TUpdateType`\>(`config`?): [`ThreadsClient`](ThreadsClient.md)\<`TStateType`, `TUpdateType`\> - -Defined in: [client.ts:183](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L183) - -#### Parameters - -##### config? - -[`ClientConfig`](../interfaces/ClientConfig.md) - -#### Returns - -[`ThreadsClient`](ThreadsClient.md)\<`TStateType`, `TUpdateType`\> - -#### Inherited from - -`BaseClient.constructor` - -## Methods - -### copy() - -> **copy**(`threadId`): `Promise`\<`Thread`\<`TStateType`\>\> - -Defined in: [client.ts:703](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L703) - -Copy an existing thread - -#### Parameters - -##### threadId - -`string` - -ID of the thread to be copied - -#### Returns - -`Promise`\<`Thread`\<`TStateType`\>\> - -Newly copied thread - -*** - -### create() - -> **create**(`payload`?): `Promise`\<`Thread`\<`TStateType`\>\> - -Defined in: [client.ts:648](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L648) - -Create a new thread. - -#### Parameters - -##### payload? - -Payload for creating a thread. - -###### graphId? - -`string` - -Graph ID to associate with the thread. - -###### ifExists? - -`OnConflictBehavior` - -How to handle duplicate creation. - -**Default** - -```ts -"raise" -``` - -###### metadata? - -`Metadata` - -Metadata for the thread. - -###### supersteps? - -`object`[] - -Apply a list of supersteps when creating a thread, each containing a sequence of updates. - -Used for copying a thread between deployments. - -###### threadId? - -`string` - -ID of the thread to create. - -If not provided, a random UUID will be generated. - -#### Returns - -`Promise`\<`Thread`\<`TStateType`\>\> - -The created thread. - -*** - -### delete() - -> **delete**(`threadId`): `Promise`\<`void`\> - -Defined in: [client.ts:736](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L736) - -Delete a thread. - -#### Parameters - -##### threadId - -`string` - -ID of the thread. - -#### Returns - -`Promise`\<`void`\> - -*** - -### get() - -> **get**\<`ValuesType`\>(`threadId`): `Promise`\<`Thread`\<`ValuesType`\>\> - -Defined in: [client.ts:636](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L636) - -Get a thread by ID. - -#### Type Parameters - -• **ValuesType** = `TStateType` - -#### Parameters - -##### threadId - -`string` - -ID of the thread. - -#### Returns - -`Promise`\<`Thread`\<`ValuesType`\>\> - -The thread. - -*** - -### getHistory() - -> **getHistory**\<`ValuesType`\>(`threadId`, `options`?): `Promise`\<`ThreadState`\<`ValuesType`\>[]\> - -Defined in: [client.ts:888](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L888) - -Get all past states for a thread. - -#### Type Parameters - -• **ValuesType** = `TStateType` - -#### Parameters - -##### threadId - -`string` - -ID of the thread. - -##### options? - -Additional options. - -###### before? - -`Config` - -###### checkpoint? - -`Partial`\<`Omit`\<`Checkpoint`, `"thread_id"`\>\> - -###### limit? - -`number` - -###### metadata? - -`Metadata` - -#### Returns - -`Promise`\<`ThreadState`\<`ValuesType`\>[]\> - -List of thread states. - -*** - -### getState() - -> **getState**\<`ValuesType`\>(`threadId`, `checkpoint`?, `options`?): `Promise`\<`ThreadState`\<`ValuesType`\>\> - -Defined in: [client.ts:795](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L795) - -Get state for a thread. - -#### Type Parameters - -• **ValuesType** = `TStateType` - -#### Parameters - -##### threadId - -`string` - -ID of the thread. - -##### checkpoint? - -`string` | `Checkpoint` - -##### options? - -###### subgraphs? - -`boolean` - -#### Returns - -`Promise`\<`ThreadState`\<`ValuesType`\>\> - -Thread state. - -*** - -### patchState() - -> **patchState**(`threadIdOrConfig`, `metadata`): `Promise`\<`void`\> - -Defined in: [client.ts:858](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L858) - -Patch the metadata of a thread. - -#### Parameters - -##### threadIdOrConfig - -Thread ID or config to patch the state of. - -`string` | `Config` - -##### metadata - -`Metadata` - -Metadata to patch the state with. - -#### Returns - -`Promise`\<`void`\> - -*** - -### search() - -> **search**\<`ValuesType`\>(`query`?): `Promise`\<`Thread`\<`ValuesType`\>[]\> - -Defined in: [client.ts:748](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L748) - -List threads - -#### Type Parameters - -• **ValuesType** = `TStateType` - -#### Parameters - -##### query? - -Query options - -###### limit? - -`number` - -Maximum number of threads to return. -Defaults to 10 - -###### metadata? - -`Metadata` - -Metadata to filter threads by. - -###### offset? - -`number` - -Offset to start from. - -###### sortBy? - -`ThreadSortBy` - -Sort by. - -###### sortOrder? - -`SortOrder` - -Sort order. -Must be one of 'asc' or 'desc'. - -###### status? - -`ThreadStatus` - -Thread status to filter on. - -#### Returns - -`Promise`\<`Thread`\<`ValuesType`\>[]\> - -List of threads - -*** - -### update() - -> **update**(`threadId`, `payload`?): `Promise`\<`Thread`\<`DefaultValues`\>\> - -Defined in: [client.ts:716](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L716) - -Update a thread. - -#### Parameters - -##### threadId - -`string` - -ID of the thread. - -##### payload? - -Payload for updating the thread. - -###### metadata? - -`Metadata` - -Metadata for the thread. - -#### Returns - -`Promise`\<`Thread`\<`DefaultValues`\>\> - -The updated thread. - -*** - -### updateState() - -> **updateState**\<`ValuesType`\>(`threadId`, `options`): `Promise`\<`Pick`\<`Config`, `"configurable"`\>\> - -Defined in: [client.ts:829](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L829) - -Add state to a thread. - -#### Type Parameters - -• **ValuesType** = `TUpdateType` - -#### Parameters - -##### threadId - -`string` - -The ID of the thread. - -##### options - -###### asNode? - -`string` - -###### checkpoint? - -`Checkpoint` - -###### checkpointId? - -`string` - -###### values - -`ValuesType` - -#### Returns - -`Promise`\<`Pick`\<`Config`, `"configurable"`\>\> diff --git a/libs/sdk-js/docs/functions/getApiKey.md b/libs/sdk-js/docs/functions/getApiKey.md deleted file mode 100644 index 8c8e4f1fa..000000000 --- a/libs/sdk-js/docs/functions/getApiKey.md +++ /dev/null @@ -1,32 +0,0 @@ -[**@langchain/langgraph-sdk**](../README.md) - -*** - -[@langchain/langgraph-sdk](../README.md) / getApiKey - -# Function: getApiKey() - -> **getApiKey**(`apiKey`?): `undefined` \| `string` - -Defined in: [client.ts:122](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L122) - -Get the API key from the environment. -Precedence: - 1. explicit argument - 2. LANGGRAPH_API_KEY - 3. LANGSMITH_API_KEY - 4. LANGCHAIN_API_KEY - -## Parameters - -### apiKey? - -`string` - -Optional API key provided as an argument - -## Returns - -`undefined` \| `string` - -The API key if found, otherwise undefined diff --git a/libs/sdk-js/docs/interfaces/ClientConfig.md b/libs/sdk-js/docs/interfaces/ClientConfig.md deleted file mode 100644 index 38c402010..000000000 --- a/libs/sdk-js/docs/interfaces/ClientConfig.md +++ /dev/null @@ -1,57 +0,0 @@ -[**@langchain/langgraph-sdk**](../README.md) - -*** - -[@langchain/langgraph-sdk](../README.md) / ClientConfig - -# Interface: ClientConfig - -Defined in: [client.ts:163](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L163) - -## Properties - -### apiKey? - -> `optional` **apiKey**: `string` - -Defined in: [client.ts:165](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L165) - -*** - -### apiUrl? - -> `optional` **apiUrl**: `string` - -Defined in: [client.ts:164](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L164) - -*** - -### callerOptions? - -> `optional` **callerOptions**: `AsyncCallerParams` - -Defined in: [client.ts:166](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L166) - -*** - -### defaultHeaders? - -> `optional` **defaultHeaders**: `Record`\<`string`, `HeaderValue`\> - -Defined in: [client.ts:168](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L168) - -*** - -### onRequest? - -> `optional` **onRequest**: [`RequestHook`](../type-aliases/RequestHook.md) - -Defined in: [client.ts:169](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L169) - -*** - -### timeoutMs? - -> `optional` **timeoutMs**: `number` - -Defined in: [client.ts:167](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L167) diff --git a/libs/sdk-js/docs/react/README.md b/libs/sdk-js/docs/react/README.md deleted file mode 100644 index 0933ca79b..000000000 --- a/libs/sdk-js/docs/react/README.md +++ /dev/null @@ -1,18 +0,0 @@ -**@langchain/langgraph-sdk** - -*** - -# @langchain/langgraph-sdk/react - -## Interfaces - -- [UseStream](interfaces/UseStream.md) -- [UseStreamOptions](interfaces/UseStreamOptions.md) - -## Type Aliases - -- [MessageMetadata](type-aliases/MessageMetadata.md) - -## Functions - -- [useStream](functions/useStream.md) diff --git a/libs/sdk-js/docs/react/functions/useStream.md b/libs/sdk-js/docs/react/functions/useStream.md deleted file mode 100644 index a9cb7d468..000000000 --- a/libs/sdk-js/docs/react/functions/useStream.md +++ /dev/null @@ -1,27 +0,0 @@ -[**@langchain/langgraph-sdk**](../README.md) - -*** - -[@langchain/langgraph-sdk](../README.md) / useStream - -# Function: useStream() - -> **useStream**\<`StateType`, `Bag`\>(`options`): [`UseStream`](../interfaces/UseStream.md)\<`StateType`, `Bag`\> - -Defined in: [react/stream.tsx:652](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L652) - -## Type Parameters - -• **StateType** *extends* `Record`\<`string`, `unknown`\> = `Record`\<`string`, `unknown`\> - -• **Bag** *extends* `object` = `BagTemplate` - -## Parameters - -### options - -[`UseStreamOptions`](../interfaces/UseStreamOptions.md)\<`StateType`, `Bag`\> - -## Returns - -[`UseStream`](../interfaces/UseStream.md)\<`StateType`, `Bag`\> diff --git a/libs/sdk-js/docs/react/interfaces/UseStream.md b/libs/sdk-js/docs/react/interfaces/UseStream.md deleted file mode 100644 index 06d1c4375..000000000 --- a/libs/sdk-js/docs/react/interfaces/UseStream.md +++ /dev/null @@ -1,227 +0,0 @@ -[**@langchain/langgraph-sdk**](../README.md) - -*** - -[@langchain/langgraph-sdk](../README.md) / UseStream - -# Interface: UseStream\ - -Defined in: [react/stream.tsx:529](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L529) - -## Type Parameters - -• **StateType** *extends* `Record`\<`string`, `unknown`\> = `Record`\<`string`, `unknown`\> - -• **Bag** *extends* `BagTemplate` = `BagTemplate` - -## Properties - -### assistantId - -> **assistantId**: `string` - -Defined in: [react/stream.tsx:614](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L614) - -The ID of the assistant to use. - -*** - -### branch - -> **branch**: `string` - -Defined in: [react/stream.tsx:564](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L564) - -The current branch of the thread. - -*** - -### client - -> **client**: `Client` - -Defined in: [react/stream.tsx:609](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L609) - -LangGraph SDK client used to send request and receive responses. - -*** - -### error - -> **error**: `unknown` - -Defined in: [react/stream.tsx:541](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L541) - -Last seen error from the thread or during streaming. - -*** - -### experimental\_branchTree - -> **experimental\_branchTree**: `Sequence`\<`StateType`\> - -Defined in: [react/stream.tsx:580](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L580) - -**`Experimental`** - -Tree of all branches for the thread. - -*** - -### getMessagesMetadata() - -> **getMessagesMetadata**: (`message`, `index`?) => `undefined` \| [`MessageMetadata`](../type-aliases/MessageMetadata.md)\<`StateType`\> - -Defined in: [react/stream.tsx:601](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L601) - -Get the metadata for a message, such as first thread state the message -was seen in and branch information. - -#### Parameters - -##### message - -`Message` - -The message to get the metadata for. - -##### index? - -`number` - -The index of the message in the thread. - -#### Returns - -`undefined` \| [`MessageMetadata`](../type-aliases/MessageMetadata.md)\<`StateType`\> - -The metadata for the message. - -*** - -### history - -> **history**: `ThreadState`\<`StateType`\>[] - -Defined in: [react/stream.tsx:574](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L574) - -Flattened history of thread states of a thread. - -*** - -### interrupt - -> **interrupt**: `undefined` \| `Interrupt`\<`GetInterruptType`\<`Bag`\>\> - -Defined in: [react/stream.tsx:585](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L585) - -Get the interrupt value for the stream if interrupted. - -*** - -### isLoading - -> **isLoading**: `boolean` - -Defined in: [react/stream.tsx:546](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L546) - -Whether the stream is currently running. - -*** - -### joinStream() - -> **joinStream**: (`runId`) => `Promise`\<`void`\> - -Defined in: [react/stream.tsx:619](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L619) - -Join an active stream. - -#### Parameters - -##### runId - -`string` - -#### Returns - -`Promise`\<`void`\> - -*** - -### messages - -> **messages**: `Message`[] - -Defined in: [react/stream.tsx:591](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L591) - -Messages inferred from the thread. -Will automatically update with incoming message chunks. - -*** - -### setBranch() - -> **setBranch**: (`branch`) => `void` - -Defined in: [react/stream.tsx:569](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L569) - -Set the branch of the thread. - -#### Parameters - -##### branch - -`string` - -#### Returns - -`void` - -*** - -### stop() - -> **stop**: () => `void` - -Defined in: [react/stream.tsx:551](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L551) - -Stops the stream. - -#### Returns - -`void` - -*** - -### submit() - -> **submit**: (`values`, `options`?) => `void` - -Defined in: [react/stream.tsx:556](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L556) - -Create and stream a run to the thread. - -#### Parameters - -##### values - -`undefined` | `null` | `GetUpdateType`\<`Bag`, `StateType`\> - -##### options? - -`SubmitOptions`\<`StateType`, `GetConfigurableType`\<`Bag`\>\> - -#### Returns - -`void` - -*** - -### values - -> **values**: `StateType` - -Defined in: [react/stream.tsx:536](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L536) - -The current values of the thread. diff --git a/libs/sdk-js/docs/react/interfaces/UseStreamOptions.md b/libs/sdk-js/docs/react/interfaces/UseStreamOptions.md deleted file mode 100644 index 9fbb6f702..000000000 --- a/libs/sdk-js/docs/react/interfaces/UseStreamOptions.md +++ /dev/null @@ -1,343 +0,0 @@ -[**@langchain/langgraph-sdk**](../README.md) - -*** - -[@langchain/langgraph-sdk](../README.md) / UseStreamOptions - -# Interface: UseStreamOptions\ - -Defined in: [react/stream.tsx:413](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L413) - -## Type Parameters - -• **StateType** *extends* `Record`\<`string`, `unknown`\> = `Record`\<`string`, `unknown`\> - -• **Bag** *extends* `BagTemplate` = `BagTemplate` - -## Properties - -### apiKey? - -> `optional` **apiKey**: `string` - -Defined in: [react/stream.tsx:435](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L435) - -The API key to use. - -*** - -### apiUrl? - -> `optional` **apiUrl**: `string` - -Defined in: [react/stream.tsx:430](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L430) - -The URL of the API to use. - -*** - -### assistantId - -> **assistantId**: `string` - -Defined in: [react/stream.tsx:420](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L420) - -The ID of the assistant to use. - -*** - -### callerOptions? - -> `optional` **callerOptions**: `AsyncCallerParams` - -Defined in: [react/stream.tsx:440](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L440) - -Custom call options, such as custom fetch implementation. - -*** - -### client? - -> `optional` **client**: `Client`\<`DefaultValues`, `DefaultValues`, `unknown`\> - -Defined in: [react/stream.tsx:425](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L425) - -Client used to send requests. - -*** - -### defaultHeaders? - -> `optional` **defaultHeaders**: `Record`\<`string`, `HeaderValue`\> - -Defined in: [react/stream.tsx:445](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L445) - -Default headers to send with requests. - -*** - -### messagesKey? - -> `optional` **messagesKey**: `string` - -Defined in: [react/stream.tsx:453](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L453) - -Specify the key within the state that contains messages. -Defaults to "messages". - -#### Default - -```ts -"messages" -``` - -*** - -### onCreated()? - -> `optional` **onCreated**: (`run`) => `void` - -Defined in: [react/stream.tsx:471](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L471) - -Callback that is called when a new stream is created. - -#### Parameters - -##### run - -`RunCallbackMeta` - -#### Returns - -`void` - -*** - -### onCustomEvent()? - -> `optional` **onCustomEvent**: (`data`, `options`) => `void` - -Defined in: [react/stream.tsx:483](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L483) - -Callback that is called when a custom event is received. - -#### Parameters - -##### data - -`GetCustomEventType`\<`Bag`\> - -##### options - -###### mutate - -(`update`) => `void` - -#### Returns - -`void` - -*** - -### onDebugEvent()? - -> `optional` **onDebugEvent**: (`data`) => `void` - -Defined in: [react/stream.tsx:507](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L507) - -**`Internal`** - -Callback that is called when a debug event is received. - This API is experimental and subject to change. - -#### Parameters - -##### data - -`unknown` - -#### Returns - -`void` - -*** - -### onError()? - -> `optional` **onError**: (`error`, `run`) => `void` - -Defined in: [react/stream.tsx:458](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L458) - -Callback that is called when an error occurs. - -#### Parameters - -##### error - -`unknown` - -##### run - -`undefined` | `RunCallbackMeta` - -#### Returns - -`void` - -*** - -### onFinish()? - -> `optional` **onFinish**: (`state`, `run`) => `void` - -Defined in: [react/stream.tsx:463](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L463) - -Callback that is called when the stream is finished. - -#### Parameters - -##### state - -`ThreadState`\<`StateType`\> - -##### run - -`undefined` | `RunCallbackMeta` - -#### Returns - -`void` - -*** - -### onLangChainEvent()? - -> `optional` **onLangChainEvent**: (`data`) => `void` - -Defined in: [react/stream.tsx:501](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L501) - -Callback that is called when a LangChain event is received. - -#### Parameters - -##### data - -###### data - -`unknown` - -###### event - -`string` & `object` \| `"on_tool_start"` \| `"on_tool_stream"` \| `"on_tool_end"` \| `"on_chat_model_start"` \| `"on_chat_model_stream"` \| `"on_chat_model_end"` \| `"on_llm_start"` \| `"on_llm_stream"` \| `"on_llm_end"` \| `"on_chain_start"` \| `"on_chain_stream"` \| `"on_chain_end"` \| `"on_retriever_start"` \| `"on_retriever_stream"` \| `"on_retriever_end"` \| `"on_prompt_start"` \| `"on_prompt_stream"` \| `"on_prompt_end"` - -###### metadata - -`Record`\<`string`, `unknown`\> - -###### name - -`string` - -###### parent_ids - -`string`[] - -###### run_id - -`string` - -###### tags - -`string`[] - -#### Returns - -`void` - -#### See - -https://langchain-ai.github.io/langgraph/cloud/how-tos/stream_events/#stream-graph-in-events-mode for more details. - -*** - -### onMetadataEvent()? - -> `optional` **onMetadataEvent**: (`data`) => `void` - -Defined in: [react/stream.tsx:495](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L495) - -Callback that is called when a metadata event is received. - -#### Parameters - -##### data - -###### run_id - -`string` - -###### thread_id - -`string` - -#### Returns - -`void` - -*** - -### onThreadId()? - -> `optional` **onThreadId**: (`threadId`) => `void` - -Defined in: [react/stream.tsx:517](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L517) - -Callback that is called when the thread ID is updated (ie when a new thread is created). - -#### Parameters - -##### threadId - -`string` - -#### Returns - -`void` - -*** - -### onUpdateEvent()? - -> `optional` **onUpdateEvent**: (`data`) => `void` - -Defined in: [react/stream.tsx:476](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L476) - -Callback that is called when an update event is received. - -#### Parameters - -##### data - -#### Returns - -`void` - -*** - -### reconnectOnMount? - -> `optional` **reconnectOnMount**: `boolean` \| () => `RunMetadataStorage` - -Defined in: [react/stream.tsx:520](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L520) - -Will reconnect the stream on mount - -*** - -### threadId? - -> `optional` **threadId**: `null` \| `string` - -Defined in: [react/stream.tsx:512](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L512) - -The ID of the thread to fetch history and current values from. diff --git a/libs/sdk-js/docs/react/type-aliases/MessageMetadata.md b/libs/sdk-js/docs/react/type-aliases/MessageMetadata.md deleted file mode 100644 index 9496a7913..000000000 --- a/libs/sdk-js/docs/react/type-aliases/MessageMetadata.md +++ /dev/null @@ -1,42 +0,0 @@ -[**@langchain/langgraph-sdk**](../README.md) - -*** - -[@langchain/langgraph-sdk](../README.md) / MessageMetadata - -# Type Alias: MessageMetadata\ - -> **MessageMetadata**\<`StateType`\>: `object` - -Defined in: [react/stream.tsx:169](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/react/stream.tsx#L169) - -## Type Parameters - -• **StateType** *extends* `Record`\<`string`, `unknown`\> - -## Type declaration - -### branch - -> **branch**: `string` \| `undefined` - -The branch of the message. - -### branchOptions - -> **branchOptions**: `string`[] \| `undefined` - -The list of branches this message is part of. -This is useful for displaying branching controls. - -### firstSeenState - -> **firstSeenState**: `ThreadState`\<`StateType`\> \| `undefined` - -The first thread state the message was seen in. - -### messageId - -> **messageId**: `string` - -The ID of the message used. diff --git a/libs/sdk-js/docs/type-aliases/RequestHook.md b/libs/sdk-js/docs/type-aliases/RequestHook.md deleted file mode 100644 index 53d535e2e..000000000 --- a/libs/sdk-js/docs/type-aliases/RequestHook.md +++ /dev/null @@ -1,25 +0,0 @@ -[**@langchain/langgraph-sdk**](../README.md) - -*** - -[@langchain/langgraph-sdk](../README.md) / RequestHook - -# Type Alias: RequestHook() - -> **RequestHook**: (`url`, `init`) => `Promise`\<`RequestInit`\> \| `RequestInit` - -Defined in: [client.ts:158](https://github.com/langchain-ai/langgraph/blob/a7ea5e44ce12e3618d1a766587163afbfe424e04/libs/sdk-js/src/client.ts#L158) - -## Parameters - -### url - -`URL` - -### init - -`RequestInit` - -## Returns - -`Promise`\<`RequestInit`\> \| `RequestInit` diff --git a/libs/sdk-js/index.cjs b/libs/sdk-js/index.cjs deleted file mode 100644 index c84256f7a..000000000 --- a/libs/sdk-js/index.cjs +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./dist/index.cjs'); \ No newline at end of file diff --git a/libs/sdk-js/index.d.cts b/libs/sdk-js/index.d.cts deleted file mode 100644 index 485d17256..000000000 --- a/libs/sdk-js/index.d.cts +++ /dev/null @@ -1 +0,0 @@ -export * from './dist/index.js' \ No newline at end of file diff --git a/libs/sdk-js/index.d.ts b/libs/sdk-js/index.d.ts deleted file mode 100644 index 485d17256..000000000 --- a/libs/sdk-js/index.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './dist/index.js' \ No newline at end of file diff --git a/libs/sdk-js/index.js b/libs/sdk-js/index.js deleted file mode 100644 index 485d17256..000000000 --- a/libs/sdk-js/index.js +++ /dev/null @@ -1 +0,0 @@ -export * from './dist/index.js' \ No newline at end of file diff --git a/libs/sdk-js/react.cjs b/libs/sdk-js/react.cjs deleted file mode 100644 index 86a38b8c3..000000000 --- a/libs/sdk-js/react.cjs +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./dist/react/index.cjs'); \ No newline at end of file diff --git a/libs/sdk-js/react.d.cts b/libs/sdk-js/react.d.cts deleted file mode 100644 index fd96c4787..000000000 --- a/libs/sdk-js/react.d.cts +++ /dev/null @@ -1 +0,0 @@ -export * from './dist/react/index.js' \ No newline at end of file diff --git a/libs/sdk-js/react.d.ts b/libs/sdk-js/react.d.ts deleted file mode 100644 index fd96c4787..000000000 --- a/libs/sdk-js/react.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './dist/react/index.js' \ No newline at end of file diff --git a/libs/sdk-js/react.js b/libs/sdk-js/react.js deleted file mode 100644 index fd96c4787..000000000 --- a/libs/sdk-js/react.js +++ /dev/null @@ -1 +0,0 @@ -export * from './dist/react/index.js' \ No newline at end of file From 1f1d032430a29800709929890cebf445615ab0c0 Mon Sep 17 00:00:00 2001 From: lc-arjun Date: Tue, 8 Jul 2025 06:59:02 -0700 Subject: [PATCH 046/129] docs: add tunnel flag to node server docs (#5398) --- docs/docs/troubleshooting/studio.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/troubleshooting/studio.md b/docs/docs/troubleshooting/studio.md index b06f325de..3fcbdea7f 100644 --- a/docs/docs/troubleshooting/studio.md +++ b/docs/docs/troubleshooting/studio.md @@ -17,7 +17,7 @@ Safari blocks plain-HTTP traffic on localhost. When running Studio with `langgra ```shell # Requires @langchain/langgraph-cli>=0.0.26 - npx @langchain/langgraph-cli dev + npx @langchain/langgraph-cli dev --tunnel ``` The command outputs a URL in this format: @@ -55,7 +55,7 @@ Disable Brave Shields for LangSmith using the Brave icon in the URL bar. ```shell # Requires @langchain/langgraph-cli>=0.0.26 - npx @langchain/langgraph-cli dev + npx @langchain/langgraph-cli dev --tunnel ``` The command outputs a URL in this format: From f21fc056bff70d7e5c8dd7553577a1a26238713a Mon Sep 17 00:00:00 2001 From: Lauren Hirata Singh Date: Tue, 8 Jul 2025 10:36:47 -0400 Subject: [PATCH 047/129] docs: Convert example notebooks (#5381) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Agentic RAG * Fix formatting * Agent supervisor * fix links * SQL agent * Graph Runs in LS * fix format * Autogen + LG tutorial * fixes * update sql * remove old notebooks * docs: Add section about data region for LGP data plane (#5378) Add section about data region. * fix: remove empty notebook (#5379) * Fix docstring for _unset_config_context function (#5374) Signed-off-by: jitokim * Fix typo in StreamMode debug description: checlkpoints → checkpoints (#5371) Signed-off-by: jitokim * fix: remove unused import in generate_llms_text.py (#5380) * dcos: Fix deprecation of TavilySearch (#5375) Fix deprecation: The class `TavilySearchResults` was deprecated in LangChain 0.3.25 and will be removed in 1.0 * Fix typo: funtion → function (#5370) fix typos Signed-off-by: jitokim * docs: feedback edits (#5387) * docs: update lgp deployment metric list (#5388) * chore(deps): bump peter-evans/create-pull-request from 6 to 7 (#5365) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 6 to 7. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/v6...v7) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * docs: correct link in docs/docs/how-tos/graph-api.md (#5377) Update graph-api.md * docs: Update quick_start.md Rest API Guide (#5368) Update quick_start.md Rest API Guide The curl command in the quick start needs some minor changes to work out of the box. I hope by adding these changes then new users can get started more quickly * Remove duplicate CONFIG_KEY_CHECKPOINT_MAP from RESERVED set (#5372) Signed-off-by: jitokim * docs: fix typo in persistence (#5329) * docs: fix typo in application_structure * docs: fix typo in persistence * chore[deps]: upgrade dependencies with `uv lock --upgrade` (#5358) * chore: upgrade dependencies with `uv lock --upgrade` * linting * upgrade PR title --------- Co-authored-by: sydney-runkle <54324534+sydney-runkle@users.noreply.github.com> Co-authored-by: Sydney Runkle * Updated examples for SummarizationNode to account for serde with persistence layers (#5257) * docs: move script into scripts (#5384) * docs: update sql tutorial (#5389) --------- Signed-off-by: jitokim Signed-off-by: dependabot[bot] Co-authored-by: Andrew Nguonly Co-authored-by: Michael Li Co-authored-by: jito Co-authored-by: Serhii Polishchuk Co-authored-by: hari-dhanushkodi Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Fadel Akram Co-authored-by: David <31293924+dreadn0ught@users.noreply.github.com> Co-authored-by: Youssef Ahmed Mohamed Abdelrahman <109446360+unauthorised-401@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: sydney-runkle <54324534+sydney-runkle@users.noreply.github.com> Co-authored-by: Sydney Runkle Co-authored-by: Nick Riley Co-authored-by: Eugene Yurtsev Co-authored-by: ccurme --- CONTRIBUTING.md | 2 +- docs/docs/concepts/multi_agent.md | 4 +- .../410e0089-2ab8-46bb-a61a-827187fd46b3.png | Bin 0 -> 75818 bytes docs/docs/how-tos/assets/autogen-output.png | Bin 0 -> 5919 bytes .../d38d1f2b-0f4c-4707-b531-a3c749de987f.png | Bin 0 -> 53669 bytes docs/docs/how-tos/autogen-integration.ipynb | 406 ----- docs/docs/how-tos/autogen-integration.md | 321 ++++ .../how-tos/autogen-langgraph-platform.ipynb | 171 -- docs/docs/how-tos/multi_agent.ipynb | 657 -------- docs/docs/how-tos/multi_agent.md | 2 +- docs/docs/how-tos/run-id-langsmith.ipynb | 274 ---- docs/docs/how-tos/run-id-langsmith.md | 155 ++ .../multi_agent/agent_supervisor.ipynb | 1403 ----------------- .../tutorials/multi_agent/agent_supervisor.md | 812 ++++++++++ .../tutorials/multi_agent/assets/diagram.png | Bin 0 -> 25505 bytes .../multi_agent/assets/multi-output.png | Bin 0 -> 14338 bytes .../tutorials/multi_agent/assets/output.png | Bin 0 -> 14338 bytes docs/docs/tutorials/overview.md | 8 +- .../rag/assets/agentic-rag-output.png | Bin 0 -> 81761 bytes .../screenshot_2024_02_14_3_43_58_pm.png | Bin 0 -> 104631 bytes .../tutorials/rag/langgraph_agentic_rag.ipynb | 928 ----------- .../tutorials/rag/langgraph_agentic_rag.md | 522 ++++++ docs/docs/tutorials/sql/output.png | Bin 0 -> 20460 bytes docs/docs/tutorials/sql/sql-agent.md | 549 +++++++ docs/mkdocs.yml | 11 +- 25 files changed, 2372 insertions(+), 3853 deletions(-) create mode 100644 docs/docs/how-tos/assets/410e0089-2ab8-46bb-a61a-827187fd46b3.png create mode 100644 docs/docs/how-tos/assets/autogen-output.png create mode 100644 docs/docs/how-tos/assets/d38d1f2b-0f4c-4707-b531-a3c749de987f.png delete mode 100644 docs/docs/how-tos/autogen-integration.ipynb create mode 100644 docs/docs/how-tos/autogen-integration.md delete mode 100644 docs/docs/how-tos/autogen-langgraph-platform.ipynb delete mode 100644 docs/docs/how-tos/multi_agent.ipynb delete mode 100644 docs/docs/how-tos/run-id-langsmith.ipynb create mode 100644 docs/docs/how-tos/run-id-langsmith.md delete mode 100644 docs/docs/tutorials/multi_agent/agent_supervisor.ipynb create mode 100644 docs/docs/tutorials/multi_agent/agent_supervisor.md create mode 100644 docs/docs/tutorials/multi_agent/assets/diagram.png create mode 100644 docs/docs/tutorials/multi_agent/assets/multi-output.png create mode 100644 docs/docs/tutorials/multi_agent/assets/output.png create mode 100644 docs/docs/tutorials/rag/assets/agentic-rag-output.png create mode 100644 docs/docs/tutorials/rag/assets/screenshot_2024_02_14_3_43_58_pm.png delete mode 100644 docs/docs/tutorials/rag/langgraph_agentic_rag.ipynb create mode 100644 docs/docs/tutorials/rag/langgraph_agentic_rag.md create mode 100644 docs/docs/tutorials/sql/output.png create mode 100644 docs/docs/tutorials/sql/sql-agent.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a4e9a3eca..48fd5593f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -60,7 +60,7 @@ In LangGraph, these are often higher level guides that show off end-to-end use c Some examples include: - [Build a Customer Support Bot](https://langchain-ai.github.io/langgraph/tutorials/customer-support/customer-support/) -- [Build a SQL Agent](https://langchain-ai.github.io/langgraph/tutorials/sql-agent/) +- [Build a SQL Agent](https://langchain-ai.github.io/langgraph/tutorials/sql/sql-agent/) Here are some high-level tips on writing a good tutorial: diff --git a/docs/docs/concepts/multi_agent.md b/docs/docs/concepts/multi_agent.md index 81967f610..5d3e30a29 100644 --- a/docs/docs/concepts/multi_agent.md +++ b/docs/docs/concepts/multi_agent.md @@ -26,7 +26,7 @@ The primary benefits of using multi-agent systems are: There are several ways to connect agents in a multi-agent system: - **Network**: each agent can communicate with [every other agent](https://langchain-ai.github.io/langgraph/tutorials/multi_agent/multi-agent-collaboration/). Any agent can decide which other agent to call next. -- **Supervisor**: each agent communicates with a single [supervisor](https://langchain-ai.github.io/langgraph/tutorials/multi_agent/agent_supervisor/) agent. Supervisor agent makes decisions on which agent should be called next. +- **Supervisor**: each agent communicates with a single [supervisor](../tutorials/multi_agent/agent_supervisor.md) agent. Supervisor agent makes decisions on which agent should be called next. - **Supervisor (tool-calling)**: this is a special case of supervisor architecture. Individual agents can be represented as tools. In this case, a supervisor agent uses a tool-calling LLM to decide which of the agent tools to call, as well as the arguments to pass to those agents. - **Hierarchical**: you can define a multi-agent system with [a supervisor of supervisors](https://langchain-ai.github.io/langgraph/tutorials/multi_agent/hierarchical_agent_teams/). This is a generalization of the supervisor architecture and allows for more complex control flows. - **Custom multi-agent workflow**: each agent communicates with only a subset of agents. Parts of the flow are deterministic, and only some agents can decide which other agents to call next. @@ -211,7 +211,7 @@ builder.add_edge(START, "supervisor") supervisor = builder.compile() ``` -Check out this [tutorial](https://langchain-ai.github.io/langgraph/tutorials/multi_agent/agent_supervisor/) for an example of supervisor multi-agent architecture. +Check out this [tutorial](../tutorials/multi_agent/agent_supervisor.md) for an example of supervisor multi-agent architecture. ### Supervisor (tool-calling) diff --git a/docs/docs/how-tos/assets/410e0089-2ab8-46bb-a61a-827187fd46b3.png b/docs/docs/how-tos/assets/410e0089-2ab8-46bb-a61a-827187fd46b3.png new file mode 100644 index 0000000000000000000000000000000000000000..9bd66e5654ae1f2d93b2329d3a37bcf853a93177 GIT binary patch literal 75818 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 z zN|_|&ER((V)$8Qd(bsbMiTJ&}QvB#yV-~^qqEV8q?D72HrM%m&yMI&;7Vw#F0WU!> z@dE}&XF8Td^@2oGa34yTi=t#EBJ>|;&*`aQJtbBGaMi%>cqmqY!{&K7YXjI!UUwJ2 z&BrrSaTe5eqKYItc@WksyV`0vH4%K$=k;B>XGJ*#f*T*a`*tBT*J)lhs-pGJ6 zZ6*jS)n6e_7?us1e&%1mx@9eXk4QZB&}FfL7R}-Geh6J_wRPs&OP`ao`mk(4dQ`ds z|LDb+vK*vydQMZW@d>RcR4+JwT4&|0fD+Yja`MGD_Y7|PQ&(VnL`$_lgdn3sfwuSC zV2Y>fTnY0+_Y+q53nXP95A97MQkyj3iavcLY8>5HwHp6Df z1W`ILg|~w?kHvq z$x$tX8XyhX{z+to13#Jpzy8H)^$|%abtA)~=wPK4Uq!(KG5mzDYHZ)9#d)7vAyX0T z?kMw($NN?iOwQGIA1f)dok#Mjae&Q9f7V6`VVbRTf=lgUHc3PR(TOlAFD{ZS-(YDFq2gH%4Qj=b()#U9A8wX_?_-nc z&sm_7td_|*(TUhtHCUD!_t}l(bCdY*Bkz4Nc2Lav-5_d9L24BJ!{ZMJiFYiv1vy0? z=;mC4tvKL5DwlBBt)c<8O&Br|T%2PjW}Bz)8GW zaqEdba89E#D@F@(4u>=}-vA5TLL6$DGFdF86sE&9*uRTzp|=EdQ+%$}B+dy~Hvt8t znm%tqd1O5f8f@I>dAyiqWFZkld^5=6d5{f|*LItwBm}H}uLB4!CXho!2$m?D0wOAC z*Z3i$JIva!hxbM9^HOH=dOQMk7LZh}kBfxuF&=)VCv4G~{5-EPVhwf#ZF$AI2`VmO zc}*rJZFUl?(Txq)r4$x&@?7f$h2JalZC)R&SBUw&=d*=G@@ijS>*~{}Sd&29gxqmT(M)aD_g!A28g?vyDG;p)Jw&l?p#M?F%k3}kq+Y^Hac z0EoXqM}Gwcg^2w&nE2&<;I2r)1)zQ6 z;BwaxmM3H20zUP{XxfMVyYhR2p0mh}D+p*!YaRlBJnTcrZ z{Z@<k+rAV@$qv|aV5TDlrT&ih3tSn59g5@#u#1~iFQXM{Vq!bm3l9}shG$>>|} zKxUdQ1woQ~nczlkpV*N76gXPb(c!orC>nuDC7-TY&=i)@;`efrClP~5BR^GdwFWjl z{YFHz`c<#xGSK<<`Zx^;d2Km5^4OZfU~4RtG8o{gj)874H^Uy#RSZU&1>)B=OV5{<3V}?Q?t91uVp?g;C6L#o8xQacGr)h(=7| zv6)H7l74i*Ei2PtK3#4eO{FvF`|^p7#c4;@YPMWHkq*c6z2i1ot=W_HG+$5s&Ssws zgLYlES{a9{u2sVqSba*s>#P9G;Q*++4Kc{J9l%flyEV4hZ*+qRo?6QG_N@|VwSld? zQhD5Lc_B%7-J8H(ctARDEY_-!#XnQ3Ce#HwsE&+F@Y&EspMIH5P~&Iz$+S6ag@T6q z-CiCVpvQkf+Pc3w?0CLEOy~NeyXj|UdGJ2vOBvW$ju~VRaUbl6e>fO`*8TY=N!kZH zof@N%k|s!Z^A9$Q`O=BfAVUjKJO5QQZVLbbx6@}Bq}QDxGWf=M;wT;WrLUfQ8%drS zb(_!`F!~mrpWrh22p$~1VDrdlh4^5t6l>Q@1I@u1!BeyQxe?HPuD=AsP%S3{YU|yf zam_Rhlg`Ki^Q;+w9)0WzggIyG6m!|1GSxK%c3weJ?d&ET!$_*{oBdw8YK#YfIycf! z4h1sL_E(_`xbAneQN$X+9ogL-&oTfRA=pSv4kjB!0vcYUGkW1Sc zNp%9u_rb4Jhk)cfL0HG-u4M;yzHB`WCA)@cNhWAZ75yJB0Q)Cp-c zHi@BGsR7LUk#xNK`}!IiLdtG%H4tXT-wNapfqnf76teW)S-=Jj&s80(0-v!TvNJ@H z5i`0ZB5?HZ*)4!fEJM*AaKC>hRm58Qp8y)wX>ZmC+ef|1Rh}ERxSi?`eJzkf!D5~UZCx<9BAJj1Ba?Xp>m`f=iHtg~?n~><*3O7op>p56 zzuX9I^+(&&Nqo_ra?QGsu1n4J{aBn;Zz3x2#4g`StJ^fVHK34B4rCrd7UbPDcr!tG z)(hWf02h>@#6ZPE)m}_YEW4~aD~UUu)fE4bJI2Z#EQ)xn`N_B)PP?{}l7l5G{bZeI zT$fuh6z5-)a08}MsunT>2yO}^#G=9+@Q3x1>ytd1lkD)Wt z;NbdL2eL?AJ~PlCxrYBD$g70{&9c+&CWtLZzeDxJ=afZ=*=y)ws2OfB%tIb1DY zObp01s9KN_pqF?$T~ezQ1$yAUzYs3E21sx@60Qi?iv`R^-iR^o1A#LTkB}#?3R1JP zV-s!%aXW6?KU^DZw07?$3>SpZcrP^=JYUTjh>L+-1MsF`RXL4%W573)#EUQ10LF#g z=H4R|884YpC(v5lbfZhX!}nEl^%u9NiJY~+-Vduzl950-zXj<1+eHjg2uNPc=^J_2 zV%|P3^zmQ#NqwD9S8-q3z3(jVFA;#QBe4;FzgnlU9T*dM+%Q1}qWJ&(!%0rXX)3Ks zaDA3jtb6K!e(2(FV4E$(pxcyE?aSlF(qO;g9o!o)FqSR| zp->Exo^bRMP<3g7LAXQ#NKy!*k8X!AUwMQewm9PJ0TiAfh1Gg14Wtmn&ypP0^X?DV z0>$~3GsB>AN#pmyztnGVYnM(uXyUv%u62H>2fF_)mnO5(VU4QKSr-j%{gdwn@9Nyo za|yYejqX9b%pPxY+C|NrQ;bk6RwV8Ovqi7XlM&}Q&=ZaC4K-8qOqpN6EIKr)2v{@z zfaDc@&T_UKl@Z^ULF@Y)<`qz+Nrwad2D|An<=gpKs6>KIWI@v}xE>*hIHV$^f=t#S zWol)p8<=?Lg_hmHQn!<>ZVF04w^$u7ce^BUMg#j%Dr@-|5hUoO6Mlorv9>i0L8j#U zfsiB&w&6%eCo8R>I_u{{szF9nJ;IH2q1Mzh_tUmY1pl#6~ty``+38y6#4MGvN#=}LPJGm_d-$9s;yJreGDWQiv+SC42At1k(V%^ z@pF$7R#R;rm;nTfglq{wK=C_Yk`!l8Ks6slbou6N@j8J3K75lN-RM0sdY^mtqt_!R zgIHujwVW>4iHnj;Wh+=2&fI(?#rmxTIaps#!V`mBw!ywt_@QhJ8kK>us4RXH=lp(^ zDlt(Me$Rmw+AfNd@~HLHPIhURHpLtqm*iSB#1Sz$$SZM z7ZXL--`bn5NB2qtb3r2U1akKP^0mF`Y@t`ZFrhQsFHd%Fp>g9Ndw~?|cJxCKDHo9I zR|36qp}KYfV#OXMF-92blRD7#hwFmHqrb6O74*zn&X8`$WaFt(s{I}vy5ecptO$pb znVB7hPm&`|h7-=0?84R+kZXM&m{D$`dZxqC7~gU>S}%mcC8(A#=}_v+uDjELO8eKm;aOpx5zizUKGRmcxW)j4?%4$>+|EzbF7|HqWv2tQz<)ruU!@ z!^vV-&cJ^O7=@A@3KyTsDO9JfKgox(8U@l7qmz%kAK$`fa^@hFg;t?&tdu)C0BysV zpPEDbc`&Kr*VENsk~|?-)V#k~$a(jXc|s+4S4AW{ zyzivPGuu#bvN{8kFGEpwesjrG1{cWeiXbUBJGy-A%vOf>x(g1z40h%Oau-n_<)M-V z6&OTpbe}Xf^UBGY_r8zN@GQ6K)l}8ZMcutJPd#WZ<7J?t5YA*%aRKThA z9WA&3*KsrTZbpNMMxozms}2BHZze%WR`~7)TixNc{=4gM`~(lMj7Uk;+f!r-YQVUu zS2KHvfPIfZiW@r*WJa$uA#PFrzz*7*g<0#-xE;-tS-!^1nMP!QKPSMK%OPjgC6VA} z|8k4#^p{ChA_-`C>rMWkZ7Tfv`ZP2+m`6+(mW=F0t0FYuy`}%UDYghiYsBU0%P4qb zY40C47wd1-3C)-p&lhy-EaEI@ocr}IUKOM4Le1fb+Q*?h5%O?cH%fL{61T&i6DTu4 z(c#T<*cJj_@(m7TJlm>TJEs$1zRJg9A+_AgcWh#wB+H@^J^N(PW8=h)v08Oo|)iH~<;PA!a26Q6om<@)5Nv;xyK}G~zg9x%7 zVo|GfS@xAFstnR-t1~_vywTs)OzbHjw_d6^Y$)o+K0z{MwOv+-G&%b!9zKDHL)Y^~ zWf+2SQbFK}5<6JDz@EbJ7$>58Mz%&iQFN(jJgL0`C?j(Vq=8~AL=9QIV%{UXkG#!D z%(V7Xp0c_#CT3=AU&sgzU9hHNz9hyYzxVB#UB`Yo7a+y^@M>6i2;7P8{&2iL;*#1A zpLql{aWae+H?|qyUmZ3~sNj)+fWg*m%>z=Ap~Np!%Jm=7&X37t+j3ULGcL}V4BCbBjhnT6)gNeM>4ilGL~bZe zMCU8IoW$(hZf&oR_L-)MHivs*nxh^b-r*f$BnckI{#O!}X3NTLyiYvGUcesGM-$62q|T*J|` z=)hXNrP%zV_a<#gIY)2U2&Y6cu6wFyQ87p}SJZ($!0r-YbhHg2aCL3!+#`|ii7ALS zVQ3AF?wb!8T?8siGh2rj8iTEt8n~l zd+LQ5qmKG+15`XubM2RGf4;7e4(!h{I8B=A`BPHv`-rb31`q!q_TDn8s`iT>r8^Et zcXx_}i^SC4*Xw`~9-oT<*9_xI)(Z$kIj4jZblvc@W{r(5V zd1FjMcAk~oeyWN4wL`&<&Kvb_6aiL5x z@p%1a;ojzaL}*rB;e;d!it~2O?%Jqk+ZOf%s}K>tpKEs+M0kbP=H8c{31_L+FJ4Cl zV1K|?-22eRzsSdw$Z?Wc)r&`w?(NUYYP2ht9~6k0u|o}HrBVKt@riS;+?<^Xh%MKIcq zoDYztvq-e|OrrheSgwQDwO!MvV5!*}iuRlbU@#-b16aO39)hq*T7J_qGaTc#0A-Ubva2>5 zM?ywsY^y`;T0A!&vJpg51pN440}Bpy3V-eQUMC4E(5r>Sa6Lfvd03crkD_Lhm}FX^ zrYD13ZIowLIC>Y-vjVpa_G3Y|RV@+%LhO!J+9%V`i)~Ky*#4v)WYGiKfyr zl8QgHCkG{Tt08yJ`^~K}1HA4xcSrN%3XP$27RCFyd+SqPmb{QjU>z8kN}b#-XZ%R( zfYXh7?##}{qs_E9ve`~DGlGfx?A4P;VM#RN4!M2esU4jjw-v@t|OPq9fwF+n`!G4iRy7cW*(+u{TCr3ch1Ix?3k{Df`n z3Iuq#4jDg|MYq4tTn#6XTI+{)W}7#k9dm?S4GxfV<{E?crJc!ZWVnJFizqu923hI` zHQRv{e%<^GZ*GeTg4*D2Agf;%Wn0wN-|~s3LHQ{I3`AiXo`j z9l5Nj`9|5<=I1ZEcNWkqA@E15JZ}r3m}`B0T-%wW6E5u{tJg0U`GN!$I;7Nul*KubRWVgj;yIW{53ct=}Th$wS zR2?`^)bvmeC2+Dgvbiu^E7$55JFqtA#su$K?Q8}q-vY|h(jvBDl_Af_Hc0YIJ?>M2%hawdF-mi940M3JF`kB z0pUud42p)Pj_YyUyXD*$bJ-CE*z4E&D?5{_GX|`oIQ^}InwEV&FN~@d!>U-jr?(!2 z=jQ1mSrlBv!!#PsomwM&y=jXTXM>JazH*!>Yp5&h(s=oiGMq!=Fd5w(FV(mEI`(az zbEfmMp!J362z-U)Qr6&;*0=`!fHmaNfXjNDn3EkORl>~d+ctdxID&5t^RNly{@hELApnxl;CT3m+1E#H^2EZuy2OW{KuBdkFb_q9_gVHH6yzDT)}{@$zBY|p&sH<9HpRM4>Y-b)c8B#!Y$3u&8v+Kbb0(&}ABR3Sw;lOzQ`n)m_Nm?HSE-(f!D{KaDLkC4bn>e6_JzO!KfTEYC(($N(EBBH zJMBVoqA%>9JU{<#VnAj)nsZ0ZF)UKa`ICW|dhoqGOC(Y0`zKeL6K=~`H1SFMgv|2I z;2{MZ4#-iGdrz38*P~)-v#N2N{i1|RF-H(rNFPggvKVBuO3O(-RBxW{vhl@uEo>qc zM)K@~l#_A)C_8RLq?iT)X;x^2dLpJX^QP+Pvb6b&){z;(Yuq%fOG74JnTk&jo}exH zVQQd@jEouuK8KgT0~DX{TQ_Zi6$}4pns%qjjq=`31%fwu+CqYtB~^vwyf@g6yGtp# zFMSzamyDSt&{y9}n>7HY0k!n?ZhrZYYVqhfJAtv#Im}49V{|G~QTFx&<+Ya_S(1LY zf%|Z6wx*{>;}d-Wl|5^>fJ6g>w4@w?C)w!Od+DSJ9@A9Jq_7d@d1B=+WJTG?3u^Zz zoPbP1gra+FQ@u5V|noaZ`yjuRXHAt3pAN5?<)K*Oc5B)_`hrtP9Hj_7H;lQ_=9(B82&AJjxU7d|2 zx*MC~Sa2|1w8uB$y=J+bHGb_?MSkmTt>@qQ5VM-ZCJi55b#j3b;<$E)AS;b(_(mCP zd`@TbD8=1?bu#y*0Yi>wl3KTy*o|{hccz=E<+W$mF&+qpY>x>irz><5P-r1t-6Cwl z2F=bE(N3(%1YFy_Qr)G;F^?PLtQ|gh&HtQb?QKUc6f<%4nIvCB8HdZfn>N9(qb?!Z za96eZrXsO8-uB!mIo0B_9-q7aK-iPy;O>I-;(IXO8GNa0IWFV7U9!0lG}&_RxeX_3 zFNK)q_4hGhoA%(qNM#$fEU`s|(lgU0p8EX2+sfhJ-m1SM`ZR(*(h#uSJ*9#rlIaSU zOPuV!WWO-Z@^)?@F3#oiP*#|*;o7I>1%dF5;I@p2={fM8w6>in5iX~qA3$xCx|rI{ z8`SP#S!F(ocDThit)8e~{F(p-n=F;~lV4lZDE)JyJtCIN3Y)n4g&Lcn%~TO2R2l>F zJm8!lqY5;NXtn21%eQi3$t0ksF!7JURJl;+UqSCs|JH%9#g^_a_L7b%IviP&59W}d zWag}XfOSsXWxcDGk^CJr1rzMGRZp)1m;ZQ|ClfE2Teh9DKn%}e4}BQf?=w6Y1Okdo z-7?Fy^NP8kt5U{11{2iqO3L{pBr8UXYM%l@KfB`VTf^DQme|h&WKi4j)4@9AE|6mv zf*BI}BQ2{`l{@kr#+n8H`)6o9^~ru(iqh^!pEu^ZW{)VBF%NuhumTlzOG#o`yg7KmkvPP{(ex$G1T3=C>hIvH|mAC)OgdH2pn1xH+f9~eZN$L7DfGP|4k|2T#{(zsEPEk{%8inY4v=J=smi4L0{UDjw z5@6=%&4E`1P#WAyC-RrWwcCv)UObR?9up2JW$Kf67}H9G)@0M@sO#Ld0axehH+ROd zp;(2p5JDsTXhErKe}`gE8vuL5Pkcf(P*03i|Af>OqUdggIoItqVadPxsu50?k zY(cQoqrA!pA|g5Tyi(U;Uf#PHT2T)Fp8IIv9g!Z>yPR<>QgWebVIlsO*!Be8_`^1m z+`U)V9QBJMRhA-`t{>VN;G_wA`#;=CR_AAwi^do?x!?~}=K_BnA6Rb9ElBvSzF&!43E1C;vLyWr{9{tKog9^fY*m$JhP%(h z-mRw7WasS3P#oKAk)g$Lt?tIsROGUEOUvUpz`s53O-6rq@yjSWRaH*v8>-A=5{H#a zBdSrFR``*_C0VK~suwcFt=-Z^6cD9sT!rI%n*}V2t=~~*H_VD@BvDCz1Eu=1KZt9i z>b_+c-aBWa#@z)tFYgrwzm>N^`O))!#JaK1@753Zwg^vGwJ}tBqgKkS1U$h) z?PHAs&>Am5UjO!bOKFW(`k7!{2`cs~5wXc&%wZk1``CAi=~?;?o*Yr3?lx`=Wh*$m z{{Rl;P`!7X>x{UtLg0%}Y+QmOdAB+7fM<$6KvL!&Y!lXnsz72jN)VT;pqFi zf2*JA+e}cdc9w4yd5D-z2CK9XR~{I`(ktK_tkxAJ6Ck_}_Xu^HjC7>#Xk41AUN|}) zyx@~d9*HmeLVYQ+FoP#^btWj7>b*`%1m$||@T&05X05l}Cvx|`S8eHoV7O<=G4=A- zSkXt;2XfSxyyPQ?lFB~|nrk49bAdBL=?d3R>XK34(KqxrqyW&Fj^FZw5 zn9|9VN-JYGdlU!fz4endJ*S3p&a-^QhS}k zFYyASihlFW0qq%f5pZ&-jP0)tHB%edscymd!zLZ zL6=+=94n`ONtVpU#Ka(jNUTkZwI25NvUECNRwC5myRnHvLlaf{O5AdLeLbM`T=mv% zd8iG1Dj77jpU8%#-Y6gLoM$?VFXGna2=M09gIi_8kt;?aM;oeZ`k6#zD4@zj`Q%4n zKc_`rmc8x6qBcE{$jM0K&n^!&q&FJt>Eqa{46o&GiJ8f>ez{V;FZ9}I={%|ayvOa* z>$Zb8%3G}$a-cwk4B7vpOZO8|vw4G==BF7uZ|AkWeF5)+$+va|HH{6BJbOb~N(Ps| zi$g%(ikt~u(D<>Dxh1MBRDYFYBkG9JK#!HrWLL=*NT#Arabr)mR%_Z`86kiDT7C!! zp^D*1SBLy)9}VLmQ!I_8(>N2%5PcK%OKmO-3+Ln3-rq8SR45InGZr3LWnID&DEH#zdQCj*E?%gE{B( zR;|`=`Ys!$G?jSZQ9KLt0)oZEw0J@IUDU24TsWS;|^j zR`T;tYxZns^yqlx|8fB+IKtzsFl^NBe1SD4*X+?g;q|GtiDLl!+QUi^_FX=Uu7tet z2GM5{iJz=NOt$7pL#0=aI(3x3X0kNv3JNrKQ%dA#5=31iAqrtAmxy%dWP|@|ABAzP zx-f37YLy#nMs^ZUSFTI?!x<6r#~fWA2WQ%cI0($F?L{A?&r8pc^!9G7^D$!~q*zJ- zKm)l;{0zaZ$P6k3{bpqX*_=TLdrPT@{mF`5Tp146j)YqW*-c5&t4SDy=;YuzW;<`* z$y(9}Ph&5?W|1y>#)9ZHUr@rajUd2vR~_uqY;0cO`51LiIA5Mk(dpq?+ZwxJyxnCG ziXcd<^?yK2#?+h~)311bMU6y$a(0|1>|{Cb67u^|lxp02V5Ph*jP^9^y~Zbfmv3#q zWRl?Y-x_JQyZm6EioP~BZ`;Gi<~tEC=g>%Czg+$#^ZiiHewSw4?Sh9HbdZDo)J^uQ z8@)lhi&Z{?y;)iM4BWdDj;o)oqpx}$`Su!0M#QXeS=eDUE)+7j@=i8+kypfxxrQMc(CwiKyu=dTiO_A{9$;cbP~7Dt&5gY{dCPx3Q|0N z&riM}5gto+f0k37f6U}eo4HSMu>CLYf_D`-53j^Pb{Sh>-2m~f02ku+;n;E!7o|uUy-+TtA zac?6lMPg#^*DYT8ENs;3l^Ga#tir#yelwgKp%%DE)tQifIoh|9iW!O7z2!$_e1V^8 zs67O`n)Ctp#=|I>#WYwWP@ko4VJv$>EKXlXQ z>?y{=QOu06vCg}o^YTUcbAypmO3#@Y88#l@2Vu2F{vB7s=VFJ26_CW9QPui+=Jt_9 z*NP(|SSSVufD3l6F7d3Strn01t3oka^?>99{=~YbFKIe^mUh`nmFwp7w_bCM`0V{! zd65a49IYl3-_L#L1+cLqZ@H%l-+v)0RH%A*IX@vIFaG&Z$+*q~f~0A%iU-zMgX4ro zD%^(|4&pn4!YO>XrX;yp^}LBEDMxz7Qn&nhbz{En&V0}BQdgfW;97?{@@kPgiA#+H zMJxo9QGme5OvnsLrW#&DeMw)Y;7jKTdM~=@`l5ByuQp{nz+MD^>{(|&3ZyZWV!oc8 z9kK={ZbI~>KSBr>tS)U|w4l0L7ftFat^7vSe0qhr4H2qWt@Y5EA=zgc*P?zR^WMDM zP{~gG@b-Z#nPbCz91a`Z>U6)oM~VEwDi#OrLTagxOWCJ2A(pX6J(yQ0Q|MhDzQ2(& zs`R0jhh_KzUmKzu`1YLzSPQXFCo=8WN5|~9zYAwMH<~GEYU-NQc719T#cUfu?5k{6 z9>jO`C=>^OnJ0A7{81&}wUtH?R-Df0f8@>HXv35Fu|)Wm`_Q-2d-XimUR2?HzS;HJ z9u{}qm0-7!hUHh5ZDHjIX6CtyUK_HmvZk1Cx21}kI;vHH3l4u|r&=^i`{_KZ>PDub zj~JmH6w{WS=!>WNpHm4C5vJ^p46X#@-*Xi%?y|#I0zStm{7-`P`-8;@(A!YGb`1Zk zCkn=yiUPsT?nA+!zr{%ZlNn{IfCffitd`=>&!7GWR?yK++dV_;|K}PJsBg48USIel zPCC^x1%T?sBd5vgD%{$i%kBK9`lkO+4Q_T>Mhes@ zYog32^$TihYU=9Ey2}%Wf1XAaEv7UA!A^mPhpQ}GH=c2WoG^of?S+C%^&G(^DjfPv zPj8uSb^TutwNKwB`~lDRE0&dxPJVkXGB*nPmVWzqubJ~K503y(FK2OBn435z-;)4; z|09q^9UWm)av_rDzq)8dSDH>qNL~H&BidZKw=uexiI3SD_z4cUep)xm@k@3 zy)xH@ox|!pGyn4WW|uiG9v(MIw^GPvz`{%a%}&8YmyzGY_@ses!OBk{%aiGjr56nN zBy*mr_A=pY*dh=pbZ%T`6-c4DDa-Dd`M-DB?t^n~wda1S?H4k3W<|gK`)~7ph~PJH zaRv{P)3S@GntaJc`my5KgD+Fia;?(P7F#n|R{S0=S1vWyqcaHg zR@L$^9fInD321Uk6fHR|m&oNk$puPo@;|R*!|~6@)avqvYwXN@?n=v^j&9T`a?zuu z$vW!y?3}-ZbjRZOd8vbLR+eErQA~+Y=238?P!IR&mj)xHKVxf52>ywq)^-LX-?9Zk z^q2=z9c#X(FeiqCi3b8BI5xZ~G2alPtdebU1b=c3FvZ#-5b4~zn7j8U7WsZJ0Rsa2 zYe<6?iK~gh4g@Gt7JjzoNJW$1>(Yhe^xN7@a*sLwx0HV`XdRG&>i$s|{$5D!k53h_ zpC^{l|E?@#2&`RPKCS0QXN81F{1VU=;@8yvOeU^b3s~aJBw(I3ZzgFVbmHF-l!D~1PT&RWr4tx zrWAAxLW^@wlWV}s;ZOxW(qIaI+|0o)YopJPCrhMY!1!A`kPz%n;9Vb_A@5UzN6N4U z1ia60Oolot(3dLB+Mrtyr}p&AprGZUn=unYTCbD1fAl4CCj2VS35-cT?Q`}E6MMg4 zc4_ds5G?|}S!>ZT1&WSRKj=Sl-glesxLhX>3(m8>F9i>PiS!bPw28&`qa68BKzb|+ zwx6pz%lKy?GReW$Kb}@C9lwm6?5wr4MAHjCS_hZ41TyeA zF{-v&>WqkmJ~vzfmuQy{fo}zc;STaczx7P@=GWAMY0e)TYyq;mwjHki&wjb4-u_e) z6%wL6OF;3)>|8}jvDY_a!ZSQ-9T100+UvZ8;1aB90)DPNq&93SB&Z9smzI}r1@rPs z^OwEfp{q)4_Ef7+f$xqnuqgMAb_@2LGy@SV&AnVUB_;vP$ykW2h| zGa!RKJuI#dsYjBmTuu`TVQD9$ROH_H+2hQ9wzC8f%- ztdHRjB7V=<)?f_tNdq=}0F(p{w_s>b$!ONN zsWkI8U(dNtR+x^zcE*`ki{@WF02*Bz&y`11dt7VKTeg##C``vBc5zf_NlaI z0aIHK_nmX+*$wC_x#(|2S1$zPB&g!e6Q`^U# z*$&lkllvYtvc|g9f#s%6l;@YaEQ$VEbrhHq&Ud%mm_o2{p_wbkD#Ukw9vM3;9GUzvToSC!U2yfj!{G6|58jQl)9A)P~Ak2BP@a4+kXiiolcWL<3Fx zS>LHb0WxPKcHhY3{k@S!j%T&qhregPnHq#MgFK9Sx%Pewy;tThs&%&j-!0(S=N)W> zX?(g{eTiLLL)1b>I_14qH<~=ZHo(eC-_m+?&UWQ(&wP2S1t=rJJ-n9&K7ce=(R%|q zpkHD90p1I24+dtJ#Bs4;n>*9PUm{;U;J-Pq&aYmL@|`C<3XzAo+#&D-KDksM(*Jyh zOgS5*O!dwu+*(pavWXz+P(Sas*uJ$1=D<=;F-y16d{%^4augSeb9!I;?P|A4$Y1`u zKO+@l9G+pyXd=HyG_aRMSG~<=1wt;Z5`$z6u$A_s;9SN^gg#l)k#E`ca+|*bg+2e6 zL|sLtnT^~d4qT6MRW-h2}*qASWgQt~dhtLgQT=@qlqD(lmvB>=yP#Gzw$#amX`lC5;#WOd7{j-K% z8#2f)DY>VkI1wPKsHxm&*@f5jgk1=FmQf6L6U+cECwb1vTPo-ni=*skw!#6GWJF&p zNS)c$7-*`RA1!k zD=L&C38NI1r7zV%*sKi4%`cbYw$v_u^*UKl{yQZs2v5fVjM>mWQFvXwKg0B zwiZ`X1=F>be0BuR~4geS(K2?V?|t@i%Pc`u!g%-W7tBLVyaP-UO_1mz^&o zbAqXkUP`u&*DnF#!eBM3!EvlSr-%fEkcgKQ*}Vq*CA>?;ka=@c0vyiuE!8pQN_B3l zKzbpY$OHRbuviB7;HSQnIPVF)Yl2G@-L7ZBnqc03l<(Ptl#<~#c)T~- z=xVKssk_!wJe)9UaH9M2Fh#k8pZ{*Qu@H5bQFqoiVDhafMW%1u9zP;qRyl!x04-=JY7&NJ0O$Ug^D%q;%QPAGp#rM(r2{I5o8dqE4_F1B{pQ*=w zh8<6xwB?>4twH%4_UY@FE%2mamBaY&rAsYe%NG>r0D*XKZZwsKfiI z`kHH99FFNC(=;NPiG7_jQ6)~zR{HMC3^FYI52z{B^) z=QsmGFOEpI4-Mba6BBtjRjhBen6=>nUsHT4f?NKOT8f_qtmY<;W!SsG<_{>xKI>EG zODmx3fW}MM@0lszk}3~USWJ~j@S*e}5)zwwK0?TR>&%}J66Co4p<&cg&kUJY{Z=@N zKC#d08fDx$Zpu;jY-XM@bjV!>dF3@agQ|)qbiHQM%z~C?g71EgeYXy z&m`zq``pY|i)K|Il5_uDjyG;oT@@ekS=#v%Y*W}Zm6=)qD!DKAMZPJem|8@`@?nxB+*ENa- zUnG8MO{uG?gS*=C#eLNxm^vq&K?3yNG5-J)cd*Qa*`QA;#IiR)?q)5i2%a|ogm1%~ zvmdZH4yEu&_j`Zvq;mcz%Q7Jt(d?n|75evVhHMvt418^YsDJV)Bvu1NfcC@+X@6%L z{51Kg5fe6Vs_Osa*Pw_K!7}(eo&4X~f`9656Ouf@p7{H)IX!QLanA9w#RM2{&$ap_ z1UC?%2H(0As5tFBX#0!$$We@x2Y+!W#;jqWtYXAuWu3Ow#2megyg~8%#JWakuZ_Ha z|2~djP*7$3Y{iGCJs%IaMJ~HW`^pi=gS7n=!6_iLzl!t+3S`iO-l2{rZp@&dXnpIKueewyCu z>Lz+)9_;Pm;NjhnC%VOj8Fi)|H+qngmRCeKO1c;CPeRmQbb5=Syf(cu|#{B2p4dh3I|8`y+&l z3{sqv8b~>2L$ILQQ^J)%rW3cTXeR0QVt^KcU^}Y7>CLmU(+8{oO2raate1D84^- zkI(q`ngM_^20dNL|304C02qbuOs0GHzt{f%NA`d3kp-67)q8FwUmXC=4QT)ov0t6j zN2#45Z~)i?d`c}F6d6#iFj1(Tp9l^PCZZmo<=5j?$cK0W0>)Z>UAhnCNA_4hNK(E$aWw=-Cb&Fmo`i zze9aH7<#1DxmJP5`|EVe@?`x}?(-eJL?6IMDAB4vNnJ%&9+c7PBJ8USIy;l+{KlMc zx+6(FX-5EMLWV@KHkeP6V{a8& zbG_mRK(iz4<;ql3vK9Bg?@CNP_cv(P4dzPYb2Fd;=0 zah)siOZJr^c(}M9N_3g)zfIIKHk%&u8GKn_I`4*l8d#bwZhay8PPG6j_tFEU_-60T zq$)>m;ElnX1rL{B&@aeBB7_4FpD?M>^#F^Af1hM{@A4lgPRw#sR9O1y16hdGgvg2( zKEGiE7y_vDRy(Vb&Qp7gwvdGwwl!-TyNo2lk<{cK6v-8{UwQMO*7K_r%n3Ig6Oqa> z1)Of^A*Fl)M<|0I;8T5_+7`-c@H7DlbMyd&;_z^-O}J)Fgh?W&?xkt;aA7>KbxEZLAx)oAt?KTpZ@{@U}tCNh6(DvK+*fF3f>zQkoa+2 z1zhO8gh>F6=+VdsbV*zFcc{vq$X6c(*CwNzkAD(3M+NhVF#F3|M9{iD-qW!k$qfmJ zknk=-5dw3P&heHZk2AQSfSC;vPv%mW%v&)#7$zuFLr?=y;ri%rfdUTb#BjzbU_&_xM2vwy-mn>|&z`wB z-~~;h67!V9_P0K(T>?Wkwd{h6S2G5>JpP=MK#j=T^x4~(gUv^0?&r5^<*$yW)ZKo+ z=DP4p#5`9GyjF^Jxxowg?o=ZMC72t1s<9Q!E75Z#5H&?b0@kF;$13z?uKg=xH1q;E zgruo+Pmc;V1C;kk!<`SN)dE~9y}^#bjmC? z=@JD>Yyj(}7i=6pUR4r~J#I(3gTV&?P!z0s2_BGAM9q^j9$$<}Z4Mz4G%O2Ovg~&S zFf4U_lj=`MfY!)GhF~Ec>-7Kp_Aw&h1b&>&jUD%Lm((*NJX~%Sh4~#jYbAA8O}h30 zme3h?ice1g=!E!}@CeS$Th(icI;Y)}Xr_|fqJ1wjW?A{ePcQ0D^=Wo~B#eIYMQ z=hLN>744B_lzP8%ZzS0~@J3Nahimj{G*(IUdSHE8c9)6?ECAble((goFTZgU%`-{H z2fKSdrN(yJd%TwSKbAe8zTP{Fpe^Dq(pu^u+5$iXnD61vxnK?e^kZi@bN~-v6}PgP zs991o*eJhIyYu~|-ip-7;nQ>Hpp~~dbT&fwR-(5Fc=26h}vEe53?&0XMG z(m!mR9?Eu)k6>vg81qP-6y)@ZuAPf_7$Y};^O*1hTns@_qPCbkGIAT3AS*LL$ex%~ zXasjPv#dg?@VMNx^vnUD zo6RwH@7>Dq|UlV?nBuH18Cn1dX^hQR4v5<;dFL|S3pF^7ez1*;r98Zs!Fe=VUqlJc<1}40F}iG{o-ed#g`$&by+FsgJMQ_udZ1p z|DQ9+f))$95#Dxj5i1MbA91m3oe5GBVp1*IL%H4|JA310;F0n3yK#C(Q)gtGWIk93 zNYp98h9O2m^0xejzW&3_$ck$f3_~g?dFU=7&uHp6cPYf9akRZj#il*mMa-z%d5;%$ z6jBuGTc1B9PjY#~C^7x|moHRTh*2AF5$24!*vhXGa1H7SbfQzv+Fpva|16b6>82o{ znIYERS%x6jT&zE1*d$Wdc$9MU|j`vwkZ{NZ*b7`x=9b8p;ek#jSEj#f$^hIZOpk&7T4-4B?zS z5u#(rlPK!yqBI4fzw^x9=R3BeBH`oUY=T^h-W57D$gP03!yFvk#P~X0FN&@(eziU8 zh}Oybm3-9~Xv=E(b5H$Gj*oP5JJol9OKjywrukf;|6LLef8|IX|05bi(asW>@qkm) zElxzKUe6tSSA_`?woi?DKYTk9p$)sgT@#}q$o1ke}jG5Rdd)4@B}kt84l zOs+X6M$uyGnhDgc#}DFghBHTnjTYLUB%~RIsWf+n9B$~QrxjDT*hy{fINWr+>I#)5 zLxq!^Ac61S^Ua8!2{fAJ6~h+X3*JGAH}q^|WCK$+Pa$c?l*t z7V!`C-Is?TI%<4Z1rer^8)F1dk>4&0_`-BQrs|x6Hy3Bsr5RWkbhI-L_3;mKgcWg? zcsP{GSsEcvV-N@smI`ev8(|w%4!GLYgT(duc&z7fI~PAkf=Eqo9OEP(TehqxWm#JUcnU?Ez?gGqs9absNXNd_=^`J?e3qBDH+?D`Tk*YHCKUV-rt?~hCgyKKwYjkCYzqIA(#wBJXd`RjOzuD+TJl@C|N z^5HMy9+r1$yEJE)HWzpSA&zMm3d0Ks+xa@I_%v+ZDBrZ@+Qi1|t$~W6(wmsN`;+$Q zs!?zvqrQm3eV5GpKy|&;WVaUVANijX>IfBOplUWg>}?JHbWxx`YtuJwzMEXbEaT#` zwKxJ%mccVqey+kn0ApP!pnoa#S>!!}j+rWzeirfDZ*2%v?cdX=nHe!LaOdAP_1drq zy(%sur#d6j^UOGL57e#@1}xN)Ft}~AgPu*SUQNM()fhARPsM*;4LNB>E?Daw^++Ig znxl&KX109O+_K=$TFKORhARn&0tS3hq&x^O=nQcY{2gwt5{`v#?)P49wdtRCg|>kG zWri=2NG%}zaIHY;D^1j#CECTsYtCz!VaF=+BnrJpwt1qZ8D)X*E~_T+ioEfQ)m2Nz z$_&VQ3E6l@0E6Ytl}>0k*{9k74GnOdb3frNIfxHpH+6U-o}FJczpdpk#CY{$^Q<{^@le9e%{LEWOMVi|uW=M9Yw-rvYEBDipK zqEUCb!f`eDd#Q}=LWAFv)#sP@;W^XlMpbk0O3j@4(8-{ObFX_u8oj77)FhV3iq_jA~4&?#K<;-OYS?Ci!I`ojj88WRd_Mf=`@5tG&ezpUpc^ z3ah5tr{Le!cWI!N3xXq5r5dmH)C;5q)o`REE6;uN@K1MY+{;xqX8M^Lv7bv`ka+E~BlON_@yuXLJ;t~Lu|F?1TAW~d8ngZQ^ zXn6`9zI`c_&csf~%tL! zUt6oOc3Y+2x(%V49h??lShoG46I_bTjgp(;*N9_#pb(?7whr4E7w|S#*$J@0dXdJr z1Lh>(UAi`_h`X$k=qhN0O{BCj&@hTSb|KifPC5K2Bq7S;VQ~$21KoL&Ju%YUXrtvS zwNsmyIJFD$hnSBVz%egGoMXG)Dtpm$eX{;?wR1uj_(<2gEfM)EwA%*sC3NWB_(A}6 zZb?V9n2(dj4Iprc6a*f<=$-f6UB9`Rqbs$BjC1m*8Z^!T2WkN$y%@>6s6xGNZQ@vo zzcirkXpFS!?nqiAR9NVU;|(0OZU(^`OG89_-mM=k0@xn1psVeTF;C=(*u2A{6xjMj z6I{&17QrgYva;s;%j@3L)*UXZ21|W!#1z6Ksd3c}y{0I8WiJ`OXJc@zq;-hTRcxqt z_~uw2EE=}8B-oi{HmP;h1EVu%@evtrW2sXQy9^La?!nvF^H+AX!!oqblHFljEWM9A z$^@$u_c~93ywT(ZoF}lXC+*9LI(9eaIP=~7AIWqwUaeii*9b{Tj$myfWp>^P0j7#HnH` z%_4w$@-@a*uEhw;7icq8PkX2!xKj@NWvqw&;}2wuL72fE?A?Ff%|=yc8QiOt1FLMv z+tY+ipf0CyXMMc#rS5&I+BY{6*^O9-xz^@Xb;mB!W_=F`S0qARV~dO0i-iXo$v{t& z0Li(J=vfo}hd%}^9uI=&%)C_u%jS>a$LA|88~&-~Sj4xlejxDDC&9a|9-F39r+@Cc z^3>2%ViZi(`ycmA6B%6;u@3Vz-EP~F${WaTk-`@8QZl-5E zR(`EUO9^vh_{siPuTocZuhrL08G5zmk_E@KKPZTNCWe=pvZLIdl*R(|4f+gXsymiw zDnz{)G1(fn7f#ZhD5W>h{(5))gZe|D-v3S?$hckL9sN=%Q#J8u8K^E7(u^9J)_N>u z-5E|8S>VEsBtqT2cfO~h3x*13j#OyFOp`l)3r2^8(%q$pkN+a+?cz9)|5XB9#to+D z*+Zu!8S#v)fCCNDTL)Vao7r;Dndtw$W~2@!2Sc>c z|N0#KDMO{hH;1!K;_v^xkzky14k(5QI12qUcaT`wm*JbsL&6s?{CR3H#A{Gk8} zDPMG|X{ql&*973^D>{2s{(VHV|8GAwrF-;`Dl5&A$l#optYoZ5b0P|MO8+V4L?G`U zqq;Xm&VtrJKtPYX)?K?PB$yytOpK4)_jo2k>2C~I}dTh8!mLTw)F{+BlnOmm~7DMSl0ZLj~~y5#y`>G&!C+W9Gb z?8m5dXlP-f(}_GhLpLLRJV+~Q`ZnMj5lTfid>&z+>)=VqEOqJMw>!jz;fV&ssmem2 zwBMA2^UiyqR}YRbtH}EQ+@>#5wKGe1jQu-j+Lv(H4v{#aY&fn2Dv3W13e+)mzo+Kc z%7yop<6dN09wsvRr!ukOhJ^?TUq`4=sB!YX8_5qQ$g$N4o@V!q(tg2!27~$EdrYtw z0TK}^6MjrE+V_z8U1l)fJhMtMQ6-gKsD;VDZ$DQO3lYUe)lo^0l_YWSzm}v zXjN8ZFzJ6ja0@=r*B>YVztF=oNI+XU;bZmcKa=w|PPh&i4p*^c*$vFm+c@a|EJyqF zV6++fBd*%FA#%U}ETT`!NOzFSv=8b2r<&&l6aW4CRF&Po_c==m6aQvtR^0#9kKIoP ztLC0xnu#3hK$D@mO3yuM7RFs629EiEcYYZl&~|%6!2z6&ogi4^ng>g6P<%a-mE7)6 zE>6=5`zC4hmgwJO?vxI_cfOcj__^C+-&|FdSRV>-P3ReD3RbWC+bhgWOs2KBoQPYT z{77k}x*h+y=bs!pZNByG?d?#{k@ww3n|b&~~8VcY&B&+%vGpgSnagu>SvsE8**_3%DARJ96!{%0CiB?3N*i$@w0 zFlr9;m%hXTpr(K&S7O`;*^)-iLQY*fbXQdVu%hB#(DX_793xdq-)hHSWtk`GR;baZ zdcUl#Yxnh_o5Le81qTyQ)Halyo;&Pv1L;_2z`~C-?Rih;KQ|;r8T?o|f@n#ddqbAb zs0vwOEV(JVh$t6);q#-ncmJEo6vf-b5{W}|{vi$IBBlEp$pv+FO?N`(+aB8oO2V1e za0^xJxBl5%s}kEG@iBYh{}3uHUA}HB4-Xn@<#1v zFu|rV3u+j*uvC5hgc&RF7<0n?^A(EB$?;*)!w;9gdAz>jm&EP2ZczG`M>}bILSMRp z=4$3*7*mr{cSNG(#q9UD-*!bVFU2ljE7xdT;i~z_HEV_gENb#$gY93y%LP0^(Q9oF zZXDtQ(L$si)tv$mCqql_YGlYEw198C_dWY5-WPw&L~VghnAC01At8}72uNfF8Q!Ke zCkHbK)|@>kus&bZt7^l$Y;4I=L7|Z%qd9${V&v)5bdWH+AswdOTaGb!5>#ZTngg3Y zda^K+X(Ut`mAXBw{VZ0ub-~xbU~wWjO7z4P>N<4ym}n2QuvoO%*w`$7uH8W3RF6%S z>Zk8&H#QbvV*zO&8pwE-BQD`U%Z?VGAODBFuj-0pTcZU6!GeVV!QI{62_(2faCZyt z65QP_f#B}$u8q3{cZbH|R?a?q@AD7teYj)P=!fdAs@2PDe)F3%31BLTiHq}KBW5aZ za*K$oX7`~8j&fSeq#$CAOD*bE{+G_%;eInbC|&1x@Y--oaIT;||G*)lE#hmI<1*=S zrf1dp8)sm(F_}w?SJr+j!Dl$~qhPgb{qpSbzyL`3Da0q>#95ugy0N*og z>u-)J4km1@G!blPPrDCM;Kdv6;89-7iaPKQ;H}eU@v^K9^uzsJ5L>%U1bTCGlh^rR zC?Fb-r_u#9PQ!L3#XhTQy@W#W?bBnFb~HZ!acvV6`mg(ft9mP%`vKRYe4OLP!X9RH zn@%IM8DiC*m6eRbw2#S#ObTq~b1cNv)E>7{dMzqmXsCV&~Mrvy6-kK;p?(a-ny9fz@5J}Mv%Tb%~I=I`(!QCS=6eMr|@i+E&uo%K35F|+x6 zl&#z@-mQgB9?WJ;tRW7YMRyq3_$-Zo>&mGl*?O_od-_2|0)@~jVUCQ016eHqeIQ!( zVD(DRw&5^bD3K^8CT0TI$>yiUJJ_%CBj_rzA(oJ@xLrrD+AY3KD3ut&)~e1pR0I3Ci?L&66y_ONO-my_4ToO-0ny`>OE$eY$SQq!cxSqG`Q zcitM9mIx+L5Ar#m-=dqA=Iz6-_s4!nGp!L#!PYPDQ@S@-opP4M*| zB+XWvU9WN)cS)4wJt7~B!hcOfPz1>CJY%!A=XZJCuD&i=R(RdEaGu|HygpJU9t8fj zY(CbnJ6kAoE2(!n%omp!`0yd4pV{WIA$@U#)Mj0c)&Oc@-g2o`MbRE%h)`~K`*@+* zZOa{$yb>}}L4x)$*%O>ZN3|$@I~$#S+52ldR?QWeex>@`bJEyRs(wLv8xXw?5gJuz z3x3bQZaLZPaR%wBUT3w@-qw=YcC*i4Xg=w3URohQPc_JiQK}lgH^$?9E#FgXlG$=2 zT{cf7KurDWc>3bCn9fn!m9up`mcVAS^j%)59tQnAdXs-+Zxwgrx93A8$~Q>bx3e`W zSs7ZiZ4S{CGMf1_MWUnVYfix^C+qdb)2Ers85ancR3bX`}6NP*tScZe&`ND-ob`I`%H(7JNGx;$St{#*1`=S^Cj zl}w4blE7~U5B5C?*%6L|vSsJO`5y|No_wd61JMNfLF*>gTn>s;av@1y3y2TU+SM z`7RbqIV!+=y}{Nd;^h?pgIBqL%1cM<3gkRYFB!Muw=(F{cY%~%&cs}a6_DQG5VgQ8 zKQs5DyKk9y=UTgxi%Fl%9w7_HLdsedyXE7Y%*J^K{rF9>7<4hVAK)`kYb)paHB#9B z?fVg}!^4R;0mY+P{Ch#T<%Fyz?_RgW-L1Pbu;?`+yuJZ2e;!z#oaQr8l6|^2xF$OX zxd>RDeXyMd_wKK-fRu=XL^U08((0|J5#5*K1Ra_?mi3kpruNpdZ+GohQ>7SZQNivE zDXb?mLwI{1?nH1{?CAgpsJyh05dyEbm-M_I4+%U@N5q8MZLFEv_tagY>w{43Vl6kv z^JU2raPDn(=bTOkTdOCuLvcWqYV z4%oFE9mo87%FPy=+uHc@oVC};sJ`;q?v9^mwibMRT8B1zhv(k3DvtokLE?6{T4UIi zfgNayaNL&UD|xPr%VS|RmewaecNbu`O?PHn!=kA5YO))Tc=HHul$*L;b^N5lStsy* z&U9#r69o}AV&_YZ;bgQp>UY#&@Wb{Xo495}vG4CZ{^2Ku_ zluNyAdOnVrFmW2vr2gEuPTy(9XFhdXBz*k{xV;>!z*`QFj{|h!ckmwos*>kJ?QL>W zhxf>hhDBSDT11C{K-U$LPoK*)sL2jR*$s$Rs_4VDaKZYMQ9TmT zobREJX68yG)eC?OM~xBy({@q}ZQOqSiBSne%&V*DuIfm*$1$_a)7Jv|@BJTd^-Fl& zw(yFLwUYNUNxOgr9+3!U^R*=;&8p3NEWX2okJqw%9@s=7ewl}JEVeXcBLDvJ zNl=*PWQrFB&)H2`CK_?zrLBb-=47!BY1yc3$w_{DzbSuA(`L2$Vlx4uk9ku0Xs$#s zxsv!~q4}V*y^THBl7g~eLZ$5iDV25qctjW}y6r*y>WYZ*_QRY6^l5Al>_vgNIlH7~ z(6?|8$@m*fmSfUO*ND_}ZRHQijgy)URtrtmh(UV`jSIcKM%P*+94Adm*XBrAgR8Zm zvhA9^_Or6B*w8FOvS5_cJz@Sz#>dW=V?(SY!|%!nmvWr8vv0*7tCvPAJ0n>YR#k8NbzDJ0*E9 zJY_pEn6j{-R3KZf+cv6`X{_VDbMqwHlhf+42bRHA)z=g7G$ZU7yTckYa64;vZOeo-fm1+XI?C?UAFwQbtLL;%<}cE>3$eEA?C2?YwY z*{Pp=Ap;V)yd-x(g`I;dQKQ3V@qDM*>pCI`oBjW&8zcf zS*kL0m3}TXcLUYF)!iQKf~hIUl^AKbiqdxfVS_dHxb(j3Xr2zA=WrNkUDCTs;>GzW z?P6<>XdWZdo1+SWdOG#xjvKSaja>`StH=QDo2j|Z{<+oZv6oUOU8 zS)<1Opi)7N!(!#bBQ|eGNped{X3S(j%lQ3+!^mli{>df7>Z8F*UN*9}yS_v%2x;r9 zXY9p0?M9;)I>hd!M5&hR{jpQe%o+D`%Y#{$7__K$n>8T<3CmmOlj6M0X7K5(Ez_aJ z?}5Gg3~G8ZZ7+P9f*e9W&TY`3-}n;$T?%#Wxw8J$AB{6M;4yx6@*ly z@yF<**1Ex;-7kkLWy#DNjM`kdeOB5cyVW|Xk@!3gCkQq8gum^IDWFJDp&%nd0Hky; zm}<#pJR`1R1fr$eKXwVkz3c?p~RCiRDv(hIZ1{@J`9&KoP( z;zqUR>w);3mg2yGO?_^$<*XPu8b3t|ZdGSm_L6FjK#GGP{1~;% z41mb4N?bBUX2_+i_ewvg>-dt!vwb-gxL&Ho(Lon}vXq<6Y&My$jXy=XTh&yPkK^Uv zHM-<>jbpR1a-gFFX(l$>quhf80ckO7%B?9LY*A{+&rZ)B)&O5jEMv0G$ZS6({~kxKz~!e(qFnV@oMrO zvsX=PLPl~|pg0_@qa73Q)|lQMCzpRe6Th`2S`-L)&1~Mjoo)P?&N7tfHA!3NE&9^m z9D1?r?FZ|6(9K;6XerCx*U2AJ6$81N^5Rg~*dsD1o;ATM7{hUu0g1Htc^dv#4>oN# zmJ}KA5yD9vLClFo6j(Y01iAM59VZ@@uLs;W_AQw4)GuS@uf(jhHzR zk8BY^MYwAfqOiC44&hFfQ*_B(d$Wc5H=W=rOSbnrYi~Y0YhS-}#p9{MYE~7}PPJF_ zQ~&0IZoPdtTUkJbnxbZ~3A5gtBUn{lrrp##D>QiJQ*0JK@bO&Q;n7Fb!#?Brjz(W% zW#QN4v=rv(^(9Z8M%Bq_2JtuUQba;|-EZ9OZ&jM$LWJO;Sy(wYl|GApmuYrB>AuH$ zS^rh9FSW!C1fnTlo&djfk5e}RyE=eb4C1>ooucHm4Dt!BPiZ@gRl-lh0r-zz2YFaS zer#@+9b84Jtk{fAJVpj$O_#duWnNz4$DlRqUEL1hv?_Rg5!(r>NRbG)f-A|Dkz*oH z>sPlPgx$0F9W4A~cB}DkxAflV?O_I6$r(G}gZ!~d0fnufmcrg$yOEY&!f+$=K>ctI$Co9HEcuuPcx=S5L^mey-y5NInV} zs`~EpQ(Gy`;@uc5*z+5#qxImH-yk@^o$Z{9+P#hD)W)7yTC8$DB)~8|j*Bo>TIXi* ztE}b9yKIf&$gSL4oWXG1(fBQ^(~bcC;8??Q=3(2}%THWdJV$5i>5(YR6xIe2s>XEN zgw?F0D~pokz!HHWtOpQaNyQ^NJ?mE(9D%EpHT~1QK?b7~cauQUlW1p6 zJQ2aB-e5$0g4XgW`X=y31AVi7ci3BpN9d21tn1a)7f-5Uw{7QEMIWU`?h*_^oq_B| zgN#48YfknBJ=Lbwc~pC;*K-zo|1z12T!o*5tc|jLv0lGYkv3>NZT%cXkozNBEmW~p&-bEk;}a#{;$T9~ z?_rC(?ranXezw~d{o`(*$62*hbuMB+)-8>#}DTBkP zx^fK{jMZ=|e|;EK=L5}C_0EG*9u(Fgd*D`f6}DrULSqV}v)^P9xWcPxqqyjns5Zd` zP(rfIq=dp49Bw@tY=|UNiB7+Xinv|(A*AF=7hHEg0`h`IQ9N6f8_7_^hXA_?rMzO% zVgugRXK<*_VWm<*RQa43$r`f<9zRa=()p|Uf{e^v&0|G|L)R?7UsNpir3P=J!f`U%flQcH#i?Immb`BjW?K&r=obb!0J9lh$ zrG00(#tMq^9ixE$ZY;txxt_iz?Ye51#E0#>B`TLpIdUxfkwJ)IG?0l_0zW~<)9r^> zmuonI3d4#A8*)UkcNs>DWU<6b1|um#%&#r|cg5q`<?2(5r^feWsnql1d_;Jmf~X z3Di|_*|bPle$eOCr79ye72V)bs$i z96`d0_i_x095DIamX1vCgy(coZa-LtXTCEEA{efDDR4o_e!i)`&v>G)l@5sMYtctG zkgFC_jA=NYt|g}^*+axG8y`}>B9~pYB9_~OYiD(|nKPE og2xzS`l)8Gq2X$52k~mmN*==tKF(Px+s-Uk*nU|$N&}XybLbHMJT!yxVHb2|LNbA; zn+hMmQS#MzX5--om%!(#V0)#!`7mZjqE=|z@@COAdm|=8G5gIZePPdRi3|lt@*x0k zv3cvM>A3BTrs@Ji>J`vYd|h=}U#{#T9|@J(V)>A&L@p0;9NFybFF=G_`7Nn|M*VH* z+H)`uePBq?_^L+}SXDSs)z?A;J=xPqeUQtftTpH@%-%ujuW21GlE$*kos(iP6L?3W0j7+4+=8)?uN})TaOhA?FGb@Yf1nXllDt-@BGw)uu&- zSt&F1@%H#gf22XV-QDQ}x+CmHkP}GV8lu{`*`$o&H~n?HbNQ0)W2Wul%2F7Mx_0wf zr~>jEtJzd3dFm)`e$%fnH7vppw<=U;p9%%hLd2i|Uq{P@iTDIIT3XtLExDOVl>wA||{K%-E>H{M1NYtPAY+hxSd*E*yZ!{2lgN*py&z9_JHtac)=ItwhFkxkFjc6 zW6>CFIn$xvx5#BQ=X)rh9ZRHurN8U_{(MEY`TLm{7U2?LXx?VOK1n#BvIaBO{FKfC zctUN_I*85!`ig>LtY1<_1-8u-DtOqYE3-!6Y5%m|B;hO5PBC^+bYu|g=i$^4^fz&RhS$E=l6PrQTJ4-=PkU|>GEfXN- zHC{R4jNgpyj}GhlPl5*Pyb!Gw>xkqKeoJ3z5y4m?RM-z*8`f>T87uLTW z_6WQ{8AFt-C<3(si2*Cbd%boMWXN?-HXCYV<@lO*qvSL&@M~qJ>l)NfhzOUNL9;Qz zSFG^J3I*Cc=SO7i zrF@T4v_>YIZ&D4XB|eGa0JJ3ZLoRzWy9@G^@k+2*O`F}16V^0k15io_pZUC+`ox0d z>fAo%2$jM){UPRge^HNy5vCD*xrpXUt$I)J;k|xLcfQ1#-#)i<<0wV4*9vJcGF_Sk z(e@|CsTVK)o2{R@{ndV&tUOEg*zVrXX&5OVWhhK5RN=8+nB{dGMZPq(acLth6JI7k zAUo@o$*8~W#HMYcYAn^#c?6$wNZ_)fE?11>tB;rKu^8ipv&N#ed=y*UJU**5j6JpK zI%XV+lO7P@hmtYzynu|Y`NT0vW!2d#10!PhgVS;Q7tI@;F?AA4Jy(G|EI5KySZ2z2SnpcZ(gj8%?2gO^-3PcwYc;dT=!xFnLez%r$oy zK4l1r;S0Pzt(Q0LrYYKDEcfP}(rIQsZBxFE$%O$*P(%nr885kn&oMm@z}!BY$-4?_ zpmMtYL1R>|?T2u@W+~(^9(jVq{A%}fl#f)RElSO-hg!1SXf9R17g2(Vo!DTzYG1oQ zsymNmI#6e`9DBwp`?A{9R{G)qCT6nm=D#8Jd!B!OGlTaE zakM#wK3>UUpsycQIuezdC+jq4E3}Qr@8lXJ*hyORHM~CMeObv0puxoH@ZRvAfK~MM z^Iq$U(y=A(BO3~V=Em+Qt{~#IL#UA-mmksfNe0^3kt#hY)!ij+#nm)8PPbe0+XEKi zIb-s`8d)2sk_gV}$Xb_!qHuwd&Sjt_0BHz74{{n%)EI?6Hs$VG)R@R{Gur}&l}Sge z7I9oV#v?1ytVr1~L45Ir55g_4$A9&5$nCGpqX_ErIE znZx+R*QqMQ;CbEbr|apCY!>6Nrm&VHTkk7c=XL_OZ3WZkFj`^_m`Q(SdM>3Dk2t`R z$|bJNe6xq@?WlQ8zL!Nd({BIv_R{B}>Jln7WT768FPP%8lSuS%Gj)JR3K>jP`u3Xv zPGn8xK2L0k*)K9OUy9K2@gvOu__Q*cR8EWXD_EqS@gAvj?ZU&heV_IhvMy+5=55Sg zeVpgsLae`8LN&@s2`soh6g@hsDAnaKq2idYed&QJTC!}Ni9F9)c`WTt8;`rTLS*mE z5cwz8m2H_#TTrNxO*Bb|3jruJn-BaGB{vC}?vbGcpAWVG7Q?T*h7K=)d%9UE=mB^w zyUV07wQF+9eTTZ@0pz&>FbL4fFGYADa2%afl1Donyms3s+T(E3$)MAV){LY>+{}Kt z9uTq$Zfa_BS#^^0Jw(j_@=I~}-QStK^G|s-DDu9Z9I(@pktx&s7Fu1lQHs(yebN#W z404+-fkuyFgbA`|0h6^`wrS``80A*ZjEk20MtwuZvA2D}Ws&cTb|SE(wS8r!-cpH> zTcGd??Z_!jVs|a}Qu$3|-+P*;(SM(?l(Cp}tK>*9(m=T7Ql!*eixE>pyl2u;%R0YL zBA*9uCswWC4b5n3Y+Y3W!`l~v)>F}H4=^yuZD;^mB$3+~AaA54S6Dnnl@T9Jn%f;V0Z|^p63*=6KkMEbW(xa z0(Xq$u&l4|yUpsR=m1)757OAMp#!t`ggmr`V$fnj&?HGhXKQVvNz5D6yOeA`fK?>Y zqb$I-9Ah5tB!){w07P&=qbnb|OG!Qx5pdf_jPAn2_eo4NuNl&;IL){DEhB65!oPM0 znMZQ>g}WhRbK8s!eI5)!gpN@gJN zI3Hl3<93+z8E{a^u#bj8%Q>EDAM5zj7S}XM0!904Z(dlcQHM~qpNB~704QVGwx>q2 zm5z>eGBuIL?)ZP66J;@c6p7|(y&Cs`W4loK$&=`EIyVsZM3nQLU%oyaeTYh_q&{?@ zx6YvJxZ)TsdDi@X)|@_Lq}#2RqSsHilPe2zJDXw_k#|IOl}4wU#8w%$&xwsy)nGlof#4;G+)N8qRe>^nWCkC9-Ff zVZo6i#c={W0gY@rGb!hZ&MclnB*v#=LNNf-CVNziJYejii9v940ZN7Z9@U|eb@ zlOHp~#r)vJ*m8zKKc7ZFp7{_d&gwS_${x!9=Whx@7r*oKdAaJNVV#%EHVZ%ya1>Pb zbj;+%H8dG2ElkZ@w0|!x79~1{-UM{*eqv#$IH6kn@6Yw2BdA!Qin`xkoN`&g z7}VZM-!%OD1Tg}?LaJ!0Fh@Uib#=JFg@r->H%ymVo@MHPm$j1;k~Azr=<;h(D`P+= zOx1Y=T1eGSo8k@S|NQM}A*)h}57>Un<~1n1e(Lh_ots;mTb6SPgaZ*c(h=dV9b zga=O)jQVMG6z-Q~y1@c`Z;dIUFe(N{VoHj#`3JU`e+w2s47rV(17{u}R6KeRm?>m* z;nvjj#7WG|%)n62^3{y)?|OqogCm53Bi=^6VxB5wp~Q@WLgO55UE!mek^B-GrCKX# zEP#R|^-lrl;E4QCMWkUAl!wr0-r+<+#hUNzW(|Wt1Nj;SHu#HZJ)7LKWdAf3O*q6R zEPMc}2r_XPjpahzx9)iX7Z%E3^ZtQ>f|+tJo@lkxCWkD%C3hfX`QIiNav~Q}M(_?c zF~xQ=+m_#99`iA^FNKd18=8_uvj_d z@>v|$Ac+~Tn#?(gG4y0&;+>`6;0IwP`IzjKgn%-P$ibFjK^TpHp6LsBMFQc{x%H++~wFCEtc9Tkgj#pj4+e1>`9%QJD_w*D0 zjKlZvy}#yUKHCy5bJ4%Y^0`Qh?NbPaXGcdjn8qP@K6N!&f0_QOi4aZD5?};eO6-Y5 z|KIrrO_HceX&?akgw*jOj~;h&^znL^-VK*CQMDnbTq1|KAxFJf_wT;#2LVTRdqnD_ zPD6xTv;s|VgOtjQeBX!Y-@P-F{O?`mSK;hd?3^?ecghRmAP;R+ zPETgd{&^w^Di~OOdR{QizyEtqzUj}3l-wYW{_l!ZNr{RMW}Sg9A@;kwy91x_{>qnbzK#O2>c7)K8JsMs z822vMnqR4wElmKimJ$bh*@UVFI4c4czzIS^%W2l>;sXBd(jQ-gtMqKl4<7)8NILCW zy~czd5TLz@_IdIFkW>x~91dwwnM=3n{83T~Yf_`!XlLr@cn89MGKBoO#NN8(&DAhg-)M=BJR1YG9Bc(z4>0`WK>SG(UJD3t*k zC!A}pwAnz|7z4f+^)w;v&r~YJP9)Dtb2z7vOVIN2;7(1gGjd;HSuRZRasV*-zBX3k zl(I=D$s0qH?26_hLt>$$ua>BFz##4hz>CR{+Cdo(=or%gY?zB;6>KZI`BH3SNr0r{ z$Ii^bk@N~MOj%6%`Gfox!|ktpuOFX8-ERg<;T}1_m!@u!0}g%F-)_I7^lG zKq!1njShR+uSdG}ikF|L3omI%Q6Fz`2fL#P`0WA5VnCAOq5#@J-h~H`hLUo=SaaTC zW-5t3-4yh)WGM-7s2@gjz2|{M89)Q$oI3^{P?l!n=5G4&gDGaX_^%!={|Wx-;^pz= zu<}Qx-B!6a<<;esqLOAoUe%e^oKw%l&lY3?&y5;T@jgqB#gd9BQGZ{b)7cuL9WF;H zuk$D=Dv&h>B$;o$fdvO*$jI~y`t|mTDe1qyw3V}?;PZ4Y-^3yOH4sVSh0XwJU4nh) z_o?$G)A{_b2L%NTcSW2fy02IbYdqz)x(+v87hCIT>_-bj@v%e2cmOmswekabGK9{f zC#Vh(Yh*q;o3|C>{w}YU_~rNUSGiGp6}PIRNJJ}@)UsXbKSOplqH_UpGup|k$!d{s z&1+sUIN_Mv^RCM0#o=bI%w+b<#YIoEbD0S=!;pP(5KNV=ZZzg72m~5l@&sFL{1k=7 zWiwl7IO_yhPMhnqzGpXpJ3GopCO}pkGhl2N*r^OJT?1afC#&fvy#P^p8Q1o@SI%m! z^`HhMV6VzVe!KqqJTub_usnS(`mkg(Y3?KAl9D*|IxCU!c~C9z(a}YJj{vX?pfk{9 zG}PTKa>hSFThZDK2%rLqXOBm^uOIOvrHt2!MS~2{Bcr1YalHW9NkFrj=i6pu1$PXE z$@%Y}fU>PgbRy{fzM!VY1(50qs~XR^fc9)`2iTKLo_EH8xO1^?2l4mdmj-}wgX#tXg6ExNn^VXHe0L8= z6?cb`_9dd={E1UY4s{|tK~XefGIj#>@0%Hw0d zyB!~ybmx)5*xmOVbUIE3Ik^=$Ob|a8b7j&WsHp)%CbB}~lX`1i6C-Ku<{5&QQ61;x zq%6BHI#w!jn(ZsxS{>Kduc=&<31me8 z?fOwmBGZNqRYe$Rk}7JkLI?&{2mHerl6blg#t);yCoF@oImSyW>Jx}n_V-EI-WUzMXC_6rL54GwdrE)7WnTup+Nt z9x3zk-81e-5n-n5t$A#B&--y1&lajy1(NO~2HWpTM#&75*7#J!nU*-ie@ip48rD|qr7F5#Vw|95Za=p&l z*0)Z%C?R^5Z957~K>~B+WCAXcw?BkM0qU_6?aR`l>Ys=^aCE)z+?ueMs{evMze@m9 zZA8+a2)gz7dEITO5I_;;0xm@D_cEwrJ2h zJ~F;7 zlK3{u^%yd9mHN5m+AVwA+j^?oht~E}AlYtCPxI30wEDs?7x=w*zn&z-RjBiMZO@a!V!>qaqNc8k zkBgJG1*R{4x2i{&Mu0~no5BS9#04ZDd|wjqe)`BEg*hUvS8X!(NzM%pBD1kH4$%4` zE|SaOn)~&IRf)@bNm+6fw?k2h%b?fn=|k#Mcc4RAy)=r}Q|P(DQ2vUe*(oErsx2Uv zvwOkhB%)rI+IcYT7BJL*qDz6bi({y&-QQ0s z*Y*Ikt%C|i(mDkGdYup=s>-FzwT7!uH8&S+aW#UdC@<4E5pcDeK3#4 zuT?sPGkJ2|ukZ9;p1NyHi$o(v+6)J99OSOvBCTa`v%VS}!Ec@&c%15!E<4_Z&+G7d z6CbQ?ajxCv;@a3PG0Kd+t+SN-$n-m$TuN5wJnNdBTyUp=)A+s#=a{^G*DTIMxDNwc zM=GL%;cc8AY~lXH^P>kid6Byhaxx;YC_0j_9{ED1_j z4Jc*+3|E1M?X8)j?4L>!QLPyz>Im5$ry$kfo5R_b(`MZJc<8N)_6NBr`YHyQba3Bo z`z;j-izel`!B*M`F zjJZ@iw!aNAkTsme!aJgK)n&8V(J`Qg!x)IA`#*yzr1b`z=MHD7KD}m{bTn;6@qFs1(tJw_AoM~T$`()GF_)EW15y_3m&C_19w z&|G(|1k?$J+HcHhG@CxERp{6>J#3f(0vtZNwPtGotKozk5(J2N8TKnrCn0M~knQ%D zBNzE=ALd4{aVGM*v=2^WYLYGmN;PtL-|v_@Z;=>oaGFze+Cn)ulx_4!q;~exz7kN# zdG`UA`Qif-)yXn~xf0P;X#wvhoFbEdF$JhB@7-Svobk>QW2A9d>wAASF`}!U`Dvb# z+Vlc!16*%c8wBsS{iUjnkZAt1CyDFyGaPtXx2#y?hvDV0jViMlMwg>|02cep-~Rhe zcMIx!OI2WE1T@cJ*^GsDpVwZ&XLAJ;3QS>e>0Y_^6aQX81TCT8_;WhLTf9!>h_ydr7_^sYx8q>HZi}y6K z(F2EB8`F23n5KiQRz>q_yWq2UzrpKtJ(SJyY-PlQZC=S=s}eElo#)Vdqs`YfFHT}2 z@b1T}bGYruveO%E)|azz#$(=Yv${P2`g+)(L~R`5^Ji3xa#AIl1}a@lZr9sGGa3XK zepx*b=GG*+TvgO*@Ol)rtpuqU9_#r})1SgC>6R$n@+(nCc9sPnQ>pQm3s9=rq2Ur& z$V%x$LN3Rrwh)K0O0Faoi}^r6#Dp>X6&?qdW{+7U{;I z#dmdwF-N~VTtJNPKFk7HM_SA77GE(;&rVdT`=zd1WP2l9-LT;Y+KJ-sPKI5;3+ zCChPm^-fmRGT2*{LftYo=MjeCfn_02YPO!t;c_gYgYb$}Ox^iewv@I37#&PJm!ku| z!X=>zIDD=PcNg;-1&@uYsz3jOkq?Ft;hFxZ~HE3 z99~bDPusDOuA=>bT)${MZA0n(9Hv-r_96|r)uJcua+kgsuo*Uv)z$N<(AGGzTvih? zc_7B?z2T^|4PnLZ{=jR{6J!pHf+@wk0vUNlNFhESWc8(>prD3$t=62C5AMP*Jo1K1 z`pzeld+RwN{lR2;o+l_u#4!uLm^`P?CmUP>I83}M-H*H2T*kGkvQPD z;m`0SL1lrY`yPOCCEie_AhnG^jp9*nZ3%Whzzpv2dA=K%7rcNL=Y6DtE~*Tben~@K zK*8bY#hS3#15Gm{j`9 zYtEBNU&m$Dn5qb?-Qe}O%kQxtmKIP` zxjLF(19XnFSkiD-)-vzIyo7Db+=;30n^7UL>Rx)53Kgu+J5!N zrmRE=m8#G-iNeYWe5zhRMYOUFiM$FH zd@B0JEJmUyx76gotJwyNjJML_!pU;&(%~^TFC?6Z_2C2K@Vrf(rL8Kh^iQKH=Q2Z# z)5hO13gW&m5=8+eK!u!#UZ6vP)aX_Y4l{ce(uK|aB%p-W=0cnIy(X<#xmY|y-m5hLH0=s zy4qnhD-w?garO)G8_)ydk3M(j`f9zhpid<@kR97m1e`V^fF>aKb?Tt*INiokHo`Xk z^HFEZH=A`P*IHAqmFHWkN6PU7bO`+5d!>=%9`%G?xeVD_! z#o%5|TeMXJTa^YX*~R(rn!DXHO;a)As!^&>wC@9@!xo56kO0?-+7~>40eFKNqL0%T zAu~>fY*aFz%(HD`_x7UMDeHLA3UXQLEwI7vg06dq!`AC0nl#D?mi8Op^N+uXs3t4n zuqYLU1%35#CFJqfG&JCgr2{P7wrA+sTlT&^z{_4QyslDs{Qc=#ec^^vo0@xWn zA4jK4g=ipa?K%Kv5+?;$i@4y^Rao>=el)p7$e`B#A2>K~I;L+}fj+>(_N9;eM<5Y~ zsWAcfQ7y*!jI*kI=wItYB{Uaj-+Rxta1}vC_m8u67?EsB9S+j~p>27N2K#=cKVc+#nOxf?1KP^~!Z{7@I$h+jn$|b+ zmQl~VSvvL$ z3(s5qvGV7Kes8#60t}`k1gvr zp!=gl+Ol^c(K?z|SbD(^;dyJYW%@IokLjDeLu4y%TNeW!wHFz~mO8y(Ur#oIx!Y5F zGP4`6WLvbSU!fUJW|>wEPM7B$(y%KMX{FFYwtXnBKF7jT@h%O9$z-wY7=i<-i6@{x z-Hmawa`A98F#ObR0Rw`BlrIS%LIIrjN;G>~(x!34r2VF%4g9uPAFmo2s=k3_89DfX z*c8AICP9L)MpwI|Pft)}h-e(|ww>atvp1lcdQ$kh%J^ zt0kg!dV-@_LY?xZ?+1DI18o+cx8L#0>I)0M>`Mq{vzk&UaHa5lv6u#6k`YEi+o@a6 zt1-vNuk6OK9|yyR)lKKiPh5@cIXkX0)4AhumT4B5$5>I9ils6^-(eh>Xp~M)TL@DG zo}~!hD~3C)Iky0GU3bILsc_6O<Fc6B&%ZnnjYF$*n(v7Lcr1YpyHe2AHjD?HX-7 z)@jDVPc)=k7wI-E!KAvpX7btKlOcJT??*Oe8b9gog>1S5a?qc&bj5085FYDu?##4^ zW$>p6;}Vv?X4l*-L~|TeSD|^|9q9r<5?l>Awq4p>iRoA7!SP6!+#0u!NddV+y<_8e zRKY|&siT7IU{CHle z-UIiv$t*?h2C9|#OCRbpLyZ2Oq1inZgNxmfp)0jS~SGL>ld8O&kRBd};r zk5f{NT>ctbyzs@Se&4}$64vRvT$b&3n^!4~8EyLVKtEFxy!$OUJ_t{Chilt94Bzc6 zxdSu79e+u$fBAar14?Cek_M@NDI*rqbSh%a;JK**A^?GgEo~O>838Q%%wgJCfG+VT z&3^&`^3dn!Emv|r?$?B`oy#EV$_2RH<9OUG&r6iE_M;nZ@GZ5H_rox)2eMm6S1DHa zw<$!%yEu1nS_uHTHoH`)h$M`DzY&NgCzVh8@^aC33)BiXsiODvv>dNCvHzxgYT{7p z<_Wjj(mDA#F55L(g@7mX?NplX_aj#l`w%?bqF#oWUlZ-I8c{V}QM1J=xE$D^Y|528 zh%cxkRSxsza6Dh6EXB(uv@T*K2cnY$7F*^x16{@KMWj7Ft!!)vXp*cg1rx{eh9T7t z*`Ad3f~cvT5D*dV;GI_IQ1oZLgIJU8$jnw6%|%2=3eHev`YxjLI22(1#N|TNp^D~p zR2VGfBEl_K8=0Gm;?dv71O>}w5aoZo`uRHkO|kb^FfNIPH2?_7riZ-lcIj9z7AmCI zvgH`bZtt>ej=zEZe$rLwSM_@Hf*#C02;*fk^dJR9ely zL2G4PAhtcbt7<{~*T&}0r@R1kw@vu{^X>Yswm`TNof4>EuxOatEJf^`gB=YCW zP4cD@9OeIpSV_V=7ttw6EW38vmL%V5^qlz;w*u)qcPfq?q? zH-iKzMgnT#pMaqI-CwgD@JW-=ncBt^T`L_!`{(hgr%5>fg!7?Aejg9Tn}SbJe&ru> z!TTcnj$ek+#tM~k)gS&9Tl>Qo2 zyNN<1wh5TkQY$1f)RBIMlIp+p7Ay5z zxgWv27s6KXM<<5f&Se>epL#prZ2I3#BSa02%D-gE5U4OYewn8jJW8KGb6@oR@2>&6 zDkEgQ4Cr`0J7!Iw{+q@$fzPoh9UVX|Di z5qL!waPt=PnSJZ&uSy{s^% z`)nK>b9I&&|5h2m7bk`!U5kiu$ka)NHV_sT$n5VMm@lOk6jN*cpL_Y8llWSRwlY(a zZfjAhQTVw6azD-gXMJ5=UOqlWZ(~~#fvdoj=*n=jt-|?`;*%QRH9kxe{fhmce!Aas zC{`J^%jdZE}BBWzxOe zKuyg|(^7MvMp=|TtN;NGBNQkc*j6<0{zJ*-VkuSU4y~BLq7?h{N=M9LRwFw*Ju^K$ zH8yLd>T{#(@E~^{_o+DXO%6Jr48Dlfxf&YSow^%PvAultVk0ES zF~+m(X+&!rhq{7CqhHzKP4F-=(C`>dUV1xZp3>y8kVgnD{-mTMXg9 z1sqcralEY+_0+HbdRkAwmYL;ENyf8h`A&`#15%Nldw}!D{gQ3JG$->f$~AL!3OS_z z;rHTMh?EXo8Nw9O?z1XJrz5SdQ&-ZuYZJCuzzhYpK2(79 z_{5U!Tf-1y91XyVnPEZ*l3t}wppeSl+_j+y^OzJA8YLK1Lg9;p1R6b*KKy6yee*Cp TWM}4D1|aZs^>bP0l+XkKi8@46 literal 0 HcmV?d00001 diff --git a/docs/docs/how-tos/assets/autogen-output.png b/docs/docs/how-tos/assets/autogen-output.png new file mode 100644 index 0000000000000000000000000000000000000000..02106782e87441467253e6f9c4b62a7e407c562e GIT binary patch literal 5919 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 literal 0 HcmV?d00001 diff --git a/docs/docs/how-tos/autogen-integration.ipynb b/docs/docs/how-tos/autogen-integration.ipynb deleted file mode 100644 index 5e58a260c..000000000 --- a/docs/docs/how-tos/autogen-integration.ipynb +++ /dev/null @@ -1,406 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "100c0c81-6a9f-4ba1-b1a8-42aae82b7172", - "metadata": {}, - "source": [ - "# How to integrate LangGraph with AutoGen, CrewAI, and other frameworks\n", - "\n", - "LangGraph is a framework for building agentic and multi-agent applications. LangGraph can be easily integrated with other agent frameworks. \n", - "\n", - "The primary reasons you might want to integrate LangGraph with other agent frameworks:\n", - "\n", - "- create [multi-agent systems](../../concepts/multi_agent) where individual agents are built with different frameworks\n", - "- leverage LangGraph to add features like [persistence](../../concepts/persistence), [streaming](../../concepts/streaming), [short and long-term memory](../../concepts/memory) and more\n", - "\n", - "The simplest way to integrate agents from other frameworks is by calling those agents inside a LangGraph [node](../../concepts/low_level/#nodes):\n", - "\n", - "```python\n", - "from langgraph.graph import StateGraph, MessagesState, START\n", - "\n", - "autogen_agent = autogen.AssistantAgent(name=\"assistant\", ...)\n", - "user_proxy = autogen.UserProxyAgent(name=\"user_proxy\", ...)\n", - "\n", - "def call_autogen_agent(state: MessagesState):\n", - " response = user_proxy.initiate_chat(\n", - " autogen_agent,\n", - " message=state[\"messages\"][-1],\n", - " ...\n", - " )\n", - " ...\n", - "\n", - "graph = (\n", - " StateGraph(MessagesState)\n", - " .add_node(call_autogen_agent)\n", - " .add_edge(START, \"call_autogen_agent\")\n", - " .compile()\n", - ")\n", - "\n", - "graph.invoke({\n", - " \"messages\": [\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"Find numbers between 10 and 30 in fibonacci sequence\",\n", - " }\n", - " ]\n", - "})\n", - "```\n", - "\n", - "In this guide we show how to build a LangGraph chatbot that integrates with AutoGen, but you can follow the same approach with other frameworks." - ] - }, - { - "cell_type": "markdown", - "id": "b189ceb2-132b-4c7b-81b4-c7b8b062f833", - "metadata": {}, - "source": [ - "## Setup" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "62417d3a-94f9-4a52-9962-12639d714966", - "metadata": {}, - "outputs": [], - "source": [ - "%pip install autogen langgraph" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "d46da41d-0a71-4654-aec8-9e6ad8765236", - "metadata": {}, - "outputs": [ - { - "name": "stdin", - "output_type": "stream", - "text": [ - "OPENAI_API_KEY: ········\n" - ] - } - ], - "source": [ - "import getpass\n", - "import os\n", - "\n", - "\n", - "def _set_env(var: str):\n", - " if not os.environ.get(var):\n", - " os.environ[var] = getpass.getpass(f\"{var}: \")\n", - "\n", - "\n", - "_set_env(\"OPENAI_API_KEY\")" - ] - }, - { - "cell_type": "markdown", - "id": "1926bbc3-6b06-41e0-9604-860a2bbf8fa3", - "metadata": {}, - "source": [ - "## Define AutoGen agent\n", - "\n", - "Here we define our AutoGen agent. Adapted from official tutorial [here](https://github.com/microsoft/autogen/blob/0.2/notebook/agentchat_web_info.ipynb)." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "524de117-ff09-4b26-bfe8-a9f85a46ffd5", - "metadata": {}, - "outputs": [], - "source": [ - "import autogen\n", - "import os\n", - "\n", - "config_list = [{\"model\": \"gpt-4o\", \"api_key\": os.environ[\"OPENAI_API_KEY\"]}]\n", - "\n", - "llm_config = {\n", - " \"timeout\": 600,\n", - " \"cache_seed\": 42,\n", - " \"config_list\": config_list,\n", - " \"temperature\": 0,\n", - "}\n", - "\n", - "autogen_agent = autogen.AssistantAgent(\n", - " name=\"assistant\",\n", - " llm_config=llm_config,\n", - ")\n", - "\n", - "user_proxy = autogen.UserProxyAgent(\n", - " name=\"user_proxy\",\n", - " human_input_mode=\"NEVER\",\n", - " max_consecutive_auto_reply=10,\n", - " is_termination_msg=lambda x: x.get(\"content\", \"\").rstrip().endswith(\"TERMINATE\"),\n", - " code_execution_config={\n", - " \"work_dir\": \"web\",\n", - " \"use_docker\": False,\n", - " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", - " llm_config=llm_config,\n", - " system_message=\"Reply TERMINATE if the task has been solved at full satisfaction. Otherwise, reply CONTINUE, or the reason why the task is not solved yet.\",\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "8aa858e2-4acb-4f75-be20-b9ccbbcb5073", - "metadata": {}, - "source": [ - "---" - ] - }, - { - "cell_type": "markdown", - "id": "dcc478f5-4a35-43f8-bf59-9cb71289cd00", - "metadata": {}, - "source": [ - "## Create the graph\n", - "\n", - "We will now create a LangGraph chatbot graph that calls AutoGen agent." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "d129e4e1-3766-429a-b806-cde3d8bc0469", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain_core.messages import convert_to_openai_messages\n", - "from langgraph.graph import StateGraph, MessagesState, START\n", - "from langgraph.checkpoint.memory import MemorySaver\n", - "\n", - "\n", - "def call_autogen_agent(state: MessagesState):\n", - " # convert to openai-style messages\n", - " messages = convert_to_openai_messages(state[\"messages\"])\n", - " response = user_proxy.initiate_chat(\n", - " autogen_agent,\n", - " message=messages[-1],\n", - " # pass previous message history as context\n", - " carryover=messages[:-1],\n", - " )\n", - " # get the final response from the agent\n", - " content = response.chat_history[-1][\"content\"]\n", - " return {\"messages\": {\"role\": \"assistant\", \"content\": content}}\n", - "\n", - "\n", - "# add short-term memory for storing conversation history\n", - "checkpointer = MemorySaver()\n", - "\n", - "builder = StateGraph(MessagesState)\n", - "builder.add_node(call_autogen_agent)\n", - "builder.add_edge(START, \"call_autogen_agent\")\n", - "graph = builder.compile(checkpointer=checkpointer)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "c761fc05-e8b6-4905-a793-eb7522d20060", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAALQAAACGCAIAAAD7HTfDAAAAAXNSR0IArs4c6QAAFtlJREFUeJztnXlcU1fax09yb26Wmx3CIrugKJsioIziXqnFpfpW1LrNdLSdmXfajtPOp/Wt2vHtfPrO286nfW2ltrYW7K51Q1GLG3VBxCAIsoiyyb6FhOzrzX3/iEMoTcIiIZf2fP8iN2d5LvnlOc89zzknNJIkAQTiCLqnDYBQFygOiFOgOCBOgeKAOAWKA+IUKA6IU1BPGzA8OpsMOhWhU1ssZtKot3ranCHBZNMZGJ3DRzg8xCeI5WlzhsH4EEdNqbq+XNtQoQ2J4hBmksNDxb4YGCcTNFYLaG/T61QExqY3V+tCY/CJsfjEGK6n7RocGsUnwe5JVQU5PUGR7NCpeFgMzmCO73FQryUeVmhb63Rt9YbZK7wjplFaItQVh1JmvvBVh8gXm73Ci8MbHx5u6Chl5oIcmcVMpm72ZbIRT5vjGIqKo+6u5sZp2co/TBBKME/b4ka6WwwnP2pbts0/IJztaVscQEVxtNbqy671pv3e39OGjBEn9rXMXyPx8md62pCBUE4cFTeUD+9pl2+b4GlDxpTj+1riFwgnxlIrBKFWfNfeoK++rf61KQMA8MxLgfnZMmWP2dOG/AQKicNksEpz5Wv+EuhpQzzDhh3BeUe6PG3FT6CQOPKzZRHx1PKrYwnKoAdGsAvP9XjaEDtUEUdvt6m1Th+dLPC0IZ4kKVVcdrXXZKTKzC9VxHE3XzlvtbenrfA889Mld35UeNqKR1BGHNeVwVM4Y9OXRqOprq72VHXXBE3iVN5Uuanx4UIJcTys0oZM4dDotLHpbv369adOnfJUddfgAhTno13NBje1PywoIY7WOv2kMQxFTSbTyCra5oRGXH2ITE7gNj/QubWLIUIJcXQ1GblCt2RPDh06lJaWlpKSsnXrVqlUCgBYvny5XC4/evRoYmLi8uXLbcVOnz69adOm5OTkRYsW7dy5U6F4NOq/8847qamp165dW716dWJiYlFRkcPqowvOR2Wt7tXfEKFEQkursuD80bdEKpVmZGQsXbp09uzZBQUFOp0OAPDuu++++OKLCQkJGzduxLBHiZvy8vLQ0NC0tDS5XH748GGtVrt3717bWxqNZv/+/Tt27NDr9UlJSQ6rjy44H9WpCHe0PFyoIQ6lBReMviVtbW0AgLVr18bFxaWlpdkuRkVFoSjq7e09ffr0vpJvvPEGjfYo4kFRNDMz02g0MplM2yCya9eumJgYF9VHFw4f0aosbmp8WFBiWMHYdLobDElJSeHz+bt3787Pz3dd0mw2f/nll+vXr1+wYEF2drbVau0bWVgsVp8yxgYEBQxsjGJz11BCHAhC07rBkXp7e2dmZoaEhGzfvn3r1q1dXY4np0mS3L59e2Zm5sqVKzMyMmw+xmp9NBPF4YzRA3YfWiWBMCjxuVDCCJyPusmRhoaGfvjhhx9//HFtbe2ePXv6rvfPRZeUlEil0h07dmzYsCEmJiYiImLQZt2aytaqCJxPieU/lBCHbwjToHFLCGZ77ExKSpo7d27fzBWbzZbJZH1lent7AQBTpkzp/7LPc/ycAdVH32Y9IQmgxNoOSgSkPkGsmlLNxLhRnuqorKx8/fXX165dy+FwCgoKoqKibNfj4+Nzc3MPHTrE5/Pj4uJiY2MxDMvIyFi9enVNTU1WVhYAoLa2NjDQcX54QPWheJphcf+2ZuZS8ei2OTIo4TnCovGGSu2oN4thWFhYWFZWVkZGRnx8/O7du23XX3755cTExIMHD2ZlZTU3N/v4+Lz99tvV1dWvvfbarVu3Dhw4kJKScvjwYWfNDqg+ujabjNauZkNABCVWDVJlJdjl7zqjkvn+YZT4p3iQ+ruatnp9yiqJpw0BVBlWAABTZ/ELcnqeednpSp+9e/dmZ2c7qDh16r179xxWycrKCgsLG1UzB5Kfn79r1y6HbwUGBra0tPz8+sGDB12MRDdyela8QJXFs1TxHACAM5+1Rc8WhEXjDt/t7e21TXEOgEZzegs+Pj4o6l71GwwGuVzu8C1nhkkkEgaD4bBKZaGy86Fx0Xqf0TZzhFBIHD3txqIL8qW/pcr3Zuw5faD1iY2+HC5V3DklAlIbXv7M0Cj84jednjbEM5z6pHX6fBF1lEEtcQAApiTx2VzkRo4bZxGoyaVvO4MjOWO23GmIUGhY6ePu9V51r2XOil/LqsHLhztDp+Lh1Ns3Sy3PYSNurhBj0s9+3u5pQ9wOYSGPfdDiE8iioDIo6jls1Jdrrhztil8oil8o8rQtbuHWDz315doF6RLKzu5QVxwAAMJivXlWXl2kil8gDInCvSdQIuPwmHQ2GZof6IrOKxKeECUtEY3ZytkRQGlx2NBriLv5vfV3tSaDdVI8l0an4QKEL8asVqpbboNGA2q5WaO00AC4J1VzhWjENG7cPAFKjby8C8aBOPpQyc3t9Qa1wqxVEjQ6UCtGOcvf0tKCoqifn9/oNssToiQAXAHKEyMBERx3LIh0E+PGUAAAX8zgix3PLY4Ke/ce8fLyWrY53n1djC+o7tkgHgSKA+IUKA47fD6fzaboU6VHGE8xh7tRqVTO8qW/TqDnsINhmLtT/OMLKA47JpPJYqHEbiKKAMVhh81mu2mH4zgFisOOXq939w768QUUhx2hUDj2+9uoDIy/7PT29iIIJbaaUQToOSBOgeKww2Kx4DxHf6A47BgMBrOZWmcIexYoDjtMJhN6jv5AcdgxGo3Qc/QHigPiFCgOO1wul8UaTz/Q527gPIcdjUZjOyQOYgN6DohToDjs8Pl8HHe8x//XCRxW7MDFPgOAngPiFCgOOzArOwA4rNiBWdkBQM8BcQoUhx24NWEAcFixA59WBgA9B8QpUBx24L6VAUBx2IH7VgYAxWGHx+PBrGx/oBe1o1ar4aam/kDPAXEKFIcduB1yAFAcduB2yAFAcdiBibcBwIDUDky8DQB6DjsCgQCuBOsP9Bx2lEolnCHtD/QcdnAch6vP+zOeTjB2EytXriRJkiRJrVZLo9FwHCdJkkaj5eTkeNo0DwO9KPD19S0uLqbTHzlRlUoFAFi4cKGn7fI8cFgBW7ZsEYl+8qsdYrF4y5YtnrOIKkBxgLlz54aHh/e/Eh0dHRsb6zmLqAIUBwAAbN68mc/n2/4Wi8XPPfecpy2iBFAcwOY8IiMjbbF5dHR0XFycpy2iBFAcj3j22WcFAgF0G/0ZhacVg47QqQmdymI2juPH4kBxQmz4ExwOh0sPr6/QetqcEUKjAYxJ5/ARDg9hsh83FTDyeY6GCm1NqUbWZlL1mDE2wmAhKAshLeNXHr8EUAbNqCPMBsKkt3DF2IQwZsQ07oh/rnYk4ii+rHhwR2u10jliDs+HgzJgsoqKmI0WVZdOL9ehGBk9ixc7RzDcFoYnjvvF6qvHuoX+XEmEmEaj7s8aQvpDWIjuWoWuV794nSQkahiZxWGI4+rx7u5OIAwQoBh0FeMPk96sbFGGRDJmPikeYpWhiuNERitgsMTBwsezEOJhuuvkIjH5xAafoRQe0qPs2axOgLGhMn4BSMLFCgU973vZUAoPLo68I11mAhMHDTucgVATyUSRXEYW5soHLTmIOCpvKhVymjCAP3q2QTyPd5i46YGpvlztupgrcZBW8sfvu71Chxq/QMYR4hDxpe+6XZdxJY7r2TL/SKiMXyYohgj9uSV5ChdlnIpDp7Y01xi9QmCo8YtFEi6uvKUmrU4fV52K40GxGmWP/vavf+179qsjO21/a7W9f9s9q0B6fNR7sdHYXGE2G93UOGUhCKK+sXQoJWk0GsJg1JRqnBVwKo6aMh3uNY53+BSVnNn36VaTSe9pQ8aao6fePn76nSEW5og5taVOs4yOxWHUE73dJq54HB+QZbaM3Gd0y5pG1ZbhIZO3PM6q72E5S74Pp6VO5+xdxyn7njYTkz2kbL7JZLh0JbO04qJS2SUS+SdMe2rRvN9ZSeLij5+Xll/oVXbyed4J09NSFz7/OJvJpCU5BbeOtXfUMpmcyIjkp5e9wsVFAICMz17AMNYLv/3QVuxK/tdnzu/755vXSssvnsh5FwDw9/99EgCwbvXupBnLbQPNmfP7mlurMIwdHTl3xdK/cDh8AIBKLcs++96DOimKMCaFz7xbmbf9T1/4+4YDAAqkx6/e+Fap6hKLJsTHpS6Ys4nBYLa23c84+PzWzf937sL+to4HIqH/stQXY6bOG9ldWCzm3MsHSspyTSbdxND4lrbqJxb8fvbMZwAAtfXF5y7ub+t4wOOKI8ISn1ryJz7PGwCw6+3Fz6x4veLelar7N9gsbnLS6tSF2wAAh0+8VVZxCQDwt92zAABvvnbWVt4ZdISOoIiiyyTycRBCOFaATk0gQ0igEATx+devPGwqS0leN8FvUmdXQ3dPE4IggAA1ddKoyLle4oC29geXr2Zx2Lz5czYO2qAzGpsrJN4hM6Yt1WgU1wuPGIzarZvfd1F+yuTZ8+dsvHrjm62b3mexcG+vYABAR1f9gaw/+/mGr1u9W6NVnM/7VKHs+ONzHxEEkfn1qyp1z3+seE2lkv1waX94WIJNGRfyPrt649uU36zzlYR1yRqvXP9aJmt+ds0e2xf06yM7Vy17VST0P5/36bdHd+989RSOu5pEdnYXZ87vuyk9/tSSPwn4Pjm5H5jMhqQZKwAANXVFB7/aPmPaUynJ6VqdMv/mkU+y/rz9j19gGAsAcPjEf6cufH5ByuayissX8j4LnDA1KnLO4nm/61V2yhVtzz7zdwAAzhl8UpvBRHQqQuRoPt2ZOCwIY3DPUV6VV9dQnL5q56yElf2vIwjy8h8y+9K2PfLW8sorjyOONSt39LVGR9DLV7PMZiOD4XQDEo8r9hIHAACCA6P7PrDLV7JoNPrzWz5gs3kAAA6b/93xPXUNJXQ60tJWvXnd/0yLWQwA6JY1SktyzBaTTqe8fO3QxjX/iItZZGtBwPM+nvPO02mv2F6uWvbq9NglAIC0Jf+59+Pf1j28ExftakODw7ug09HC2ydnJj69IGUTAIAE5LdH33zYWDYpPCn77HvJiatXL/+brcrkiFn/+nDd/drC2KgFAICZM1Yunv87AMAEv8nS4lMPagujIudIvINxjlCtkYeFTB/i/xbFEK3K8WFXjhVAECTCHNxzVNfcZDCYidOX/fwttUZ+6crn92tv6fUqAACbxRuirQ6xEOb8m0dKynIVyg6MwSJJq0arEAn9htVI3cOSiImJNmUAACInJQMAmlvvCQU+AACbmAAA3l5BJGk1GXU1dVKCsHxz7M1vjr357zZIAIBS3WV7gTEexWQioT8AQKUeZE7J4V0gCMNiMXmLAx/1Lg4EAOj0KrmivbO7QSZvLryd3b+RXmXno96xR70jCCLg+yhVg/TuDJSFEk6WaDkWB5ONWPSDxzVqdQ+fJ/l5MKFS9+z9eAsT4yxd/AcvcUDupU+6HiPEI0ky8+tXmlvvpS7cFhIUW1515Ur+VyRpHW47BoPGNsbbYLMeRRvhYTMAAA2NZYETpgAAmloq+TwJjgtVahkAYOum923q6cNLHNjRWdf/CoowAABWKzGCu8A5QhaL29BUNn/OBlvvAAB/3wi1pgcAsGThtrion3gjnqMYgk5HXffuApPWxHJy8IRjcXB4CGEevDM2m2e7hwEUFp1Qa+QvvfK57cstFPo9jjjqHpbU1BVtSH9rRtyTAABZT3PfW4MuOCKB/Tsh4Pto9cq+lxqtHADAZnGDAqZOjph19kKGordDq1VUVl/bmP4PAACb/Sij5CMJHbHxg94FgiCL5m45d3H/N9/vFvB9CqTH5v5mvY8kpKu70RbZjKT34TzsECYC5zseJRw/yuJ8FGMPnrCNmJhoMunv3L1g74mwAAC0OiUXF/W5fa22F/z7Q2KgmG2gAQAgCMPmQl33otMqAQAB/pGPWtP1AgCsVisAAMeFarVdnXJFe9/fNp/f39mGBMfWN5SYTAbby7uVeQAA29i8Ku1ViVdwt6wRx0UvvXDQFnxMmphIo9Hyb33f14LxMWZNXNzFnFnpkyNmqbVyvUG9If2tp9P+CgCQeAcLBX5FJTl9nRKExWIZ/McrMYyt1vTYWh4KTBzhOBEHsmfPnp9fxfnojVMygR+XjrqSiK8krOp+/q3b2XqDWq3pKS7LPXvxo+TEVRaLqagkx2q1WizmH69/dbcqz2DQzp65BsNYTa1VdyvzDEZteFgChrGKy3Lr6m+zWLyggKlOrWfiBdLjvb0dTCZeXpl36UqmhTBHhCX6SEL1Bo205DSTyUFR7GbRyfzCIyRpfWL+cwiCYkx2gfR4Z1cDoNGamiuCAqb6SsKu3zxS31CCIIx7D27kXv5kYsj0JQu3Wa3EOx+kz0pYGR6WIBT4AEDDOUIGinE4Ar1eXVx6rqWt2mQ2Vj+48d2xPRETE/g8b7W6p/D2yfi4JyXewQAAgjDnXfsiclJySJDTfXIu7uKLw69zWLz4uFSxaAKCMBgMJpvFpdFoIqG/tPh0VfV1EpCNzeUnz7xHECZbF3nXvwycMCUyYpat8cKibBYLj49LBQAYDOo75RdUaplOrzKadK4jM4PapO7UJKU6zqA5FgcAoKfdpFaSbL6rIwkQBJ0Ws1ir6y2ruFR576pWp5wWvTgkOHaCXwRJkgXSY3cr87y8AtNXvdHQWGYy6SPCEoIDY3oUreVVV+YkpzNQLCQopqmlqqOjduZPn3f6w2Lhvj4Ti0rO3L5zhiAsG9LfUqq7GxrLkuKXTfCbZDYbC4pOSEtyhAKfyeGzGhpLbeLgsPkCgU9ZxaWq+/k6vSopfhnOEYSFTLtfe+tm0YmWturpMUvWrt7FYDDpdHpr+/3Couyyyst3K/NKyn4oLDoZNSWFi4siI5JZTE7V/fzS8guynuaoKfOip8xlYuwRiMPFXajVPYW3s++UXyiv+rG0/OKNW0dFQv8J/pN8JaGBAVH1D0uLS881tVT6+0ckTH/KNm/hQhx+vhE6verO3fP1D+/4SkKDAqJcfIKKVnVIJCNosuOYw+kywYdV2lsX1b6TJS6a/sVAEIQtrCZJskfe+t5HGxfM2fjk4hfGuHcAgE6nOvjVXxEE/fO2A2PQdXtl56J0sW+I46N5nU5mhEbh107IDBoTizsWpy+eu7jfYQYOZwv+65UTbu3abDZ+eOD3QoHvxNB4FMUaGkvNZoO/36QRNDWyuzh2+p/tHTVRkSk4LuqWNbZ31sxKWDWC3oeLpkePMkhnyhhkgXFDhbbgh96AmOFNJ4wMrU5pNDrIANFo9OHOZwwXs8V0o/D70vKLHV31KIr5+0akJK+1xaTDZWR3UVZxufD2yebWewRhFosCEqYtnTd7A4q6/cc9Govblm6R+AaPSBwAgNOftqN8PkcATwT/paHu0jIRfeomXxdlBnleXbbVr6Go3XUZyLjDYiba7slcK2NwcSAILf0vgY3FraNqG8TDNEhbN+4IHrTYkDY1KbpMpz7pCE0KGCXbIJ7k4e3WNS/5c4WDxzRD2tQk8sEWr/d+cL3JbBrhBD6EChi1pooLDSu2+Q5FGcPbK6tTW3K/6CQRDG5WGHcQFquiSc5AiJUv+NPoQ90BP+wjGIovK26e6QmK9WLx2Uwc/pYi1TGoTQaVvuOBYvZKr7iU4W1oHeHhLbcvKSoKVKQVCPy5NARBmQiDidJRGjyXwbOQABAmwmIkzEbCajYrO7QYix4zhxc/XzSE2gN5rBOM5Z2mpmpdV7NRrbBoVQRJkhYjPNnHk7C4qJWw4gKUJ0R8g5khUbjAa+TeHR5vDXEKPE0Q4hQoDohToDggToHigDgFigPiFCgOiFP+HySxlkwJXoZrAAAAAElFTkSuQmCC", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "from IPython.display import display, Image\n", - "\n", - "display(Image(graph.get_graph().draw_mermaid_png()))" - ] - }, - { - "cell_type": "markdown", - "id": "23d629c3-1d6b-40af-adf6-915e15657566", - "metadata": {}, - "source": [ - "## Run the graph\n", - "\n", - "We can now run the graph." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "a279b667-0f5d-4008-8d43-c806a3f379c4", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001B[33muser_proxy\u001B[0m (to assistant):\n", - "\n", - "Find numbers between 10 and 30 in fibonacci sequence\n", - "\n", - "--------------------------------------------------------------------------------\n", - "\u001B[33massistant\u001B[0m (to user_proxy):\n", - "\n", - "To find numbers between 10 and 30 in the Fibonacci sequence, we can generate the Fibonacci sequence and check which numbers fall within this range. Here's a plan:\n", - "\n", - "1. Generate Fibonacci numbers starting from 0.\n", - "2. Continue generating until the numbers exceed 30.\n", - "3. Collect and print the numbers that are between 10 and 30.\n", - "\n", - "Let's implement this in Python:\n", - "\n", - "```python\n", - "# filename: fibonacci_range.py\n", - "\n", - "def fibonacci_sequence():\n", - " a, b = 0, 1\n", - " while a <= 30:\n", - " if 10 <= a <= 30:\n", - " print(a)\n", - " a, b = b, a + b\n", - "\n", - "fibonacci_sequence()\n", - "```\n", - "\n", - "This script will print the Fibonacci numbers between 10 and 30. Please execute the code to see the result.\n", - "\n", - "--------------------------------------------------------------------------------\n", - "\u001B[31m\n", - ">>>>>>>> EXECUTING CODE BLOCK 0 (inferred language is python)...\u001B[0m\n", - "\u001B[33muser_proxy\u001B[0m (to assistant):\n", - "\n", - "exitcode: 0 (execution succeeded)\n", - "Code output: \n", - "13\n", - "21\n", - "\n", - "\n", - "--------------------------------------------------------------------------------\n", - "\u001B[33massistant\u001B[0m (to user_proxy):\n", - "\n", - "The Fibonacci numbers between 10 and 30 are 13 and 21. \n", - "\n", - "These numbers are part of the Fibonacci sequence, which is generated by adding the two preceding numbers to get the next number, starting from 0 and 1. \n", - "\n", - "The sequence goes: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...\n", - "\n", - "As you can see, 13 and 21 are the only numbers in this sequence that fall between 10 and 30.\n", - "\n", - "TERMINATE\n", - "\n", - "--------------------------------------------------------------------------------\n", - "{'call_autogen_agent': {'messages': {'role': 'assistant', 'content': 'The Fibonacci numbers between 10 and 30 are 13 and 21. \\n\\nThese numbers are part of the Fibonacci sequence, which is generated by adding the two preceding numbers to get the next number, starting from 0 and 1. \\n\\nThe sequence goes: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...\\n\\nAs you can see, 13 and 21 are the only numbers in this sequence that fall between 10 and 30.\\n\\nTERMINATE'}}}\n" - ] - } - ], - "source": [ - "# pass the thread ID to persist agent outputs for future interactions\n", - "# highlight-next-line\n", - "config = {\"configurable\": {\"thread_id\": \"1\"}}\n", - "\n", - "for chunk in graph.stream(\n", - " {\n", - " \"messages\": [\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"Find numbers between 10 and 30 in fibonacci sequence\",\n", - " }\n", - " ]\n", - " },\n", - " # highlight-next-line\n", - " config,\n", - "):\n", - " print(chunk)" - ] - }, - { - "cell_type": "markdown", - "id": "c6cd57b4-d4ee-49f6-be12-318613849669", - "metadata": {}, - "source": [ - "Since we're leveraging LangGraph's [persistence](https://langchain-ai.github.io/langgraph/concepts/persistence/) features we can now continue the conversation using the same thread ID -- LangGraph will automatically pass previous history to the AutoGen agent:" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "e68811a7-962e-4fe3-9f45-9b99ebbe04e7", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001B[33muser_proxy\u001B[0m (to assistant):\n", - "\n", - "Multiply the last number by 3\n", - "Context: \n", - "Find numbers between 10 and 30 in fibonacci sequence\n", - "The Fibonacci numbers between 10 and 30 are 13 and 21. \n", - "\n", - "These numbers are part of the Fibonacci sequence, which is generated by adding the two preceding numbers to get the next number, starting from 0 and 1. \n", - "\n", - "The sequence goes: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...\n", - "\n", - "As you can see, 13 and 21 are the only numbers in this sequence that fall between 10 and 30.\n", - "\n", - "TERMINATE\n", - "\n", - "--------------------------------------------------------------------------------\n", - "\u001B[33massistant\u001B[0m (to user_proxy):\n", - "\n", - "The last number in the Fibonacci sequence between 10 and 30 is 21. Multiplying 21 by 3 gives:\n", - "\n", - "21 * 3 = 63\n", - "\n", - "TERMINATE\n", - "\n", - "--------------------------------------------------------------------------------\n", - "{'call_autogen_agent': {'messages': {'role': 'assistant', 'content': 'The last number in the Fibonacci sequence between 10 and 30 is 21. Multiplying 21 by 3 gives:\\n\\n21 * 3 = 63\\n\\nTERMINATE'}}}\n" - ] - } - ], - "source": [ - "for chunk in graph.stream(\n", - " {\n", - " \"messages\": [\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"Multiply the last number by 3\",\n", - " }\n", - " ]\n", - " },\n", - " # highlight-next-line\n", - " config,\n", - "):\n", - " print(chunk)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.3" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/docs/docs/how-tos/autogen-integration.md b/docs/docs/how-tos/autogen-integration.md new file mode 100644 index 000000000..efbcf3d30 --- /dev/null +++ b/docs/docs/how-tos/autogen-integration.md @@ -0,0 +1,321 @@ +# How to integrate LangGraph with AutoGen, CrewAI, and other frameworks + +This guide shows how to integrate AutoGen agents with LangGraph to leverage features like persistence, streaming, and memory, and then deploy the integrated solution to LangGraph Platform for scalable production use. In this guide we show how to build a LangGraph chatbot that integrates with AutoGen, but you can follow the same approach with other frameworks. + +Integrating AutoGen with LangGraph provides several benefits: + +- Enhanced features: Add [persistence](../concepts/persistence.md), [streaming](../concepts/streaming.md), [short and long-term memory](../concepts/memory.md) and more to your AutoGen agents. +- Multi-agent systems: Build [multi-agent systems](../concepts/multi_agent.md) where individual agents are built with different frameworks. +- Production deployment: Deploy your integrated solution to [LangGraph Platform](../concepts/langgraph_platform.md) for scalable production use. + +## Prerequisites + +- Python 3.9+ +- Autogen: `pip install autogen` +- LangGraph: `pip install langgraph` +- OpenAI API key + +## Setup + +Set your your environment: + +```python +import getpass +import os + + +def _set_env(var: str): + if not os.environ.get(var): + os.environ[var] = getpass.getpass(f"{var}: ") + + +_set_env("OPENAI_API_KEY") +``` + +## 1. Define AutoGen agent + +Create an AutoGen agent that can execute code. This example is adapted from AutoGen's [official tutorials](https://github.com/microsoft/autogen/blob/0.2/notebook/agentchat_web_info.ipynb): + +```python +import autogen +import os + +config_list = [{"model": "gpt-4o", "api_key": os.environ["OPENAI_API_KEY"]}] + +llm_config = { + "timeout": 600, + "cache_seed": 42, + "config_list": config_list, + "temperature": 0, +} + +autogen_agent = autogen.AssistantAgent( + name="assistant", + llm_config=llm_config, +) + +user_proxy = autogen.UserProxyAgent( + name="user_proxy", + human_input_mode="NEVER", + max_consecutive_auto_reply=10, + is_termination_msg=lambda x: x.get("content", "").rstrip().endswith("TERMINATE"), + code_execution_config={ + "work_dir": "web", + "use_docker": False, + }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly. + llm_config=llm_config, + system_message="Reply TERMINATE if the task has been solved at full satisfaction. Otherwise, reply CONTINUE, or the reason why the task is not solved yet.", +) +``` + +## 2. Create the graph + +We will now create a LangGraph chatbot graph that calls AutoGen agent. + +```python +from langchain_core.messages import convert_to_openai_messages +from langgraph.graph import StateGraph, MessagesState, START +from langgraph.checkpoint.memory import MemorySaver + +def call_autogen_agent(state: MessagesState): + # Convert LangGraph messages to OpenAI format for AutoGen + messages = convert_to_openai_messages(state["messages"]) + + # Get the last user message + last_message = messages[-1] + + # Pass previous message history as context (excluding the last message) + carryover = messages[:-1] if len(messages) > 1 else [] + + # Initiate chat with AutoGen + response = user_proxy.initiate_chat( + autogen_agent, + message=last_message, + carryover=carryover + ) + + # Extract the final response from the agent + final_content = response.chat_history[-1]["content"] + + # Return the response in LangGraph format + return {"messages": {"role": "assistant", "content": final_content}} + +# Create the graph with memory for persistence +checkpointer = MemorySaver() + +# Build the graph +builder = StateGraph(MessagesState) +builder.add_node("autogen", call_autogen_agent) +builder.add_edge(START, "autogen") + +# Compile with checkpointer for persistence +graph = builder.compile(checkpointer=checkpointer) +``` + +```python +from IPython.display import display, Image + +display(Image(graph.get_graph().draw_mermaid_png())) +``` + +![Graph](./assets/autogen-output.png) + +## 3. Test the graph locally + +Before deploying to LangGraph Platform, you can test the graph locally: + +```python +# pass the thread ID to persist agent outputs for future interactions +# highlight-next-line +config = {"configurable": {"thread_id": "1"}} + +for chunk in graph.stream( + { + "messages": [ + { + "role": "user", + "content": "Find numbers between 10 and 30 in fibonacci sequence", + } + ] + }, + # highlight-next-line + config, +): + print(chunk) +``` + +**Output:** +``` +user_proxy (to assistant): + +Find numbers between 10 and 30 in fibonacci sequence + +-------------------------------------------------------------------------------- +assistant (to user_proxy): + +To find numbers between 10 and 30 in the Fibonacci sequence, we can generate the Fibonacci sequence and check which numbers fall within this range. Here's a plan: + +1. Generate Fibonacci numbers starting from 0. +2. Continue generating until the numbers exceed 30. +3. Collect and print the numbers that are between 10 and 30. + +... +``` + +Since we're leveraging LangGraph's [persistence](https://langchain-ai.github.io/langgraph/concepts/persistence/) features we can now continue the conversation using the same thread ID -- LangGraph will automatically pass previous history to the AutoGen agent: + +```python +for chunk in graph.stream( + { + "messages": [ + { + "role": "user", + "content": "Multiply the last number by 3", + } + ] + }, + # highlight-next-line + config, +): + print(chunk) +``` + +**Output:** +``` +user_proxy (to assistant): + +Multiply the last number by 3 +Context: +Find numbers between 10 and 30 in fibonacci sequence +The Fibonacci numbers between 10 and 30 are 13 and 21. + +These numbers are part of the Fibonacci sequence, which is generated by adding the two preceding numbers to get the next number, starting from 0 and 1. + +The sequence goes: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ... + +As you can see, 13 and 21 are the only numbers in this sequence that fall between 10 and 30. + +TERMINATE + +-------------------------------------------------------------------------------- +assistant (to user_proxy): + +The last number in the Fibonacci sequence between 10 and 30 is 21. Multiplying 21 by 3 gives: + +21 * 3 = 63 + +TERMINATE + +-------------------------------------------------------------------------------- +{'call_autogen_agent': {'messages': {'role': 'assistant', 'content': 'The last number in the Fibonacci sequence between 10 and 30 is 21. Multiplying 21 by 3 gives:\n\n21 * 3 = 63\n\nTERMINATE'}}} +``` + +## 4. Prepare for deployment + +To deploy to LangGraph Platform, create a file structure like the following: + +``` +my-autogen-agent/ +├── agent.py # Your main agent code +├── requirements.txt # Python dependencies +└── langgraph.json # LangGraph configuration +``` + +=== "agent.py" + + ```python + import os + import autogen + from langchain_core.messages import convert_to_openai_messages + from langgraph.graph import StateGraph, MessagesState, START + from langgraph.checkpoint.memory import MemorySaver + + # AutoGen configuration + config_list = [{"model": "gpt-4o", "api_key": os.environ["OPENAI_API_KEY"]}] + + llm_config = { + "timeout": 600, + "cache_seed": 42, + "config_list": config_list, + "temperature": 0, + } + + # Create AutoGen agents + autogen_agent = autogen.AssistantAgent( + name="assistant", + llm_config=llm_config, + ) + + user_proxy = autogen.UserProxyAgent( + name="user_proxy", + human_input_mode="NEVER", + max_consecutive_auto_reply=10, + is_termination_msg=lambda x: x.get("content", "").rstrip().endswith("TERMINATE"), + code_execution_config={ + "work_dir": "/tmp/autogen_work", + "use_docker": False, + }, + llm_config=llm_config, + system_message="Reply TERMINATE if the task has been solved at full satisfaction.", + ) + + def call_autogen_agent(state: MessagesState): + """Node function that calls the AutoGen agent""" + messages = convert_to_openai_messages(state["messages"]) + last_message = messages[-1] + carryover = messages[:-1] if len(messages) > 1 else [] + + response = user_proxy.initiate_chat( + autogen_agent, + message=last_message, + carryover=carryover + ) + + final_content = response.chat_history[-1]["content"] + return {"messages": {"role": "assistant", "content": final_content}} + + # Create and compile the graph + def create_graph(): + checkpointer = MemorySaver() + builder = StateGraph(MessagesState) + builder.add_node("autogen", call_autogen_agent) + builder.add_edge(START, "autogen") + return builder.compile(checkpointer=checkpointer) + + # Export the graph for LangGraph Platform + graph = create_graph() + ``` + +=== "requirements.txt" + + ``` + langgraph>=0.1.0 + pyautogen>=0.2.0 + langchain-core>=0.1.0 + langchain-openai>=0.0.5 + ``` + +=== "langgraph.json" + + ```json + { + "dependencies": ["."], + "graphs": { + "autogen_agent": "./agent.py:graph" + }, + "env": ".env" + } + ``` + + +## 5. Deploy to LangGraph Platform + +Deploy the graph with the LangGraph Platform CLI: + +``` +pip install -U langgraph-cli +``` + +``` +langgraph deploy --config langgraph.json +``` diff --git a/docs/docs/how-tos/autogen-langgraph-platform.ipynb b/docs/docs/how-tos/autogen-langgraph-platform.ipynb deleted file mode 100644 index 29bd24ba5..000000000 --- a/docs/docs/how-tos/autogen-langgraph-platform.ipynb +++ /dev/null @@ -1,171 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "8381b6e0-29a6-48c5-b451-5d2549351249", - "metadata": {}, - "source": [ - "# How to use LangGraph Platform to deploy CrewAI, AutoGen, and other frameworks\n", - "\n", - "[LangGraph Platform](https://langchain-ai.github.io/langgraph/concepts/langgraph_platform/) provides infrastructure for deploying agents. This integrates seamlessly with LangGraph, but can also work with other frameworks. The way to make this work is to wrap the agent in a single LangGraph node, and have that be the entire graph.\n", - "\n", - "Doing so will allow you to deploy to LangGraph Platform, and allows you to get a lot of the [benefits](https://langchain-ai.github.io/langgraph/concepts/langgraph_platform/). You get horizontally scalable infrastructure, a task queue to handle bursty operations, a persistence layer to power short term memory, and long term memory support.\n", - "\n", - "In this guide we show how to do this with an AutoGen agent, but this method should work for agents defined in other frameworks like CrewAI, LlamaIndex, and others as well." - ] - }, - { - "cell_type": "markdown", - "id": "1113cb16-b538-448c-924c-85731ce96ebd", - "metadata": {}, - "source": [ - "## Setup" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "f05993fa-9d03-4f45-bc13-0a8d87260d86", - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "%pip install autogen langgraph" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f4e0ca12-1714-4776-a30a-9527e519799b", - "metadata": {}, - "outputs": [], - "source": [ - "import getpass\n", - "import os\n", - "\n", - "\n", - "def _set_env(var: str):\n", - " if not os.environ.get(var):\n", - " os.environ[var] = getpass.getpass(f\"{var}: \")\n", - "\n", - "\n", - "_set_env(\"OPENAI_API_KEY\")" - ] - }, - { - "cell_type": "markdown", - "id": "1926bbc3-6b06-41e0-9604-860a2bbf8fa3", - "metadata": {}, - "source": [ - "## Define autogen agent\n", - "\n", - "Here we define our AutoGen agent. From https://github.com/microsoft/autogen/blob/0.2/notebook/agentchat_web_info.ipynb" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d4a14dc7-d565-4207-8788-525f85b9fb27", - "metadata": {}, - "outputs": [], - "source": [ - "import autogen\n", - "import os\n", - "\n", - "config_list = [{\"model\": \"gpt-4o\", \"api_key\": os.environ[\"OPENAI_API_KEY\"]}]\n", - "\n", - "llm_config = {\n", - " \"timeout\": 600,\n", - " \"cache_seed\": 42,\n", - " \"config_list\": config_list,\n", - " \"temperature\": 0,\n", - "}\n", - "\n", - "autogen_agent = autogen.AssistantAgent(\n", - " name=\"assistant\",\n", - " llm_config=llm_config,\n", - ")\n", - "\n", - "user_proxy = autogen.UserProxyAgent(\n", - " name=\"user_proxy\",\n", - " human_input_mode=\"NEVER\",\n", - " max_consecutive_auto_reply=10,\n", - " is_termination_msg=lambda x: x.get(\"content\", \"\").rstrip().endswith(\"TERMINATE\"),\n", - " code_execution_config={\n", - " \"work_dir\": \"web\",\n", - " \"use_docker\": False,\n", - " }, # Please set use_docker=True if docker is available to run the generated code. Using docker is safer than running the generated code directly.\n", - " llm_config=llm_config,\n", - " system_message=\"Reply TERMINATE if the task has been solved at full satisfaction. Otherwise, reply CONTINUE, or the reason why the task is not solved yet.\",\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "b1170836-f23e-4e4c-ab83-ce791cd7fbd2", - "metadata": {}, - "source": [ - "## Wrap in LangGraph\n", - "\n", - "We now wrap the AutoGen agent in a single LangGraph node, and make that the entire graph.\n", - "The main thing this involves is defining an Input and Output schema for the node, which you would need to do if deploying this manually, so it's no extra work" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "7b417c16-ff4e-4d5c-a9a9-0aaeeef6ede5", - "metadata": {}, - "outputs": [], - "source": [ - "from langgraph.graph import StateGraph, MessagesState\n", - "\n", - "\n", - "def call_autogen_agent(state: MessagesState):\n", - " last_message = state[\"messages\"][-1]\n", - " response = user_proxy.initiate_chat(autogen_agent, message=last_message.content)\n", - " # get the final response from the agent\n", - " content = response.chat_history[-1][\"content\"]\n", - " return {\"messages\": {\"role\": \"assistant\", \"content\": content}}\n", - "\n", - "\n", - "graph = StateGraph(MessagesState)\n", - "graph.add_node(call_autogen_agent)\n", - "graph.set_entry_point(\"call_autogen_agent\")\n", - "graph = graph.compile()" - ] - }, - { - "cell_type": "markdown", - "id": "f6a18377-ac29-478f-a76a-b213f1a3c85d", - "metadata": {}, - "source": [ - "## Deploy with LangGraph Platform\n", - "\n", - "You can now deploy this as you normally would with LangGraph Platform. See [these instructions](https://langchain-ai.github.io/langgraph/concepts/deployment_options/) for more details." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.3" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/docs/docs/how-tos/multi_agent.ipynb b/docs/docs/how-tos/multi_agent.ipynb deleted file mode 100644 index 6ee5777de..000000000 --- a/docs/docs/how-tos/multi_agent.ipynb +++ /dev/null @@ -1,657 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "34d3d54e-9a2b-481e-bccd-74aca7a53f9a", - "metadata": {}, - "source": [ - "# Build multi-agent systems" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "3f0b4f70-f14e-4026-82c0-874786789ee8", - "metadata": {}, - "source": [ - "A single agent might struggle if it needs to specialize in multiple domains or manage many tools. To tackle this, you can break your agent into smaller, independent agents and composing them into a [multi-agent system](../../concepts/multi_agent).\n", - "\n", - "In multi-agent systems, agents need to communicate between each other. They do so via [handoffs](#handoffs) — a primitive that describes which agent to hand control to and the payload to send to that agent.\n", - "\n", - "This guide covers the following:\n", - "\n", - "* implementing [handoffs](#handoffs) between agents\n", - "* using handoffs and the prebuilt [agent](../../agents/agents) to [build a custom multi-agent system](#build-a-multi-agent-system)\n", - "\n", - "To get started with building multi-agent systems, check out LangGraph [prebuilt implementations](#prebuilt-implementations) of two of the most popular multi-agent architectures — [supervisor](../../agents/multi-agent#supervisor) and [swarm](../../agents/multi-agent#swarm)." - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "7d43e110-16fc-4899-97f1-015d5b804b87", - "metadata": {}, - "source": [ - "## Handoffs\n", - "\n", - "To set up communication between the agents in a multi-agent system you can use [**handoffs**](../../concepts/multi_agent#handoffs) — a pattern where one agent *hands off* control to another. Handoffs allow you to specify:\n", - "\n", - "- **destination**: target agent to navigate to (e.g., name of the LangGraph node to go to)\n", - "- **payload**: information to pass to that agent (e.g., state update)\n", - "\n", - "### Create handoffs\n", - "\n", - "To implement handoffs, you can return [`Command`](../command) objects from your agent nodes or tools:\n", - "\n", - "```python\n", - "from typing import Annotated\n", - "from langchain_core.tools import tool, InjectedToolCallId\n", - "from langgraph.prebuilt import create_react_agent, InjectedState\n", - "from langgraph.graph import StateGraph, START, MessagesState\n", - "from langgraph.types import Command\n", - "\n", - "def create_handoff_tool(*, agent_name: str, description: str | None = None):\n", - " name = f\"transfer_to_{agent_name}\"\n", - " description = description or f\"Transfer to {agent_name}\"\n", - "\n", - " @tool(name, description=description)\n", - " def handoff_tool(\n", - " # highlight-next-line\n", - " state: Annotated[MessagesState, InjectedState], # (1)!\n", - " # highlight-next-line\n", - " tool_call_id: Annotated[str, InjectedToolCallId],\n", - " ) -> Command:\n", - " tool_message = {\n", - " \"role\": \"tool\",\n", - " \"content\": f\"Successfully transferred to {agent_name}\",\n", - " \"name\": name,\n", - " \"tool_call_id\": tool_call_id,\n", - " }\n", - " return Command( # (2)!\n", - " # highlight-next-line\n", - " goto=agent_name, # (3)!\n", - " # highlight-next-line\n", - " update={\"messages\": state[\"messages\"] + [tool_message]}, # (4)!\n", - " # highlight-next-line\n", - " graph=Command.PARENT, # (5)!\n", - " )\n", - " return handoff_tool\n", - "```\n", - "\n", - "1. Access the [state](../../concepts/low_level#state) of the agent that is calling the handoff tool using the [InjectedState][langgraph.prebuilt.InjectedState] annotation. See [this guide](../tool-calling/#read-state) for more information.\n", - "2. The `Command` primitive allows specifying a state update and a node transition as a single operation, making it useful for implementing handoffs.\n", - "3. Name of the agent or node to hand off to.\n", - "4. Take the agent's messages and **add** them to the parent's **state** as part of the handoff. The next agent will see the parent state.\n", - "5. Indicate to LangGraph that we need to navigate to agent node in a **parent** multi-agent graph.\n", - "\n", - "!!! tip\n", - "\n", - " If you want to use tools that return `Command`, you can either use prebuilt [`create_react_agent`][langgraph.prebuilt.chat_agent_executor.create_react_agent] / [`ToolNode`][langgraph.prebuilt.tool_node.ToolNode] components, or implement your own tool-executing node that collects `Command` objects returned by the tools and returns a list of them, e.g.:\n", - " \n", - " ```python\n", - " def call_tools(state):\n", - " ...\n", - " commands = [tools_by_name[tool_call[\"name\"]].invoke(tool_call) for tool_call in tool_calls]\n", - " return commands\n", - " ```\n", - "\n", - "!!! Important\n", - "\n", - " This handoff implementation assumes that:\n", - " \n", - " - each agent receives overall message history (across all agents) in the multi-agent system as its input. If you want more control over agent inputs, see [this section](#control-agent-inputs)\n", - " - each agent outputs its internal messages history to the overall message history of the multi-agent system. If you want more control over **how agent outputs are added**, wrap the agent in a separate node function:\n", - "\n", - " ```python\n", - " def call_hotel_assistant(state):\n", - " # return agent's final response,\n", - " # excluding inner monologue\n", - " response = hotel_assistant.invoke(state)\n", - " # highlight-next-line\n", - " return {\"messages\": response[\"messages\"][-1]}\n", - " ```" - ] - }, - { - "cell_type": "markdown", - "id": "3956f12d-285a-4799-a0a5-db13def58a15", - "metadata": {}, - "source": [ - "### Control agent inputs\n", - "\n", - "You can use the [`Send()`][langgraph.types.Send] primitive to directly send data to the worker agents during the handoff. For example, you can request that the calling agent populate a task description for the next agent:\n", - "\n", - "```python\n", - "\n", - "from typing import Annotated\n", - "from langchain_core.tools import tool, InjectedToolCallId\n", - "from langgraph.prebuilt import InjectedState\n", - "from langgraph.graph import StateGraph, START, MessagesState\n", - "# highlight-next-line\n", - "from langgraph.types import Command, Send\n", - "\n", - "def create_task_description_handoff_tool(\n", - " *, agent_name: str, description: str | None = None\n", - "):\n", - " name = f\"transfer_to_{agent_name}\"\n", - " description = description or f\"Ask {agent_name} for help.\"\n", - "\n", - " @tool(name, description=description)\n", - " def handoff_tool(\n", - " # this is populated by the calling agent\n", - " task_description: Annotated[\n", - " str,\n", - " \"Description of what the next agent should do, including all of the relevant context.\",\n", - " ],\n", - " # these parameters are ignored by the LLM\n", - " state: Annotated[MessagesState, InjectedState],\n", - " ) -> Command:\n", - " task_description_message = {\"role\": \"user\", \"content\": task_description}\n", - " agent_input = {**state, \"messages\": [task_description_message]}\n", - " return Command(\n", - " # highlight-next-line\n", - " goto=[Send(agent_name, agent_input)],\n", - " graph=Command.PARENT,\n", - " )\n", - "\n", - " return handoff_tool\n", - "```\n", - "\n", - "See the multi-agent [supervisor](../tutorials/agent_supervisor.ipynb#4-create-delegation-tasks) tutorial for a full example of using [`Send()`][langgraph.types.Send] in handoffs." - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "21511f57-7bf3-4223-9a17-ce9fc84c40ab", - "metadata": {}, - "source": [ - "## Build a multi-agent system\n", - "\n", - "You can use handoffs in any agents built with LangGraph. We recommend using the prebuilt [agent](../../agents/overview) or [`ToolNode`](../tool-calling#use-prebuilt-toolnode), as they natively support handoffs tools returning `Command`. Below is an example of how you can implement a multi-agent system for booking travel using handoffs:\n", - "\n", - "```python\n", - "from langgraph.prebuilt import create_react_agent\n", - "from langgraph.graph import StateGraph, START, MessagesState\n", - "\n", - "def create_handoff_tool(*, agent_name: str, description: str | None = None):\n", - " # same implementation as above\n", - " ...\n", - " return Command(...)\n", - "\n", - "# Handoffs\n", - "transfer_to_hotel_assistant = create_handoff_tool(agent_name=\"hotel_assistant\")\n", - "transfer_to_flight_assistant = create_handoff_tool(agent_name=\"flight_assistant\")\n", - "\n", - "# Define agents\n", - "flight_assistant = create_react_agent(\n", - " model=\"anthropic:claude-3-5-sonnet-latest\",\n", - " # highlight-next-line\n", - " tools=[..., transfer_to_hotel_assistant],\n", - " # highlight-next-line\n", - " name=\"flight_assistant\"\n", - ")\n", - "hotel_assistant = create_react_agent(\n", - " model=\"anthropic:claude-3-5-sonnet-latest\",\n", - " # highlight-next-line\n", - " tools=[..., transfer_to_flight_assistant],\n", - " # highlight-next-line\n", - " name=\"hotel_assistant\"\n", - ")\n", - "\n", - "# Define multi-agent graph\n", - "multi_agent_graph = (\n", - " StateGraph(MessagesState)\n", - " # highlight-next-line\n", - " .add_node(flight_assistant)\n", - " # highlight-next-line\n", - " .add_node(hotel_assistant)\n", - " .add_edge(START, \"flight_assistant\")\n", - " .compile()\n", - ")\n", - "```\n", - "\n", - "??? example \"Full example: Multi-agent system for booking travel\"\n", - "\n", - " ```python\n", - " from typing import Annotated\n", - " from langchain_core.messages import convert_to_messages\n", - " from langchain_core.tools import tool, InjectedToolCallId\n", - " from langgraph.prebuilt import create_react_agent, InjectedState\n", - " from langgraph.graph import StateGraph, START, MessagesState\n", - " from langgraph.types import Command\n", - " \n", - " # We'll use `pretty_print_messages` helper to render the streamed agent outputs nicely\n", - " \n", - " def pretty_print_message(message, indent=False):\n", - " pretty_message = message.pretty_repr(html=True)\n", - " if not indent:\n", - " print(pretty_message)\n", - " return\n", - " \n", - " indented = \"\\n\".join(\"\\t\" + c for c in pretty_message.split(\"\\n\"))\n", - " print(indented)\n", - " \n", - " \n", - " def pretty_print_messages(update, last_message=False):\n", - " is_subgraph = False\n", - " if isinstance(update, tuple):\n", - " ns, update = update\n", - " # skip parent graph updates in the printouts\n", - " if len(ns) == 0:\n", - " return\n", - " \n", - " graph_id = ns[-1].split(\":\")[0]\n", - " print(f\"Update from subgraph {graph_id}:\")\n", - " print(\"\\n\")\n", - " is_subgraph = True\n", - " \n", - " for node_name, node_update in update.items():\n", - " update_label = f\"Update from node {node_name}:\"\n", - " if is_subgraph:\n", - " update_label = \"\\t\" + update_label\n", - " \n", - " print(update_label)\n", - " print(\"\\n\")\n", - " \n", - " messages = convert_to_messages(node_update[\"messages\"])\n", - " if last_message:\n", - " messages = messages[-1:]\n", - " \n", - " for m in messages:\n", - " pretty_print_message(m, indent=is_subgraph)\n", - " print(\"\\n\")\n", - "\n", - "\n", - " def create_handoff_tool(*, agent_name: str, description: str | None = None):\n", - " name = f\"transfer_to_{agent_name}\"\n", - " description = description or f\"Transfer to {agent_name}\"\n", - " \n", - " @tool(name, description=description)\n", - " def handoff_tool(\n", - " # highlight-next-line\n", - " state: Annotated[MessagesState, InjectedState], # (1)!\n", - " # highlight-next-line\n", - " tool_call_id: Annotated[str, InjectedToolCallId],\n", - " ) -> Command:\n", - " tool_message = {\n", - " \"role\": \"tool\",\n", - " \"content\": f\"Successfully transferred to {agent_name}\",\n", - " \"name\": name,\n", - " \"tool_call_id\": tool_call_id,\n", - " }\n", - " return Command( # (2)!\n", - " # highlight-next-line\n", - " goto=agent_name, # (3)!\n", - " # highlight-next-line\n", - " update={\"messages\": state[\"messages\"] + [tool_message]}, # (4)!\n", - " # highlight-next-line\n", - " graph=Command.PARENT, # (5)!\n", - " )\n", - " return handoff_tool\n", - " \n", - " # Handoffs\n", - " transfer_to_hotel_assistant = create_handoff_tool(\n", - " agent_name=\"hotel_assistant\",\n", - " description=\"Transfer user to the hotel-booking assistant.\",\n", - " )\n", - " transfer_to_flight_assistant = create_handoff_tool(\n", - " agent_name=\"flight_assistant\",\n", - " description=\"Transfer user to the flight-booking assistant.\",\n", - " )\n", - " \n", - " # Simple agent tools\n", - " def book_hotel(hotel_name: str):\n", - " \"\"\"Book a hotel\"\"\"\n", - " return f\"Successfully booked a stay at {hotel_name}.\"\n", - " \n", - " def book_flight(from_airport: str, to_airport: str):\n", - " \"\"\"Book a flight\"\"\"\n", - " return f\"Successfully booked a flight from {from_airport} to {to_airport}.\"\n", - " \n", - " # Define agents\n", - " flight_assistant = create_react_agent(\n", - " model=\"anthropic:claude-3-5-sonnet-latest\",\n", - " # highlight-next-line\n", - " tools=[book_flight, transfer_to_hotel_assistant],\n", - " prompt=\"You are a flight booking assistant\",\n", - " # highlight-next-line\n", - " name=\"flight_assistant\"\n", - " )\n", - " hotel_assistant = create_react_agent(\n", - " model=\"anthropic:claude-3-5-sonnet-latest\",\n", - " # highlight-next-line\n", - " tools=[book_hotel, transfer_to_flight_assistant],\n", - " prompt=\"You are a hotel booking assistant\",\n", - " # highlight-next-line\n", - " name=\"hotel_assistant\"\n", - " )\n", - " \n", - " # Define multi-agent graph\n", - " multi_agent_graph = (\n", - " StateGraph(MessagesState)\n", - " .add_node(flight_assistant)\n", - " .add_node(hotel_assistant)\n", - " .add_edge(START, \"flight_assistant\")\n", - " .compile()\n", - " )\n", - " \n", - " # Run the multi-agent graph\n", - " for chunk in multi_agent_graph.stream(\n", - " {\n", - " \"messages\": [\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"book a flight from BOS to JFK and a stay at McKittrick Hotel\"\n", - " }\n", - " ]\n", - " },\n", - " # highlight-next-line\n", - " subgraphs=True\n", - " ):\n", - " pretty_print_messages(chunk)\n", - " ```\n", - "\n", - " 1. Access agent's state\n", - " 2. The `Command` primitive allows specifying a state update and a node transition as a single operation, making it useful for implementing handoffs.\n", - " 3. Name of the agent or node to hand off to.\n", - " 4. Take the agent's messages and **add** them to the parent's **state** as part of the handoff. The next agent will see the parent state.\n", - " 5. Indicate to LangGraph that we need to navigate to agent node in a **parent** multi-agent graph." - ] - }, - { - "cell_type": "markdown", - "id": "e8314da4-9971-429b-9e70-58b40795de74", - "metadata": {}, - "source": [ - "## Multi-turn conversation\n", - "\n", - "Users might want to engage in a *multi-turn conversation* with one or more agents. To build a system that can handle this, you can create a node that uses an [`interrupt`][langgraph.types.interrupt] to collect user input and routes back to the **active** agent.\n", - "\n", - "The agents can then be implemented as nodes in a graph that executes agent steps and determines the next action:\n", - "\n", - "1. **Wait for user input** to continue the conversation, or \n", - "2. **Route to another agent** (or back to itself, such as in a loop) via a [handoff](#handoffs)\n", - "\n", - "```python\n", - "def human(state) -> Command[Literal[\"agent\", \"another_agent\"]]:\n", - " \"\"\"A node for collecting user input.\"\"\"\n", - " user_input = interrupt(value=\"Ready for user input.\")\n", - "\n", - " # Determine the active agent.\n", - " active_agent = ...\n", - "\n", - " ...\n", - " return Command(\n", - " update={\n", - " \"messages\": [{\n", - " \"role\": \"human\",\n", - " \"content\": user_input,\n", - " }]\n", - " },\n", - " goto=active_agent\n", - " )\n", - "\n", - "def agent(state) -> Command[Literal[\"agent\", \"another_agent\", \"human\"]]:\n", - " # The condition for routing/halting can be anything, e.g. LLM tool call / structured output, etc.\n", - " goto = get_next_agent(...) # 'agent' / 'another_agent'\n", - " if goto:\n", - " return Command(goto=goto, update={\"my_state_key\": \"my_state_value\"})\n", - " else:\n", - " return Command(goto=\"human\") # Go to human node\n", - "```\n", - "\n", - "??? example \"Full example: multi-agent system for travel recommendations\"\n", - "\n", - " In this example, we will build a team of travel assistant agents that can communicate with each other via handoffs.\n", - " \n", - " We will create 2 agents:\n", - " \n", - " * travel_advisor: can help with travel destination recommendations. Can ask hotel_advisor for help.\n", - " * hotel_advisor: can help with hotel recommendations. Can ask travel_advisor for help.\n", - "\n", - " ```python\n", - " from langchain_anthropic import ChatAnthropic\n", - " from langgraph.graph import MessagesState, StateGraph, START\n", - " from langgraph.prebuilt import create_react_agent, InjectedState\n", - " from langgraph.types import Command, interrupt\n", - " from langgraph.checkpoint.memory import MemorySaver\n", - " \n", - " \n", - " model = ChatAnthropic(model=\"claude-3-5-sonnet-latest\")\n", - "\n", - " class MultiAgentState(MessagesState):\n", - " last_active_agent: str\n", - " \n", - " \n", - " # Define travel advisor tools and ReAct agent\n", - " travel_advisor_tools = [\n", - " get_travel_recommendations,\n", - " make_handoff_tool(agent_name=\"hotel_advisor\"),\n", - " ]\n", - " travel_advisor = create_react_agent(\n", - " model,\n", - " travel_advisor_tools,\n", - " prompt=(\n", - " \"You are a general travel expert that can recommend travel destinations (e.g. countries, cities, etc). \"\n", - " \"If you need hotel recommendations, ask 'hotel_advisor' for help. \"\n", - " \"You MUST include human-readable response before transferring to another agent.\"\n", - " ),\n", - " )\n", - " \n", - " \n", - " def call_travel_advisor(\n", - " state: MultiAgentState,\n", - " ) -> Command[Literal[\"hotel_advisor\", \"human\"]]:\n", - " # You can also add additional logic like changing the input to the agent / output from the agent, etc.\n", - " # NOTE: we're invoking the ReAct agent with the full history of messages in the state\n", - " response = travel_advisor.invoke(state)\n", - " update = {**response, \"last_active_agent\": \"travel_advisor\"}\n", - " return Command(update=update, goto=\"human\")\n", - " \n", - " \n", - " # Define hotel advisor tools and ReAct agent\n", - " hotel_advisor_tools = [\n", - " get_hotel_recommendations,\n", - " make_handoff_tool(agent_name=\"travel_advisor\"),\n", - " ]\n", - " hotel_advisor = create_react_agent(\n", - " model,\n", - " hotel_advisor_tools,\n", - " prompt=(\n", - " \"You are a hotel expert that can provide hotel recommendations for a given destination. \"\n", - " \"If you need help picking travel destinations, ask 'travel_advisor' for help.\"\n", - " \"You MUST include human-readable response before transferring to another agent.\"\n", - " ),\n", - " )\n", - " \n", - " \n", - " def call_hotel_advisor(\n", - " state: MultiAgentState,\n", - " ) -> Command[Literal[\"travel_advisor\", \"human\"]]:\n", - " response = hotel_advisor.invoke(state)\n", - " update = {**response, \"last_active_agent\": \"hotel_advisor\"}\n", - " return Command(update=update, goto=\"human\")\n", - " \n", - " \n", - " def human_node(\n", - " state: MultiAgentState, config\n", - " ) -> Command[Literal[\"hotel_advisor\", \"travel_advisor\", \"human\"]]:\n", - " \"\"\"A node for collecting user input.\"\"\"\n", - " \n", - " user_input = interrupt(value=\"Ready for user input.\")\n", - " active_agent = state[\"last_active_agent\"]\n", - " \n", - " return Command(\n", - " update={\n", - " \"messages\": [\n", - " {\n", - " \"role\": \"human\",\n", - " \"content\": user_input,\n", - " }\n", - " ]\n", - " },\n", - " goto=active_agent,\n", - " )\n", - " \n", - " \n", - " builder = StateGraph(MultiAgentState)\n", - " builder.add_node(\"travel_advisor\", call_travel_advisor)\n", - " builder.add_node(\"hotel_advisor\", call_hotel_advisor)\n", - " \n", - " # This adds a node to collect human input, which will route\n", - " # back to the active agent.\n", - " builder.add_node(\"human\", human_node)\n", - " \n", - " # We'll always start with a general travel advisor.\n", - " builder.add_edge(START, \"travel_advisor\")\n", - " \n", - " \n", - " checkpointer = MemorySaver()\n", - " graph = builder.compile(checkpointer=checkpointer)\n", - " ```\n", - " \n", - " Let's test a multi turn conversation with this application.\n", - "\n", - " ```python\n", - " import uuid\n", - " \n", - " thread_config = {\"configurable\": {\"thread_id\": str(uuid.uuid4())}}\n", - " \n", - " inputs = [\n", - " # 1st round of conversation,\n", - " {\n", - " \"messages\": [\n", - " {\"role\": \"user\", \"content\": \"i wanna go somewhere warm in the caribbean\"}\n", - " ]\n", - " },\n", - " # Since we're using `interrupt`, we'll need to resume using the Command primitive.\n", - " # 2nd round of conversation,\n", - " Command(\n", - " resume=\"could you recommend a nice hotel in one of the areas and tell me which area it is.\"\n", - " ),\n", - " # 3rd round of conversation,\n", - " Command(\n", - " resume=\"i like the first one. could you recommend something to do near the hotel?\"\n", - " ),\n", - " ]\n", - " \n", - " for idx, user_input in enumerate(inputs):\n", - " print()\n", - " print(f\"--- Conversation Turn {idx + 1} ---\")\n", - " print()\n", - " print(f\"User: {user_input}\")\n", - " print()\n", - " for update in graph.stream(\n", - " user_input,\n", - " config=thread_config,\n", - " stream_mode=\"updates\",\n", - " ):\n", - " for node_id, value in update.items():\n", - " if isinstance(value, dict) and value.get(\"messages\", []):\n", - " last_message = value[\"messages\"][-1]\n", - " if isinstance(last_message, dict) or last_message.type != \"ai\":\n", - " continue\n", - " print(f\"{node_id}: {last_message.content}\")\n", - " ```\n", - " \n", - " ```\n", - " --- Conversation Turn 1 ---\n", - " \n", - " User: {'messages': [{'role': 'user', 'content': 'i wanna go somewhere warm in the caribbean'}]}\n", - " \n", - " travel_advisor: Based on the recommendations, Aruba would be an excellent choice for your Caribbean getaway! Aruba is known as \"One Happy Island\" and offers:\n", - " - Year-round warm weather with consistent temperatures around 82°F (28°C)\n", - " - Beautiful white sand beaches like Eagle Beach and Palm Beach\n", - " - Clear turquoise waters perfect for swimming and snorkeling\n", - " - Minimal rainfall and location outside the hurricane belt\n", - " - A blend of Caribbean and Dutch culture\n", - " - Great dining options and nightlife\n", - " - Various water sports and activities\n", - " \n", - " Would you like me to get some specific hotel recommendations in Aruba for your stay? I can transfer you to our hotel advisor who can help with accommodations.\n", - " \n", - " --- Conversation Turn 2 ---\n", - " \n", - " User: Command(resume='could you recommend a nice hotel in one of the areas and tell me which area it is.')\n", - " \n", - " hotel_advisor: Based on the recommendations, I can suggest two excellent options:\n", - " \n", - " 1. The Ritz-Carlton, Aruba - Located in Palm Beach\n", - " - This luxury resort is situated in the vibrant Palm Beach area\n", - " - Known for its exceptional service and amenities\n", - " - Perfect if you want to be close to dining, shopping, and entertainment\n", - " - Features multiple restaurants, a casino, and a world-class spa\n", - " - Located on a pristine stretch of Palm Beach\n", - " \n", - " 2. Bucuti & Tara Beach Resort - Located in Eagle Beach\n", - " - An adults-only boutique resort on Eagle Beach\n", - " - Known for being more intimate and peaceful\n", - " - Award-winning for its sustainability practices\n", - " - Perfect for a romantic getaway or peaceful vacation\n", - " - Located on one of the most beautiful beaches in the Caribbean\n", - " \n", - " Would you like more specific information about either of these properties or their locations?\n", - " \n", - " --- Conversation Turn 3 ---\n", - " \n", - " User: Command(resume='i like the first one. could you recommend something to do near the hotel?')\n", - " \n", - " travel_advisor: Near the Ritz-Carlton in Palm Beach, here are some highly recommended activities:\n", - " \n", - " 1. Visit the Palm Beach Plaza Mall - Just a short walk from the hotel, featuring shopping, dining, and entertainment\n", - " 2. Try your luck at the Stellaris Casino - It's right in the Ritz-Carlton\n", - " 3. Take a sunset sailing cruise - Many depart from the nearby pier\n", - " 4. Visit the California Lighthouse - A scenic landmark just north of Palm Beach\n", - " 5. Enjoy water sports at Palm Beach:\n", - " - Jet skiing\n", - " - Parasailing\n", - " - Snorkeling\n", - " - Stand-up paddleboarding\n", - " \n", - " Would you like more specific information about any of these activities or would you like to know about other options in the area?\n", - " ```" - ] - }, - { - "cell_type": "markdown", - "id": "04d18c63-a0eb-45ac-86dc-0cc5bd683973", - "metadata": {}, - "source": [ - "## Prebuilt implementations" - ] - }, - { - "cell_type": "markdown", - "id": "e0e4ce57-f8de-4f37-836e-c1e1a02dd7b7", - "metadata": {}, - "source": [ - "LangGraph comes with prebuilt implementations of two of the most popular multi-agent architectures:\n", - "\n", - "- [supervisor](../../agents/multi-agent#supervisor) — individual agents are coordinated by a central supervisor agent. The supervisor controls all communication flow and task delegation, making decisions about which agent to invoke based on the current context and task requirements. You can use [`langgraph-supervisor`](https://github.com/langchain-ai/langgraph-supervisor-py) library to create a supervisor multi-agent systems.\n", - "- [swarm](../../agents/multi-agent#supervisor) — agents dynamically hand off control to one another based on their specializations. The system remembers which agent was last active, ensuring that on subsequent interactions, the conversation resumes with that agent. You can use [`langgraph-swarm`](https://github.com/langchain-ai/langgraph-swarm-py) library to create a swarm multi-agent systems." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.3" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/docs/docs/how-tos/multi_agent.md b/docs/docs/how-tos/multi_agent.md index 5aead8b95..fdd781d4f 100644 --- a/docs/docs/how-tos/multi_agent.md +++ b/docs/docs/how-tos/multi_agent.md @@ -130,7 +130,7 @@ def create_task_description_handoff_tool( return handoff_tool ``` -See the multi-agent [supervisor](../tutorials/multi_agent/agent_supervisor.ipynb#4-create-delegation-tasks) example for a full example of using [`Send()`][langgraph.types.Send] in handoffs. +See the multi-agent [supervisor](../tutorials/multi_agent/agent_supervisor.md#4-create-delegation-tasks) example for a full example of using [`Send()`][langgraph.types.Send] in handoffs. ## Build a multi-agent system diff --git a/docs/docs/how-tos/run-id-langsmith.ipynb b/docs/docs/how-tos/run-id-langsmith.ipynb deleted file mode 100644 index 550c8ae64..000000000 --- a/docs/docs/how-tos/run-id-langsmith.ipynb +++ /dev/null @@ -1,274 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# How to pass custom run ID or set tags and metadata for graph runs in LangSmith\n", - "\n", - "

\n", - "\n", - "Debugging graph runs can sometimes be difficult to do in an IDE or terminal. [LangSmith](https://docs.smith.langchain.com) lets you use trace data to debug, test, and monitor your LLM apps built with LangGraph — read the [LangSmith documentation](https://docs.smith.langchain.com) for more information on how to get started.\n", - "\n", - "To make it easier to identify and analyzed traces generated during graph invocation, you can set additional configuration at run time (see [RunnableConfig](https://api.python.langchain.com/en/latest/runnables/langchain_core.runnables.config.RunnableConfig.html#langchain_core.runnables.config.RunnableConfig)):\n", - "\n", - "| **Field** | **Type** | **Description** |\n", - "|-------------|---------------------|--------------------------------------------------------------------------------------------------------------------|\n", - "| run_name | `str` | Name for the tracer run for this call. Defaults to the name of the class. |\n", - "| run_id | `UUID` | Unique identifier for the tracer run for this call. If not provided, a new UUID will be generated. |\n", - "| tags | `List[str]` | Tags for this call and any sub-calls (e.g., a Chain calling an LLM). You can use these to filter calls. |\n", - "| metadata | `Dict[str, Any]` | Metadata for this call and any sub-calls (e.g., a Chain calling an LLM). Keys should be strings, values should be JSON-serializable. |\n", - "\n", - "LangGraph graphs implement the [LangChain Runnable Interface](https://python.langchain.com/api_reference/core/runnables/langchain_core.runnables.base.Runnable.html) and accept a second argument (`RunnableConfig`) in methods like `invoke`, `ainvoke`, `stream` etc.\n", - "\n", - "The LangSmith platform will allow you to search and filter traces based on `run_name`, `run_id`, `tags` and `metadata`.\n", - "\n", - "\n", - "## TLDR\n", - "\n", - "```python\n", - "import uuid\n", - "# Generate a random UUID -- it must be a UUID\n", - "config = {\"run_id\": uuid.uuid4()}, \"tags\": [\"my_tag1\"], \"metadata\": {\"a\": 5}}\n", - "# Works with all standard Runnable methods \n", - "# like invoke, batch, ainvoke, astream_events etc\n", - "graph.stream(inputs, config, stream_mode=\"values\")\n", - "```\n", - "\n", - "The rest of the how to guide will show a full agent.\n", - "\n", - "## Setup\n", - "\n", - "First, let's install the required packages and set our API keys" - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [], - "source": [ - "%%capture --no-stderr\n", - "%pip install --quiet -U langgraph langchain_openai" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [], - "source": [ - "import getpass\n", - "import os\n", - "\n", - "\n", - "def _set_env(var: str):\n", - " if not os.environ.get(var):\n", - " os.environ[var] = getpass.getpass(f\"{var}: \")\n", - "\n", - "\n", - "_set_env(\"OPENAI_API_KEY\")\n", - "_set_env(\"LANGSMITH_API_KEY\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "

Set up LangSmith for LangGraph development

\n", - "

\n", - " Sign up for LangSmith to quickly spot issues and improve the performance of your LangGraph projects. LangSmith lets you use trace data to debug, test, and monitor your LLM apps built with LangGraph — read more about how to get started here. \n", - "

\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Define the graph\n", - "\n", - "For this example we will use the [prebuilt ReAct agent](https://langchain-ai.github.io/langgraph/how-tos/create-react-agent/)." - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [], - "source": [ - "from langchain_openai import ChatOpenAI\n", - "from typing import Literal\n", - "from langgraph.prebuilt import create_react_agent\n", - "from langchain_core.tools import tool\n", - "\n", - "# First we initialize the model we want to use.\n", - "model = ChatOpenAI(model=\"gpt-4o\", temperature=0)\n", - "\n", - "\n", - "# For this tutorial we will use custom tool that returns pre-defined values for weather in two cities (NYC & SF)\n", - "@tool\n", - "def get_weather(city: Literal[\"nyc\", \"sf\"]):\n", - " \"\"\"Use this to get weather information.\"\"\"\n", - " if city == \"nyc\":\n", - " return \"It might be cloudy in nyc\"\n", - " elif city == \"sf\":\n", - " return \"It's always sunny in sf\"\n", - " else:\n", - " raise AssertionError(\"Unknown city\")\n", - "\n", - "\n", - "tools = [get_weather]\n", - "\n", - "\n", - "# Define the graph\n", - "graph = create_react_agent(model, tools=tools)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Run your graph\n", - "\n", - "Now that we've defined our graph let's run it once and view the trace in LangSmith. In order for our trace to be easily accessible in LangSmith, we will pass in a custom `run_id` in the config.\n", - "\n", - "This assumes that you have set your `LANGSMITH_API_KEY` environment variable.\n", - "\n", - "Note that you can also configure what project to trace to by setting the `LANGCHAIN_PROJECT` environment variable, by default runs will be traced to the `default` project." - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "================================\u001b[1m Human Message \u001b[0m=================================\n", - "\n", - "what is the weather in sf\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "Tool Calls:\n", - " get_weather (call_9ZudXyMAdlUjptq9oMGtQo8o)\n", - " Call ID: call_9ZudXyMAdlUjptq9oMGtQo8o\n", - " Args:\n", - " city: sf\n", - "=================================\u001b[1m Tool Message \u001b[0m=================================\n", - "Name: get_weather\n", - "\n", - "It's always sunny in sf\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "\n", - "The weather in San Francisco is currently sunny.\n" - ] - } - ], - "source": [ - "import uuid\n", - "\n", - "\n", - "def print_stream(stream):\n", - " for s in stream:\n", - " message = s[\"messages\"][-1]\n", - " if isinstance(message, tuple):\n", - " print(message)\n", - " else:\n", - " message.pretty_print()\n", - "\n", - "\n", - "inputs = {\"messages\": [(\"user\", \"what is the weather in sf\")]}\n", - "\n", - "config = {\"run_name\": \"agent_007\", \"tags\": [\"cats are awesome\"]}\n", - "\n", - "print_stream(graph.stream(inputs, config, stream_mode=\"values\"))" - ] - }, - { - "attachments": { - "d38d1f2b-0f4c-4707-b531-a3c749de987f.png": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAABUAAAAHACAIAAADsm1WnAAAAA3NCSVQICAjb4U/gAAAgAElEQVR4XuydB5RURdqGnUTOOUgSBcmgIgiiEiQpiAQRUBFB17y6uuuuYf81u66rrhkUsyhKjiKIBMlBSSIqURBEchjCpP/pqba4dqK7p3ume+btM4fT1K34VN3b96svVEL58pXO0EcEREAEREAEREAEREAEREAEREAERCC2CSTGdvfUOxEQAREQAREQAREQAREQAREQAREQARcBCfBaByIgAiIgAiIgAiIgAiIgAiIgAiIQBwQkwMfBJKmLIiACIiACIiACIiACIiACIiACIiABXmtABERABERABERABERABERABERABOKAgAT4OJgkdVEEREAEREAEREAEREAEREAEREAEJMBrDYiACIiACIiACIiACIiACIiACIhAHBCQAB8Hk6QuioAIiIAIiIAIiIAIiIAIiIAIiIAEeK0BERABERABERABERABERABERABEYgDAhLg42CS1EUREAEREAEREAEREAEREAEREAERkACvNSACIiACIiACIiACIiACIiACIiACcUBAAnwcTJK6KAIiIAIiIAIiIAIiIAIiIAIiIAIS4LUGREAEREAEREAEREAEREAEREAERCAOCEiAj4NJUhdFQAREQAREQAREQAREQAREQAREQAK81oAIiIAIiIAIiIAIiIAIiIAIiIAIxAEBCfBxMEnqogiIgAiIgAiIgAiIgAiIgAiIgAhIgNcaEAEREAEREAEREAEREAEREAEREIE4ICABPg4mSV0UAREQAREQAREQAREQAREQAREQAQnwWgMiIAIiIAIiIAIiIAIiIAIiIAIiEAcEJMDHwSSpiyIgAiIgAiIgAiIgAiIgAiIgAiIgAV5rQAREQAREQAREQAREQAREQAREQATigIAE+DiYJHVRBERABERABERABERABERABERABCTAaw2IgAiIgAiIgAiIgAiIgAiIgAiIQBwQkAAfB5OkLoqACIiACIiACIiACIiACIiACIiABHitAREQAREQAREQAREQAREQAREQARGIAwIS4ONgktRFERABERABERABERABERABERABEZAArzUgAiIgAiIgAiIgAiIgAiIgAiIgAnFAQAJ8HEySuigCIiACIiACIiACIiACIiACIiACEuC1BkRABERABERABERABERABERABEQgDghIgI+DSVIXRUAEREAEREAEREAEREAEREAERCCpWLHioiACIiAC+ZJAuXJle/XqVaFC+S1btubLAWpQIiACIiACIiACIiACBYpAcrRH+9hj/ype3PceQVZWVmrqsd9++239+vULFy5KTU2NdmcKYP2NGjW66aYbwxv4Aw/8Iz093ZTt3r1bx44d+D5v3vyJEyeFV2G8l+ratcvll3diFF9//fX48RPjfTim/xUrVvz73/9mx7Jo0eIxY8YGP7SmTZsOHny9zT9hwsT5878OvnhUcyK9z537VdWqVWnlf/976fHHn4xqc/mj8pIlS7LIu3XrWqdO7UqVKiUkJOzevXvz5i2ffz5jxowvDh8+nD+GqVGIgAiIgAiIgAiIQJwSiLoAf+211/IafVo6x44dGzXq4yeeeEoviKdlFVKGWrVqDh58Q0hFbOYHH3zYCvAXXHC+qef48RMFVoA/77zzDASw5BsBvkyZMs4V0qVL5/HjJ2RkZAS5Zm6//da+ffvYzD/++GPsCPBt2rQx0jvd69u3rwT4wHOalJQ0ZMiN//jHA6VLl3bmhGGzZs169brq4MGDTz/973feeTf45RG4RV0VAREQAREQAREQAREIlUCs+MAXLVp06NCb5s2bc955LUIdg/KLgAhEikCVKlU6deoYZG2lSpW68sorgsyc+9nWrFlz/Phx0+7SpUs9OvD888/NmDGdv4svbpv7fYu1FpOTk99++61nnnnKKb2fdH3SbFe5RIa33hqBqB/Z/lOhmQv+ZVFFtnLVJgIiIAIiIAIiIAL5iUDUNfAhwapR48xRoz5s377Tzp07QyqozP4ILF26rH//Ad5XGzdu/MgjD5l0nxm4lJZ26t3duwal5FcC1103CGPpYEbXp0/vIkWKBJMzT/Js3brtyiuvGjCg/86du0aMeNOjD/Xr1z///PNILFeuXJ50L6Ya/c9/nr3iiu6mS8uXr3jjjeHz5s3bt28/KZUrV77sskvvuOP2hg0b8N8ePa5EjP/rXx+IYP8x1DdzQZ0pKbH1qxTBYaoqERABERABERABEcg5gVx9VcJ9+tln/2M7jW981apVOnbsyItjYqLbFqBChQr/+98L11xzbc7HphogsGfPni+/nO2NwtrGc8lnBu8iSsnfBLZv34G3S7FixXCBxvkZz+fTjve66waaPOvWfdeoUcPT5s/9DN9mf3K/3fhqkUAG118/yPT5lVdeffTRxwlQYofw66+/jh796dix47BZGDjQtRt4442D3333PSY9voap3oqACIiACIiACIhAPiCQqyb0e/fuW7x4if1Dbvzww1FDhgzt2fNqa+kK0w4d2terd04+gKshiEAcEcCx2SjesaYeMOD0O2hI7LhGM8D167//+eef42ik6qoHgb59e5uUVatW/etfjzmld5uTLb+//OX+LVu2kILCvHfvq4VRBERABERABERABEQg9wnkqgbe3/AWL178/PMvPPjgP2wGAp7/8MOP5r+FCqU0bNjIXuIN8sCBA95VIfPbI/H279+/deupU6Nq1qxRrlx5U2Tv3j0//7zdfK9duzax2TCgRU39448/4THrXa13CgalzZs3q1ixQtGixWho+/btK1asLIDW5rzEt2jRHCmucOEi6OjQc1qw3tDOOecccxjBhg0bCFhIhjp16gC/WrVqx48fGz7c07yZDIUKFSIgwtln12Va4bxu3ToERZ+ihXdz9I310LBhw/Lly3O6AR4Za9eu47wD75w+U+rWrcsUU5aQij/99BMWxUG2a2o7++yzMTYmujsOxJBZsmQp0b98NhRTiZguE57w6qt70StU6y+99HLgUQ8a5Fa/T5w4sWXLlkGOpUSJEsx7rVq1ChcuzI3MtAZW5BJBjTuOyrnRuE/5Et7C27x5s5kFmi5b1hVWk9Vr+sxcb9vm3oDYuHGjvziarKgmTZqwKphWOsOq8PkgMnXSSbO7wbaIfbBgJW7WJKH+pk6dFiSxXMhGr0wrU6ZMDdAcMvwHH3xkdPUege68S/Fk4AgMQiQeOXJk06bNK1eucLrT2/zkSWHlJZ9yqm/evDlbvSYDGwpmEVqepMPTXxQ9bj0WGHk8fiYIrc9NTTprgJVgKucRxBrA5is19eiGDT+sXPmNv2q9R6cUERABERABERABEcgrAjEhwDP4yZOnOgV45D1LhKhas2bNsP+96aZhkyZN9ub1+uuvmjfm7NqmoNi3ef72t79ee21/89+PPhr15z/fi7M9Pp8ewbq++279ww8/gp2/d+UmhXhdf/nLPbzE8zbpzHP06NFPP/3sueeeR1rzVzafpXfq1Omppx4/66yz7Lh4z547d959992P47H3YF955SXj49qpU5dNmza98MJ/8aQ1fhMI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dBs/fqIzZKnHdLCKLrusI442zl8Bnhg8fnksOI+i9NdD0lnMPXv2Qp/v8ZOxdes2jnhkru3ZeAEq0SUREAEREAEREAERyCsCCeXLV8qrtsNrF/0MZwURPurAgYObN2/OTZWd6TCaH2z1y5Urh54WE1PcXwljHt5YVCowAdTpKNXLlCmdmnqMPRQc3YMxVMZUu02bizCsxdmVUgsXLmKaAjfkcZWyxF1HnX7o0OEffvjB21o4QG2sT8pSQ8mSJdhTQOzBFN+aAQcoWEAucVoEfGrWrFm4cCFuYUyauYvzduwYBWCYXbp0KUQ7TL79TRYqZdwxWBUIeOzZIY46w7Dn7RAi2zrm6MwRDzqsyk+cOI5SHQMWIomG9LAlOgC4KlWqiJzMDchdwM0YTD8x2q9b9yz+xUcGodpnEe4yDqKnewcPHmL92AB4PjOTiJ0FLjl8wbzi0kvdwTXQ5LNTzE8J88htTqSGkAbory2li4AIiIAIiIAIiEBUCcSfAB9VHKpcBERABEQgnxHwKcDnszFqOCIgAiIgAiIgAgWEQKyY0BcQ3BqmCIiACIiACIiACIiACIiACIiACIRHQAJ8eNxUSgREQAREQAREQAREQAREQAREQARylYAE+FzFrcZEQAREQAREQAREQAREQAREQAREIDwCEuDD46ZSIiACIiACIiACIiACIiACIiACIpCrBCTA5ypuNSYCIiACIiACIiACIiACIiACIiAC4RFQFPrwuKmUCIiACIhAfBAoUaJE7dq16StH0OvUz/iYM/VSBERABERABETADwEJ8H7AKFkEREAEREAEREAEREAEREAEREAEYomATOhjaTbUFxEQAREQAREQAREQAREQAREQARHwQ0ACvB8wShYBERABERABERABERABERABERCBWCIgAT6WZkN9EQEREAEREAEREAEREAEREAEREAE/BCTA+wGjZBEQAREQAREQAREQAREQAREQARGIJQIS4GNpNtQXERABERABERABERABERABERABEfBDQAK8HzBKFgEREAEREAEREAEREAEREAEREIFYIiABPpZmQ30RAREQAREQAREQAREQAREQAREQAT8EJMD7AaNkERABERABERABERABERABERABEYglAhLgY2k21BcREAEREAEREAEREAEREAEREAER8ENAArwfMEoWAREQAREQAREQAREQAREQAREQgVgiIAE+lmZDfREBERABERABERABERABERABERABPwQkwPsBo2QREAEREAEREAEREAEREAEREAERiCUCEuBjaTbUFxEQAREQAREQAREQAREQAREQARHwQ0ACvB8wShYBERABERABERABERABERABERCBWCIgAT6WZkN9EQEREAEREAEREAEREAEREAEREAE/BCTA+wGjZBEQAREQAREQAREQAREQAREQARGIJQIS4GNpNtQXERABERABERABERABERABERABEfBDQAK8HzBKFgEREAEREAEREAEREAEREAEREIFYIiABPpZmQ30RAREQAREQAREQAREQAREQAREQAT8EJMD7AaNkERABERABERABERABERABERABEYglAhLgY2k21BcREAEREAEREAEREAEREAEREAER8ENAArwfMEoWAREQAREQAREQAREQAREQAREQgVgiIAE+lmZDfREBERABERABERABERABERABERABPwQkwPsBo2QREAEREAEREAEREAEREAEREAERiCUCydHrzOq166JXeezX3LRxo9jvpHooAiIgAiIgAiIgAiIgAiIgAiIQLwSkgY+XmVI/RUAEREAEREAEREAEREAEREAECjQBCfAFevo1eBEQAREQAREQAREQAREQAREQgXghIAE+XmZK/RQBERABERABERABERABERABESjQBBLq1ZerdoFeARq8CIiACIiACIiACIiACIiACIhAXBCQBj4upkmdFAEREAEREAEREAEREAEREAERKOgEEsqXr1TQGWj8IiACIiACIiACIiACIiACIiACIhDzBKSBj/kpUgdFQAREQAREQAREQAREQAREQARE4IwzJMBrFYiACIiACIiACIiACIiACIiACIhAHBCQAB8Hk6QuioAIiIAIiIAIiIAIiIAIiIAIiIAEeK0BERABERABERABERABERABERABEYgDAhLg42CS1EUREAEREAEREAEREAEREAEREAERkACvNSACIiACIiACIiACIiACIiACIiACcUBAAnwcTJK6KAIiIAIiIAIiIAIiIAIiIAIiIAIS4LUGREAEREAEREAEREAEREAEREAERCAOCEiAj4NJUhdFQAREQAREQAREQAREQAREQAREQAK81oAIiIAIiIAIiIAIiIAIiIAIiIAIxAEBCfBxMEnqogiIgAiIgAiIgAiIgAiIgAiIgAhIgNcaEAEREAEREAEREAEREAEREAEREIE4ICABPg4mSV0UAREQAREQAREQAREQAREQAREQAQnwWgMiIAIiIAIiIAIiIAIiIAIiIAIiEAcEJMDHwSSpiyIgAiIgAiIgAiIgAiIgAiIgAiIgAV5rQAREQAREQAREQAREQAREQAREQATigIAE+DiYJHVRBERABERABERABERABERABERABCTAaw2IgAiIgAiIgAiIgAiIgAiIgAiIQBwQkAAfB5OkLoqACIiACIiACIiACIiACIiACIiABHitAREQAREQAREQAREQAREQAREQARGIAwIS4ONgktRFERABERABERABERABERABERABEZAArzUgAiIgAiIgAiIgAiIgAiIgAiIgAnFAQAJ8HEySuigCIiACIiACIiACIiACIiACIiACEuC1BkRABERABERABERABERABERABEQgDghIgI+DSVIXRUAEREAEREAEREAEREAEREAEREACvNaACIiACIiACIiACIiACIiACIiACMQBAQnwcTBJ6qIIiIAIiIAIiIAIiIAIiIAIiIAISIDXGhABERABERABERABERABERABERCBOCAgAT4OJkldFAEREAEREAEREAEREAEREAEREAEJ8FoDIiACIiACIiACIiACIiACIiACIhAHBCTAx8EkqYsiIAIiIAIiIAIiIAIiIAIiIAIiIAFea0AEREAEREAEREAEREAEREAEREAE4oCABPg4mCR1UQREQAREQAREQAREQAREQAREQAQkwGsNiIAIiIAIiIAIiIAIiIAIiIAIiEAcEEjO/T4mFEpJKl48qWhRviQmJ5+RkJD7fVCLYRLIyspMT886mZZx7FjG0aN8CbOeUIolJSUXKlQoOSWZT0L2J5TSyisCeUYgK/uTzict/eTJkxkZ6bnQFd0vuQBZTYiACIhAHhLIkx+XPByvmhYBEfAgkFC+fKVcg5JYpEhy2TLJJYrnWotqKKoE0o8cTd9/IPP48Si1gsRetFgxpPco1a9qRSA3CSDDH0tNRZyPUqO6X6IEVtWKgAiIQCwTiPaPSyyPXX0TgYJJIPcE+JTy5VLKlYVyVkZG5omTWSdPZqZnnJGZkZWZVTDRx+OoExITzkhMSkxJSkgplFikcEKiywUjbd/+tL37Ij6cYsWKFy1W1LVgsrIyXErMjMzs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H54feyOQPAKa2U4rOHg8xRs2rM/NJWJPnjNHSRFAAAEEEEAAAQQQ2CmQgQMCCKSIwLZtW/WTIpWlmggggAACCCCAAAIIVD6BiM0MX/loqBECCCCAAAIIIIAAAggggAACiSNAAJ8454KSIIAAAggggAACCCCAAAIIIBBQgAA+IA1vIIAAAggggAACCCCAAAIIIJA4AgTwiXMuKAkCCCCAAAIIIIAAAggggAACAQUI4APS8AYCCCCAAAIIIIAAAggggAACiSNAAJ8454KSIIAAAggggAACCCCAAAIIIBBQgAA+IA1vIIAAAggggAACCCCAAAIIIJA4AgTwiXMuKAkCCCCAAAIIIIAAAggggAACAQUI4APS8AYCCCCAAAIIIIAAAggggAACiSNAAJ8454KSIIAAAggggAACCCCAAAIIIBBQgAA+IA1vIIAAAggggAACCCCAAAIIIJA4AgTwiXMuKAkCCCCAAAIIIIAAAggggAACAQUI4APS8AYCCCCAAAIIIIAAAggggAACiSNAAJ8454KSIIAAAggggAACCCCAAAIIIBBQgAA+IA1vIIAAAggggAACCCCAAAIIIJA4AgTwiXMuKAkCCCCAAAIIIIAAAggggAACAQUI4APS8AYCCCCAAAIIIIAAAggggAACiSNAAJ8454KSIIAAAggggAACCCCAAAIIIBBQgAA+IA1vIIAAAggggAACCCCAAAIIIJA4AgTwiXMuKAkCCCCAAAIIIIAAAggggAACAQUI4APS8AYCCCCAAAIIIIAAAggggAACiSNAAJ8454KSIIAAAggggAACCCCAAAIIIBBQgAA+IA1vIIAAAggggAACCCCAAAIIIJA4AgTwiXMuKAkCCCCAAAIIIIAAAggggAACAQUI4APS8AYCCCCAAAIIIIAAAggggAACiSNAAJ8454KSIIAAAggggAACCCCAAAIIIBBQgAA+IA1vIIAAAggggAACCCCAAAIIIJA4AgTwiXMuKAkCCCCAAAIIIIAAAggggAACAQUI4APS8AYCCCCAAAIIIIAAAggggAACiSNAAJ8454KSIIAAAggggAACCCCAAAIIIBBQIKN6jeoB3+QNBBBAAAEEEEAAAQQQQAABBBBIDAFa4BPjPFAKBBBAAAEEEEAAAQQQQAABBIIKZGzdsjVoAt5EAAEEEEAAAQQQQAABBBBAAIH4C9AC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RfFP9+7dunb9z0EHHVi3bt3c3LzVq1drwPDzz7/w008/2XfxucbqlGnsjxIYGb+ZWxutLwi/Z1Dz2w0YcKa+HRo1aqjyqMxffvnlCy9MXbBgQfBszbvlLViNGjUGDx7YrVvXvfbaq7jY89tvv02f/vYLL7yQn1/6te5zXH1tDR48yPr+WrNmrQbzv/TSVJUzlBIqjU7o5MmT9CER2tVXX+PIv8njj4/Wxi1bNg8adJbPBynIvvpqEF2XLie1bNlSD5U2btyo0zF9+vSZM98N8j1+xBGdevfWt/+h+vbXQVevXvPjjz9qGvn33//AXrDywup2vUePbv3799cJ1dfxqlUrZ8/+QAPQ/v7770BK5Sq/7jH0QVJWvXr1rl+/3siRI/7zn//stlt9fVMfccRRgQ5htgf6BJq/7q+//vqmm27x+8F4/vnnrdbE4IewvxvKR/rGG69v166d9rLuW8aMecz8TWnj5ZdfoRkfQz8iKQMJEMAHkonidsXwF110ib7niOGjqFyZst41elfN0luVblLUHU5dvevGnVYylj59v3TXm7tkVrS0OKPdzn46Ga70pml+nhSoIBHuvF/x2tSuXfu+++459thj7Fnstdfe+tHGc845Z8SIkc4bWcWr9957lxWgal/loxvrE0447oorrs7JyTZfQtWqVXGWrH//vjfddKP5QzbvanI4ffXqpYGRl19+pc/stbqrNrnpy6xlyxaTJk3Ul7TZUffNh+58de/+n/POG7F9+3azfd9991GfdvuhrS/FKlWynUUKskV35+bd9957z+89kEr72Wefd+58tJLpOYg9gA9nX79FEvKQIQPNWy+88JLuVPwmYyMCySugOSXMX2ugcEh/BSZBjRresNZ6Kdh78MH7dBmxtugioxmh9HPGGX2uvPKa//3vfz4saja//vprFYxZ2zVYplWrlvoZNGjQvffeP2nScz676BKkR4ebN286+uijnnji8exsP9eT3r1P0e24ot9rrvmvlpn0ycH5T8U2J5/cRds7dGj34Ycf2xPss88+7dt7b+v10qQbPgG84paTTjpRcaBWmfIbvV955RXnn3+ulaGutJrdunv3rrfccuvLL7/qUxIda/Toh8388OYtrZWtf+pHS2M8+OBD9ieGga6xkvHJ1vlPdSPyewaV8rzzhl122aU+3w6aOE2vCRMm3H33fc7cfLaU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" - } - }, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## View the trace in LangSmith\n", - "\n", - "Now that we've ran our graph, let's head over to LangSmith and view our trace. First click into the project that you traced to (in our case the default project). You should see a run with the custom run name \"agent_007\".\n", - "\n", - "![image.png](attachment:d38d1f2b-0f4c-4707-b531-a3c749de987f.png)" - ] - }, - { - "attachments": { - "410e0089-2ab8-46bb-a61a-827187fd46b3.png": { - "image/png": "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Vy63y6ty5ao33XSrOrR06aIFC76zm61MmbI33zyCQ8eOHV67drXKQ+WkHz9+TAREu9A8SZw8eYKWDj/66OM333zLqjae0EOH3jRnzixkL5abn376Hw899LAbLY4ZM7pZs2YUnDfvex8JiAMGDLjvvnud9G3Xrt2TJ389efJkUUo5oeQPh66++mqkQ3rCm0n37t0XLFjgD72SPggBISAE/JmAP9og7tz5l0JWt25DR+zq1WugDxl/W+WvVy+nhp07dziqStK9RQCJrX37Dqq2sWPtSIfqEBq4Rx99TP2+7rrrypYt460O5HM9uGa//PKLkyZNRG+az00bm6tevcbChT/wveuuuwqwG/7c9Nat25KTk+kh/27b9oc/dzUg+iZTLiBOk3TSHwjExZWPiIhwqSeseVaqVNmlIj7K7I8axCNH/k5IuFSiRPE6deoS9J9dMm0HbxQKq1atHhUVzZKxbba6deupRC102uaRFG8R2LZt26FDf1evXu299z54//33nVSL7u2nnxb169eXPF27dmUl2knmAj/0zDPPrFjxi+5GdHR0hQrlMaa87bYRKEHxtnnhhef/9a9nC6qfUVERjRo1onV6VVB98PN2Dx06iDFDp07t16xZz28/763/d0+mnP+fI+mhPxBgOfSxx55OSIj/+OP3Tpw4YaZLPF9Gj34cAXH69K/Xr19jpojv8vijBpEFu927dzLmyMioKlWq2Q4+NDQE2ZH0PXt28S/2iHXq5AiCVpnr1q1PSlpa6t69e2zrkRSvE+jatVuNGrWcS4eq0RUrctxTGjZ0qCf2evfcq/DcufM42ejP3r17f/11DbaV118/SFmz4Zddo0ZN9yqXUvlD4MCB/VOnTuff/GlOWhECQkAInDhx7MyZMyVKxDz00D8qVKiYJxCkw1GjHkM6TElJ9oeblT8KiEDctStnldnu8nGNGrXDwsLJtmHDWqVftJutXLkKpUqVJhvSYUZGep7nJt8yIODyybfm/LOhM2fOqo6VKROoS8zoQceNG6dGMWSIxWpWPkJACNglEB4eFhrqjwtWdnsriULAKwRSU1PRHZ49e7Z48eKjRz+BTOKkWlZNH3roicqVq6SkpHz66YcnTx53kjl/DvnpFWsUEPFBsWKhLQtRNOJ9UqVKdbsCYr16FvUhH12bLVPWpq+6qluLFm0IgYGseerUyd9+27Bq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FNFRXJb0UHGDCWMXSYAESIAEbCagRQERgwoPf/X27Vus6CVNlpR6RJtnmRVYTwCXHy5CXIq4IHFZWl8RS5IACZAACZCA+xDQrn7u5YsXwJggQYIkH3zw5jWO8OjoGPcBy566PQF4pcDuUKwsQzoUF6Tbj4oDIAESIAESIAELCGhXQETn8UqOjooODArESzpBwoQRb9++0x2RMTFRMZQVLZhdZokrAeyVgmjYiHeIiDbwWYbiEDVgZZm6w7iSZH4SIAESIAG3JqBpARFk8WKOiHgbGBSElT7IiPjPrXGz8+5FAD7LkA1pd+hes8bekgAJkAAJ2E5A6wIiRojX84vnz+EoABnRz98PB/Q6QrVj+/hZAwkYEsA2ejhwySEaNiPa8NogARIgARLwWgJuICCKuUHwudevI+PpnJt5kAAJkAAJkAAJkAAJOJCARr2YHThiVk0CJEACJEACJEACJKBKgAKiKh6eJAESIAESIAESIAHvI0AB0fvmnCMmARIgARIgARIgAVUCFBBV8fAkCZAACZAACZAACXgfAQqI3jfnHDEJkAAJkAAJkAAJqBKggKiKhydJgARIgARIgARIwPsIUED0vjnniEmABEiABEiABEhAlQAFRFU8PEkCJEACJEACJEAC3keAAqL3zTlHTAIkQAIkQAIkQAKqBCggquLhSRIgARIgARIgARLwPgIUEL1vzjliEiABEiABEiABElAlQAFRFQ9PkgAJkAAJkAAJkID3EaCA6H1zzhGTAAmQAAmQAAmQgCoBCoiqeHiSBEiABEiABEiABLyPAAVE75tzjpgESIAESIAESIAEVAlQQFTFw5MkQAIkQAIkQAIk4H0EKCB635xzxCRAAiRAAiRAAiSgSoACoioeniQBEiABEiABEiAB7yNAAdH75pwjJgESIAESIAESIAFVAhQQVfHwJAmQAAmQAAmQAAl4HwEKiN435xwxCZAACZAACZAACagSoICoiocnSYAESIAESIAESMD7CFBA9L4554hJgARIgARIgARIQJUABURVPDxJAiRAAiRAAiRAAt5HgAKi9805R0wCJEACJEACJEACqgQoIKri4UkSIAESIAESIAES8D4CFBC9b845YhIgARIgARIgARJQJUABURUPT5IACZAACZAACZCA9xGggOh9c84RkwAJkAAJkAAJkIAqAQqIqnh4kgRIgARI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CZAACSgRKFy48Lp1a5TOMC1elizZjCggnp1Yql6/fpMkHd648X6h+dix440bN3EaOwqIVqI2Mk+0shanFIP/FCw/KlWq2KdPbzSIwI2bN29xSstshARIgARIgARIQI0AAuU8efIE/i7YnQX54LmMaHpqBZx1jgKis0i7qB24hP/663apcdjGYuvxOBlEuqjjbJYESIAESIAEPJwAdl5BbDv4NkjjnD595rVrf2ph2BQQtTALDuwDdgSSaoc/zaBBg/fu1UWZ4kECJEACJEACDiVw6tQp+UKqQ1t0u8qxrCxJh9DdTJs2Y8KECYajcCFACohudznFrcObN2++ffs2grbfuXMHuwDBMz9u5ZmbBEiABEiABEjAMQT+/POvjh07JUuWDJ7OR48etTGYnX37SC9m+/JkbSRAAiRAAiRAAiTgBgTUvZi1GCjbDaCyiyRAAiRAAiRAAiTguQQoIHru3HJkJEACJEACJEACJGAVAQqIVmFjIRIgARIgARIgARLwXAIUED13bjkyEiABEiABEiABErCKAAVEq7CxEAmQAAmQAAmQAAl4LgEKiJ47txwZCZAACZAACZAACVhFgAKiVdhYiARIgARIgARIgAQ8lwAFRM+dW46MBEiABEiABEiABKwiQAHRKmwsRAIkQAIkQAIkQAKeS4ACoufOLUdGAiRAAiRAAiRAAlYRoIBoFTYWIgESIAESIAESIAHPJUAB0XPnliMjARIgARIgARIgAasIUEC0ChsLkQAJkAAJkAAJkIDnEqCA6Llzy5GRAAmQAAmQAAmQgFUEKCBahY2FSIAESIAESIAESMBzCVBA9Ny55chIgARIgARIgARIwCoCFBCtwsZCJEACJEACJEACJOC5BCggeu7ccmQkQAIkQAIkQAIkYBUBCohWYWMhEiABEiABEiABEvBcAhQQPXduOTISIAESIAESIAESsIoABUSrsLEQCZAACZAACZAACXguAT93GZqvr19AQICfvx8OH/3hLj1nP0mABEiABEiABEhAhUCM/ojE8S4yIiIiKipSJbNzTrmBgAiJMDAoCNKhc4iwFRIgARIgARIgARJwJgGh+YKogyMoURBkxNfh4RAXndkHo7a0LiAGBSUKDApEpyFZR7x9+053RMbERMXEuBAamyYBEiABEiABEiABuxHAsqiPj6+/v5+/v39AggRCUnwdDinx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vNxYE1H8uF1jDyYYmZOaDx/cVzk526sWMc1WBERABOrU8QTwmdfGjRsXLFhIpptgj9qrxhgjTiByL00yGksjGnW4cGFkbsCdJ9cg72r8iEfO0pCJFZOpJ3IQaqUiIAIRRAA5OG/evD17solKrgZHJ5f7nYtEgQhENKLJiUjuj/vvfyBS1WG5P07qUAREQAREQASqDIF//vPFKjPXSp9ohApEOH9W9Kp04BpQBERABERABERABMKdQMnhWuE+U81PBERABERABERABESgUghIIFYKZg0iAiIgAiIgAiIgAlWHgARi1blXmqkIiIAIiIAIiIAIVAoBCcRKwaxBREAEREAEREAERKDqEJBArDr3SjMVAREQAREQAREQgUohIIFYKZg1iAiIgAiIgAiIgAhUHQISiFXnXmmmIiACIiACIiACIlApBCQQKwWzBhEBERABERABERCBqkMg7ATi+fPnoRcVVXUQaqYiIAIiIAIiIAIiUGEEjCgyAqnCBvHuOGwFYrT3TPW3CIiACIiACIiACEQegagojyiKdIFYWFgIhdjYyD0DMPKefK1YBERABERABETAJwEjioxA8lmpvC+EnQWx8IwRiLHlvVL1JwIiIAIiIAIiIAJVj0BsrEcUGYFUabMPO4FYUFDA4uPi42vWlB9ipT0GGkgEREAEREAERCAcCSCHEEXMzAikSpti2AnEs2cLQRAVFZWYmFRpFDSQCIiACIiACIiACIQhAeQQoghphECqzOmFnUBk8Xm5ufw3ITExLi6uMlloLBEQAREQAREQAREIHwIIIeQQ8zHSqDInFo4CETfMvNw8KNRKSYmOVrRKZT4PGksEREAEREAERCAsCCCBEEJMBVFUyREqDBqOApFp5eaeys/Px6Zap24d2RHD4jnVJERABERABERABCqLAOIHCYQQQg4hiipr2JJxwtc+dzInh2nGx8en1K59Oo9X7rlznhzaeomACIiACIiACIhAdSVAVAp+h2ZnGXVo5FDlLzZ8BSIsgHLu7LnEpEQwxSckFOTnn/G8Cs+fP1t03opeIiACIiACIiACIlDlCXBWCtmwyXdIRhtiljEcsiR2li+J7dDQDGuByBRBU1CQn5iUhK0Vjci7yj8FWoAIiIAIiIAIiIAI+CZAzDLasPL9Du0zCneByFwBXtW3OQAAIABJREFUlHPiBK6aaMSY2Bhe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iIAIiIAIiIAIhCEBI96MkHOdXpkEYkFBPp3GxcfXrCk/RFe8KhQBERABERABERCB8CKAbEO8MScj5FwnVyaBePbsWbqOiopKTExy7V2FIiACIiACIiACIiACYUUA2YZ4Q8Ih5HxNrEwCkU5zT+Xy34TExLi4OF9jqFwEREAEREAEREAERCAcCCDYkG3MxEg4X1MKQSBetJtcWFhoBqiVkhIdrWgVX5xVLgIiIAIiIAIiIAKXmABSDcHGJBBvSLiLZ3ORwItOSkoOdrJeiQ/PnCmIjvG84hPisVX6MVcGO5Dqi4AIiIAIiIAIiIAIlAsBbIe169Rmczk/P//UyRwSFVrdFkm7MgtExyyjCvJPF2tEAlaios6eLSxKoa2XCIiACIiACIiACIjAJSZAVAoGweRatYw6zDlx3EsOVpBA9Cw7/3R+VI2o2LjYmNjYhITE6OhoJlEkEyUVL/FjoeFFQAREQAREQAQijQCar2bNaKyGiYmJybVSTF4bdpZP5uQ45aBLSf36jYJH5no0i6cwJiY2KTkpvih2Wi8REAEREAEREAEREIFwIMC2cpHf4RmnFmR6zsKokAQiXfnUiFzDBTI+Pi42Li4mBjsie87KkhgOz4bmIAIiIAIiIAIiECkEEGqcpMdZKWfIZ5NfgPsfK3cKQV+F5Rx3zMDYEZlEbm5hjVxPBpyil3aZL5DQ/xcBERABERABERCByiDgbZ4Lyl4XskAs8jD0Fn5FMTA+yt1QeLd3q6MyERABERABERABERABXwS8haBrPVfbITV9lYcsED19+jANerQjlx3y0TnhgJbkbKYSERABERABERABERCBQAhcMBz6El3u5SEkyi6ZjG/nQmNKNLI0kMmrjgiIgAiIgAiIgAiIQHkSQBr6V4e+hVyNslgQPWswToduqykWpEUzK2UrOQBbo9sIKhMBERABERABERCBiCQQgEOhu2nQouW/h7IKRI9EdHE69LpXXlP01ov+pxiR912LFgEREAEREAEREIGgCJSiCO19FUkvf/XLLhA9AwTsdGjm5m9CQZFQZREQAREQAREQAREQgcAJ+N90tvopkw+ibTZFQlTCL/D7o5oiIAIiIAIiIAIiULkEAlSHTKpcLIhmcUYjBhi/XLk8NJoIiIAIiIAIiIAIRDCBwKWhgVSOAtF0KJkYwU+fli4CIiACIiACIhBmBIKVhmb65S4QTbclMtH8rTjlMHtaNB0REAEREAEREIFqS+Bir79QXAArSCAa4iUTMlEs1fY+aGEiIAIiIAIiIAIiEEYEQhGF9ulXqEC0D1TWiYYRc01FBERABERABERABKo1gfKKYq7WkLQ4ERABERABERABEYgkAhKIkXS3tVYREAEREAEREAERCICABGIAkFRFBERABERABERABCKJgARiJN1trVUEREAEREAEREAEAiAggRgAJFURAREQAREQAREQgUgi8P8DjezhV1S5aa0AAAAASUVORK5CYII=" - } - }, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In addition, you will be able to filter traces after the fact using the tags or metadata provided. For example,\n", - "\n", - "![image.png](attachment:410e0089-2ab8-46bb-a61a-827187fd46b3.png)\n" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.4" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/docs/docs/how-tos/run-id-langsmith.md b/docs/docs/how-tos/run-id-langsmith.md new file mode 100644 index 000000000..0cd87e864 --- /dev/null +++ b/docs/docs/how-tos/run-id-langsmith.md @@ -0,0 +1,155 @@ +# How to pass custom run ID or set tags and metadata for graph runs in LangSmith + +!!! tip "Prerequisites" + This guide assumes familiarity with the following: + + - [LangSmith Documentation](https://docs.smith.langchain.com) + - [LangSmith Platform](https://smith.langchain.com) + - [RunnableConfig](https://api.python.langchain.com/en/latest/runnables/langchain_core.runnables.config.RunnableConfig.html#langchain_core.runnables.config.RunnableConfig) + - [Add metadata and tags to traces](https://docs.smith.langchain.com/how_to_guides/tracing/trace_with_langchain#add-metadata-and-tags-to-traces) + - [Customize run name](https://docs.smith.langchain.com/how_to_guides/tracing/trace_with_langchain#customize-run-name) + +Debugging graph runs can sometimes be difficult to do in an IDE or terminal. [LangSmith](https://docs.smith.langchain.com) lets you use trace data to debug, test, and monitor your LLM apps built with LangGraph — read the [LangSmith documentation](https://docs.smith.langchain.com) for more information on how to get started. + +To make it easier to identify and analyzed traces generated during graph invocation, you can set additional configuration at run time (see [RunnableConfig](https://api.python.langchain.com/en/latest/runnables/langchain_core.runnables.config.RunnableConfig.html#langchain_core.runnables.config.RunnableConfig)): + +| **Field** | **Type** | **Description** | +|-------------|---------------------|--------------------------------------------------------------------------------------------------------------------| +| run_name | `str` | Name for the tracer run for this call. Defaults to the name of the class. | +| run_id | `UUID` | Unique identifier for the tracer run for this call. If not provided, a new UUID will be generated. | +| tags | `List[str]` | Tags for this call and any sub-calls (e.g., a Chain calling an LLM). You can use these to filter calls. | +| metadata | `Dict[str, Any]` | Metadata for this call and any sub-calls (e.g., a Chain calling an LLM). Keys should be strings, values should be JSON-serializable. | + +LangGraph graphs implement the [LangChain Runnable Interface](https://python.langchain.com/api_reference/core/runnables/langchain_core.runnables.base.Runnable.html) and accept a second argument (`RunnableConfig`) in methods like `invoke`, `ainvoke`, `stream` etc. + +The LangSmith platform will allow you to search and filter traces based on `run_name`, `run_id`, `tags` and `metadata`. + +## TLDR + +```python +import uuid +# Generate a random UUID -- it must be a UUID +config = {"run_id": uuid.uuid4()}, "tags": ["my_tag1"], "metadata": {"a": 5}} +# Works with all standard Runnable methods +# like invoke, batch, ainvoke, astream_events etc +graph.stream(inputs, config, stream_mode="values") +``` + +The rest of the how to guide will show a full agent. + +## Setup + +First, let's install the required packages and set our API keys + +```python +%%capture --no-stderr +%pip install --quiet -U langgraph langchain_openai +``` + +```python +import getpass +import os + + +def _set_env(var: str): + if not os.environ.get(var): + os.environ[var] = getpass.getpass(f"{var}: ") + + +_set_env("OPENAI_API_KEY") +_set_env("LANGSMITH_API_KEY") +``` + +!!! tip + Sign up for LangSmith to quickly spot issues and improve the performance of your LangGraph projects. [LangSmith](https://docs.smith.langchain.com) lets you use trace data to debug, test, and monitor your LLM apps built with LangGraph — read more about how to get started [here](https://docs.smith.langchain.com). + +## Define the graph + +For this example we will use the [prebuilt ReAct agent](https://langchain-ai.github.io/langgraph/how-tos/create-react-agent/). + +```python +from langchain_openai import ChatOpenAI +from typing import Literal +from langgraph.prebuilt import create_react_agent +from langchain_core.tools import tool + +# First we initialize the model we want to use. +model = ChatOpenAI(model="gpt-4o", temperature=0) + + +# For this tutorial we will use custom tool that returns pre-defined values for weather in two cities (NYC & SF) +@tool +def get_weather(city: Literal["nyc", "sf"]): + """Use this to get weather information.""" + if city == "nyc": + return "It might be cloudy in nyc" + elif city == "sf": + return "It's always sunny in sf" + else: + raise AssertionError("Unknown city") + + +tools = [get_weather] + + +# Define the graph +graph = create_react_agent(model, tools=tools) +``` + +## Run your graph + +Now that we've defined our graph let's run it once and view the trace in LangSmith. In order for our trace to be easily accessible in LangSmith, we will pass in a custom `run_id` in the config. + +This assumes that you have set your `LANGSMITH_API_KEY` environment variable. + +Note that you can also configure what project to trace to by setting the `LANGCHAIN_PROJECT` environment variable, by default runs will be traced to the `default` project. + +```python +import uuid + + +def print_stream(stream): + for s in stream: + message = s["messages"][-1] + if isinstance(message, tuple): + print(message) + else: + message.pretty_print() + + +inputs = {"messages": [("user", "what is the weather in sf")]} + +config = {"run_name": "agent_007", "tags": ["cats are awesome"]} + +print_stream(graph.stream(inputs, config, stream_mode="values")) +``` + +**Output:** +``` +================================ Human Message ================================== + +what is the weather in sf +================================== Ai Message =================================== +Tool Calls: + get_weather (call_9ZudXyMAdlUjptq9oMGtQo8o) + Call ID: call_9ZudXyMAdlUjptq9oMGtQo8o + Args: + city: sf +================================= Tool Message ================================== +Name: get_weather + +It's always sunny in sf +================================== Ai Message =================================== + +The weather in San Francisco is currently sunny. +``` + +## View the trace in LangSmith + +Now that we've ran our graph, let's head over to LangSmith and view our trace. First click into the project that you traced to (in our case the default project). You should see a run with the custom run name "agent_007". + +![LangSmith Trace View](assets/d38d1f2b-0f4c-4707-b531-a3c749de987f.png) + +In addition, you will be able to filter traces after the fact using the tags or metadata provided. For example, + +![LangSmith Filter View](assets/410e0089-2ab8-46bb-a61a-827187fd46b3.png) \ No newline at end of file diff --git a/docs/docs/tutorials/multi_agent/agent_supervisor.ipynb b/docs/docs/tutorials/multi_agent/agent_supervisor.ipynb deleted file mode 100644 index 2303872ef..000000000 --- a/docs/docs/tutorials/multi_agent/agent_supervisor.ipynb +++ /dev/null @@ -1,1403 +0,0 @@ -{ - "cells": [ - { - "attachments": { - "8ee0a8ce-f0a8-4019-b5bf-b20933e40956.png": { - "image/png": "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" - } - }, - "cell_type": "markdown", - "id": "a3e3ebc4-57af-4fe4-bdd3-36aff67bf276", - "metadata": {}, - "source": [ - "# Multi-agent supervisor\n", - "\n", - "[**Supervisor**](../../../concepts/multi_agent#supervisor) is a multi-agent architecture where **specialized** agents are coordinated by a central **supervisor agent**. The supervisor agent controls all communication flow and task delegation, making decisions about which agent to invoke based on the current context and task requirements.\n", - "\n", - "In this tutorial, you will build a supervisor system with two agents — a research and a math expert. By the end of the tutorial you will:\n", - "\n", - "1. Build specialized research and math agents\n", - "2. Build a supervisor for orchestrating them with the prebuilt [`langgraph-supervisor`](https://langchain-ai.github.io/langgraph/agents/multi-agent/#supervisor)\n", - "3. Build a supervisor from scratch\n", - "4. Implement advanced task delegation\n", - "\n", - "![diagram](attachment:8ee0a8ce-f0a8-4019-b5bf-b20933e40956.png)\n", - "\n", - "## Setup\n", - "\n", - "First, let's install required packages and set our API keys" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "0d30b6f7-3bec-4d9f-af50-43dfdc81ae6c", - "metadata": {}, - "outputs": [], - "source": [ - "%%capture --no-stderr\n", - "%pip install -U langgraph langgraph-supervisor langchain-tavily \"langchain[openai]\"" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "c84adef6-51b3-46c5-8490-c2a1ad967769", - "metadata": {}, - "outputs": [], - "source": [ - "import getpass\n", - "import os\n", - "\n", - "\n", - "def _set_if_undefined(var: str):\n", - " if not os.environ.get(var):\n", - " os.environ[var] = getpass.getpass(f\"Please provide your {var}\")\n", - "\n", - "\n", - "_set_if_undefined(\"OPENAI_API_KEY\")\n", - "_set_if_undefined(\"TAVILY_API_KEY\")" - ] - }, - { - "cell_type": "markdown", - "id": "be85e3ad", - "metadata": {}, - "source": [ - "
\n", - "

Set up LangSmith for LangGraph development

\n", - "

\n", - " Sign up for LangSmith to quickly spot issues and improve the performance of your LangGraph projects. LangSmith lets you use trace data to debug, test, and monitor your LLM apps built with LangGraph — read more about how to get started here. \n", - "

\n", - "
" - ] - }, - { - "cell_type": "markdown", - "id": "349a5673-962e-4de9-ac19-70ee426ef433", - "metadata": {}, - "source": [ - "## 1. Create worker agents" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "ad822cf5-56d4-47f7-ad64-d9fd3f57551e", - "metadata": {}, - "source": [ - "First, let's create our specialized worker agents — research agent and math agent:\n", - "\n", - "* Research agent will have access to a web search tool using [Tavily API](https://tavily.com/)\n", - "* Math agent will have access to simple math tools (`add`, `multiply`, `divide`)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "5e34989a-8989-432e-b6aa-8de91ab83372", - "metadata": {}, - "source": [ - "### Research agent\n", - "\n", - "For web search, we will use `TavilySearch` tool from `langchain-tavily`:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "0fdc7345-2967-484b-881a-114dfac3f534", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Find events, attractions, deals, and more at nyctourism.com Skip Main Navigation Menu The Official Website of the City of New York Text Size Powered by Translate SearchSearch Primary Navigation The official website of NYC Home NYC Resources NYC311 Office of the Mayor Events Connect Jobs Search Office of the Mayor | Mayor's Bio | City of New York Secondary Navigation MayorBiographyNewsOfficials Eric L. Adams 110th Mayor of New York City Mayor Eric Adams has served the people of New York City as an NYPD officer, State Senator, Brooklyn Borough President, and now as the 110th Mayor of the City of New York. Mayor Eric Adams has served the people of New York City as an NYPD officer, State Senator, Brooklyn Borough President, and now as the 110th Mayor of the City of New York. He gave voice to a diverse coalition of working families in all five boroughs and is leading the fight to bring back New York City’s economy, reduce inequality, improve public safety, and build a stronger, healthier city that delivers for all New Yorkers. As the representative of one of the nation’s largest counties, Eric fought tirelessly to grow the local economy, invest in schools, reduce inequality, improve public safety, and advocate for smart policies and better government that delivers for all New Yorkers.\n" - ] - } - ], - "source": [ - "from langchain_tavily import TavilySearch\n", - "\n", - "web_search = TavilySearch(max_results=3)\n", - "web_search_results = web_search.invoke(\"who is the mayor of NYC?\")\n", - "\n", - "print(web_search_results[\"results\"][0][\"content\"])" - ] - }, - { - "cell_type": "markdown", - "id": "cc899eb6-b08e-41b8-b92b-75908c44e8b0", - "metadata": {}, - "source": [ - "To create individual worker agents, we will use LangGraph's prebuilt [agent](../../../agents/agents#basic-configuration)." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "15e179e4-1a49-4c76-9235-0ca989eb0d2d", - "metadata": {}, - "outputs": [], - "source": [ - "from langgraph.prebuilt import create_react_agent\n", - "\n", - "research_agent = create_react_agent(\n", - " model=\"openai:gpt-4.1\",\n", - " tools=[web_search],\n", - " prompt=(\n", - " \"You are a research agent.\\n\\n\"\n", - " \"INSTRUCTIONS:\\n\"\n", - " \"- Assist ONLY with research-related tasks, DO NOT do any math\\n\"\n", - " \"- After you're done with your tasks, respond to the supervisor directly\\n\"\n", - " \"- Respond ONLY with the results of your work, do NOT include ANY other text.\"\n", - " ),\n", - " name=\"research_agent\",\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "023ae2f2-517b-4611-a0ca-506b8c0b734e", - "metadata": {}, - "source": [ - "Let's [run the agent](../../../agents/run_agents) to verify that it behaves as expected. \n", - "\n", - "\n", - "??? note \"We'll use `pretty_print_messages` helper to render the streamed agent outputs nicely\"\n", - "\n", - " ```python\n", - " from langchain_core.messages import convert_to_messages\n", - " \n", - " \n", - " def pretty_print_message(message, indent=False):\n", - " pretty_message = message.pretty_repr(html=True)\n", - " if not indent:\n", - " print(pretty_message)\n", - " return\n", - " \n", - " indented = \"\\n\".join(\"\\t\" + c for c in pretty_message.split(\"\\n\"))\n", - " print(indented)\n", - " \n", - " \n", - " def pretty_print_messages(update, last_message=False):\n", - " is_subgraph = False\n", - " if isinstance(update, tuple):\n", - " ns, update = update\n", - " # skip parent graph updates in the printouts\n", - " if len(ns) == 0:\n", - " return\n", - " \n", - " graph_id = ns[-1].split(\":\")[0]\n", - " print(f\"Update from subgraph {graph_id}:\")\n", - " print(\"\\n\")\n", - " is_subgraph = True\n", - " \n", - " for node_name, node_update in update.items():\n", - " update_label = f\"Update from node {node_name}:\"\n", - " if is_subgraph:\n", - " update_label = \"\\t\" + update_label\n", - " \n", - " print(update_label)\n", - " print(\"\\n\")\n", - " \n", - " messages = convert_to_messages(node_update[\"messages\"])\n", - " if last_message:\n", - " messages = messages[-1:]\n", - " \n", - " for m in messages:\n", - " pretty_print_message(m, indent=is_subgraph)\n", - " print(\"\\n\")\n", - " ```" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "bfaa81e6", - "metadata": {}, - "outputs": [], - "source": [ - "# hide-cell\n", - "from langchain_core.messages import convert_to_messages\n", - "\n", - "\n", - "def pretty_print_message(message, indent=False):\n", - " pretty_message = message.pretty_repr(html=True)\n", - " if not indent:\n", - " print(pretty_message)\n", - " return\n", - "\n", - " indented = \"\\n\".join(\"\\t\" + c for c in pretty_message.split(\"\\n\"))\n", - " print(indented)\n", - "\n", - "\n", - "def pretty_print_messages(update, last_message=False):\n", - " is_subgraph = False\n", - " if isinstance(update, tuple):\n", - " ns, update = update\n", - " # skip parent graph updates in the printouts\n", - " if len(ns) == 0:\n", - " return\n", - "\n", - " graph_id = ns[-1].split(\":\")[0]\n", - " print(f\"Update from subgraph {graph_id}:\")\n", - " print(\"\\n\")\n", - " is_subgraph = True\n", - "\n", - " for node_name, node_update in update.items():\n", - " update_label = f\"Update from node {node_name}:\"\n", - " if is_subgraph:\n", - " update_label = \"\\t\" + update_label\n", - "\n", - " print(update_label)\n", - " print(\"\\n\")\n", - "\n", - " messages = convert_to_messages(node_update[\"messages\"])\n", - " if last_message:\n", - " messages = messages[-1:]\n", - "\n", - " for m in messages:\n", - " pretty_print_message(m, indent=is_subgraph)\n", - " print(\"\\n\")" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "71474c5b-6a9b-460e-bf30-77831976aaf9", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Update from node agent:\n", - "\n", - "\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "Name: research_agent\n", - "Tool Calls:\n", - " tavily_search (call_U748rQhQXT36sjhbkYLSXQtJ)\n", - " Call ID: call_U748rQhQXT36sjhbkYLSXQtJ\n", - " Args:\n", - " query: current mayor of New York City\n", - " search_depth: basic\n", - "\n", - "\n", - "Update from node tools:\n", - "\n", - "\n", - "=================================\u001b[1m Tool Message \u001b[0m=================================\n", - "Name: tavily_search\n", - "\n", - "{\"query\": \"current mayor of New York City\", \"follow_up_questions\": null, \"answer\": null, \"images\": [], \"results\": [{\"title\": \"List of mayors of New York City - Wikipedia\", \"url\": \"https://en.wikipedia.org/wiki/List_of_mayors_of_New_York_City\", \"content\": \"The mayor of New York City is the chief executive of the Government of New York City, as stipulated by New York City's charter.The current officeholder, the 110th in the sequence of regular mayors, is Eric Adams, a member of the Democratic Party.. During the Dutch colonial period from 1624 to 1664, New Amsterdam was governed by the Director of New Netherland.\", \"score\": 0.9039154, \"raw_content\": null}, {\"title\": \"Office of the Mayor | Mayor's Bio | City of New York - NYC.gov\", \"url\": \"https://www.nyc.gov/office-of-the-mayor/bio.page\", \"content\": \"Mayor Eric Adams has served the people of New York City as an NYPD officer, State Senator, Brooklyn Borough President, and now as the 110th Mayor of the City of New York. He gave voice to a diverse coalition of working families in all five boroughs and is leading the fight to bring back New York City's economy, reduce inequality, improve\", \"score\": 0.8405867, \"raw_content\": null}, {\"title\": \"Eric Adams - Wikipedia\", \"url\": \"https://en.wikipedia.org/wiki/Eric_Adams\", \"content\": \"Eric Leroy Adams (born September 1, 1960) is an American politician and former police officer who has served as the 110th mayor of New York City since 2022. Adams was an officer in the New York City Transit Police and then the New York City Police Department (NYPD) for more than 20 years, retiring at the rank of captain.He served in the New York State Senate from 2006 to 2013, representing the\", \"score\": 0.77731717, \"raw_content\": null}], \"response_time\": 1.81}\n", - "\n", - "\n", - "Update from node agent:\n", - "\n", - "\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "Name: research_agent\n", - "\n", - "The current mayor of New York City is Eric Adams.\n", - "\n", - "\n" - ] - } - ], - "source": [ - "for chunk in research_agent.stream(\n", - " {\"messages\": [{\"role\": \"user\", \"content\": \"who is the mayor of NYC?\"}]}\n", - "):\n", - " pretty_print_messages(chunk)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "95e76c28-e9c9-42b7-8381-5e2a07f900cb", - "metadata": {}, - "source": [ - "### Math agent\n", - "\n", - "For math agent tools we will use [vanilla Python functions](../../../agents/tools#define-simple-tools):" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "95910bb8-7144-4015-9ea4-d97d0c22db12", - "metadata": {}, - "outputs": [], - "source": [ - "def add(a: float, b: float):\n", - " \"\"\"Add two numbers.\"\"\"\n", - " return a + b\n", - "\n", - "\n", - "def multiply(a: float, b: float):\n", - " \"\"\"Multiply two numbers.\"\"\"\n", - " return a * b\n", - "\n", - "\n", - "def divide(a: float, b: float):\n", - " \"\"\"Divide two numbers.\"\"\"\n", - " return a / b\n", - "\n", - "\n", - "math_agent = create_react_agent(\n", - " model=\"openai:gpt-4.1\",\n", - " tools=[add, multiply, divide],\n", - " prompt=(\n", - " \"You are a math agent.\\n\\n\"\n", - " \"INSTRUCTIONS:\\n\"\n", - " \"- Assist ONLY with math-related tasks\\n\"\n", - " \"- After you're done with your tasks, respond to the supervisor directly\\n\"\n", - " \"- Respond ONLY with the results of your work, do NOT include ANY other text.\"\n", - " ),\n", - " name=\"math_agent\",\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "0df97bc0-f38b-4893-a135-c16cecbfa759", - "metadata": {}, - "source": [ - "Let's run the math agent:" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "f803943c-6dd2-4b42-93ba-0210ec276132", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Update from node agent:\n", - "\n", - "\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "Name: math_agent\n", - "Tool Calls:\n", - " add (call_p6OVLDHB4LyCNCxPOZzWR15v)\n", - " Call ID: call_p6OVLDHB4LyCNCxPOZzWR15v\n", - " Args:\n", - " a: 3\n", - " b: 5\n", - "\n", - "\n", - "Update from node tools:\n", - "\n", - "\n", - "=================================\u001b[1m Tool Message \u001b[0m=================================\n", - "Name: add\n", - "\n", - "8.0\n", - "\n", - "\n", - "Update from node agent:\n", - "\n", - "\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "Name: math_agent\n", - "Tool Calls:\n", - " multiply (call_EoaWHMLFZAX4AkajQCtZvbli)\n", - " Call ID: call_EoaWHMLFZAX4AkajQCtZvbli\n", - " Args:\n", - " a: 8\n", - " b: 7\n", - "\n", - "\n", - "Update from node tools:\n", - "\n", - "\n", - "=================================\u001b[1m Tool Message \u001b[0m=================================\n", - "Name: multiply\n", - "\n", - "56.0\n", - "\n", - "\n", - "Update from node agent:\n", - "\n", - "\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "Name: math_agent\n", - "\n", - "56\n", - "\n", - "\n" - ] - } - ], - "source": [ - "for chunk in math_agent.stream(\n", - " {\"messages\": [{\"role\": \"user\", \"content\": \"what's (3 + 5) x 7\"}]}\n", - "):\n", - " pretty_print_messages(chunk)" - ] - }, - { - "cell_type": "markdown", - "id": "dceefc4c-95e1-4565-8946-4c113a11416a", - "metadata": {}, - "source": [ - "## 2. Create supervisor with `langgraph-supervisor`" - ] - }, - { - "cell_type": "markdown", - "id": "eb5637a4-8ecb-4c2c-82f5-3674205e37b5", - "metadata": {}, - "source": [ - "To implement out multi-agent system, we will use [`create_supervisor`][langgraph_supervisor.supervisor.create_supervisor] from the prebuilt `langgraph-supervisor` library:" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "6f32a820-1f3d-4698-831b-46252e2316bc", - "metadata": {}, - "outputs": [], - "source": [ - "from langgraph_supervisor import create_supervisor\n", - "from langchain.chat_models import init_chat_model\n", - "\n", - "supervisor = create_supervisor(\n", - " model=init_chat_model(\"openai:gpt-4.1\"),\n", - " agents=[research_agent, math_agent],\n", - " prompt=(\n", - " \"You are a supervisor managing two agents:\\n\"\n", - " \"- a research agent. Assign research-related tasks to this agent\\n\"\n", - " \"- a math agent. Assign math-related tasks to this agent\\n\"\n", - " \"Assign work to one agent at a time, do not call agents in parallel.\\n\"\n", - " \"Do not do any work yourself.\"\n", - " ),\n", - " add_handoff_back_messages=True,\n", - " output_mode=\"full_history\",\n", - ").compile()" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "4c45a3c2-4d9e-4760-87bc-3cc2c007a167", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "from IPython.display import display, Image\n", - "\n", - "display(Image(supervisor.get_graph().draw_mermaid_png()))" - ] - }, - { - "cell_type": "markdown", - "id": "3a94c3d1-3617-4d68-ac9a-b9bb2c05a604", - "metadata": {}, - "source": [ - "Let's now run it with a query that requires both agents:\n", - "\n", - "* research agent will look up the necessary GDP information\n", - "* math agent will perform division to find the percentage of NY state GDP, as requested" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "89b77171-58d0-4b36-8cb3-b69d69e4bdf9", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Update from node supervisor:\n", - "\n", - "\n", - "=================================\u001b[1m Tool Message \u001b[0m=================================\n", - "Name: transfer_to_research_agent\n", - "\n", - "Successfully transferred to research_agent\n", - "\n", - "\n", - "Update from node research_agent:\n", - "\n", - "\n", - "=================================\u001b[1m Tool Message \u001b[0m=================================\n", - "Name: transfer_back_to_supervisor\n", - "\n", - "Successfully transferred back to supervisor\n", - "\n", - "\n", - "Update from node supervisor:\n", - "\n", - "\n", - "=================================\u001b[1m Tool Message \u001b[0m=================================\n", - "Name: transfer_to_math_agent\n", - "\n", - "Successfully transferred to math_agent\n", - "\n", - "\n", - "Update from node math_agent:\n", - "\n", - "\n", - "=================================\u001b[1m Tool Message \u001b[0m=================================\n", - "Name: transfer_back_to_supervisor\n", - "\n", - "Successfully transferred back to supervisor\n", - "\n", - "\n", - "Update from node supervisor:\n", - "\n", - "\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "Name: supervisor\n", - "\n", - "In 2024, the US GDP was $29.18 trillion and New York State's GDP was $2.297 trillion. New York State accounted for approximately 7.87% of the total US GDP in 2024.\n", - "\n", - "\n" - ] - } - ], - "source": [ - "for chunk in supervisor.stream(\n", - " {\n", - " \"messages\": [\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"find US and New York state GDP in 2024. what % of US GDP was New York state?\",\n", - " }\n", - " ]\n", - " },\n", - "):\n", - " pretty_print_messages(chunk, last_message=True)\n", - "\n", - "final_message_history = chunk[\"supervisor\"][\"messages\"]" - ] - }, - { - "cell_type": "markdown", - "id": "599b8d13-70a9-40f3-99b9-5e3d35cc6f56", - "metadata": {}, - "source": [ - "## 3. Create supervisor from scratch" - ] - }, - { - "cell_type": "markdown", - "id": "e23764f8-f818-45f3-a5ee-4cb7b7002336", - "metadata": {}, - "source": [ - "Let's now implement this same multi-agent system from scratch. We will need to:\n", - "\n", - "1. Set up how the supervisor [communicates](#set-up-agent-communication) with individual agents\n", - "2. Create the [supervisor agent](#create-supervisor-agent)\n", - "3. [Combine]() supervisor and worker agents into a single multi-agent graph." - ] - }, - { - "cell_type": "markdown", - "id": "78d32089-0259-4aa3-a473-077ecce342dd", - "metadata": {}, - "source": [ - "### Set up agent communication" - ] - }, - { - "cell_type": "markdown", - "id": "a6c6b436-e95b-476b-b427-7b02d8384cc5", - "metadata": {}, - "source": [ - "We will need to define a way for the supervisor agent to communicate with the worker agents. A common way to implement this in multi-agent architectures is using **handoffs**, where one agent *hands off* control to another. Handoffs allow you to specify:\n", - "\n", - "- **destination**: target agent to transfer to\n", - "- **payload**: information to pass to that agent\n", - "\n", - "We will implement handoffs via **handoff tools** and give these tools to the supervisor agent: when the supervisor calls these tools, it will hand off control to a worker agent, passing the full message history to that agent." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "7873a6c3-7de0-46d1-96ce-2dca7c62245a", - "metadata": {}, - "outputs": [], - "source": [ - "from typing import Annotated\n", - "from langchain_core.tools import tool, InjectedToolCallId\n", - "from langgraph.prebuilt import InjectedState\n", - "from langgraph.graph import StateGraph, START, MessagesState\n", - "from langgraph.types import Command\n", - "\n", - "\n", - "def create_handoff_tool(*, agent_name: str, description: str | None = None):\n", - " name = f\"transfer_to_{agent_name}\"\n", - " description = description or f\"Ask {agent_name} for help.\"\n", - "\n", - " @tool(name, description=description)\n", - " def handoff_tool(\n", - " state: Annotated[MessagesState, InjectedState],\n", - " tool_call_id: Annotated[str, InjectedToolCallId],\n", - " ) -> Command:\n", - " tool_message = {\n", - " \"role\": \"tool\",\n", - " \"content\": f\"Successfully transferred to {agent_name}\",\n", - " \"name\": name,\n", - " \"tool_call_id\": tool_call_id,\n", - " }\n", - " # highlight-next-line\n", - " return Command(\n", - " # highlight-next-line\n", - " goto=agent_name, # (1)!\n", - " # highlight-next-line\n", - " update={**state, \"messages\": state[\"messages\"] + [tool_message]}, # (2)!\n", - " # highlight-next-line\n", - " graph=Command.PARENT, # (3)!\n", - " )\n", - "\n", - " return handoff_tool\n", - "\n", - "\n", - "# Handoffs\n", - "assign_to_research_agent = create_handoff_tool(\n", - " agent_name=\"research_agent\",\n", - " description=\"Assign task to a researcher agent.\",\n", - ")\n", - "\n", - "assign_to_math_agent = create_handoff_tool(\n", - " agent_name=\"math_agent\",\n", - " description=\"Assign task to a math agent.\",\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "3bc810a4-1866-4915-abd9-12655954e673", - "metadata": {}, - "source": [ - "1. Name of the agent or node to hand off to.\n", - "2. Take the agent's messages and add them to the parent's state as part of the handoff. The next agent will see the parent state.\n", - "3. Indicate to LangGraph that we need to navigate to agent node in a **parent** multi-agent graph." - ] - }, - { - "cell_type": "markdown", - "id": "6a7bd301-c954-4189-87e2-b3bf42d187c1", - "metadata": {}, - "source": [ - "### Create supervisor agent" - ] - }, - { - "cell_type": "markdown", - "id": "ca787ce6-46f9-49c3-8f9f-ddb7ff52cdeb", - "metadata": {}, - "source": [ - "Then, let's create the supervisor agent with the handoff tools we just defined. We will use the prebuilt [`create_react_agent`][langgraph.prebuilt.chat_agent_executor.create_react_agent]:" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "de5d1ff8-e7a0-4efe-93fe-d304eaef29b6", - "metadata": {}, - "outputs": [], - "source": [ - "supervisor_agent = create_react_agent(\n", - " model=\"openai:gpt-4.1\",\n", - " tools=[assign_to_research_agent, assign_to_math_agent],\n", - " prompt=(\n", - " \"You are a supervisor managing two agents:\\n\"\n", - " \"- a research agent. Assign research-related tasks to this agent\\n\"\n", - " \"- a math agent. Assign math-related tasks to this agent\\n\"\n", - " \"Assign work to one agent at a time, do not call agents in parallel.\\n\"\n", - " \"Do not do any work yourself.\"\n", - " ),\n", - " name=\"supervisor\",\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "dd4bc4e2-e133-42fd-a47f-6fb63fa51697", - "metadata": {}, - "source": [ - "### Create multi-agent graph" - ] - }, - { - "cell_type": "markdown", - "id": "8e6dcae1-eb91-4a07-aef8-53cbed14a002", - "metadata": {}, - "source": [ - "Putting this all together, let's create a graph for our overall multi-agent system. We will add the supervisor and the individual agents as [subgraph](../../../concepts/low_level#subgraphs) nodes." - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "584443af-587a-44f3-a320-f942868191e4", - "metadata": {}, - "outputs": [], - "source": [ - "from langgraph.graph import END\n", - "\n", - "# Define the multi-agent supervisor graph\n", - "supervisor = (\n", - " StateGraph(MessagesState)\n", - " # NOTE: `destinations` is only needed for visualization and doesn't affect runtime behavior\n", - " .add_node(supervisor_agent, destinations=(\"research_agent\", \"math_agent\", END))\n", - " .add_node(research_agent)\n", - " .add_node(math_agent)\n", - " .add_edge(START, \"supervisor\")\n", - " # always return back to the supervisor\n", - " .add_edge(\"research_agent\", \"supervisor\")\n", - " .add_edge(\"math_agent\", \"supervisor\")\n", - " .compile()\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "12576211-a946-46ec-bf81-24215597a1fe", - "metadata": {}, - "source": [ - "Notice that we've added explicit [edges](../../../concepts/low_level#edges) from worker agents back to the supervisor — this means that they are guaranteed to return control back to the supervisor. If you want the agents to respond directly to the user (i.e., turn the system into a router, you can remove these edges)." - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "id": "0175fe14-5854-4197-b7e8-559335d0f81b", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "from IPython.display import display, Image\n", - "\n", - "display(Image(supervisor.get_graph().draw_mermaid_png()))" - ] - }, - { - "cell_type": "markdown", - "id": "d36496de-7121-4c49-8cb6-58c943c66628", - "metadata": {}, - "source": [ - "With the multi-agent graph created, let's now run it!" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "id": "56ba78e9-d9c1-457c-a073-d606d5d3e013", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Update from node supervisor:\n", - "\n", - "\n", - "=================================\u001b[1m Tool Message \u001b[0m=================================\n", - "Name: transfer_to_research_agent\n", - "\n", - "Successfully transferred to research_agent\n", - "\n", - "\n", - "Update from node research_agent:\n", - "\n", - "\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "Name: research_agent\n", - "\n", - "- US GDP in 2024 is projected to be about $28.18 trillion USD (Statista; CBO projection).\n", - "- New York State's nominal GDP for 2024 is estimated at approximately $2.16 trillion USD (various economic reports).\n", - "- New York State's share of US GDP in 2024 is roughly 7.7%.\n", - "\n", - "Sources:\n", - "- https://www.statista.com/statistics/216985/forecast-of-us-gross-domestic-product/\n", - "- https://nyassembly.gov/Reports/WAM/2025economic_revenue/2025_report.pdf?v=1740533306\n", - "\n", - "\n", - "Update from node supervisor:\n", - "\n", - "\n", - "=================================\u001b[1m Tool Message \u001b[0m=================================\n", - "Name: transfer_to_math_agent\n", - "\n", - "Successfully transferred to math_agent\n", - "\n", - "\n", - "Update from node math_agent:\n", - "\n", - "\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "Name: math_agent\n", - "\n", - "US GDP in 2024: $28.18 trillion\n", - "New York State GDP in 2024: $2.16 trillion\n", - "Percentage of US GDP from New York State: 7.67%\n", - "\n", - "\n", - "Update from node supervisor:\n", - "\n", - "\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "Name: supervisor\n", - "\n", - "Here are your results:\n", - "\n", - "- 2024 US GDP (projected): $28.18 trillion USD\n", - "- 2024 New York State GDP (estimated): $2.16 trillion USD\n", - "- New York State's share of US GDP: approximately 7.7%\n", - "\n", - "If you need the calculation steps or sources, let me know!\n", - "\n", - "\n" - ] - } - ], - "source": [ - "for chunk in supervisor.stream(\n", - " {\n", - " \"messages\": [\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"find US and New York state GDP in 2024. what % of US GDP was New York state?\",\n", - " }\n", - " ]\n", - " },\n", - "):\n", - " pretty_print_messages(chunk, last_message=True)\n", - "\n", - "final_message_history = chunk[\"supervisor\"][\"messages\"]" - ] - }, - { - "cell_type": "markdown", - "id": "dac583a8-af2c-402f-801e-15a6bc318e44", - "metadata": {}, - "source": [ - "Let's examine the full resulting message history:" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "id": "1eff504c-7437-477e-ab28-936c1238eaca", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "================================\u001b[1m Human Message \u001b[0m=================================\n", - "\n", - "find US and New York state GDP in 2024. what % of US GDP was New York state?\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "Name: supervisor\n", - "Tool Calls:\n", - " transfer_to_research_agent (call_KlGgvF5ahlAbjX8d2kHFjsC3)\n", - " Call ID: call_KlGgvF5ahlAbjX8d2kHFjsC3\n", - " Args:\n", - "=================================\u001b[1m Tool Message \u001b[0m=================================\n", - "Name: transfer_to_research_agent\n", - "\n", - "Successfully transferred to research_agent\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "Name: research_agent\n", - "Tool Calls:\n", - " tavily_search (call_ZOaTVUA6DKrOjWQldLhtrsO2)\n", - " Call ID: call_ZOaTVUA6DKrOjWQldLhtrsO2\n", - " Args:\n", - " query: US GDP 2024 estimate or actual\n", - " search_depth: advanced\n", - " tavily_search (call_QsRAasxW9K03lTlqjuhNLFbZ)\n", - " Call ID: call_QsRAasxW9K03lTlqjuhNLFbZ\n", - " Args:\n", - " query: New York state GDP 2024 estimate or actual\n", - " search_depth: advanced\n", - "=================================\u001b[1m Tool Message \u001b[0m=================================\n", - "Name: tavily_search\n", - "\n", - "{\"query\": \"US GDP 2024 estimate or actual\", \"follow_up_questions\": null, \"answer\": null, \"images\": [], \"results\": [{\"url\": \"https://www.advisorperspectives.com/dshort/updates/2025/05/29/gdp-gross-domestic-product-q1-2025-second-estimate\", \"title\": \"Q1 GDP Second Estimate: Real GDP at -0.2%, Higher Than Expected\", \"content\": \"> Real gross domestic product (GDP) decreased at an annual rate of 0.2 percent in the first quarter of 2025 (January, February, and March), according to the second estimate released by the U.S. Bureau of Economic Analysis. In the fourth quarter of 2024, real GDP increased 2.4 percent. The decrease in real GDP in the first quarter primarily reflected an increase in imports, which are a subtraction in the calculation of GDP, and a decrease in government spending. These movements were partly [...] by [Harry Mamaysky](https://www.advisorperspectives.com/search?author=Harry%20Mamaysky) of [QuantStreet Capital](https://www.advisorperspectives.com/firm/quantstreet-capital), 10/14/2024\\n\\n#### [The Worst of Allan Roth](https://www.advisorperspectives.com/articles/2024/10/21/worst-of-allan-roth/)\\n\\n by [Allan Roth](https://www.advisorperspectives.com/search?author=Allan%20Roth), 10/21/2024 [...] by [Juan Pablo Spinetto](https://www.advisorperspectives.com/search?author=Juan%20Pablo%20Spinetto) of [Bloomberg News](https://www.advisorperspectives.com/firm/bloomberg-news), 04/05/2025\\n\\n#### [Your Clients Are Clueless About Their Risk Tolerance](https://www.advisorperspectives.com/articles/2024/10/23/clients-clueless-about-risk-tolerance/)\\n\\n by [Dan Solin](https://www.advisorperspectives.com/search?author=Dan%20Solin), 10/23/2024\", \"score\": 0.78650844, \"raw_content\": null}, {\"url\": \"https://www.statista.com/statistics/216985/forecast-of-us-gross-domestic-product/\", \"title\": \"GDP forecast U.S. 2034 - Statista\", \"content\": \"[](https://www.statista.com/statistics/216985/forecast-of-us-gross-domestic-product/#statisticContainer) This graph shows a forecast of the gross domestic product of the United States of America for fiscal years 2024 to 2034. GDP refers to the market value of all final goods and services produced within a country in a given period. According to the CBO, the United States GDP will increase steadily over the next decade from 28.18 trillion U.S. dollars in 2023 to 41.65 trillion U.S. dollars in [...] US Congressional Budget Office. (February 7, 2024). Forecast of the gross domestic product of the United States from fiscal year 2024 to fiscal year 2034 (in billion U.S. dollars) [Graph]. In Statista. Retrieved May 20, 2025, from https://www.statista.com/statistics/216985/forecast-of-us-gross-domestic-product/ [...] US Congressional Budget Office. (2024). Forecast of the gross domestic product of the United States from fiscal year 2024 to fiscal year 2034 (in billion U.S. dollars). Statista. Statista Inc.. Accessed: May 20, 2025. https://www.statista.com/statistics/216985/forecast-of-us-gross-domestic-product/\", \"score\": 0.7576693, \"raw_content\": null}, {\"url\": \"https://www.bea.gov/data/gdp/gross-domestic-product\", \"title\": \"Gross Domestic Product | U.S. Bureau of Economic Analysis (BEA)\", \"content\": \"Real gross domestic product (GDP) decreased at an annual rate of 0.2 percent in the first quarter of 2025 (January, February, and March), according to the second estimate released by the U.S. Bureau of Economic Analysis. In the fourth quarter of 2024, real GDP increased 2.4 percent. The decrease in real GDP in the first quarter primarily reflected an increase in imports, which are a subtraction in the calculation of GDP, and a decrease in government spending. These movements were partly offset\", \"score\": 0.75723875, \"raw_content\": null}], \"response_time\": 2.48}\n", - "=================================\u001b[1m Tool Message \u001b[0m=================================\n", - "Name: tavily_search\n", - "\n", - "{\"query\": \"New York state GDP 2024 estimate or actual\", \"follow_up_questions\": null, \"answer\": null, \"images\": [], \"results\": [{\"url\": \"https://comptroller.nyc.gov/reports/annual-state-of-the-citys-economy-and-finances-2024/\", \"title\": \"Annual State of the City's Economy and Finances 2024\", \"content\": \"[[1]](https://comptroller.nyc.gov/reports/annual-state-of-the-citys-economy-and-finances-2024/#_ftnref1) At that time, the Comptroller’s Office expected five-year cumulative real GDP growth, 2020 to 2024, of 8.7 percent while the mayor expected 9.5 percent.\\n\\n[[2]](https://comptroller.nyc.gov/reports/annual-state-of-the-citys-economy-and-finances-2024/#_ftnref2) U.S. Bureau of Labor Statistics Local Area Unemployment Statistics (LAUS). [...] [[19]](https://comptroller.nyc.gov/reports/annual-state-of-the-citys-economy-and-finances-2024/#_ftnref19) FY 2024 actuals include $742 million in transfers to the capital fund through Interfund Agreements, as detailed in Schedule G6 of the FY 2024 Annual Comprehensive Financial Report. [...] (constant 2019 dollars)**22,550 15,322 13,596 19,451 21,211 21,096\\n**_% change_**(32.1%)(11.3%)43.1%9.0%(0.5%)\\n\\nSource: NY State Department of Taxation and Finance and Office of the New York City Comptroller\", \"score\": 0.82795376, \"raw_content\": null}], \"response_time\": 2.76}\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "Name: research_agent\n", - "Tool Calls:\n", - " tavily_search (call_DxuGWv9Ii19fPys582KcSLOg)\n", - " Call ID: call_DxuGWv9Ii19fPys582KcSLOg\n", - " Args:\n", - " query: New York state GDP 2024 (in dollars, not percentage growth or projections)\n", - " search_depth: advanced\n", - "=================================\u001b[1m Tool Message \u001b[0m=================================\n", - "Name: tavily_search\n", - "\n", - "{\"query\": \"New York state GDP 2024 (in dollars, not percentage growth or projections)\", \"follow_up_questions\": null, \"answer\": null, \"images\": [], \"results\": [{\"url\": \"https://comptroller.nyc.gov/reports/annual-state-of-the-citys-economy-and-finances-2024/\", \"title\": \"Annual State of the City's Economy and Finances 2024\", \"content\": \"(constant 2019 dollars)**22,550 15,322 13,596 19,451 21,211 21,096\\n**_% change_**(32.1%)(11.3%)43.1%9.0%(0.5%)\\n\\nSource: NY State Department of Taxation and Finance and Office of the New York City Comptroller [...] | Retail Trade | 301,565 | $56,208 | 14.4 | (0.6) | (5.2) | 2.7 | 2.9 | 2.2 | 2.1 |\\n| Leisure & Hospitality | 431,227 | $56,086 | 96.2 | 32.4 | 15.4 | 8.9 | 3.8 | 4.5 | 7.3 |\\n| **Total: Low Wage Sectors** | **1,997,491** | **$62,185** | **184.6** | **102.2** | **91.6** | **62.7** | **32.0** | **26.8** | **29.3** |\\n| **Total NYC Employment** | **4,485,695** | **$114,294** | **307.7** | **119.9** | **78.1** | **88.0** | **65.1** | **53.2** | **51.4** | [...] [[1]](https://comptroller.nyc.gov/reports/annual-state-of-the-citys-economy-and-finances-2024/#_ftnref1) At that time, the Comptroller’s Office expected five-year cumulative real GDP growth, 2020 to 2024, of 8.7 percent while the mayor expected 9.5 percent.\\n\\n[[2]](https://comptroller.nyc.gov/reports/annual-state-of-the-citys-economy-and-finances-2024/#_ftnref2) U.S. Bureau of Labor Statistics Local Area Unemployment Statistics (LAUS).\", \"score\": 0.8098936, \"raw_content\": null}, {\"url\": \"https://nyassembly.gov/Reports/WAM/2025economic_revenue/2025_report.pdf?v=1740533306\", \"title\": \"[PDF] New York State Economic and Revenue Report\", \"content\": \"Sources: Federal Reserve; NYS Assembly Ways and Means Committee staff. NYS ASSEMBLY| U.S. ECONOMIC FORECAST AT A GLANCE| 15 Actual Actual Actual Forecast Forecast 2022 2023 2024 2025 2026 Real GDP 2.5 2.9 2.8 2.4 2.1 Consumption 3.0 2.5 2.8 2.7 2.1 Investment 6.0 0.1 4.0 3.1 3.8 Exports 7.5 2.8 3.2 2.4 1.1 Imports 8.6 (1.2) 5.4 3.5 1.3 Government (1.1) 3.9 3.4 1.5 0.1 Federal (3.2) 2.9 2.5 1.7 0.2 State and Local 0.2 4.4 3.9 1.4 0.1 Personal Income 3.1 5.9 5.5 5.0 4.9 Wages & Salaries 7.8 5.4 [...] in 2024 on an annualized basis. National output, measured with inflation-adjusted Gross Domestic Product (or real GDP), continues to grow at solid rates, surpassing its pre-pandemic peak by 12.1 percent, as of the fourth quarter of 2024 (see Figure 2). However, the pace of average quarterly growth has decelerated from 3.2 percent in 2023 to 2.5 percent in 2024 on an annualized basis. 121.7 114.5 115.3 112.1 109.2 106.3 70 75 80 85 90 95 100 105 110 115 120 125 130 2019Q4 2020Q2 2020Q4 2021Q2 [...] three-month moving average of 2.5 million in December 2023 to 872,000 in December 2024. The ratio of job openings to unemployed persons, another key metric for assessing the balance between labor demand and supply, has also steadily declined in recent months. By December 2024, this ratio had dropped to 1.10, down from its peak of 2.03 in March 2022. 24 | U.S. ECONOMIC FORECAST ANALYSIS | NYS ASSEMBLY With diminishing supply shortages in the labor market, growth of labor and other incomes will\", \"score\": 0.8051581, \"raw_content\": null}], \"response_time\": 2.86}\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "Name: research_agent\n", - "Tool Calls:\n", - " tavily_search (call_wjYTJR9EnmCqzKrkrONpxYO0)\n", - " Call ID: call_wjYTJR9EnmCqzKrkrONpxYO0\n", - " Args:\n", - " query: New York State GDP (nominal) in US dollars for 2024 (actual or forecast)\n", - " search_depth: advanced\n", - "=================================\u001b[1m Tool Message \u001b[0m=================================\n", - "Name: tavily_search\n", - "\n", - "{\"query\": \"New York State GDP (nominal) in US dollars for 2024 (actual or forecast)\", \"follow_up_questions\": null, \"answer\": null, \"images\": [], \"results\": [{\"url\": \"https://nyassembly.gov/Reports/WAM/2025economic_revenue/2025_report.pdf?v=1740533306\", \"title\": \"[PDF] New York State Economic and Revenue Report\", \"content\": \"Sources: Federal Reserve; NYS Assembly Ways and Means Committee staff. NYS ASSEMBLY| U.S. ECONOMIC FORECAST AT A GLANCE| 15 Actual Actual Actual Forecast Forecast 2022 2023 2024 2025 2026 Real GDP 2.5 2.9 2.8 2.4 2.1 Consumption 3.0 2.5 2.8 2.7 2.1 Investment 6.0 0.1 4.0 3.1 3.8 Exports 7.5 2.8 3.2 2.4 1.1 Imports 8.6 (1.2) 5.4 3.5 1.3 Government (1.1) 3.9 3.4 1.5 0.1 Federal (3.2) 2.9 2.5 1.7 0.2 State and Local 0.2 4.4 3.9 1.4 0.1 Personal Income 3.1 5.9 5.5 5.0 4.9 Wages & Salaries 7.8 5.4 [...] New York State Economic Outlook (Percent Change) Actual Estimate Forecast Forecast 2023-24 2024-25 2025-26 2026-27 Employment Percent Change 1.8 1.5 1.0 0.8 Level (Thousands) 9,441.6 9,589.7 9,694.3 9,773.6 Personal Income Percent Change 5.2 5.8 4.6 4.4 Level (Billions) 1,581.5 1,671.1 1,754.9 1,835.0 Total Wages Percent Change 4.2 6.7 4.4 4.0 Level (Billions) 864.0 915.9 964.3 1,005.1 Base Wages Percent Change 5.1 5.4 4.4 4.3 Level (Billions) 764.0 803.1 840.7 876.6 Variable Compensation [...] is 0.3 percentage point above the forecast of the Division of the Budget. The Committee’s forecast is 0.1 percentage point above S&P Global forecast and Moody’s Analytics’ projection. The forecast is 0.2 percentage point above the Blue Chip Consensus forecast. Actual Estimate Forecast Forecast 2023 2024 2025 2026 Ways and Means 2.9 2.8 2.4 2.1 Division of the Budget 2.9 2.8 2.1 2.0 Blue Chip Consensus 2.9 2.8 2.2 2.0 Moody's Analytics 2.9 2.8 2.3 1.6 S&P Global 2.9 2.8 2.3 2.0 Sources: NYS\", \"score\": 0.846159, \"raw_content\": null}, {\"url\": \"https://comptroller.nyc.gov/reports/annual-state-of-the-citys-economy-and-finances-2024/\", \"title\": \"Annual State of the City's Economy and Finances 2024\", \"content\": \"(constant 2019 dollars)**22,550 15,322 13,596 19,451 21,211 21,096\\n**_% change_**(32.1%)(11.3%)43.1%9.0%(0.5%)\\n\\nSource: NY State Department of Taxation and Finance and Office of the New York City Comptroller [...] [[1]](https://comptroller.nyc.gov/reports/annual-state-of-the-citys-economy-and-finances-2024/#_ftnref1) At that time, the Comptroller’s Office expected five-year cumulative real GDP growth, 2020 to 2024, of 8.7 percent while the mayor expected 9.5 percent.\\n\\n[[2]](https://comptroller.nyc.gov/reports/annual-state-of-the-citys-economy-and-finances-2024/#_ftnref2) U.S. Bureau of Labor Statistics Local Area Unemployment Statistics (LAUS). [...] | Retail Trade | 301,565 | $56,208 | 14.4 | (0.6) | (5.2) | 2.7 | 2.9 | 2.2 | 2.1 |\\n| Leisure & Hospitality | 431,227 | $56,086 | 96.2 | 32.4 | 15.4 | 8.9 | 3.8 | 4.5 | 7.3 |\\n| **Total: Low Wage Sectors** | **1,997,491** | **$62,185** | **184.6** | **102.2** | **91.6** | **62.7** | **32.0** | **26.8** | **29.3** |\\n| **Total NYC Employment** | **4,485,695** | **$114,294** | **307.7** | **119.9** | **78.1** | **88.0** | **65.1** | **53.2** | **51.4** |\", \"score\": 0.7992077, \"raw_content\": null}], \"response_time\": 2.65}\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "Name: research_agent\n", - "\n", - "- US GDP in 2024 is projected to be about $28.18 trillion USD (Statista; CBO projection).\n", - "- New York State's nominal GDP for 2024 is estimated at approximately $2.16 trillion USD (various economic reports).\n", - "- New York State's share of US GDP in 2024 is roughly 7.7%.\n", - "\n", - "Sources:\n", - "- https://www.statista.com/statistics/216985/forecast-of-us-gross-domestic-product/\n", - "- https://nyassembly.gov/Reports/WAM/2025economic_revenue/2025_report.pdf?v=1740533306\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "Name: supervisor\n", - "Tool Calls:\n", - " transfer_to_math_agent (call_WEBMqUupSKqT5slb6ilX2VEO)\n", - " Call ID: call_WEBMqUupSKqT5slb6ilX2VEO\n", - " Args:\n", - "=================================\u001b[1m Tool Message \u001b[0m=================================\n", - "Name: transfer_to_math_agent\n", - "\n", - "Successfully transferred to math_agent\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "Name: math_agent\n", - "Tool Calls:\n", - " divide (call_fsn6la6HTqfNl3sLp9v1WVoz)\n", - " Call ID: call_fsn6la6HTqfNl3sLp9v1WVoz\n", - " Args:\n", - " a: 2.16\n", - " b: 28.18\n", - "=================================\u001b[1m Tool Message \u001b[0m=================================\n", - "Name: divide\n", - "\n", - "0.0766501064584812\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "Name: math_agent\n", - "\n", - "US GDP in 2024: $28.18 trillion\n", - "New York State GDP in 2024: $2.16 trillion\n", - "Percentage of US GDP from New York State: 7.67%\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "Name: supervisor\n", - "\n", - "Here are your results:\n", - "\n", - "- 2024 US GDP (projected): $28.18 trillion USD\n", - "- 2024 New York State GDP (estimated): $2.16 trillion USD\n", - "- New York State's share of US GDP: approximately 7.7%\n", - "\n", - "If you need the calculation steps or sources, let me know!\n" - ] - } - ], - "source": [ - "for message in final_message_history:\n", - " message.pretty_print()" - ] - }, - { - "cell_type": "markdown", - "id": "239700cd-d2d3-44be-8cf5-021d15615de2", - "metadata": {}, - "source": [ - "!!! Important\n", - "\n", - " You can see that the supervisor system appends **all** of the individual agent messages (i.e., their internal tool-calling loop) to the full message history. This means that on every supervisor turn, supervisor agent sees this full history. If you want more control over:\n", - "\n", - " * **how inputs are passed to agents**: you can use LangGraph [`Send()`][langgraph.types.Send] primitive to directly send data to the worker agents during the handoff. See the [task delegation](#create-delegation-tasks) example below\n", - " * **how agent outputs are added**: you can control how much of the agent's internal message history is added to the overall supervisor message history by wrapping the agent in a separate node function:\n", - "\n", - " ```python\n", - " def call_research_agent(state):\n", - " # return agent's final response,\n", - " # excluding inner monologue\n", - " response = research_agent.invoke(state)\n", - " # highlight-next-line\n", - " return {\"messages\": response[\"messages\"][-1]}\n", - " ```" - ] - }, - { - "cell_type": "markdown", - "id": "1c2a0aff-935a-46b8-bdcf-7125b80f1f41", - "metadata": {}, - "source": [ - "## 4. Create delegation tasks" - ] - }, - { - "cell_type": "markdown", - "id": "1a13d919-49bf-4cc3-838f-714cd3fb8b26", - "metadata": {}, - "source": [ - "So far the individual agents relied on **interpreting full message history** to determine their tasks. An alternative approach is to ask the supervisor to **formulate a task explicitly**. We can do so by adding a `task_description` parameter to the `handoff_tool` function." - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "id": "dc1e4d24-8738-4548-a5e7-8556e476b805", - "metadata": {}, - "outputs": [], - "source": [ - "from langgraph.types import Send\n", - "\n", - "\n", - "def create_task_description_handoff_tool(\n", - " *, agent_name: str, description: str | None = None\n", - "):\n", - " name = f\"transfer_to_{agent_name}\"\n", - " description = description or f\"Ask {agent_name} for help.\"\n", - "\n", - " @tool(name, description=description)\n", - " def handoff_tool(\n", - " # this is populated by the supervisor LLM\n", - " task_description: Annotated[\n", - " str,\n", - " \"Description of what the next agent should do, including all of the relevant context.\",\n", - " ],\n", - " # these parameters are ignored by the LLM\n", - " state: Annotated[MessagesState, InjectedState],\n", - " ) -> Command:\n", - " task_description_message = {\"role\": \"user\", \"content\": task_description}\n", - " agent_input = {**state, \"messages\": [task_description_message]}\n", - " return Command(\n", - " # highlight-next-line\n", - " goto=[Send(agent_name, agent_input)],\n", - " graph=Command.PARENT,\n", - " )\n", - "\n", - " return handoff_tool\n", - "\n", - "\n", - "assign_to_research_agent_with_description = create_task_description_handoff_tool(\n", - " agent_name=\"research_agent\",\n", - " description=\"Assign task to a researcher agent.\",\n", - ")\n", - "\n", - "assign_to_math_agent_with_description = create_task_description_handoff_tool(\n", - " agent_name=\"math_agent\",\n", - " description=\"Assign task to a math agent.\",\n", - ")\n", - "\n", - "supervisor_agent_with_description = create_react_agent(\n", - " model=\"openai:gpt-4.1\",\n", - " tools=[\n", - " assign_to_research_agent_with_description,\n", - " assign_to_math_agent_with_description,\n", - " ],\n", - " prompt=(\n", - " \"You are a supervisor managing two agents:\\n\"\n", - " \"- a research agent. Assign research-related tasks to this assistant\\n\"\n", - " \"- a math agent. Assign math-related tasks to this assistant\\n\"\n", - " \"Assign work to one agent at a time, do not call agents in parallel.\\n\"\n", - " \"Do not do any work yourself.\"\n", - " ),\n", - " name=\"supervisor\",\n", - ")\n", - "\n", - "supervisor_with_description = (\n", - " StateGraph(MessagesState)\n", - " .add_node(\n", - " supervisor_agent_with_description, destinations=(\"research_agent\", \"math_agent\")\n", - " )\n", - " .add_node(research_agent)\n", - " .add_node(math_agent)\n", - " .add_edge(START, \"supervisor\")\n", - " .add_edge(\"research_agent\", \"supervisor\")\n", - " .add_edge(\"math_agent\", \"supervisor\")\n", - " .compile()\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "622bc89a-0787-41ea-bf18-c591be85509b", - "metadata": {}, - "source": [ - "!!! note\n", - "\n", - " We're using [`Send()`][langgraph.types.Send] primitive in the `handoff_tool`. This means that instead of receiving the full `supervisor` graph state as input, each worker agent only sees the contents of the `Send` payload. In this example, we're sending the task description as a single \"human\" message." - ] - }, - { - "cell_type": "markdown", - "id": "4d1dba40-c948-4117-9df6-5bdb1ab162c7", - "metadata": {}, - "source": [ - "Let's now running it with the same input query:" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "id": "882f9e00-5fdf-4278-ab26-a59fc949fa91", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Update from subgraph supervisor:\n", - "\n", - "\n", - "\tUpdate from node agent:\n", - "\n", - "\n", - "\t==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "\tName: supervisor\n", - "\tTool Calls:\n", - "\t transfer_to_research_agent (call_tk8q8py8qK6MQz6Kj6mijKua)\n", - "\t Call ID: call_tk8q8py8qK6MQz6Kj6mijKua\n", - "\t Args:\n", - "\t task_description: Find the 2024 GDP (Gross Domestic Product) for both the United States and New York state, using the most up-to-date and reputable sources available. Provide both GDP values and cite the data sources.\n", - "\n", - "\n", - "Update from subgraph research_agent:\n", - "\n", - "\n", - "\tUpdate from node agent:\n", - "\n", - "\n", - "\t==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "\tName: research_agent\n", - "\tTool Calls:\n", - "\t tavily_search (call_KqvhSvOIhAvXNsT6BOwbPlRB)\n", - "\t Call ID: call_KqvhSvOIhAvXNsT6BOwbPlRB\n", - "\t Args:\n", - "\t query: 2024 United States GDP value from a reputable source\n", - "\t search_depth: advanced\n", - "\t tavily_search (call_kbbAWBc9KwCWKHmM5v04H88t)\n", - "\t Call ID: call_kbbAWBc9KwCWKHmM5v04H88t\n", - "\t Args:\n", - "\t query: 2024 New York state GDP value from a reputable source\n", - "\t search_depth: advanced\n", - "\n", - "\n", - "Update from subgraph research_agent:\n", - "\n", - "\n", - "\tUpdate from node tools:\n", - "\n", - "\n", - "\t=================================\u001b[1m Tool Message \u001b[0m=================================\n", - "\tName: tavily_search\n", - "\t\n", - "\t{\"query\": \"2024 United States GDP value from a reputable source\", \"follow_up_questions\": null, \"answer\": null, \"images\": [], \"results\": [{\"url\": \"https://www.focus-economics.com/countries/united-states/\", \"title\": \"United States Economy Overview - Focus Economics\", \"content\": \"The United States' Macroeconomic Analysis:\\n------------------------------------------\\n\\n**Nominal GDP of USD 29,185 billion in 2024.**\\n\\n**Nominal GDP of USD 29,179 billion in 2024.**\\n\\n**GDP per capita of USD 86,635 compared to the global average of USD 10,589.**\\n\\n**GDP per capita of USD 86,652 compared to the global average of USD 10,589.**\\n\\n**Average real GDP growth of 2.5% over the last decade.**\\n\\n**Average real GDP growth of 2.5% over the last decade.**\\n\\nShare of the region's population [...] | | 2020 | 2021 | 2022 | 2023 | 2024 |\\n| --- | --- | --- | --- | --- | --- |\\n| [Population (million)](https://www.focus-economics.com/country-indicator/united-states/population/) | 331 | 332 | 334 | 337 | 340 |\\n| [GDP (USD bn)](https://www.focus-economics.com/country-indicator/united-states/gdp/) | 21,354 | 23,681 | 26,007 | 27,721 | 29,185 |\", \"score\": 0.73981786, \"raw_content\": null}, {\"url\": \"https://tradingeconomics.com/united-states/gdp\", \"title\": \"United States GDP - Trading Economics\", \"content\": \"| Related | Last | Previous | Unit | Reference |\\n| --- | --- | --- | --- | --- |\\n| [Full Year GDP Growth](/united-states/full-year-gdp-growth) | 2.80 | 2.90 | percent | Dec 2024 |\\n| [GDP](/united-states/gdp) | 27720.71 | 26006.89 | USD Billion | Dec 2023 |\\n| [GDP Annual Growth Rate](/united-states/gdp-growth-annual) | 2.10 | 2.50 | percent | Mar 2025 |\\n| [GDP Constant Prices](/united-states/gdp-constant-prices) | 23528.00 | 23542.30 | USD Billion | Mar 2025 |\", \"score\": 0.65359193, \"raw_content\": null}, {\"url\": \"https://fred.stlouisfed.org/series/GDP\", \"title\": \"Gross Domestic Product (GDP) | FRED | St. Louis Fed\", \"content\": \"Q1 2025: 29,976.638 |\\nBillions of Dollars, Seasonally Adjusted Annual Rate |\\nQuarterly\\n\\nUpdated:\\nMay 29, 2025\\n7:56 AM CDT\\n\\n[Next Release Date:\\nJun 26, 2025](/releases/calendar?rid=53&y=2025)\\n\\nObservations\\n\\n| | | |\\n| --- | --- | --- |\\n| Q1 2025: | 29,976.638 | |\\n| Q4 2024: | 29,723.864 | |\\n| Q3 2024: | 29,374.914 | |\\n| Q2 2024: | 29,016.714 | |\\n| Q1 2024: | 28,624.069 | |\\n| [View All](/data/GDP.txt) | |\\n\\nUnits:\\n\\nFrequency:\", \"score\": 0.6152965, \"raw_content\": null}], \"response_time\": 2.53}\n", - "\n", - "\n", - "Update from subgraph research_agent:\n", - "\n", - "\n", - "\tUpdate from node tools:\n", - "\n", - "\n", - "\t=================================\u001b[1m Tool Message \u001b[0m=================================\n", - "\tName: tavily_search\n", - "\t\n", - "\t{\"query\": \"2024 New York state GDP value from a reputable source\", \"follow_up_questions\": null, \"answer\": null, \"images\": [], \"results\": [{\"url\": \"https://www.ibisworld.com/united-states/economic-profiles/new-york/\", \"title\": \"New York Economic Trends, Stats & Rankings | IBISWorld\", \"content\": \"#### What is New York's Gross Domestic Product (GDP)?\\n\\nIn 2024, New York's GDP reached $1.8tn, representing an increase of 1.3% from 2023. New York's GDP has grown at an annualized rate of 2.9% over the five years to 2024. Moreover, New York's trailing five-year GDP growth ranks it 37th out of all 50 US states. [...] In 2024, the state of New York has a population of 19,482,372, having grown an annualized 0.0% over the five years to 2024, which ranks it 44th out of all 50 US states by growth rate. New York's gross state product (GSP) in 2024 reached $1.8tn, with growth of 1.3% over the 5 years to 2024. Businesses in New York employed a total of 11,671,845 people in 2024, with average annual employment growth over the past five years of 0.0%. The top three sectors by total employment are Finance and [...] The Finance and Insurance, Real Estate and Rental and Leasing and Information sectors contributed the most to New York's GDP in 2024, representing a combined 46.3% of state GDP.\\n\\nGDP trends by sector are an important indicator of which sectors are contributing the most value-add to the state's economy, in addition to how the state economy is evolving over time.\\n\\nSector\\n\\nGDP\\n\\nGrowth 2024 (%)\\n\\nAnnualized Growth 2019-24\", \"score\": 0.8051581, \"raw_content\": null}, {\"url\": \"https://comptroller.nyc.gov/reports/annual-state-of-the-citys-economy-and-finances-2024/\", \"title\": \"Annual State of the City's Economy and Finances 2024\", \"content\": \"(constant 2019 dollars)**22,550 15,322 13,596 19,451 21,211 21,096\\n**_% change_**(32.1%)(11.3%)43.1%9.0%(0.5%)\\n\\nSource: NY State Department of Taxation and Finance and Office of the New York City Comptroller [...] [[1]](https://comptroller.nyc.gov/reports/annual-state-of-the-citys-economy-and-finances-2024/#_ftnref1) At that time, the Comptroller’s Office expected five-year cumulative real GDP growth, 2020 to 2024, of 8.7 percent while the mayor expected 9.5 percent.\\n\\n[[2]](https://comptroller.nyc.gov/reports/annual-state-of-the-citys-economy-and-finances-2024/#_ftnref2) U.S. Bureau of Labor Statistics Local Area Unemployment Statistics (LAUS). [...] **($ in millions)****FY 2025****FY 2026****FY 2027****FY 2028****Total****Change from June 2024 (FY2025-FY2028)****Source as Share of Total**\\n**General Obligation Bonds**$6,900$6,230$6,920$7,110$27,160$1,960 42.8%\\n**TFA FTS Bonds**6,900 6,230 6,920 7,110 27,160 2,460 42.8%\\n**NYC Water Finance Authority**1,726 2,474 2,452 2,505 9,157 435 14.4%\\n**Total****$15,526****$14,934****$16,292****$16,725****$63,477****$4,855****100.0%**\", \"score\": 0.74541736, \"raw_content\": null}], \"response_time\": 3.45}\n", - "\n", - "\n", - "Update from subgraph research_agent:\n", - "\n", - "\n", - "\tUpdate from node agent:\n", - "\n", - "\n", - "\t==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "\tName: research_agent\n", - "\t\n", - "\t- United States 2024 GDP: $29.2 trillion (USD) \n", - "\t Source: [Focus Economics](https://www.focus-economics.com/countries/united-states/)\n", - "\t\n", - "\t- New York State 2024 GDP: $1.8 trillion (USD) \n", - "\t Source: [IBISWorld](https://www.ibisworld.com/united-states/economic-profiles/new-york/)\n", - "\n", - "\n", - "Update from subgraph supervisor:\n", - "\n", - "\n", - "\tUpdate from node agent:\n", - "\n", - "\n", - "\t==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "\tName: supervisor\n", - "\tTool Calls:\n", - "\t transfer_to_math_agent (call_EqT01HDOQDd5Timk89cccdXP)\n", - "\t Call ID: call_EqT01HDOQDd5Timk89cccdXP\n", - "\t Args:\n", - "\t task_description: Calculate what percentage of the US GDP ($29.2 trillion) was New York State's GDP ($1.8 trillion) in 2024. Show your working and round the final answer to two decimal points.\n", - "\n", - "\n", - "Update from subgraph math_agent:\n", - "\n", - "\n", - "\tUpdate from node agent:\n", - "\n", - "\n", - "\t==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "\tName: math_agent\n", - "\tTool Calls:\n", - "\t divide (call_OpdUlYEFqk4RZ2rF46M9eTrS)\n", - "\t Call ID: call_OpdUlYEFqk4RZ2rF46M9eTrS\n", - "\t Args:\n", - "\t a: 1.8\n", - "\t b: 29.2\n", - "\n", - "\n", - "Update from subgraph math_agent:\n", - "\n", - "\n", - "\tUpdate from node tools:\n", - "\n", - "\n", - "\t=================================\u001b[1m Tool Message \u001b[0m=================================\n", - "\tName: divide\n", - "\t\n", - "\t0.06164383561643836\n", - "\n", - "\n", - "Update from subgraph math_agent:\n", - "\n", - "\n", - "\tUpdate from node agent:\n", - "\n", - "\n", - "\t==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "\tName: math_agent\n", - "\tTool Calls:\n", - "\t multiply (call_vdKJTLtIzmG6JbPcGQn93MR6)\n", - "\t Call ID: call_vdKJTLtIzmG6JbPcGQn93MR6\n", - "\t Args:\n", - "\t a: 0.06164383561643836\n", - "\t b: 100\n", - "\n", - "\n", - "Update from subgraph math_agent:\n", - "\n", - "\n", - "\tUpdate from node tools:\n", - "\n", - "\n", - "\t=================================\u001b[1m Tool Message \u001b[0m=================================\n", - "\tName: multiply\n", - "\t\n", - "\t6.164383561643836\n", - "\n", - "\n", - "Update from subgraph math_agent:\n", - "\n", - "\n", - "\tUpdate from node agent:\n", - "\n", - "\n", - "\t==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "\tName: math_agent\n", - "\t\n", - "\tNew York State's GDP was approximately 6.16% of the US GDP in 2024.\n", - "\n", - "\n", - "Update from subgraph supervisor:\n", - "\n", - "\n", - "\tUpdate from node agent:\n", - "\n", - "\n", - "\t==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "\tName: supervisor\n", - "\t\n", - "\tNew York State’s GDP was approximately 6.16% of the US GDP in 2024.\n", - "\t\n", - "\t**Working:**\n", - "\t- Percentage = (NY GDP / US GDP) × 100\n", - "\t- = ($1.8 trillion / $29.2 trillion) × 100\n", - "\t- = 0.06164 × 100\n", - "\t- = 6.16% (rounded to two decimal points)\n", - "\n", - "\n" - ] - } - ], - "source": [ - "for chunk in supervisor_with_description.stream(\n", - " {\n", - " \"messages\": [\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"find US and New York state GDP in 2024. what % of US GDP was New York state?\",\n", - " }\n", - " ]\n", - " },\n", - " subgraphs=True,\n", - "):\n", - " pretty_print_messages(chunk, last_message=True)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6d3916d1-7de9-47c1-ae6f-80865b804e77", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.10" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/docs/docs/tutorials/multi_agent/agent_supervisor.md b/docs/docs/tutorials/multi_agent/agent_supervisor.md new file mode 100644 index 000000000..ba8f84ff6 --- /dev/null +++ b/docs/docs/tutorials/multi_agent/agent_supervisor.md @@ -0,0 +1,812 @@ +# Multi-agent supervisor + +[**Supervisor**](../../concepts/multi_agent.md#supervisor) is a multi-agent architecture where **specialized** agents are coordinated by a central **supervisor agent**. The supervisor agent controls all communication flow and task delegation, making decisions about which agent to invoke based on the current context and task requirements. + +In this tutorial, you will build a supervisor system with two agents — a research and a math expert. By the end of the tutorial you will: + +1. Build specialized research and math agents +2. Build a supervisor for orchestrating them with the prebuilt [`langgraph-supervisor`](https://langchain-ai.github.io/langgraph/agents/multi-agent/#supervisor) +3. Build a supervisor from scratch +4. Implement advanced task delegation + +![diagram](assets/diagram.png) + +## Setup + +First, let's install required packages and set our API keys + +```python +%%capture --no-stderr +%pip install -U langgraph langgraph-supervisor langchain-tavily "langchain[openai]" +``` + +```python +import getpass +import os + + +def _set_if_undefined(var: str): + if not os.environ.get(var): + os.environ[var] = getpass.getpass(f"Please provide your {var}") + + +_set_if_undefined("OPENAI_API_KEY") +_set_if_undefined("TAVILY_API_KEY") +``` + +!!! tip + Sign up for LangSmith to quickly spot issues and improve the performance of your LangGraph projects. [LangSmith](https://docs.smith.langchain.com) lets you use trace data to debug, test, and monitor your LLM apps built with LangGraph. + +## 1. Create worker agents + +First, let's create our specialized worker agents — research agent and math agent: + +* Research agent will have access to a web search tool using [Tavily API](https://tavily.com/) +* Math agent will have access to simple math tools (`add`, `multiply`, `divide`) + +### Research agent + +For web search, we will use `TavilySearch` tool from `langchain-tavily`: + +```python +from langchain_tavily import TavilySearch + +web_search = TavilySearch(max_results=3) +web_search_results = web_search.invoke("who is the mayor of NYC?") + +print(web_search_results["results"][0]["content"]) +``` + +**Output:** +``` +Find events, attractions, deals, and more at nyctourism.com Skip Main Navigation Menu The Official Website of the City of New York Text Size Powered by Translate SearchSearch Primary Navigation The official website of NYC Home NYC Resources NYC311 Office of the Mayor Events Connect Jobs Search Office of the Mayor | Mayor's Bio | City of New York Secondary Navigation MayorBiographyNewsOfficials Eric L. Adams 110th Mayor of New York City Mayor Eric Adams has served the people of New York City as an NYPD officer, State Senator, Brooklyn Borough President, and now as the 110th Mayor of the City of New York. Mayor Eric Adams has served the people of New York City as an NYPD officer, State Senator, Brooklyn Borough President, and now as the 110th Mayor of the City of New York. He gave voice to a diverse coalition of working families in all five boroughs and is leading the fight to bring back New York City's economy, reduce inequality, improve public safety, and build a stronger, healthier city that delivers for all New Yorkers. As the representative of one of the nation's largest counties, Eric fought tirelessly to grow the local economy, invest in schools, reduce inequality, improve public safety, and advocate for smart policies and better government that delivers for all New Yorkers. +``` + +To create individual worker agents, we will use LangGraph's prebuilt [agent](../../agents/agents.md). + +```python +from langgraph.prebuilt import create_react_agent + +research_agent = create_react_agent( + model="openai:gpt-4.1", + tools=[web_search], + prompt=( + "You are a research agent.\n\n" + "INSTRUCTIONS:\n" + "- Assist ONLY with research-related tasks, DO NOT do any math\n" + "- After you're done with your tasks, respond to the supervisor directly\n" + "- Respond ONLY with the results of your work, do NOT include ANY other text." + ), + name="research_agent", +) +``` + +Let's [run the agent](../../agents/run_agents.md) to verify that it behaves as expected. + +!!! note "We'll use `pretty_print_messages` helper to render the streamed agent outputs nicely" + + ```python + from langchain_core.messages import convert_to_messages + + + def pretty_print_message(message, indent=False): + pretty_message = message.pretty_repr(html=True) + if not indent: + print(pretty_message) + return + + indented = "\n".join("\t" + c for c in pretty_message.split("\n")) + print(indented) + + + def pretty_print_messages(update, last_message=False): + is_subgraph = False + if isinstance(update, tuple): + ns, update = update + # skip parent graph updates in the printouts + if len(ns) == 0: + return + + graph_id = ns[-1].split(":")[0] + print(f"Update from subgraph {graph_id}:") + print("\n") + is_subgraph = True + + for node_name, node_update in update.items(): + update_label = f"Update from node {node_name}:" + if is_subgraph: + update_label = "\t" + update_label + + print(update_label) + print("\n") + + messages = convert_to_messages(node_update["messages"]) + if last_message: + messages = messages[-1:] + + for m in messages: + pretty_print_message(m, indent=is_subgraph) + print("\n") + ``` + +```python +from langchain_core.messages import convert_to_messages + + +def pretty_print_message(message, indent=False): + pretty_message = message.pretty_repr(html=True) + if not indent: + print(pretty_message) + return + + indented = "\n".join("\t" + c for c in pretty_message.split("\n")) + print(indented) + + +def pretty_print_messages(update, last_message=False): + is_subgraph = False + if isinstance(update, tuple): + ns, update = update + # skip parent graph updates in the printouts + if len(ns) == 0: + return + + graph_id = ns[-1].split(":")[0] + print(f"Update from subgraph {graph_id}:") + print("\n") + is_subgraph = True + + for node_name, node_update in update.items(): + update_label = f"Update from node {node_name}:" + if is_subgraph: + update_label = "\t" + update_label + + print(update_label) + print("\n") + + messages = convert_to_messages(node_update["messages"]) + if last_message: + messages = messages[-1:] + + for m in messages: + pretty_print_message(m, indent=is_subgraph) + print("\n") +``` + +```python +for chunk in research_agent.stream( + {"messages": [{"role": "user", "content": "who is the mayor of NYC?"}]} +): + pretty_print_messages(chunk) +``` + +**Output:** +``` +Update from node agent: + + +================================== Ai Message ================================== +Name: research_agent +Tool Calls: + tavily_search (call_U748rQhQXT36sjhbkYLSXQtJ) + Call ID: call_U748rQhQXT36sjhbkYLSXQtJ + Args: + query: current mayor of New York City + search_depth: basic + + +Update from node tools: + + +================================= Tool Message ================================== +Name: tavily_search + +{"query": "current mayor of New York City", "follow_up_questions": null, "answer": null, "images": [], "results": [{"title": "List of mayors of New York City - Wikipedia", "url": "https://en.wikipedia.org/wiki/List_of_mayors_of_New_York_City", "content": "The mayor of New York City is the chief executive of the Government of New York City, as stipulated by New York City's charter.The current officeholder, the 110th in the sequence of regular mayors, is Eric Adams, a member of the Democratic Party.. During the Dutch colonial period from 1624 to 1664, New Amsterdam was governed by the Director of Netherland.", "score": 0.9039154, "raw_content": null}, {"title": "Office of the Mayor | Mayor's Bio | City of New York - NYC.gov", "url": "https://www.nyc.gov/office-of-the-mayor/bio.page", "content": "Mayor Eric Adams has served the people of New York City as an NYPD officer, State Senator, Brooklyn Borough President, and now as the 110th Mayor of the City of New York. He gave voice to a diverse coalition of working families in all five boroughs and is leading the fight to bring back New York City's economy, reduce inequality, improve", "score": 0.8405867, "raw_content": null}, {"title": "Eric Adams - Wikipedia", "url": "https://en.wikipedia.org/wiki/Eric_Adams", "content": "Eric Leroy Adams (born September 1, 1960) is an American politician and former police officer who has served as the 110th mayor of New York City since 2022. Adams was an officer in the New York City Transit Police and then the New York City Police Department (``` +``` + +### Math agent + +For math agent tools we will use [vanilla Python functions](../../agents/tools.md#define-simple-tools): + +```python +def add(a: float, b: float): + """Add two numbers.""" + return a + b + + +def multiply(a: float, b: float): + """Multiply two numbers.""" + return a * b + + +def divide(a: float, b: float): + """Divide two numbers.""" + return a / b + + +math_agent = create_react_agent( + model="openai:gpt-4.1", + tools=[add, multiply, divide], + prompt=( + "You are a math agent.\n\n" + "INSTRUCTIONS:\n" + "- Assist ONLY with math-related tasks\n" + "- After you're done with your tasks, respond to the supervisor directly\n" + "- Respond ONLY with the results of your work, do NOT include ANY other text." + ), + name="math_agent", +) +``` + +Let's run the math agent: + +```python +for chunk in math_agent.stream( + {"messages": [{"role": "user", "content": "what's (3 + 5) x 7"}]} +): + pretty_print_messages(chunk) +``` + +**Output:** +``` +Update from node agent: + + +================================== Ai Message ================================== +Name: math_agent +Tool Calls: + add (call_p6OVLDHB4LyCNCxPOZzWR15v) + Call ID: call_p6OVLDHB4LyCNCxPOZzWR15v + Args: + a: 3 + b: 5 + + +Update from node tools: + + +================================= Tool Message ================================== +Name: add + +8.0 + + +Update from node agent: + + +================================== Ai Message ================================== +Name: math_agent +Tool Calls: + multiply (call_EoaWHMLFZAX4AkajQCtZvbli) + Call ID: call_EoaWHMLFZAX4AkajQCtZvbli + Args: + a: 8 + b: 7 + + +Update from node tools: + + +================================= Tool Message ================================== +Name: multiply + +56.0 + + +Update from node agent: + + +================================== Ai Message ================================== +Name: math_agent + +56 + + +``` + +## 2. Create supervisor with `langgraph-supervisor` + +To implement out multi-agent system, we will use [`create_supervisor`][langgraph_supervisor.supervisor.create_supervisor] from the prebuilt `langgraph-supervisor` library: + +```python +from langgraph_supervisor import create_supervisor +from langchain.chat_models import init_chat_model + +supervisor = create_supervisor( + model=init_chat_model("openai:gpt-4.1"), + agents=[research_agent, math_agent], + prompt=( + "You are a supervisor managing two agents:\n" + "- a research agent. Assign research-related tasks to this agent\n" + "- a math agent. Assign math-related tasks to this agent\n" + "Assign work to one agent at a time, do not call agents in parallel.\n" + "Do not do any work yourself." + ), + add_handoff_back_messages=True, + output_mode="full_history", +).compile() +``` + +```python +from IPython.display import display, Image + +display(Image(supervisor.get_graph().draw_mermaid_png())) +``` + +![Graph](assets/output.png) + +**Note:** When you run this code, it will generate and display a visual representation of the supervisor graph showing the flow between the supervisor and worker agents. + +Let's now run it with a query that requires both agents: + +* research agent will look up the necessary GDP information +* math agent will perform division to find the percentage of NY state GDP, as requested + +```python +for chunk in supervisor.stream( + { + "messages": [ + { + "role": "user", + "content": "find US and New York state GDP in 2024. what % of US GDP was New York state?", + } + ] + }, +): + pretty_print_messages(chunk, last_message=True) + +final_message_history = chunk["supervisor"]["messages"] +``` + +**Output:** +``` +Update from node supervisor: + + +================================= Tool Message ================================== +Name: transfer_to_research_agent + +Successfully transferred to research_agent + + +Update from node research_agent: + + +================================= Tool Message ================================== +Name: transfer_back_to_supervisor + +Successfully transferred back to supervisor + + +Update from node supervisor: + + +================================= Tool Message ================================== +Name: transfer_to_math_agent + +Successfully transferred to math_agent + + +Update from node math_agent: + + +================================= Tool Message ================================== +Name: transfer_back_to_supervisor + +Successfully transferred back to supervisor + + +Update from node supervisor: + + +================================== Ai Message ================================== +Name: supervisor + +In 2024, the US GDP was $29.18 trillion and New York State's GDP was $2.297 trillion. New York State accounted for approximately 7.87% of the total US GDP in 2024. + + +``` + +## 3. Create supervisor from scratch + +Let's now implement this same multi-agent system from scratch. We will need to: + +1. [Set up how the supervisor communicates](#set-up-agent-communication) with individual agents +2. [Create the supervisor agent](#create-supervisor-agent) +3. Combine supervisor and worker agents into a [single multi-agent graph](#create-multi-agent-graph). + +### Set up agent communication + +We will need to define a way for the supervisor agent to communicate with the worker agents. A common way to implement this in multi-agent architectures is using **handoffs**, where one agent *hands off* control to another. Handoffs allow you to specify: + +- **destination**: target agent to transfer to +- **payload**: information to pass to that agent + +We will implement handoffs via **handoff tools** and give these tools to the supervisor agent: when the supervisor calls these tools, it will hand off control to a worker agent, passing the full message history to that agent. + +```python +from typing import Annotated +from langchain_core.tools import tool, InjectedToolCallId +from langgraph.prebuilt import InjectedState +from langgraph.graph import StateGraph, START, MessagesState +from langgraph.types import Command + + +def create_handoff_tool(*, agent_name: str, description: str | None = None): + name = f"transfer_to_{agent_name}" + description = description or f"Ask {agent_name} for help." + + @tool(name, description=description) + def handoff_tool( + state: Annotated[MessagesState, InjectedState], + tool_call_id: Annotated[str, InjectedToolCallId], + ) -> Command: + tool_message = { + "role": "tool", + "content": f"Successfully transferred to {agent_name}", + "name": name, + "tool_call_id": tool_call_id, + } + # highlight-next-line + return Command( + # highlight-next-line + goto=agent_name, # (1)! + # highlight-next-line + update={**state, "messages": state["messages"] + [tool_message]}, # (2)! + # highlight-next-line + graph=Command.PARENT, # (3)! + ) + + return handoff_tool + + +# Handoffs +assign_to_research_agent = create_handoff_tool( + agent_name="research_agent", + description="Assign task to a researcher agent.", +) + +assign_to_math_agent = create_handoff_tool( + agent_name="math_agent", + description="Assign task to a math agent.", +) +``` + +1. Name of the agent or node to hand off to. +2. Take the agent's messages and add them to the parent's state as part of the handoff. The next agent will see the parent state. +3. Indicate to LangGraph that we need to navigate to agent node in a **parent** multi-agent graph. + +### Create supervisor agent + +Then, let's create the supervisor agent with the handoff tools we just defined. We will use the prebuilt [`create_react_agent`][langgraph.prebuilt.chat_agent_executor.create_react_agent]: + +```python +supervisor_agent = create_react_agent( + model="openai:gpt-4.1", + tools=[assign_to_research_agent, assign_to_math_agent], + prompt=( + "You are a supervisor managing two agents:\n" + "- a research agent. Assign research-related tasks to this agent\n" + "- a math agent. Assign math-related tasks to this agent\n" + "Assign work to one agent at a time, do not call agents in parallel.\n" + "Do not do any work yourself." + ), + name="supervisor", +) +``` + +### Create multi-agent graph + +Putting this all together, let's create a graph for our overall multi-agent system. We will add the supervisor and the individual agents as subgraph [nodes](../../concepts/low_level.md#nodes). + +```python +from langgraph.graph import END + +# Define the multi-agent supervisor graph +supervisor = ( + StateGraph(MessagesState) + # NOTE: `destinations` is only needed for visualization and doesn't affect runtime behavior + .add_node(supervisor_agent, destinations=("research_agent", "math_agent", END)) + .add_node(research_agent) + .add_node(math_agent) + .add_edge(START, "supervisor") + # always return back to the supervisor + .add_edge("research_agent", "supervisor") + .add_edge("math_agent", "supervisor") + .compile() +) +``` + +Notice that we've added explicit [edges](../../concepts/low_level.md#edges) from worker agents back to the supervisor — this means that they are guaranteed to return control back to the supervisor. If you want the agents to respond directly to the user (i.e., turn the system into a router, you can remove these edges). + +```python +from IPython.display import display, Image + +display(Image(supervisor.get_graph().draw_mermaid_png())) +``` + +![Graph](assets/multi-output.png) + +**Note:** When you run this code, it will generate and display a visual representation of the multi-agent supervisor graph showing the flow between the supervisor and worker agents. + +With the multi-agent graph created, let's now run it! + +```python +for chunk in supervisor.stream( + { + "messages": [ + { + "role": "user", + "content": "find US and New York state GDP in 2024. what % of US GDP was New York state?", + } + ] + }, +): + pretty_print_messages(chunk, last_message=True) + +final_message_history = chunk["supervisor"]["messages"] +``` + +**Output:** +``` +Update from node supervisor: + + +================================= Tool Message ================================== +Name: transfer_to_research_agent + +Successfully transferred to research_agent + + +Update from node research_agent: + + +================================== Ai Message ================================== +Name: research_agent + +- US GDP in 2024 is projected to be about $28.18 trillion USD (Statista; CBO projection). +- New York State's nominal GDP for 2024 is estimated at approximately $2.16 trillion USD (various economic reports). +- New York State's share of US GDP in 2024 is roughly 7.7%. + +Sources: +- https://www.statista.com/statistics/216985/forecast-of-us-gross-domestic-product/ +- https://nyassembly.gov/Reports/WAM/2025economic_revenue/2025_report.pdf?v=1740533306 + + +Update from node supervisor: + + +================================= Tool Message ================================== +Name: transfer_to_math_agent + +Successfully transferred to math_agent + + +Update from node math_agent: + + +================================== Ai Message ================================== +Name: math_agent + +US GDP in 2024: $28.18 trillion +New York State GDP in 2024: $2.16 trillion +Percentage of US GDP from New York State: 7.67% + + +Update from node supervisor: + + +================================== Ai Message ================================== +Name: supervisor + +Here are your results: + +- 2024 US GDP (projected): $28.18 trillion USD +- 2024 New York State GDP (estimated): $2.16 trillion USD +- New York State's share of US GDP: approximately 7.7% + +If you need the calculation steps or sources, let me know! + + +``` + +Let's examine the full resulting message history: + +```python +for message in final_message_history: + message.pretty_print() +``` + +**Output:** +``` +================================ Human Message ================================== + +find US and New York state GDP in 2024. what % of US GDP was New York state? +================================== Ai Message =================================== +Name: supervisor +Tool Calls: + transfer_to_research_agent (call_KlGgvF5ahlAbjX8d2kHFjsC3) + Call ID: call_KlGgvF5ahlAbjX8d2kHFjsC3 + Args: +================================= Tool Message ================================== +Name: transfer_to_research_agent + +Successfully transferred to research_agent +================================== Ai Message =================================== +Name: research_agent +Tool Calls: + tavily_search (call_ZOaTVUA6DKrOjWQldLhtrsO2) + Call ID: call_ZOaTVUA6DKrOjWQldLhtrsO2 + Args: + query: US GDP 2024 estimate or actual + search_depth: advanced + tavily_search (call_QsRAasxW9K03lTlqjuhNLFbZ) + Call ID: call_QsRAasxW9K03lTlqjuhNLFbZ + Args: + query: New York state GDP 2024 estimate or actual + search_depth: advanced +================================= Tool Message ================================== +Name: tavily_search + +{"query": "US GDP 2024 estimate or actual", "follow_up_questions": null, "answer": null, "images": [], "results": [{"url": "https://www.advisorperspectives.com/dshort/updates/2025/05/29/gdp-gross-domestic-product-q1-2025-second-estimate", "title": "Q1 GDP Second Estimate: Real GDP at -0.2%, Higher Than Expected", "content": "> Real gross domestic product (GDP) decreased at an annual rate of 0.2 percent in the first quarter of 2025 (January, February, and March), according to the second estimate released by the U.S. Bureau of Economic Analysis. In the fourth quarter of 2024, real GDP increased 2.4 percent. The decrease in real GDP in the first quarter primarily reflected an increase in imports, which are a subtraction in the calculation of GDP, and a decrease in government spending. These movements were partly [...] by [Harry Mamaysky](https://www.advisor``` +``` + +!!! important + You can see that the supervisor system appends **all** of the individual agent messages (i.e., their internal tool-calling loop) to the full message history. This means that on every supervisor turn, supervisor agent sees this full history. If you want more control over: + + * **how inputs are passed to agents**: you can use LangGraph [`Send()`][langgraph.types.Send] primitive to directly send data to the worker agents during the handoff. See the [task delegation](#4-create-delegation-tasks) example below + * **how agent outputs are added**: you can control how much of the agent's internal message history is added to the overall supervisor message history by wrapping the agent in a separate node function: + + ```python + def call_research_agent(state): + # return agent's final response, + # excluding inner monologue + response = research_agent.invoke(state) + # highlight-next-line + return {"messages": response["messages"][-1]} + ``` + +## 4. Create delegation tasks + +So far the individual agents relied on **interpreting full message history** to determine their tasks. An alternative approach is to ask the supervisor to **formulate a task explicitly**. We can do so by adding a `task_description` parameter to the `handoff_tool` function. + +```python +from langgraph.types import Send + + +def create_task_description_handoff_tool( + *, agent_name: str, description: str | None = None +): + name = f"transfer_to_{agent_name}" + description = description or f"Ask {agent_name} for help." + + @tool(name, description=description) + def handoff_tool( + # this is populated by the supervisor LLM + task_description: Annotated[ + str, + "Description of what the next agent should do, including all of the relevant context.", + ], + # these parameters are ignored by the LLM + state: Annotated[MessagesState, InjectedState], + ) -> Command: + task_description_message = {"role": "user", "content": task_description} + agent_input = {**state, "messages": [task_description_message]} + return Command( + # highlight-next-line + goto=[Send(agent_name, agent_input)], + graph=Command.PARENT, + ) + + return handoff_tool + + +assign_to_research_agent_with_description = create_task_description_handoff_tool( + agent_name="research_agent", + description="Assign task to a researcher agent.", +) + +assign_to_math_agent_with_description = create_task_description_handoff_tool( + agent_name="math_agent", + description="Assign task to a math agent.", +) + +supervisor_agent_with_description = create_react_agent( + model="openai:gpt-4.1", + tools=[ + assign_to_research_agent_with_description, + assign_to_math_agent_with_description, + ], + prompt=( + "You are a supervisor managing two agents:\n" + "- a research agent. Assign research-related tasks to this assistant\n" + "- a math agent. Assign math-related tasks to this assistant\n" + "Assign work to one agent at a time, do not call agents in parallel.\n" + "Do not do any work yourself." + ), + name="supervisor", +) + +supervisor_with_description = ( + StateGraph(MessagesState) + .add_node( + supervisor_agent_with_description, destinations=("research_agent", "math_agent") + ) + .add_node(research_agent) + .add_node(math_agent) + .add_edge(START, "supervisor") + .add_edge("research_agent", "supervisor") + .add_edge("math_agent", "supervisor") + .compile() +) +``` + +!!! note + We're using [`Send()`][langgraph.types.Send] primitive in the `handoff_tool`. This means that instead of receiving the full `supervisor` graph state as input, each worker agent only sees the contents of the `Send` payload. In this example, we're sending the task description as a single "human" message. + +Let's now running it with the same input query: + +```python +for chunk in supervisor_with_description.stream( + { + "messages": [ + { + "role": "user", + "content": "find US and New York state GDP in 2024. what % of US GDP was New York state?", + } + ] + }, + subgraphs=True, +): + pretty_print_messages(chunk, last_message=True) +``` + +**Output:** +``` +Update from subgraph supervisor: + + + Update from node agent: + + + ================================== Ai Message ================================== + Name: supervisor + Tool Calls: + transfer_to_research_agent (call_tk8q8py8qK6MQz6Kj6mijKua) + Call ID: call_tk8q8py8qK6MQz6Kj6mijKua + Args: + task_description: Find the 2024 GDP (Gross Domestic Product) for both the United States and New York state, using the most up-to-date and reputable sources available. Provide both GDP values and cite the data sources. + + +Update from subgraph research_agent: + + + Update from node agent: + + + ================================== Ai Message ================================== + Name: research_agent + Tool Calls: + tavily_search (call_KqvhSvOIhAvXNsT6BOwbPlRB) + Call ID: call_KqvhSvOIhAvXNsT6BOwbPlRB + Args: + query: 2024 United States GDP value from a reputable source + search_depth: advanced + tavily_search (call_kbbAWBc9KwCWKHmM5v04H88t) + Call ID: call_kbbAWBc9KwCWKHmM5v04H88t + Args: + query: 2024 New York state GDP value from a reputable source + search_depth: advanced + + +Update from subgraph research_agent: + + + Update from node tools: + + + ================================= Tool Message ================================== + Name: tavily_search + + {"query": "2024 United States GDP value from a reputable source", "follow_up_questions": null, "answer": null, "images": [], "results": [{"url": "https://www.focus-economics.com/countries/united-states/", "title": "United States Economy Overview - Focus Economics", "content": "The United States' Macroeconomic Analysis:\n------------------------------------------\n\n**Nominal GDP of USD 29,185 billion in 2024.**\n\n**Nominal GDP of USD 29,179 billion in 2024.**\n\n**GDP per capita of USD 86,635 compared to the global average of USD 10,589.**\n\n**GDP per capita of USD 86,652 compared to the global average of USD 10,589.**\n\n**Average real GDP growth of 2.5% over the last decade.**\n\n**Average real GDP growth of ``` +``` \ No newline at end of file diff --git a/docs/docs/tutorials/multi_agent/assets/diagram.png b/docs/docs/tutorials/multi_agent/assets/diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..8aaad47591014bf58887f4697663a977a8141ae9 GIT binary patch literal 25505 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 ZJpWr-)bP~I#WZA4@kcTbbM9-u{a-{_0=57E literal 0 HcmV?d00001 diff --git a/docs/docs/tutorials/rag/assets/screenshot_2024_02_14_3_43_58_pm.png b/docs/docs/tutorials/rag/assets/screenshot_2024_02_14_3_43_58_pm.png new file mode 100644 index 0000000000000000000000000000000000000000..65402f1e047a8b2767e3162bb7e9b9f2497ab761 GIT binary patch literal 104631 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%0Ag{=VjqA7f@stk$0!V*--xvZQmVFbsPR4 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 U@L>6#8U`TnboFyt=akR{0ODduAOHXW literal 0 HcmV?d00001 diff --git a/docs/docs/tutorials/rag/langgraph_agentic_rag.ipynb b/docs/docs/tutorials/rag/langgraph_agentic_rag.ipynb deleted file mode 100644 index e9fe98d47..000000000 --- a/docs/docs/tutorials/rag/langgraph_agentic_rag.ipynb +++ /dev/null @@ -1,928 +0,0 @@ -{ - "cells": [ - { - "attachments": { - "7ad1a116-28d7-473f-8cff-5f2efd0bf118.png": { - "image/png": "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AQQQQAABBBBAgOAJ9wACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggEBIgeBLCoIsAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIEDzhHkAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEQgIET0IYdBFAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABgifcAwgggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIBASIDgSQiDLgIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCBA8IR7AAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBAICRA8CWHQRQABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQInnAPIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIhAYInIQy6CCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggADBE+4BBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQCAkQPAkhEEXAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEECB4wj2AAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCIQECJ6EMOgigAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgRPuAcQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAgZAAwZMQBl0EEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAgOAJ9wACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggEBIgeBLCoIsAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIEDzhHkAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEQgIET0IYdBFAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABgifcAwgggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIBASIDgSQiDLgIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCBA8IR7AAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBAICRA8CWHQRQABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQInnAPIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIhAYInIQy6CCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggADBE+4BBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQCAkQPAkhEEXAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEECB4wj2AAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCIQECJ6EMOgigAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgRPuAcQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAgZAAwZMQBl0EEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAgOAJ9wACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggEBIgeBLCoIsAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIEDzhHkAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEQgIET0IYdBFAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABgifcAwgggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIBASIDgSQiDLgIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCBA8IR7AAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBAICRA8CWHQRQABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQInnAPIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIhAYInIQy6CCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggADBE+4BBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQCAkQPAkhEEXAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEECB4wj2AAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCIQECJ6EMOgigAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgRPuAcQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAgZAAwZMQBl0EEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAgOAJ9wACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgggEBIgeBLCoIsAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIEDzhHkAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEQgIET0IYdBFAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABgifcAwgggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIBASIDgSQiDLgIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCBA8IR7AAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBAICRA8CWHQRQABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQInnAPIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIhAYInIQy6CCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggADBE+4BBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQCAkkD/Up4sAAggggAACCCCAAAIIIIAAArkk8N5779n48ePt0EMPtWeffdby5897f6Lv2LHD7r77btu1a5c1a9bMunbtmks6uXOYjRs32gMPPBD3YHfddZfVrFkz7jJmIoAAAggggMCBL3DI31478C+TK0QAAQQQQAABBBBAAAEEEEBg7wssXbrUPvvsM5sxY4ZNnTrV1qxZY0ceeaT/OvHEE61t27bBSdx00002cOBAf3rmzJlWuHDhYFle6Wzbts3q1avnn85pp51mr7/++l49tVmzZlnPnj3jHuOQQw6xKlWqWO3ate3MM8/0+3FXzMLMFStWWKtWreJu8eWXX1rz5s3jLmMmAggggAACCBz4Annvay0HvjlXiAACCCCAAAIIIIAAAgggcAAKDBo0yLp162abNm2KurqxY8eaXn379rV7773XbrjhBlMggJZeYP369TZy5Mj0C2LmPP744/bwww/nOBOmaNGidsUVVwR7nzRpkk2ePDmYpoMAApkLzF2+yT7+ZbHNWLjRFixLse3bd1mVCkWsfrXidupRFa19w3KZ74ClvsD2nX/bzzNW+/0qZQpb/SrFkEEAgTwgQPAkD3wInAICCCCAAAIIIIAAAggggMD+LfDuu+/aQw89FFyEsjWOPfZYK1u2rI0ZM8Z++eUXf1mfPn2sc+fO/vxgZTpxBRo0aGBVq1YNlimLZ+LEicH0o48+ag0bNrQ2bdoE87LaKVasmPXo0SPYTJk1BE8CDjoIZCrQb/Qie+GzWenWWeQFVPQaOn65de5Uw+44q54XME63GjNCAms3brV7+0zx5xzbpJz16to0tJQuAgjsKwGCJ/tKnuMigAACCCCAAAIIIIAAAggcEALJycn21FNPBddy55132s03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IECgh8MffvihValSJdOzGzRokHXr1s02bdoUtZ6CB3r17dvX7r33Xrvhhhu8bw3vv18brlChQmBTunTpqGuNnVi3bp116dLFn33ppZfa448/HrvKbqezcrzd7mwfr6AH+gpOuTZp0iSbPHmym9wr7wsWLLCRI0cmtO+KFSsmtF5eWil//vx2/vnn+6/777/frrvuOhs9erT/c/jwww/7wcy8dL6cy+4Flq1LtUufHWspm7b7K+c79BBr4gUMWniv1vXLRO3g2ld+t+R/1rvyxJp22lHRgZUXB/1lP/2xxqqVL2zPXdkkats9PbF5606bPHudv9uSRQt4wZOcH+GkphUsJXW7TZidbNPmJJuycXSMi5781d67q5WVLZaU84OwBwQQyJYAwZNssbERAggggAACCCCAAAIIIIDA/iywatUqv26CrkFDEqnmSZky0Q/sYq9PdRYeeuihYHa9evXs2GOPNQ0pNGbMGPvll1/8ZX369LHOnTv784OV97POE0884QeClH1z1VVX7fWzz+3j7c0LKlasWFRWz+uvv77Xgyfh6+nQoYMVKFAgPCuqv79naSg49fbbb5syovRzN378eP+ljDHa/iPw3Fezg8BJMS8I0ffOllajbOG4FzB93nrb/k9NkNe/nZsuePLn4o22YGmKrduwNe72eX1mhZIF7bqTvYy9k81mLUmxa14cb6lekGb1uq32xuB5dv8Fh+f1S+D8EDhgBQieHLAfLReGAAIIIIAAAggggAACCCCQkYACIa5pCKPdBU6Sk5PtqaeecpvYnXfeaTfffLPly5c2pIrqpgwYMMAUBPj000/368CJLlKZOI899lhwvXu7k9vH29vXsy/3/+qrr5oCOAdyS0pKsptuuskPnug6X3vtNb/+yYF8zQfSta1ITrVRk1b6l1TIG5bq4/taW7niBRO6xOWrt9g0b5ivRjVKJLT+/rZS/arFrN+9re2inr/6GSgDf15iN59e10oU5hHu/vZZcr4HhgA/eQfG58hVIIAAAggggAACCCCAAAIIZEHg+++/D9a+8MILg35GHWUPuKG6lImhYElsUwH28847zzTEUGxT8EU1KaZPn24aYkkF2JUBcMEFF5i+SR/bvvrqK39dFa6/8sor/ToPymzR9nXr1rWTTz7ZOnXqFLuZP71r1y6/PoS+ka+6LPXr17czzjgj01okf/31lx/8ibfDs88+26/nEl6mOi9vvvmmPyslJSVYpHNUACm2de3a1cLDRWX1eLH707T28d133/nXqKHDGjZsaM2aNfOv9dBDD43aJHy++owKFixow4YNs59++sm0buPGje0///mPlSpVKmo7TUybNs2/VgXK9NkqG0c1bo4++mirUSPn9Q7SHXAfzFAGx4gRI/wMmeLFi/uGJ510UqZnktF9pmysl19+2f95kZHu1dimnyX9PMycOdNmzZrlZ38dfvjh/s+D6uYk0lRbSP6qyfLjjz+a6qLE+9lLZF+sk7sCb/wwPzjghR2qJxw4cRu9N3yBPX1FYzd5wL1XLVPYTmlT2b79ZakfQHnXu95bvAAKDQEEcl8g/W90uX8OHBEBBBBAAAEEEEAAAQQQQACBXBWYPXu2fzwNcRTvgXnsyajWiWvXX3+966Z7j/fwduLEif7QV3qA75rqo3z88cfWu3dv/8F8gwYN3CL//YcffrCBAwf6GSwlSpSwe+65J1iubT/66CO79dZb7a677grmq7N582a7++67LXy+CqL069cvasixqI28ifnz55sCRPHaEUcckS54snr16rjrz507N+78s846Kyp4ktXjxZ5X//79/doy4flu2DQ9lH/uuecsXKtF9u769MD9pZdeCoqOax96+P7ee+/ZN998Y1WrVg3v1g/OKJgVr6nGy4MPPmiFChWKt3i/mKdMlXBWlU568ODBmQ7Xltl9Juf/+7//869dtV9igycKRqkmkIIesU11iJ5//vl028Sup2kFvU4//fTgc125cuVuaxbF2w/zcl9g9JS0rBMd+ZL21bN8AiMnrrSUzjutWKG0zL/d7WBNyjbrP3qRTfcyVpZ4mSvVKxSxRjVL2CXtaljxDDI6vLIj9vHPi23c7LU2xxtKq3blonZWy8pWr2rx3R3O5q3YZF+MXWozF220lV5tlxoVi1pj73gqLl84KbFzvuL4mn7wRAcbOWUVwZPdqrMCAntHgODJ3nFlrwgggAACCCCAAAIIIIAAAnlUYP369cGZJfItd32j3T3obdeunam4eaJN37D/97//HWStKMukadOm/jf8tUz7vfbaa/0siHh1KvTQv1evXn52Sng7Hf/FF1+0c889189Ecefz1ltvRQVOlDWiwvUKDrgH2m7d8LvqtnTs2DGYtWTJEnMBpmBmqKPsBPdQfMuWLX7x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yodqiVQtGwmkL1gVGc7LnePO6H9W3WyrUykyVJ6Kw//yXKcMXy9d0yzYLqPOmpRttnpd2rBjZUtxb2fkxHwE9rYAmSd7W5j9I4AAAggggAACCCCAAAII5DmBq666yj744AP/vPr06WNnnXVWpt+Cb9KkiZ199tn29ddf+9vceOONdsopp1iHDh1MBdw3b97sP8j//fff7aSTTrJLL73UX++6666zL774wu/36NHDL5CtQMmECRNMx3XtP//5j+tm+/2II47ws030jX5lSdx999128cUXm7IH9G3/1157Le6+FWRRBk44MyWc1aEH/uH6Ii1atLDwkE/a6VFHHWXKAlAwqnPnzta1a1e/4LiOrQLrumYNeaWWneNpO3fM22+/3VxGiI7VvXt3UwBHzrp2NWUWqQh6Tppq0ihQoACKPAcMGGDHHHOMaQg2BU6ef/75YPdarswH3Se1atUK5qsTDjb07NnTX3b44Yfb6tWrbdq0af69ovPdU02ZUZllUimo1L59e79A/LXXXmu9evXyD6179p577jFlEukz/+ijj+KeUnbvM+1MPzfar+6T3r172+DBg+344483BTPlpyLy8+bNs3/9619BYCfuSXgz33777WDRTTfdFPTp5H2BJnVL2i9TVvvBiy/HLrVL2mU9S6yhV3ukcvnCtmzVlmB4rtgrr12lmE2elVak/d0RC+zm0+oGq/QeMj/o16sayVypXSEynNxnPy32z02BGNe+HLPEdaPelQ2jYI2GAJvsFYbXdZ3bqkrUOlmZ+Gj0omD1o+qXDvp0EEAgdwUO8X5pySBmmrsnwtEQQAABBBBAAAEEEEAAAQQQyE2B66+/3lRcW+20006zF154IdNvrycnJ9sjjzwSBEMyOtd27doFgRmt89hjj0UFSmK3u+uuu+zWW2+Nmq2HwQMHDvTnzZw5M+phuOq0tG7d2l92xRVXmIIyro0bN84uvPBCNxn1ruCFy3wIb7dt2zZ/eLGolTOZGD58uB+cCK+iIMAZZ5wRnhXVv/POO81l72TneNqZCzBoe12jyzqIOtA/E8rqUYDANdUnUVBLTeeh8wm3//73v+YygWToskUUcMooQ0JBJNVV0XBurt1www123333ucngXYG3jM739ddf9++/YOVsdHTvPvfccwltqYDaM88846+rYIWCTBkNt+aGt9O7PnfXMrvPwnVNwveZ21YBEwVtMmvKkgpnbYXX1WOsp59+2l599VV/toJTqk2TL1++8Gr087DArCUpdtkzv/lnWMbLqvj6weMyHZaq7d3D/QDJiS0q2eOXHhlc2YBfltizn8wMphW8GNIz8nM/ef56u/b58cHyM46t6heOH+cFNzTkl2v97z/Galco4ibt3Md/8YMymnH0EWWsS/satm3HThvvZbh8NXpxkLHSvlkFe+Y/jYPtRkxbZff2mRJMlytd0No0LGfHefsonJTflO2SvGmbdT2hVrBOvI6GGTvtodG2OXWHv/jLh4+zyqHsmHjbMA8BBPaOAMN27R1X9ooAAggggAACCCCAAAIIIJDHBdzDfJ2mgiiXXHKJafiiP//803buTD+UjB6UK9tAGSMaxskNeeQuU0XflY0SfmivZcqS0IPt2KLweuj7xhtvpAucaJvwg+DYAufhaWVHhFvLli39IcVclodbpgdWlc9LAABAAElEQVT9OlbsOWt5eH9u/cze462vB939+vUzDZ8Ur6kGi2vxtnfL4r1r/fA2yoz49NNPTVk9sdej2jR6OB/7GYQ9Y810zPC8cF8P+bt16xZ1HB1TgSIN3xYuYB/v3N28V155JV0NGi3TvsIZP279rL6Hz3l324YtNXTXkCFD7MQTT4zaTMESZbA0bhx5MBxeIbP7TC6uuSHW3LTe9TOiTJ3zzz8/yjW8zsqVK8OTfl8ZQMr8UoDKBU60QIGv8OebbkNm5DmB+lWLWYPaJf3zWpu81a55eYJlVJcks5M/q0Vly6y2SNNaJa3T0ZWCXQzygi1P9Z8RFTg5r321qMCJVr7ngsODbSbMXGt3vznJ7n97qn0+cpEVz6BgvDbo2Ki8nX5MJNtEw24N/HmJdX9rqt3+2kT/2G98M8fLvgt2n66j4cUu7zUuCJwc26QcgZN0SsxAIPcEyDzJPWuOhAACCCCAAAIIIIAAAgggkMcEZs+e7Q8x5WpbuNP78MMPrW3btm4yw3d9c1/DUmnIIQ0dtbu2fv16U6F4BVISffC+u31mtDwlJcWvWVGtWrUgc2Xt2rV+do2GdcrKA/eMjhFvvmpnqFaGggJ6qK2gk4b9Cj+0j7dddufpWFu2bDFdZ7h4fXb3F2871VPRA30dp2bNmsEQb7pWLVO9DRWG1yuz63Q2Wkf3izJcMls/3rnsrXnK6FGQS59XmTJl/MNoiDJlehQpUiS45tjj6z5btGiR1fKGK9N99e233/oBDq2noOEFF1wQu0nUtDK69DOh+0XBJBWkj/0cw9lWbmOt++abbyb0c+q24T3vCMRmhVQqV9jOb1vNjq5Tyhp4BeDDQRGXeXJK68rWo0t0fahHP55h3/661L+wUiWSbHCPduku8sNRi+zNQXMsNVRfpUih/Hbb+fUyHFpr4txku++dqZa8IVLUXufY6+qmdunTv/nZJ7GZJ+7AY73MlicHzLQlK9PXTNE6gx5ra+WKR+qYbPcKqUxftMHG/bXONFSYAkpqMnj/ntZWt1JkKDF/Af9BAIFcEyB4kmvUHAgBBBBAAAEEEEAAAQQQQCAvCiigoKGZVPfDBVH07fmLLrooL54u54RAnhVQxpaCJaqxo/bZZ5+Zsp5y2jTkmYY+U1M2S6tWrfz6LG4ot5zun+33jcAMr2D8jS//HmRZuLN44qrG1qlxBTe5x97XekXYl3tDZ6kofMkiaUXrd7fzDV4myJI1XtC0fBEr4tU1UVu9casVzJ/PinoBGC++kWFThsmy5FRbs2GrHyQt7WWtVCpVKCowpI0//XWJPfNxZPgxzdMQZG/ecrTVrkjgRB40BPaVAMGTfSXPcRFAAAEEEEAAAQQQQAABBPKcgDJJlI2iLIYqVSLDr+S5E+WEEMgDAgqWpKam+oXeNdydhtMaPz6txoSGcPvyyy/3SIaTMramTp1qhx12mJ+ZkgcunVPYQwIKRDzqDaU1bc76IIhyy3n17NIONfbQEfL+bl4c9Jd9OGSBf6LFihawo+qVtgc7N7AShfPn/ZPnDBE4wAUInhzgHzCXhwACCCCAAAIIIIAAAggggAACCOxJgZ49e1rv3r0z3aUCJ6pBQ0MgUQEFUmYuTrEaXvH2Gl52yMHS5i7fZEu9jJhGNYpbqaJJB8tlc50I7BcChDD3i4+Jk0QAAQQQQAABBBBAAAEEEEAAAQTyvkC7du3sscces9q1a+f9k+UM85SA6oC0bRCpBZKnTm4vnkwdr6aJXjQEEMh7AgRP8t5nwhkhgAACCCCAAAIIIIAAAggggAACeVagY8eOfsH7ggULWqFChfyXgiUNGzb0i77n2RPnxBBAAAEEEMiCAMN2ZQGLVRFAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQODAFzj0wL9ErhABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQSFyA4EniVqyJAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACB4EAwZOD4EPmEhFAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQCBxAYIniVuxJgIIIIAAAggggAACCCCAAAIIIIAAAggggAACCBwEAgRPDoIPmUtEAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQACBxAUIniRuxZoIIIAAAggggAACCCCAAAIIIIAAAggggAACCCBwEAgQPDkIPmQuEQEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBIXIHiSuBVrIoAAAggggAACCCCAAAIIIIAAAggggAACCCCAwEEgQPDkIPiQuUQEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBIXIDgSeJWrIkAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIHgQDBk4PgQ+YSEUAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAIHEBgieJW7EmAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIHAQCBE8Ogg+ZS0QAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAIHEBQieJG7FmggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIHAQCBA8OQg+ZC4RAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEhcgeJK4FWsigAACCCCAAAIIIIAAAggggAACCCCAAAIIIIDAQSBA8OQg+JC5RAQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEhcgOBJ4lasiQACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAgeBQP6D4Bq5RAQQQCBPC7z33ns2fvx4O/TQQ+3ZZ5+1/Pnz3j/N//vf/2z58uXpHM8991zr1KlTuvmJzpg4caL17dvXX71r167WrFmzRDdlPU9g+/btdv/999vQoUPtuuuu81/AIIAAAtkR+GDkQhs1bXW6TRvUKG53nFUv3XxmIIAAAggggAACCCCAAAIHukDee0J3oItzfQggcMALKMjQu3dvmzBhgs2aNcsKFSpkjRs3toYNG9pll11mVapUiTL47bffbODAgf68J554Ik8GT4YMGWJz586NOm9NNGrUKEfBk8WLF9tXX33l7/fUU0/NcfDk66+/tk8//TTdeRYoUMBq1qxphx12mJ1zzjlWtGjRdOvkZMbatWtt5syZ/i4OP/xwK1u2bE52l/C2w4YNs08++cRfXwGus88+2ypXrpzw9qyIAAJ7X2Dg+GX23rCFCR+ofMkke+W65gmvv6dWnDxvvU2evS7d7jZs3mF2VrrZzEAAAQQQQAABBBBAAAEEDngBgid56COevTTFHvjgj+CM2h5Z1m4947Bgen/ujPtrnW1K3WGFC+az1vXK7M+XwrkjkKnATz/9ZP/+97+j1tm0aZONGDHCf7377rumh9zK2Nif2nnnnWerV6d9I3nZsmX2ww8/5MnTX7hwoY0cOTLTc1N2z8svv2zHHntsputlZaECYNdff72/yUsvveQHMbKyfXbXLVmyZNSmRYoUiZpmAgEE9r3A4jVbbIH3O16ibdXaffPreZvDo38/GzVpZaKnzHoIIIAAAggggMB+KzB40gqbszzFFq9OtRTvudXVJ9WyepWLWeGkfPvtNXHiCCCw5wT2zV9ne+78D6g9/TB5RdQf1yu8P7YPlODJfX2nWsqm7VakUH4b/mSHA+pz42IQcAJbtmyxa6+91k1ajRo17Pjjjzc90B49erRNmzbNFEjp0aOHdejQwUqXLh2sm9c7t956a3CKGmorrwZPgpP0Ou3atbOCBQv6s5QBpMCK2po1a+zqq6/2P5PcyhDxD7wX/tO6dWs/GDdu3Dg/IBcbTNkLh2SXCCCQRYGa5YtYvRolorZatGKTpW7d6c+rW624N2zjIcHycl7myb5oFxxT1fRyrfXtQ12XdwQQQAABBBBA4IAS+GPRBhsxbZWNm7XOZnjZt+H22z/DmDatV9pOPbqinX5UJStEICVMRB+Bg0qA4Eke+rhHTokeZ1p/VM9cvNGO8P6opiGAQN4X0ANsBUfUGjRoYN9//31w0vfcc4998MEH9uqrr1q/fv32q8BJcBH7WUfZJaVKlQrOWsGrhx9+2K8vo89Jw3upTsj+3A455BA/0yk222l/vibOHYEDTeA07w9uvcLtfi/TeOj4tDpSH9zVykKxk/Bq9BFAAAEEEEAAAQT2kMBPM9bYb7PW2PjZyTbXe9amVtj7gm/VKpFs/i1e5snmzdssNXW7P5yphjR98cu/rH3TCnZi0/LWvmG5PXQ27AYBBPYXAYIneeST2rBlhy1Yljakw5nHVbWBPy/xz2zo1JUET/LIZ8RpILA7gUWLFgWrXHzxxUFfHRWDv/zyy/2aJ3rgnVFTAfBRo0bZL7/8YtOnT7e6devaySefnGldkeTkZPv888/99RcsWGC1a9f2a5FccMEFcWt7vPPOO6aht4oXL24333xz1KmobscXX3zhz9PQYgoC7YmWkpLi1+aYMmWKyemYY46xM844Y0/sOuF9qD6LMk7Gjx/vb6NslHhNtWr0Gchf2USqYdKyZUtTTZZwUwaOC5CF9/XZZ5/ZH39EhmDUNklJSXbXXXcFmz/11FO2a9euYLpFixZ20kkn+UO76bNcsmSJ1apVy//sTznllGA9dd5++21bsWJF1DxNKFB0ww03pJsfnqFjfvfdd6Zz12etzBx9xieeeGK6ejPffPONny2l7bt06eKfT3hf6s+YMcO+/PJLf3arVq3shBNOiFpFQSpdj44lI9VjkafuzUqVoh8mR23IBAIIRAmsSdlm/UcvsukLN9iS1VuseoUi1qhmCbukXQ0rXjjjX+ezu13UwZlAAAEEEEAAAQT2U4E/l6TYj1NXmL6s7IZRVcCk0RGVrH7NslajSilvePn0v0tt2brD/lq41uYtXmfzFq21wb8t9V//PqnmATNCzH76kXLaCOS6QPp/IXL9FDigBEb9sSqAOLtlZRv/51pb7v1xrH/gbzqtbrAstjNq+mr7cfJKm75ggz8k1hktK9mZLSqbipNO8+ap6Gi8ob9SUnfaR6MX2nQvVXHesk1WoVQhq+9luHRpV82qlikcexj7+OfFwf5uOLWuffv7cvvpj9U2e8lGq1GxqPeNyorpvlX5xOd/2mbvOGpbvOCQ2mYviv9gv+l+P/wfbX/sEblTYDl8XPoI7EmBcuUi30LRA/orr7zSYgMlsdOxx1c2xKOPPhrMHjt2rH300UemYbPCD9/dCnoIftVVV/lDUbl52ubjjz/2i9a/+eab6QIgAwYM8B+Ka8iq2ODJvHnz7PXXX/d3deSRR6bb1h0jK+8aLqtr1642e/bsYDP5qDZI9+7dg3m50TnuuOOCw6xaFfl3VzN37Nhhqofy2muvBeuooyHX+vTp4wcyevXqZcWKFfOXK0DirMIbuPo24Xnqhz8/ZSCF25lnnmnbtm2zG2+8MZgtI90Pjz32mB94cwtUIF5Bi9imwERmwRMNV3bnnXf6AZrwtj/++KP/Wdx+++12xx13BIsUOHLXpyCLto1t/fv3NwXj1I466ij/3f1HmT46Hzdcmpuv91deecWef/553zQ8nz4CCKQXGDNrrd395mTbviMScF22aouN/WON9R+2yJ6/vpk1rRX5xqTbQ3a3c9vzjgACCCCAAAII7K8CUxestz5D5tuYf4bg0hCpR9SraHWrl7Z6XtAkXsAkfK1a3rheBf/1999/25/z19jIcfPtwyELbNjkVXb/RUdYK29YLxoCCBz4AgRP8shnPHRKWlHOfN4/6I1rlrTjGpWzz0Ys8rNRlJVSIs63Cv/v69n2ybC0MfzdZfw5f71NnJNsC1dutjleGmKxogXSBU8mzk22O70/whXIcE1/hCsd8fORi6z7JQ3sLC8AE24//L7Cpnn7LZD/UCtRpIC99tVfwWJtqzEhx3vLH/T+B+LaNz8tsZ27/naTwfsPY5cFfdepVLogwROHwft+K9CsWbPg3AcNGmTKInnooYesevXqwfzddfTwXg/B27ZtaypC7h48v/jii35NC2WiuKZv9Wu4JjdUWNGiRa1p06Y2efJkf562VQ2WYcOGWYECBdxmuf7erVu3IHCia1MtkrVr15oe2uu6crP9/vvvweFkFW4aTi0cOFFBeWWMuOHYVOdFQQ8NwaZWrVq14OG/smlcQEOZHLGfufYTbsom0S/hP//8s/9ZzZ8/39544w1/FWUaKYjlgk0KMlxyySWWP3/a/7KV4VGxYsVgdwrWJNIeeOCBIHCie0XZNDt37vSDQ9pex2nevLl17NjR353OUZ+dmrKRYoMnymJRdoprquPjmgIvyrRSwEZNn3vjxo1t6dKlQe2fa665xpTlEw46uu15RwCBNAF92eXO1ycFv0/p98QqXtbJUu/3PP2Opd/lbveWD+7ZzpK839Fcy+52bnveEUAAAQQQQACB/VXgzSHz7P0f5tu27busUKEC1ujwSta0fiWrULZIti5JX4A8onY5q1G5pA0fO9+mTF9qt7zyu3U8upI9ddmR2donGyGAwP4jQPAkD3xW3vMzGzd9rX8mTbzItfd3sT+OooInaspKUTZJuI2eviYqcFK7anErXyrJC3Cst+FeoENBjnhts1dH5ZZXJwbfXixUMJ/VqFTUVq/famuTt/p/iPf8YLq1rlfGKpQsmG4X+tZj3+/nWewf71pRQ41dfGw1O7xq2reydS2b/gnQzPKyYFyr7w0zEdtqVygaO4tpBPY7AT3QVpbAgw8+6J+7Hrbrdf755/sZBfXq1dvtNekBc9++ff0i83q4rswMZZ6o/frrr/4wXm4n7777bhA4UUBCWSYqTr9+/Xp/eDAFURRAUfaChl3aF02ZMWPGjPEPraCCMmJcUfNJkybZOeeck2unpeBGODii4IFrGlbsySefdJP+cFxuyLLVq1fbRRddZHPnzvUzJpTpo6wdBRlcoEFDYV1//fX+9soeOfvss4N9xevos1JTAEH3iLI0FNBQ0E3DiykwoftGfgpA6OUCJj169IjapYbccoGWqAWhCe1H56im/b/33nv+NWh66tSppswXtWeeeSa4Jn1OGlpN56T7SH7OROvq/nLBkc6dO3t/mBTSbL9p/26Z7r2ePXsGwR8tcz8jyui577773Ga8I4BAjMAbP8wNAic1Kxezvre3sKLe725rvWG8Lvu/sbZ63VY/gPLBSC/D74RawdbZ3S7YAR0EEEAAAQQQQGA/FAjXlWvRtLq1aVzVihdL/2wrO5dWxAvEnNG+nlWvVMJGeVkoIyYst1u9Z2wvXt0kO7tjGwQQ2E8E4j9h309O/kA5zWkL1wfBjHZHpg37c3TdSPqfy0oJX+8rg+YEkzedW8/6d2tlL13TzP/mYZPDSgf7C1b6p6M/pt2wD6297JYf/9fB3r+jpX33SFu78rTaweovfxvZfzDzn04RLwvmq0eOs0/va2PDnuxoTUOpiqNnRIbBef2G5v6+tX9lwKgV8caW1HTs63QvYk9D4EAQ0LftVeNB37R3TdN6wK0Hxhs3phWmc8ti32+77TY/AKL5+oZLOLgQrqmi5UOHDtWb37RvBU7U9NBbWQauDR8+3HVz/f2nn34Kjqmhx1zgRDOVqaOMir3VVAz+iiuu8F/HH3+8X7PEBXIUqAgPM6UAgsvgufTSS6OCBMqMUPDEtTlzMv730a2TnXfdOwpsqKlGjjJMXFMAJydNNVxck4uCP64pYKfgm5qCOMqYck0BHNcU5Am3IUOGBJPh+1QzlVXkmj53lzWjeeF6QArA0BBAIGOBUVMiv1c91KWBHzjR2mWKJdl9F0VqUo2YGv1vRHa3y/hMWIIAAggggAACCORtAY3OMnT8cm+Y5YLW+cwmdtIxdfZY4CR85U3qV7QupzexKl4mym/TVtmNb04JL6aPAAIHmADBkzzwgQ6bGvnD2AVPCuQ7xA7/Z/xqZaUoO8W17Tv/tnlerRE1BSUu61DDLfKHbHjQ++M6ozYy9Ef43efVNx3HtSuOr+m6fg2VYCKmc+d59ax8ibTIfaGkQ+1f7asFayxYuSXo00HgYBU4+uij/WwC1RPRQ3rX9I17PYTP7EF4eFgubafi765pKKRw09BOanoQriLc4RbOqlDGxL5qGqbJNQ2DFdsaNmwYO2uPTStQoiGt9AobKEChQICrXaIDhgNTRxxxhF/wXTVN3Kt8+fLBeYXXDWbugU5sYXgNk6XsHL10TjlpGhbMtapVqwbX5a4vfJ+FP7P27dsH97ArDO/244bs0v3XunVrN9t/dwGmOnXq2Lp166KOp2VuyLQ///wzajsmEEAgWmCNlxWspoziRjWiM3ePaxAJgi5bvTlqw+xuF7UTJhBAAAEEEEAAgf1E4J3hC4LRWU5rX9/qVIt8IXlvXELZ0oXtkjMaW/26FWzC9FV2S5+pe+Mw7BMBBPKAAMN25YEPYbhX8F1NgZAaZSPF2tt7mSGqYaJMEWWnqBaK2rLkVP9d/2nj/eHsfTk9qmkfGlYrXr0RDe+gpmOt27DVf4U3LufVHtE6KlafUTuyRnRR0sO9IcNcS92203V5R+CgFihRooRfL0IFs1Xg2xWB19BHGh5KtU3iNW2XSNu6dWswLJJqb8Q2ZS4o+2XZsmW7HdIpdts9OR1+EB/OOnHHKFWqlOvu8XcFa9xQUnKXhdp///tfv15J+IDh89TyzFpycnJmi7O9rEqVKlHb6tzd+UctyMaEq52jTcPZJPF2tWFDZJhF1WpRwE9F4RWAmjVrltWvX99mzpwZ1OPR/sKZJeF7U9ucfvrp8Q7jz3NDe2W4AgsQOIgFUrftCrKFSxZPX7dKw7xq+NVUb7iIDSmRjLHsbncQU3PpCCCAAAIIILAfC3z7+/KgLm+HNnXssBplcuVqCuTPZxec1MB+KJpkY6cstrvfmWLP/ochvHIFn4MgkIsCBE9yETveoTRmtQquu9brm9mua3OXbwr6yk5xwZOlayLrly6eFKwT7hRMyhdVEF7Lwn9Mp2zabte+MCG8SVTfDe0VNfOfiVJewXgaAggkJqDshq5du/p1JDR0lNqAAQP8AEr4gXNie4usFS5AntFQYO4heHgIscge4vc2b47+9nL8tRKfW7BgWpaatlBx8pxcc+JHTVtT9U1ccEaF2d0QYa+//rodc8wxUbsrUyb6F+xwxlDUit5EogGu2O12N+3OdXfrZWd5OHMms2vTvmOXn3vuuX7wRMsGDx7sB0/CQ3adddZZWhQ0febahxsGLXZ/wYpeJzx8WHg+fQQQMCtYIJIgrt/h4rXt29PmK4jiWna3c9vzjgACCCCAAAIHn4Dqa+pvotgRDfK6hEZmeefHBf5pNqhX0Y5tVj3XT/nkY+tayuZtNnrSSvvkF9UCrprr57AvD1izZk3/i5vNmzc3vTQstEaYiPflyX15nhwbgewKEDzJrtwe2m7kH5ExqhXQ6D90Ydw9KzvltjMP85cV9gIjru0Kj+flZmbwriG2whkp6mfUFHyhIYDAnhPQ8EWqe+JqQaxatSqqLkpWj6R6KCpAr0Lh+na/HlSHH1KvWLEieHgdHpIpfJzU1FRvSMC//doqbr7LznDT8d7DAZCMAjduu+rVI7+8KrujRo3IMINaR4XRc6Mdd9xx/lBRqrGhYbwmTJhgGl7NNX0+rikzSEXOs9LCQaLsZqaEXbNy7ETW1b3iCsZ//fXXdthhaf8/SWRb1abR56bsla+++spuueUWv4i8ttX8Jk3Sf7tK2SkqUq/gyNixY3M1aJbINbEOAvuDgDKLSxQr4GeV6HfEjVt2WHGv7pxry9alBlnG5UsXcrP9jOTsbBfsIKazaUskqyVmEZMIIIAAAgggcIAIvPDCC6YAin6/79Spk2kY6LZt2wZfRsurl/nR6EW2YGmKf3qtGqcfkSG3zvsYrzj9nPmrre8P86ydN0JM5dDvZrl1DvvqONdee61pSOdvv/3Wf7nz0N+JGjJbgRQFVPR3ZV5pGgL94YcfDk5HNUCvueaaYJoOAmGByFfawnPp55rAsClpQ3bt7oDKTlm3aZu/WtWykT+QF66M/y3xjIIqZUulfQtcY2ePfOZ4++W5TnFfw5/ssLtTytLypH++PbmVYb2y5MbK+5eA6kpklLmxY8cOW7Ag7RsxuioVIc9pc8XFtZ/+/ftH7e79998PpmPrilSoUMFfpoCLggiuKTPks88+c5MZvoezGFRgPLNWq1atYPEXX3wR9F0nto6Gm7833vXQ37VevXq5rv+u4IJrjz32mLl6Mm7e7t5VR8S1oUOHum6eeQ/fK/fee2+G92m8E1agzhV5V7BO16dh0NQuvPDCqOCb294FpjQsl4JRNAQQyJ5A7SrFgg3fHRH5f4hm9h4yP1hWLzSEqmZmd7tgh16nSKG0QI3qp2z2hgajIYAAAgggsDcF9PfSVVddZZdffrndeuutmX7JatCgQf56WldfjKLlXOChhx6y6667znfXkL033XSTdejQwW677TbT32zZ/YJYzs8s4z2s37zdPvtpsb9C4waVrUqFyO9NGW+1d5ZULl/MWjWrYWu935t6D0mrTbp3jpT39vrAAw+Y6o3qWcL1119v7ouJU6ZMsX79+vnDZp9zzjn+8NEvv/yyTZ8+fZ9fxPDhw23kyJHB66233trn58QJ5F2ByNfX8u45HrBntutvswkz1vrXV6lcYfvqv+mLKX8+Zok91X+mv86IaavtvNZVrGyxgkEGybjpayzZC6qU8sZYdG38X+v88a/ddPi9Ue1SNmztcn8M7Yc/mm7/u/TI8OK91q/i1WHR/0RUh2Xs7HXWqt7eLd611y6EHSOQicAzzzxjAwcONP1ioEwHPVBXqqqyOT744IOg9ohSWQsUyPnwd/rl1gUkevTo4RfmVqBEAZE+ffoEZ/qf//wn6KujVOxhw4b587p16+YPZ6W6KR999FFUYXX9MlGkSBF/yLFwVkQ48KP9PPLII/71Kotk6tSpfibCySef7O//7LPP9n9Z0sRzzz1nGm6sTZs2psyYcePGBefhr7yX/3PCCSf4v8gpU2f06NH+8fWNKrWKFSvaHXfcYQqqKKjUsWNH/48FfQNFn5f+mFPmjFLZtSy2hTNq9AfcjTfeaGeeeaa/vgJqy5cvt1NPPdWf1v3gCqrLwTUNLaZaNXppWDEFLWKbitWHg3BavnZt2v9HNEzbTz/9FGyiIJkyQNROOukka9WqlZ8FMn78eGvRooWfCaVvkylwpGvWfjU/Xqq+huZydXr+n73zgI+i+OL4U6T3Kk167x1EpCg2LBQVRFGs/EUBFSxgRxFQVLAhzYKgAgqKImJHRBClKQgIIjX0Enpo+t/vhNnsXe6SS7nkkrz3+Wy2zc7Mfq/kdn7z3uM9Y80/ZJc9zv3zfqLe8ePHm3BfhK0jDw2sSSKPQHXDDTf4eEzZ63WtBJRALIF7O1SWXmsXm51JX22UfYdOmsTxvzm/pb5fssPF1Ouyiu42G8m9zltJKee36fqth8xvt9tfXSKdW5aWwk7OvJWbnbxIztdT/6vjRGfvdbqtBJSAElACSiA5BHjeYOKVfY7ht7R9pvDWx+9yJjvxmxrPewZj1VJOgOdIlvvvv994mSNQzZs3zwgniCeEGMYjhdeEZwvv82HKW09eDXid2Hy9jWr65o9MXo0pu+oCJ2TYOsf75IsF2+SiuiWkleOBkpWMZ0mWQYMGmQl3jBUw8c5Gt2CcgoVxE553eT+xJCUqQmrxtOMhtj76+Pfff6dLX2wfdB25BM5yQrY4Q/hq6UFg6T/R0tt5GMWubXuePNwpdpDL25fdTlL3q56MHQxrVruovHZXrJvb0Ol/ycyftpqiJHnv37maExs7m6xwEst/+nOURB+M9VIhMfx3z7V2q6S+jk//7IZ5YFZhkxpF5IJasW6F+w6dkPU7j0jPtuV9QkPc8doSWbk+NknyD8+3lTye2NpR+45Jl2cWmDZaNyghI26t67ZnN176bJ1M+36z2cXrpdtF5aRGmXxGBNrrDATkz51NLm9Y0hbXtRLIkASuvPJKScwTgxsjb0SNGjXce2RWD6ILRiLu3Llzu+cYdG/evLnZ79mzpyCSeI0HB/uA4T1utwcMGGBmbtl91vwwQMAIZCRLHzJkiM8pBBH/PB/PP/+8jB492qec3UGsGTx4sN2VcePGyXPPPefuezfwiLDMyFGSUHJx73XBtnl44scYRogu/zwihJ1iJhvGQD4D/NZIdM7sNWbNBDMeFhADAtnEiROFGVvBDO8gfiS+99578sQTTwQrZo7zwy2QwIY7PSJUKNa5c2cZNWqUWxSxgnBk9sere8KzgesyOXoCGblPCMVljdeOh6pgxvscF+6EjOu9XjEJldVzSiAzEXh08p/y3eJY8WPhyIslgUiqMmjSnz5CiT+Hzq3LysAu1f0PJ/s6W9FXy3fKk+8G9i70/31pr9G1ElACSkAJKIGUECC0MYOvGL8ReUbyn1DE7Pb+/fubMgzSMtNdLTwEtm7daiadIaKwHD582DTExDErogR7rgxPj3xr7TbiV9kYdUjwOrmqTfzxNN/SabM3b8km+fm3jUHH+NKmF5HTCqHCEVBYECyYROdveDhddtllJtpBoGdg//Ip3ed9XLt27ERyxgZeffVVU2VCz8IpbVOvz9gEzsnY3c/YvScJvLXWtYrZTZ918QI5pYgTaguvDbxU8FbhAbvXpRVk9sJtxoNkz/7j8ujbK3yuC7ZDfY90rylD3491kzsac0rmOUmtWLx2QfWi0rBSIe+hFG33uqSifDJvq+kvyegnf73Rp75SxXOreOJDRHcyIgFEA37gB3Mdv/76681gsvUGsPeYLVs2uxnv4cD7sIBHgr8xCM8MIQQD76A4P2hxn8Xbwd9IIM9DB54W5LHAyE3Ru3dv423hL574X88+IbDwdMCjxt/8f/AwgE6oL4QewjhZw0OHc4hOqWVeRl52tn7aGjZsmGG1YMECWb58uRt7lbwlCBwILIgwhKjyN7xPglmPHj2E15Jrva+FLR/omD3nvw7Ud8p478//Gv99/zrIfYN78tixY819BurPrl2+/wu8dRK6yyueXHvttd7T8bb5AYwQ9cILLxjBEC8Uf0uoPf+yuq8EMhOBhPLO+d/nsJtry/vlC8i4L9b7eBYzAea+LlWlU7PAMy2Te51t/9L658rGDkfk7dnxQ0/YcKy2rK6VgBJQAkpACaQGAZ4Z+vTpY35PM8EKT/i2bdu6VeN1YicH4XXCxCe18BEgOgGTr1jwdkdA4XmC510m8LGQxwJvdsL5Bsu1GY4ekgsO4QQrV6pgOJpIVp21K5cw4sl8Z7wv0ATpZFWagS/KlSuXed7nORzhBAGF9xBr+3xow2e98847RkBh3KRw4fBFqyG3jzUmbzIuQHQG+hRoIiHPwHPmzDGXEMaOsGNEsiC3J99ZRLPgMxLMGwtR+JtvvjHX8TliTISoHdwjkz25lmgXGBMto6KiTBQT+/1GBIiTJx3vc0dQtpEfCI2NLwRjS/7P5XCdMWOGmZi7du1ak2uX6BKUK1nSd9I6z+u8Hl7D++zEiRNm0iih1xhXYMyJnDBE4siKpp4n6fiqdxm6UKLO5CyZ/9JFkj2bo4oEsMHTVstsx+0Pe6t/UxOugW28SB6Y8IesI3zCGWMm4IAu1WSwM0sRQ5T49LH44cC2Ot4iQ6aukT+csA+E0vK3p2+pLVc0ivtQ9XpjqfzulMXmvtBWvEnrSVjaafDP5lybhiXkhZ7xPU84uX7HERk8ZbX8tfGAKev9gzfK/BfbeQ/pthLIsAT4UU9MWP4x8o+GfzD8Y0zKwHdybv7AgQMmHBbiSP78+UOqgn/kJH3HRZ7+2b4jgBBii3WwHwE0gLcG/9xZ0yb/jBMqz2A5Mz0QdyhHnhVYER7M63ETUufDXAgWzLY6duyY6SsCU6g/FgjHZcNpwZFQZ4RwiyTjvhBQWMOecFo8hIbLeJ3hwg9F2uG9Ahs1JaAEQiew7/AJ2eH87irjhEMtmCf08I/JvY6e8Ttxk/N79aiTt47ffyWdBKh5PR7IofdeSyoBJaAElIASSJwAA6yEQGYAkAFFb47Ezz77zEziohY88vHM9zd+a3755Zdm0g9e/UyQqlmzpglZm1DC6qQMcPq3mdX2+V0/1xFQrJDCPsYALRMKed1gHk5bviFa/vfKEtPEnV2bSvEiecLZXJLqnvz577IlKlpG920kjSuHTwRIUqcirDDPhVZEwSuFZ29rpUuXFgQUJu8h4KW2McmUSaA8kyLSvvHGG26I6j///FPy5fPNnfP+++/Lo48+arqBYHjnnXfG6xIhsolq4T8WQtSKxCanvv3220KIcey2224zIg55Y+DDWI2N1EBIcfrNJNa6dWPHXW+88UYzOdR2iPthUqydJGuPs+Z+EZ+94RCZWDl06FBvMZk9e7YQwcTmObUnGQ8hTDhjN1nNVDzJBK/4CceTY+22w87DbE4plj+n7IiOMaG5uLUmNYvIG/+LVTCD3epe50F8+74Yo1rmc2Yx8kCewxEzwmX0d8POo3Li1GkzsFwgzzlSqnDuoOJRuPqh9SoBJaAElIASUAJKQAkoASWgBJSAElACkUXgtddecwczSTiNmMKkq/bt25scjQziMVucWe1eY0Y3Ib0Y2A9kzKjG+97fkjrA6X99Vt5HOGGQ99tvvzWhmZiYhSGkMEueHJjly5dPdUQfLYiSF6etkTy5c8h9Pc9P9fpTUuGKdbtk1nerpZMTWnVQgNCqKak7M17LhEW8PhBRvJ9dQocjoCCkeMOep4QB3hqNGzc23h9dunQxOU/xLCFENYY4Qk4fr3nFEyaBIkwQXpCw2N7IGkQDob/W8Oro1q2b3TXiRf369c2kSiJWENKM67mOPKQYYdQnTZpktslJioBho4kwSZY6yeFKPlEMUYdcuBifPb4rbZ8oj8hC9AwbKp1y5J2xeWwJtf3xxx+biZ9432B4wiAE0Sc8W7yhugnfTt7SrGYatisTvOIIHXXKFXDvZOxXG9ztiiV9FVP3hGejaL4cThL6tJv9S3+rO/lO1JSAElACSkAJKAEloASUgBJQAkpACSgBJeAlgPcC+RDxPiEfAQOChL1h0BB75JFH4gknHGdGuR18ZZY14XQQXQixgzHrGq8IbygwBiO9M8O5LtAAJ4OmavEJEHaIXIssDNIyAI6Qwuvw119/mRBsDP4y2At3/5yU8WsM7ciqLbERWIoXC5/nfGg9iV+qaMHYHKarN8eGFYtfImlHYEs+T7waiAxho0PYbe/avwye/qEc868joev8vSu4G8JKEerJLkSmYNuu2UYssAsD/Wyzpow1Pp8Icnigsbbh4c477zzj9WDLJXeNN5oVF/DkwKwXB9u8b/3FE45b41pCeOFZhRBDmC2b95TwY17xhLBe1gh7jrCbWDQSBA9rsPF6kBA1AmZ4yVnzCpP0xd4bAgjfa/a18uZdhenAgQNNFYTaZkFcseHU8fAjDB/htxF5YGK9/PDMyYqm4kkGf9Wdz6occ8IoHDp2UtZEHZbpC6Nk0co97l31aHOeu60bSkAJKAEloASUgBJQAkpACSgBJaAElIASiGQChAPGQ4TBP8SNRYsWublOEDH8Y/xzL8weJ1wXRpgbBgvxUMFWrFghV111ldlmlrdXPEnOAKepKA3+EIKMQWnvwLR3P9g2A9WBztl6EJQIkxRszblQzidUBq8BBsVpk9BrNvwas+lTw9ZvP2qqKV0ibiJxatSbGnXkzB471EqO4ZQaXhkM0vNasXiFhpTWnZGut6HhUtpnK6RST4sWLUx1CAwICHhh8B3C945//lDbLmG1bEg6yvBdZMWTjRs32mJm7e2z/awlFraakGXWEJCseNKyZUvjbYdA6c0b6hVPEC2t9evXzxVOOIaoQ75cDCEuIUO0xgPG5uZF0LJGuLWsaCqeZNBX/dNft8mwD1Yn2PtbLqsgJQv5urEmeIGeVAJKQAkoASWgBJSAElACSkAJKAEloASUQDoT6NGjh/E+YSY1MfztjGpi8dvZ1N4ukszcGmFsrHDCMWaWM8ucgVNmWDOgz0x7LDkDnObCZP558MEHTbgfK2SwtosVG+w+4kRmM8QwO2idkntjAjGWK2fkDWvmdHLEYYfP9NHsJPMPoaXCMWDNwDgD+d6F/EDefbZtblJyZBImjzWL9TCx3iW8d73H2MZLwnvMW4btUN/fCBokLE8Nw4MNI6eIV6ho06aNEU/4nsE7xQok/m3694P8KDaU19GjsYKevYbwYG+99ZbZHT16tEycONEIt7z/mzdvbkLb2bJ27U3oTg5VKzYi7hCqEDHF63nizQmzfv16Uw33hvDC4jU86hBO8AhLyBCXydlrjdytXIeIx3siK1rkfctkxVchGfccLLk8VZE0/okba0nb2sWSUbNeogSUgBJQAkpACSgBJaAElIASUAJKQAkogfQjwAAtOUqYLW2FEwYFrQeJf8+8s77LlCkj/uFlKlas6IbvYva2nbGdnAFO/7aTsv/RRx8lpXimK0votClTpqT4vo47EViwnDkib1gzZ85Y8STm+L8pvk8+A17xhLByeGbZBcEjkOEVgdjBee9ijwUSIAPVE45jfJ7xkvj666/N2tsGQsT5559vQu5VqFDBJIz3hrLylk3q9oEDB8TraUaydGtWeGAfkTWYeIKQEKoRBovwWORwwpuDhfwhNocISeYffvhhc6+2znPPPdduyp49e4TvNRtKkBOIJ9bzxL4XOI4YZb8nCW/YoUMHDgc0Wy7gSedgoBCFqRVuL1ibkX488r5lIp1YhPSvRpkCJvlUzuxnS67s2SSvk+i9Yok8UqNMfilRMPCXZ4R0XbuhBJSAElACSkAJKAEloASUgBJQAkpACWRgAvPnzzfJipkZjTcIYWJS20i2zIxtYv1j5DoJNuhrw9tQjtn6CdnBg7H5MiiTnAHOhOpO7By8Ro4cmVixsJ4n7wILA+x2O6F9vBQCnecYocX++OMPEzZt6dKlpt8M6iJKkVS7QYMGPm0wMJ4aFnM8VjzJdcbLIzXqTK06zna4YsdSIWzXjTfemFrdStd6CFuF14ddEDK8xufQLt7jqbmN54Y1BIahQ4faXZ81fezVq5fPseTu4DXHa4hQhCiDaISIgiHkkFsEQRUhBfOKJ3ierFq1SmrXru0KGnx/cBzzCjwIZHzubN1sBzOvV16gMomdD3RNZj+m4kkGfYUrl8wrg7pUz6C9124rASWgBJSAElACSkAJKAEloASUgBJQAhmJAKLD9OnT5eOPPzbhr2zfyTESDmNAkAFVEhxj7du3D9pM8eLF3XMJDRxSyP98Ugc43YaSuUE+l4xuv/32mwlzRJ4IK1wRGo3wQldccYUUKxbeSCiR7Hly8PAJ8/KWL50vo7/MKe7/li1bZNq0aTJz5kw3BJWttFq1aq5gUrVqVXs4bOsffvghpLoRNRB3kuJlklDF1HP99debhdBXhM1CFIYJ9sknn7jiCd9NLIggsMNL5NJLLzVhCDmOJ8rhw4fNdZUrVzZr+wee5H5C/OAeggnNtnywdXKvC1ZfZjiu4klmeBX1HpSAElACSkAJKAEloASUgBJQAkpACSgBJRAGAkuWLDGiyWeffSaHDh3yaeGOO+6Qiy66yOdYau54Ezfj6RDMGHy1CePpZ5UqVYIVDXg8KQOcASvIAgcRSRBLWBBPMEL8EFqqXbt2xsskrTAULZRTdu45JvsPxqRVkyG3c+DwcVO2mhMZJqva2rVrjWgydepU8Xp6wcN6mLBOK8NDatasWaY5PKIQgf2NcFr33HOPOYyXCiJgahvfZzVq1BDyMlnxxIbhsm3xmVq9erX7GSNcIYY4AldrhDXzGt5eiCcILsOHDzdJ373ndTv5BFQ8ST47vVIJKIFMToC4kbgoq/KeyV9ovb0MQQBXbz6TJC1UUwKRTCDmxL/O/46zJKH8dJHc/+T07cSp2JjeOc4JPqiVnHr1GiWgBJSAEkg/AiRznjFjhiBEEG7GGgmS7cxnjg0aNMieSte11/uF8F6TJk1K9u/GUAY40/Vm07BxBp1nz54tc+bMMaIJCcAxxJJrr71Wrr766jTsTVxTzWsUkc/mR8mOPbGz8OPOpP/WwSOxgk6V0sFDJ6V/L8PTgxUrVsiHH34oiCbehPDkGLrmmmvM+6V69bSPokMOJBvSqm3btgFvnkTu1vBSSal4wueG8GDnnXeeScCOJ92xY8eM94hNJE97/kIv5RFP7PeuFUkohzhizR63+wg/sOc+x48fbz6vfE5btmxpwoGRQH7Dhg1yww03uN53v/zyi3md6Kc18r8QlhHjdaM/Wd1UPImQd4A+aEfIC6HdyNIEGJz99NNPZfHixeafEv+wRowYIV27ds3SXPTmlUAkECCWcqdOnczsNhs/GfdnFVMi4dXJ2n04/e9/MmX+Vvlt3T5ZvemgRB88Ifd0qio925bLMmBe/3K9TP1usxRxZoHWqlBAWlQrKtedX8aJpZ5lEOiNKgEloAQyDQFCynz++edmVrQNx8TN1apVS0qUKCFz584VkgdHR0fL7bffLtmzZ4+Ie7/kkktM6BvC1fA8x+9Fwny1atVK8EphQJF8ARz3Dt4md4AzIm46jJ0g1wJsWGwy7bJlyxqvAX6T835IT2tSpbART/bsj80fkZ598W/74BnPkyols07YLpKbv/TSS/LBBx/44GjdurURTBBOSFafXjZv3jy3ab4TAhnhrhBhV65cabxU8N5IyNstUB3eY3iyWG8X73HvdqlSpeTuu+/2HpIyZcr47NsE7tYDxZ60x+0+/Sefks3Xwvf3xIkTzWLLsG7evLm5T7bJK+VviOYsWP/+/eW+++7zL5Ll9lU8SaeXXB+0RfRBO53efNpsQALMnuKfAgm8vBbuWK3ettJqm/idTzzxhGmOuLQMQAczfmQ888wzQgxhEqpVrFgxWNFUOZ7W7aVKpwNUQjiDxx57LMAZMQk1mcGRUWzIkCGCKzE/7NJzZqFNXMePQBZ+0DGzhlk7/j8wMwpb7WfGJ3Dw2Cm5581lsm5zXOJZ7urcgjki9ub2Hzkhj7y70vSvdZ1i0qNNykWecwvGPgzviz4u85fvNss3y3bKqDvrS56c2SKWhXZMCSgBJaAE4ggw8/jdd9+NN9BmBz+joqJk1KhR5gKEE+yuu+4y60j4wyDnCy+8IN27dzcJ5hFLCItjQ+PYPj711FM+4klyBzhtfZlpzax4Qp8hmJA0G2PAG7GEGezkM8mdO3dE3HKDioVMP/btPxoR/fF2Yt2mPWa3XPHIYOXtWzi2GbC33w3Uj8iGcNmhQwczUB+ONpNap1c8qVu3btDL8UpBPOH7Y926dea7gmgk1gKJKcEilTDuEszIX4LnFmEPCxcu7FOsdOnSPvtWJPEfiwnkEcJnFG8SvgsJr8d9+Js3TJjNr+Jfxu4Hul97Liutz3KS1fyXlW44Eu412IP24J615fKGJSOhi/H6EI4H7ffnbZFXZ8TF66PR+lUL64N2PPp6INwEdu7caVwXrasi/0D4p8OspKuuuipoorBt27aZWJl4qOCeSmzJ2rVrm8XOcgp335NT/44dO9wfMT179jTiSLB6+JFsudx8883CQHowwy2XmV5YyZIlxX9mRLDrvMeT0p73ukjb5j3VrFmzgN3Cu6lhw4YBz6XkIPXaGSKJ1cND8J133plYMXMegQ2xgtcz1CR7IVWcxEK8vwgbQczt7777zjwUUwWfV5IQekM1JLFqLa4EkkVg+/4Y6fHir3L4yElzfbazz5J6zu+YJs5y7fmlpXDeOAFl5OfrZOHqfaZc02qF5aFO1Xza/O6PXTJ2zgZz7K2+jSV/7vDNb4rad0y6PLPAtNW6QQkZcWvwB0ifTiaws+vAcflkUZQsWRctK9dHC5OEsGKFc8p7A5pJ0XxxLBKoRk8pASWgBJRAOhBgxjiiyWuvvea2nj9/funYsaOZMU4oG+/gKM8Djz/+uBlQf+WVV9xrwrUxbNgwGTNmjKmekDOJDeYhAIwdO1amTJni/l709o3k8AMHDnQP9ejRww2P4x48s+Ed4PQPkeNfNqPv8xp//PHHsnXrVnMrl19+uQlbxGAynkaRaN1fWiz/bDkgnS6tJTUrFY+ILu5xxJzxU3+TlvWKycjb60dEn8LdCcJFIUIyKZPxE94zarEEEFD4jrXh7hAfEUv4jk3suyw1GCJ0MzZB+D2+zxinyZFDf5cnlW34nsyS2pMsUj6hB+3m1Yr4UIikB+2jx0/L7+v2m/4VzJvdmaXo09Vk7VxSv4Qcjjnp86BNG9cPX6gP2skiqhcll8Abb7zhCgQMEL///vvir/b7182Pg4ceeiieko94wPLOO+8IsXb5ce5NcuhfT6Tv45pvxRP/GRH+fSeGJjO9MB5CnnvuOf8iie4npb1EK0vHAvwwQZiytnz5cvn999/tbljWhCH48ccfQ6r73HPPDalcJBViRk+XLl3M8uijj5oke8SBZTYNMwgDJf2LpP5rXzIfgZdnrnOFk3zOb6N3+jeVckUDzzD8a+th2bQtNiY367suqSCFPOIKvw/t+eOnTkt+yVg/0UsUzCn/u7SSyKUia6Oc+3t1scQ4vx337D8uY7/aII9em/axrTPfO07vSAkoASWQugTIJTd69GifGeNMBLOiiX0e8gon5A2gDMaM6bQwPJ+T4v3M4CQJzFkQUrZv327WHOc3ML/TvTZ58mRJ7wFOb3/Sa5tk1Mxk79u3ryCcRKpg4uXTsUVJGemIJ2s27I0Y8WTZmh2mix0al/J2NVNv8z2iFphAwYIFg07GDXxF6h7lc5wRPsupe9epX1vGejJL/ftP8xr1QTsOuT5ox7HQrfQjsHv3btc1nbBEDMAWKeIrZPr3jriRTz75pHuYGLok4SKsEC6SCxbEzuidMGGCiSFpww25F2SgDWZ6IQTxTz8tHpDSur1wvRQk0iTcmTVmy4VbPLFtsW7Tpk2C8aczupcGD71vv/224A3FZ4641ja2tZeDbiuBcBHYGR0j85bvMtXncsJSTR3YXIrlzxlycx8tiHIElPCGQQy5M6lcsFqZfPLBI83l+iELjQfKrJ+jpE+HylIgjN40qXwLWp0SUAJKIFMTwGseb+Vx48aZ+yR/3KWXXmoGzP0TJDPJzIbjYaIO+xgzy+vVq2e2I/kPgkko3vDpPcAZCQyvvPJKk88kEvoSah9uuKCsTP95m/z9z26JbupMTCmQfjk1bJ+X/xklZc7NK0wWVlMCSiBzEFDxJA1fR33QDg5bH7SDs9Ez4SWAEGKNMEaJCSe4PT7//PP2EpNAq0+fPmLjYJI35aOPPhJEANyeM7Jwwk3ysPHss8+69xvujbRuL9z3k171M/sHASczG+7G9957rxFPuM8333zT5D/JzPes9xY5BMZ+vdHtzHVtzkuScMKF037ckmnFE+6vTJHcclmLUjJ7wTYjoEz8YZP0dQQUNSWgBJSAEkg/AoRuIZmzFUPq169vJqKQaD3QzGRCeRE3H0M4IWSx3fd6WKffHWnLSkCka6sy8uK0NfL72p3Spkn5dEXy4+JNcurUv3JJIxVO0vWF0MaVQCoTUPEklYEmVJ0+aCdERx+0E6ajZ8NFYM6cOW7V1113nbsdbAMPApt0C08MxBJ/I9Zn586dJVDiMMQXZnqtWrXKPISQ9AsvAJKF+buQUy8JDilL4vrbbrvN5HrAs4VjlStXNrPELrroIv8umH3iWpIjghn5zDDDFZsZRQnNvvr777+N+BOowmuuucZ107fnyfNiZ60dPhwbkoZz9BEByd9uv/124y5vjye1PXudXXM9SQ25P8KG1apVSxo0aGDu0z+GqLevvD45c+aU77//XubPn2/ijZI47tZbbw348EjSOO4TkYzXPxG6zAAAQABJREFUldlphCxo3Lix2ARutk8ZdY0Hx9y5c42HDDFYea/wMJ2QBXuP4Yn1+uuvm88KjJjN6G98jvgsrFmzRtauXWsS0levXt18FojFGoq1atXK8Ccny7fffus8rJwK+LkLpS4towSSQuAnJ0eJtRtbn2c3Q14fPHxSFqzZKy1rFA3pmr2HT8iUn7bIKicxfdSeY3JeiTxSp3wBufHCckHzo5B2ZOrPW+W3dftkvRNKq2KpvHJ101JStUz+RNs8HHNaPvxps6zaclA2bD8iJQrlkmpl80v3C8saYSTRCpwCPduVN+IJZX/8Y7eKJ6FA0zJKQAkogTARQDBBOEFA4Tcv4gfPLMGMyWCERcUQTjDEFAzRJdjzhymgf5RAGhK4vmUZme5M1liweKOUKZFfqpRLOIpEuLq2ISra9KFsybzO77Ok/zYMV7+0XiWgBFJOQMWTlDMMuQZ90E4clT5oJ85IS6QugXXr1pkKCXMUaMaVf2vkOrF29913281460DCybJly0zoKwbxrZEfZerUqTJ+/HgzOF+zZk17yqy//vprmTVrlvFgKVCggDz88MPuea798MMPpV+/fjJgwAD3OBtHjx6VBx980CRusycQUXho8oYcs+fseuPGjW5CRnvMrmvUqBFPPCH5mU3gaMuxJk9KoONXX321j3iS1Pa8bZAEkrwyXrMh0xiUf/nll00yNnse7rZPCB4kxSQGsjUG39977z35/PPPpUyZMvawWSPOIGQFMvK7PPHEE5IrV/q7iQfqXyjH8FTxelRxzVdffZVgqLaE3mNwfumll0zTPJz7iyeIUeQDQvTwNxsewv8a/3LsI5B16NDBfV137dqVaL6iQPXoMSWQVAKIH1j50vmSlAy9UIEckitHNtnhCCDv/bA5JPHkl7X75MFxv8tJZyajte27j8mvf+6VKd9vkVF3N5D6FQraU2Z9xMk30mfscln1T7R7nDYXrtgjN19WwT0WaGOZc01/p72jMafc07RHXroZjsfMoBtrytVNEo/jXaF4HilSKKfsiz4uu52cLmpKQAkoASWQPgT4/U/eEiYZkQfkxhtvTLAjs2fPNs8RFLLCCb+FScKO3XTTTWatf5RApBC4qW1ZGTJ5lcz5aZ3cdX0Tyen81kpL+8+ZsfLtgr9Nk7e1Ly8F82RPy+a1LSWgBMJMQMWTMAP2Vq8P2vqg7X0/6Hb6EyAxoLVQZrozq90O9l544YVCcvNQjVn2PGhYrxW8TJi1RR4MjlFvr169jCdE9uzxf2wx8M9Dj/91tP/qq69Kp06djCeK7c9bb73lI5zgNULiegQCO6hty3rXhBkjhrG1qKgosQKTPeZd46FgB7lJyEgCb4x68DjwNwQgryW1PXst3LzCCWIIryGCEoZHyZAhQ4LeK4P7CCfkq8EDhcF8DM4vvviiYW0OnPlDiKgmTZpITEyMEaYQh6yRZJI6EhKlbNlIXC9atMhHOOH1J5nmwoULEwyDldB7bOjQoUFvlffJLbfcYlhTiFxDzIAkFASvA5+Hu+66S5YsWWI8roJWdOYE11vjNbXJTe0xXSuB1Caw/8gJt8pzC4ee58RedGO7cvLyR3/Jsr/2ye6Dx6V4geB14AHSf8xyE/qK67OdfZaUdrxOtu06ao4hcNzvnP9qyIWS45yzbRPy+uz1PsJJvSqFnf8BIivXR8sH38TOIHYLezaOOqJL39HLXKGGfC7lnBmUew4cNyLIaWdwgMGJ5lWLCLnrErNiThnEE5LHcy39V1MCSkAJKIG0JYBYwiSf9u3bi/9vcf+e4IXMBBfMCidsI8Bg/Obu0qWL2dY/SiBSCDCpY8POI/K+8xtnxrerpHuHumnata8X/iN79h6RixqXlKtCmGCSpp3TxpSAEkgxARVPUowwtAr0QVsftEN7p2iptCSwY8cOt7lQBly95cuXT1o8VXKrWOEE4YUQUCRnRMAh6TViAAIKeVK6d+/u9su7gdCA5wvr48ePy0MPPeR6QzDQTRgvjHbI/2CN0GTWowVPEVz0vYP/thzrhg0bijcPDN4HiDrBDG54zWC7d+82AgPbJJt87rnn2EzQktqerWzEiBF2U8g5AwuMWXGEQIMBLP/3v/+ZcGVu4TMbsEYkseEKGLQnTBXGPftbx44dhcXaf//9Z8Kh9e/f37xuCAmE/IqUEF5PP/20EXRsf+0aDysrdtljeJ1Yg2vXrl3N7okTJ4xHE6Hf/C2U95j/NXYf7x7rfcV7HZHLempxDi8ebMKECTJw4EB7WdB18eLF3XPez6h7UDeUQCoTiNob50VRysntkVS7xgmd9cr0tUZM+NAJxdXvyipBqxj79T+ucFK+VD555/4mktcRNPY5YbxufulX2bP/uPEQmfzjZrn94gqmHgSXmT9tdesc51xjPVN2OSJI9xcWyeEjsZ4zbqEzG7RnPVya1ykmL91WT7JnixU8xnz1j7zz5QZTEnHmme61/C+Pt1+ycC5Zu+mgOU7bpZx9NSWgBJSAEkh7AqEIHjxP2FwmXuGE3214ZmPdunWTQBO90v6OtEUl4EuA31Prth02nrnfOGLGJedX8i0Qpj3ynCxdsVXy5jlH7rykQpha0WqVgBJITwJxU9TSsxdZoO3UeNC2s/V40E7I/B+0vxnWRj4e2EJmPdNKip2ZIclMRR60rQV60B7fp5GMu7eRfPrUBZI79zm2aLy1/4P2t0PbyKQHmsqXT7eS266o6JbnQTsU40HbGg/aakogXATsAC71J5YonjLECLbmHbC1xxJaf/fdd+5pBocRTjByZzz22GPuuR9++MHd9t/A0wLhBMPTgYcXa1u2xH0v/Pnnn65QwwOQFU4oS+4U3PUzsuH94fVw8d4P92pny3GPPAQGMrx+rHDCefLO4FmCIQx4vZLMQb8/ePE0bdrURyAib0ekGHGq8YjxX5YvX+7TRbypmGGIkQvHywRvm0GDBplz/n9S8h7D+8kaIeescMIxK9ywjaAYink/u97PdCjXahklkBwCexxvEWtF88f3FLTngq1zO6Ek2jeNzevzyU9RQm6SYDbPyRVi7cnuNY1wwn6RfDlk4PVxYR7nOuG4rC3fEO0KLq0blHCFE87jLdKrQ/DBBHKTWHuwczVXOOEYoVWtrTojiNj9YOsiTpgya/qbzpLQtRJQAkog8gjwm/mGG24wHfMKJxwgdC25BfPly6deJ5H30mmPPAReu6uBnOd4zC7+fYtMnOn73OMplmqbCCfkWsmZ42x53PmdVtlpW00JKIHMR0DFkzR6TfVBW0QftNPozabNhEygcOHCbtnEBssp6M2JgpdFUmzDhtjZuogfJMX2GoPw1oJ5hHDe/zrracI5QiFZI3SRtdatW9tNd+1fj3sig2wQ3skaySr9Z7/h2WPNhlmz+3aNeOJvXpEJzx5/I58GogRh0hDAhg8fbrxPbDn/B017PD3WeMAghvgviGde456sXXzxxSa0m91njWcRoeL8LSXvsfXrY4V0+saDOEKMXThnX5u//vrLv9mA+wcPxs5q56T3MxqwsB5UAqlAoLAjXFiLPhKXF8QeC2V9c5typhiTWX5YEfc59L92rxPyCsvuhOSqU8437OEFNWPFdM5v33OUlbGofXH/D9rW9f3MU6D2eb71xF4V+xdPFixf3uyy3xGJfneEGLusjTrkTsIhf0ooduBMbhjKFs4fxy2Ua7WMElACSkAJpA0Br3BCjkZ/I/8ixiSbULz1/a/XfSWQlgSYOEy40m3bD8gbHyyS9Vv2h6X5n5fGCifks3vDmXR8Ud3QQ3qHpUNaqRJQAmEjENydIGxNZs2KU+tB+6tF2014hkh+0OZh22t4u/Awrg/aXiq6HQkEyOtgLZRwP96HBa+nh60j2JqBeDsjvmzZsvGKkfSavA0MSCeUXySxGMW2Yu/AdqDB5EDH7LUZYe19rQJ5AHkFgmCvU1IZkCcG0SQh+/ffuGTOCZVLi3NffvmlmR2YWFtebyqvmOi9DsEPbxyvJfc95v0sIBSS7D2Y2c9MsPP2uPceQsldZK/TtRJILoEyReM8ZHfsD01E8G+rqpNonjBcm7YflklO4vj2joeIv8Wc+NcNoVUwgIcL6UPISUI+EZtXjzq84knhvPEFi8L5AnvLeNsjrFevV5b4d8ndt6G93ANBNnZ4EsWXKhTHLUhxPawElIASUAJpTMArnOAB7/XopSs///yzyUPHNqFx1ZRARiBAFJUhH62Rz3+OkulzVkqjumWkduUSUqp4vhR3/4+1O+X31VGydfsh81tu9D0NpZhOEEkxV61ACUQyARVP0ujV0QdtcQcAEkOuD9qJEdLzqUXAO1jsHZAPVn/u3LlN2CwGdRcvXiyHDx8OaYCa8EfWDh06ZDd91nb2vDf5tU+BJOzYkGBcEkkD+km4hQSLkqTemv+gPse9x4KJJITdCtUIa+UVTvBQIcwXRqiuUMNLhdpeWpYjeai1pLxXkvseI9wcniz2NQrk1WL7Y0PU2f1gaxVPgpHR4+EiUDRfXKL03dFxyeOT2t5NF5WToe+vktUbDkj18+K+12w9ObPHOYgjbASykydjjyOiWMvjhAWzllBIMFvGrnM5IScIEUtid8yGi7Xnveucnja8x/23d0fH5ofBc8bmTvEvo/tKQAkoASWQPgS8wsn06dONx7J/Tz755BNziKTzdeumbRJu/77ovhJICoHHr68hBR1P2slfb5Tflm8xS+WKxaRW5eJSp0r8SSsJ1X38xGnZtC1aflsZJZu3xnqyXN/uPHmwY7WELtNzSkAJZBICKp6k0QupD9rixIGMe5hPCLs+aCdER8+lJgEG0AkdxAx4Hh4IfYVAkpCR4JycDQz+vvPOO9K3b9+EiptztFO1alXjVUJbXOsdNGbw1w4mV6wYlyco0YqDFPDOvt+6das0a9bMp2RSBsl9LkxkxysSheo1kEiVAU97PYAI9+Rvf//9t3vovPPOc7eTu2ETmHP9L7/8YryEbF0kqL/88svtbtC1N7SYfa2DFk7DE17vq2Ahzk6ejJ9YOiXvsWrVqgkhIRBHfv31V5+cJ8m5dZv/hmu995OcuvQaJRAKAbRXwlrhnfHP1kNy1PH8yOMRL0KpgzIdGpWUEVPXmMklXyzYFu8y2ingeIngVUJbh46dkvyeHHTbHa8OK3QU9+SLK1M07v/Ypt1HpZUnvBeNnE4gx0rRQjll174YEybsh+fbpkjw2OsktbdhwKhXTQkoASWgBCKHgFc4mTBhgpv7z9vDo0ePig3ZhXiipgQyGoG+HSo74bSKy8fO76zZC6Nk/YY9Zvl+4XopWaKAlC6eX0qXyC9lzy3ghC8WOe78pkMoOX7ylBw6ely27jwkUTsPyA5nffp07ISV+lULy+2XVJAW1YpkNBzaXyWgBJJJIG5KWzIr0MtCI2AftCltH7RDu9K3FA/azN7DEnrQ5rx90GbbWqgP2ra8XSf2oE05+vXjiHay4OWLAi4/DG9jqwu61gftoGj0RJgItGzZ0tTMgPacOXMSbeW+++5zy7z44ovyxRdfuPsJbVhPBcpMmTLFp+ikSZPc/Vq1arnbyd0g34W1qVOnyn//+Y6UhdpnW0eo64IFC7qi0Lx584xnTqjXJqUcg+7WKwEPoBUrVriXkwD93XffdfcZqE+JITRZUaFFixY+wgn1hvKeoVyJEnGzmxBcIsXwvrJC3rRp08R6QNn+4VXjDdFlj6fkPda4cWNTDQIbeWNSYrz21vOHXCl4tqgpgbQgUK9yQdMM4sWnv8YXPkLpA54YV7YsbYp6w2B5v7IrOuG9rE2cu8lumvX4bza6+1XLxHmuVCwRl6do+vytzv8At5jZ+PSXKN8Dnr06FQuZPfrz1IerPGeSvvnhT1vcixpVi8sx5h7UDSWgBJSAEkgXAl7hZMSIEXLJJZcE7AfPLEwuU6+TgHj0YAYhQK63p7rVkLcHNJUOzu+uwgVzOhMXTxgR5adfN8jUWX/IS2/NlxcnzJfXJi2UcVN/lYkzlsqMOX/Kr8s2S9S2A0Y4Keskg+/dsYqMc/KbqHCSQV587aYSSCUC6nmSSiBDqYYH7QV/7DGzBHnQvvHCpM+Itg/an87b6hMGy/tgzIP272tjXQl50O5zRWW3e6E+aNM3BB9riT1of79vh+kPD9pDe9S2lyV5rQ/aSUamF6SQwB133CGTJ082tTDr6uqrr05wJny9evXkmmuukc8++8xcc88998hll10mbdq0ERK4M0OLAd2lS5eaB5EePXqYcv/73//Eur0/88wzJlE2QsmSJUuEdq3deuutdjPZ6xo1ahhvE2b14ynx4IMPSteuXQUPAmb8v/nmmwHrRmThYcrrmeL17GDQ35tjpEmTJuIN+0SljRo1EjwBEKO6desmt99+u0ksSdu7d+8W7tkmZk9Je/fff79J2k6btDNo0CBBvIEx943hVUQS9JQY+WgQChBQYEnC+PPPP18Iv4ZwMmrUKLd6zuP5wHukQoUK7nE2vGLDkCFDzLnq1avLnj17ZOXKlcL7hP6mluEVlZAXFaJS69atTYL4Xr16yciRI03T9OPhhx8WvIh4vT/88MOAXUrue4zK+MxQL++R8ePHy1dffSXt2rUThEz4kUR+w4YNcsMNN7jCTsBOOAfffvtt99S9997rbuuGEgg3gd6XVTa/6Whn0neb5PqWZZPlpXGTkzie33TB7F5nxmSvtYvN6UlfbZR9h06axPG/rdsv3y/Z4V7W67KK7jaJ5UsVzy3bdx+TqF1H5d6xy6R763Jy4tRpWbw+Wmb+FLy9/s6gwI/Ldprfqt8t3iHtVu6RJjWKyAW1ikopx7tl3yFnsGHnEenZtryPF4zb+JkNwoxN/zGunV6XxPXPv6zuKwEloASUQNoR8Aon/H7mGSGY8bsXU6+TYIT0eEYigIjCgq3cfFB+33hAlv8TLSud9b5o37y9lCF3b71KhaVh5ULSqGJBqeLkqlNTAkogaxI4J2vedvrctT5o64N2+rzztNWECDBgfcUVVwgJthnE7tOnj7zyyisJzmB/9tlnJVu2bK4YwuAvi7+dPn3aDIpzHMHgzjvvdIWS1157zb+4DBgwQFIjzBQVMwB+3XXXmTY+/vhjYbFGXwJ5PyBwdO/e3RaLtx47dqywWCOppP+A/8CBA414Qhl49u/f3xY3a/ateJKS9hhY557wOmAQ/vHHH/dph53BgwcnKITFuyDIAR4YrYcEQpTXEJDIq0IoN7v07t1b4OA1vCJYrJeEFVBsmaZNm8Zjac8lZ41XVELGgzLiCdazZ0957733BE8Q+nfTTTf5XMprTLg5f0voPWa9WfyvYR+vIcQaRBsMYWrixIlmMQfO/GnevLmbW8Z7nG2EtxdeeEFmzJhhTiFOtW/f3r+Y7iuBsBGoViaf1HQepMlXwgP3Xa8vkTG9Gwl5Q5Ji5ZwQW9XKF5C1mw4GvKx+hYJyUeOSrlDyxYIox/PY13Okc+uyUrFEHp/rH762ujwwZrk5tmTNPmGxVqhADok+GDhXS/ECOeWR7jVNLhbKH405JfOW7zKLvZ71BdWLSsNKsV4q3uNsE17sjleXmGvZb1mvmBFe2FZTAkpACSiB9CPgFU545rn77ruDdmb58uWyatUq6dixo+Y6CUpJT2RUAkw0YbmpddInNGfUe9Z+KwElkHwCSXvCS347eqVDwD5oA8M+aAdLAJoQMPugHayMfdC253nIfn7KavfBm+PBHrTtNTxkPzhuuTz69gqZ8eMWye/E3A5m9kHbnrcP2sM+WC393lgmT7/3pzBb8u/th22ReGsetG8Z+Zs+aMcjowfSgoA3FBciCoPlhDD666+/HBfd0/G6wGA5Hgd4jBDKyX+gmKTveKPYwWlbAbkzXn755Xihnxj4RZTo16+fLequEWms+Sc59+7jIeE1BuMJz2WFCnuOwX7a8u8z57312fIJrQOVJzzZBx98YISCQNeSg8VaoOvtuUBrb3k8IxBP8Ojxvxfy0iBm+fP3svTnRXveY95tBvkfeughn3Zo88orrxRECm8C+0D9tsfeeOONePlnOEddXm8fWz6pa2+fE7vWy5LQXd9880088QHRBA+WYMlBE3qPecUbG2LN2yc+H3jqdOnSxYert8yuXbu8u2YboQWvLwSq0aNHu+cRz7yvr3tCN5RAGAk80LGqWzsiSrcXfpGJczeb2Yw2F4kt4ORhN3a23bAnnPXN7cp59vguOlP4zNFhN9eWfl2qiTcpPKfy5DpHBt1YUwZ2qe5zPTstaxSVMf0aC0KJ10oWyy1v3tMowWTwHZuWkulPtpSG1YsELbfjTCJ4W/dJJ74rMzgnfLtRuj7/i2w685uPpPN9OlSxxXStBJSAElAC6UTAK5zcdddd5rdtQl2x3sedOnVKqJieUwJKQAkoASWQ6Qmc5cze9IuEnOnvOV1vkAfLXqNiwy/QER5iu7QqK42d2Xs1y+b3eUi9Z8wyM1OwiJNk88unW/n0++vlO+WJd1e6x2YPuVCK5vN9QH5/3hYZ98V6iXGSXlnjQfu+LlWlU7PYGNv2uF0vc9wWB767wmdGIn0ceWd96fHCIhPGoXWDEjLi1rr2Ene9dd8xGeIkPv3DCSXhP2hAoadvqS1XODlbrPGgvWrLQfnt7/1CTG7rKsmD9qSHm0tlJ6akmhJIKwLr1q0zIaZsfgvb7vvvvy+tWvl+/uw575pQQ4SlIuwQ4aMSswMHDgiJ4hFaQh18T6zOYOcPHz5s8laULVvWDeW0b98+411DaKekDLoHayPQcfJnkC8DYYCBbUQnwn55B+4DXZecY7RDTGbu0Zu4Pjl1BbuGfCoM6NNO+fLlXa8W7pNz5NsgMTxLQvdouVCG9wr5UBIqH6w/4Th+4sQJQeDitSpSJDYJIiHK+KmQJ08e95792+Y9tmXLFhOujPfU7NmzjcBBOQTDa6+91v8Sn/3o6GjzeeC9gphEQnr/13HHjh2CN4rXKDtu3LiQPqPe63RbCaQWgdVOwvh7Xl/qTv6w9Q67o66ToDQu15E9ntL1PicJ+w4nUTxJ4QvmCT6xxdvOQWeCStRe53ureB43sf2eQ8cl5znZJK/zu9BPq/FearbJR7fdSSLP90A+pzxt5ziTf88W/thJwjrC+Q3oNZLdj+vbWCqeq7/nvFx0WwkoASWQ1gSYsEKYW+yWW24RvOgTM37rMlHG672e2DV6XgkoASWgBJRAZiSg4kk6vKr6oB0LXR+00+HNp00mSABBgfBMzMyyIgoz6K+//voEr9OTSkAJxBHAWwuxhPw62PTp0wWPp5QaIcXIN4ThzdKsWTMTns4/dFxK29HrlUBSCSBEDHY8fFeuP+CKKH07V5UeTj6TrGKvfvG3vP/NJnO7+fJml0ZVC8sT3WpKgdwaITirvAf0PpWAEohMAl7hBAGFsKehGDnq+K11ayrkYwylPS2jBJSAElACSiBSCah4kk6vjD5oi+iDdjq9+bTZkAjgSYI3Cp4MpUsH9tQKqSItpAQyOQHEkpiYGJPonVB3hNNavDjWw5I8L59++mmqeDfhrbVixQqpUqWK8UzJ5Fj19jIoAX7frdl6WMo5OUgIs5pV7J8dR2Sb4xFTp1x+KZTX1xM6qzDQ+1QCSkAJRBoBr3BC+C3yOqopASWgBJSAElACSSOg4knSeIWltD5o64N2WN5YWqkSUAJKIIwESHo/fvz4BFtAOCEHjZoSUAJKQAkoASWgBJRA2hHwCidXXHGFjBkzJu0a15aUgBJQAkpACWQiAupLHwEvZrH8OaVVzZwR0JO07UIlJ6cJi5oSUAJKQAlkLgIXXnihiaddsWLFzHVjejdKQAkoASWgBJSAEohwAl7h5KKLLlLhJMJfL+2eElACSkAJRDYBFU8i+/XR3ikBJaAElIASiEgCbdu2NQnvc+bMKbly5TILYkmtWrVM0veI7LR2SgkoASWgBJSAElACmZgAuRtvuOEGc4cXXHCBvPPOO5n4bvXWlIASUAJKQAmEn4CG7Qo/Y21BCSgBJaAElIASUAJKQAkoASWgBJSAElACYSPwzTffyJ133mnqb9SokXzyySdha0srVgJKQAkoASWQVQicnVVuVO9TCSgBJaAElIASUAJKQAkoASWgBJSAElACmY3AzJkzXeGkRo0aKpxkthdY70cJKAEloATSjYCKJ+mGXhtWAkpACSgBJaAElIASUAJKQAkoASWgBJRA8gm8//770q9fP1NBuXLl5Kuvvkp+ZXqlElACSkAJKAEl4ENAxRMfHLqjBJSAElACSkAJKAEloASUgBJQAkpACSiByCcwfvx4efTRR01HixUrJj/99FPEd/r48eNCWDHy5G3fvj1efx9++GEpX768TJ8+Pd45PaAElIASUAJKIK0JqHiS1sS1PSWgBJSAElACSkAJKAEloASUgBJQAkogUxI4ePCg/PLLL8I6nDZy5EgZMmSIaSJPnjyyZMmScDaXanXnzJlTevfuLUeOHJEJEyb41Ltx40aZOnWqlCpVSq6++mqfc7qjBJSAElACSiA9CKh4kh7UtU0loASUgBJQAkpACSgBJaAElIASUAJKINMQ2Lp1q/Tq1Uvq1q0r3bp1kwsuuEA++uijsNzfW2+9JaNGjXLrXr16tbudETZ69OghRYsWNeLJ7t273S6PHTvWbA8YMEBy5MjhHrcbe/fuNaKL3Q+2Pnr0qPFqoW48XdSUgBJQAkpACSSXgIonySWn1ykBJaAElIASUAJKQAkoASWgBJSAElACWZ7A22+/LVdccYVPvhE8Tx588MFUF1CmTZsmzzzzjMt83bp17nZG2cidO7c88MADprsIQVhUVJR88MEHQt6Wzp07m2P8+e+//2Ty5MkmzJcN93XllVfKn3/+6ZZhIyYmRp599llTrmbNmtKiRQtp0qSJVKtWTf744w+fsrqjBJSAElACSiBUAmc5/4j+C7WwllMCSkAJKAEloASUgBJQAkpACSgBJaAElIASEFm1apXgJcE6nxM6q0u7dnLo6BH55Ie5PnhefPFFuf76632OJWeHZPB4t1hbunSp8eCw+xlpjUdImzZtjIfIsmXLjCfNxIkT5bXXXpNrrrnGvZUPP/xQBg4caPYRQ3bt2iWbN2+WvHnzmvBoBQoUMOcee+wxI7Kw0759e5dLdHS0DBs2zN03hfWPElACSkAJKIEQCah4EiIoLaYElIASUAJKQAkoASWgBJSAElACSkAJKAEI4G0y8uWX5eChQ3Jxs6YyvE8fKeAM6GMHnXweA19/Xb779TezzwA/uTxIkp5cW7BggXTv3t29/Mcff5QKFSq4+xlxg7BmeOcgLLFdtWpV472TLVs2czvM9W3cuLEQrgt+eJOcPn1aBg0aZPafe+45IQQYxjkS0I8ZM8Z4AZmD+kcJKAEloASUQAoJaNiuFALUy5WAElACSkAJKAEloASUgBJQAkpACSiBrEGAcFx4fwwePFj+dQbyhzmiyehHHnGFEyggonDsvWcGS+nixU3yePKg4KGSHFu4cKGPcDJr1qwML5zAgfBchOmyuWEecZhZ4YTz+/btM8IJCeRZNm3aJOSWadCgAadlw4YNZs2fiy++2Gzzujz//PMyd+7ckPKjuBXohhJQAkpACSiBAATU8yQAFD2kBJSAElACSkAJKAEloASUgBJQAkpACSgBLwGEEyuCNKtdS4b37StlHHEkIcML5bWp0+S9L74QPFAI4XXZZZcldInPOYSTG264wT1mPTDcAxl8Y+bMmdKvXz+pU6eOIAqdddZZ7h2tWbMmQVZ4rMAT27FjhwwdOlSoz2sPPfSQ9HEELjUloASUgBJQAskhoOJJcqjpNUpACSgBJaAElIASUAJKIMIIrN12WP799z+pUTZ/hPVMu6MElIASyPgEvMJJ53ZtTZiupNzVDCcPyiAnlBf21FNPye23357o5ZldOAHA6tWr5fLLL5euXbvKiBEjfJgcOHBA6tWrZ45xLkeOHD7ny5cvLw0bNvQ5dsgJo7ZkyRKZP3++jB8/3pwjV0yNGjV8yumOElACSkAJKIFQCJwTSiEtowSUgBJQAkpACSgBJaAElEBkEThx6l9ZujlGtu2PkenzNsjfm6Ild65z5Nxi+WTj1mi3s6/c01Aql8wrxQvkdI/phhJQAkpACYROwCucVHfyjDx6222hX3ymZBdHcMEQUAgtRQgv6zVhTvj9+fLLL+Xuu+92j2Y2jxP3xhLYKFiwoAnrRYJ4PEvwIDn77ISjz+fPn1/atm1rlnXr1pnwXYsWLVLxJAHOekoJKAEloASCE1DxJDgbPaMElIASUAJKQAkoASWgBCKCwMnT/8lPq3bL+h1H5G/Hw+SvrYdk++5j8fp2LOaUj3BCgftGLzPlWjUoLj1al5OGlQrFu04PKAEloASUQGACXuEkX5488uZA3/wmga8KfNQroNg8H4EElJEjR8qoUaPcSrKicGJvnqTwN998s7z00ksmGfyll14q+fLlEwSVN998U/I6+WWw7t27m+NFixaVo0ePyvr162XlypXmnPVeMTv6RwkoASWgBJRAEgioeJIEWFpUCSgBJaAElIASUAJKQAmkJYHdB4/L579tly9+3SFbdx6J13SBArmkWsXiUqtScSlSKLeck+0sOXL0pByNOSlRuw7J2o17ZGtUtPz7338yf/lus3RqXVZ6tCkn5xXNHa8+PaAElIASUAJxBPyFk8nPPpNojpO4qwNvIaDUrFhBbn7qaTdRur+AEh0d5z04YcIEadGiReDKMtFRb64T7221bt1apkyZIkOGDDFiyCeffOKe3rZtm1StWlVOnTolCxYscI/bjUqVKpl8Kv6hvex5XSsBJaAElIASSIyA5jxJjJCeVwJKQAkoASWgBJSAElAC6UDg13X7ZOi0NfE8THLnzi6VyxeTquWLSPUKRX2S6wbqJmLK31v2ysp1u2Tz1v2mSL682eXeqytLlxZlAl2ix5SAElACWZ5AIOGkphOyK7Vs9caNcosjoBw8fFi8ic+p/7BzrFOnTnLdddf5hO5KrbYzaj0nTpyQ3bt3m/97eJjkzBkXjhIBZe/evRITE2NyoxQoUMD1Ssmo96v9VgJKQAkogfQnoOJJ+r8G2gMloASUgBJQAkpACSgBJeBDYM6yHTJsyhqJOX7aPV6pQjGpUbGoVK9YTHLlSJ4D+eI/t8mi37fIwYMxpt6uF1eQAY6IoqYElIASUAJxBMItnNiWEFDwQDnkiCX333+/PPDAA/aUrpWAElACSkAJKIEIIKDiSQS8CNoFJaAElIASUAJKQAkoASVgCbw/b4u8OmOt3ZWWTSo4okkxObdobFx390QyN44cPSELft8qix0RBWtSu4S8cVfdZNamlykBJaAEMh+BBx980ITUyu/k05j0zGBJTY8Tf1qrt2yVQU7ujtV//WUSyOOFoqYElIASUAJKQAlEBgEVTyLjddBeKAEloASUgBJQAkpACSgBeW/uZnnj03UuiVs6N5Iy5+Z391NzY92mvfL592vk+PFTUqdKEXmrT8PUrF7rUgJKQAlkSAKucOIkJZ80+OmwCicW0KGzs0nHPn0kKipKBRQLRddKQAkoASWgBCKAgIonEfAiaBeUgBJQAkpACSgBJaAElMDKzQel9+tL5cSJ2FBdD915oZxzztlhBbNz7xH5aM5KOXQoRprXKS6v3lkvrO1p5RmPwF/ObPihQ4fG6/grr7wihQoVindcD4SHwNy5c+Wdd97xqTx37twyZswYn2O6kzICrnCSP79MchKU1yybdnmh1h46LDf27et8Hx9SASVlL6NerQSUgBJQAkog1QgkL1hyqjWvFSkBJaAElIASUAJKQAkoASUAgVdnrXeFk1uvbRx24YQ2CQV21/WNZdJnv8uilbvl2Y/XyhPXVeOUmhIwBA4cOCAM3Pvb8ePH/Q/57DOov2XLFhkwYIAUKVLE55zuJJ3Azp07A74OSa9JrwhEgBwnCCdfffWV1KxZU57v10+qlygeqGjYjlXLn08+HPOmdL+7t+lL7dq1pVatWmFrTytWAkpACSgBJaAEEicQ3qlsibevJZSAElACSkAJKAEloASUQKIEfvnll0TLZOQCb371j/y+dp+5hWsuqSWliudLs9vJ6SSfv6ZdTdPerPlbhGT1aiIjR440OQ/++ecfxeEQuO2222TdunXucu655ybIZc6cOTJ58mQ57CTCzqq2f/9+GTRokIwePTrFCMiD4eWf4gq1ApeATQ5vhZP3R4xIc+HEdqZqrlzyxEMPmd1u3brJqlWr7CldKwEloASUgBJQAulAQMWTdICuTSoBJaAElIASUAJKQAmETmDhwoXCINIFF1wgY8eOlc2bN4d+cQYouWHnUXn3yw2mpwgntSun7WxnGi5RNI9c0LSi6cPrn/8juw7EmO2s/GfUqFFm9ne7du3Me6+vE05n4sSJsm3btiyJ5ZxzzpEcOXK4S5aEkMSbRjj64IMPBCEppXb22We77Hkd1FKHgBVOECkubd9ePnj1Vcl7PH2//zo2qC8jnntO6Ntdd91l1qlzt1qLElACSkAJKAElkFQCKp4klZiWVwJKQAkoASWgBDIFgU2bNsktt9wi7Z3BkrkBQtJkipvMJDdx/vnnm9fq2LFjJvcCg9l33323zJgxI1MMKs1autO8UnVqlEwX4cS+TVo3LicVyhWR3fuOyYsz1duCAe9HHnnEhPDZunWrfPbZZ/Lkk0/KRRddJAgp7POeVIsjsHfvXjl69GjcgSBbp06dEsJQnT4dm98nSDFzmAFkQoelhtE/a/v2xXp62X3v+uTJk6Z///33n/dwwG36d+TIkYDnknoQLvQLgY56//3336RWoeWTQADG1rujy2WXyWv39ZM8B1PnvZaEbsQv6rz/rqlRXZ53PFD47qGP9FVNCSgBJaAElIASSHsCKp6kPXNtUQkoASWgBJRAxBNg4Oa1116Te+65Ry688EITc5uQIU8//bTMnz8/Ivq/fPlyWbBggSxbtixZ/SHx7o8//mjCoDzxxBPJqkMvSjsCzz77rHz77bcyxEng27BhQ/nyyy/lgQcekLZt28pDzgATA92hDMSmXY9DaynGSQ7/3fJdkitXdjm/frnQLgpjqbpVY0Mx/bh0uyxatz+MLUV+1eQ94DuQ99a4cePkiiuuMJ1GMEE4QUBBSEFQ+e233yL/hsLYQ+6/RYsW0qhRIyM2vfDCCwFbQ2R4+OGHpXLlytKsWTOpVKmS4ecvQiEivPXWW6a+unXrSr169QTRlNfBGv+LypcvL4899pg9ZNbkiOC4NfrE/7Frr73W1EdeC8RXvkeuvPJKQSixFhUVZYTaKlWqmP5VqFBBXn75ZZ8yhCKj/qlTp5o66R9t3nHHHW6Isq+//tqUadWqlan6999/N/tcx8L/U69xLwyQw4V+IRhTL14HauEhgKeJFU4ubtZUhvVyWJ84EZ7GkllrpxbNZVifPiZ0F98/GsIrmSD1MiWgBJSAElACKSCgCeNTAE8vVQJKQAkoASWQGQl88cUXZjDafybtr7/+KiyIDszG7t27t5x11lnphoCBc3IRlCtXTn766ack98ObwLho0aJJvl4vSHsCvGY333yzWb7//nv59NNPZebMmTJt2jSz8F64+OKLzcJgaUaw0V9vlO07D0vjemWlWOHc6d7lOlVLyC+/b5Hdew7LZ79ul+ZVC6d7nyKhA5c5s9JZVq5cad5zn3/+uWzfvt14CBDKiwUhpVOnTtKxY8dI6HKa9WHXrl1y3XXXmfZggIj5xhtvSN68eeP1AaGT/zFY/fr1BVEBdognI5w8E9aGDx8u48ePN7sILMWKFTP/f55zQhnlcnJC4DVovTK84gcX+P/v4hih/po0aSKLFy82eWy6du1q/nfwev7xxx/SuHFjOX78uBFDeF3pO+UR2F955RXTJkIaZtslJw5l+a7hfxDi7jfffCOdO3eWUqVKGYEEbwHyaFBfhw4dzPX88Yo7eEHedNNN5lzVqlWNaMI9xsTEGCHFvUg3Uo2A9ThhXbp4cRnuCBSRal3atTVdG/T66zJgwAAj2hUoUCBSu6v9UgJKQAkoASWQ6QioeJLpXlK9ISWgBJSAElACySfAIBazqK0xkNOyZUtBXCBhN54e2IQJE8yMzYwsOvTs2VNsiBS21TIWAQZpWe677z5hljfL0qVLjbiHwFejRg0Tkg0xhZnnkWoLV8WGEapWvljEdLG2430y1xFP5v+xW053F8mmvurua1OnTh1h6eMMtuJ9gleK9cZD0GMhOTgCCkJK6dKl3Wsz6wYeGBj3/KqTLwKDiRUEzAHnz/r1613hBEGBzyieg3BCAEUQhxdhiqxwgvcJn2GEev7/8Nn2ihC27lDWgwcPljx58pgk9ni/vPnmm8a7ZceOHeZyhFjEkDZt2pj/ceQV2bhxo9l/3Rm4tuKJbYuB9xUrVggD2bzut912m/GIQzzBa+TFF1+ULVu2GPEETxb2AxkCEsb/W95P5JZRCx8Br3BCK6MHPiIFAgh94etB0mv2Cih4y+B5qaYElIASUAJKQAmkDQH9ZZY2nLUVJaAElIASUAIRTyA6Olqef/55t5/9+/c3A4TZsmUzxxik/uijj2TYsGHy8ccfG0HFLZwBNwoWLCjco1rGJkCYG7ygWBYtWmREFGZ/r1mzxiwMehIC5+qrrzZLJM3YPXjslGzedkjOLZFfKpQpGDEvRD1HPPl58UaJOX5KPvttm3RunvkFgKTC5/vDekHhuYB4hyCwdu1a972HiIIwwIIXQ2Y17hlDdLBGCC+8LbxeIOvWrTOn8ThBOMEIUYXHGJ4heBIinqxevdqcw+OEnFTWEPJZkmt4c1hvSbZJwO41vjMw7gMRBaM8/aBv5CLxeiwi4tjvE0KQYXi2JNXsewM+fI8RipD6EFMykzEBg4H/1DJEppw5cwoil12z7d3Pnj27sHDMbvN+teGvBjmCV00nNFtGMASU1Rs2yHuO5xZeT4iNakpACSgBJaAElED4Cah4En7G2oISUAJKQAkogQxBYMyYMe5AF7HbEUv8jTjtzKoNNDMWLw5mYjOLlkEowqzUrl3bxJT3hiixdTLLlwEMyjFj97vvvjMziznGgPill15qPAtsedaET7HJiEk2jDHohqDjbwy6NW3a1D1MCJRRo0ZJoATADRo0cPMZuBec2bBtMsDFQmiWn3/+Wfbs2SPVq1cXwr+w9hrhXxjcoC1i9RNX32sM7ttBNvIm5MuXz3vabHNfs2fPNiyJww8TePIaMPCnFp9A8+bNhWXQoEHm/WTD6CxcuFBYmBWPiHLVVVcJr3l624I1e0wXShSN//qnZ9/y5skuJR1BZ0tUtHy2aLuKJ4m8GHzGWcilwXsOEQUxBUF60qRJZrnkkkvMd6f/d0EiVWeI09ZzwzvYz/+IatWq+eSkIrwXxveY12DH993u3bvNYVtfWn9GbbvPPPOMsPjboUOHfMQTvEms+Qsx9ngoawQj/l+QJ8Z60XEd/2+Y0OBtJ5T6IrFMoN8AKe0nvzlYvAJdUupsVruW3HqV7//mpFyfHmX7dusq3zrhU992PLJUPEmPV0DbVAJKQAkogaxIQMWTrPiq6z0rASWgBJSAEghAwMah5xTJdINZIOEEIYMwNuRE8dqsWbPM4A8zsP0HDRkk4jyhv5i9SxgVa9Tz4YcfSr9+/UyMb3t87NixAQdKEH787dxzz40nnhCmJZAxG9Ymg/Y/b9tEtIDRJ5984hYhzj0hzAglQwgpawg1ti2u8793Qtq8++67pjghw/zFE4Ql7t1rlu3bb79tQtpkhgE17/2l5jbvUZujYv/+/SYPAYPaCHSEA2IhFJD1Rgn0nk7N/gSr66dV+82p4kXyBiuSbsdLlShgxJM9B46neh8YSM2dO7fxTMifP79Z8xngGMIga+9ivd9SvSNhqPCEk3Cae8BDgpBPeDDY9yCiKfdZokQJuf/++zNNbhQbvpEQVQghwYz7xv7880+fItYLoLiTewIjXwiGCMXgeGKfT5uDhGv8E89zLFQrW7asKcp3R6DQYLb/odZHOSuqILwkZF26dDHiGt4nfNfzfwaBnWT1/P/M6Mb/wQ2O1wSfD7swycBu2zX5ctLKhjsTFzKaEV6MZdsZoTGj9V/7qwSUgBJQAkogIxJQ8SQjvmraZyWgBJSAElACqUyAASpm/mIkv03qINHAgQN9hBNCtpAE14Y+IVb8Dz/8YMKf+Hd97969ZtYtIV5sAmE7kxRPAULe4HWBMah1+PBhs434Yg0vFX/zn+lKyA7CoVhD4CCMSKiG4MH9MFDIDGvvtY8++qhJGEwbKTVC1niFE/IrMDOZ2Pq0T/gYZrgzuGZD0KS0TXs9zBioZmHAMqE19+p/PrFrEjtPfQyesfCeDGVNsuhg5fzrwMuJ9xYDrAgpLMzeZYATLyG8VqZMmWJxhH29YecR00aJInnC3lZSGyhTPL+5JPrQiaRemmh5wiIxcMpnCA+urGR8f7HgUcB3GInVM7rZ72eSqyNC83nie518Jl6zgi/eiX///bfxqCDkGd9pGOGxMBvSi88qoSIZeA8koFQ4E26J72YEFNpFJE2ukacEo74hQ4Yk+f9goHb5zsG4R4QRr3eOf3m+z/HWYcE7h/993kkN/uUz0n6wfC/+98B3thVSvGu+L/iux/yPe/ftdiBhhmO878iN1dkJgVXmjFjn34dI3l/kCI9rHFGWJPendu6Qc84tGcnd1b4pASWgBJSAEsgUBFQ8yRQvo96EElACSkAJKIGUEbDhSqjFX3RIrOYlS5aYZLmUQ1iYMWOGMKjFgPZTTz1lQtZwjpBZNpkw+17jOgaJWDPA8dBDDwneFxjhluzgHKFNrLVr184MSBEv3yYXtucCrRFnJk6c6J5icC8picQRLm688UZ59tlnzUAe8e9JkIzoZEUN//BdbmNJ2Bg+fLhbesSIESYsGAcYOBowYIDhwqAkYpTX28W9KAUbeMjwOvDaMQiVFQzRhPvFeE+kpR2NOWWaK1E4ssJ20akyjucJduLEaTly/LTkzRmb+8gcTOGf9957z9TgFSBTUiWfDRbes3bQ1O7bwVTW3nLebQZsbXl7nDXH7Tn/tT1v10ntP6H4WMihwXdKRrYbbrhByC1E4ngGpgm3hQDhb4gnCOB4lOD5Rb4TK7AgkCASY3iA3HXXXeZ7HWEePniC8DklmTxJ5PFW5LsfcXnlypUmTwmiP94NNtdKr169Aobf8u+X3acNQmXh8UHIR/qHJw3h1zh+yy232KIhr8nFwYQEvBQJJdnWEfDxiuS7Bq9FBBOSf+NRyH1Tftu2bW5Yx9T+jg+54+lUEJGMJU+e8AjKfOfgabp6w8Z0usOUNTv07XdMBX2de/gvJvW9AlPWO71aCSgBJaAElEDmJKDiSeZ8XfWulIASUAJKQAkkiYDNH8JFNnRKqBUwKGSNBOwIJxheBAx8EfMfQwwJJp488sgjRjihHINHDG5Y8YRQMJFi3I+dAc2gJ6FWEIUwBkJTKp4w8Dt37lxTHwODDChaw9ODEF+WC6FvUntgjfAwCFS8dsziZmCPtV1Sa9/WH6gNe7/B1gygsjDT3K7tNvtWDLHlvPsMSjIDHK8oFhvih4FYEoATfi0tjYTsWK5UFCZSq/95csc9Juw+eFzyFk/9wUw81DKL4cnmXXhvsb98+XIjEOA5Zj0suGcEYb7rMrpwwr2cd955Rpjm+x/vChZyYyFY+XtOEIYKUf3jjz92hRNE6SeeeIKqXOO7lvBdL730kvEWwwPFGv+vbKJ2/ncQZhIRG0GC7y8EaFgj0tAna/b7i322rdltvpfedcIpkufqgw8+MP2z4g5l/cUTex3n7DaJyf2NXCb87yMUpf1+pwzh3Pg/stHxJCBUlw3NaK8nN1NmeH/Y+4mEda1atSS/M5EC743nHCHisdtvi4RuhdSH1xxxkn5Xd35jXdvhCsl2JgxeSBdrISWgBJSAElACSiDZBOKeipJdhV6oBJSAElACSkAJZHQChQoVcm/BJu11DySywSC0tVatWtlNsya+PwP833//vdnHW4PBIn/zFx2spwnl7AC3/zVpvY+YwQC712wYGo4xUJpSY3DfGiGkbC4Ae8wbFszL3Z5PjXVmSkJL2B/eewxKLlq0SP766y8XEe9DwuIwEx4vpvSwEyf/Nc0eczxQ8uWNP+iaHn2ybR4/GZd7YFd0jFQIg3hi28oMa/KcsCAYICjbhTBB1hi4JazV5ZdfbkIz2eMZZW3zBdn+8rnCiwLDowKvE/5/kMcGFnx3Iy57BQX+JyCIELaMsoj1VpC29bLm2B133GGWAwcOyMGDB4XvP8Jgecu3bt3ahDQk/BvnEED4P4QwS3nK0i9r3mTwjz/+uLB4jb7b44gx3AP5d/CKtIaI4i+kUCbYdzIeNQg6Tz75pPA/EKGlcOHCrndF7969pUePHsJ9IvbidcH/Gu990va0adOMV6bth66TTgDR7SVHYMMr6T3Hy7JmxYrSpV3bpFeUxlesdkST16fFCogjHGExe6XKcrbznlNTAkpACSgBJaAEwk9AxZPwM9YWlIASUAJKQAlEPAEbLoWOJtXTw+ZK4Vob351ta15PFmYMBxJP7Cxie00krr2DZ+HqH+G/rDHT2jvb2h63a2YtqwUmQKi3OXPmmJnnXqaUJt8Gg9csgd6LgWsMz9HjZzxPYk5EnnhywgnVZa1EoVx2U9cBCDDojUcBgonNjWSLIbDynmOQH4EhIxqCQiAvIa8oYu/L+32PoBDMEAZsYvhgZexxhAR/4dqeY41gYkUc9gnblRqW2t/5iCLBwlHBmCUh4/+r/+sQrL6E6snq5xDMycFC7rBBTrg5LNIFlIGvxfaz7223Sn3nf5ejwGX1l1HvXwkoASWgBJRAmhFQ8STNUGtDSkAJKAEloAQil4CdWctMW+K9k9CYGcKhmNdrhZn+/tdxzJr/OXs8I6wZoEst8zLx1slsZK8lNAiY2gN73nYz4jahbwjTg2jinWnOvTCAbQUTmxQ6Eu6xQP4csi/6uMR4hIpI6Bd9iPF4nhQvkDNSuhUx/SDE3nfffWc8m/Bu4rvTGsm+rWBy/vnn28MZdl2zZk2TzyTD3kAm6ThenKkdqjGToEnybdiQmBlBQLHhui5xRNgHnx6c5HvVC5SAElACSkAJKIGUEVDxJGX89GoloASUgBJQApmGAMlxv/32WxNfntwPffv2DeneKlSo4JZbv369zwxgTnhDT4U609itMIENO+PWO2iZQPF0O3X06NF4bZMfJZCVL1/ePUwy+mA5YtxCWXyDEEmIJXYhz4k1vKlISh3JA44NKheW75fskO17DknZkgnPOrf3lVbrE2fEk/x5s6dqsvi06n+42kEoYUE48YbZa9y4sUkMjmjSqFGjcDWv9SoBJZBKBBBQEDq7du0asR4orzuh2gjXVcb5f/byGS+ZVLp9rUYJKAEloASUgBIIkYCKJyGC0mJKQAkoASWgBDI7gfvuu8+IJ9wnIS0qVaokV155ZaK3Xa1aNbcMogszrW3y3Hnz5rlJkqtWrRovhrt7YTI2EG1WrlxpxB6S+iL+RIp5w6+QMBkBxYo9DLguWLAgYFcpAycSLpMYHv6EGFHzJYAg99lnn8msWbN8wszhjWPFEoQTEnJHsjWsXMiIJ6v/2SVN65SOqK4i6GBFCkY2w7SARihDPo+857x5cwjFdeGFF5oF7ww1JaAEMhYB8hCRS8YKKGcXKiidED+d3DPpbYQUm/HDXClbpoyMnzBBMkJ40/Rmpu0rASWgBJSAEggHARVPwkFV61QCSkAJKAElkAEJ1KtXT6655hozQEj377nnHjNwz0xqErgjAKxYscKERLrkkktMglvKcQ3Jf/EA+frrr6VPnz7SoUMH2bFjh8ZBeVgAAEAASURBVJCc11q/fv3sZqqsmTHK4DlGYmH6i5BDeC36Qogwb4gThJbo6Gi3bfIUWEPQIFeBNQQMbwx9ezzUNcmK69SpY8QdrrntttvkuuuuM30b6SSr9donn3xi4tgzcx2DWffu3c02SW3r169vQgCRQJ7wauSNoe+2jCmYBf7gZUJYrtmzZ5vF3jKvN+/HSy+9VNq3b59gbgR7TaSsG1cqZLoSte2A7Nl/VIoVzhMpXZOtOw6avlQvG1keMWkJ6Oeffzbfh4gm1oOsQYMG5r1GGDi+F9WUgBLI2AS8AsojQ56TbM89Jx1btJB/o9Mvr5gVThBlEXdUOMnY7zHtvRJQAkpACWRsAmf951jGvgXtvRJQAkpACSgBJZBaBBAXnn76aWFAPyFjtvXkyZPdIgxo9+7d293332jZsqUp780bcu+997rix5o1a4wwYK9DeEEswHr27Okjwtgy5A2hH8HCdjVr1swn4TohOn799Vd7eYLrF154Qbp162bKMLBCW02aNJHp06f7XPf5558bsYiDb775phGNbAEG+hE//A3vCGa5Ut4aQgseKtZo/4033rC7Adfk+LAePgELZKKDCE4zZsyQzZs3u3fF64FXDsJJxYoV3eMZbaPT0IWyfddRubBZRWnVqFzEdP/VSQud9/0JGdW7oZxfvUjE9CutOsJ7btSoUaY5wukhxPJeu+CCC9KqC8luB++YoUOHxrv+lVdeEW+OqngF9ECWIjB37lzBW9RrCPRjxozxHsoy23g08r/50KFD8tKIEXJ13TrynydnW1qBGOT8Npjx7XeiwklaEdd2lIASUAJKQAkkTEA9TxLmo2eVgBJQAkpACWQpAgysMWBIuKgJTpgIPE28yc3JWYKHCgPXXsPThLA2jz32mOttwXkSnv/vf/8ThBKvcMI5776/CODdx4sjkFE3A+oMEiJU+Bv5V7wWrB5vGbvtbd8eC7T21undpiwD+3jk4EliGTIY8uijj/qEmgpU78MPP2wGaocPHy6//PJLoCKyf/9+KVIkawxqly1b1ggnDF7jCdW0aVOpUaNGQC4Z7WD7hiVk0lcbZc0/u6Vl/fPk7Gxnpfst7Nx7xAgntRzPmKwonPAC2JCFrVq1Mu+3dH9RktABPNMYGPc3ktwHMgaL33vvPZOfas+ePVKsWDF59tlnM9T3C55BAwcONOERhwwZkqohIgMxS+tjf/zxh0ydOtWn2QceeMC8Vt6DoZbjGrwYA71PvPVlpW0mSrz00ktm0sOAhx6SlbfcIgO7dBbx5NIKN49Hx09Q4STckLV+JaAElIASUAJJJKCeJ0kEpsWVgBJQAkpACWQ1AgzS796924SxKliwYKK3f+zYMSEhOmEmSpQokWj51ChASCfyErBG+CDnCGG3zjkn/eeJkMQcHjly5JCSJUua24URg30cy549u1n7iy+WC07Cu3btkn379pl7Q+AqXry4j/hky+o64xHYuveY3DTiV4mJOSWtm1eSCxqel+438fOyLTJv0T8y4Prq0vWCsuneH+1A0gjgYYenHeECEWut8X3jb4glhLzz9+BbvXq1m6fJ/5q02kd8xhty8ODB5jsyoXbJr3XzzTebInhCEtYxMxmeiYSm9NoPP/xgcpN5j4Vajmv+/fdfOXXqlHs54SqxTZs2ucey4sZHH30kDz74oLn165ywpM/1vCVNMHy6fLk88uwQ9ThJE9raiBJQAkpACSiB0Amk/4hC6H3VkkpACSgBJaAElEA6EChcuLCwhGqE/ahSpUqoxVOlHIOCkZp/AA+bcuV8wzHBiCUUQwxCCEpJDpZQ2tEy6UOgbNHcclmzUjJz3hZZvGKr1KlcQgoWSN8k7QuXbpIihXJKh8al0geKtpoqBBCPAwkm3spHjx5thJOGDRtK//79TViymJiYdBdO6CPhI7dv3y6PP/54oveBNxp5pXLlypVpvNK8rxOeUBs2bDCHEMYWL17sPe1uh1qOCxDsE3t/uBVnoQ34YggoHzv5jv5zBKaBN3STAo63a7hMhZNwkdV6lYASUAJKQAmknEDgOBgpr1drUAJKQAkoASWgBJSAElACSiAEAl3PLyPZzj7L8UY6Ib84Akp62lc/r5eTJ0/LnZdVlHy5sqVnV7TtNCCA9wJ2//33S+vWrY1HGyERU2KEB/P3ZAlU38GDB4UQY6lhiNGEXHrOSfbtDQnpXzfCEN42oRj9syEXQymfWBnapf1Ahjcii9cTxL8cYodd/M95920Z1mrJI4CA8uKLL5qLpzueTD2fHiwHw5T/ZKYTHhWPkzJlymhy+OS9XHqVElACSkAJKIGwEtBfVGHFq5UrASWgBJSAElACSkAJKIGECVQplVcub1HaFFrqiCdrN+5N+IIwnV2xbqfQfp3KheVaR9BRy9wECAn4zz//mJvEc8PfCC1Yvnx5ufDCC31OET6K4+TXwNasWWP2n3zySeMlUq1aNWnUqJG0a9dO1q1b53Mt4sBbb71lztetW9fk0KLcuHHjTDlEF+pmwesEIxeFPcYakcFajx49fM5xPpAAsXHjRhPKrHr16tK4cWNT5+TJkwUG1tjnenKLXHvttUL/aPuOO+6Qw4cP22JJWiMOkQuMemiX9q9xQkHN9ctJQ+g08jjhQUnbU6ZMEcQbtfQj4BVQVjmfk5uffCrVBZSZq1bLw44wQ6hR8swR7lRNCSgBJaAElIASiCwCKp5E1uuhvVECSkAJKAEloASUgBLIggQGdqkmTWoWNXf+5by1smPPkTSnMOu7NabN/11eMc3b1gbTngD5mDA8TQJ5m1hh4eTJkz6ds/vkzMBsua+//lomTZokzZo1M/UhzIwfP97n2uHDh8szzzxjPFMqVapkylIOjxGS1hN2i0FrGzqJizt27Oge47g3l1Xz5s2lc+fOZrEN2f7YfcSWLl26CLlgMHJ74FGCqEFoMGv2fkaOHGnCYlnR6Ntvv5VvvvnGFgt5jYhz4403CqIM7TVp0sS0/fvvv0vPnj2FtTWElYsuusicJyTXI488Irc4CcsDCUH2Gl2Hn4BXQFnjCHCdBjwoq511athixxPp4SeeMMLJtGnTjMBGvQh4fEbUlIASUAJKQAkogcggoDlPIuN10F4oASWgBJSAElACSkAJZGECOc45W4b0qCUdBy8w4bu++HGN3HR1fcmVI/w/1/dFH5OxU2IHlp+5tY40qxp6jqMs/JJl2Fvv1q2b/PLLL27/GdhnwNbagAEDpF+/fnY35DWeIjNmzDAeFiR6r1+/vsyaNUuGDh1qBI+tW7e6YgreJxdffLGQ02nBggXyzjvvSIcOHYzoYsMlzZ8/33ifDBs2LKC4Q8f69u3r9g/xJlCYrZkzZ/6fvfMAj6ra2vCC0CGUhCIQeu9FugUEAUGKdFAEKeKlyA9XEdArSBOliVdQr6CI9F5EqggI0kGk99577+U/38I9TiaTZJLMJDOTbz3PzDlnn312ec9kkuzvrLVUrIFogkVq5PDCU/4DBw4UCCUQVuwNHh87rFBK8AL47bffpE2bNrJo0aJQAo19/fD2kbx9586dOnbs58r1VJT85ptv5MqVK7bFclw/cuRIWzNgV7duXfnzzz9ly5YtAoGIFncEjJCHHCinLlxQD5R5w4dJ1gwZoj2ouZs2Sc/PPg8jnKBB5K3BzwdEu88//1wqVqwY7X54IQmQAAmQAAmQQMwJ0PMk5gzZAgmQAAmQAAmQAAmQAAnEmEC6lElkUs+nC6XnL9yU+b/tk8vX/glRFOMOnDRw8PjlUMJJzZKZnNRikT8RqFKlikBAMYvCmBuOzQvho6JjwcHBKpzg2rRp00rRokVVzDh9+rQ2t2fPHt3C4+Tll19W4QQFlSpVUlElffr0et7dbwgrBqtevboEBQVpvwidBTt+/HioMGAog4hjwifBiwYWXoJ2PRnOGwQYGMJwGeEExx07dpQPP/xQEidOjEO1+/fvC8SiGTNmCEQgeKnATJJ4PeBbnBEwHiiBqVLJDUts7GQJH9HNgTJ71e8qnGAyffv2DSWioezrr79WAeXYsWPSvHlzWbduHYppJEACJEACJEACcUTA84+yxdHE2C0JkAAJkAAJkAAJkAAJ+BqBbMHJVUB5+79b5NDRi3L63DWp9GwOKVc0q1uncuPmPdl+4Lz8vuFpzgt4nFA4cStir20Mi/cwhITCYj1Cdg0ZMiTG44VYYm/24gDKz549q6dLlixpX83j++fPn9c+7EWhTJky6bzhqYJE7tmyZbONI2/evLb9mCRdN6IRcqdEZPv379dFcuR7cTSIKjTvIAABpUiRItLU2iKEV2frZ2ZCv35RGtzsFSul96hRthwnFSpUcHo9BBR4I8EzCgIKPLgi+xw5bYiFJEACJEACJEACMSZAz5MYI2QDJEACJEACJEACJEACJOA+Ankzp5IVgytLxWLprafiH8jyNQdl6qKdcvX63Rh3ct0STZatOyzfz9yiwkmNcplVrKFwEmO0ftuA4wL+5cuXozXXzJkz63VLliyJUi6P6CZrN4PMmDGj7u7bt88Uyblz52whvjzl8ZIlSxbtb9WqVbZ+ne0gHBSEk+7du8vcuXNl+fLl0r59e2dVQ5WZ3DOhCp0cuFrPyaUsciBQuHBhmW4JjlmzZpWNO3fJp+N+dKgR/uEoK2QchBN4NSF8XHjCiWmhW7du8sknn+hhnTp16IFiwHBLAiRAAiRAArFMgOJJLANndyRAAiRAAiRAAiRAAiTgCoGR7UpIl9fySUbLG+XIsUvyzeQNMsdK6r7vyEVXLrfVuXD5tmzadVqWrj0k307ZKJv/OiGpUyaS/1g5Vga8Xlgg1tBIwJFAihQpBIIHFvYR3gp24sSJaIWwwrXG8wPeHvB4iSwZuvEGgZgQEytQoIBejvwlyCeChPJ4kh+WPXt2SZ48ue67+814CqCvbdu2OW0ewoZJHN+lSxcpVaqUIKzZ0QiSkmf4O9fGwYMHnbZpCl2tZ+pz6xoBCCiLFy+WQoUKyXjr3ta3kshHFMIL5960wnN9NW26epxMmzYtTKiu8HpGvh2TD4chvMKjxHISIAESIAES8CwBhu3yLF+2TgIkQAIkQAIkQAIkQALRJvBmleyC15Jt52T6H2dk54Fzstd6JUuWWIKDUkiigIQSlCaFBKdNIRnSpZQ79+5br4dy5+5DuXDllpw4fVVuWt4mxrJnCZQqlkfLOzVyWdcmMMXckkAYAkjm/tprrwkSnL/yyitStmxZWblypQoOEFMGDBggSC6PBOyuWEhIiLz99tua36RXr156PfKLPHr0SJBMHkmyTa4RtIfcLBs3bpTevXvL1KlTdcEZXi8ffPCBILTW4cOH5bvvvrN1bZLFI59IQECALm63bt1a5zB06FBBzhXkV4FgYvKvdO3a1Xa9u3eQ+BvjQ9L4+vXrqygCbwMkpE+SJImGZEJoM5xDUvt33nlHQzNt2LDBlutk3LhxAo+ZQYMG2YYHgQUJ6Hv06CELFy4UCDBoZ/To0bY62HG1XqiLeOASAeM90tTKZ7PHCrtWtWMnGd3zAylvhfWytw27dknnz4donhSUO8txYl/f2X6DBg0kTZo0AiEFAgo+E1WrVnVW1W/KEGoP3zcw/AzVrFlT9/Fzi+8ieOXAU4tGAiRAAiRAArFBgOJJbFBmHyRAAiRAAiRAAiRAAiQQAwIIq4XX8Yt3ZOn28/LLhjNy6vQ1bfHYiSsRtpwjJK28VDKj1C2dQUKCkkVYlydJwJ7A66+/Lr/++qscOHBAhROIDdeuXZPx48erB8qhQ4dsyc0htjgz+3KIJvBmGT58uIbNggeKMYTSshdPELoKwsBPP/2k3hnGQ6Nx48YqniBXyZQpU8zlti1CIsGQlB7iCTxLZs2aJQiPhcTvWIBFnheMBW05mv14zT7EDmMQM+C9Ep4hnwoEpUSJEsmkSZMEws3EiRNV7IHgA0P/xjp37qwswBmvEiVKqLdBs2bN9BpwsRdPWrRoIatXrxaEAzMeNLjG0Vyt53gdj10jgM/qWEvIaN+qleyxfg5a9ekr7zZrKl2aNtUGEKYL3ibG2rZtK8ibEh2DWILPcCNLrIGIMsoK/1W3bt3oNOUT1zx+/Ng2zgkTJtjEEwitsHv3/nkgwFaROyRAAiRAAiTgIQIJrD/8wv/Lz0OdslkSIAESIAESIAESIAESIIGYEbh595GcvXJHjl64I38duy5PJIFkSpdM0qRKJg+sNaaQoCRSOnsqSRwQs354tW8RgLeGs0ValGNhPzqG0F0I4wUh4s6dO4LFTQgKjknho9I2RBh4YaAN5B2B2ODMEN4LAgL6xII1nsKPrsE7BS+EtDLCSFTawljy5MkT4SX9+/dX0ca+Ev7lhtgDduAYFBQkjsnocQ5iEeaI+jdu3FA24AxPGkcDP9QJDAyMkEl49SAywXvF0Y4dO+ZYxOMICOAz3NTy0IKAAsv6d1i1Uxcu2K6CSAfBMKa2e/duqVWrljbz+eefqydKTNv0xuvPnj0r5cuXtw1txYoV6rkFLy54dHXs2FHFT1uFv3cuWMzx85M0aVLHUzwmARIgARIggWgTcP4XarSb44UkQAIkQAIkQAIkQAIkQAKxQSBVsgDNV4KcJS8XzxAbXbIPHyCAxXRnyajtvSeiOo3g4GDbJe7KEQIRxBUhBKIKEnS7w+DxYe/1EdU2IWIgXFlEZsIN2deBUGNykNiX2++Dq2GL+lgEjshc5RdePQhWjp8TCDu0qBHAfZo+d64Mt0Kr/WiFl7MXTfCz2K5dO7eFmEK+FXgdvfDCC9KzZ08VAtG+v1q+fPnU6w15YhC+z5lBVP3hhx9kxIgRygN1wGfIkCGSJUsWZ5ewjARIgARIgASiRICeJ1HCxcokQAIkQAIkQAIkQAIkQAIkQAIkQAIkEJrA+vXrBaHokMMHwhQ8wJDrx90GT7DSpUtrswhH9+6777q7izhtz3ieNGzYUE6fPi07duyQrVu3ysGDB8N4niCs38cff6zjLVSokC2fEXIbwWMlPI+2OJ0gOycBEiABEvApAgl9arQcLAmQAAmQAAmQAAmQAAmQAAmQAAmQAAl4GQEIJgjPBU8JJDT3hHCCKcMTDLl3YMOGDROEivNXa2XllEGovcWLF4eZIsLbjRw5UssHDx6sdTZt2iQQTo4fPy6LFi0Kcw0LSIAESIAESCCqBCieRJUY65MACZAACZAACZAACZAACZAACZAACZBAHBFIliyZmPw033//vXTr1i2ORuLZbqtXr66h9pA43tHggYMXrG7durrNmDGjVKlSRff379+vW76RAAmQAAmQQEwIUDyJCT1eSwIkQAIkQAIkQAIkQAIkQAIkQAIkQAJxQMAIKHPmzBF4afibIVdT27ZtZfPmzbJr165Q00OCeFjmzJkF+WWMFSxYUHfPnTtnirglARIgARIggWgToHgSbXS8kARIgARIgARIgARIgARIgARIgARIgATijoARUFatWiV16tSJu4F4qOemTZtqy+PGjQvVQ4YMGfT4zJkzcvPmTds5E9IsU6ZMtjLukAAJkAAJkEB0CVA8iS45XkcCJEACJEACJEACJEACJEACJEACJEACcUwAAkpAQIAmV69UqVIcj8a93SOHSdWqVW3J4E3ryP2SMmVKPVy4cKFuEcYLieJh+fLl0y3fSIAESIAESCAmBCiexIQeryUBEiABEiABEiABEiABEiABEiABEiCBOCZw+PBhSZUqlZw6dUpM6Ko4HpLbum/ZsmWYthIkSCC9evXS8h49esirr74qpUuX1mTxEFxq1aoV5hoWkAAJkAAJkEBUCVA8iSox1icBEiABEiABEiABEiABEiABEiABEiABLyOAvCAIZ3Xnzh3JkSOHXL9+3ctGGPlwIIrAEib8Z7mqcuXKAk8Tx3KIKr1791YPlJ07d+r5ChUqyJQpUyRx4sR6zDcSIAESIAESiAmBf34bxaQVXksCJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACJEACfkIgwRPL/GQunAYJkAAJkAAJkAAJkAAJkAAJkAAJkAAJxGsCL774ophE8mvWrJFs2bL5NQ8sa50/f15Sp04tyZMn9+u5cnIkQAIkQAKxS4CeJ7HLm72RAAmQAAmQAAmQAAmQAAmQAAmQAAmQgMcI/P7771KoUCFt//nnnxeE83LVOnXqJCNHjnS1ulfUQ6ivTJkyUTjxirvBQZAACZCAfxGgeOJf95OzIQESIAESIAESIAESIAESIAESIAESiOcEFi9erAnUgaF27dqydu1al4js2LFDvvjiC1mxYoVL9VmJBEiABEiABPyZAMUTf767nBsJkAAJkAAJWATwBCGShtJIgARIgARIgARIgATiD4E5c+bIc889pxNu0aKFQFCJzHr16qVVhg4dqonnI6vP8yRAAiRAAiTgzwQonvjz3eXcSIAESIAE4jWBZcuWSYECBeSXX37RJw7jNQxOngRIgARIgARIgATiIYHJkydLtWrVdObvvPOOTJs2LUIKr776qhQrVkxDff3vf/+LsC5PkgAJkAAJkIC/E2DCeH+/w5wfCZAACZBAvCJw7949wVOGeK1fv17nHhAQIIcPH45XHDhZEiABEiAB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EaIrPJEQizoQT9AvBEXjSYDrkZPiypUruvCDfjAubGPTwARzhUCA8YVn8JhAPHnk08A4w5tveNdHt9zV8UXWPoQe5IHBE8q4J2CPe4EX7o2joT5CvSGRu73njmM9V48hKEEsAmd8xhz7hOM9PicQsOxDpzm272o9c50rn1FTl1sSIAES8GYCeDAHeczgjWJv+J2NhyLsDWIKwjTSSIAESIAESMAfCVA88ce7yjmRAAmQAAn4PAF74WTmzJlStmzZMHP6+eef9elvnEDcaTyxTyMBEiABEiABEiABEiABdxCApyT+3lywYIF69TlrE96YyHdGIwESIAESIAF/JEDxxB/vKudEAiRAAiTg0wTshZOJEydq7H5nE0LYHPxDW716dc2J4KwOy0iABEiABEiABEiABEggpgTgiYJcVwgja2/wKjQhIu3LuU8CJEACJEAC/kAgrN+8P8yKcyABEiABEiABHyVgL5wgnwmSdDozhOpasmSJnqpbt66zKiwjARIgARIgARIgARIgAbcQaNCggYwbN05z7XXq1MkW+hJhEvv06eOWPtgICZAACZAACXgbAYon3nZHOB4SIAESIIF4S2D06NEycuRInT/24VESniGBNvI/IFFx/fr1w6vGchIgARIgARIgARIgARJwGwEkle/Zs6ccOHBASpcure1CQKGRAAmQAAmQgD8SSOSPk+KcSIAESIAESMDXCMDLZMiQITrs4cOHS506dSKcggmZ0Lhx4wjr8SQJkAAJkAAJkAAJkAAJeIIAQnnBazpBggSeaJ5tkgAJkAAJkECcE2DOkzi/BRwACZAACZBAfCcwYcIE+c9//qMYBg0aJC1btowQyeXLl6VUqVISEhIiixYtktSpU0dYnydJgARIgARIgARIgARIgARIgARIgARIgASiRoCeJ1HjxdokQAIkQAIk4FYCM2bMsAkniBcdmXCCzpMnTy5FihTRsF4UTtx6O9gYCZAACZAACZAACZAACZAACZAACZAACSgBep7wg0ACJEACJEACcURg/vz58u6772rvH3zwgXTu3DmORsJuSYAESIAESIAESIAESIAESIAESIAESIAE7AkwYbw9De6TAAmQAAmQQCwRWLp0qU046dq1K4WTWOLObkiABEiABEiABEiABEiABEiABEiABEjAFQIUT1yhxDokQAIkQAIk4EYCq1atkrff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O27cuFA0MmTIoMdnzpyRmzdv2s7t27dP9zNlymQr4w4JkAAJkAAJkAAJkAAJuJMAPU/cSZNtkQAJkAAJOBKgeOJIhMckQAIkQAIk4GECAQEBAgElV65c2pMvCCjIYVK1alXZs2dPKDrBwcEa0guFCxcu1HMI47VixQrdN142esA3EiABEiABEiABEiABEnADAeN54oam2AQJkAAJkAAJhEuA4km4aHiCBEiABEiABDxHIHHixJpcPSYCyvr16z03QCctt2zZMkwpnvbr1auXlvfo0UNeffVVKV26tCaLh+BSq1atMNewgARIgARIgARIgARIgARiQsCIJ/Q8iQlFXksCJEACJBAZAYonkRHieRIgARIgARLwEIFkyZLJggULbMnj4YHy+PFjl3qbPXu2NGvWTCZPnuxS/ahWMv+IJkz4z58KlStXFniawOzLIar07t1bPVB27typ5ytUqCBTpkwRiEQ0EiABEiABEiABEiABEiABEiABEiABEvA1Agkstf6Jrw2a4yUBEiABEiABfyJw/fp19dg4fvy4Tmv37t22UFjhzfPy5ctSqlQpKVasmAow4dWLzXL8SXH+/HlJnTq1JE+ePDa7Zl8kQAIkQAIkQAIkQALxiECHDh00DG7hwoVl0aJF8WjmnCoJkAAJkEBsEvjncdLY7JV9kQAJkAAJkAAJ2AhAbJg/f76EhIRoGf4JRN6QiCwoKEjatm0rO3bs8Jj3SUT9OzsHbxUkiKdw4owOy0iABEiABEiABEiABNxFgM8Bu4sk2yEBEiABEoiIAMWTiOj8fe727dvStWtXjen+8OFDF64Q+fbbb+Wjjz4SPBlMIwESIAESIIHICKRLl04FlKxZs2pV5A05ffp0hJfVq1dPz8+dOzfCejxJAiRAAiRAAiRAAiRAAv5EwIgnJtSsP82NcyEBEiABEvAeAl4vnkCsQAx480IM9Xbt2skPP/wgrgoZMcW9efNmmTdvnsZu37dvn0vNLV68WCZOnCg3b950qb4nK125ckVj0X/99dee7MZv2541a5by279/v9/OkRMjARLwDgLIJwIhJEuWLDqgihUryuHDh8MdHMJ24bVhwwZZs2ZNuPV4ggRIgARIgARIgARIgAT8iQDFE3+6m5wLCZAACXgvAa8XT+zRlShRQhAX/tdff5V+/fpJw4YN5erVq/ZVPLJftmxZady4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q9/RaOsFFKlAMiOAAALlVEDTYfqk/6eTEEg0gUfenR8JnKQHQYiXbuhlLeulRW3m3OVbbcnKre6atpef3Npq18gJKCgQ46/v2rvPMqz4fweM2pBSOtmwVqr9f/3bmvU3m7ci6N/jU2xnEKRZv3GXPTNmkd16DiPFSomeYhFAAAEEChBg2q4CcLiEAAIIIFBsgYRf8fGTTz6xVq1auY+mAVm5cqVddNFFdthhh7kpPl5//fUIgl78a5op5evRo4fbDhw40M2p7jOdcsopriyNOlHSNFy+fG2/+uorn9XVE76mfb28DyetgeLzXHXVVTZp0iQ76aST7PDDD7cLLrjAHfv8O3bscHO+t2nTxo488khr166dXXnllaZAj0+aFz5vO3Tt008/dec1J7xPK1assIsvvtjat2/vymvdurU98sgjpmDKgSQt6KspyY466ijn+8EHH0QtRvPVaxFfTadyxBFHOGe55/3GhwIIt912m7uufMp/xhln2Pjx4yPl+v4uX748ck7tkMGLL77ozqk+HWuKNT13fZ5//nk75phjrFu3bpF59H0BGinSr18/15fu3bu734V///vf/rLb6lmpTP1+9enTx/VDjg8++GAkX1F+VxRIuvvuu11fNc9/7969rWfPnm5U08yZMyNlsoMAAgggkCPQuHHjyEH4zwF/koCKl2BbFgJrsnbaF9PXuqqrBdNSvTnsqHwDJ9HaN/LrFdFOl4tzHZul2/CbjzKNxFF6/6sVpunNSAgggAACCMRLwL9/IHgSL3HqQQABBCqmQMIHT/RiRS/q69Wr50YcPPPMM6ZRHb/+9a9Nc6ffeuuttmTJEvf0RowY4V7Wa/FZvbjWXO2zZs1y92uEgtKJJ57ojps0aeKO9QJe5ftPeB53BRHOOuss93GZgx/+D2h/rGCD7lVasGCBPf7449aiRQv38vybb74xvaT36eabb7ZXXnnFHfbt29eNilGA4rrrrvNZTMEeJU2VEk4ff/yxO9Q0Y0q7du1yC/BOmDDBlaPylB577DF77rnn3H5Rfig4c/vttztj9Ud2f/3rX/crQgGgs88+2yZPnuyudejQwd2jIMk777wTya8g04UXXuiCWf55KO+MGTPcosDaKvlAT9jVvyzbt2+fy+OPx40b5567TipQcf7557vrMtUIE6V58+a58wsXLrS2bdu64IqCU1dffbVNnTrV5dEPX/Ydd9zh2q/fF6V//vOftmzZMrdflN8VtUcBHfVVwTMFzvQZMGCANWvWzJXHDwQQQACB3AL6s8Ynfakh/GeBzucXxPf3sEWgNAWe+WRxpPhz+7aw+hmpkeNYdt6akP33iVjyJmOeZnXTbEDv7L9PawqvVz7P/vt4MvaFNiOAAAIIJJ+A/3sjwZPke3a0GAEEEEgmgYSfL0CjDB566CG77LLL7LPPPnMv3/WSPiUlxb0w18iBn376yb3s96MG9AJG3/zXC/JbbrnFrW3y3nvvuZEkf/7zn93z0QLoynfFFVdEXaRWma655prIs1Q9ejGeN/ngysiRI23OnDmunXohr7r18l4v7jUCQ1stOq9pxL788ks3lZQCEaeddppNnDjR5s6d60ZmKHhy55132ttvv21/+9vf3NRPCjD4YIpexiupLM0Vr6CJXtrLQyM0dKwAgEa0FCWpDKX777/fBg8e7PYffvhhFwxyB7/8UL3qiwIhb731lpuaTPdqBM4//vEPF1hRVr3wUuBK/dW+RtsoPfXUUy74lXcxYXexkB+HHnqoPfDAA240j6bEuuGGG+zDDz+0+fPnuzIbNWrkylcxf/rTn9zz01+ktOC78moki0bAhJOCXwrIqTz1Xe1TkEYjfIryuzJ27FhX7NNPP+3W0QnXwT4CCCCQrAIvvfSSaerK/FLHjh3z/TM0v3vC57WOmEZiKiCvLxzceOONLgCuP/emTZsW+X96+B72EYiXwMRgjRKfLjyuhd+Nebt56x77+scNdkynejHds2HrbhsxcZnNDhamX7F+h7VoWN0ObVXTLuzTMt/1UYKYhb351XL7z/xMWxBMpdWmSQ07vVcT69Aso9A6t+7cZ29MXGqzl222Rau2WcPa1axj8wwb3Ke5KTASS7qkXyv78OuVLuuEmevsmtPaxXIbeRBAAAEEECi2gA+eFLsgCkAAAQQQQKAAgYQPnuRtu0YbKFCgpBfiWshdL+K15ode6mtEiT5+NIqmz1KQZNGiRXmLKpVjH3ioXLmyvfHGG7Zlyxa35oVe8CtpNIPO6aOkxeg1SkLt1bRWCgAcf/zxNj6Y2uo///mPHX300aZpqBS46d+/f2QdlR9//NHdr2CJX3BXgQIFbFSePGJZ68MVEvz4/vvv3a5G4vikQI1G0oSTr/fkk0+OlK+puBQ80UggBYT0os2Xp2m5fOBE5ShYdaApPDe+38+7Zoyv99hjj3XtUV16OaekAFXepKm5fBkKuCl4oqBPUZOeq6YuU+BL03Rp1JKebUmsuVPUtpAfAQQQKCkBfXmhoKQ/k4877riCshR6TV9m0J/lSv/3f//nPv4mTYOoLyaQECgLAQU/lFo1TS/SYui1a6ZYtZTKtjoIgLz6+dKYgiffzMu0G5+dYXv25qz9s2rdDpv8wwYbMW6ZPfrHw61b61q5GLYF641c/cx0m70wK3JedU76fr0NGdA6ci7azrTgnhuC+rbvzJlqS/VpAfi3gxEzt1zY2U7vmT2qJNr9/lzrBtWtbu1Uy8zaZeuCNV1ICCCAAAIIxFuAkSfxFqc+BBBAoGIJJF3wROt6+KSXKvoo+Zf6CiREe5Gj0R/xSOEpSMKBiLVrs7+9qBEw+uRNPpii85oWS8ETjTZR8ESjXpTOPPNMt9WP1atXu/277rrL9MmbVF6swRNNeeVH1WgdEJ8UiMmbfD98QELXFfBRkEBlaOF1TVumtWmUunbt6rZF+eGn6SrKPT6vr1eGeZMCSnmT1jnxqVKlA5/FTqOUZK6ROU8++aT7qFyNXtGUYSQEEEAgWQSK8v/C8D9W9aUBn6KV4QPVPo/fKtCsEYoadRIOlGg6Ra3jpekq/Z9R/h62CJS2wMZt2dOBqp5GdYo2XZfuubBfS3tk5FybNjfT1m3eZQ1q5l+GRoDc8PR009RXSlpHpGkw6mTl2u3unAIcQ4PrY+7pYylVcv6u8s8PF+QKnBzWvo4F36OxWQuybPin+U+htT0Iulzz5LRIoEbrubRsXMPWb9rlgiBqxz2vzbajOtQ1LRJfWKof5FHwRIvH616/Dkph93EdAQQQQACB4gj4kSfhv48WpzzuRQABBBBAIJpA0gVPMjKiT0Pg1zBRJzV9lx+d4jsdDgronH+xEw5a+LzF2aamRv9HZtOmTV2xCq5oSqm8KTydlNbMUNI3cLUOyfvvv++OtQi6T82bN3e7Gh2iqb/ypoYNG+Y9le9x2GrNmjUuGJJfZl9ueBSH7vEvtvyaMb6/WpPFr02SX5k6Hw6YZGXlfIOyoHuiXZOvXr4NHTo014gX5T3QUSCx/K5obR6N0rn33nvd2iqamk1rz+h3Uc8zHGyK1m7OIYAAAokioGBweNrKWNv1m9/8xvTJL33++ef5XTJNy6i1vbZu3epGU+rPOD9dmP5/qj9b/XG+hXABgRIUWLEhZxRFkxinsApXf0YwddZjo+a5YMIbwVRc1w7M+bJGOJ/2n/lkYSRw0qpJur00tKfVCAIamcE0XkMenmzrN+5yI0Rem7DUfndia3e7Ai7vTlzu9vXj2eAePzJlbRAEGfzAt7Z1W/bImUimX3ZUnx/hctSh9e3hSw+zqpWDqEuQnh6z0F76KHu0toIzdw3u8std+W8a16lm85Zkry2oupsExyQEEEAAAQRKW4DgSWkLUz4CCCCAgARyvr6W5B61atVy656oGxqVoamkNFLDf7p3756rhz7Y4hdiz3WxFA78CBlNbaUAhG+X32q0hk96ya9F2xWQ0Boamo5MU5r4qaqUz4/o0EsljXDx5fhtUV8ydevWzVX/xRdf+GZEFoWPnAh2NLWYktYFUZBDf2HxwR0FLny9vn26Nn36dHdPtB8+qOAXc9e0X379kGj5CzvnF37XXPkKKnkPbTXV2IGkovyuKLinadf+8pe/uK3q07RrJAQQQACBwgXS09Pdmlr+zxLdoVGU+nPRB7ILL4UcCBRfYH0wWsSnehlV/W7M27Rg2q6TejV2+d+ZuMJ+GVQS9f4vgrVCfLpjcGcXONFx3fQUG3Ze9ghrHY8PpuPyafqirEjA5bjDG0YCJ7qu0SJ/OK2tz7rfVmuT+HTjWR0jgROd0xomPs3+JSDij/Pb1g2mKfNJwRMSAggggAAC8RDwwZN41EUdCCCAAAIVVyDhR55o3ZAZM2a4hWP1mB599FFr0KCB+3ar1jMJJ33rf8iQIaaFzhV00BohehGjgIXWsgiPPNCaGJoORFNoaW2RPn362Pbt290Ldy3arnVDnn322UjxfmTFrbfeapqaRMEQLSp+9913R0ZdKPOwYcPcPVqoXgEdnzQSQ9M3aTF3rYuiQMOvfvUrt7C8XghpsfJw0st+LULv55s//fTTw5ddOxUomDJliltbQ8Ghww47zAU0dP7iiy/Olb+wg8suu8yuvfZaN23Kv//9b+emxXvzJrVLoyk0ukNBGz/SQ/l0v08ylJ/WDxk0aJBbi0VrimzevNmNCtLi8kpac0Rr0lx//fU2evRo15969bIXVn311Vfdt43lFGtSG95++23TiBctan/CCSe4Nmo6t8svv9xZxVqWz1fY74ry6Znqd01t1+/RggULImun6LmQEEAAAQQQQCB5BOoEgQufsrblrAviz8WyHdK3pY35dpUbNfL59zmLz+e9d0Mw5ZVS1WBKrkNb1sx1+djO2X8n0slV67dHrq3I3BHZP75r/ci+3zmkRe5y/HltNZJFKb1GVdsYBIn0Caf6wTRlyqP1U2JJm35ZG0Z562TkuMVyL3kQQAABBBAorgDTdhVXkPsRQAABBAoSSPjgyaRJk9w6Er4Tn332mdvVC+28wROtdTJixAi3eLle2r/zzjv+NrcGh16m++TnUtfUSgoEvPXWW+6Spl/Si3+t3aHATd7k82kqJgVPlMcHVpTX36Npo8LBE13TAvfNmjVzAREFdIYPH67TLqiTN3iiQINexGvUiYI+eQMICuC8/PLL9thjj7lyNNJCH5+KGjxRcGb58uX2wAMPuMCD6tT0YgpEhZO+DTxq1CgXZFHgRnbKq6CRX/BX+TW3/euvv+4CLVpIXcEofZTyBrE09diYMWNcvRq1cdZZZ9l1113ngl4K4CiwFU4qOzy3vq75vzBpVM+HH37ops/SWjEaIeOTpj3T3PpK0b7B7M/5svx9hf2u7N27177++mufPbLVmjEK5uQd9RTJwA4CCCCAAAIIJKRAs3o5U0+t3hhbECFvRzoEC81rGq4lq7bav4KF408KRojkTTt3/xyZQqtWlBEuwfInpjVJtJ6IX8BeZYSDJ3Vq7B+wqJMefbRMuD5N6/WHx6bmbVLk2E/tFTmRz87q0ELxTWrnuOWTndMIIIAAAgiUiIAfeZL33+8lUjiFIIAAAggg8IvAQcEfONmrU5YzEi2Cvm7dOvdSXUGI/NYiUbc1zdeePXvclFOaHsS/RC9NEgVctIC51htR+/JbSDfWNijIoimvFNxQeQeaFAhQ4EijexSgUDtlF619uqaP8hb0Fxb9iqlMtU9Tj0Uz1tozWvdEASe1YefOnVa1alX3OdDnsW/fPlevfhfq1KnjRoYcqIu/L7/fFbVZz0Dt1jOtWbNmriCRv58tAggggAACCCS+gP523Pv6sa6hHYLRIK/dkP3li4Ja/sengi+yBAvE1w6msRpzV/YXP979zyr739dnu9vOPK65jf4ie52SD+7+ldXPSA2mP82pRyNBxt573H5VHHPDODdFl4IoE/5+vLseXpvk4f/vcPtVaISKMii4cvZd2V/s0LReD/5PV3effvjytF/Q4u6pwdRjn9/fV9kKTAPv/NKNVNHImS8fylmfr8CbuIgAAggggEAxBfTlSH1BUzNdaP1REgIIIIAAAqUhkPAjTw6003qBrVEesSSNNol30uiL8AiM4tZfnIBJuG4FScIeBbUx1j4osKIAS0FJa4X4pDZoCqziJgV/GjVqVNxict0ftglfUJtLuq5w+ewjgAACCCCAQPwEgr+6uGmtNDpj4fIttj0Y+VE9CF4UNZ3Wo7E9+OaPbnTJB1+v3O921VMzGCWiUSWqa8uOvZaRlvPX81XBqI59vyyY0iC0EHuzemmRspas275f8GRfAV+Nqlc71dZmBl9SCYIdnwfBGL9YfKTAIuxsCBa199OAqVwSAggggAACCCCAAAIIIFCeBCqVp87QFwQQQAABBBBAAAEESkLgsHbZa9cpeDF68v6Bj1jqUGBi4DFNXdbwNFjhcd9tgum9fHpl/BK/67bPfbo4ctyhWc4XTdo0rBE5P+rL5W4ES+REsDP6mxXhw1z7h7ap7Y7Vnr++kT0qJleGIhy8MXFZJHePjnUi++wggAACCCBQ2gJ+EpWCZsEo7TZQPgIIIIBA+RfI+Wpb+e8rPUQAAQQQQAABBBBAICaBKwa0s69nrnd5/zV2iZ13TPMDGqXx22DheD9dV7SKrzqtnf1h3pTsesYstswte9zC8f+Zv9HGTV0dueUPA9pE9rWwfJMGabZq3Q5bsXa7XfXMNBt8XEvbvXefTVmQZe9OzJ4eLHJDaOeGQe1twrQ1bkTL2Cmrrd+s9dazU107tks9axKMbsncstsWrNlmlxzfKtcomFARblfrp4yakFPPH07OaV/evBwjgAACCCBQ0gIET0palPIQQAABBKIJEDyJpsI5BBBAAAEEEEAAgQot0LFZunVuU8vmLNpkmVm77PJ/TrWnr+hh1VKKNnC7ZTDFVsdWNW3eks1RPbu1rmUnHNE4Eij54OsVpk84nRWsl9KmYfXwKbvpnIPt+qenu3NTf8w0fXzSuitZm3f7w1zbBjVT7ebBnSNrsWzfude+mL7WfcIZjz24nnVvmz1KJXxe+5pe7LLHp5ruVTrmsPou8OIO+IEAAggggEAcBAiexAGZKhBAAAEErGj/+gMMAQQQQAABBBBAAIEKInD9oA6RniqIcsED39gr45farKWbI2uR+AyVgvVLlCr5nexD93NIv5aho/3z3DfkELv27I6mReHDqXq1KnbLhZ1t2NkHh0+7/WM61bOnrz3CLVAfvti4fpo9dWWPAheDH9SriY264xjrfnDdfPOtztoZLtb2BAupzFi8yZ7/bLGd//dvbMmqre66Fp2/+rT2ufJygAACCCCAAAIIIIAAAgiUB4GDgmh9AUtKlocu0gcEEEAAAQQQQAABBA5MYE6wYPyV//wuMsrCl3LfZV3thK4N/WGJbTODRdhXBwvFa1H4WtWrxlTu5mAkyIoNO6xVg+qRhe3Xb9llqVUqW40gABMlnpOrXC38vipYRF7/LEgP8qvulGBB+XD6v0kr7ME3fwyfcovdP3vNEdamUc4aLLkycIAAAggggEApCfTp08eWLl1q55xzjj3yyCOlVAvFIoAAAghUdAGm7arovwH0HwEEEEAAAQQQQCBfgc7NM2zkbb3tzhFzbNaCTZEgysog2FAaqW56iulTlFQzrYrVDNoZTvUzUsOHBe7XC+rTp6C0MnNH5HJ6jarWo0Mdu/2Czqa6SQgggAACCMRbwH8PmAXj4y1PfQgggEDFEuBfOxXredNbBBBAAAEEEEAAgSIKKBDx/y4/3N2lER0/Lt9qLfOsQVLEIpMu+6+PaGI92tYJFrPPsNo1Cg60JF3naDACCCCAQNIJEDxJukdGgxFAAIGkFCB4kpSPjUYjgAACCCCAAAIIlIWAAim/6hz7qI6yaGNp1Nm2cQ3Th4QAAggggAACCCCAAAIIVBSB3JMZV5Re08+IQKtWraxTp042bNiwyDl2EEAAAQQQQAABBBBAAAEEEEAAgUQVYORJoj4Z2oUAAgiULwGCJ+XreRa5N5ofdMeOHTZmzJgi38sNCCCAAAIIIIAAAggggAACCCCAQLwFfPAk3vVSHwIIIIBAxRIgeFKxnneu3m7evDlynJmZaTNnzowcs4MAAggggAACCCCAAAIIIIAAAggksgALxify06FtCCCAQPILEDxJ/md4wD147733LPxtjXHjxh1wWdyIAAIIIIAAAggggAACCCCAAAIIIIAAAggggEB5ESB4Ul6e5AH04/3338911/jx43Mdc4AAAggggAACCCCAAAIIIIAAAggkmoD/IigjTxLtydAeBBBAoHwJEDwpX88z5t589dVXNmnSpFz5p02bZvqQEEAAAQQQQAABBBBAAAEEEEAAgUQVIHiSqE+GdiGAAALlS4DgSfl6njH3RlN2KaWkpLhtmzZt3HbChAluyw8EEEAAAQQQQAABBBBAAAEEEEAgEQUIniTiU6FNCCCAQPkTIHhS/p5poT1asWKF+Sm7UlNTXf5OnTq5LVN3FcpHBgQQQAABBBBAAAEEEEAAAQQQQAABBBBAAIFyLkDwpJw/4Gjd+/jjj23r1q3WqlUrq1atmstyyCGHuH2m7oomxjkEEEAAAQQQQAABBBBAAAEEEEgUAUaeJMqToB0IIIBA+RYgeFK+n2/U3n366afu/CmnnGKVK1d2+/Xq1bP+/fu7/Y8++ijqfZxEAAEEEEAAAQQQQAABBBBAAAEEylqA4ElZPwHqRwABBCqGAMGTivGcI72cOXNmZKH4gQMHWqVK2b8CCqIMGDDA5fvggw9s+/btkXvYQQABBBBAAAEEEEAAAQQQQAABBBJFgOBJojwJ2oEAAgiUbwGCJ+X7+e7XOz/qpF+/ftatW7fIyBMFUU477TRr27atLV++3BRAISGAAAIIIIAAAggggAACCCCAAAIIIIAAAgggUBEFCJ5UsKf+2WefuR5r1IlSlSpV3FYjTxRA8ecJnjgWfiCAAAIIIIAAAggggAACCCCAQIIJMPIkwR4IzUEAAQTKqQDBk3L6YKN1a+LEiTZ79mxr3rx5JEjip+3yQZRTTz3V3fr555/bjBkzohXDOQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEyrUAwZNy/Xhzd27s2LHuhEaXVK9e3e37BeN9EOWQQw6xE0880V1TAIWEAAIIIIAAAggggAACCCCAAAIIIIAAAggggEBFE8ies6mi9bqC9veLL75wPdfaJj754Inf6ryuK9Ayfvx4Gzp0qM/KFgEEEEAAAQQQQCCBBMZMX2Obt++1Vg3SbHXWLtuwZZelV6tqVSofZGkpleyQlrWsRb20BGoxTUEAAQQQQKBkBJi2q2QcKQUBBBBAoGABgicF+5Sbq1OnTrUFCxZYnz597PDDD4/0y4848VtdGDBggP3973+3adOmuU/37t0j+dlBAAEEEEAAAQQQKFuBkV+vsHeCz4LlWwptSIO61axzy5rWs0MdO71nE6ueWrnQe8iAAAIIIIBAogsQPEn0J0T7EEAAgfIhQPCkfDzHQnsxbtw4l0eBkXDyI078VtcyMjLs5JNPttdff92NPiF4EhZjHwEEEEAAAQQQKBuB9/6zyv7vyxU2d8mmmBuwLnOn6fPF9LX22rglduqRTezXRzS2lvWzp3CNuSAyIoAAAgggkEACBE8S6GHQFAQQQKAcCxA8KccPN9w1TcFVu3Zt8wvC+2s+aOK3/rwPnnzzzTf+FFsEEEAAAQQQQACBMhD4dMZae+vLZTZzflbU2mvVSrPaNdOsbrCtE3zqBZ+FyzdaakoVO6JzE5s6Z5VNn73S1m7Yaa98tMhGjFtqJ/dsbENPb28Z1fjnQFRUTiKAAAIIIIAAAggggECFF+BfSxXgV2D16tU2a9Ysu+CCC6x+/fq5euyn6/Jbf7Ffv37Wt29fmzBhgmVmZlrdunX9JbYIIIAAAggggAACcRAY/8N6GxVMzzU52PpUv14Na9m0jrVqWssa1qlhdWtHX9Okfcucv7v17dnK9Jk5b419H3yWBoGV979aYfNXbLW/nN/JOjZN98WzRQABBBBAICkEGHmSFI+JRiKAAAJJL0DwJOkfYeEdWLx4scuUd9SJTvoRJ37rMv7yo0ePHi54Mm/ePOvdu3f4EvsIIIAAAggggAACpSjwzCeL7MUPF7oaGjbIsM7tGljHVvWsfp0Dn27rsI6NTJ/v56+xSdOW2dzFm+yqp6bZbb/pbMcfkvsLNqXYNYpGAAEEEECg2AIET4pNSAEIIIAAAjEIEDyJASnZsyjwsWTJkqjd8EETvw1nGjp0qAuaEDgJq7CPAAIIIIAAAgiUnsDS9TvsrhFz7PufNlqVKpVsYL9O1iUInJRk6tqhkQvEfPndMps8fand/NwMu3hAa7vq1HYlWQ1lIYAAAgggUGoCBE9KjZaCEUAAAQRCApVC++xWQIHU1FTX64MOOihq7wmcRGXhJAIIIIAAAgggUOICm7bvsdteneUCJ9XTUuzsAYeUeODEN1rroZzYu42dcXIXd+rVMYvtiY8W+MtsEUAAAQQQQAABBBBAAIEKL0DwpIL/ClStWrWCC9B9BBBAAAEEEEAgMQRuHz7b5i3dbFoA/txTDrV2LXLWLSmtFh4SjGq55Y99XfEKoDz5MQGU0rKmXAQQQACBkhNg5EnJWVISAggggED+AgRP8repEFcInlSIx0wnEUAAAQQQQCDBBV4at9i+nZW9MPyAX3WwZo0y4trii8/q4ep75WMCKHGFpzIEEEAAgQMS8MGTA7qZmxBAAAEEEIhRgOBJjFDlNVtKSkp57Rr9QgABBBBAAAEEkkJg6frt9sbnS11bDz+0WTDipE7c261gzYm/au/qVQBlyoKNcW8DFSKAAAIIIFBUgfymIC9qOeRHAAEEEEAgmgDBk2gqFegcwZMK9LDpKgIIIIAAAggkpMArQeBk05Y9lp6easd2a1FmbTwyCNx06djI1f/6hOxgTpk1hooRQAABBBBAAAEEEEAAgTIWIHhSxg+grKsneFLWT4D6EUAAAQQQQKAiC3z94wZ7/6sVjuCoIHBSMyO1TDl6Hdrc1f/1zPX28bTVZdoWKkcAAQQQQCA/AT9tFyNP8hPiPAIIIIBASQgQPCkJxSQuw6954v/ikcRdoekIIIAAAggggEDSCXwwJTtAUb16inXv1LjM29+0Ybp17dzEtWP4+GVl3h4agAACCCCAQDQB/w6D4Ek0Hc4hgAACCJSUAMGTkpJM0nJ88GTPnj1J2gOajQACCCCAAAIIJKfAnr0/2zdzNrjGd2hd36pWrZwQHenRualrx9wlm+2HZZsTok00AgEEEEAAgbAAwZOwBvsIIIAAAqUlQPCktGSTpFw/bdfevXuTpMU0EwEEEEAAAQQQKB8C387faFu3ZX+B5bCOZT/qxKuGR5/MXrbFn2aLAAIIIIAAAggggAACCFQoAYInFepx79/ZKlWquJMET/a34QwCCCCAAAIIIFCaAhN+WOeKb1A/3Zo3zijNqopcdssmtdw9MxdvKvK93IAAAggggEBpCzDypLSFKR8BBBBAQAIET/g9cAIET/hFQAABBBBAAAEE4iswfnp28KRT2wbxrTiG2po3rOlyfTc/M4bcZEEAAQQQQCC+AgRP4utNbQgggEBFFSB4UlGffJ5+s+ZJHhAOEUAAAQQQQACBUhTYtH2Pbd6629WQUSO1FGs6sKLr1k6zjIxqtn7jrgMrgLsQQAABBBAoRQGCJ6WIS9EIIIAAAhEBgicRioq9w8iTiv386T0CCCCAAAIIxFdg/ebswIlqzaiREt/KY6ytZkZ2UGdF5o4Y7yAbAggggAACCCCAAAIIIFB+BAielJ9nWayeEDwpFh83I4AAAggggAACRRJYtzlnREfNBBx5Eu7M+k05gZ7wefYRQAABBBAoKwFGnpSVPPUigAACFUuA4EnFet759pbgSb40XEAAAQQQQAABBEpcYH04eJKeeNN2hTucllo5fMg+AggggAACCCCAAAIIIFAhBAieVIjHXHgnCZ4UbkQOBBBAAAEEEECgpATWb8kZzVG50kElVWyplFOjGsGTUoGlUAQQQACBYgscdFBi/xla7A5SAAIIIIBAmQoQPClT/sSpnAXjE+dZ0BIEEEAAAQQQKP8CqVVzAhI7d+1LyA6vXbfVtatGapWEbB+NQgABBBCouAJ+2q6KK0DPEUAAAQTiIUDwJB7KSVAHI0+S4CHRRAQQQAABBBAoNwKtG1SP9GXn7r2R/UTZWRUETvbsyQ7q1KhG8CRRngvtQAABBBDIFvDBE0ae8BuBAAIIIFCaAgRPSlM3icpm5EkSPSyaigACCCCAAAJJL9C8flqkD7sSMHiyYu1m1776dVKtamWmRIk8LHYQQAABBBJCgOBJQjwGGoEAAgiUewGCJ+X+EcfWQUaexOZELgQQQAABBBBAoCQEWtRLs2q/LMSeuXlHSRRZomWs2bDNlde1Te0SLZfCEEAAAQQQKEmB5s2bl2RxlIUAAggggEAugYOCaP1/c53hoEIJtGrVKtJfDXf1Q17zbn2maOfznivoWL9u+V1XHfldy3s+v/b4fLGWVVB7Yi0rljJiKauwPvky/Da/PhalPQWVVdT25FfWgbQnWlkH2p68ZRWnPeGyitseX1ZJtEdlqRwlX+6BbhOtPd65uH0L96s4Zfn2eN8DLSvcnuKUlajt8e1iiwACBQvcN2aHrd74s7VqUdcuHNi14MxxvvrCqKmmNU8G9UixEzpWjXPtVIcAAggggEDBAhdccIH16dPHrr766kjG3r17R/bZQQABBBBAoCQECJ6UhGISl3HjjTfawoULberUqUncC5qOAAIIIIAAAggkn0CNrhdYRvsBruHXDDna0mukJEQnZsxdbR9+Pte1Zf0X99neDfMTol00AgEEEEAAgYIE3nzzTSOAUpAQ1xBAAAEEiipA8KSoYuUw/wcffGDz5s0rhz2jSwgggAACCCCQKAJ+hJy2ft+3LXzOX8vvnO7xecL7+eX3ef027z3+2F+PttU5jRILXwvvF1RGQfdutjo2r2o/3W4nHNvejurazO2X9Y9X35tuK1Zuskr7tlnTNSPsoJ93uyaF+xzeD7dX5/NeK+ycv7+wfHnL1X15z8VShn+Wsd7r61F+f2/4nN/322jl6ppStGsFncu+K/u+aPn8dbYIIIBARRcgcFLRfwPoPwIIIFA6AgRPSseVUhFAAAEEEEAAAQQQKFTgD09+ZzPmbUyYqbvmLFxnoz+Z7dp9xaD29j/9cqZ4LbQzZIi7QLSAij/nG+OPtQ3v63q0c/583m1h9x5oYEnlHui9/r7C2ub74vPpWEnH/ly0bbRz2XfmDoRFy5f3nK8vv23e/Dr258J1+nPhbXjfl69z3sef89v88vvr/r7C8vn8fhutzqKU4cvx27z3+vN+66/rWEnH/lx4G97Pm8/dWMC9efP7svz5vFt/PbwN7xdk68sK5w+f8/eGz/l9v412r78v2rWCzqlMJeUpKF+0a9l3ltx/J/nVEW6bgickBBBAAAEESlqgSkkXSHkIIIAAAggggAACCCAQm8CJ3Rq64MmSZZk2edYKO/LQsh19MmPuGtfwDi1r2pC+LWPrBLnKTEAvRZX8tswaQsUIIIAAAggggAACCJRDgUrlsE90CQEEEEAAAQQQQACBpBA4OQieNKpXzbV10tQltiFrR5m1W8GbRUs2uPoH921hlStlv5gvswZRMQIIIIAAAggggAACCCBQhgIET8oQn6oRQAABBBBAAAEEKrZA3fQUu/r09g5h+449NvG7JWUCoqDNN98tdXX/6vAGNvCIxmXSDipFAAEEEEAAAQQQQAABBBJFgOBJojwJ2oEAAggggAACCCBQIQX6H97ILuqfvbbInHlrbOw3i+LuoKDNtu27rVuHOvbw/xwW9/qpEAEEEEAAAQQQQAABBBBINAGCJ4n2RGgPAggggAACCCCAQIUTuOa09ta3e0PX78nTl9qHE+fHzeCzIFijoE275hn27FU94lYvFSGAAAIIIIAAAggggAACiSxA8CSRnw5tQwABBBBAAAEEEKgwAg9c0tU0ZZbSjB9W2uhxP5Z639/7fK79JwjWaN2Vu37bpdTrowIEEEAAAQQQQAABBBBAIFkEDvpvkJKlsbQTAQQQQAABBBBAAIHyLvDC2MX27L8XuG42bpRhvbo2t0PbZ49KKam+Z23eae9+/qOtXLXJ+gQBm4eYqqukaCkHAQQQQAABBBBAAAEEyokAwZNy8iDpBgIIIIAAAggggED5ERg1aYU98GbOyJN2berbUUEQpVXTWsXu5NhvF9nkadmLw595XHO75eyDi10mBSCAAAIIIIAAAggggAAC5U2A4El5e6L0BwEEEEAAAQQQQKBcCHwwdZU9Pvony9qyO9KfLh0b2cGt61untvUj52LZWbFmi/24eL3NX7TeNmZtt1oZKXb5qW3tvGOaxXI7eRBAAAEEEEAAAQQQQACBCidA8KTCPXI6jAACCCCAAAIIIJAsAqs27rQRXy630cFn5659kWanpVW1jm0bWJe2Da1ORqrVqlktck07m7fssrUbt9nazG22cFmmLVuR5a7XDIImp/ZqbL/u2cQ6Nk3PdQ8HCCCAAAIIIIAAAggggAACOQIET3Is2EMAAQQQQAABBBBAICEFFqzaZm9+vdzenbg83/ZlZFSzmkEgJXPjdtuxY0+ufE0aVLf+RzS0c49uZg1r5Q605MrIAQIIIIAAAggggAACCCCAgBMgeMIvAgIIIIAAAggggAACSSKwPhhRMmfZFpu7MpiGa/kWmx98Vq/fuV/r06pVscM71LYj2tWxXu3rWKfmGfvl4QQCCCCAAAIIIIAAAggggED+AgRP8rfhCgIIIIAAAggggAACCCCAAAIIIIAAAggggAACCFRAgUoVsM90GQEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBDIV4DgSb40XEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAIGKKEDwpCI+dfqMAAIIIIAAAggggAACCCCAAAIIIIAAAggggAAC+QoQPMmXhgsIIIAAAggggAACCCCAAAIIIIAAAggggAACCCBQEQUInlTEp06fEUAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAIF8Bgif50nABAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEKqIAwZOK+NTpMwIIIIAAAggggAACCCCAAAIIIIAAAggggAACCOQrQPAkXxouIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAQEUUIHhSEZ86fUYAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAIF8BQie5EvDBQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEKiIAgRPKuJTp88IIIAAAggggAACCCCAAAIIIIAAAggggAACCCCQrwDBk3xpuIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIVUYDgSUV86vQZAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEE8hUgeJIvDRcQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEECgIgoQPKmIT50+I4AAAggggAACCCCAAAIIIIAAAggggAACCCCAQL4CBE/ypeECAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIVEQBgicV8anTZwQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEMhXgOBJvjRcQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAgYooQPCkIj51+owAAggggAACCCCAAAIIIIAAAggggAACCCCAAAL5ChA8yZeGCwgggAACCCCAAAIIlH+B7du327XXXmvDhg2zvXv3lv8O00MEEEAAAQQQQAABBBBAIAaBKjHkIQsCCCCAAAIIIIAAAggEAgsWLLATTjghl0W9evWsW7dudtVVV1nPnj1zXUuGgylTpti7777rmjpkyBA75JBD9mv23//+d8vKyrI777zTUlJS9rvOCQQQQAABBBBAAAEEEECgvAkc9N8glbdO0R8EEEAAAQQQQAABBEpDYN68eXbyySdbjRo1rH379q6KGTNmRKoaPXq0de/ePXKcDDs7duywv/zlL1atWjW76667rHLlyvs1u3fv3rZq1SqbPXu26/t+GTiBAAIIIIAAAggggAACCJQzAabtKmcPlO4ggAACCCCAAAIIlL7AgAED7L333nOfWbNm2Xnnnecqfe6556JWvmHDBtu2bVvUa/E4uXHjxnyrSUtLs4cfftjuvffeqIGTfG/M58KePXtszZo1xne08gHiNAIIIIAAAggggAACCCSFAMGTpHhMNBIBBBBAAAEEEEAgUQUyMjLskksucc3TyBSfFDx47bXXrEuXLtajRw+3HThwoP3www8+S8xbldGvXz+X//7777dWrVrZxx9/7NYo0b5Ghijdc8897prOaRqxSZMm2UknnWSHH364XXDBBe7YZQx+XHTRRZG8yq9PeM0TBXz8eY06UVI7/DltNWrFpxUrVtjFF1/sRuQceeSR1rp1a3vkkUdMwRQSAggggAACCCCAAAIIIJBsAqx5kmxPjPYigAACCCCAAAIIJJyARlootW3bNtK2ESNG2G233eaOtRbK2rVrzY9S+eabb6xmzZqRvIXtaF2VhQsXumxad0Vp8eLFtn79erffokULt9V6JRoFM3LkSLc+y+OPP266pvtVpwIq3333nct71FFHWf369d3+O++847bh0SKaxsuPqFF5SoMGDcq15kmVKtn/nNi1a5edc845bmovTWmm/k6YMMEee+wxNx3YlVde6e7nBwIIIIAAAggggAACCCCQLAIET5LlSdFOBBBAAAEEEEAAgYQR0KiMadOm2c8//2zff/+9vfDCC65tfgSIghAPPvigO/fmm2+6kSH79u2zW265xXSsKb808mP48OH24osv5tuv6tWru7wa5bF06VI39ddPP/3k8it4sm7dOrffrl07tz3rrLNMHwU75syZY5dddpndcccdproV2FG7N23aZLVq1bJrrrkmUu8nn3yy37RiCoI89NBDLs+XX37pAiP33Xdf1DVPtOC8Rqf07dvXnn/+eRdgUft0/M9//tMInkSo2UEAAQQQQAABBBBAAIEkESB4kiQPimYigAACCCCAAAIIJI6ARlXoE06nnnqqmxpL5zIzM12gokmTJqbPkiVLXFZNn6XgyaJFi9yxpsnaunWr24/2Q0EPpaZNm7qtgiUagXLuuee6MnzwRFNkRUuDBw92p7UI/BtvvGFbtmyx1NTUaFmLde7HH3909ytY4qf4Ouigg1zARu2VR926dYtVBzcjgAACCCCAAAIIIIAAAvEUIHgST23qQgABBBBAAAEEECgXAh06dLAzzjjD9eXpp592ozY0qkSjNZR8UEOBhOOOO86dC//Q6A8lrRGiT2GpWbNmLotfL+WEE06w22+/PVKPRqZESy1btoycPuaYYyL7Jb2zevVqV+Rdd91l+uRNCtoQPMmrwjECCCCAAAIIIIAAAggksgDBk0R+OrQNAQQQQAABBBBAICEFunbtatdee61rm0aHPProo/bEE0/YAw884M5ptIlPmr4rJSXFH7ptfsGOXJlCB748rVeiAM1hhx3mRrb4dVDCQZLQbSU+ykSjZHyAKFxP8+bN3eGAAQPstNNOC19y+w0bNtzvHCcQQAABBBBAAAEEEEAAgUQWIHiSyE+HtiGAAAIIIIAAAggkvIBGjih4oum4tLaHptDSmiIKaGidEo3KuPrqq61SpUoH3JfGjRu7e7XouxaF98GUSZMmufM+eHHAFRRyoxad1yiasWPH2oUXXrhfbgWTlLQ2yj333GMES/Yj4gQCCCCAAAIIIIAAAggkmQDBkyR7YDQXAQQQQAABBBBAILEE6tWrZ5dffrk999xzbnF0v8j6vffea0OGDLGHH37YNLVX//79LT093QVUnnrqqagjOPLrWaNGjdylWbNmuYXm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" - } - }, - "cell_type": "markdown", - "id": "46397e48-aba2-4bd3-bb31-d840f2fcbda4", - "metadata": { - "editable": true, - "slideshow": { - "slide_type": "" - }, - "tags": [] - }, - "source": [ - "# Agentic RAG\n", - "\n", - "In this tutorial we will build a [retrieval agent](https://python.langchain.com/docs/tutorials/qa_chat_history). Retrieval agents are useful when you want an LLM to make a decision about whether to retrieve context from a vectorstore or respond to the user directly.\n", - "\n", - "By the end of the tutorial we will have done the following:\n", - "\n", - "1. Fetch and preprocess documents that will be used for retrieval.\n", - "2. Index those documents for semantic search and create a retriever tool for the agent.\n", - "3. Build an agentic RAG system that can decide when to use the retriever tool.\n", - "\n", - "![Screenshot 2024-02-14 at 3.43.58 PM.png](attachment:7ad1a116-28d7-473f-8cff-5f2efd0bf118.png)\n", - "\n", - "## Setup\n", - "\n", - "Let's download the required packages and set our API keys:" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "969fb438", - "metadata": {}, - "outputs": [], - "source": [ - "%%capture --no-stderr\n", - "%pip install -U --quiet langgraph \"langchain[openai]\" langchain-community langchain-text-splitters" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e4958a8c", - "metadata": {}, - "outputs": [], - "source": [ - "import getpass\n", - "import os\n", - "\n", - "\n", - "def _set_env(key: str):\n", - " if key not in os.environ:\n", - " os.environ[key] = getpass.getpass(f\"{key}:\")\n", - "\n", - "\n", - "_set_env(\"OPENAI_API_KEY\")" - ] - }, - { - "cell_type": "markdown", - "id": "3d07e8d4", - "metadata": {}, - "source": [ - "" - ] - }, - { - "cell_type": "markdown", - "id": "c74e4532", - "metadata": {}, - "source": [ - "## 1. Preprocess documents\n", - "\n", - "1\\. Fetch documents to use in our RAG system. We will use three of the most recent pages from [Lilian Weng's excellent blog](https://lilianweng.github.io/). We'll start by fetching the content of the pages using `WebBaseLoader` utility:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "53ff068e-053f-41da-a8b5-b23efc2442fd", - "metadata": { - "scrolled": true - }, - "outputs": [], - "source": [ - "from langchain_community.document_loaders import WebBaseLoader\n", - "\n", - "urls = [\n", - " \"https://lilianweng.github.io/posts/2024-11-28-reward-hacking/\",\n", - " \"https://lilianweng.github.io/posts/2024-07-07-hallucination/\",\n", - " \"https://lilianweng.github.io/posts/2024-04-12-diffusion-video/\",\n", - "]\n", - "\n", - "docs = [WebBaseLoader(url).load() for url in urls]" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "0e027561-c144-469c-913d-c3d8295500ed", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "\"Reward Hacking in Reinforcement Learning | Lil'Log\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\nLil'Log\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n|\\n\\n\\n\\n\\n\\n\\nPosts\\n\\n\\n\\n\\nArchive\\n\\n\\n\\n\\nSearch\\n\\n\\n\\n\\nTags\\n\\n\\n\\n\\nFAQ\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n Reward Hacking in Reinforcement Learning\\n \\nDate: November 28, 2024 | Estimated Reading Time: 37 min | Author: Lilian Weng\\n\\n\\n \\n\\n\\nTable of Contents\\n\\n\\n\\nBackground\\n\\nReward Function in RL\\n\\nSpurious Correlation\\n\\n\\nLet’s Define Reward Hacking\\n\\nList of Examples\\n\\nReward hacking examples in RL tasks\\n\\nReward hacking examples in LLM tasks\\n\\nReward hacking examples in real life\\n\\n\\nWhy does Reward Hacking Exist?\\n\\n\\nHacking RL Environment\\n\\nHacking RLHF of LLMs\\n\\nHacking the Training Process\\n\\nHacking the Evaluator\\n\\nIn-Context Reward Hacking\\n\\n\\nGeneralization of Hacking Skills\\n\\nPeek into Mitigations\\n\\nRL Algorithm Improvement\\n\\nDetecting Reward Hacking\\n\\nData Analysis of RLHF\\n\\n\\nCitation\\n\\nReferences\\n\\n\\n\\n\\n\\nReward hacking occurs when a reinforcement learning (RL) agent exploits flaws or ambiguities in the reward function to ac\"" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "docs[0][0].page_content.strip()[:1000]" - ] - }, - { - "cell_type": "markdown", - "id": "ca258767-ce4f-4eaa-8ae5-25e9361675e1", - "metadata": {}, - "source": [ - "2\\. Split the fetched documents into smaller chunks for indexing into our vectorstore:" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "24d2cefd-d0f0-44ae-aa4b-0436a675dc56", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain_text_splitters import RecursiveCharacterTextSplitter\n", - "\n", - "docs_list = [item for sublist in docs for item in sublist]\n", - "\n", - "text_splitter = RecursiveCharacterTextSplitter.from_tiktoken_encoder(\n", - " chunk_size=100, chunk_overlap=50\n", - ")\n", - "doc_splits = text_splitter.split_documents(docs_list)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "a82479d9-e7d3-481f-893d-0a95c404f0bf", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "\"Reward Hacking in Reinforcement Learning | Lil'Log\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\nLil'Log\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n|\\n\\n\\n\\n\\n\\n\\nPosts\\n\\n\\n\\n\\nArchive\\n\\n\\n\\n\\nSearch\\n\\n\\n\\n\\nTags\\n\\n\\n\\n\\nFAQ\"" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "doc_splits[0].page_content.strip()" - ] - }, - { - "cell_type": "markdown", - "id": "c5e7b434-c4c3-4a42-aa4e-2a0bb1e7a2a0", - "metadata": {}, - "source": [ - "## 2. Create a retriever tool" - ] - }, - { - "cell_type": "markdown", - "id": "732d6512-51af-426d-995f-98ae72eff4af", - "metadata": {}, - "source": [ - "Now that we have our split documents, we can index them into a vector store that we'll use for semantic search. \n", - "\n", - "1\\. Use an in-memory vector store and OpenAI embeddings:" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "e50c9efe-4abe-42fa-b35a-05eeeede9ec6", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain_core.vectorstores import InMemoryVectorStore\n", - "from langchain_openai import OpenAIEmbeddings\n", - "\n", - "vectorstore = InMemoryVectorStore.from_documents(\n", - " documents=doc_splits, embedding=OpenAIEmbeddings()\n", - ")\n", - "retriever = vectorstore.as_retriever()" - ] - }, - { - "cell_type": "markdown", - "id": "225d2277-45b2-4ae8-a7d6-62b07fb4a002", - "metadata": {}, - "source": [ - "2\\. Create a retriever tool using LangChain's prebuilt `create_retriever_tool`:" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "0b97bdd8-d7e3-444d-ac96-5ef4725f9048", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.tools.retriever import create_retriever_tool\n", - "\n", - "retriever_tool = create_retriever_tool(\n", - " retriever,\n", - " \"retrieve_blog_posts\",\n", - " \"Search and return information about Lilian Weng blog posts.\",\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "9cfdc027-5ea8-42ba-b0f4-0590505d76ff", - "metadata": {}, - "source": [ - "3\\. Test the tool:" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "58c17a90-9a85-46c9-96a9-1e7b224330c4", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'(Note: Some work defines reward tampering as a distinct category of misalignment behavior from reward hacking. But I consider reward hacking as a broader concept here.)\\nAt a high level, reward hacking can be categorized into two types: environment or goal misspecification, and reward tampering.\\n\\nWhy does Reward Hacking Exist?#\\n\\nPan et al. (2022) investigated reward hacking as a function of agent capabilities, including (1) model size, (2) action space resolution, (3) observation space noise, and (4) training time. They also proposed a taxonomy of three types of misspecified proxy rewards:\\n\\nLet’s Define Reward Hacking#\\nReward shaping in RL is challenging. Reward hacking occurs when an RL agent exploits flaws or ambiguities in the reward function to obtain high rewards without genuinely learning the intended behaviors or completing the task as designed. In recent years, several related concepts have been proposed, all referring to some form of reward hacking:'" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "retriever_tool.invoke({\"query\": \"types of reward hacking\"})" - ] - }, - { - "cell_type": "markdown", - "id": "7c4e9e70-3de1-4ab4-ab42-c298cef00eb6", - "metadata": {}, - "source": [ - "## 3. Generate query" - ] - }, - { - "cell_type": "markdown", - "id": "2ba89a91-3dc5-4663-a6a5-43ccb2575849", - "metadata": {}, - "source": [ - "Now we will start building components ([nodes](../../../concepts/low_level#nodes) and [edges](../../../concepts/low_level#edges)) for our agentic RAG graph. Note that the components will operate on the [`MessagesState`](../../../concepts/low_level#messagesstate) — graph state that contains a `messages` key with a list of [chat messages](https://python.langchain.com/docs/concepts/messages/).\n", - "\n", - "1\\. Build a `generate_query_or_respond` node. It will call an LLM to generate a response based on the current graph state (list of messages). Given the input messages, it will decide to retrieve using the retriever tool, or respond directly to the user. Note that we're giving the chat model access to the `retriever_tool` we created earlier via `.bind_tools`:" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "32f21d6f-9d0e-44e1-8edd-1fd903164d6d", - "metadata": {}, - "outputs": [], - "source": [ - "from langgraph.graph import MessagesState\n", - "from langchain.chat_models import init_chat_model\n", - "\n", - "response_model = init_chat_model(\"openai:gpt-4.1\", temperature=0)\n", - "\n", - "\n", - "def generate_query_or_respond(state: MessagesState):\n", - " \"\"\"Call the model to generate a response based on the current state. Given\n", - " the question, it will decide to retrieve using the retriever tool, or simply respond to the user.\n", - " \"\"\"\n", - " response = (\n", - " response_model\n", - " # highlight-next-line\n", - " .bind_tools([retriever_tool]).invoke(state[\"messages\"])\n", - " )\n", - " return {\"messages\": [response]}" - ] - }, - { - "cell_type": "markdown", - "id": "552e0f6c-5af5-4c13-91a6-437f320a4ed6", - "metadata": {}, - "source": [ - "2\\. Try it on a random input:" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "5cdc7e76-8680-42e6-9cdb-44aa4104f0f7", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "\n", - "Hello! How can I help you today?\n" - ] - } - ], - "source": [ - "input = {\"messages\": [{\"role\": \"user\", \"content\": \"hello!\"}]}\n", - "generate_query_or_respond(input)[\"messages\"][-1].pretty_print()" - ] - }, - { - "cell_type": "markdown", - "id": "df45f7c8-df6c-4687-9f25-0357e29532cb", - "metadata": {}, - "source": [ - "3\\. Ask a question that requires semantic search:" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "845e1bca-3097-423f-a9c8-967fe1216375", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "Tool Calls:\n", - " retrieve_blog_posts (call_tYQxgfIlnQUDMdtAhdbXNwIM)\n", - " Call ID: call_tYQxgfIlnQUDMdtAhdbXNwIM\n", - " Args:\n", - " query: types of reward hacking\n" - ] - } - ], - "source": [ - "input = {\n", - " \"messages\": [\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"What does Lilian Weng say about types of reward hacking?\",\n", - " }\n", - " ]\n", - "}\n", - "generate_query_or_respond(input)[\"messages\"][-1].pretty_print()" - ] - }, - { - "cell_type": "markdown", - "id": "3e4756cb-b952-47a7-be4a-4f8a0866b67f", - "metadata": {}, - "source": [ - "## 4. Grade documents" - ] - }, - { - "cell_type": "markdown", - "id": "0b278967-18ab-409e-9ca4-6ee44a23e708", - "metadata": {}, - "source": [ - "1\\. Add a [conditional edge](../../../concepts/low_level#conditional-edges) — `grade_documents` — to determine whether the retrieved documents are relevant to the question. We will use a model with a structured output schema `GradeDocuments` for document grading. The `grade_documents` function will return the name of the node to go to based on the grading decision (`generate_answer` or `rewrite_question`):" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "98f0e1a5-5ca8-4d8c-a94c-fc0976ae1937", - "metadata": {}, - "outputs": [], - "source": [ - "from pydantic import BaseModel, Field\n", - "from typing import Literal\n", - "\n", - "GRADE_PROMPT = (\n", - " \"You are a grader assessing relevance of a retrieved document to a user question. \\n \"\n", - " \"Here is the retrieved document: \\n\\n {context} \\n\\n\"\n", - " \"Here is the user question: {question} \\n\"\n", - " \"If the document contains keyword(s) or semantic meaning related to the user question, grade it as relevant. \\n\"\n", - " \"Give a binary score 'yes' or 'no' score to indicate whether the document is relevant to the question.\"\n", - ")\n", - "\n", - "\n", - "# highlight-next-line\n", - "class GradeDocuments(BaseModel):\n", - " \"\"\"Grade documents using a binary score for relevance check.\"\"\"\n", - "\n", - " binary_score: str = Field(\n", - " description=\"Relevance score: 'yes' if relevant, or 'no' if not relevant\"\n", - " )\n", - "\n", - "\n", - "grader_model = init_chat_model(\"openai:gpt-4.1\", temperature=0)\n", - "\n", - "\n", - "def grade_documents(\n", - " state: MessagesState,\n", - ") -> Literal[\"generate_answer\", \"rewrite_question\"]:\n", - " \"\"\"Determine whether the retrieved documents are relevant to the question.\"\"\"\n", - " question = state[\"messages\"][0].content\n", - " context = state[\"messages\"][-1].content\n", - "\n", - " prompt = GRADE_PROMPT.format(question=question, context=context)\n", - " response = (\n", - " grader_model\n", - " # highlight-next-line\n", - " .with_structured_output(GradeDocuments).invoke(\n", - " [{\"role\": \"user\", \"content\": prompt}]\n", - " )\n", - " )\n", - " score = response.binary_score\n", - "\n", - " if score == \"yes\":\n", - " return \"generate_answer\"\n", - " else:\n", - " return \"rewrite_question\"" - ] - }, - { - "cell_type": "markdown", - "id": "ddbdc0c2-6f0c-41ec-b4d1-ad20d4498006", - "metadata": {}, - "source": [ - "2\\. Run this with irrelevant documents in the tool response:" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "0a62e5f7-4c4e-44cd-b4bd-77b6879ce970", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'rewrite_question'" - ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from langchain_core.messages import convert_to_messages\n", - "\n", - "input = {\n", - " \"messages\": convert_to_messages(\n", - " [\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"What does Lilian Weng say about types of reward hacking?\",\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"\",\n", - " \"tool_calls\": [\n", - " {\n", - " \"id\": \"1\",\n", - " \"name\": \"retrieve_blog_posts\",\n", - " \"args\": {\"query\": \"types of reward hacking\"},\n", - " }\n", - " ],\n", - " },\n", - " {\"role\": \"tool\", \"content\": \"meow\", \"tool_call_id\": \"1\"},\n", - " ]\n", - " )\n", - "}\n", - "grade_documents(input)" - ] - }, - { - "cell_type": "markdown", - "id": "ba25a787-004e-4e6c-8f22-62087af7da1d", - "metadata": {}, - "source": [ - "3\\. Confirm that the relevant documents are classified as such:" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "id": "8bd5d24b-f05e-47c4-b954-267ab514a090", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'generate_answer'" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "input = {\n", - " \"messages\": convert_to_messages(\n", - " [\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"What does Lilian Weng say about types of reward hacking?\",\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"\",\n", - " \"tool_calls\": [\n", - " {\n", - " \"id\": \"1\",\n", - " \"name\": \"retrieve_blog_posts\",\n", - " \"args\": {\"query\": \"types of reward hacking\"},\n", - " }\n", - " ],\n", - " },\n", - " {\n", - " \"role\": \"tool\",\n", - " \"content\": \"reward hacking can be categorized into two types: environment or goal misspecification, and reward tampering\",\n", - " \"tool_call_id\": \"1\",\n", - " },\n", - " ]\n", - " )\n", - "}\n", - "grade_documents(input)" - ] - }, - { - "cell_type": "markdown", - "id": "4c337d45-bc35-4e88-8b27-ebc6631f9fed", - "metadata": {}, - "source": [ - "## 5. Rewrite question" - ] - }, - { - "cell_type": "markdown", - "id": "e8d67fdf-0b77-4b90-97f2-63a571c3e496", - "metadata": {}, - "source": [ - "1\\. Build the `rewrite_question` node. The retriever tool can return potentially irrelevant documents, which indicates a need to improve the original user question. To do so, we will call the `rewrite_question` node:" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "id": "278d1d83-dda6-4de4-bf8b-be9965c227fa", - "metadata": {}, - "outputs": [], - "source": [ - "REWRITE_PROMPT = (\n", - " \"Look at the input and try to reason about the underlying semantic intent / meaning.\\n\"\n", - " \"Here is the initial question:\"\n", - " \"\\n ------- \\n\"\n", - " \"{question}\"\n", - " \"\\n ------- \\n\"\n", - " \"Formulate an improved question:\"\n", - ")\n", - "\n", - "\n", - "def rewrite_question(state: MessagesState):\n", - " \"\"\"Rewrite the original user question.\"\"\"\n", - " messages = state[\"messages\"]\n", - " question = messages[0].content\n", - " prompt = REWRITE_PROMPT.format(question=question)\n", - " response = response_model.invoke([{\"role\": \"user\", \"content\": prompt}])\n", - " return {\"messages\": [{\"role\": \"user\", \"content\": response.content}]}" - ] - }, - { - "cell_type": "markdown", - "id": "1ec05f29-48a2-4325-8c56-da60490f2a60", - "metadata": {}, - "source": [ - "2\\. Try it out:" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "id": "15404075-b7c8-4248-84d3-ca2b361aa3d2", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "What are the different types of reward hacking described by Lilian Weng, and how does she explain them?\n" - ] - } - ], - "source": [ - "input = {\n", - " \"messages\": convert_to_messages(\n", - " [\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"What does Lilian Weng say about types of reward hacking?\",\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"\",\n", - " \"tool_calls\": [\n", - " {\n", - " \"id\": \"1\",\n", - " \"name\": \"retrieve_blog_posts\",\n", - " \"args\": {\"query\": \"types of reward hacking\"},\n", - " }\n", - " ],\n", - " },\n", - " {\"role\": \"tool\", \"content\": \"meow\", \"tool_call_id\": \"1\"},\n", - " ]\n", - " )\n", - "}\n", - "\n", - "response = rewrite_question(input)\n", - "print(response[\"messages\"][-1][\"content\"])" - ] - }, - { - "cell_type": "markdown", - "id": "55eab9fe-f1d6-4ad3-93d6-4638a92c9395", - "metadata": {}, - "source": [ - "## 6. Generate an answer" - ] - }, - { - "cell_type": "markdown", - "id": "d9362002-e66e-4e58-90af-d225c184b5d1", - "metadata": {}, - "source": [ - "1\\. Build `generate_answer` node: if we pass the grader checks, we can generate the final answer based on the original question and the retrieved context:" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "id": "20b0e60a-a5aa-4e95-a15a-2c91382e508f", - "metadata": {}, - "outputs": [], - "source": [ - "GENERATE_PROMPT = (\n", - " \"You are an assistant for question-answering tasks. \"\n", - " \"Use the following pieces of retrieved context to answer the question. \"\n", - " \"If you don't know the answer, just say that you don't know. \"\n", - " \"Use three sentences maximum and keep the answer concise.\\n\"\n", - " \"Question: {question} \\n\"\n", - " \"Context: {context}\"\n", - ")\n", - "\n", - "\n", - "def generate_answer(state: MessagesState):\n", - " \"\"\"Generate an answer.\"\"\"\n", - " question = state[\"messages\"][0].content\n", - " context = state[\"messages\"][-1].content\n", - " prompt = GENERATE_PROMPT.format(question=question, context=context)\n", - " response = response_model.invoke([{\"role\": \"user\", \"content\": prompt}])\n", - " return {\"messages\": [response]}" - ] - }, - { - "cell_type": "markdown", - "id": "8f59a1fc-fe75-4907-ae86-0dd33c4d9a7f", - "metadata": {}, - "source": [ - "2\\. Try it:" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "id": "15d84cb0-b529-49d0-b18e-1d03ff3f7c0d", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "\n", - "Lilian Weng says that reward hacking can be categorized into two types: environment or goal misspecification, and reward tampering. These categories describe different ways in which an agent might exploit flaws in the reward system. Environment or goal misspecification involves unintended behaviors due to poorly specified objectives, while reward tampering involves directly manipulating the reward signal.\n" - ] - } - ], - "source": [ - "input = {\n", - " \"messages\": convert_to_messages(\n", - " [\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"What does Lilian Weng say about types of reward hacking?\",\n", - " },\n", - " {\n", - " \"role\": \"assistant\",\n", - " \"content\": \"\",\n", - " \"tool_calls\": [\n", - " {\n", - " \"id\": \"1\",\n", - " \"name\": \"retrieve_blog_posts\",\n", - " \"args\": {\"query\": \"types of reward hacking\"},\n", - " }\n", - " ],\n", - " },\n", - " {\n", - " \"role\": \"tool\",\n", - " \"content\": \"reward hacking can be categorized into two types: environment or goal misspecification, and reward tampering\",\n", - " \"tool_call_id\": \"1\",\n", - " },\n", - " ]\n", - " )\n", - "}\n", - "\n", - "response = generate_answer(input)\n", - "response[\"messages\"][-1].pretty_print()" - ] - }, - { - "cell_type": "markdown", - "id": "955882ef-7467-48db-ae51-de441f2fc3a7", - "metadata": {}, - "source": [ - "## 7. Assemble the graph\n", - "\n", - "* Start with a `generate_query_or_respond` and determine if we need to call `retriever_tool`\n", - "* Route to next step using `tools_condition`:\n", - " * If `generate_query_or_respond` returned `tool_calls`, call `retriever_tool` to retrieve context \n", - " * Otherwise, respond directly to the user\n", - "* Grade retrieved document content for relevance to the question (`grade_documents`) and route to next step:\n", - " * If not relevant, rewrite the question using `rewrite_question` and then call `generate_query_or_respond` again\n", - " * If relevant, proceed to `generate_answer` and generate final response using the `ToolMessage` with the retrieved document context" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "id": "8718a37f-83c2-4f16-9850-e61e0f49c3d4", - "metadata": {}, - "outputs": [], - "source": [ - "from langgraph.graph import StateGraph, START, END\n", - "from langgraph.prebuilt import ToolNode\n", - "from langgraph.prebuilt import tools_condition\n", - "\n", - "workflow = StateGraph(MessagesState)\n", - "\n", - "# Define the nodes we will cycle between\n", - "workflow.add_node(generate_query_or_respond)\n", - "workflow.add_node(\"retrieve\", ToolNode([retriever_tool]))\n", - "workflow.add_node(rewrite_question)\n", - "workflow.add_node(generate_answer)\n", - "\n", - "workflow.add_edge(START, \"generate_query_or_respond\")\n", - "\n", - "# Decide whether to retrieve\n", - "workflow.add_conditional_edges(\n", - " \"generate_query_or_respond\",\n", - " # Assess LLM decision (call `retriever_tool` tool or respond to the user)\n", - " tools_condition,\n", - " {\n", - " # Translate the condition outputs to nodes in our graph\n", - " \"tools\": \"retrieve\",\n", - " END: END,\n", - " },\n", - ")\n", - "\n", - "# Edges taken after the `action` node is called.\n", - "workflow.add_conditional_edges(\n", - " \"retrieve\",\n", - " # Assess agent decision\n", - " grade_documents,\n", - ")\n", - "workflow.add_edge(\"generate_answer\", END)\n", - "workflow.add_edge(\"rewrite_question\", \"generate_query_or_respond\")\n", - "\n", - "# Compile\n", - "graph = workflow.compile()" - ] - }, - { - "cell_type": "markdown", - "id": "fb7c8138-8b01-4858-b9d1-b4bc5f7ebb33", - "metadata": {}, - "source": [ - "Visualize the graph:" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "id": "7b5a1d35", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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ERGTJk3KcFW9w74HFcXj966MVCpi5ZLqqNnYGPn9szNdFgAAdCs93YDtsvSdLb2kRu3WL/oVyvB7srvuuqtF4NYbVFdXxx133JEO3Og+eQV9YvTu/dLLyxb5NwAAoPcRugHbZfm7Wz5EF0/ot5Utgd6oeGJB+nHJuxu3siUAAOyahG7AdilZuCV0GzOhfwYrAXqi4mavC8vfrc5gJQAAkBlCN6DTmpoiVizZ8iF67HihG9DS2PEFEVmbHq9aVh2N9anMFgQAAN3MIExAp5WtrI3Ue2PwFw7qG/kF8vuuUl5eHq+++mqUlJTE8uXLo6KiIkaOHBljx46N3XbbLaZMmRL5+flt7ltaWhplZWUREVFRUdFq/WuvvRaDBrWeAGPAgAExduzYbda2fv36WLhwYSxcuDDefffdWLt2beTl5cXgwYNj8uTJse+++8bo0aM79XwrKipixYoVLdrGjx+ffo6bZ2B94403YsWKFVFVVRUDBgyIMWPGxJ577hnTpk2LRYsWRXV1daxdu7bV8cvKyuL1119v89wjR46MIUOGdKpe2peT1ycGDcmJdWX1kWqKKFtVGyPGtn2tAgDArkjoBnTaurK69OPBw3MzWMmuq7y8PG699db43e9+t81tTz755JgxY0YceuihkZOTk26/5pprYs6cOe3u96UvfanN9nHjxsXdd9/d5rqGhoZ4/PHH46abborXXnttm7UNHjw4vvjFL8bMmTOjT59th7M333xz3HjjjS3afvSjH8VHP/rReOKJJ+Kaa66J5cuXt7nv9OnTY9q0aXHOOee0O3lCeXl5nH322W2umzVrVnz961/fZo103ODhubGurD4iIirW1gndAADoVXRPATpt/drmoVteBivZNZWWlsaZZ57ZocAtImL27Nnxla98Je67774W7U1NTYnW9cILL8TMmTPjW9/6VocCt4hNIdfVV18dn/vc56KkpGS7z33TTTfFv/7rv7YbuEVEnHHGGRERZivtQZq/PqxvFtYDAEBvIHQDOq1CT7cuU1NTE1//+tejvLy80/seeOCBXVDRFvPmzYvS0tLt2nfu3Llx+eWXRyrV+XG9Hn300bj22mu3us2IESPi8MMP367a6DrNXx8293gDAIDewu2lQKc1v720SOiWqMcee6zdXmQFBQVxyCGHRE1NTcyfP79Fj67i4uKYOHFii+333Xff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8i+xaNGidFtDQ0O88MILcc0117QIxvbaa69W+//whz+Mp556qkVbKpWKRYsWxZVXXhm//vWv232eJSUl7a5LUlt1z5kzJ66++upYv359uq26ujoefvjh+P3vf98tdfUGyxdVReq9PL54fL9o425fAADYpfXNdAHAzql4QkEsfnNjREQsf2djjN+nMMMV7RoeffTRFstvv/12fOtb30ovDx48OMrLy9vcd8SIEW32SIuIOProo6O4uDiWL1/eon3evHlxxhlnpGdDraraEqD+0z/9U+yxxx4REXHiiSfGdddd12J9RMRXv/rVGD9+fOy7775RWloa77zzTrv1NXfjjTfGd77znTbHXUvSpz71qTZnXr333nvj3nvvjYKCgsjLy0vXPHjw4PjMZz7TpTX1Fkvfrkw/Lp7YerZdAADY1enpBmyXsRP6px8ve0dPt6Tcc889W12/tUDrBz/4QfTp0/bLen5+fnzzm99sd9+qqqpWgdrixYvTj4cNGxaXXnppm/suXLgwHnjggXjxxRc7FLhFRNx3331x4403dmjbHTFx4sQ499xz211fVVXVouby8vJOzepK+5a9veV6Kh7ffytbAgDArknoBmyX0XsURNZ7ryArl1RHbZVx3ZKw9957d3qfgoKC+OlPfxr777//Vrf78Ic/HF/84hc7fNyFCxe2WD7++OPjwgsv7FRt3/nOd2LOnDnpnnTNzZs3r1PH2l4XXHBBHHvssR3evnnYyPaprWqKFYurIyIiq0/EmN31dAMAoPcRugHbpU+fiN332tR7JZWKeOMVvYOScPXVV8e9994b5557bptBVXMFBQVx8cUXx0MPPRRHHXVUh45/3nnnxfXXXx8jRozY6nbtTchw0UUXxe9+97sYN27cVvedNWtWPPjgg/Hxj388ioqK4tZbb42pU6dus778/PxWbXl5edvcb1vH/OEPfxiXXHLJNrctLi5udwZYOu7NeRWRSm16vNuk/pGdY0A3AAB6n6xUavPbYoDOef2linjo1k0D4o/Zo1988uLxGa5o15JKpWLt2rWxatWqWLFiRXpig1GjRsXo0aNj6NChkZ2dvd3HX7lyZbz55ptRU1MT2dnZMXLkyBg+fHgMGzYs+vbd9pCfpaWlsWDBgqisrIz6+vooKiqKUaNGxcSJE9sdq23NmjXx5ptvxrp162LcuHExZcqU7a5/ezQ0NMSSJUtiwYIFERHRr1+/GDFiRAwfPjwGDx7c7u25dM4dv1wUy9/ddHvp8Z8aE5MPLspwRQAA0P2EbsB2a6hPxa8ueyMa6ze9jFx42Z5RWJST4aqATKqubIhff/etiNjUI/YLV+8bOXl6ugEA0PuYvRTYbn1zsmLC5MJYMG9DRES88cq6OPjoYd1ex/XXXx9LlizpsuOvXbs2cnJyYsCAAV12jr59+8Y3v/nNHb6Vkh1XVlYW//mf/9ml5+iua+o73/lOt/fee/2ldenHEz5QKHADAKDXEroBO2SfqUXp0G3u02tj6lHDop07C7vMM888E6+++mqXHT+VSrV7u2SSvvzlLwvdeoCysrJ44IEHuvQc3XVNXXLJJd0auqVSm14HNttnattjAwIAQG9g8Bpgh0zYd0D0H7BpXLEN5Q0mVIBe7K1562JdWX1ERBQMyI6JH+i6nnwAANDT6ekG7JA+fSKmzRgef7l7ZUREPPvw6tj3wKKIbuztNmbMmKio6Lqwr6qqKrKzs7u0F1pubm7k5uZ22fHpuMLCwhg/fnw0NjZ22Tm665rqjt50aamI5x5ZnV489KPDwrwUAAD0ZiZSAHZYU2MqfnPFW1FTtSmkOPnc3WLP/fRwgd7knX9siD/9z9KIiMgv6BMXXr539M0xnhsAAL2X76CBHdYnOysOPnpIevnJP62Ipq7rJAT0ME1NEU/+aWV6+aAjhwrcAADo9YRuQCIOPHxYFLw3ttv6tQ3x4uOrt7EHsKt4+Yk1UbHmvbHcCrNj6pHdP4sxAAD0NEI3IBF9c7Pi6NNGpZefe3RNVFbUZ7AioDtUVtTHMw9vCdmP+vgovdwAACCEbkCC9tp/UIzZo19ERDTUp+Kxu1dkuCKgqz1294porN80POzo3fvF3gcOynBFAADQMwjdgETNOLM4PWPhu/+ojDfnrctsQUCXeXPeunj3H5UREZGVFXHcrOIMVwQAAD2H0A1I1JCRuXHgR7ZMqvDIbSVRsaYugxUBXaFiTV08cltJevnAI4bEkBG5GawIAAB6FqEbkLjDThwZQ0bkRMSm20zvu2FJNNSlMlwVkJTGzb/X791WOnh4Thx24sgMVwUAAD2L0A1IXHbfrDj1n3ePnNxNg6mvLa2Lh/6wLMNVAUl57O4VsbZ0Uw/WvjlZ8fELdo++uSZPAACA5oRuQJcoGpYbJ549Nr28YN6GeP6x1VvZA9gZzH1qbfzj+Yr08gmfHhtFw9xWCgAA7yd0A7rMxMkD4qBm47s9/cDqePWZtRmsCNgR858tj/+7Z2V6+YDDB8ee+w3IYEUAANBzCd2ALvWRU0bF7nv3Ty8/9seV8cYrFVvZA+iJ3py7LubcuSK9vPve/eOoU0dnsCIAAOjZhG5Al8rqE3HqeeNi1G756bYHf18Sb81bl8GqgM5469X18cDNy9PLI3fLj1PPGxdZ3kUAAEC7vF0Gulx2Tlb800V7RNGwnHTb/Tctj/nPlmewKqAjnn9sddx/45aJUAYOyYnTL9ojsnNMnAAAAFuTlUqlUpkuAugdKivq47ZrF0bluoZ02/TjhsWHjh+RwaqA9jzyh+Xxjxe29EotGJAdn/7qhCgsytnKXgAAQITQDehmG9c3xJ2/Whjlq+vTbftNK4pjPzEmQscZ6BHqapri7t8ujhWLq9Ntg4bmxJlf2EPgBgAAHSR0A7pdbXVT/PE3i2LV0pp02257FsRJnxkb/Qr7ZrAyYP3a+rjr14tiXdmWYHz4mLw44/N7RH7/7AxWBgAAOxehG5ARDfWpuO9/lsSStzam2woKs+Okc8bG2In9t7In0FVKFlbFvTcsidrqpnTb2IkF8fELdo+cXF1RAQCgM4RuQMakmiKeemBVvPh/Zem2rKyI6ccPi2nHjogsn/GhWzTWp+Lph1bFy0+ujdSWvC32P2xwHPXx0dHHtEsAANBpQjcg4xa+URn337Q06mu3vByNKM6PGWeOiRFj8zNYGez6Fr1ZGY/eXtJigpPsnKw44azi2OuDAzNYGQAA7NyEbkCPsK6sPv70P4tjzcq6LY1ZmyZZOPxjI40lBQmrWt8Qc+4uiXfmV7ZoHzQ0Jz7+z+NiyMi8DFUGAAC7BqEb0KP87ZHSePbhNS3acnKz4qAjh8ZBRwwVvkECXn6yLJ55qLRF79KsrIgDPzIkDjtxZPTNcW83AADsKKEb0OOUr66LR25fHiULq1u05+RmxQc/PDgOOXqYWU6hk5qaIt54pSJe+sualj1KY9Pt3Md9ckwML3Y7NwAAJEXoBvRYr71YEU/ctzJqqppatPfJjhi/b2HsM7UoJk4eENl99cqB9tTVNMX8Z8vjpSfKYuP6hhbr+uZmxWEnjIgDPzLUxCUAAJAwoRvQo9XXNsUrT5XFS4+vjZqqxlbrc3KzYtJ+A2Lfg4ti970KM1Ah9Dz1tal49/X18eYr6+Kdv1e2Wq/XKAAAdD2hG7BTaKxPxfznyuP5x9a06q2zWXbfrBg7sSB236swxu1VGMPHGAie3qN8dV2sWFwVb81bHwtfax20RUQMH5MXBx4xJCZOGRT5BX26uUIAAOhdhG7ATmfhG+s2k4gAACAASURBVJXx5ssVsWD+hmioa/8lLLtvVvQf2DcKB236b0BRThQOzHmvLScKBmxqM2g8PVldTVPU123+LxUNdY1RXd0Ua0qqo2xlbZStrI21pXXR2ND+78LeBw6MAw4bEmPGF3Rj5QAA0LsJ3YCdVmN9Kt55fUO8/kJFLH17Y9RvJYCD3mTIiJwYO6kw9tinMMZN6h85eXq1AQBAdxO6AbuMFYuqYuk7G2Ppgo2xfFF1NNZ7eWPXl5PXJ4aNyotho/Ji5Lh+MX6fwigsysl0WQAA0OsJ3YBdVsWauihfUxcVq2ujvHTT49qqxqirbYy62lTU1zVFXU3Ttg8EGdR/YN8oKMyOfoV9o1//7Cgo3HRb9JBReTF8VJ6ADQAAeiihGwCJOPzww6OmpiYiIl588cUMVwMAAJBZBnkBAAAAgIQJ3QAAAAAgYUI3AAAAAEiY0A0AAAAAEiZ0AwAAAICECd0AAAAAIGFCNwAAAABImNANAAAAABImdAMAAACAhAndAAAAACBhQjcAAAAASJjQDQAAAAASJnQDAAAAgIQJ3QAAAAAgYUI3AAAAAEiY0A0AAAAAEiZ0AwAAAICECd0AAAAAIGFCNwAAAABImNANAAAAABImdAMAAACAhAndAAAAACBhQjcAAAAASJjQDQAAAAASJnQDAAAAgIQJ3QAAAAAgYUI3AAAAAEiY0A0AAAAAEiZ0AwAAAICECd0AAAAAIGFCNwAAAABImNANAAAAABImdAMAAACAhAndAAAAACBhQjcAAAAASJjQDQAAAAASJnQDAAAAgIQJ3QAAAAAgYUI3AAAAAEiY0A0AAAAAEiZ0AwAAAICECd0AAAAAIGFCNwAAAABImNANAAAAABImdAMAAACAhAndAAAAACBhQjcAAAAASJjQDQAAAAASJnQDAAAAgIQJ3QAAAAAgYUI3AAAAAEiY0A0AAAAAEiZ0AwAAAICECd0AAAAAIGFCNwAAAABImNANAAAAABImdAMAAACAhAndAAAAACBhQjcAAAAASJjQDQAAAAASJnQDAAAAgIQJ3QAAAAAgYUI3AAAAAEiY0A0AAAAAEiZ0AwAAAICECd0AAAAAIGFCNwAAAABImNANAAAAABImdAMAAACAhAndAAAAACBhQjcAAAAASJjQDQAAAAASJnQDAAAAgIQJ3QAAAAAgYUI3AAAAAEiY0A0AAAAAEiZ0AwAAAICECd0AAAAAIGFCNwAAAABImNANAAAAABImdAMAAACAhAndAAAAACBhQjcAAAAASJjQDQAAAAASJnQDAAAAgIQJ3QAAAAAgYUI3AAAAAEiY0A0AAAAAEiZ0AwAAAICECd0AAAAAIGFCNwAAAABImNANAAAAABImdAMAAACAhAndAAAAACBhQjcAAAAASJjQDQAAAAASJnQDAAAAgIQJ3QAAAAAgYUI3AAAAAEiY0A0AAAAAEiZ0AwAAAICECd0AAAAAIGFCNwAAAABImNANAAAAABImdAMAAACAhAndAAAAACBhQjcAAAAASJjQDQAAAAASJnQDAAAAgIQJ3QAAAAAgYUI3AAAAAEiY0A0AAAAAEiZ0AwAAAICECd0AAAAAIGFCNwAAAABImNANAAAAABImdAMAAACAhAndAAAAACBhQjcAAAAASJjQDQAAAAASJnQDAAAAgIRlpVKpVKaLAKDnOvjggyOVSkVWVla6rfny5sdba2trXUTEiy++2M3PBgAAoHv0zXQBAPR8m4Oz5povb368tTbf8QAAAL2J0A2ADmne021HpFKpVj3nAAAAdjXGdANgqwYOHBgRyfZUy8rKisLCwsSOBwAA0NMI3QDYqlmzZqUf72jw1nz/T33qUzt0LAAAgJ7MRAoAbFV1dXWcdNJJsX79+h2+LXTz/oWFhTF79my93QAAgF2Wnm4AbFW/fv3i/PPPj4i2J1ToqOb7nX/++QI3AABgl6anGwDbVFtbG6eeemqsWbNmu3u7Ne/l9tBDD0V+fn4XVAoAANAz6OkGwDbl5eXFZz/72e3ev/n3O+ecc47ADQAA2OUJ3QDokNNOOy0GDRq0XbeYZmVlpXu5feITn+iiCgEAAHoOoRsAHZKfnx9nn312ermjwVsqlUpve+6558aAAQO6pD4AAICexJhuAHRYbW1tzJw5M8rKyjo8ttvm7YqKiuLPf/5z9OvXrxsqBQAAyCw93QDosLy8vDjnnHPSy9v63qZ5MDdr1iyBGwAA0GsI3QDolNNOOy0GDBjQqRlM8/Pz44wzzujCqgAAAHoWoRsAnVJQUBCf/vSn08vt9XZ7/4ylRUVFXV4bAABAT2FMNwA6raqqKk455ZRYt25du2O7bW4fNGhQzJ49262lAABAr6KnGwCdVlBQEOeee25ERGRlZbXq7dY8iPvkJz8pcAMAAHodPd0A2C5VVVVxwgknRFVVVat1m0O3/Pz8ePDBB2PAgAEZqBAAACBz9HQDYLsUFBTEWWedlV5u6zucs846S+AGAAD0Snq6AbDdKisrY+bMmbF+/fp02+ZeboWFhTF79uwoLCzMYIUAAACZoacbANutsLAwzjnnnPRy8+9xzj33XIEbAADQa+npBsAO2bhxY5x00klRWVmZbhs2bFjcd999kZeXl8HKAAAAMkfo1gnlq+vi7fnrYkNFQ1RXNkR1VWM0NWa6KoDMKykpiZUrV6aXi4uLY+TIkRmsCKBn6JMd0a8gO/oV9o3CQX1jzw8OisHDczNdFgDQDYRu29BQn4pX/romXn9xXZStqst0OQAA7OSGjMiNyYcMigOPGBZ9c7IyXQ4A0EWEbu1IpSL+8Xx5PPNgaWzcoDsbAADJKhiQHR8+YURMOXRwZBlpGQB2OUK3NtRsbIw//e/SWP5uVYv27L5ZUTyhf4zcrV8UDMiJfoXZkZ3t20kAANrW2JiK6srGqNpQH6XLqmPZOxujsaHl2+8xe/SLmeftFv0K+2aoSgCgKwjd3qd0WU3ce8OS2Li+Id3Wr7BvTDtuREyaMiiDlQEAsCt49x/r47lHV7V4v9l/QHacev64GDmuXwYrAwCSJHRrpmxlbdz6H+9GQ/2WH8nUo4fFgUcMz2BVAADsil756+p46f/WpJez+2bFp74yIYaPMfMzAOwKhG7vqdnYGDf99J30N47ZfbNixifHxtiJhRmuDACAXdWydypjzh3L0l/6FgzIjnO+PtGtpgCwCzBk63vm3FXSoov/yefuLnADAKBLjZ1YGKect0dk9900TnDVhsZ49M6SDFcFACRB6BYRJQurYsGrG9LLx36iOIaPMZ4GAABdb+io/DjmjOL08jt/r4zFb1VmsCIAIAm9PnRLNUU8cvvy9PKe+w+MPfYdmMGKAADobXbfa0DsdcCWSbseu2tFpJoyWBAAsMN6fei26M3KKF9dHxGbxnE79NiRGa4IAIDe6JCPjoi+uZvenq8rq493X9+wjT0AgJ6s14dub7+6Pv34gCOGRb/+Bq0FAKD79evfNw78yND08tuvrstgNQDAjurdoVsqYsH8LaHb5IMHZ7AYAAB6u8lTh6QfL5hf6RZTANiJ9erQraKsLmqrN72TKRqWE3n9sjNcEQAAvVlOXp8YPDw3IiLqa5uifHVthisCALZXrw7dKtfVpx8XDc/PYCUAALBJ0bC89OPK9Q0ZrAQA2BG9OnTb0Cx0KyjUyw0AgMwrGLhljOHK9fVb2RIA6Ml6dehWvaEx/TjfBAoAAPQABYVb3pdW6ekGADutXh26pVJtPwYAgExp/ra0sdGbVADYWfXq0A0AAAAAuoLQDQAAAAASJnQDAAAAgIQJ3QAAAAAgYUI3AAAAAEiY0A0AAAAAEiZ0AwAAAICECd0AAAAAIGFCNwAAAABImNANAAAAABImdAMAAACAhAndAAAAACBhQjcAAAAASJjQDQAAAAASJnQDAAAAgIQJ3QAAAAAgYUI3AAAAAEiY0A0AAAAAEiZ0AwAAAICECd0AAAAAIGFCNwAAAABImNANAAAAABImdAMAAACAhAndAAAAACBhQjcAAAAASJjQDQAAAAASJnQDAAAAgIQJ3QAAAAAgYUI3AAAAAEiY0A0AAAAAEiZ0AwAAAICECd0AAAAAIGFCNwAAAABImNANAAAAABImdAMAAACAhAndAAAAACBhfTNdAAAAJOGFF5+Nutra9HJh4YDYf/+DMlgRANCbCd0AANjpNTQ0xL998+IWbUVFg+OePz6SoYoAgN7O7aUAAAAAkDChG9BCKpWKVCqV6TIAAABgpyZ0AyIioqxsTdx5161xzrlnxI03XZ/pcgAAAGCnZkw36OWWLV8av/nNtfHU04+n22pqqjNYEQAAAOz89HSDXm7RondaBG4AAADAjhO6AQAAAEDChG4AAAAAkDChWy/2+hv/iG9f+rVYu7Ys06UAAAAA7FJMpLCLqampiSVLF8XixQtj0aJ3o7R0ZRQU9I8xY8bG6NFj4gOTPxhDhw6L0tJVccmlX4uKivL4ytc+Fz/98S9j5MhRHT5PyYrl8fLLz8eKFSVRVrYm+vTpE2PHjotx43aPscXjYvTo4sjLy+vQsaqqqmLpssXp5d3HjY/8/Pz0cnV1dTz3/NOxePGiWLt2TVTXVMfY4nGxxx7jY4/dJ0Rx8W6RnZ3d8R/S+9TW1sb8v8+N11//R5SXl8WGDetj6NDhsdtu42LcbnvEmDFjY+jQYR0+3rp1FbFy1YoWbc2fU2NjY7z8yguxYMGbsWrViqiqrooBhQNi1KgxMWHCpDh46rQ2j7t+w/pYsnhhLF6yMBYtWhgVFWsjNzcviooGx9577xt77blvjBo1ukM1NjY2xjvvLohUKhXvvPN2q/XLly+NN996vc193//vsy1JXiuZ1NDQEK+//vd4/Y1/xNq1ZbG2vCz65feLCRMmxYTxk2LixL2ioKAgIjb9Hi5esjAiIvpm942JE/dsdbyysjWxpmx1i7aJE/aMvn079rK8ePHCqKmtSS/3y+8X48bt0eHn05Ou+9Gji2PEiJEt9h1cNKRV27ZUVlbG8pKlLdqGDB4aw4eP6NRxusLykmXx8svPx6pVK6O8fG3U1ddF0aDBMWhQUUyatFfs/8GDol+/fh0+XsmK5bFhw/r0cnaf7Jg0aa/0cnV1dTzztydj6dIlsXJlSURWxMABg6K4eGzsN+WAmDBhUqLPL5O1rlu/Ll566blYsmRRlJWtidq62hgzujjGjh0Xu+22exSP2S0KCws7XXddXV3Me/XlWLmyJFasKInVa0pj4MBBMWZ0cRSPGRv77jslBg0q2uoxlixZFNXNJqbJzcmN8eMnRsSm14B3F74db7/9VixesjCy+2RHUdHgGDZseHxwvwNjwoRJkZWV1em6m0vyusv03+rGxsaYP39uvP7GP2L16lWxYcP6GDRocBQXj40x7/17FPQr2O7jAwB0BaHbLuSxvzwc1/z836Oqqmqr28085fR4+ZUXoqKiPCIili1bEhd/5Z/j59f8JorHjN3qvi+/8kJcd90v4o03X9tmPccfd3J8/qIvR1HR4K1u9+RfH4sf/fh76eWvfuWbcerMM6KhoSFu/v0NcdPN1291//32OyAu/fZVnQoNIzaFWHfc8fu45dbfbXPb4cNHxJcv/kYcfthR29z29jt+H7f94cYWbVd894dx5Ec+Gk8//UT86r9/HiUrlre57yEHT28RujU0NMRTTz8et99+c4d+5kVFg+OCf/5CnHjCzOjTp/2OrIsWvRsXff7sdtc/9fTj7U6ucOUVP4qPHHHMNmvpimslEzZUbog777wl/nj3bVv93SooKIiLv/T1OG7GSfG7//1N3HHn79Pr/nzf/7X60P8/v/t1PPDgfS3arvnZf8eBBxzcobrOPf/MVue//89PbHO/nnjdTxg/Kd5d2DL8nTJl//iv/9z67/77/Xn23fHb6/6rRdvxx50c3/rmdzt1nCQ99/wz8dvr/ivefbd1uP1+Hzvx1PjsORd2KGy88spvxVsL3mjRdtcdD8bgwUPitj/cFLfe9rt2r9cLL/hSt4ZuXVXrsuVL44YbfhWPPzFnmzVMmbJ/fPXL32wzAH+/urq6eOTR++OG//nv9N/J9hx66Ifj2GOOj2nTD4+BAwa2Wv+Vr32u1TEemP1k3HjTdXH7HTdv9dhFRYPj/PM+HyeeMLPDYfxmXXHdZepvdVNTU8y+/5743f/+Zqv/HgUFBfHZcz7XqWMDAHQ1odsuYNWqlfEf1/4onn32qQ5t/6c//7FV2+rVpbG6dFW7oVtNTU387Jrvx5zHHupwXQ8/Mjv++tRf4uIvfT2OP+7kDn9jf8cdv49jP3pifOObX4rXX//7NrefP39unH/BJ+OyS78f06cf3qFzvPzKC3HZ5V/fZkC52erVpXHZ5d+Iww47Mi7+4tc7/aEhIuIPt98cv/nttVvdZuYpp7eo8Yc/uiJWry7t8DkqKsrjpz/7fjz8yP3x7W9dGaNHjel0nTuqO6+Vrvbsc0/HVVdf0qHrpKqqKn704+/FzTff0G64lGk99bqf9clz4t9/eHmLtr//fV4sWbKoU733Hn5kdqu2ww87ssP7J6mmpiZ+9OMrOxQIbfbAg/fFAw/eF5declUc+9ETOn3O2rrauOrqS7d5zuOPO6nTx07ajtZ6x523xH//+j86fL6//31eXPC5s+KsT50bZ3/mn9vtrdvQ0BDf+vZX4pW5L3bouM8//0w8//wzcdSRx8Z3L/9Bh/a54MJPdeg1oqKiPK75+Q/ij3f/IX70g2s79PvXndddd/ytLitbE1de9e2YP3/uNretqqrq1DUBANAdjOm2k6upqYmv/9sXOxy4tWXs2HHxuxtujwMOmNrm+nXrKuJr/++iToUom20OIq648luRSqU6tE/JiuVx8syjOvQmvvl5rvr+pbGhcsM2t33woT/Fv379Cx0OHpp7+uknYtZZp8Rrr83v1H6PPz5nm8HD8OEjWnwQ+fvfX+1U4Nbc/Plz4wc//G6Hf+ZJ6e5rpSv9efbd8e1Lvtrp66SnBm49+bo/+ugZceIJM1ute+TRBzp8rsWLF8bixQtbtBUUFMQhh3yow8dIysaNG+Pbl3y1U8FHc9//98va/HJkW6677hfbPOeMGR/r1G3DXWV7a21qaoqf/PTq7Q5Xbr3tf+OfL5gV65vd7trcr379Hx0O3Jo78MCO9VCN6PxrxOLFC+PzXzgnlpcs2+p23X3ddfXf6jVrVsdX/99FHQrcAAB6KqHbTu66G34Zy5YtaXPdMUcfF2ecflac/k+firFjx7V7jMu+8/3YY48Jba5raGiIK7/37XZvESwqGhzTpx8eRx15bOyz9+R2z/HkX/8Sjzxy/1aeydbtvvv4OP64k+OoI49t97lUVVXFvffeudXjvPjSc/Hjn1zV7vq99twnPnLEMXHYYUdudRyoH/zoiqipqWl3/fu9/0NQQUFBfOhDR8RHjjgmPQ7YGaef1eIWolNnnh5bM3z4iPS+bZk/f2488eRjba4bOHBQHLD/1NhvvwPafJ4FBQWx334HtPnfsGFt/1x6yrWShOeefyau+fnWe61MmDApZsz4WBx66Ie3+u/QE+wM1/2JJ5zSav/7H7g3GhoaOnSuJ578S6u24487OSPjBd78+xti7ryX2lw3ZnRxnHjCzJj1yXPi4KnT2r12fv4fP4xVq1Z26rzv/3kPHz4ijjn6uDjk4Onpto+f+olOHbOrbG+tN918favbsjcrKCiIA/afGkcdeWwceMDB7f5sS1Ysj1/96uet2peXLIt77rm93ZoPPODgOOywI9u8DX7aoYe1u9/W7LP35Jgx42MxZcr+W30dqagoj+uv/+VWj5Wp6665pP5Wb/5Csb33NxGbvjDc1t8TAIBMc3vpTuyll5+Pu+/+Q6v2vfbcJy677N9jbPFu6bYLL/hi/Oa318Y9997Ravt7770z/u0bl7V5jutv+FWb3/qPHTsuvvmNy2PKlP1btDc0NMQdd94S113/i1b7XPuLn8TUqdNi2LDh23xum02YMCn+9WuXxOTJ+7Vof/bZp+Kq71/aqtfOH26/MU77+JltDpq9cuWK+O4V/9bmeT4167NxztkXtLrlaOHCd+KHP7qi1XhEy5YtiZt/f0NceMEXO/xcNvvchRfHmZ/4dHpA6fUb1scjj9wfM449scV2gwYVxTlnX5AeJ2fM6OK48MIvxYTxk2L06OLIycmJiIi1a8viD7ffHHfedUurc/3qv38e06cd3up5DR8+In5+za8jYtP4bZdd/o0W6085+fT4/EVf7tTzyvS1kpQ1a1bH9676dpvrCgoK4tJvXxUHHzw9cnNzW6x76qnH42c///dtjgHV3XaW637KlP1j7NhxLT5kV1SUx4svPRfTp2070Hh0TuteccccfVyn69xRy5YtaXOsroKCgrjqez+Ngw48pEV7Q0ND/NcvftpmD6Pf/e9vtms8uoKCgrjiuz9qEWAtW740nn32qZi875ROH68rdabWZ57ZNBZaW8do79b0Z555Mn7ys6tb/V4+/MjsOProGTHt0A+n295++802a/zyxd+I4487uUVQ9e67b8cvfvmzeGXui7HXnvt0+tbrmaecHuede1GrAG/FypL45a+uiaefbj0+4+NPzIlPvHZWq7+HEZm/7pL8Wx0R8dvr/qtVz9XNvnzxN2LGsR9rsW9VVVX89rr/ivv+dFen6gb+P3v3GdDkubcB/AqgDBGCIILgwlG0iloXAknArbWO1lqrFrW2tlpr7Tn2HFt7+nZYT60ddjhb62i1dmpdrXVAgogDRetCRXAhiDJFZiDvBw+p+DyBoEkekly/T3LnfpI/eBOSK/cgIiJz40w3KxYTs0vQ5ubmhkWLllQL3ADA2dkZs15+DZGqAYJrfv9jC/Lz8wTt6deuir6If3TYKKz66ntBiAIATk5OGP/0JHy9coPgk/SioqJal5rdrWePPvjs069E32CEhkZgwXzhTIWioiKkpYlvHP3td6sEL/zd3NywfNk6THt+pugeP23atMWSL1dj9Kixgts2fL8GaWkXjP12ANzZWP7pcdHVTnDzaOyBMU88LXoK3uOjn4KbmxsmT3oBq77eiEjVALRs2VofuAFAkybemDF9Nt6Y+47g+hs3sgy+kTQlqceKKf3403rRJZidO3fF6lU/IixMKQjcACAiIhJrvvmx3h0GYS3jXiaT4bHhjwuu3blTuE/bvS5cOC+YEdO0qS8efjikTnWawnKRcSuXe+GLz1YJgg/gzu/Bq7Pn4sUXXhHctvPPbbhw4XydHl8u98KSL1ZXC7EAIDCgBcY88XSd7svc6lKrVqvFkqWfCO6jQ/tgfLv2VwwZ/JjoXpBhYUqs+eZHdBQJGz9Y+DbKy8v1X58/L3yu7N07DKNHjRU8RwUFtcPHHy3F/731X4wfP7nmb/Qe/12wGK/Oniv6XOHv1xzz3/3I4P5wy1Z8Jtou5bgz9d/qkyePi35AeGe8fCMa1rm5ueGVWf/CU2MNHxBEREREJAWGblbsTLJwH5VZM18TPUGtitgLbAC4JrJXzIYNawRtHdoHY9bLr4mGDndr27Y9Zr70T0H7/gRNjddV6dtXgQXvf2rwU3AACAnpjlat2gjas25cF7RdTb8iuiTpX6+9hYc6dKyxFicnJ0x7/mU09w8Q3HbipPF7zQwdMgIqZX+j+wN3Zrtt36rGpGjhbKR7DRgwVHSZTUbmtTo95v2QcqyYUn5+nuiMQbncC4sWflnr6X6ennK4uzc2V3l1Zm3jvn+/wYK2WPXuWmcPauKES0sfHTba4gdyJB1LFJ2hNPOlf9Z6WujYJyeILsdbtXpZnWqY/sIrBrcLqG/qUmtMzJ+ie6G99dZ/0aSJd43XenrK8e/X3hK05+XlVgtrKysrBX1u3jS8r6ZMJkOkakCdn9fvDRnFRKoG4JmJUwXtJ08ex+HEA9XapBx3pv5bDQAb7jkFucqSL1eLBntVZDIZnps6o5aKiYiIiCyLoZuVKisrQ2qq8FPi3nctlRHTrJmfUcFMaWmp6Jv1f//r/2oNUaoMHjRc8EK7qKgI2dk3a722U8cu1WZziZHJZOgXJXyTnpUlfCGvVgv3NqvLmyUXFxe8ILLc8qKB5S9iJk+aZnTf+yGTyfDoo6ME7RkZ5g3dpB4rppR45KBou6EZYfWdtY17b28fKBX9BO0xscJZvVV0Oh1+/2OLoL1/P8svLY2PFwbFTZv6GvXzlslkGPvkBEF7QkKc0QeLBAW1Q//7OPVUCnWtVexQjdmv/Nvgidv3atWqDR5/fJyg/fKVi/p/t2zZSnB7ampKnWcbmsoTTzwtuvdacnL1fTOlHHem/lt99eplJCTECdrHPz1Z9AMAIiIiovqOoZuVyjQwe8nLq0mt17Zo2VrQdu8pmafPCE8pbO4fUOun5ndzcHBA15BHBO13v8l5UD4+wlP4boh8en7wULygTaGIqtNjPdRBGFYau3Szb19FrbOk6qqwsBAXLpxHfLwaBw7sQ0bmNTRr5i/oZ2ismIq1jBVj/PVXkqAtMLAlBg4YZtE6TMUax/3QocJTTLdt32Swf/LZ04Lnr+CHOtV4eIy5XL4sDCPHPRVd7YCUmvTvJx5C5eRkG3X90CEjqi3hrc/qUmtJSYloIB7WV1mnxxTbz+7ixb//z8TGOgDMmv0c4vbF1OmxTMHTwxOjRgqXeN/7nC71uDOGsX+rjxw9JGhzc3PDU09x2SgRERFZJx6kYKUaNRJfylFWVlbr7KLCwluCtntP+Dtx4rigz7WMdHz08ft1qBKIif1T0Hb58kV079azTvdjiJdcGDLm5uZU+7qsrAwnTgiXw+38czuOHj1s9GOJfep/4cI5o65t3erBl3tptVrs/HMbdv65HRcunBPdd0yMuUM3axkrxjh5Svi9qJT9jX7zWp9Y67jv2aMP5HKvaktKU1NTcO58Mjq0Dxb0j4sThiFDRE5C+2Uk+gAAIABJREFUtYSLl1IFbR2DHzb6ejc3NzT3DxAso7x+PQPe3sLQ4l5SBI33qy61njVwIrLYoQo1OX/PwSAAcPHi3/sTtmnTFsOGjhTM3C0qKsJb//cvRKoGYNy46FqXZpuS2PLbK1cvVfta6nFnDGP+VgPAsWPC01cHDxpe47YZRERERPWZ9b2TJAAwuFl7evoVtGnTtsZrL10UvkC/d2lfTo74sr7tOzYbWaFhJSUlD3wfVcQOH7iX2CERAHDo0P4HfvyioiLodLpa945q0eL+3wxXVFQgVr0b33yzTHRPo9qUa8tr7/QArGWsGEMsoAwIMG75Wn1jrePeyckJI0c8ibXrVlZr//PPHYLQrbKyUnRpaV332DKFkpISwYw7APD2rtsJvL6+foLf82sZ6TXuZVXl3gN06rO61JptxueYouLqH148N3UGjh1LFH2ujVXvRqx6N7p364kJE6agxyO9H/jxa+PbVDhT9MqVv0O3+jDujGHM32oAOHfujKCtRQvhsl8iIiIia8HlpVbK0dFRdKbA5t9+qvG648ePir6ZaNmi+pJTc+6l1bSpr8nuy8GI5UmGwgdTaO4fYNRm7W5uje7r/gtuFWDmy89i/vtv3lfgZgnWMlZqo9PpRGcP+vk1t1gNpmTN437gwKGCtt//+A2lpaXV2k6fPiE4ZCE8XCXJCbJih9EAqHWT/3s1FVmOe+2acb/7rq7C/b/qq7rUas6x7H/P77eXVxMs+XK16N6nVZKOJWLOay/h9Xmv4lId9je8Hz4iz4F5ebn6DyTqw7gzhjF/qwEgL194aEpzI/ftIyIiIqqPGLpZsUEDHxW0bdn6C84knxLtX15ejq+/WSpob9rUV7CERGwJqqnc+ybH3G7fLjTbfbcy4ymBxcXFmPfmP5BsYGlVc/8AKBX9MP7pyXhh2iyMHjVWdPmdudnKWLk30Kni6WHcDI36xlrHPQAENA9Ezx59qrUVFRUh4UD1DdbVGuGppQMHCAM7SzAUQtZ1abKri6ugzZy/Y9bg1i3zff9iH17J5V749JMVmDL5xRqvPXBgHyY/OxZ7Y4RL403FxVn8AJdbtwoA2Na402q1oh98NPWx3IcvRERERKbG5aVWbOiQx/DN6mWC9hkvTcYbc99B//5D4OBwJ1fNyrqO996fh5MnhXtWzXzpn4I2F1fhC/DHHx+H6IlTH6hmmYMDGrs3fqD7qKuG9+xXV+XHjduNPl3TEGcDb4hM4cNF74r+fzX3D8Czz05HVORA/f9vlczMDDw9QbgRvTnZylhxcXGBm5ub4E1fbp5w3yFrYK3jvsqjj44SbJ7/+x9bEakaAODOG/Tde36vdrubmxv69A43e21iDP28y8vLaz3d8W5iSymbmfgQFmsjdnJwUFA7fPKR8O9fXRnaH9XFxQXRz0zFY8NH45dfN2L9htUG7+O9+fNQodVi4EDTH7hiaGlt1WxOexh35vwAgYiIiMjcGLpZMR+fppgx/VUsXfap4LYFH/wfFnzwf+jcuSvy8nJx9epl0fsIDY2AUtFP0C626XFBfp7R+7LUJx4enqLtRUW3Lbp8sS6upl9BrHq3oL1Xz1C8P/+TOr2ZMjdbGistW7QWzCw090EU5mKN4/5uoX0iBCHooUP7kZV1Hb6+zXDi5DHB0tIB/YeKBjSW0MzXT7Q9NzenTie4ZogsI7f35XVykeeSzMxrFnmO8fJqguemzsDYsRPxyy/fY923X4v2W/z5QvQJjTD5hv83soQnfDb3D9D/DbClcefk5CR6oENm5jV06dLNorUQERERmQqXl1q5J8eMx+hRYw3efvLkcYOBW3P/AMye9W/R27y8hEFKalrK/RUpMUPLAw39XOqDHTt+E7QFBrbEf/6zwCKBW0VFhdF9bWmsBIps2G3KfY1qU5efe22scdzfzcXFBcOGjhK0797zBwBArd4juK1/v8Fmr8uQqsDgXjm52XW6H7GQt1kz//uuyxZ4iIRrRUVFZt3rTVBDYw9MmfwC1n+3GUFB7UTrEXveflCZ1zMEbXcv77a1cSe2dD0jU/gzICIiIrIWDN1swMsz52Duv/6vTtf07NEHy5atQ7Nm4p+Sdwx+WNCWmppi1k3zzcXd3V1wOisAHP8rSYJqjHPwULygLXriVIstt8yrw5JKWxorAc2FJyrGxu5CebnpT4AV23Mp++YNk92/NY77ew0ZPFzQtn37JpSVlWHX7h3V2ps29UXnzl0tVZqoliI/7zNnThp9/cmTx0X3tPIXCVXsiaFDDcSW35tbc/8AfPrJCtHDOs6fTzb54+3bFytoaxFY/cMBWxp39x7qBACJRw5YvA4iIiIiU2HoZgOysq7j8pVLRvUND1dh0YdfYuEHn9e4DCak6yOi7ctXfHZfNUotrK9S0PbTz+uRmlo/Z2Tl5AhnKXTs2Nk8D6YTNt2sQ/hjS2PF3084s+NaRjq2bd9k8scSm0WSeT3TqGtTUs4Z1c/axv292rZtLwhcrmWkY83alYKQYOiQEYI9Di0tMEC4Kf+vm35AZWWlUdf/8utGQZtc7gVXkX0T7Ylc7iV6SMxnX3yoP8XTkjwae2Di+CmCdlPPIj2ceADHjh8RtAcGVv9wwJbGXUCAcEnriRPHcOCg8IMoIiIiImvA0M3KpaScw7jxj2HD92v0bW5ubhjQfwjGPz0Zs15+De+8vRArln+L37fHYf67H6Fnjz61vjn1aOyBvn0Vgvbde/7AwUP7Tf59mJtK1V+0/aNP3jfpkj5TcReZ0ebg6FjrdUeOHhS0lRk4lbOKj8j+XufOn0FxcXGtjwfY1ljpcc+JmVW+XrUEBf87LdBUmjcXziLRxO2p9Y1yeXk5Pv9ykVGPYW3jXszw4aMFbd9vXCto6xc1yBLl1GjgQOHJqVevXsbRpMO1Xpt+7aroPo4jR4wxSW3WTuyQghs3svDtd6tM+jglJSVG/a43chcewFBULJwtdr8qKipEP7hwc3ODUln999qWxl1Il+6i7ctXfAatVmvhaoiIiIgeHEM3K1ZWVob5C96s1vbfBYux9bcYzHvjPTz/3EsYPWoslIp+6NA+GI6OjkZ/8g0AkydNE23/YOHbOHBgX63XX7qUhn+//goWfFC3pa/m8FCHjogIjxS0nzlzEos+no/8gvwar9dqtdi0+UeMfmKQRWYJBYss2Tx8OMFgf51Oh3XfrsJHH78vuO3c+eQa36yIzZIoKirCn7u2G1mt7YwVH5+mmCAyg6WoqAjTp0fjXC3LxwpuFaCw8JZRjyW2SXlqagr2xvxp8Jrbt29j3pv/wIkTx4x6DGsb92LuDRjEdGgfLLqU1tI6tA8WDYc+XPRujT+/axnp+Ne/Zgra3dzcMOaJ8Sat0VoNf3S06JLODd+vwY8/ra81kMkvyMcXSz7GM5OeqHF23Jatv2DkqP5Y9+0q3L5922C/gweFHyiI7W8pJqOWw1muZaRjzmsviY6ZSdHT4HnPISm2NO5atWqDEY89IWi/dCkNr78xu9afXWIil6ISERFR/cLQzYqlpJzFpUtp1drOnDmJ3bt/x/Ydm7Fm7Vd4593XMfX5pxHVvxcGDQlD/4F98MykJ/DmW3Ow4fu1Nb6p6NA+GMOGjhS05+Xl4vV5r+Kdd1/H2XNnqi3zKrhVgDPJp7B02WJMfnYsDh3aj127dhgdEpjTc1NniLbv3LkN4yeMwM6d23D9eqY+mNRqtUi/dhVqzR5MmfoUPv9iEfLycvHlko/NXmu7th0EbYs/WygIsHQ6HS5fvoiFi97F6jXLDd5fTSdwuru7i55mufizhdi0+cdq+5ndvHkDv/y6Efv3a6r1taWxMnbsRLi5uQnar2Wk44UXn8H3G9fhwoXzKCsr09+Wm5uDLVt/wdPjHxOcqGlIyxatRR/n/QX/EbzhLyoqwm9bfsbE6NE4XMc3ldY07sU0dm+MwSJ7u91tyJDHLFRN7cQC6Bs3sjD1+aeh1uyp9jtQUlKCxCMH8dLMKYITGwHghWmz4C4yo8oeubi4YMaLs0VvW7Z8MV6Y/gwSjxys9vtXUlKC1NQUbNr8I8ZPGIFff92Iq1cv4+dfvjf4OFu3/QoAWL1mOcaOG4ZNm3/E5csXodPdWYd/q/AWvvp6iejsMLHl3GJeeHEifvxpPS5fvqj/vSspKcGFC+fx66YfMGHiKNFlpXK5l2ggBdjWuIt+5jnR9sQjBzF+wkj88sv3uHDhvD48LS8vx8mTx/Hp4g/w+rxXLVkqERERUa2EO3mT1RDbE2rdt1/Xet3Vq5dx9eplxMersX7DN3jxhVfw2PDHRfvOevk1XL5yUXTD6lj17mpvPNzc3EQ3YwaAxZ8vxIpl34puHm8prVq1wfx3P8Kbb80R3FZUVIQPPnxH/3VN30vSsUTE7YuBIiLKbLUO6D8E6779SlDD6/NeRatWbdChQ0fcvJGFtIsXjAp5vt+4DnP+OQ8ymUz09knRz4vOkvv8i0X4/ItFcHNzQ8OGzvrHGjhwGMLCqr/BtJWx4tHYA9HPPG9wT7qVX32BlV99AQD60MzQ91ITFxcXzJj+qujPffWa5Vi9ZvkD3X8Vaxr3hgwcMBQ7d24zeLtS0c+C1dSsuX8AnhwzAT/9vF5w29vvzAVw5//E1cUVyWdPG7yfwMCWokG2PRs4cBhSLpzHjz99J7gtNTUFr/1v1lZN4xgAVn2zFAMHDBUcJHT23Jlq+7IVFRXh8y/+Xsotl3vV+HwbESGcVSqmqKgIy5YvxrLli43qX2XGi7Ph4uIiepstjTtvbx9MfXYGVn2zVPT2L5d+ov93bf/XRERERFLjTDcr5u3t88Cb6xcVFeGTT/+LPXt3it7u7OyM995ZhNDQCKPuy5DU1BTBrDwphIer8Oa8+aIzjO5W24v4vXsNLwE0BW9vH/zj1TdEb7t0KQ27du1A0rFEo2dV7fj9N3y/cZ3B24cOGVHjWCoqKqr2WBcuCDfyt6WxMnrUWESqBtTar6io6IHe8A0eNBxBQe3qfP+GTnM0xFrGvSHduvYwWHtoaAS8vX0sXFHNnp3yYo2/B5cupdUYfMjlXnj/vY8l/ZCivnr+uZfw9LhJNfYx5ndyf4JG0LZr1+81XlPT8+2M6a8iMEB4+rGpRD/znOgS0rvZ0rh7csx4hIerau3HwI2IiIjqO4ZuVu6ZCc/W+kbaGPPff9PgXilyuRf++/6neGPuO/f1WEFB7fDfBYvRtm37By3TJPr3G4y1q3826gW9mCcefxqvvvq6iasS6t9vMCZFP1+na+b8cx42/7pL9P/p5CnhDLQqDg4OeOP1d43eFys1NUV0DyVbGSsNGzbEvDfeM/u+Rk5OTnj3nUXo0qWb0dcMHDgMCxd+UefHspZxL8bR0REPdRAPGgcPetTC1dTOxcUF7779IUaPfqrO13bp0g3Ll65Dy5atzVCZ9XNycsK052di6ZerERgo3I+yNnK5F2bO+IfoMk2xkzONMSn6eTw5xjzPFW5ubpj9yr8xZfILtfa1pXHn7OyMt9/6AKNHja3TdWY75ZuIiIjoPkn/cSY9kL59FdiwfgvWr1+N48eP4Gr6ZRQVFUEu90KLFq3Qrm0HtGrVBs187yyjuZ6ViT/+2Cr6affBg/EYNfJJg481cOAwPPJIb6xZuxLHjh+ptgznXnK5F/r0CUekagD69A4zuKwRABo0aChoM7SE5l4NRa51dq79Wh+fppj/7kfYs3cntm3bhHPnz9T4iXnnzl3Ru1cYhg0dUeusGrHHd27oXGtNYiZPmobevfrivwvfNvjzlsu90K/fYDz9VDR8fJoCAFauWI+PPpovui+QIYEBLbB86Tqs/OoLbNr8Y419W7Vqg8LCW6IbmwPmGyuW5OTkhJdmvIohg4fju/XfiO7hdLduXXtg+vTZeG/+vBq/33sFNA/E4k9W4LctP+PrVUsMjsOI8Eg8/vhT6N6tJwDhsqqGRowxaxn3Ytq27YCkY4mC9tA+tc+slEKDBg0wa+YcDB82Ct//sA7796tr/Fl379YTo0Y9CUVElFG/A84iz5FODRo8UM3mYo5aO3bsjK9XbsAPP36H+PjYWg856dtXgfAwJfr3G2Lw78voUWPRv/8Q7NnzB37d9EOtv8cjR4zB0+MmCZap1uaNue9g028/4cyZkwb7NPcPgEo1AGOfnGDweVaMOcedpf9WOzk5YdbLr2HQoEexfv1q7IuPNdi3aVNfPD/1JURFDcLI0f2rfc+ennKjaiQiIiIyB5muandgO3QkNhuardcBAN1VPuihaipxRZaz+LOF+G3Lz9XaHh02CnP+Oc/o+yguLsbFS6m4du0qKrRaNHR2hoeHJ3y8m6JFi1b1Jjwxhk6nQ+b1DFy6mIrbRbehLS+Hp6ccHh6eaNmyTb3YzPzGjSxcSD2P27cL9fX5+vqhTZu2Bn/W2dk3cT7lLG4V5CMwsKXRswBKSkqQmpaCrKxMlJQUw9u7KXy8m8KnqS8auzeuc+22MFZKS0tx4cI5ZOfcRHFREWQODvDw8EQzXz80bdoMjRo1AgA8M+kJwZv1rb/FGD2GcnNzcPXqZWTduI7Kykp4e/ugVcs2ZllCaQ3jvsrvf2zBh4veq9Y2bOhIvDbnTQNX1C9arRbnzicjNycb+QV5cHZ2gaOjIzw95WjbtgM8GntIXaJV02q1uHr1Mi5eSkVFRQV0Oh08PeXw9JQjqE27+1oyeavwFm5kXUdWViaKiotQXlYG32Z+8PX1Q1MfXzRsKAyS7jX6iUGCZam7/zwAR0dHlJaWIj39Ci5fuYiKigpUVlZCLveCv1/z+5rFJ8aWxl1RUREuXDiHnNxs3LpVALncC839A+HvHwBXV1epyzO5Y/E3kbjnBgAgbGhT9BlgP69RiYiIbAlnutmpsWMnCkK31LSUOt2Hq6srOgY/jI7BD5uyNEnIZDL4+zWHv19zqUsxqGlTX9FTRmvi7e1zX2GNi4sLOnXsjE4mWqpjC2PF2dkZnTp1MfvjeHk1gZdXE7M/DmAd476K2GydAQOGSFDJ/XFycjLZ7xMJOTk5oXXrILRuHWSy+2zs3hiN3RvXuO/ig3B2dkZQUDuz3T9gW+POzc2tTkvxiYiIiOoDhm424Gr6Fbg4u+iXFhpDbENoFyOWZRJZ2tZtv+KEyImophQY0BLRz0w162PQ/SsvLxcc9iKXeyGkS/dar+X4qS4nJxvLV35u9sd5+qlotGnT1uyPQ0RERERUnzF0s3IFtwrw8qypyMvLxdPjJuGpsRNr3b8kvyAfy5YvFrSbcoYAkakcOpRQ414+phAU1M5qQhN7U1JSgnfnvyHY/2rY0JFwdHSs9XqOn+pycrKxa9cOsz+OStGPoRsRERER2T2GblZu6dJP9bPWvt+4Ft9vXItJ0dPQu1coWrUK0u8zBdzZKyomdhd++eV7XMtIF9xX374Ki9VNRFST7Oyb2LX7d/zw47eiM3Pr46mlREREREREd2PoZsX279dg55/bBO1r163E2nUrAdw5Ac3F1RWZmddqPcGsV89Qs9VKdL9atmyNwEum2VTckKA25ttTierm9Xmv4sCBfTX2mTB+Clq2bG3U/XH8VNfI3R2tWrVBRUWFWR+HJ0YSERERETF0s2qxmj219hGb0XavoKB2mPfGe7X2I5LC88+9hOefe0nqMshCkpNP1Xh7r56hmDxpmtH3x/FTnb9fc6z55kepyyAiIiIisgsOUhdA9+8fs1/HpOjnH+g+IlUD8OknK+7rhEsiIkuaFD0NC97/FE5O/LyIiIiIiIjqP75zsWIuLi6YPGkaHn98HGJi/sSOHb/h3Plko64dPWosHh/9FAIDzbvsiojoQY0e/RSGDxuFoCDrWcZJRERERETE0M0GeDT2wMgRYzByxBjk5+fh9OkTSLuYitzcHOQX5MHN1Q3NmvnD17cZmvn6oWWrNvBo7CF12UQ2qV/UIFy7dlX/taOjE5ydnSWsyLqMHPEkyspK0ayZH5r5+iEk5BG4ublJXRbRfRk8aDiys2/ov27Y0BkODlxkQERERGQvZDqdTid1EVI5EpsNzdbrAIDuKh/0UDWVuCIiIiIisnfH4m8icc+dwDZsaFP0GcDXqERERNaIH7cSERERERERERGZGEM3IiIiIiIiIiIiE2PoRkREREREREREZGIM3YiIiIiIiIiIiEyMoRsREREREREREZGJMXQjIiIiIiIiIiIyMYZuREREREREREREJsbQjYiIiIiIiIiIyMQYuhEREREREREREZkYQzciIiIiIiIiIiITY+hGRERERERERERkYgzdiIiIiIiIiIiITIyhGxERERERERERkYkxdCMiIiIiIiIiIjIxhm5EREREREREREQmxtCNiIiIiIiIiIjIxBi6ERERERERERERmRhDNyIiIiIiIiIiIhNj6EZERERERERERGRiDN2IiIiIiIiIiIhMjKEbERERERERERGRiTF0IyIiIiIiIiIiMjGGbkRERERERERERCbG0I2IiIiIiIiIiMjEGLoRERERERERERGZGEM3IiIiIiIiIiIiE2PoRkREREREREREZGIM3YiIiIiIiIiIiEyMoRsREREREREREZGJMXQjIiIiIiIiIiIyMYZuREREREREREREJmbXoZujk0z/78oKnYSVEBERERHdoav8+3Wpk5Ndv1wnIiKyanb9V9y1saP+3yW3tRJWQkRERER0R/Gtv1+X3v16lYiIiKyLXYdujdyd9P8uul0hYSVERERERHfcLvw7dGvU2KmGnkRERFSf2XXo1rS5q/7f2enFElZCRERERHRH1pW/X5f6NneRsBIiIiJ6EHYdujm7OsA34M4LmaLbFbhxrUTiioiIiIjInmVnlqD4fyswfPwawtWdM92IiIislV2HbgDQskMj/b/PJOZIWAkRERER2bu7X4+2fMhdwkqIiIjoQdl96NYl1Av43yGm5//KR0FOmbQFEREREZFdul1QjrNJ+fqvu/RpImE1RERE9KDsPnST+zTEQ90aAwB0lcBRzQ2JKyIiIiIie3Qk9gZ0ujv/bt+1MZo0ayhtQURERPRA7D50A4CwIc30s91S/ipAysn8mi8gIiIiIjKhlJP5OHf879egYYObSVgNERERmQJDN9yZ7aYc/vcLm9hfr+Hs0VwJKyIiIiIie3HuWC5if70G/G+WW/iwppzlRkREZAMYuv1Pj0hvhIR56b+O25aJQ7uzJKyIiIiIiGzd4b1Z0GzJ1H/dqacHevdvKmFFREREZCoyna5q5wgCgO3fXsG5Y7f0XwcENULYUD94evPTRiIiIiIyjYKcMuz/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KJGdsYvQ7Z///CdmzJiBJ598Es8++yzX2xNRvePj44MPPvgAgPiyyGHDhmHq1Kl1us9vv/1WtF2hUODVV18V7KWWnJyMd955RxCgbd26FcOHDxedARYbG4uUlBRBe8uWLfHOO++gWbNm1dpzc3Px7rvv4uzZs9XaL1++jJiYGAwcONCo760mFRUV2Llzp6C9devWmDt3Llq2bKlvKysrw44dO7By5UoAQO/evR/48YmI6P/Zu/OwKuv8/+OvAyiL6EEQc0FcMheS1IamKdO0NJdwyWUyzK1cpnKaNpv4fptmamyYyr7WlFZj5mRGjS1upGZRtpmFaYWhueJ+XFAQBQ4e5feHP4/gOQdBb7jPDc/HdXV1n8/9ue/7fTyXCC8+C1Cz1a1bV927d1f37t1VUlKiX375xT0Kbtu2bWX65ufna8WKFVqxYoWCgoLUtWtX3XjjjerZs6eaNGli0jsAUF1qzFZtWVlZev31172e69Kli5YtW6YHH3yQwA1ArbB161atXLnSo/22227To48+6nXzgg4dOujFF19U8+bNPc7Nnz/fo62wsNDr192rrrpKzz33nEfgJkkNGzZUSve0uMYAACAASURBVEqKunfv7nHujTfeKDNV42IdP37ca/v9999fJnCTznzTPGTIEM2fP18jRozQVVdddcnPBwAAtYfNZlOnTp1033336b///a/S0tL08MMPKyEhwWP0vMvlUkZGhqZPn67ExETdfvvtmjlzpjIzM32uFwfA2iwfum3atEkPPPCAxowZo1dffdXjNwtnRUREVHNlAGCe1157zaOtefPmuuuuu8qdPtm4cWONGTPGo/2rr77yGJ22cOFCr9NKx40bV+7mCyEhIZo4caJHe15enpYtW+bzuoryteNqbm6uz2siIyM1fvz4C+6kCgAAUJ4mTZrojjvu0Kuvvqr09HRNmzZNffr08TqtdNu2bZo7d67Gjx+vvn376qmnntKqVasM+SUkAP9g2dDtbNh255136uuvv3a3X2g3OwCo6Y4ePapffvnFo33EiBEVWq/suuuu8zoqeOPGjWVef/nllx59unXrpkaNGl3wGY0aNdKNN97o0f7zzz9f8NoLqV+/vtf6P//8c36LDAAAqk14eLj69eunlJQUrVq1SjNnztTvf/97r9NKjxw5oiVLluiRRx7RDTfcoPvvv19LliwxoWoA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duFp94fgQV6wrcKMGxERWSZbWyu8NLAe8P+XuoQr2bh5PVveoMhiXL34ACk3n/TssLYGXnq9HqxtZA6KiIhIYlZWQNfXPGHz/7mDjLTHiDx1v5S1TBuTbmQQZ47cU/3s16wGarvbyxgNERGR4TnVropnWjqpXkcc5thuJI1zR5/Wq5q2roXqNTiGGxERWSa7ajZo2dFF9frcMSbdiDQUFQLxV54+3W/WhtPXExFR5aB+zUu8moMCJSeJp4p5lFeI5Lhc1evm7VmvIiIiy9asdS3V0FT37z7Cw4zH8gZUAUy6keRuxWXjUd6TjtfVqtugjmc1mSMiIiIyDuc6dqju9KQVUmFBERKusYspVUxs9APVz6517eDgyFZuRERk2arYWcPT9+nYbtejsnQsbdrM9qo9dOhQZGU92fF2dnYyR0Pq7iY9nU3W99kaMkZCRERkfP7NnHDhxJPugHeTcuDXxLGUNYi0U69X+TSpKWMkRERExlO/aQ0kxT55eHk3KbeUpU2XWSfdyDRlZylVP7vUZSs3IiKqXGrXfTqOaU5WgYyRkCXIUatXqR9bRERElqy2+9NcgnqOwdyweylJLufh0z8IO3tOrUVERJWLXbWn1z5zriSSachWS9zaV2O9ioiIKge7ak/TVeb8EJNJN5Jcft7TP4gqdjzEiIiocqmqdu3LzzHfSiKZhke5avWqqqxXERFR5aDegCcvx3wfYvLKTdJTm6itiJO2ERFRpWOl+onXQZJSUaHcERARERlHkYXkFZh0IyIiIiIiIiIikpjZTqQQFhaGe/eezAy2cOFCVK9evZQ1iIiIiIiIiIiIjMNsk26RkZFISUkBACiV5tu/l4iIiIiIiIiILA+7lxIREREREREREUmMSTciIiIiIiIiIiKJMelGREREREREREQkMSbdiIiIiIiIiIiIJGa2EynMmzcP+fn5AAAnJyeZoyEiIiIiIiIiInrKbJNuAQEBcodAREREREREREQkit1LiYiIiIiIiIiIJMakGxERERERERERkcSYdCMiIiIiIiIiIpIYk25EREREREREREQSM9uJFHr37o2UlBQAwMGDBzmDKRERERERERERmQy2dCMiIiIiIiIiIpIYk25EREREREREREQSY9KNiIiIiIiIiIhIYky6ERERERERERERSYxJNyIiIiIiIiIiIomZ7eylu3fvljsEIiIiIiIiIiIiUWzpRkREREREREREJDEm3YiIiIiIiIiIiCTGpBsREREREREREZHEmHQjIiIiIiIiIiKSGJNuREREREREREREEjPb2Ut79+6NlJQUAMDBgwfh5OQkc0RERERERERERERPsKUbERERERERERGRxJh0IyIiIiIiIiIikhiTbkRERERERERERBJj0o2IiIiIiIiIiEhiZjuRQkBAADw8PAAAtrZm+zWIiIiIiIiIiMgCmW22at68eXKHQEREREREREREJIrdS4mIiIiIiIiIiCTGpBsREREREREREZHEmHQjIiIiIiIiIiKSGJNuREREREREREREEjPbiRQiIyORn58PAAgKCpI5GiIiIiIiIiIioqfMNukWFhaGlJQUAMDBgwfh5OQkc0RERERERESmLTc3F8ePH4KyQInng9rBxcVV7pCIZFdQUICIM6eRnJyE5gHPoUGDhnKHRBbCbJNuREREREREpL/ExHi8PXEkcnJyVGUfh32ObsE9ZYyKSF5KpRJjxw1FQkKcqqxvn9cwfdpHMkZFloJjuhERGUFhYaHcIRAREVEl99ffOzUSbgDw0+Z1KCoq0nsbrNOQKarIcfnff//TSLgBwM5dvyItLbWiYREx6UZEZEhxcTewavUS9On3Is6e+0/ucIiIiKgSOydSF0lIiENmZkap67JOQ6ZIiuMyMuqCaPn99HsVCY0IALuXEhEZRMSZ01i7djlirlxWleXn5ckYEREREVV2nTsH4+q1GI2ygICWUCicta7DOg2ZIimPy/btOmHLzxsE5R51vcodH1Exs026DR06FFlZWQAAOzs7maMhItJ0+vRJjUoAERERkdx6dH8FB//Zg9jY6wAAhcIZI4aP1bkO6zRkiqQ8Lps1a4EunYNx+MgBVdm4kMlwdHSUZPtUuZl10o2IiIiIiIj0U7u2C9aGb0FU1AU8eJCJ559vhypVqsgdFpHsPps5D2NuTcCVK5cRFNQWTjWd5A6JLITZJt2IiIiIiIio7Jo1ayF3CEQmx8uzHrw868kdBlkYTqRAJLFdu3dg8ZL5UCqVcodCRERERERERDJhSzciPTzIeoDEhDjEJ8QiNu4Gsh5kQqGoBQ8PT9St64mWLVrB3t4e/0WcwoKF8wAAqal38cmMuXqPOVhYWIhr16/gwoWzSEtLRUZmOhyqOcDbuz7q1fOBp2c9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", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "from IPython.display import Image, display\n", - "\n", - "display(Image(graph.get_graph().draw_mermaid_png()))" - ] - }, - { - "cell_type": "markdown", - "id": "eb655cfb-d4e4-4f6a-8a0d-01e8611b18ab", - "metadata": {}, - "source": [ - "## 8. Run the agentic RAG" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "id": "7649f05a-cb67-490d-b24a-74d41895139a", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Update from node generate_query_or_respond\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "Tool Calls:\n", - " retrieve_blog_posts (call_NYu2vq4km9nNNEFqJwefWKu1)\n", - " Call ID: call_NYu2vq4km9nNNEFqJwefWKu1\n", - " Args:\n", - " query: types of reward hacking\n", - "\n", - "\n", - "\n", - "Update from node retrieve\n", - "=================================\u001b[1m Tool Message \u001b[0m=================================\n", - "Name: retrieve_blog_posts\n", - "\n", - "(Note: Some work defines reward tampering as a distinct category of misalignment behavior from reward hacking. But I consider reward hacking as a broader concept here.)\n", - "At a high level, reward hacking can be categorized into two types: environment or goal misspecification, and reward tampering.\n", - "\n", - "Why does Reward Hacking Exist?#\n", - "\n", - "Pan et al. (2022) investigated reward hacking as a function of agent capabilities, including (1) model size, (2) action space resolution, (3) observation space noise, and (4) training time. They also proposed a taxonomy of three types of misspecified proxy rewards:\n", - "\n", - "Let’s Define Reward Hacking#\n", - "Reward shaping in RL is challenging. Reward hacking occurs when an RL agent exploits flaws or ambiguities in the reward function to obtain high rewards without genuinely learning the intended behaviors or completing the task as designed. In recent years, several related concepts have been proposed, all referring to some form of reward hacking:\n", - "\n", - "\n", - "\n", - "Update from node generate_answer\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "\n", - "Lilian Weng categorizes reward hacking into two types: environment or goal misspecification, and reward tampering. She considers reward hacking as a broad concept that includes both of these categories. Reward hacking occurs when an agent exploits flaws or ambiguities in the reward function to achieve high rewards without performing the intended behaviors.\n", - "\n", - "\n", - "\n" - ] - } - ], - "source": [ - "for chunk in graph.stream(\n", - " {\n", - " \"messages\": [\n", - " {\n", - " \"role\": \"user\",\n", - " \"content\": \"What does Lilian Weng say about types of reward hacking?\",\n", - " }\n", - " ]\n", - " }\n", - "):\n", - " for node, update in chunk.items():\n", - " print(\"Update from node\", node)\n", - " update[\"messages\"][-1].pretty_print()\n", - " print(\"\\n\\n\")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.3" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/docs/docs/tutorials/rag/langgraph_agentic_rag.md b/docs/docs/tutorials/rag/langgraph_agentic_rag.md new file mode 100644 index 000000000..2aae24820 --- /dev/null +++ b/docs/docs/tutorials/rag/langgraph_agentic_rag.md @@ -0,0 +1,522 @@ +# Agentic RAG + +In this tutorial we will build a [retrieval agent](https://python.langchain.com/docs/tutorials/qa_chat_history). Retrieval agents are useful when you want an LLM to make a decision about whether to retrieve context from a vectorstore or respond to the user directly. + +By the end of the tutorial we will have done the following: + +1. Fetch and preprocess documents that will be used for retrieval. +2. Index those documents for semantic search and create a retriever tool for the agent. +3. Build an agentic RAG system that can decide when to use the retriever tool. + +![Screenshot 2024-02-14 at 3.43.58 PM.png](assets/screenshot_2024_02_14_3_43_58_pm.png) + +## Setup + +Let's download the required packages and set our API keys: + +```python +%%capture --no-stderr +%pip install -U --quiet langgraph "langchain[openai]" langchain-community langchain-text-splitters +``` + +```python +import getpass +import os + + +def _set_env(key: str): + if key not in os.environ: + os.environ[key] = getpass.getpass(f"{key}:") + + +_set_env("OPENAI_API_KEY") +``` + +!!! tip + Sign up for LangSmith to quickly spot issues and improve the performance of your LangGraph projects. [LangSmith](https://docs.smith.langchain.com) lets you use trace data to debug, test, and monitor your LLM apps built with LangGraph. + + +## 1. Preprocess documents + +1. Fetch documents to use in our RAG system. We will use three of the most recent pages from [Lilian Weng's excellent blog](https://lilianweng.github.io/). We'll start by fetching the content of the pages using `WebBaseLoader` utility: + + ```python + from langchain_community.document_loaders import WebBaseLoader + + urls = [ + "https://lilianweng.github.io/posts/2024-11-28-reward-hacking/", + "https://lilianweng.github.io/posts/2024-07-07-hallucination/", + "https://lilianweng.github.io/posts/2024-04-12-diffusion-video/", + ] + + docs = [WebBaseLoader(url).load() for url in urls] + ``` + + ```python + docs[0][0].page_content.strip()[:1000] + ``` + +2. Split the fetched documents into smaller chunks for indexing into our vectorstore: + + ```python + from langchain_text_splitters import RecursiveCharacterTextSplitter + + docs_list = [item for sublist in docs for item in sublist] + + text_splitter = RecursiveCharacterTextSplitter.from_tiktoken_encoder( + chunk_size=100, chunk_overlap=50 + ) + doc_splits = text_splitter.split_documents(docs_list) + ``` + + ```python + doc_splits[0].page_content.strip() + ``` + +## 2. Create a retriever tool + +Now that we have our split documents, we can index them into a vector store that we'll use for semantic search. + +1. Use an in-memory vector store and OpenAI embeddings: + + ```python + from langchain_core.vectorstores import InMemoryVectorStore + from langchain_openai import OpenAIEmbeddings + + vectorstore = InMemoryVectorStore.from_documents( + documents=doc_splits, embedding=OpenAIEmbeddings() + ) + retriever = vectorstore.as_retriever() + ``` + +2. Create a retriever tool using LangChain's prebuilt `create_retriever_tool`: + + ```python + from langchain.tools.retriever import create_retriever_tool + + retriever_tool = create_retriever_tool( + retriever, + "retrieve_blog_posts", + "Search and return information about Lilian Weng blog posts.", + ) + ``` + +3. Test the tool: + + ```python + retriever_tool.invoke({"query": "types of reward hacking"}) + ``` + +## 3. Generate query + +Now we will start building components ([nodes](../../concepts/low_level.md#nodes) and [edges](../../concepts/low_level.md#edges)) for our agentic RAG graph. Note that the components will operate on the [`MessagesState`](../../concepts/low_level.md#messagesstate) — graph state that contains a `messages` key with a list of [chat messages](https://python.langchain.com/docs/concepts/messages/). + +1. Build a `generate_query_or_respond` node. It will call an LLM to generate a response based on the current graph state (list of messages). Given the input messages, it will decide to retrieve using the retriever tool, or respond directly to the user. Note that we're giving the chat model access to the `retriever_tool` we created earlier via `.bind_tools`: + + ```python + from langgraph.graph import MessagesState + from langchain.chat_models import init_chat_model + + response_model = init_chat_model("openai:gpt-4.1", temperature=0) + + + def generate_query_or_respond(state: MessagesState): + """Call the model to generate a response based on the current state. Given + the question, it will decide to retrieve using the retriever tool, or simply respond to the user. + """ + response = ( + response_model + # highlight-next-line + .bind_tools([retriever_tool]).invoke(state["messages"]) + ) + return {"messages": [response]} + ``` + +2. Try it on a random input: + + ```python + input = {"messages": [{"role": "user", "content": "hello!"}]} + generate_query_or_respond(input)["messages"][-1].pretty_print() + ``` + + **Output:** + ``` + ================================== Ai Message ================================== + + Hello! How can I help you today? + ``` + +3. Ask a question that requires semantic search: + + ```python + input = { + "messages": [ + { + "role": "user", + "content": "What does Lilian Weng say about types of reward hacking?", + } + ] + } + generate_query_or_respond(input)["messages"][-1].pretty_print() + ``` + + **Output:** + ``` + ================================== Ai Message ================================== + Tool Calls: + retrieve_blog_posts (call_tYQxgfIlnQUDMdtAhdbXNwIM) + Call ID: call_tYQxgfIlnQUDMdtAhdbXNwIM + Args: + query: types of reward hacking + ``` + +## 4. Grade documents + +1. Add a [conditional edge](../../concepts/low_level.md#conditional-edges) — `grade_documents` — to determine whether the retrieved documents are relevant to the question. We will use a model with a structured output schema `GradeDocuments` for document grading. The `grade_documents` function will return the name of the node to go to based on the grading decision (`generate_answer` or `rewrite_question`): + + ```python + from pydantic import BaseModel, Field + from typing import Literal + + GRADE_PROMPT = ( + "You are a grader assessing relevance of a retrieved document to a user question. \n " + "Here is the retrieved document: \n\n {context} \n\n" + "Here is the user question: {question} \n" + "If the document contains keyword(s) or semantic meaning related to the user question, grade it as relevant. \n" + "Give a binary score 'yes' or 'no' score to indicate whether the document is relevant to the question." + ) + + + # highlight-next-line + class GradeDocuments(BaseModel): + """Grade documents using a binary score for relevance check.""" + + binary_score: str = Field( + description="Relevance score: 'yes' if relevant, or 'no' if not relevant" + ) + + + grader_model = init_chat_model("openai:gpt-4.1", temperature=0) + + + def grade_documents( + state: MessagesState, + ) -> Literal["generate_answer", "rewrite_question"]: + """Determine whether the retrieved documents are relevant to the question.""" + question = state["messages"][0].content + context = state["messages"][-1].content + + prompt = GRADE_PROMPT.format(question=question, context=context) + response = ( + grader_model + # highlight-next-line + .with_structured_output(GradeDocuments).invoke( + [{"role": "user", "content": prompt}] + ) + ) + score = response.binary_score + + if score == "yes": + return "generate_answer" + else: + return "rewrite_question" + ``` + +2. Run this with irrelevant documents in the tool response: + + ```python + from langchain_core.messages import convert_to_messages + + input = { + "messages": convert_to_messages( + [ + { + "role": "user", + "content": "What does Lilian Weng say about types of reward hacking?", + }, + { + "role": "assistant", + "content": "", + "tool_calls": [ + { + "id": "1", + "name": "retrieve_blog_posts", + "args": {"query": "types of reward hacking"}, + } + ], + }, + {"role": "tool", "content": "meow", "tool_call_id": "1"}, + ] + ) + } + grade_documents(input) + ``` + +3. Confirm that the relevant documents are classified as such: + + ```python + input = { + "messages": convert_to_messages( + [ + { + "role": "user", + "content": "What does Lilian Weng say about types of reward hacking?", + }, + { + "role": "assistant", + "content": "", + "tool_calls": [ + { + "id": "1", + "name": "retrieve_blog_posts", + "args": {"query": "types of reward hacking"}, + } + ], + }, + { + "role": "tool", + "content": "reward hacking can be categorized into two types: environment or goal misspecification, and reward tampering", + "tool_call_id": "1", + }, + ] + ) + } + grade_documents(input) + ``` + +## 5. Rewrite question + +1. Build the `rewrite_question` node. The retriever tool can return potentially irrelevant documents, which indicates a need to improve the original user question. To do so, we will call the `rewrite_question` node: + + ```python + REWRITE_PROMPT = ( + "Look at the input and try to reason about the underlying semantic intent / meaning.\n" + "Here is the initial question:" + "\n ------- \n" + "{question}" + "\n ------- \n" + "Formulate an improved question:" + ) + + + def rewrite_question(state: MessagesState): + """Rewrite the original user question.""" + messages = state["messages"] + question = messages[0].content + prompt = REWRITE_PROMPT.format(question=question) + response = response_model.invoke([{"role": "user", "content": prompt}]) + return {"messages": [{"role": "user", "content": response.content}]} + ``` + +2. Try it out: + + ```python + input = { + "messages": convert_to_messages( + [ + { + "role": "user", + "content": "What does Lilian Weng say about types of reward hacking?", + }, + { + "role": "assistant", + "content": "", + "tool_calls": [ + { + "id": "1", + "name": "retrieve_blog_posts", + "args": {"query": "types of reward hacking"}, + } + ], + }, + {"role": "tool", "content": "meow", "tool_call_id": "1"}, + ] + ) + } + + response = rewrite_question(input) + print(response["messages"][-1]["content"]) + ``` + + **Output:** + ``` + What are the different types of reward hacking described by Lilian Weng, and how does she explain them? + ``` + +## 6. Generate an answer + +1. Build `generate_answer` node: if we pass the grader checks, we can generate the final answer based on the original question and the retrieved context: + + ```python + GENERATE_PROMPT = ( + "You are an assistant for question-answering tasks. " + "Use the following pieces of retrieved context to answer the question. " + "If you don't know the answer, just say that you don't know. " + "Use three sentences maximum and keep the answer concise.\n" + "Question: {question} \n" + "Context: {context}" + ) + + + def generate_answer(state: MessagesState): + """Generate an answer.""" + question = state["messages"][0].content + context = state["messages"][-1].content + prompt = GENERATE_PROMPT.format(question=question, context=context) + response = response_model.invoke([{"role": "user", "content": prompt}]) + return {"messages": [response]} + ``` + +2. Try it: + + ```python + input = { + "messages": convert_to_messages( + [ + { + "role": "user", + "content": "What does Lilian Weng say about types of reward hacking?", + }, + { + "role": "assistant", + "content": "", + "tool_calls": [ + { + "id": "1", + "name": "retrieve_blog_posts", + "args": {"query": "types of reward hacking"}, + } + ], + }, + { + "role": "tool", + "content": "reward hacking can be categorized into two types: environment or goal misspecification, and reward tampering", + "tool_call_id": "1", + }, + ] + ) + } + + response = generate_answer(input) + response["messages"][-1].pretty_print() + ``` + + **Output:** + ``` + ================================== Ai Message ================================== + + Lilian Weng categorizes reward hacking into two types: environment or goal misspecification, and reward tampering. She considers reward hacking as a broad concept that includes both of these categories. Reward hacking occurs when an agent exploits flaws or ambiguities in the reward function to achieve high rewards without performing the intended behaviors. + ``` + +## 7. Assemble the graph + +* Start with a `generate_query_or_respond` and determine if we need to call `retriever_tool` +* Route to next step using `tools_condition`: + * If `generate_query_or_respond` returned `tool_calls`, call `retriever_tool` to retrieve context + * Otherwise, respond directly to the user +* Grade retrieved document content for relevance to the question (`grade_documents`) and route to next step: + * If not relevant, rewrite the question using `rewrite_question` and then call `generate_query_or_respond` again + * If relevant, proceed to `generate_answer` and generate final response using the `ToolMessage` with the retrieved document context + +```python +from langgraph.graph import StateGraph, START, END +from langgraph.prebuilt import ToolNode +from langgraph.prebuilt import tools_condition + +workflow = StateGraph(MessagesState) + +# Define the nodes we will cycle between +workflow.add_node(generate_query_or_respond) +workflow.add_node("retrieve", ToolNode([retriever_tool])) +workflow.add_node(rewrite_question) +workflow.add_node(generate_answer) + +workflow.add_edge(START, "generate_query_or_respond") + +# Decide whether to retrieve +workflow.add_conditional_edges( + "generate_query_or_respond", + # Assess LLM decision (call `retriever_tool` tool or respond to the user) + tools_condition, + { + # Translate the condition outputs to nodes in our graph + "tools": "retrieve", + END: END, + }, +) + +# Edges taken after the `action` node is called. +workflow.add_conditional_edges( + "retrieve", + # Assess agent decision + grade_documents, +) +workflow.add_edge("generate_answer", END) +workflow.add_edge("rewrite_question", "generate_query_or_respond") + +# Compile +graph = workflow.compile() +``` + +Visualize the graph: + +```python +from IPython.display import Image, display + +display(Image(graph.get_graph().draw_mermaid_png())) +``` + +![Graph](assets/agentic-rag-output.png) + +## 8. Run the agentic RAG + +```python +for chunk in graph.stream( + { + "messages": [ + { + "role": "user", + "content": "What does Lilian Weng say about types of reward hacking?", + } + ] + } +): + for node, update in chunk.items(): + print("Update from node", node) + update["messages"][-1].pretty_print() + print("\n\n") +``` + +**Output:** +``` +Update from node generate_query_or_respond +================================== Ai Message ================================== +Tool Calls: + retrieve_blog_posts (call_NYu2vq4km9nNNEFqJwefWKu1) + Call ID: call_NYu2vq4km9nNNEFqJwefWKu1 + Args: + query: types of reward hacking + + + +Update from node retrieve +================================= Tool Message ================================== +Name: retrieve_blog_posts + +(Note: Some work defines reward tampering as a distinct category of misalignment behavior from reward hacking. But I consider reward hacking as a broader concept here.) +At a high level, reward hacking can be categorized into two types: environment or goal misspecification, and reward tampering. + +Why does Reward Hacking Exist?# + +Pan et al. (2022) investigated reward hacking as a function of agent capabilities, including (1) model size, (2) action space resolution, (3) observation space noise, and (4) training time. They also proposed a taxonomy of three types of misspecified proxy rewards: + +Let's Define Reward Hacking# +Reward shaping in RL is challenging. Reward hacking occurs when an RL agent exploits flaws or ambiguities in the reward function to obtain high rewards without genuinely learning the intended behaviors or completing the task as designed. In recent years, several related concepts have been proposed, all referring to some form of reward hacking: + + + +Update from node generate_answer +================================== Ai Message ================================== + +Lilian Weng categorizes reward hacking into two types: environment or goal misspecification, and reward tampering. She considers reward hacking as a broad concept that includes both of these categories. Reward hacking occurs when an agent exploits flaws or ambiguities in the reward function to achieve high rewards without performing the intended behaviors. +``` \ No newline at end of file diff --git a/docs/docs/tutorials/sql/output.png b/docs/docs/tutorials/sql/output.png new file mode 100644 index 0000000000000000000000000000000000000000..006d100aad6a03be8929fe5af5806217e83f79e7 GIT binary patch literal 20460 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

dB z@eWr8KSpdes{L1S@t;Q%b2&2aZtC%j(f&^<=N`}W{>Sm;v}}~~iygUNDrpyLGbais z(F#XdLrt#bwvjr~v9KLcxhBP&SB!9|;;_GX(kYo63TA9I(OSET5w~{VhjGkT=9s(gD zO-+dr&qKg!AM|Hb&i+`2PPAO zYPg3CiaP^r7Sc#u$S`AWtEfF7t=hPD8wl?+up zURzeyw%AQ%+A~qDSp{ngZ@j+XMLbCQo;cnn5Yod!drC@5!p! z?tY`=AotFxzYcoVYw)F_jh}&1vhnzNV3mR z0*Jxuw0Tei^dW5#p$>11HB`nwiJl9ZZ(D>L4-}^}7`arV6#KW8l%GL(nzsE~N?34gy@TCRB;K-6Rn1^Uxtyq_&DPQ_ zhFyaT!;5OqEic;L!Y(!vf(pZNgD5cgv)g55miV5$Fbhi9+X`;>vjGji#(`+aIW9{@aU|mg9hPFd%z-|Dw|82#eOIFC5Ii zxR(NXdgW3|=puCc&HN_b<^*y`_vE{$^D9`+r~*H%>->Gn6Jx1J?nDzVqpDRIzvE#) zYZ$A zL?2lFB#PEFqm2~fXRc~%^pHg&AKj?LuCDtVyiM?Ie`VxjfbN72RX-7~S9h&~cWGef zm(x6dAuTg-LJ)Rg?CqXcAHGiZKXFN~&UvX+6+Mx^f4!w!K5VC3sqC0_(0KVj@s2DD zi}~IT)*Ykz-)1HG_-B(sd*_X#ePvDl!(REzc0>x5YcNmXG-t`y2Zg zp7R-Dpf`lu=i%x)fTKiE0}zYqvLV-<;^_5}Mp z{*F8o^ssl`7^$g)3p{Y}`zv|qp)wyVAd5lu5~k@{f7u+3E_Usx{gxDr+lgl~q_vlH%60l9rGZfK?v=|0-Oo#N@(6uPOD*WHbHC9F-jUacM=@P0jdB{+vB zE~92fZ`Ra&3xgv*4zFp?CK^-+FCXqOKq56&R8EtP!9|cdn2Hn9PK>k566~!JO2FU% zrc}iZS%2^*oVII@t_+^s%8O+BcaY-a<2|2VEBAZ#RS9#X^2wR0t~z91;A&j9@2y<_ zI~GT8-acD)$>L5(**zTP!$UZ-4lr#yTwD)TthaY{O}-v+H{~EodLN|~ z_}8=0115!G^QQjKr2ZYh!6uZ2+TP21F`q*|)@kQEvECH;V3~NgyFb*p_L;bkB*5`T z=GiT_cK9tz^`14fyyRpGfHQWkstF2vCBk~_m9I-;rev7fJ_ZJ2M-GNhFENWLmI${@ z4Ar>$`e-~Ejfd5f9ORR_yPb#7d5x`$@s3s3$!Jw~469urNRs>Oe^LYJXJ~a}lXk!0 zs*jOuitL3|gY4%^6$kJr2ZXNyVdoeL6jB7Pjfwl>l6U!WH6YTLz0hVoHTGzt@l^h! zP-1YWPh7Ie$V>BcmKs{>N$q-gEB^V->}K3-P*b8wl;7<`bKTP%J|w}`fU?)JJZ>g5 z7;aTgRMlo@WTbNYRQQtt9f`QOUn literal 0 HcmV?d00001 diff --git a/docs/docs/tutorials/sql/sql-agent.md b/docs/docs/tutorials/sql/sql-agent.md new file mode 100644 index 000000000..84782d371 --- /dev/null +++ b/docs/docs/tutorials/sql/sql-agent.md @@ -0,0 +1,549 @@ +# Build a SQL agent + +In this tutorial, we will walk through how to build an agent that can answer questions about a SQL database. + +At a high level, the agent will: + +1. Fetch the available tables from the database +2. Decide which tables are relevant to the question +3. Fetch the schemas for the relevant tables +4. Generate a query based on the question and information from the schemas +5. Double-check the query for common mistakes using an LLM +6. Execute the query and return the results +7. Correct mistakes surfaced by the database engine until the query is successful +8. Formulate a response based on the results + +!!! warning "Security note" + Building Q&A systems of SQL databases requires executing model-generated SQL queries. There are inherent risks in doing this. Make sure that your database connection permissions are always scoped as narrowly as possible for your agent's needs. This will mitigate though not eliminate the risks of building a model-driven system. + +## 1. Setup + +Let's first install some dependencies. This tutorial uses SQL database and tool abstractions from [langchain-community](https://python.langchain.com/docs/concepts/architecture/#langchain-community). We will also require a LangChain [chat model](https://python.langchain.com/docs/concepts/chat_models/). + +```python +%%capture --no-stderr +%pip install -U langgraph langchain_community "langchain[openai]" +``` + +!!! tip + Sign up for LangSmith to quickly spot issues and improve the performance of your LangGraph projects. [LangSmith](https://docs.smith.langchain.com) lets you use trace data to debug, test, and monitor your LLM apps built with LangGraph. + +### Select a LLM + +First we [initialize our LLM](https://python.langchain.com/docs/how_to/chat_models_universal_init/). Any model supporting [tool-calling](https://python.langchain.com/docs/integrations/chat/#featured-providers) should work. We use OpenAI below. + +```python +from langchain.chat_models import init_chat_model + +llm = init_chat_model("openai:gpt-4.1") +``` + +### Configure the database + +We will be creating a SQLite database for this tutorial. SQLite is a lightweight database that is easy to set up and use. We will be loading the `chinook` database, which is a sample database that represents a digital media store. +Find more information about the database [here](https://www.sqlitetutorial.net/sqlite-sample-database/). + +For convenience, we have hosted the database (`Chinook.db`) on a public GCS bucket. + +```python +import requests + +url = "https://storage.googleapis.com/benchmarks-artifacts/chinook/Chinook.db" + +response = requests.get(url) + +if response.status_code == 200: + # Open a local file in binary write mode + with open("Chinook.db", "wb") as file: + # Write the content of the response (the file) to the local file + file.write(response.content) + print("File downloaded and saved as Chinook.db") +else: + print(f"Failed to download the file. Status code: {response.status_code}") +``` + +We will use a handy SQL database wrapper available in the `langchain_community` package to interact with the database. The wrapper provides a simple interface to execute SQL queries and fetch results: + +```python +from langchain_community.utilities import SQLDatabase + +db = SQLDatabase.from_uri("sqlite:///Chinook.db") + +print(f"Dialect: {db.dialect}") +print(f"Available tables: {db.get_usable_table_names()}") +print(f'Sample output: {db.run("SELECT * FROM Artist LIMIT 5;")}') +``` + +**Output:** +``` +Dialect: sqlite +Available tables: ['Album', 'Artist', 'Customer', 'Employee', 'Genre', 'Invoice', 'InvoiceLine', 'MediaType', 'Playlist', 'PlaylistTrack', 'Track'] +Sample output: [(1, 'AC/DC'), (2, 'Accept'), (3, 'Aerosmith'), (4, 'Alanis Morissette'), (5, 'Alice In Chains')] +``` + +### Tools for database interactions + +`langchain-community` implements some built-in tools for interacting with our `SQLDatabase`, including tools for listing tables, reading table schemas, and checking and running queries: + +```python +from langchain_community.agent_toolkits import SQLDatabaseToolkit + +toolkit = SQLDatabaseToolkit(db=db, llm=llm) + +tools = toolkit.get_tools() + +for tool in tools: + print(f"{tool.name}: {tool.description}\n") +``` + +**Output:** +``` +sql_db_query: Input to this tool is a detailed and correct SQL query, output is a result from the database. If the query is not correct, an error message will be returned. If an error is returned, rewrite the query, check the query, and try again. If you encounter an issue with Unknown column 'xxxx' in 'field list', use sql_db_schema to query the correct table fields. + +sql_db_schema: Input to this tool is a comma-separated list of tables, output is the schema and sample rows for those tables. Be sure that the tables actually exist by calling sql_db_list_tables first! Example Input: table1, table2, table3 + +sql_db_list_tables: Input is an empty string, output is a comma-separated list of tables in the database. + +sql_db_query_checker: Use this tool to double check if your query is correct before executing it. Always use this tool before executing a query with sql_db_query! + +``` + +## 2. Using a prebuilt agent + +Given these tools, we can initialize a pre-built agent in a single line. To customize our agents behavior, we write a descriptive system prompt. + +```python +from langgraph.prebuilt import create_react_agent + +system_prompt = """ +You are an agent designed to interact with a SQL database. +Given an input question, create a syntactically correct {dialect} query to run, +then look at the results of the query and return the answer. Unless the user +specifies a specific number of examples they wish to obtain, always limit your +query to at most {top_k} results. + +You can order the results by a relevant column to return the most interesting +examples in the database. Never query for all the columns from a specific table, +only ask for the relevant columns given the question. + +You MUST double check your query before executing it. If you get an error while +executing a query, rewrite the query and try again. + +DO NOT make any DML statements (INSERT, UPDATE, DELETE, DROP etc.) to the +database. + +To start you should ALWAYS look at the tables in the database to see what you +can query. Do NOT skip this step. + +Then you should query the schema of the most relevant tables. +""".format( + dialect=db.dialect, + top_k=5, +) + +agent = create_react_agent( + llm, + tools, + prompt=system_prompt, +) +``` + +!!! note + This system prompt includes a number of instructions, such as always running specific tools before or after others. In the [next section](#3-customizing-the-agent), we will enforce these behaviors through the graph's structure, providing us a greater degree of control and allowing us to simplify the prompt. + +Let's run this agent on a sample query and observe its behavior: + +```python +question = "Which genre on average has the longest tracks?" + +for step in agent.stream( + {"messages": [{"role": "user", "content": question}]}, + stream_mode="values", +): + step["messages"][-1].pretty_print() +``` + +**Output:** +``` +================================ Human Message ================================= + +Which genre on average has the longest tracks? +================================== Ai Message ================================== +Tool Calls: + sql_db_list_tables (call_d8lCgywSroCgpVl558nmXKwA) + Call ID: call_d8lCgywSroCgpVl558nmXKwA + Args: +================================= Tool Message ================================= +Name: sql_db_list_tables + +Album, Artist, Customer, Employee, Genre, Invoice, InvoiceLine, MediaType, Playlist, PlaylistTrack, Track +================================== Ai Message ================================== +Tool Calls: + sql_db_schema (call_nNf6IIUcwMYLIkE0l6uWkZHe) + Call ID: call_nNf6IIUcwMYLIkE0l6uWkZHe + Args: + table_names: Genre, Track +================================= Tool Message ================================= +Name: sql_db_schema + + +CREATE TABLE "Genre" ( + "GenreId" INTEGER NOT NULL, + "Name" NVARCHAR(120), + PRIMARY KEY ("GenreId") +) + +/* +3 rows from Genre table: +GenreId Name +1 Rock +2 Jazz +3 Metal +*/ + + +CREATE TABLE "Track" ( + "TrackId" INTEGER NOT NULL, + "Name" NVARCHAR(200) NOT NULL, + "AlbumId" INTEGER, + "MediaTypeId" INTEGER NOT NULL, + "GenreId" INTEGER, + "Composer" NVARCHAR(220), + "Milliseconds" INTEGER NOT NULL, + "Bytes" INTEGER, + "UnitPrice" NUMERIC(10, 2) NOT NULL, + PRIMARY KEY ("TrackId"), + FOREIGN KEY("MediaTypeId") REFERENCES "MediaType" ("MediaTypeId"), + FOREIGN KEY("GenreId") REFERENCES "Genre" ("GenreId"), + FOREIGN KEY("AlbumId") REFERENCES "Album" ("AlbumId") +) + +/* +3 rows from Track table: +TrackId Name AlbumId MediaTypeId GenreId Composer Milliseconds Bytes UnitPrice +1 For Those About To Rock (We Salute You) 1 1 1 Angus Young, Malcolm Young, Brian Johnson 343719 11170334 0.99 +2 Balls to the Wall 2 2 1 None 342562 5510424 0.99 +3 Fast As a Shark 3 2 1 F. Baltes, S. Kaufman, U. Dirkscneider & W. Hoffman 230619 3990994 0.99 +*/ +================================== Ai Message ================================== +Tool Calls: + sql_db_query_checker (call_urTRmtiGtTxkwHtscec7Fd2K) + Call ID: call_urTRmtiGtTxkwHtscec7Fd2K + Args: + query: SELECT Genre.Name, AVG(Track.Milliseconds) AS AvgMilliseconds +FROM Track +JOIN Genre ON Track.GenreId = Genre.GenreId +GROUP BY Genre.Name +ORDER BY AvgMilliseconds DESC +LIMIT 1; +================================= Tool Message ================================= +Name: sql_db_query_checker + +\`\`\`sql +SELECT Genre.Name, AVG(Track.Milliseconds) AS AvgMilliseconds +FROM Track +JOIN Genre ON Track.GenreId = Genre.GenreId +GROUP BY Genre.Name +ORDER BY AvgMilliseconds DESC +LIMIT 1; +\`\`\` +================================== Ai Message ================================== +Tool Calls: + sql_db_query (call_RNMqyUEMv0rvy0UxSwrXY2AV) + Call ID: call_RNMqyUEMv0rvy0UxSwrXY2AV + Args: + query: SELECT Genre.Name, AVG(Track.Milliseconds) AS AvgMilliseconds +FROM Track +JOIN Genre ON Track.GenreId = Genre.GenreId +GROUP BY Genre.Name +ORDER BY AvgMilliseconds DESC +LIMIT 1; +================================= Tool Message ================================= +Name: sql_db_query + +[('Sci Fi & Fantasy', 2911783.0384615385)] +================================== Ai Message ================================== + +The genre with the longest average track length is "Sci Fi & Fantasy," with an average duration of about 2,911,783 milliseconds (approximately 48.5 minutes) per track. +``` + +This worked well enough: the agent correctly listed the tables, obtained the schemas, wrote a query, checked the query, and ran it to inform its final response. + +!!! tip + You can inspect all aspects of the above run, including steps taken, tools invoked, what prompts were seen by the LLM, and more in the [LangSmith trace](https://smith.langchain.com/public/bd594960-73e3-474b-b6f2-db039d7c713a/r). + +## 3. Customizing the agent + +The prebuilt agent lets us get started quickly, but at each step the agent has access to the full set of tools. Above, we relied on the system prompt to constrain its behavior— for example, we instructed the agent to always start with the "list tables" tool, and to always run a query-checker tool before executing the query. + +We can enforce a higher degree of control in LangGraph by customizing the agent. Below, we implement a simple ReAct-agent setup, with dedicated nodes for specific tool-calls. We will use the same [state](../../concepts/low_level.md#state) as the pre-built agent. + +We construct dedicated nodes for the following steps: + +- Listing DB tables +- Calling the "get schema" tool +- Generating a query +- Checking the query + +Putting these steps in dedicated nodes lets us (1) force tool-calls when needed, and (2) customize the prompts associated with each step. + +```python +from typing import Literal +from langchain_core.messages import AIMessage +from langchain_core.runnables import RunnableConfig +from langgraph.graph import END, START, MessagesState, StateGraph +from langgraph.prebuilt import ToolNode + + +get_schema_tool = next(tool for tool in tools if tool.name == "sql_db_schema") +get_schema_node = ToolNode([get_schema_tool], name="get_schema") + +run_query_tool = next(tool for tool in tools if tool.name == "sql_db_query") +run_query_node = ToolNode([run_query_tool], name="run_query") + + +# Example: create a predetermined tool call +def list_tables(state: MessagesState): + tool_call = { + "name": "sql_db_list_tables", + "args": {}, + "id": "abc123", + "type": "tool_call", + } + tool_call_message = AIMessage(content="", tool_calls=[tool_call]) + + list_tables_tool = next(tool for tool in tools if tool.name == "sql_db_list_tables") + tool_message = list_tables_tool.invoke(tool_call) + response = AIMessage(f"Available tables: {tool_message.content}") + + return {"messages": [tool_call_message, tool_message, response]} + + +# Example: force a model to create a tool call +def call_get_schema(state: MessagesState): + # Note that LangChain enforces that all models accept `tool_choice="any"` + # as well as `tool_choice=`. + llm_with_tools = llm.bind_tools([get_schema_tool], tool_choice="any") + response = llm_with_tools.invoke(state["messages"]) + + return {"messages": [response]} + + +generate_query_system_prompt = """ +You are an agent designed to interact with a SQL database. +Given an input question, create a syntactically correct {dialect} query to run, +then look at the results of the query and return the answer. Unless the user +specifies a specific number of examples they wish to obtain, always limit your +query to at most {top_k} results. + +You can order the results by a relevant column to return the most interesting +examples in the database. Never query for all the columns from a specific table, +only ask for the relevant columns given the question. + +DO NOT make any DML statements (INSERT, UPDATE, DELETE, DROP etc.) to the database. +""".format( + dialect=db.dialect, + top_k=5, +) + + +def generate_query(state: MessagesState): + system_message = { + "role": "system", + "content": generate_query_system_prompt, + } + # We do not force a tool call here, to allow the model to + # respond naturally when it obtains the solution. + llm_with_tools = llm.bind_tools([run_query_tool]) + response = llm_with_tools.invoke([system_message] + state["messages"]) + + return {"messages": [response]} + + +check_query_system_prompt = """ +You are a SQL expert with a strong attention to detail. +Double check the {dialect} query for common mistakes, including: +- Using NOT IN with NULL values +- Using UNION when UNION ALL should have been used +- Using BETWEEN for exclusive ranges +- Data type mismatch in predicates +- Properly quoting identifiers +- Using the correct number of arguments for functions +- Casting to the correct data type +- Using the proper columns for joins + +If there are any of the above mistakes, rewrite the query. If there are no mistakes, +just reproduce the original query. + +You will call the appropriate tool to execute the query after running this check. +""".format(dialect=db.dialect) + + +def check_query(state: MessagesState): + system_message = { + "role": "system", + "content": check_query_system_prompt, + } + + # Generate an artificial user message to check + tool_call = state["messages"][-1].tool_calls[0] + user_message = {"role": "user", "content": tool_call["args"]["query"]} + llm_with_tools = llm.bind_tools([run_query_tool], tool_choice="any") + response = llm_with_tools.invoke([system_message, user_message]) + response.id = state["messages"][-1].id + + return {"messages": [response]} +``` + +Finally, we assemble these steps into a workflow using the Graph API. We define a [conditional edge](../../concepts/low_level.md#conditional-edges) at the query generation step that will route to the query checker if a query is generated, or end if there are no tool calls present, such that the LLM has delivered a response to the query. + +```python +def should_continue(state: MessagesState) -> Literal[END, "check_query"]: + messages = state["messages"] + last_message = messages[-1] + if not last_message.tool_calls: + return END + else: + return "check_query" + + +builder = StateGraph(MessagesState) +builder.add_node(list_tables) +builder.add_node(call_get_schema) +builder.add_node(get_schema_node, "get_schema") +builder.add_node(generate_query) +builder.add_node(check_query) +builder.add_node(run_query_node, "run_query") + +builder.add_edge(START, "list_tables") +builder.add_edge("list_tables", "call_get_schema") +builder.add_edge("call_get_schema", "get_schema") +builder.add_edge("get_schema", "generate_query") +builder.add_conditional_edges( + "generate_query", + should_continue, +) +builder.add_edge("check_query", "run_query") +builder.add_edge("run_query", "generate_query") + +agent = builder.compile() +``` + +We visualize the application below: + +```python +from IPython.display import Image, display +from langchain_core.runnables.graph import CurveStyle, MermaidDrawMethod, NodeStyles + +display(Image(agent.get_graph().draw_mermaid_png())) +``` + +![Graph](./output.png) + +**Note:** When you run this code, it will generate and display a visual representation of the SQL agent graph showing the flow between the different nodes (list_tables → call_get_schema → get_schema → generate_query → check_query → run_query). + +We can now invoke the graph exactly as before: + +```python +question = "Which genre on average has the longest tracks?" + +for step in agent.stream( + {"messages": [{"role": "user", "content": question}]}, + stream_mode="values", +): + step["messages"][-1].pretty_print() +``` + +**Output:** +``` +================================ Human Message ================================= + +Which genre on average has the longest tracks? +================================== Ai Message ================================== + +Available tables: Album, Artist, Customer, Employee, Genre, Invoice, InvoiceLine, MediaType, Playlist, PlaylistTrack, Track +================================== Ai Message ================================== +Tool Calls: + sql_db_schema (call_qxKtYiHgf93AiTDin9ez5wFp) + Call ID: call_qxKtYiHgf93AiTDin9ez5wFp + Args: + table_names: Genre,Track +================================= Tool Message ================================= +Name: sql_db_schema + + +CREATE TABLE "Genre" ( + "GenreId" INTEGER NOT NULL, + "Name" NVARCHAR(120), + PRIMARY KEY ("GenreId") +) + +/* +3 rows from Genre table: +GenreId Name +1 Rock +2 Jazz +3 Metal +*/ + + +CREATE TABLE "Track" ( + "TrackId" INTEGER NOT NULL, + "Name" NVARCHAR(200) NOT NULL, + "AlbumId" INTEGER, + "MediaTypeId" INTEGER NOT NULL, + "GenreId" INTEGER, + "Composer" NVARCHAR(220), + "Milliseconds" INTEGER NOT NULL, + "Bytes" INTEGER, + "UnitPrice" NUMERIC(10, 2) NOT NULL, + PRIMARY KEY ("TrackId"), + FOREIGN KEY("MediaTypeId") REFERENCES "MediaType" ("MediaTypeId"), + FOREIGN KEY("GenreId") REFERENCES "Genre" ("GenreId"), + FOREIGN KEY("AlbumId") REFERENCES "Album" ("AlbumId") +) + +/* +3 rows from Track table: +TrackId Name AlbumId MediaTypeId GenreId Composer Milliseconds Bytes UnitPrice +1 For Those About To Rock (We Salute You) 1 1 1 Angus Young, Malcolm Young, Brian Johnson 343719 11170334 0.99 +2 Balls to the Wall 2 2 1 None 342562 5510424 0.99 +3 Fast As a Shark 3 2 1 F. Baltes, S. Kaufman, U. Dirkscneider & W. Hoffman 230619 3990994 0.99 +*/ +================================== Ai Message ================================== +Tool Calls: + sql_db_query (call_RPN3GABMfb6DTaFTLlwnZxVN) + Call ID: call_RPN3GABMfb6DTaFTLlwnZxVN + Args: + query: SELECT Genre.Name, AVG(Track.Milliseconds) AS AvgTrackLength +FROM Track +JOIN Genre ON Track.GenreId = Genre.GenreId +GROUP BY Genre.GenreId +ORDER BY AvgTrackLength DESC +LIMIT 1; +================================== Ai Message ================================== +Tool Calls: + sql_db_query (call_PR4s8ymiF3ZQLaoZADXtdqcl) + Call ID: call_PR4s8ymiF3ZQLaoZADXtdqcl + Args: + query: SELECT Genre.Name, AVG(Track.Milliseconds) AS AvgTrackLength +FROM Track +JOIN Genre ON Track.GenreId = Genre.GenreId +GROUP BY Genre.GenreId +ORDER BY AvgTrackLength DESC +LIMIT 1; +================================= Tool Message ================================= +Name: sql_db_query + +[('Sci Fi & Fantasy', 2911783.0384615385)] +================================== Ai Message ================================== + +The genre with the longest tracks on average is "Sci Fi & Fantasy," with an average track length of approximately 2,911,783 milliseconds. +``` + +!!! tip + See [LangSmith trace](https://smith.langchain.com/public/94b8c9ac-12f7-4692-8706-836a1f30f1ea/r) for the above run. + +## Next steps + +Check out [this guide](https://docs.smith.langchain.com/evaluation/how_to_guides/langgraph) for evaluating LangGraph applications, including SQL agents like this one, using LangSmith. \ No newline at end of file diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 7cfbb246f..020c6e28a 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -269,19 +269,18 @@ nav: - Examples: - Template applications: concepts/template_applications.md # TODO: make tutorial - - Agentic RAG: tutorials/rag/langgraph_agentic_rag.ipynb - - Agent Supervisor: tutorials/multi_agent/agent_supervisor.ipynb - - SQL agent: tutorials/sql-agent.ipynb + - Agentic RAG: tutorials/rag/langgraph_agentic_rag.md + - Agent Supervisor: tutorials/multi_agent/agent_supervisor.md + - SQL agent: tutorials/sql/sql-agent.md - Prebuilt chat UI: agents/ui.md - - Graph runs in LangSmith: how-tos/run-id-langsmith.ipynb + - Graph runs in LangSmith: how-tos/run-id-langsmith.md - LangGraph Platform: - Authentication: - tutorials/auth/getting_started.md - tutorials/auth/resource_auth.md - tutorials/auth/add_auth_server.md - Use RemoteGraph: how-tos/use-remote-graph.md - - Deploy CrewAI, AutoGen, and other frameworks: how-tos/autogen-langgraph-platform.ipynb - # combine with how-tos/autogen-integration.ipynb + - Deploy CrewAI, AutoGen, and other frameworks: how-tos/autogen-integration.md - Front-end and generative UI: - Integrate LangGraph into a React app: cloud/how-tos/use_stream_react.md - Implement generative UI with LangGraph: cloud/how-tos/generative_ui_react.md From 4de1bd6e666ba9305d259f8f043608c4f9c6aac9 Mon Sep 17 00:00:00 2001 From: Lauren Hirata Singh Date: Tue, 8 Jul 2025 12:33:14 -0400 Subject: [PATCH 048/129] docs: cleanup (#5401) * docs: cleanup * fix nav * fix * fix nits --- docs/_scripts/extract_images.py | 70 -- docs/docs/additional-resources/index.md | 11 + docs/docs/agents/agents.md | 2 +- docs/docs/cloud/concepts/threads.md | 12 - docs/docs/examples/index.md | 23 + docs/docs/guides/index.md | 41 + .../tutorials/multi_agent/agent_supervisor.md | 2 +- docs/docs/tutorials/overview.md | 21 - docs/docs/tutorials/sql-agent.ipynb | 759 ------------------ docs/mkdocs.yml | 3 + 10 files changed, 80 insertions(+), 864 deletions(-) delete mode 100644 docs/_scripts/extract_images.py create mode 100644 docs/docs/additional-resources/index.md delete mode 100644 docs/docs/cloud/concepts/threads.md create mode 100644 docs/docs/examples/index.md create mode 100644 docs/docs/guides/index.md delete mode 100644 docs/docs/tutorials/overview.md delete mode 100644 docs/docs/tutorials/sql-agent.ipynb diff --git a/docs/_scripts/extract_images.py b/docs/_scripts/extract_images.py deleted file mode 100644 index 781ba0a22..000000000 --- a/docs/_scripts/extract_images.py +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env python3 -""" -Script to extract images from the graph-api.ipynb notebook and save them to assets folder. -""" - -import json -import base64 -import os -from pathlib import Path - -def extract_images_from_notebook(notebook_path, assets_dir): - """Extract images from notebook and save them to assets directory.""" - - # Read the notebook - with open(notebook_path, 'r') as f: - notebook = json.load(f) - - # Create assets directory if it doesn't exist - os.makedirs(assets_dir, exist_ok=True) - - image_count = 0 - - # Process each cell - for cell_idx, cell in enumerate(notebook['cells']): - if cell['cell_type'] == 'code': - # Check if this cell contains draw_mermaid_png - source = ''.join(cell.get('source', [])) - if 'draw_mermaid_png' in source: - print(f"Found draw_mermaid_png in cell {cell_idx}") - - # Check for outputs with images - if 'outputs' in cell: - for output_idx, output in enumerate(cell['outputs']): - if output.get('output_type') == 'display_data': - data = output.get('data', {}) - - # Check for PNG data - if 'image/png' in data: - png_data = data['image/png'] - - # Decode base64 data - try: - image_bytes = base64.b64decode(png_data) - - # Generate filename - image_count += 1 - filename = f"graph_api_image_{image_count}.png" - filepath = os.path.join(assets_dir, filename) - - # Save the image - with open(filepath, 'wb') as img_file: - img_file.write(image_bytes) - - print(f"Saved image: {filepath}") - - except Exception as e: - print(f"Error decoding image {image_count}: {e}") - - print(f"Extracted {image_count} images to {assets_dir}") - return image_count - -if __name__ == "__main__": - notebook_path = "docs/docs/how-tos/graph-api.ipynb" - assets_dir = "docs/docs/how-tos/assets" - - if os.path.exists(notebook_path): - count = extract_images_from_notebook(notebook_path, assets_dir) - print(f"Successfully extracted {count} images") - else: - print(f"Notebook not found: {notebook_path}") \ No newline at end of file diff --git a/docs/docs/additional-resources/index.md b/docs/docs/additional-resources/index.md new file mode 100644 index 000000000..6e4e7a93b --- /dev/null +++ b/docs/docs/additional-resources/index.md @@ -0,0 +1,11 @@ +# Additional resources + +This section contains additional resources for LangGraph. + +- [Community agents](../agents/prebuilt.md): A collection of prebuilt libraries that you can use in your LangGraph applications. +- [LangGraph Academy](https://academy.langchain.com/courses/intro-to-langgraph): A collection of courses that teach you how to use LangGraph. +- [Case studies](../adopters.md): A collection of case studies that show how LangGraph is used in production. +- [FAQ](../concepts/faq.md): A collection of frequently asked questions about LangGraph. +- [llms.txt](../llms-txt-overview.md): A list of documentation files in the `llms.txt` format that allow LLMs and agents to access our documentation. +- [LangChain Forum](https://forum.langchain.com/): A place to ask questions and get help from other LangGraph users. +- [Troubleshooting](../troubleshooting/errors/index.md.md): A collection of troubleshooting guides for common issues. \ No newline at end of file diff --git a/docs/docs/agents/agents.md b/docs/docs/agents/agents.md index b00184266..04ee419ce 100644 --- a/docs/docs/agents/agents.md +++ b/docs/docs/agents/agents.md @@ -52,7 +52,7 @@ agent.invoke( ) ``` -1. Define a tool for the agent to use. Tools can be defined as vanilla Python functions. For more advanced tool usage and customization, check the [tools](./tools.md) page. +1. Define a tool for the agent to use. Tools can be defined as vanilla Python functions. For more advanced tool usage and customization, check the [tools](../how-tos/tool-calling.md) page. 2. Provide a language model for the agent to use. To learn more about configuring language models for the agents, check the [models](./models.md) page. 3. Provide a list of tools for the model to use. 4. Provide a system prompt (instructions) to the language model used by the agent. diff --git a/docs/docs/cloud/concepts/threads.md b/docs/docs/cloud/concepts/threads.md deleted file mode 100644 index ffd48faa8..000000000 --- a/docs/docs/cloud/concepts/threads.md +++ /dev/null @@ -1,12 +0,0 @@ -# Threads - -A thread contains the accumulated state of a sequence of [runs](../../concepts/assistants.md#execution). When a run is executed, the [state](../../concepts/low_level.md#state) of the underlying graph of the assistant will be persisted to the thread. - -A thread's current and historical state can be retrieved. To persist state, a thread must be created prior to executing a run. - -The state of a thread at a particular point in time is called a [checkpoint](../../concepts/persistence.md#checkpoints). Checkpoints are persisted and can be used to restore the state of a thread at a later time. - -## Learn more - -* For more on threads and checkpoints, see this section of the [LangGraph conceptual guide](../../concepts/persistence.md). -* The LangGraph Platform API provides several endpoints for creating and managing threads and thread state. See the [API reference](../../cloud/reference/api/api_ref.html#tag/threads) for more details. diff --git a/docs/docs/examples/index.md b/docs/docs/examples/index.md new file mode 100644 index 000000000..84c721ac3 --- /dev/null +++ b/docs/docs/examples/index.md @@ -0,0 +1,23 @@ +# Examples + +The pages in this section provide end-to-end examples for the following topics: + +## General + +- [Template Applications](../concepts/template_applications.md): Create a LangGraph application from a template. +- [Agentic RAG](./rag/langgraph_agentic_rag.md): Build a retrieval agent that can decide when to use a retriever tool. +- [Agent Supervisor](./multi_agent/agent_supervisor.md): Build a supervisor agent that can manage a team of agents. +- [SQL agent](./sql/sql-agent.md): Build a SQL agent that can execute SQL queries and return the results. +- [Prebuilt chat UI](../agents/ui.md): Use a prebuilt chat UI to interact with any LangGraph agent. +- [Graph runs in LangSmith](../how-tos/run-id-langsmith.md): Use LangSmith to track and analyze graph runs. + +## LangGraph Platform + +- [Set up custom authentication](./auth/getting_started.md): Set up custom authentication for your LangGraph application. +- [Make conversations private](./auth/resource_auth.md): Make conversations private by using resource-based authentication. +- [Connect an authentication provider](./auth/add_auth_server.md): Connect an authentication provider to your LangGraph application. +- [Rebuild graph at runtime](../cloud/deployment/graph_rebuild.md): Rebuild a graph at runtime. +- [Use RemoteGraph](../how-tos/use-remote-graph.md): Use RemoteGraph to deploy your LangGraph application to a remote server. +- [Deploy CrewAI, AutoGen, and other frameworks](../how-tos/autogen-integration.md): Deploy CrewAI, AutoGen, and other frameworks with LangGraph. +- [Integrate LangGraph into a React app](../cloud/how-tos/use_stream_react.md) +- [Implement Generative User Interfaces with LangGraph](../cloud/how-tos/generative_ui_react.md) \ No newline at end of file diff --git a/docs/docs/guides/index.md b/docs/docs/guides/index.md new file mode 100644 index 000000000..1d57f63ea --- /dev/null +++ b/docs/docs/guides/index.md @@ -0,0 +1,41 @@ +# Guides + +The pages in this section provide a conceptual overview and how-tos for the following topics: + +## LangGraph APIs + +- [Graph API](../concepts/low_level.md): Use the Graph API to define workflows using a graph paradigm. +- [Functional API](../concepts/functional_api.md): Use Functional API to build workflows using a functional paradigm without thinking about the graph structure. +- [Runtime](../concepts/pregel.md): Pregel implements LangGraph's runtime, managing the execution of LangGraph applications. + +## Core capabilities + +These capabilities are available in both LangGraph OSS and the LangGraph Platform. + +- [Streaming](../concepts/streaming.md): Stream outputs from a LangGraph graph. +- [Persistence](../concepts/persistence.md): Persist the state of a LangGraph graph. +- [Durable execution](../concepts/durable_execution.md): Save progress at key points in the graph execution. +- [Memory](../concepts/memory.md): Remember information about previous interactions. +- [Context](../agents/context.md): Pass outside data to a LangGraph graph to provide context for the graph execution. +- [Models](../agents/models.md): Integrate various LLMs into your LangGraph application. +- [Tools](../concepts/tools.md): Interface directly with external systems. +- [Human-in-the-loop](../concepts/human_in_the_loop.md): Enable human intervention at any point in a workflow. +- [Breakpoints](../concepts/breakpoints.md): Pause the execution of a LangGraph graph at a specific point. +- [Time travel](../concepts/time-travel.md): Travel back in time to a specific point in the execution of a LangGraph graph. +- [Subgraphs](../concepts/subgraphs.md): Build modular graphs. +- [Multi-agent](../concepts/multi_agent.md): Break down a complex workflow into multiple agents. +- [MCP](../concepts/mcp.md): Use MCP servers in a LangGraph graph. +- [Evaluation](../agents/evals.md): Use LangSmith to evaluate your graph's performance. + +## Platform-only capabilities + +These capabilities are only available in [LangGraph Platform](../concepts/langgraph_platform.md). + +- [Authentication and access control](../concepts/auth.md): Authenticate and authorize users to access a Langraph graph. +- [Assistants](../concepts/assistants.md): Build assistants that can be used to interact with a LangGraph graph. +- [Double-texting](../concepts/double_texting.md): Handle double-texting (consecutive messages before a first response is returned) in a LangGraph graph. +- [Webhooks](../cloud/concepts/webhooks.md): Send webhooks to a LangGraph graph. +- [Cron jobs](../cloud/concepts/cron_jobs.md): Schedule jobs to run at a specific time. +- [Server customization](../how-tos/http/custom_lifespan.md): Customize the server that runs a LangGraph graph. +- [Data management](../cloud/concepts/data_storage_and_privacy.md): Manage data in a LangGraph graph. +- [Deployment](../concepts/deployment_options.md): Deploy a LangGraph graph to a server. \ No newline at end of file diff --git a/docs/docs/tutorials/multi_agent/agent_supervisor.md b/docs/docs/tutorials/multi_agent/agent_supervisor.md index ba8f84ff6..71335c8db 100644 --- a/docs/docs/tutorials/multi_agent/agent_supervisor.md +++ b/docs/docs/tutorials/multi_agent/agent_supervisor.md @@ -206,7 +206,7 @@ Name: tavily_search ### Math agent -For math agent tools we will use [vanilla Python functions](../../agents/tools.md#define-simple-tools): +For math agent tools we will use [vanilla Python functions](../../how-tos/tool-calling.md#define-a-tool): ```python def add(a: float, b: float): diff --git a/docs/docs/tutorials/overview.md b/docs/docs/tutorials/overview.md deleted file mode 100644 index 6eacbd4e4..000000000 --- a/docs/docs/tutorials/overview.md +++ /dev/null @@ -1,21 +0,0 @@ -# Examples - -The pages in this section provide end-to-end examples for the following topics: - -## General - -- [Agentic RAG](./rag/langgraph_adaptive_rag.ipynb) -- [Agent Supervisor](./multi_agent/agent_supervisor.md) -- [SQL agent](./sql/sql-agent.md) -- [Graph runs in LangSmith](../how-tos/run-id-langsmith.md) - -## LangGraph Platform - -- [Set up custom authentication](./auth/getting_started.md) -- [Make conversations private](./auth/resource_auth.md) -- [Connect an authentication provider](./auth/add_auth_server.md) -- [Rebuild graph at runtime](../cloud/deployment/graph_rebuild.md) -- [Use RemoteGraph](../how-tos/use-remote-graph.md) -- [Deploy CrewAI, AutoGen, and other frameworks](../how-tos/autogen-integration.md) -- [Integrate LangGraph into a React app](../cloud/how-tos/use_stream_react.md) -- [Implement Generative User Interfaces with LangGraph](../cloud/how-tos/generative_ui_react.md) \ No newline at end of file diff --git a/docs/docs/tutorials/sql-agent.ipynb b/docs/docs/tutorials/sql-agent.ipynb deleted file mode 100644 index a06626f40..000000000 --- a/docs/docs/tutorials/sql-agent.ipynb +++ /dev/null @@ -1,759 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "cb71c4a7-9f99-4f08-be34-b3ba81ac075f", - "metadata": {}, - "source": [ - "# Build a SQL agent\n", - "\n", - "In this tutorial, we will walk through how to build an agent that can answer questions about a SQL database.\n", - "\n", - "At a high level, the agent will:\n", - "\n", - "1. Fetch the available tables from the database\n", - "2. Decide which tables are relevant to the question\n", - "3. Fetch the schemas for the relevant tables\n", - "4. Generate a query based on the question and information from the schemas\n", - "5. Double-check the query for common mistakes using an LLM\n", - "6. Execute the query and return the results\n", - "7. Correct mistakes surfaced by the database engine until the query is successful\n", - "8. Formulate a response based on the results\n", - "\n", - "!!! warning \"Security note\"\n", - "\n", - " Building Q&A systems of SQL databases requires executing model-generated SQL queries. There are inherent risks in doing this. Make sure that your database connection permissions are always scoped as narrowly as possible for your agent's needs. This will mitigate though not eliminate the risks of building a model-driven system.\n", - "\n", - "## 1. Setup\n", - "\n", - "Let's first install some dependencies. This tutorial uses SQL database and tool abstractions from [langchain-community](https://python.langchain.com/docs/concepts/architecture/#langchain-community). We will also require a LangChain [chat model](https://python.langchain.com/docs/concepts/chat_models/)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1b613286-41c3-4ca5-9514-36aac0121a5a", - "metadata": {}, - "outputs": [], - "source": [ - "%%capture --no-stderr\n", - "%pip install -U langgraph langchain_community \"langchain[openai]\"" - ] - }, - { - "cell_type": "markdown", - "id": "f5258ad0-39e1-418e-bddb-56e9aab1b43a", - "metadata": {}, - "source": [ - "

\n", - "

Set up LangSmith for LangGraph development

\n", - "

\n", - " Sign up for LangSmith to quickly spot issues and improve the performance of your LangGraph projects. LangSmith lets you use trace data to debug, test, and monitor your LLM apps built with LangGraph — read more about how to get started here. \n", - "

\n", - "
" - ] - }, - { - "cell_type": "markdown", - "id": "62886241-caa7-40bd-8867-096a97acaf40", - "metadata": {}, - "source": [ - "### Select a LLM\n", - "\n", - "First we [initialize our LLM](https://python.langchain.com/docs/how_to/chat_models_universal_init/). Any model supporting [tool-calling](https://python.langchain.com/docs/integrations/chat/#featured-providers) should work. We use OpenAI below." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "2b981efc-bcc9-49f4-aa66-4c15a76210a4", - "metadata": {}, - "outputs": [], - "source": [ - "from langchain.chat_models import init_chat_model\n", - "\n", - "llm = init_chat_model(\"openai:gpt-4.1\")" - ] - }, - { - "cell_type": "markdown", - "id": "804ca604-7ac4-4229-a3e9-3a9825eeefa4", - "metadata": {}, - "source": [ - "### Configure the database\n", - "\n", - "We will be creating a SQLite database for this tutorial. SQLite is a lightweight database that is easy to set up and use. We will be loading the `chinook` database, which is a sample database that represents a digital media store.\n", - "Find more information about the database [here](https://www.sqlitetutorial.net/sqlite-sample-database/).\n", - "\n", - "For convenience, we have hosted the database (`Chinook.db`) on a public GCS bucket." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b58ba6b7-5f80-4970-bc29-961de0e24fbd", - "metadata": {}, - "outputs": [], - "source": [ - "import requests\n", - "\n", - "url = \"https://storage.googleapis.com/benchmarks-artifacts/chinook/Chinook.db\"\n", - "\n", - "response = requests.get(url)\n", - "\n", - "if response.status_code == 200:\n", - " # Open a local file in binary write mode\n", - " with open(\"Chinook.db\", \"wb\") as file:\n", - " # Write the content of the response (the file) to the local file\n", - " file.write(response.content)\n", - " print(\"File downloaded and saved as Chinook.db\")\n", - "else:\n", - " print(f\"Failed to download the file. Status code: {response.status_code}\")" - ] - }, - { - "cell_type": "markdown", - "id": "5ae005fb-e7b0-43f1-95b2-565d19c82610", - "metadata": {}, - "source": [ - "We will use a handy SQL database wrapper available in the `langchain_community` package to interact with the database. The wrapper provides a simple interface to execute SQL queries and fetch results:" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "18822c9b-6df2-4a5c-a12d-046d2b2131c9", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Dialect: sqlite\n", - "Available tables: ['Album', 'Artist', 'Customer', 'Employee', 'Genre', 'Invoice', 'InvoiceLine', 'MediaType', 'Playlist', 'PlaylistTrack', 'Track']\n", - "Sample output: [(1, 'AC/DC'), (2, 'Accept'), (3, 'Aerosmith'), (4, 'Alanis Morissette'), (5, 'Alice In Chains')]\n" - ] - } - ], - "source": [ - "from langchain_community.utilities import SQLDatabase\n", - "\n", - "db = SQLDatabase.from_uri(\"sqlite:///Chinook.db\")\n", - "\n", - "print(f\"Dialect: {db.dialect}\")\n", - "print(f\"Available tables: {db.get_usable_table_names()}\")\n", - "print(f'Sample output: {db.run(\"SELECT * FROM Artist LIMIT 5;\")}')" - ] - }, - { - "cell_type": "markdown", - "id": "3bf47b6c-30dd-405f-8a03-21327af3c764", - "metadata": {}, - "source": [ - "### Tools for database interactions\n", - "\n", - "`langchain-community` implements some built-in tools for interacting with our `SQLDatabase`, including tools for listing tables, reading table schemas, and checking and running queries:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "aab9e00a-aa28-494a-a95a-a6638ea03bd1", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "sql_db_query: Input to this tool is a detailed and correct SQL query, output is a result from the database. If the query is not correct, an error message will be returned. If an error is returned, rewrite the query, check the query, and try again. If you encounter an issue with Unknown column 'xxxx' in 'field list', use sql_db_schema to query the correct table fields.\n", - "\n", - "sql_db_schema: Input to this tool is a comma-separated list of tables, output is the schema and sample rows for those tables. Be sure that the tables actually exist by calling sql_db_list_tables first! Example Input: table1, table2, table3\n", - "\n", - "sql_db_list_tables: Input is an empty string, output is a comma-separated list of tables in the database.\n", - "\n", - "sql_db_query_checker: Use this tool to double check if your query is correct before executing it. Always use this tool before executing a query with sql_db_query!\n", - "\n" - ] - } - ], - "source": [ - "from langchain_community.agent_toolkits import SQLDatabaseToolkit\n", - "\n", - "toolkit = SQLDatabaseToolkit(db=db, llm=llm)\n", - "\n", - "tools = toolkit.get_tools()\n", - "\n", - "for tool in tools:\n", - " print(f\"{tool.name}: {tool.description}\\n\")" - ] - }, - { - "cell_type": "markdown", - "id": "6baf93d3-afd5-484e-9bf7-3ff20401e06f", - "metadata": {}, - "source": [ - "## 2. Using a prebuilt agent\n", - "\n", - "Given these tools, we can initialize a pre-built agent in a single line. To customize our agents behavior, we write a descriptive system prompt." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "f6b9f10f-c6cb-43bc-b671-79aadc71280b", - "metadata": {}, - "outputs": [], - "source": [ - "from langgraph.prebuilt import create_react_agent\n", - "\n", - "system_prompt = \"\"\"\n", - "You are an agent designed to interact with a SQL database.\n", - "Given an input question, create a syntactically correct {dialect} query to run,\n", - "then look at the results of the query and return the answer. Unless the user\n", - "specifies a specific number of examples they wish to obtain, always limit your\n", - "query to at most {top_k} results.\n", - "\n", - "You can order the results by a relevant column to return the most interesting\n", - "examples in the database. Never query for all the columns from a specific table,\n", - "only ask for the relevant columns given the question.\n", - "\n", - "You MUST double check your query before executing it. If you get an error while\n", - "executing a query, rewrite the query and try again.\n", - "\n", - "DO NOT make any DML statements (INSERT, UPDATE, DELETE, DROP etc.) to the\n", - "database.\n", - "\n", - "To start you should ALWAYS look at the tables in the database to see what you\n", - "can query. Do NOT skip this step.\n", - "\n", - "Then you should query the schema of the most relevant tables.\n", - "\"\"\".format(\n", - " dialect=db.dialect,\n", - " top_k=5,\n", - ")\n", - "\n", - "agent = create_react_agent(\n", - " llm,\n", - " tools,\n", - " prompt=system_prompt,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "78b1c7cf-9a0f-48c3-baec-be8101bc3c77", - "metadata": {}, - "source": [ - "!!! note\n", - "\n", - " This system prompt includes a number of instructions, such as always running specific tools before or after others. In the [next section](#customizing-the-agent), we will enforce these behaviors through the graph's structure, providing us a greater degree of control and allowing us to simplify the prompt.\n", - "\n", - "\n", - "Let's run this agent on a sample query and observe its behavior:" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "9317c234-6251-4723-a335-7fee6d11ac2b", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "================================\u001b[1m Human Message \u001b[0m=================================\n", - "\n", - "Which genre on average has the longest tracks?\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "Tool Calls:\n", - " sql_db_list_tables (call_d8lCgywSroCgpVl558nmXKwA)\n", - " Call ID: call_d8lCgywSroCgpVl558nmXKwA\n", - " Args:\n", - "=================================\u001b[1m Tool Message \u001b[0m=================================\n", - "Name: sql_db_list_tables\n", - "\n", - "Album, Artist, Customer, Employee, Genre, Invoice, InvoiceLine, MediaType, Playlist, PlaylistTrack, Track\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "Tool Calls:\n", - " sql_db_schema (call_nNf6IIUcwMYLIkE0l6uWkZHe)\n", - " Call ID: call_nNf6IIUcwMYLIkE0l6uWkZHe\n", - " Args:\n", - " table_names: Genre, Track\n", - "=================================\u001b[1m Tool Message \u001b[0m=================================\n", - "Name: sql_db_schema\n", - "\n", - "\n", - "CREATE TABLE \"Genre\" (\n", - "\t\"GenreId\" INTEGER NOT NULL, \n", - "\t\"Name\" NVARCHAR(120), \n", - "\tPRIMARY KEY (\"GenreId\")\n", - ")\n", - "\n", - "/*\n", - "3 rows from Genre table:\n", - "GenreId\tName\n", - "1\tRock\n", - "2\tJazz\n", - "3\tMetal\n", - "*/\n", - "\n", - "\n", - "CREATE TABLE \"Track\" (\n", - "\t\"TrackId\" INTEGER NOT NULL, \n", - "\t\"Name\" NVARCHAR(200) NOT NULL, \n", - "\t\"AlbumId\" INTEGER, \n", - "\t\"MediaTypeId\" INTEGER NOT NULL, \n", - "\t\"GenreId\" INTEGER, \n", - "\t\"Composer\" NVARCHAR(220), \n", - "\t\"Milliseconds\" INTEGER NOT NULL, \n", - "\t\"Bytes\" INTEGER, \n", - "\t\"UnitPrice\" NUMERIC(10, 2) NOT NULL, \n", - "\tPRIMARY KEY (\"TrackId\"), \n", - "\tFOREIGN KEY(\"MediaTypeId\") REFERENCES \"MediaType\" (\"MediaTypeId\"), \n", - "\tFOREIGN KEY(\"GenreId\") REFERENCES \"Genre\" (\"GenreId\"), \n", - "\tFOREIGN KEY(\"AlbumId\") REFERENCES \"Album\" (\"AlbumId\")\n", - ")\n", - "\n", - "/*\n", - "3 rows from Track table:\n", - "TrackId\tName\tAlbumId\tMediaTypeId\tGenreId\tComposer\tMilliseconds\tBytes\tUnitPrice\n", - "1\tFor Those About To Rock (We Salute You)\t1\t1\t1\tAngus Young, Malcolm Young, Brian Johnson\t343719\t11170334\t0.99\n", - "2\tBalls to the Wall\t2\t2\t1\tNone\t342562\t5510424\t0.99\n", - "3\tFast As a Shark\t3\t2\t1\tF. Baltes, S. Kaufman, U. Dirkscneider & W. Hoffman\t230619\t3990994\t0.99\n", - "*/\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "Tool Calls:\n", - " sql_db_query_checker (call_urTRmtiGtTxkwHtscec7Fd2K)\n", - " Call ID: call_urTRmtiGtTxkwHtscec7Fd2K\n", - " Args:\n", - " query: SELECT Genre.Name, AVG(Track.Milliseconds) AS AvgMilliseconds\n", - "FROM Track\n", - "JOIN Genre ON Track.GenreId = Genre.GenreId\n", - "GROUP BY Genre.Name\n", - "ORDER BY AvgMilliseconds DESC\n", - "LIMIT 1;\n", - "=================================\u001b[1m Tool Message \u001b[0m=================================\n", - "Name: sql_db_query_checker\n", - "\n", - "```sql\n", - "SELECT Genre.Name, AVG(Track.Milliseconds) AS AvgMilliseconds\n", - "FROM Track\n", - "JOIN Genre ON Track.GenreId = Genre.GenreId\n", - "GROUP BY Genre.Name\n", - "ORDER BY AvgMilliseconds DESC\n", - "LIMIT 1;\n", - "```\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "Tool Calls:\n", - " sql_db_query (call_RNMqyUEMv0rvy0UxSwrXY2AV)\n", - " Call ID: call_RNMqyUEMv0rvy0UxSwrXY2AV\n", - " Args:\n", - " query: SELECT Genre.Name, AVG(Track.Milliseconds) AS AvgMilliseconds\n", - "FROM Track\n", - "JOIN Genre ON Track.GenreId = Genre.GenreId\n", - "GROUP BY Genre.Name\n", - "ORDER BY AvgMilliseconds DESC\n", - "LIMIT 1;\n", - "=================================\u001b[1m Tool Message \u001b[0m=================================\n", - "Name: sql_db_query\n", - "\n", - "[('Sci Fi & Fantasy', 2911783.0384615385)]\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "\n", - "The genre with the longest average track length is \"Sci Fi & Fantasy,\" with an average duration of about 2,911,783 milliseconds (approximately 48.5 minutes) per track.\n" - ] - } - ], - "source": [ - "question = \"Which genre on average has the longest tracks?\"\n", - "\n", - "for step in agent.stream(\n", - " {\"messages\": [{\"role\": \"user\", \"content\": question}]},\n", - " stream_mode=\"values\",\n", - "):\n", - " step[\"messages\"][-1].pretty_print()" - ] - }, - { - "cell_type": "markdown", - "id": "6b2afc54-0a26-40f8-bca2-01cbb2fc3443", - "metadata": {}, - "source": [ - "This worked well enough: the agent correctly listed the tables, obtained the schemas, wrote a query, checked the query, and ran it to inform its final response.\n", - "\n", - "!!! tip\n", - "\n", - " You can inspect all aspects of the above run, including steps taken, tools invoked, what prompts were seen by the LLM, and more in the [LangSmith trace](https://smith.langchain.com/public/bd594960-73e3-474b-b6f2-db039d7c713a/r)." - ] - }, - { - "cell_type": "markdown", - "id": "2ed79712-ca6b-47dc-9bc9-7cb6fc50a8aa", - "metadata": {}, - "source": [ - "## 3. Customizing the agent\n", - "\n", - "The prebuilt agent lets us get started quickly, but at each step the agent has access to the full set of tools. Above, we relied on the system prompt to constrain its behavior— for example, we instructed the agent to always start with the \"list tables\" tool, and to always run a query-checker tool before executing the query.\n", - "\n", - "We can enforce a higher degree of control in LangGraph by customizing the agent. Below, we implement a simple ReAct-agent setup, with dedicated nodes for specific tool-calls. We will use the same [state](../../concepts/low_level/#state) as the pre-built agent.\n", - "\n", - "We construct dedicated nodes for the following steps:\n", - "\n", - "- Listing DB tables\n", - "- Calling the \"get schema\" tool\n", - "- Generating a query\n", - "- Checking the query\n", - "\n", - "Putting these steps in dedicated nodes lets us (1) force tool-calls when needed, and (2) customize the prompts associated with each step." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "992f6ce6-f932-4f44-994c-c0ba5032dbd1", - "metadata": {}, - "outputs": [], - "source": [ - "from typing import Literal\n", - "from langchain_core.messages import AIMessage\n", - "from langchain_core.runnables import RunnableConfig\n", - "from langgraph.graph import END, START, MessagesState, StateGraph\n", - "from langgraph.prebuilt import ToolNode\n", - "\n", - "\n", - "get_schema_tool = next(tool for tool in tools if tool.name == \"sql_db_schema\")\n", - "get_schema_node = ToolNode([get_schema_tool], name=\"get_schema\")\n", - "\n", - "run_query_tool = next(tool for tool in tools if tool.name == \"sql_db_query\")\n", - "run_query_node = ToolNode([run_query_tool], name=\"run_query\")\n", - "\n", - "\n", - "# Example: create a predetermined tool call\n", - "def list_tables(state: MessagesState):\n", - " tool_call = {\n", - " \"name\": \"sql_db_list_tables\",\n", - " \"args\": {},\n", - " \"id\": \"abc123\",\n", - " \"type\": \"tool_call\",\n", - " }\n", - " tool_call_message = AIMessage(content=\"\", tool_calls=[tool_call])\n", - "\n", - " list_tables_tool = next(tool for tool in tools if tool.name == \"sql_db_list_tables\")\n", - " tool_message = list_tables_tool.invoke(tool_call)\n", - " response = AIMessage(f\"Available tables: {tool_message.content}\")\n", - "\n", - " return {\"messages\": [tool_call_message, tool_message, response]}\n", - "\n", - "\n", - "# Example: force a model to create a tool call\n", - "def call_get_schema(state: MessagesState):\n", - " # Note that LangChain enforces that all models accept `tool_choice=\"any\"`\n", - " # as well as `tool_choice=`.\n", - " llm_with_tools = llm.bind_tools([get_schema_tool], tool_choice=\"any\")\n", - " response = llm_with_tools.invoke(state[\"messages\"])\n", - "\n", - " return {\"messages\": [response]}\n", - "\n", - "\n", - "generate_query_system_prompt = \"\"\"\n", - "You are an agent designed to interact with a SQL database.\n", - "Given an input question, create a syntactically correct {dialect} query to run,\n", - "then look at the results of the query and return the answer. Unless the user\n", - "specifies a specific number of examples they wish to obtain, always limit your\n", - "query to at most {top_k} results.\n", - "\n", - "You can order the results by a relevant column to return the most interesting\n", - "examples in the database. Never query for all the columns from a specific table,\n", - "only ask for the relevant columns given the question.\n", - "\n", - "DO NOT make any DML statements (INSERT, UPDATE, DELETE, DROP etc.) to the database.\n", - "\"\"\".format(\n", - " dialect=db.dialect,\n", - " top_k=5,\n", - ")\n", - "\n", - "\n", - "def generate_query(state: MessagesState):\n", - " system_message = {\n", - " \"role\": \"system\",\n", - " \"content\": generate_query_system_prompt,\n", - " }\n", - " # We do not force a tool call here, to allow the model to\n", - " # respond naturally when it obtains the solution.\n", - " llm_with_tools = llm.bind_tools([run_query_tool])\n", - " response = llm_with_tools.invoke([system_message] + state[\"messages\"])\n", - "\n", - " return {\"messages\": [response]}\n", - "\n", - "\n", - "check_query_system_prompt = \"\"\"\n", - "You are a SQL expert with a strong attention to detail.\n", - "Double check the {dialect} query for common mistakes, including:\n", - "- Using NOT IN with NULL values\n", - "- Using UNION when UNION ALL should have been used\n", - "- Using BETWEEN for exclusive ranges\n", - "- Data type mismatch in predicates\n", - "- Properly quoting identifiers\n", - "- Using the correct number of arguments for functions\n", - "- Casting to the correct data type\n", - "- Using the proper columns for joins\n", - "\n", - "If there are any of the above mistakes, rewrite the query. If there are no mistakes,\n", - "just reproduce the original query.\n", - "\n", - "You will call the appropriate tool to execute the query after running this check.\n", - "\"\"\".format(dialect=db.dialect)\n", - "\n", - "\n", - "def check_query(state: MessagesState):\n", - " system_message = {\n", - " \"role\": \"system\",\n", - " \"content\": check_query_system_prompt,\n", - " }\n", - "\n", - " # Generate an artificial user message to check\n", - " tool_call = state[\"messages\"][-1].tool_calls[0]\n", - " user_message = {\"role\": \"user\", \"content\": tool_call[\"args\"][\"query\"]}\n", - " llm_with_tools = llm.bind_tools([run_query_tool], tool_choice=\"any\")\n", - " response = llm_with_tools.invoke([system_message, user_message])\n", - " response.id = state[\"messages\"][-1].id\n", - "\n", - " return {\"messages\": [response]}" - ] - }, - { - "cell_type": "markdown", - "id": "cd23a432-09c1-428c-88a7-6b4d1fe55577", - "metadata": {}, - "source": [ - "Finally, we assemble these steps into a workflow using the Graph API. We define a [conditional edge](../../concepts/low_level/#conditional-edges) at the query generation step that will route to the query checker if a query is generated, or end if there are no tool calls present, such that the LLM has delivered a response to the query." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "8b3ce09d-0eec-456d-8447-d04f79ccfc23", - "metadata": {}, - "outputs": [], - "source": [ - "def should_continue(state: MessagesState) -> Literal[END, \"check_query\"]:\n", - " messages = state[\"messages\"]\n", - " last_message = messages[-1]\n", - " if not last_message.tool_calls:\n", - " return END\n", - " else:\n", - " return \"check_query\"\n", - "\n", - "\n", - "builder = StateGraph(MessagesState)\n", - "builder.add_node(list_tables)\n", - "builder.add_node(call_get_schema)\n", - "builder.add_node(get_schema_node, \"get_schema\")\n", - "builder.add_node(generate_query)\n", - "builder.add_node(check_query)\n", - "builder.add_node(run_query_node, \"run_query\")\n", - "\n", - "builder.add_edge(START, \"list_tables\")\n", - "builder.add_edge(\"list_tables\", \"call_get_schema\")\n", - "builder.add_edge(\"call_get_schema\", \"get_schema\")\n", - "builder.add_edge(\"get_schema\", \"generate_query\")\n", - "builder.add_conditional_edges(\n", - " \"generate_query\",\n", - " should_continue,\n", - ")\n", - "builder.add_edge(\"check_query\", \"run_query\")\n", - "builder.add_edge(\"run_query\", \"generate_query\")\n", - "\n", - "agent = builder.compile()" - ] - }, - { - "cell_type": "markdown", - "id": "c377e9dd-92a7-45d4-91bf-408a6f2af8ca", - "metadata": {}, - "source": [ - "We visualize the application below:" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "f728ed5f-7bcd-489e-9174-4e4725962335", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "from IPython.display import Image, display\n", - "from langchain_core.runnables.graph import CurveStyle, MermaidDrawMethod, NodeStyles\n", - "\n", - "display(Image(agent.get_graph().draw_mermaid_png()))" - ] - }, - { - "cell_type": "markdown", - "id": "977173cf-8f8d-416e-a122-aebff115f29a", - "metadata": {}, - "source": [ - "We can now invoke the graph exactly as before:" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "6c800a77-2359-4011-ab0c-dad22ed333b1", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "================================\u001b[1m Human Message \u001b[0m=================================\n", - "\n", - "Which genre on average has the longest tracks?\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "\n", - "Available tables: Album, Artist, Customer, Employee, Genre, Invoice, InvoiceLine, MediaType, Playlist, PlaylistTrack, Track\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "Tool Calls:\n", - " sql_db_schema (call_qxKtYiHgf93AiTDin9ez5wFp)\n", - " Call ID: call_qxKtYiHgf93AiTDin9ez5wFp\n", - " Args:\n", - " table_names: Genre,Track\n", - "=================================\u001b[1m Tool Message \u001b[0m=================================\n", - "Name: sql_db_schema\n", - "\n", - "\n", - "CREATE TABLE \"Genre\" (\n", - "\t\"GenreId\" INTEGER NOT NULL, \n", - "\t\"Name\" NVARCHAR(120), \n", - "\tPRIMARY KEY (\"GenreId\")\n", - ")\n", - "\n", - "/*\n", - "3 rows from Genre table:\n", - "GenreId\tName\n", - "1\tRock\n", - "2\tJazz\n", - "3\tMetal\n", - "*/\n", - "\n", - "\n", - "CREATE TABLE \"Track\" (\n", - "\t\"TrackId\" INTEGER NOT NULL, \n", - "\t\"Name\" NVARCHAR(200) NOT NULL, \n", - "\t\"AlbumId\" INTEGER, \n", - "\t\"MediaTypeId\" INTEGER NOT NULL, \n", - "\t\"GenreId\" INTEGER, \n", - "\t\"Composer\" NVARCHAR(220), \n", - "\t\"Milliseconds\" INTEGER NOT NULL, \n", - "\t\"Bytes\" INTEGER, \n", - "\t\"UnitPrice\" NUMERIC(10, 2) NOT NULL, \n", - "\tPRIMARY KEY (\"TrackId\"), \n", - "\tFOREIGN KEY(\"MediaTypeId\") REFERENCES \"MediaType\" (\"MediaTypeId\"), \n", - "\tFOREIGN KEY(\"GenreId\") REFERENCES \"Genre\" (\"GenreId\"), \n", - "\tFOREIGN KEY(\"AlbumId\") REFERENCES \"Album\" (\"AlbumId\")\n", - ")\n", - "\n", - "/*\n", - "3 rows from Track table:\n", - "TrackId\tName\tAlbumId\tMediaTypeId\tGenreId\tComposer\tMilliseconds\tBytes\tUnitPrice\n", - "1\tFor Those About To Rock (We Salute You)\t1\t1\t1\tAngus Young, Malcolm Young, Brian Johnson\t343719\t11170334\t0.99\n", - "2\tBalls to the Wall\t2\t2\t1\tNone\t342562\t5510424\t0.99\n", - "3\tFast As a Shark\t3\t2\t1\tF. Baltes, S. Kaufman, U. Dirkscneider & W. Hoffman\t230619\t3990994\t0.99\n", - "*/\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "Tool Calls:\n", - " sql_db_query (call_RPN3GABMfb6DTaFTLlwnZxVN)\n", - " Call ID: call_RPN3GABMfb6DTaFTLlwnZxVN\n", - " Args:\n", - " query: SELECT Genre.Name, AVG(Track.Milliseconds) AS AvgTrackLength\n", - "FROM Track\n", - "JOIN Genre ON Track.GenreId = Genre.GenreId\n", - "GROUP BY Genre.GenreId\n", - "ORDER BY AvgTrackLength DESC\n", - "LIMIT 1;\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "Tool Calls:\n", - " sql_db_query (call_PR4s8ymiF3ZQLaoZADXtdqcl)\n", - " Call ID: call_PR4s8ymiF3ZQLaoZADXtdqcl\n", - " Args:\n", - " query: SELECT Genre.Name, AVG(Track.Milliseconds) AS AvgTrackLength\n", - "FROM Track\n", - "JOIN Genre ON Track.GenreId = Genre.GenreId\n", - "GROUP BY Genre.GenreId\n", - "ORDER BY AvgTrackLength DESC\n", - "LIMIT 1;\n", - "=================================\u001b[1m Tool Message \u001b[0m=================================\n", - "Name: sql_db_query\n", - "\n", - "[('Sci Fi & Fantasy', 2911783.0384615385)]\n", - "==================================\u001b[1m Ai Message \u001b[0m==================================\n", - "\n", - "The genre with the longest tracks on average is \"Sci Fi & Fantasy,\" with an average track length of approximately 2,911,783 milliseconds.\n" - ] - } - ], - "source": [ - "question = \"Which genre on average has the longest tracks?\"\n", - "\n", - "for step in agent.stream(\n", - " {\"messages\": [{\"role\": \"user\", \"content\": question}]},\n", - " stream_mode=\"values\",\n", - "):\n", - " step[\"messages\"][-1].pretty_print()" - ] - }, - { - "cell_type": "markdown", - "id": "fc3d8130-15c3-4c22-bb17-eb82ad41586e", - "metadata": {}, - "source": [ - "!!! tip\n", - "\n", - " See [LangSmith trace](https://smith.langchain.com/public/94b8c9ac-12f7-4692-8706-836a1f30f1ea/r) for the above run." - ] - }, - { - "cell_type": "markdown", - "id": "838b3acf-3186-4aa1-b211-cf136e95c39d", - "metadata": {}, - "source": [ - "## Next steps\n", - "\n", - "Check out [this guide](https://docs.smith.langchain.com/evaluation/how_to_guides/langgraph) for evaluating LangGraph applications, including SQL agents like this one, using LangSmith." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.4" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 020c6e28a..a66966905 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -109,6 +109,7 @@ nav: - Agent architectures: concepts/agentic_concepts.md - Guides: + - guides/index.md - LangGraph APIs: - Graph API: - Overview: concepts/low_level.md @@ -268,6 +269,7 @@ nav: - Environment variables: cloud/reference/env_var.md - Examples: + - examples/index.md - Template applications: concepts/template_applications.md # TODO: make tutorial - Agentic RAG: tutorials/rag/langgraph_agentic_rag.md - Agent Supervisor: tutorials/multi_agent/agent_supervisor.md @@ -286,6 +288,7 @@ nav: - Implement generative UI with LangGraph: cloud/how-tos/generative_ui_react.md - Additional resources: + - additional-resources/index.md - agents/prebuilt.md # NOTE: prebuilt.md is auto-generated by `make build-prebuilt` - LangGraph Academy course: https://academy.langchain.com/courses/intro-to-langgraph - Case studies: adopters.md From fb1c0ae9f9072363e1c934d259549ed131f1bcd1 Mon Sep 17 00:00:00 2001 From: Jake Broekhuizen Date: Tue, 8 Jul 2025 09:55:15 -0700 Subject: [PATCH 049/129] docs: Updating mcp_tools_node fn & referencing runtime graph rebuild docs (#5328) Fix: Updating mcp_tools_node fn & referencing runtime graph rebuild docs --- docs/docs/concepts/server-mcp.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/docs/concepts/server-mcp.md b/docs/docs/concepts/server-mcp.md index 0d40bfb2e..b66eaada3 100644 --- a/docs/docs/concepts/server-mcp.md +++ b/docs/docs/concepts/server-mcp.md @@ -209,7 +209,7 @@ To make user-scoped tools available to your LangGraph Platform deployment, start ```python from langchain_mcp_adapters.client import MultiServerMCPClient -def get_mcp_tools_node(state, config): +def mcp_tools_node(state, config): user = config["configurable"].get("langgraph_auth_user") # e.g., user["github_token"], user["email"], etc. @@ -223,14 +223,19 @@ def get_mcp_tools_node(state, config): } }) tools = await client.get_tools() # (3) - return {"tools": tools} - + + # Your tool-calling logic here + + tool_messages = ... + return {"messages": tool_messages} ``` 1. MCP only supports adding headers to requests made to `streamable_http` and `sse` `transport` servers. 2. Your MCP server URL. 3. Get available tools from your MCP server. +_This can also be done by [rebuilding your graph at runtime](https://langchain-ai.github.io/langgraph/cloud/deployment/graph_rebuild/) to have a different configuration for a new run_ + ## Session behavior The current LangGraph MCP implementation does not support sessions. Each `/mcp` request is stateless and independent. From 9cb6365914d11ca33909d1d3c5f56565c91fc16b Mon Sep 17 00:00:00 2001 From: Michael Li Date: Wed, 9 Jul 2025 04:58:04 +1000 Subject: [PATCH 050/129] docs: update file paths to make the examples more robust (#5382) * cli: update file paths to make the examples more robust * fix: fix the prompt path --- libs/cli/examples/graphs_reqs_a/graphs_submod/agent.py | 2 +- libs/cli/examples/graphs_reqs_b/graphs_submod/agent.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/cli/examples/graphs_reqs_a/graphs_submod/agent.py b/libs/cli/examples/graphs_reqs_a/graphs_submod/agent.py index 5ab615871..1073110cb 100644 --- a/libs/cli/examples/graphs_reqs_a/graphs_submod/agent.py +++ b/libs/cli/examples/graphs_reqs_a/graphs_submod/agent.py @@ -17,7 +17,7 @@ model_oai = ChatOpenAI(temperature=0) model_anth = model_anth.bind_tools(tools) model_oai = model_oai.bind_tools(tools) -prompt = open("prompt.txt").read() +prompt = open(Path(__file__).parent.parent / "prompt.txt").read() subprompt = open(Path(__file__).parent / "subprompt.txt").read() diff --git a/libs/cli/examples/graphs_reqs_b/graphs_submod/agent.py b/libs/cli/examples/graphs_reqs_b/graphs_submod/agent.py index 5ab615871..1073110cb 100644 --- a/libs/cli/examples/graphs_reqs_b/graphs_submod/agent.py +++ b/libs/cli/examples/graphs_reqs_b/graphs_submod/agent.py @@ -17,7 +17,7 @@ model_oai = ChatOpenAI(temperature=0) model_anth = model_anth.bind_tools(tools) model_oai = model_oai.bind_tools(tools) -prompt = open("prompt.txt").read() +prompt = open(Path(__file__).parent.parent / "prompt.txt").read() subprompt = open(Path(__file__).parent / "subprompt.txt").read() From 0d8a8c5847703e78b88b3b2e3fb224a4d3adff63 Mon Sep 17 00:00:00 2001 From: William FH <13333726+hinthornw@users.noreply.github.com> Date: Tue, 8 Jul 2025 12:41:47 -0700 Subject: [PATCH 051/129] feat: [CLI] Add arg to retain build deps (setuptools, pip, wheel) (#5404) --- docs/docs/cloud/reference/cli.md | 1 + libs/cli/examples/langgraph.json | 1 + libs/cli/langgraph_cli/config.py | 124 ++++++++++++++++++---- libs/cli/pyproject.toml | 2 +- libs/cli/schemas/schema.json | 36 ++++++- libs/cli/schemas/schema.v0.json | 36 ++++++- libs/cli/schemas/version.schema.json | 46 ++++++++ libs/cli/tests/unit_tests/cli/test_cli.py | 7 +- libs/cli/tests/unit_tests/test_config.py | 57 +++++++++- libs/cli/uv.lock | 2 +- 10 files changed, 280 insertions(+), 32 deletions(-) create mode 100644 libs/cli/schemas/version.schema.json diff --git a/docs/docs/cloud/reference/cli.md b/docs/docs/cloud/reference/cli.md index b43be5485..2181f59e2 100644 --- a/docs/docs/cloud/reference/cli.md +++ b/docs/docs/cloud/reference/cli.md @@ -51,6 +51,7 @@ The LangGraph CLI requires a JSON configuration file that follows this [schema]( | `node_version` | Specify `node_version: 20` to use LangGraph.js. | | `pip_config_file` | Path to `pip` config file. | | `pip_installer` | _(Added in v0.3)_ Optional. Python package installer selector. It can be set to `"auto"`, `"pip"`, or `"uv"`. From version 0.3 onward the default strategy is to run `uv pip`, which typically delivers faster builds while remaining a drop-in replacement. In the uncommon situation where `uv` cannot handle your dependency graph or the structure of your `pyproject.toml`, specify `"pip"` here to revert to the earlier behaviour. | + | `keep_pkg_tools` | _(Added in v0.3.4)_ Optional. Control whether to retain Python packaging tools (`pip`, `setuptools`, `wheel`) in the final image. Accepted values:
  • true : Keep all three tools (skip uninstall).
  • false / omitted : Uninstall all three tools (default behaviour).
  • list[str] : Names of tools to retain. Each value must be one of "pip", "setuptools", "wheel".
. By default, all three tools are uninstalled. | | `dockerfile_lines` | Array of additional lines to add to Dockerfile following the import from parent image. | | `checkpointer` | Configuration for the checkpointer. Contains a `ttl` field which is an object with the following keys:
  • `strategy`: How to handle expired checkpoints (e.g., `"delete"`).
  • `sweep_interval_minutes`: How often to check for expired checkpoints (integer).
  • `default_ttl`: Default time-to-live for checkpoints in **minutes** (integer). Defines how long checkpoints are kept before the specified strategy is applied.
| | `http` | HTTP server configuration with the following fields:
  • `app`: Path to custom Starlette/FastAPI app (e.g., `"./src/agent/webapp.py:app"`). See [custom routes guide](../../how-tos/http/custom_routes.md).
  • `cors`: CORS configuration with fields for `allow_origins`, `allow_methods`, `allow_headers`, etc.
  • `configurable_headers`: Define which request headers to exclude or include as a run's configurable values.
  • `disable_assistants`: Disable `/assistants` routes
  • `disable_mcp`: Disable `/mcp` routes
  • `disable_meta`: Disable `/ok`, `/info`, `/metrics`, and `/docs` routes
  • `disable_runs`: Disable `/runs` routes
  • `disable_store`: Disable `/store` routes
  • `disable_threads`: Disable `/threads` routes
  • `disable_ui`: Disable `/ui` routes
  • `disable_webhooks`: Disable webhooks calls on run completion in all routes
  • `mount_prefix`: Prefix for mounted routes (e.g., "/my-deployment/api")
| diff --git a/libs/cli/examples/langgraph.json b/libs/cli/examples/langgraph.json index 51eb14be9..0d8563e55 100644 --- a/libs/cli/examples/langgraph.json +++ b/libs/cli/examples/langgraph.json @@ -8,6 +8,7 @@ "scikit-learn", "./graphs" ], + "keep_pkg_tools": false, "graphs": { "agent": "./graphs/agent.py:graph", "storm": "./graphs/storm.py:graph" diff --git a/libs/cli/langgraph_cli/config.py b/libs/cli/langgraph_cli/config.py index cd0356350..ce1c6e8b9 100644 --- a/libs/cli/langgraph_cli/config.py +++ b/libs/cli/langgraph_cli/config.py @@ -338,7 +338,7 @@ class HttpConfig(TypedDict, total=False): Default is False. """ disable_meta: bool - """Optional. If True, all meta endpoints (/ok, /info, /metrics, /docs) are disabled. + """Optional. If True, all meta endpoints (/openapi.json, /info, /metrics, /docs) are disabled. Default is False. """ @@ -471,21 +471,61 @@ class Config(TypedDict, total=False): """Optional. Named definitions of UI components emitted by the agent, each pointing to a JS/TS file. """ + keep_pkg_tools: Optional[Union[bool, list[str]]] + """Optional. Control whether to retain Python packaging tools in the final image. + + Allowed tools are: "pip", "setuptools", "wheel". + You can also set to true to include all packaging tools. + """ -PIP_CLEANUP_LINES = """# -- Ensure user deps didn't inadvertently overwrite langgraph-api + +_BUILD_TOOLS = ("pip", "setuptools", "wheel") + + +def _get_pip_cleanup_lines( + install_cmd: str, + to_uninstall: Optional[tuple[str]], + pip_installer: Literal["uv", "pip"], +) -> str: + commands = [ + f"""# -- Ensure user deps didn't inadvertently overwrite langgraph-api RUN mkdir -p /api/langgraph_api /api/langgraph_runtime /api/langgraph_license && \ - touch /api/langgraph_api/__init__.py /api/langgraph_runtime/__init__.py /api/langgraph_license/__init__.py +touch /api/langgraph_api/__init__.py /api/langgraph_runtime/__init__.py /api/langgraph_license/__init__.py RUN PYTHONDONTWRITEBYTECODE=1 {install_cmd} --no-cache-dir --no-deps -e /api # -- End of ensuring user deps didn't inadvertently overwrite langgraph-api -- -# -- Removing pip from the final image ~<:===~~~ -- -RUN pip uninstall -y pip setuptools wheel && \ - rm -rf /usr/local/lib/python*/site-packages/pip* /usr/local/lib/python*/site-packages/setuptools* /usr/local/lib/python*/site-packages/wheel* && \ - find /usr/local/bin -name "pip*" -delete || true -# pip removal for wolfi -RUN rm -rf /usr/lib/python*/site-packages/pip* /usr/lib/python*/site-packages/setuptools* /usr/lib/python*/site-packages/wheel* && \ - find /usr/bin -name "pip*" -delete || true -{uv_removal} -# -- End of pip removal --""" +# -- Removing build deps from the final image ~<:===~~~ --""" + ] + if to_uninstall: + for pack in to_uninstall: + if pack not in _BUILD_TOOLS: + raise ValueError( + f"Invalid build tool: {pack}; must be one of {', '.join(_BUILD_TOOLS)}" + ) + packs_str = " ".join(sorted(to_uninstall)) + commands.append(f"RUN pip uninstall -y {packs_str}") + # Ensure the directories are removed entirely + packages_rm = " ".join( + f"/usr/local/lib/python*/site-packages/{pack}*" for pack in to_uninstall + ) + if "pip" in to_uninstall: + packages_rm += ' && find /usr/local/bin -name "pip*" -delete || true' + commands.append(f"RUN rm -rf {packages_rm}") + wolfi_packages_rm = " ".join( + f"/usr/lib/python*/site-packages/{pack}*" for pack in to_uninstall + ) + if "pip" in to_uninstall: + wolfi_packages_rm += ' && find /usr/bin -name "pip*" -delete || true' + commands.append(f"RUN rm -rf {wolfi_packages_rm}") + if pip_installer == "uv": + commands.append( + f"RUN uv pip uninstall --system {packs_str} && rm /usr/bin/uv /usr/bin/uvx" + ) + else: + if pip_installer == "uv": + commands.append( + "RUN rm /usr/bin/uv /usr/bin/uvx\n# -- End of build deps removal --" + ) + return "\n".join(commands) def _parse_version(version_str: str) -> tuple[int, int]: @@ -563,6 +603,7 @@ def validate_config(config: Config) -> Config: "checkpointer": config.get("checkpointer"), "ui": config.get("ui"), "ui_config": config.get("ui_config"), + "keep_pkg_tools": config.get("keep_pkg_tools"), } if config.get("node_version"): @@ -635,6 +676,22 @@ def validate_config(config: Config) -> Config: f"Invalid http.app format: '{http_conf['app']}'. " "Must be in format './path/to/file.py:attribute_name'" ) + if keep_pkg_tools := config.get("keep_pkg_tools"): + if isinstance(keep_pkg_tools, list): + for tool in keep_pkg_tools: + if tool not in _BUILD_TOOLS: + raise ValueError( + f"Invalid keep_pkg_tools: '{tool}'. " + "Must be one of 'pip', 'setuptools', 'wheel'." + ) + elif keep_pkg_tools is True: + pass + else: + raise ValueError( + f"Invalid keep_pkg_tools: '{keep_pkg_tools}'. " + "Must be bool or list[str] (with values" + " 'pip', 'setuptools', and/or 'wheel')." + ) return config @@ -1128,6 +1185,27 @@ def _image_supports_uv(base_image: str) -> bool: return version >= min_uv +def get_build_tools_to_uninstall(config: Config) -> tuple[str]: + keep_pkg_tools = config.get("keep_pkg_tools") + if not keep_pkg_tools: + return _BUILD_TOOLS + if keep_pkg_tools is True: + return () + expected = _BUILD_TOOLS + if isinstance(keep_pkg_tools, list): + for tool in keep_pkg_tools: + if tool not in expected: + raise ValueError( + f"Invalid build tool to uninstall: {tool}. Expected one of {expected}" + ) + return tuple(sorted(set(_BUILD_TOOLS) - set(keep_pkg_tools))) + else: + raise ValueError( + f"Invalid value for keep_pkg_tools: {keep_pkg_tools}." + " Expected True or a list containing any of {expected}." + ) + + def python_config_to_docker( config_path: pathlib.Path, config: Config, @@ -1135,20 +1213,18 @@ def python_config_to_docker( ) -> tuple[str, dict[str, str]]: """Generate a Dockerfile from the configuration.""" pip_installer = config.get("pip_installer", "auto") - + build_tools_to_uninstall = get_build_tools_to_uninstall(config) + if pip_installer == "auto": + if _image_supports_uv(base_image): + pip_installer = "uv" + else: + pip_installer = "pip" if pip_installer == "uv": install_cmd = "uv pip install --system" - uv_removal = "RUN uv pip uninstall --system pip setuptools wheel && rm /usr/bin/uv /usr/bin/uvx" elif pip_installer == "pip": install_cmd = "pip install" - uv_removal = "" else: - if _image_supports_uv(base_image): - install_cmd = "uv pip install --system" - uv_removal = "RUN uv pip uninstall --system pip setuptools wheel && rm /usr/bin/uv /usr/bin/uvx" - else: - install_cmd = "pip install" - uv_removal = "" + raise ValueError(f"Invalid pip_installer: {pip_installer}") # configure pip pip_install = f"PYTHONDONTWRITEBYTECODE=1 {install_cmd} --no-cache-dir -c /api/constraints.txt" @@ -1297,7 +1373,11 @@ ADD {relpath} /deps/{name} js_inst_str, "", # Add pip cleanup after all installations are complete - PIP_CLEANUP_LINES.format(install_cmd=install_cmd, uv_removal=uv_removal), + _get_pip_cleanup_lines( + install_cmd=install_cmd, + to_uninstall=build_tools_to_uninstall, + pip_installer=pip_installer, + ), "", f"WORKDIR {local_deps.working_dir}" if local_deps.working_dir else "", ] diff --git a/libs/cli/pyproject.toml b/libs/cli/pyproject.toml index 1a781e6f2..8c959ccab 100644 --- a/libs/cli/pyproject.toml +++ b/libs/cli/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "langgraph-cli" -version = "0.3.3" +version = "0.3.4" description = "CLI for interacting with LangGraph API" authors = [] requires-python = ">=3.9" diff --git a/libs/cli/schemas/schema.json b/libs/cli/schemas/schema.json index c069f7e9e..19d8893a4 100644 --- a/libs/cli/schemas/schema.json +++ b/libs/cli/schemas/schema.json @@ -134,6 +134,23 @@ ], "description": "Optional. Linux distribution for the base image.\n\nMust be either 'debian' or 'wolfi'. If omitted, defaults to 'debian'.\n" }, + "keep_pkg_tools": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Optional. Control whether to retain Python packaging tools in the final image.\n\nYou can also set to true to include all packaging tools.\n" + }, "pip_installer": { "anyOf": [ { @@ -298,6 +315,23 @@ ], "description": "Optional. Linux distribution for the base image.\n\nMust be either 'debian' or 'wolfi'. If omitted, defaults to 'debian'.\n" }, + "keep_pkg_tools": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Optional. Control whether to retain Python packaging tools in the final image.\n\nYou can also set to true to include all packaging tools.\n" + }, "pip_installer": { "anyOf": [ { @@ -505,7 +539,7 @@ }, "disable_meta": { "type": "boolean", - "description": "Optional. If True, all meta endpoints (/ok, /info, /metrics, /docs) are disabled.\n\nDefault is False.\n" + "description": "Optional. If True, all meta endpoints (/openapi.json, /info, /metrics, /docs) are disabled.\n\nDefault is False.\n" }, "disable_runs": { "type": "boolean", diff --git a/libs/cli/schemas/schema.v0.json b/libs/cli/schemas/schema.v0.json index c069f7e9e..19d8893a4 100644 --- a/libs/cli/schemas/schema.v0.json +++ b/libs/cli/schemas/schema.v0.json @@ -134,6 +134,23 @@ ], "description": "Optional. Linux distribution for the base image.\n\nMust be either 'debian' or 'wolfi'. If omitted, defaults to 'debian'.\n" }, + "keep_pkg_tools": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Optional. Control whether to retain Python packaging tools in the final image.\n\nYou can also set to true to include all packaging tools.\n" + }, "pip_installer": { "anyOf": [ { @@ -298,6 +315,23 @@ ], "description": "Optional. Linux distribution for the base image.\n\nMust be either 'debian' or 'wolfi'. If omitted, defaults to 'debian'.\n" }, + "keep_pkg_tools": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Optional. Control whether to retain Python packaging tools in the final image.\n\nYou can also set to true to include all packaging tools.\n" + }, "pip_installer": { "anyOf": [ { @@ -505,7 +539,7 @@ }, "disable_meta": { "type": "boolean", - "description": "Optional. If True, all meta endpoints (/ok, /info, /metrics, /docs) are disabled.\n\nDefault is False.\n" + "description": "Optional. If True, all meta endpoints (/openapi.json, /info, /metrics, /docs) are disabled.\n\nDefault is False.\n" }, "disable_runs": { "type": "boolean", diff --git a/libs/cli/schemas/version.schema.json b/libs/cli/schemas/version.schema.json new file mode 100644 index 000000000..041b130c1 --- /dev/null +++ b/libs/cli/schemas/version.schema.json @@ -0,0 +1,46 @@ +{ + "$id": "https://github.com/langchain-ai/langgraph/libs/cli/schemas/version.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "LangGraph Platform configuration (when building via the langgraph-cli).", + "type": "object", + "oneOf": [ + { + "allOf": [ + { + "oneOf": [ + { + "properties": { + "version": { + "type": "string", + "maxLength": 0 + } + }, + "required": ["version"] + }, + { + "not": { + "required": ["version"] + } + } + ] + }, + { + "$ref": "https://raw.githubusercontent.com/langchain-ai/langgraph/main/libs/cli/schemas/schema.json" + } + ] + }, + { + "allOf": [ + { + "properties": { + "version": { "const": "v0" } + }, + "required": ["version"] + }, + { + "$ref": "https://raw.githubusercontent.com/langchain-ai/langgraph/main/libs/cli/schemas/schema.v0.json" + } + ] + } + ] +} diff --git a/libs/cli/tests/unit_tests/cli/test_cli.py b/libs/cli/tests/unit_tests/cli/test_cli.py index 268f44e00..e6d0a17b4 100644 --- a/libs/cli/tests/unit_tests/cli/test_cli.py +++ b/libs/cli/tests/unit_tests/cli/test_cli.py @@ -10,13 +10,14 @@ from pathlib import Path from click.testing import CliRunner from langgraph_cli.cli import cli, prepare_args_and_stdin -from langgraph_cli.config import PIP_CLEANUP_LINES, Config, validate_config +from langgraph_cli.config import Config, _get_pip_cleanup_lines, validate_config from langgraph_cli.docker import DEFAULT_POSTGRES_URI, DockerCapabilities, Version from langgraph_cli.util import clean_empty_lines -FORMATTED_CLEANUP_LINES = PIP_CLEANUP_LINES.format( +FORMATTED_CLEANUP_LINES = _get_pip_cleanup_lines( install_cmd="uv pip install --system", - uv_removal="RUN uv pip uninstall --system pip setuptools wheel && rm /usr/bin/uv /usr/bin/uvx", + to_uninstall=("pip", "setuptools", "wheel"), + pip_installer="uv", ) DEFAULT_DOCKER_CAPABILITIES = DockerCapabilities( version_docker=Version(26, 1, 1), diff --git a/libs/cli/tests/unit_tests/test_config.py b/libs/cli/tests/unit_tests/test_config.py index 3971b60e2..691c1e888 100644 --- a/libs/cli/tests/unit_tests/test_config.py +++ b/libs/cli/tests/unit_tests/test_config.py @@ -9,7 +9,8 @@ import click import pytest from langgraph_cli.config import ( - PIP_CLEANUP_LINES, + _BUILD_TOOLS, + _get_pip_cleanup_lines, config_to_compose, config_to_docker, docker_tag, @@ -18,9 +19,10 @@ from langgraph_cli.config import ( ) from langgraph_cli.util import clean_empty_lines -FORMATTED_CLEANUP_LINES = PIP_CLEANUP_LINES.format( +FORMATTED_CLEANUP_LINES = _get_pip_cleanup_lines( install_cmd="uv pip install --system", - uv_removal="RUN uv pip uninstall --system pip setuptools wheel && rm /usr/bin/uv /usr/bin/uvx", + to_uninstall=("pip", "setuptools", "wheel"), + pip_installer="uv", ) PATH_TO_CONFIG = pathlib.Path(__file__).parent / "test_config.json" @@ -51,6 +53,7 @@ def test_validate_config(): "http": None, "ui": None, "ui_config": None, + "keep_pkg_tools": None, **expected_config, } assert actual_config == expected_config @@ -77,6 +80,7 @@ def test_validate_config(): "http": None, "ui": None, "ui_config": None, + "keep_pkg_tools": None, } actual_config = validate_config(expected_config) assert actual_config == expected_config @@ -925,6 +929,53 @@ def test_config_to_docker_pip_installer(): assert "uv pip install --system" in docker_default +def test_config_retain_build_tools(): + graphs = {"agent": "./graphs/agent.py:graph"} + base_config = { + "python_version": "3.11", + "dependencies": ["."], + "graphs": graphs, + } + config_true = validate_config( + {**copy.deepcopy(base_config), "keep_pkg_tools": True} + ) + docker_true, _ = config_to_docker( + PATH_TO_CONFIG, config_true, "langchain/langgraph-api:0.2.47" + ) + assert not any( + "/usr/local/lib/python*/site-packages/" + pckg + "*" in docker_true + for pckg in _BUILD_TOOLS + ) + assert "RUN pip uninstall -y pip setuptools wheel" not in docker_true + config_false = validate_config( + {**copy.deepcopy(base_config), "keep_pkg_tools": False} + ) + docker_false, _ = config_to_docker( + PATH_TO_CONFIG, config_false, "langchain/langgraph-api:0.2.47" + ) + assert all( + "/usr/local/lib/python*/site-packages/" + pckg + "*" in docker_false + for pckg in _BUILD_TOOLS + ) + assert "RUN pip uninstall -y pip setuptools wheel" in docker_false + config_list = validate_config( + {**copy.deepcopy(base_config), "keep_pkg_tools": ["pip", "setuptools"]} + ) + docker_list, _ = config_to_docker( + PATH_TO_CONFIG, config_list, "langchain/langgraph-api:0.2.47" + ) + assert all( + "/usr/local/lib/python*/site-packages/" + pckg + "*" in docker_list + for pckg in ("wheel",) + ) + assert not any( + "/usr/local/lib/python*/site-packages/" + pckg + "*" in docker_list + for pckg in ("pip", "setuptools") + ) + assert "RUN pip uninstall -y wheel" in docker_list + assert "RUN pip uninstall -y pip setuptools" not in docker_list + + # config_to_compose def test_config_to_compose_simple_config(): graphs = {"agent": "./agent.py:graph"} diff --git a/libs/cli/uv.lock b/libs/cli/uv.lock index a6a0d0270..b312f2e06 100644 --- a/libs/cli/uv.lock +++ b/libs/cli/uv.lock @@ -522,7 +522,7 @@ wheels = [ [[package]] name = "langgraph-cli" -version = "0.3.3" +version = "0.3.4" source = { editable = "." } dependencies = [ { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, From 2fee6499809cafa5cc19b21b60d54ad6a0a169ee Mon Sep 17 00:00:00 2001 From: William FH <13333726+hinthornw@users.noreply.github.com> Date: Tue, 8 Jul 2025 12:55:10 -0700 Subject: [PATCH 052/129] chore: (cli) Update description of disable_meta (#5406) --- libs/cli/langgraph_cli/config.py | 5 ++++- libs/cli/schemas/schema.json | 2 +- libs/cli/schemas/schema.v0.json | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/libs/cli/langgraph_cli/config.py b/libs/cli/langgraph_cli/config.py index ce1c6e8b9..9030c3ba2 100644 --- a/libs/cli/langgraph_cli/config.py +++ b/libs/cli/langgraph_cli/config.py @@ -338,7 +338,10 @@ class HttpConfig(TypedDict, total=False): Default is False. """ disable_meta: bool - """Optional. If True, all meta endpoints (/openapi.json, /info, /metrics, /docs) are disabled. + """Optional. Remove meta endpoints. + + Set to True to disable the following endpoints: /openapi.json, /info, /metrics, /docs. + This will also make the /ok endpoint skip any DB or other checks, always returning {"ok": True}. Default is False. """ diff --git a/libs/cli/schemas/schema.json b/libs/cli/schemas/schema.json index 19d8893a4..e76e69826 100644 --- a/libs/cli/schemas/schema.json +++ b/libs/cli/schemas/schema.json @@ -539,7 +539,7 @@ }, "disable_meta": { "type": "boolean", - "description": "Optional. If True, all meta endpoints (/openapi.json, /info, /metrics, /docs) are disabled.\n\nDefault is False.\n" + "description": "Optional. Remove meta endpoints.\n\n\nDefault is False.\n" }, "disable_runs": { "type": "boolean", diff --git a/libs/cli/schemas/schema.v0.json b/libs/cli/schemas/schema.v0.json index 19d8893a4..e76e69826 100644 --- a/libs/cli/schemas/schema.v0.json +++ b/libs/cli/schemas/schema.v0.json @@ -539,7 +539,7 @@ }, "disable_meta": { "type": "boolean", - "description": "Optional. If True, all meta endpoints (/openapi.json, /info, /metrics, /docs) are disabled.\n\nDefault is False.\n" + "description": "Optional. Remove meta endpoints.\n\n\nDefault is False.\n" }, "disable_runs": { "type": "boolean", From c8d32f104de42df833950076d638c0061b4dacc4 Mon Sep 17 00:00:00 2001 From: nlimpid Date: Wed, 9 Jul 2025 04:09:57 +0800 Subject: [PATCH 053/129] fix(doc): remove incorrect navigation title overrides for mobile (#5399) --- .../navigation_title_ovverides.css | 29 ------------------- docs/mkdocs.yml | 1 - 2 files changed, 30 deletions(-) delete mode 100644 docs/docs/stylesheets/navigation_title_ovverides.css diff --git a/docs/docs/stylesheets/navigation_title_ovverides.css b/docs/docs/stylesheets/navigation_title_ovverides.css deleted file mode 100644 index 4e7c937d7..000000000 --- a/docs/docs/stylesheets/navigation_title_ovverides.css +++ /dev/null @@ -1,29 +0,0 @@ -/* - * This file is used to override the navigation title for the LangGraph documentation. - * It is used to change the title of the first and second items in the navigation menu. - * The first item is the Guides page, and the second item is the Reference page. - */ - -.md-nav--primary > .md-nav__list > .md-nav__item:nth-child(1) > .md-nav__link .md-ellipsis { - visibility: hidden !important; - position: relative; -} - -.md-nav--primary > .md-nav__list > .md-nav__item:nth-child(1) > .md-nav__link .md-ellipsis::after { - content: "Home"; - visibility: visible; - position: absolute; - left: 0; -} - -.md-nav--primary > .md-nav__list > .md-nav__item:nth-child(2) > .md-nav__link .md-ellipsis { - visibility: hidden !important; - position: relative; -} - -.md-nav--primary > .md-nav__list > .md-nav__item:nth-child(2) > .md-nav__link .md-ellipsis::after { - content: "Home"; - visibility: visible; - position: absolute; - left: 0; -} \ No newline at end of file diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index a66966905..f11c007ec 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -381,7 +381,6 @@ validation: copyright: > Copyright © 2025 LangChain, Inc | Consent Preferences extra_css: - - stylesheets/navigation_title_ovverides.css - stylesheets/version_admonitions.css - stylesheets/logos.css - stylesheets/sticky_navigation.css From 7a662135353eaf72a98cb78f757a5c0cd1d60ae2 Mon Sep 17 00:00:00 2001 From: Kai-Wendel <125994309+Kai-Wendel@users.noreply.github.com> Date: Tue, 8 Jul 2025 22:49:04 +0200 Subject: [PATCH 054/129] Fix typo in types.py in the interrupt example (#5407) Update types.py This example still lacked to include `Command`. --- libs/langgraph/langgraph/types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/langgraph/langgraph/types.py b/libs/langgraph/langgraph/types.py index 095e73c24..8a653c0b9 100644 --- a/libs/langgraph/langgraph/types.py +++ b/libs/langgraph/langgraph/types.py @@ -428,7 +428,7 @@ def interrupt(value: Any) -> Any: from langgraph.checkpoint.memory import MemorySaver from langgraph.constants import START from langgraph.graph import StateGraph - from langgraph.types import interrupt + from langgraph.types import interrupt, Command class State(TypedDict): From 7a4fd2518509d587bc4c32809f786fa62c687733 Mon Sep 17 00:00:00 2001 From: Andrew Nguonly Date: Wed, 9 Jul 2025 10:53:21 -0400 Subject: [PATCH 055/129] docs: Add `RESUMABLE_STREAM_TTL_SECONDS` to env vars list (#5413) * Add RESUMABLE_STREAM_TTL_SECONDS to env vars list. * Update default value for BG_JOB_SHUTDOWN_GRACE_PERIOD_SECS. * Update LANGGRAPH_POSTGRES_POOL_MAX_SIZE description. --- docs/docs/cloud/reference/env_var.md | 60 +++++++++++++++++----------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/docs/docs/cloud/reference/env_var.md b/docs/docs/cloud/reference/env_var.md index 563cec2a1..333508d96 100644 --- a/docs/docs/cloud/reference/env_var.md +++ b/docs/docs/cloud/reference/env_var.md @@ -10,6 +10,10 @@ This environment variable should be set to `True` if the implementation of a gra Defaults to `False`. +## `BG_JOB_SHUTDOWN_GRACE_PERIOD_SECS` + +Specifies, in seconds, how long the server will wait for background jobs to finish after the queue receives a shutdown signal. After this period, the server will force termination. Defaults to `180` seconds. Set this to ensure jobs have enough time to complete cleanly during shutdown. Added in `langgraph-api==0.2.16`. + ## `BG_JOB_TIMEOUT_SECS` The timeout of a background run can be increased. However, the infrastructure for a Cloud SaaS deployment enforces a 1 hour timeout limit for API requests. This means the connection between client and server will timeout after 1 hour. This is not configurable. @@ -18,10 +22,6 @@ A background run can execute for longer than 1 hour, but a client must reconnect Defaults to `3600`. -## `BG_JOB_SHUTDOWN_GRACE_PERIOD_SECS` - -Specifies, in seconds, how long the server will wait for background jobs to finish after the queue receives a shutdown signal. After this period, the server will force termination. Defaults to `3600` seconds. Set this to ensure jobs have enough time to complete cleanly during shutdown. Added in `langgraph-api==0.2.16`. - ## `DD_API_KEY` Specify `DD_API_KEY` (your [Datadog API Key](https://docs.datadoghq.com/account_management/api-app-keys/)) to automatically enable Datadog tracing for the deployment. Specify other [`DD_*` environment variables](https://ddtrace.readthedocs.io/en/stable/configuration.html) to configure the tracing instrumentation. @@ -40,6 +40,14 @@ Type of authentication for the LangGraph Server deployment. Valid values: `langs For deployments to LangGraph Platform, this environment variable is set automatically. For local development or deployments where authentication is handled externally (e.g. self-hosted), set this environment variable to `noop`. +## `LANGGRAPH_POSTGRES_POOL_MAX_SIZE` + +Beginning with langgraph-api version `0.2.12`, the maximum size of the Postgres connection pool (per replica) can be controlled using the `LANGGRAPH_POSTGRES_POOL_MAX_SIZE` environment variable. By setting this variable, you can determine the upper bound on the number of simultaneous connections the server will establish with the Postgres database. + +For example, if a deployment is scaled up to 10 replicas and `LANGGRAPH_POSTGRES_POOL_MAX_SIZE` is configured to `150`, then up to `1500` connections to Postgres can be established. This is particularly useful for deployments where database resources are limited (or more available) or where you need to tune connection behavior for performance or scaling reasons. + +Defaults to `150` connections. + ## `LANGSMITH_RUNS_ENDPOINTS` For deployments with [self-hosted LangSmith](https://docs.smith.langchain.com/self_hosting) only. @@ -54,6 +62,10 @@ Set `LANGSMITH_TRACING` to `false` to disable tracing to LangSmith. Defaults to `true`. +## `LOG_COLOR` + +This is mainly relevant in the context of using the dev server via the `langgraph dev` command. Set `LOG_COLOR` to `true` to enable ANSI-colored console output when using the default console renderer. Disabling color output by setting this variable to `false` produces monochrome logs. Defaults to `true`. + ## `LOG_LEVEL` Configure [log level](https://docs.python.org/3/library/logging.html#logging-levels). Defaults to `INFO`. @@ -62,9 +74,14 @@ Configure [log level](https://docs.python.org/3/library/logging.html#logging-lev Set `LOG_JSON` to `true` to render all log messages as JSON objects using the configured `JSONRenderer`. This produces structured logs that can be easily parsed or ingested by log management systems. Defaults to `false`. -## `LOG_COLOR` +## `MOUNT_PREFIX` -This is mainly relevant in the context of using the dev server via the `langgraph dev` command. Set `LOG_COLOR` to `true` to enable ANSI-colored console output when using the default console renderer. Disabling color output by setting this variable to `false` produces monochrome logs. Defaults to `true`. +!!! info "Only Allowed in Self-Hosted Deployments" + The `MOUNT_PREFIX` environment variable is only allowed in Self-Hosted Deployment models, LangGraph Platform SaaS will not allow this environment variable. + +Set `MOUNT_PREFIX` to serve the LangGraph Server under a specific path prefix. This is useful for deployments where the server is behind a reverse proxy or load balancer that requires a specific path prefix. + +For example, if the server is to be served under `https://example.com/langgraph`, set `MOUNT_PREFIX` to `/langgraph`. ## `N_JOBS_PER_WORKER` @@ -94,16 +111,14 @@ Database Connectivity: - The custom Postgres instance must be accessible by the LangGraph Server. The user is responsible for ensuring connectivity. -## `LANGGRAPH_POSTGRES_POOL_MAX_SIZE` +## `REDIS_CLUSTER` -Beginning with langgraph-api version `0.2.12`, the maximum size of the Postgres connection pool can be controlled using the `LANGGRAPH_POSTGRES_POOL_MAX_SIZE` environment variable. By setting this variable, you can determine the upper bound on the number of simultaneous connections the server will establish with the Postgres database. This is particularly useful for deployments where database resources are limited (or more available) or where you need to tune connection behavior for performance or scaling reasons. If not specified, the pool size defaults to 150 connections. +!!! info "Only Allowed in Self-Hosted Deployments" + Redis Cluster mode is only available in Self-Hosted Deployment models, LangGraph Platform SaaS will provision a redis instance for you by default. -## `REDIS_URI_CUSTOM` +Set `REDIS_CLUSTER` to `True` to enable Redis Cluster mode. When enabled, the system will connect to Redis using cluster mode. This is useful when connecting to a Redis Cluster deployment. -!!! info "Only for Self-Hosted Data Plane and Self-Hosted Control Plane" - Custom Redis instances are only available for [Self-Hosted Data Plane](../../concepts/langgraph_self_hosted_data_plane.md) and [Self-Hosted Control Plane](../../concepts/langgraph_self_hosted_control_plane.md) deployments. - -Specify `REDIS_URI_CUSTOM` to use a custom Redis instance. The value of `REDIS_URI_CUSTOM` must be a valid [Redis connection URI](https://redis-py.readthedocs.io/en/stable/connections.html#redis.Redis.from_url). +Defaults to `False`. ## `REDIS_KEY_PREFIX` @@ -114,20 +129,19 @@ Specify a prefix for Redis keys. This allows multiple LangGraph Server instances Defaults to `''`. -## `REDIS_CLUSTER` +## `REDIS_URI_CUSTOM` -!!! info "Only Allowed in Self-Hosted Deployments" - Redis Cluster mode is only available in Self-Hosted Deployment models, LangGraph Platform SaaS will provision a redis instance for you by default. +!!! info "Only for Self-Hosted Data Plane and Self-Hosted Control Plane" + Custom Redis instances are only available for [Self-Hosted Data Plane](../../concepts/langgraph_self_hosted_data_plane.md) and [Self-Hosted Control Plane](../../concepts/langgraph_self_hosted_control_plane.md) deployments. -Set `REDIS_CLUSTER` to `True` to enable Redis Cluster mode. When enabled, the system will connect to Redis using cluster mode. This is useful when connecting to a Redis Cluster deployment. +Specify `REDIS_URI_CUSTOM` to use a custom Redis instance. The value of `REDIS_URI_CUSTOM` must be a valid [Redis connection URI](https://redis-py.readthedocs.io/en/stable/connections.html#redis.Redis.from_url). -Defaults to `False`. +## `RESUMABLE_STREAM_TTL_SECONDS` -## `MOUNT_PREFIX` +Time-to-live in seconds for resumable stream data in Redis. -!!! info "Only Allowed in Self-Hosted Deployments" - The `MOUNT_PREFIX` environment variable is only allowed in Self-Hosted Deployment models, LangGraph Platform SaaS will not allow this environment variable. +When a run is created and the output is streamed, the stream can be configured to be resumable (e.g. `stream_resumable=True`). If a stream is resumable, output from the stream is temporarily stored in Redis. The TTL for this data can be configured by setting `RESUMABLE_STREAM_TTL_SECONDS`. -Set `MOUNT_PREFIX` to serve the LangGraph Server under a specific path prefix. This is useful for deployments where the server is behind a reverse proxy or load balancer that requires a specific path prefix. +See the [Python](https://langchain-ai.github.io/langgraph/cloud/reference/sdk/python_sdk_ref/#langgraph_sdk.client.RunsClient.stream) and [JS/TS](https://langchain-ai.github.io/langgraphjs/reference/classes/sdk_client.RunsClient.html#stream) SDKs for more details on how to implement resumable streams. -For example, if the server is to be served under `https://example.com/langgraph`, set `MOUNT_PREFIX` to `/langgraph`. +Defaults to `120` seconds. From 4d7c107bb8ad824a199e62b6547dc789cd8ecce9 Mon Sep 17 00:00:00 2001 From: Eugene Yurtsev Date: Wed, 9 Jul 2025 12:19:49 -0400 Subject: [PATCH 056/129] Update config.yml (#5412) --- .github/ISSUE_TEMPLATE/config.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index c2d2f70e0..fe68aea78 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,15 +1,8 @@ -blank_issues_enabled: true version: 2.1 contact_links: - - name: 🤔 Question or Problem - about: Ask a question or ask about a problem in GitHub Discussions. - url: https://github.com/langchain-ai/langgraph/discussions/categories/q-a - name: Feature Request url: https://github.com/langchain-ai/langgraph/discussions/categories/ideas about: Suggest a feature or an idea - - name: Show and tell - about: Show what you built with LangChain - url: https://github.com/langchain-ai/langgraph/discussions/categories/show-and-tell - name: LangChain Forum url: https://forum.langchain.com/ about: General community discussions and support From 1240f8bdca3eecac0d6e6bc152d4fd70a7c1d168 Mon Sep 17 00:00:00 2001 From: jito Date: Thu, 10 Jul 2025 01:20:33 +0900 Subject: [PATCH 057/129] fix: correct troubleshooting link path (#5411) fix: correct troubleshooting link path from index.md.md to index.md Signed-off-by: jitokim --- docs/docs/additional-resources/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/additional-resources/index.md b/docs/docs/additional-resources/index.md index 6e4e7a93b..33e52e805 100644 --- a/docs/docs/additional-resources/index.md +++ b/docs/docs/additional-resources/index.md @@ -8,4 +8,4 @@ This section contains additional resources for LangGraph. - [FAQ](../concepts/faq.md): A collection of frequently asked questions about LangGraph. - [llms.txt](../llms-txt-overview.md): A list of documentation files in the `llms.txt` format that allow LLMs and agents to access our documentation. - [LangChain Forum](https://forum.langchain.com/): A place to ask questions and get help from other LangGraph users. -- [Troubleshooting](../troubleshooting/errors/index.md.md): A collection of troubleshooting guides for common issues. \ No newline at end of file +- [Troubleshooting](../troubleshooting/errors/index.md): A collection of troubleshooting guides for common issues. \ No newline at end of file From 6eace78c53d5a34998ae247d470ec8e71fb14af9 Mon Sep 17 00:00:00 2001 From: Sydney Runkle <54324534+sydney-runkle@users.noreply.github.com> Date: Wed, 9 Jul 2025 13:23:28 -0400 Subject: [PATCH 058/129] patch[langgraph]: Fix hint for `invoke`/`stream` to allow for `Command` and `None` (#5414) use Command and None as well --- libs/langgraph/langgraph/pregel/__init__.py | 9 +++++---- libs/langgraph/langgraph/pregel/protocol.py | 9 +++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/libs/langgraph/langgraph/pregel/__init__.py b/libs/langgraph/langgraph/pregel/__init__.py index 2397c1978..21d4d593b 100644 --- a/libs/langgraph/langgraph/pregel/__init__.py +++ b/libs/langgraph/langgraph/pregel/__init__.py @@ -99,6 +99,7 @@ from langgraph.types import ( All, CachePolicy, Checkpointer, + Command, Interrupt, Send, StateSnapshot, @@ -2342,7 +2343,7 @@ class Pregel(PregelProtocol[StateT, InputT, OutputT], Generic[StateT, InputT, Ou def stream( self, - input: InputT, + input: InputT | Command | None, config: RunnableConfig | None = None, *, stream_mode: StreamMode | Sequence[StreamMode] | None = None, @@ -2564,7 +2565,7 @@ class Pregel(PregelProtocol[StateT, InputT, OutputT], Generic[StateT, InputT, Ou async def astream( self, - input: InputT, + input: InputT | Command | None, config: RunnableConfig | None = None, *, stream_mode: StreamMode | Sequence[StreamMode] | None = None, @@ -2808,7 +2809,7 @@ class Pregel(PregelProtocol[StateT, InputT, OutputT], Generic[StateT, InputT, Ou def invoke( self, - input: InputT, + input: InputT | Command | None, config: RunnableConfig | None = None, *, stream_mode: StreamMode = "values", @@ -2883,7 +2884,7 @@ class Pregel(PregelProtocol[StateT, InputT, OutputT], Generic[StateT, InputT, Ou async def ainvoke( self, - input: InputT, + input: InputT | Command | None, config: RunnableConfig | None = None, *, stream_mode: StreamMode = "values", diff --git a/libs/langgraph/langgraph/pregel/protocol.py b/libs/langgraph/langgraph/pregel/protocol.py index e55be3cbc..dce0ef870 100644 --- a/libs/langgraph/langgraph/pregel/protocol.py +++ b/libs/langgraph/langgraph/pregel/protocol.py @@ -9,6 +9,7 @@ from langchain_core.runnables.graph import Graph as DrawableGraph from typing_extensions import Self from langgraph.pregel.types import All, StateSnapshot, StateUpdate, StreamMode +from langgraph.types import Command from langgraph.typing import InputT, OutputT, StateT @@ -98,7 +99,7 @@ class PregelProtocol(Runnable[InputT, Any], Generic[StateT, InputT, OutputT], AB @abstractmethod def stream( self, - input: InputT, + input: InputT | Command | None, config: RunnableConfig | None = None, *, stream_mode: StreamMode | list[StreamMode] | None = None, @@ -110,7 +111,7 @@ class PregelProtocol(Runnable[InputT, Any], Generic[StateT, InputT, OutputT], AB @abstractmethod def astream( self, - input: InputT, + input: InputT | Command | None, config: RunnableConfig | None = None, *, stream_mode: StreamMode | list[StreamMode] | None = None, @@ -122,7 +123,7 @@ class PregelProtocol(Runnable[InputT, Any], Generic[StateT, InputT, OutputT], AB @abstractmethod def invoke( self, - input: InputT, + input: InputT | Command | None, config: RunnableConfig | None = None, *, interrupt_before: All | Sequence[str] | None = None, @@ -132,7 +133,7 @@ class PregelProtocol(Runnable[InputT, Any], Generic[StateT, InputT, OutputT], AB @abstractmethod async def ainvoke( self, - input: InputT, + input: InputT | Command | None, config: RunnableConfig | None = None, *, interrupt_before: All | Sequence[str] | None = None, From 543cbe9032eba084cbc938fd887e14f24b864fb6 Mon Sep 17 00:00:00 2001 From: Sydney Runkle <54324534+sydney-runkle@users.noreply.github.com> Date: Wed, 9 Jul 2025 14:12:00 -0400 Subject: [PATCH 059/129] chore: add PR title linter (#5416) --- .github/workflows/pr_lint.yml | 43 +++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 .github/workflows/pr_lint.yml diff --git a/.github/workflows/pr_lint.yml b/.github/workflows/pr_lint.yml new file mode 100644 index 000000000..cada5b1ba --- /dev/null +++ b/.github/workflows/pr_lint.yml @@ -0,0 +1,43 @@ +name: PR Title Lint + +permissions: + pull-requests: read + +on: + pull_request: + types: [opened, edited, synchronize] + +jobs: + lint-pr-title: + runs-on: ubuntu-latest + steps: + - name: Validate PR Title + uses: amannn/action-semantic-pull-request@v5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + types: | + feat + fix + docs + style + refactor + perf + test + build + ci + chore + revert + release + scopes: | + checkpoint + checkpoint-postgres + checkpoint-sqlite + cli + langgraph + prebuilt + scheduler-kafka + sdk-py + requireScope: false + ignoreLabels: | + ignore-lint-pr-title From 0733ec65adfbd256dbe4957b358bb0fb73cf18c0 Mon Sep 17 00:00:00 2001 From: Sam Crowder Date: Wed, 9 Jul 2025 11:37:39 -0700 Subject: [PATCH 060/129] docs: introduce LangGraph Server changelog (#5417) * introduce changelog * fix spelling * Update docs/mkdocs.yml Co-authored-by: Lauren Hirata Singh * Update docs/docs/cloud/reference/langgraph_server_changelog.md Co-authored-by: Lauren Hirata Singh * Update docs/docs/cloud/reference/langgraph_server_changelog.md Co-authored-by: Lauren Hirata Singh * Update langgraph_server_changelog.md --------- Co-authored-by: Lauren Hirata Singh --- .../reference/langgraph_server_changelog.md | 93 +++++++++++++++++++ docs/mkdocs.yml | 1 + 2 files changed, 94 insertions(+) create mode 100644 docs/docs/cloud/reference/langgraph_server_changelog.md diff --git a/docs/docs/cloud/reference/langgraph_server_changelog.md b/docs/docs/cloud/reference/langgraph_server_changelog.md new file mode 100644 index 000000000..bd5484e8c --- /dev/null +++ b/docs/docs/cloud/reference/langgraph_server_changelog.md @@ -0,0 +1,93 @@ +# LangGraph Server Changelog + +[LangGraph Server](../../concepts/langgraph_server.md) is an API platform for creating and managing agent-based applications. It provides built-in persistence, a task queue, and supports deploying, configuring, and running assistants (agentic workflows) at scale. This changelog documents all notable updates, features, and fixes to LangGraph Server releases. + +--- + +## v0.2.66 (2025-06-26) +- Fixed a 404 error when creating multiple runs with the same thread_id using `on_not_exist="create"`. + +## v0.2.65 (2025-06-25) +- Ensured that only fields from `assistant_versions` are returned when necessary. +- Ensured consistent data types for in-memory and PostgreSQL users, improving internal authentication handling. + +## v0.2.64 (2025-06-24) +- Added descriptions to version entries for better clarity. + +## v0.2.62 (2025-06-23) +- Improved user handling for custom authentication in the JS Studio. +- Added Prometheus-format run statistics to the metrics endpoint for better monitoring. +- Added run statistics in Prometheus format to the metrics endpoint. + +## v0.2.61 (2025-06-20) +- Set a maximum idle time for Redis connections to prevent unnecessary open connections. + +## v0.2.60 (2025-06-20) +- Enhanced error logging to include traceback details for dictionary operations. +- Added a `/metrics` endpoint to expose queue worker metrics for monitoring. + +## v0.2.57 (2025-06-18) +- Removed CancelledError from retriable exceptions to allow local interrupts while maintaining retriability for workers. +- Introduced middleware to gracefully shut down the server after completing in-flight requests upon receiving a SIGINT. +- Reduced metadata stored in checkpoint to only include necessary information. +- Improved error handling in join runs to return error details when present. + +## v0.2.56 (2025-06-17) +- Improved application stability by adding a handler for SIGTERM signals. + +## v0.2.55 (2025-06-17) +- Improved the handling of cancellations in the queue entrypoint. +- Improved cancellation handling in the queue entry point. + +## v0.2.54 (2025-06-16) +- Enhanced error message for LuaLock timeout during license validation. +- Fixed the $contains filter in custom auth by requiring an explicit ::text cast and updated tests accordingly. +- Ensured project and tenant IDs are formatted as UUIDs for consistency. + +## v0.2.53 (2025-06-13) +- Resolved a timing issue to ensure the queue starts only after the graph is registered. +- Improved performance by setting thread and run status in a single query and enhanced error handling during checkpoint writes. +- Reduced the default background grace period to 3 minutes. + +## v0.2.52 (2025-06-12) +- Now logging expected graphs when one is omitted to improve traceability. +- Implemented a time-to-live (TTL) feature for resumable streams. +- Improved query efficiency and consistency by adding a unique index and optimizing row locking. + +## v0.2.51 (2025-06-12) +- Handled `CancelledError` by marking tasks as ready to retry, improving error management in worker processes. +- Added LG API version and request ID to metadata and logs for better tracking. +- Added LG API version and request ID to metadata and logs to improve traceability. +- Improved database performance by creating indexes concurrently. +- Ensured postgres write is committed only after the Redis running marker is set to prevent race conditions. +- Enhanced query efficiency and reliability by adding a unique index on thread_id/running, optimizing row locks, and ensuring deterministic run selection. +- Resolved a race condition by ensuring Postgres updates only occur after the Redis running marker is set. + +## v0.2.46 (2025-06-07) +- Introduced a new connection for each operation while preserving transaction characteristics in Threads state `update()` and `bulk()` commands. + +## v0.2.45 (2025-06-05) +- Enhanced streaming feature by incorporating tracing contexts. +- Removed an unnecessary query from the Crons.search function. +- Resolved connection reuse issue when scheduling next run for multiple cron jobs. +- Removed an unnecessary query in the Crons.search function to improve efficiency. +- Resolved an issue with scheduling the next cron run by improving connection reuse. + +## v0.2.44 (2025-06-04) +- Enhanced the worker logic to exit the pipeline before continuing when the Redis message limit is reached. +- Introduced a ceiling for Redis message size with an option to skip messages larger than 128 MB for improved performance. +- Ensured the pipeline always closes properly to prevent resource leaks. + +## v0.2.43 (2025-06-04) +- Improved performance by omitting logs in metadata calls and ensuring output schema compliance in value streaming. +- Ensured the connection is properly closed after use. +- Aligned output format to strictly adhere to the specified schema. +- Stopped sending internal logs in metadata requests to improve privacy. + +## v0.2.42 (2025-06-04) +- Added timestamps to track the start and end of a request's run. +- Added tracer information to the configuration settings. +- Added support for streaming with tracing contexts. + +## v0.2.41 (2025-06-03) +- Added locking mechanism to prevent errors in pipelined executions. diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index f11c007ec..2f8ddad26 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -261,6 +261,7 @@ nav: - MCP Adapters: reference/mcp.md - LangGraph Platform: - Server API: cloud/reference/api/api_ref.md + - Server changelog: cloud/reference/langgraph_server_changelog.md - Control Plane API: cloud/reference/api/api_ref_control_plane.md - CLI: cloud/reference/cli.md - SDK (Python): cloud/reference/sdk/python_sdk_ref.md From 8ca5e56f52026c96ef7cb4a8e3e0a71500bd9430 Mon Sep 17 00:00:00 2001 From: Eugene Yurtsev Date: Wed, 9 Jul 2025 14:59:41 -0400 Subject: [PATCH 061/129] fix(docs): links in examples file (#5420) Fix broken links in examples --- .github/workflows/pr_lint.yml | 1 + docs/docs/examples/index.md | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/pr_lint.yml b/.github/workflows/pr_lint.yml index cada5b1ba..50749b528 100644 --- a/.github/workflows/pr_lint.yml +++ b/.github/workflows/pr_lint.yml @@ -38,6 +38,7 @@ jobs: prebuilt scheduler-kafka sdk-py + docs requireScope: false ignoreLabels: | ignore-lint-pr-title diff --git a/docs/docs/examples/index.md b/docs/docs/examples/index.md index 84c721ac3..aadfb0f2c 100644 --- a/docs/docs/examples/index.md +++ b/docs/docs/examples/index.md @@ -5,17 +5,17 @@ The pages in this section provide end-to-end examples for the following topics: ## General - [Template Applications](../concepts/template_applications.md): Create a LangGraph application from a template. -- [Agentic RAG](./rag/langgraph_agentic_rag.md): Build a retrieval agent that can decide when to use a retriever tool. -- [Agent Supervisor](./multi_agent/agent_supervisor.md): Build a supervisor agent that can manage a team of agents. -- [SQL agent](./sql/sql-agent.md): Build a SQL agent that can execute SQL queries and return the results. +- [Agentic RAG](../tutorials/rag/langgraph_agentic_rag.md): Build a retrieval agent that can decide when to use a retriever tool. +- [Agent Supervisor](../tutorials/multi_agent/agent_supervisor.md): Build a supervisor agent that can manage a team of agents. +- [SQL agent](../tutorials/sql/sql-agent.md): Build a SQL agent that can execute SQL queries and return the results. - [Prebuilt chat UI](../agents/ui.md): Use a prebuilt chat UI to interact with any LangGraph agent. - [Graph runs in LangSmith](../how-tos/run-id-langsmith.md): Use LangSmith to track and analyze graph runs. ## LangGraph Platform -- [Set up custom authentication](./auth/getting_started.md): Set up custom authentication for your LangGraph application. -- [Make conversations private](./auth/resource_auth.md): Make conversations private by using resource-based authentication. -- [Connect an authentication provider](./auth/add_auth_server.md): Connect an authentication provider to your LangGraph application. +- [Set up custom authentication](../tutorials/auth/getting_started.md): Set up custom authentication for your LangGraph application. +- [Make conversations private](../tutorials/auth/resource_auth.md): Make conversations private by using resource-based authentication. +- [Connect an authentication provider](../tutorials/auth/add_auth_server.md): Connect an authentication provider to your LangGraph application. - [Rebuild graph at runtime](../cloud/deployment/graph_rebuild.md): Rebuild a graph at runtime. - [Use RemoteGraph](../how-tos/use-remote-graph.md): Use RemoteGraph to deploy your LangGraph application to a remote server. - [Deploy CrewAI, AutoGen, and other frameworks](../how-tos/autogen-integration.md): Deploy CrewAI, AutoGen, and other frameworks with LangGraph. From 0ab97700560147cb9bfac1fe9b50098aaf6b1fd2 Mon Sep 17 00:00:00 2001 From: Sydney Runkle <54324534+sydney-runkle@users.noreply.github.com> Date: Wed, 9 Jul 2025 15:10:20 -0400 Subject: [PATCH 062/129] release(langgraph): v0.5.2 (#5421) langgraph bump --- libs/langgraph/pyproject.toml | 2 +- libs/langgraph/uv.lock | 4 ++-- libs/prebuilt/uv.lock | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/langgraph/pyproject.toml b/libs/langgraph/pyproject.toml index a8dbae74b..811c0a195 100644 --- a/libs/langgraph/pyproject.toml +++ b/libs/langgraph/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "langgraph" -version = "0.5.1" +version = "0.5.2" description = "Building stateful, multi-actor applications with LLMs" authors = [] requires-python = ">=3.9" diff --git a/libs/langgraph/uv.lock b/libs/langgraph/uv.lock index 2762e3fe1..4101e10e7 100644 --- a/libs/langgraph/uv.lock +++ b/libs/langgraph/uv.lock @@ -670,7 +670,7 @@ name = "importlib-metadata" version = "8.7.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "zipp", marker = "python_full_version < '3.11'" }, + { name = "zipp", marker = "python_full_version < '3.10'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/76/66/650a33bd90f786193e4de4b3ad86ea60b53c89b669a5c7be931fac31cdb0/importlib_metadata-8.7.0.tar.gz", hash = "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000", size = 56641, upload-time = "2025-04-27T15:29:01.736Z" } wheels = [ @@ -1192,7 +1192,7 @@ wheels = [ [[package]] name = "langgraph" -version = "0.5.1" +version = "0.5.2" source = { editable = "." } dependencies = [ { name = "langchain-core" }, diff --git a/libs/prebuilt/uv.lock b/libs/prebuilt/uv.lock index 4fbe095ef..a81d27a3c 100644 --- a/libs/prebuilt/uv.lock +++ b/libs/prebuilt/uv.lock @@ -316,7 +316,7 @@ wheels = [ [[package]] name = "langgraph" -version = "0.5.1" +version = "0.5.2" source = { editable = "../langgraph" } dependencies = [ { name = "langchain-core" }, From 63f051ad28226b69794776be3e9cd3a073b9ffb4 Mon Sep 17 00:00:00 2001 From: Sam Crowder Date: Wed, 9 Jul 2025 13:25:47 -0700 Subject: [PATCH 063/129] Update changelog via LangGraph Changelog Bot --- .../reference/langgraph_server_changelog.md | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/docs/docs/cloud/reference/langgraph_server_changelog.md b/docs/docs/cloud/reference/langgraph_server_changelog.md index bd5484e8c..6df35f08d 100644 --- a/docs/docs/cloud/reference/langgraph_server_changelog.md +++ b/docs/docs/cloud/reference/langgraph_server_changelog.md @@ -4,6 +4,55 @@ --- +## v0.2.83 (2025-07-09) +- Reduced the default time-to-live for resumable streams to 2 minutes. +- Enhanced data submission logic to send data to both Beacon and LangSmith instance based on license configuration. +- Enabled submission of self-hosted data to a Langsmith instance when the endpoint is configured. + +## v0.2.82 (2025-07-03) +- Addressed a race condition in background runs by implementing a lock using join, ensuring reliable execution across CTEs. + +## v0.2.81 (2025-07-03) +- Optimized run streams by reducing initial wait time to improve responsiveness for older or non-existent runs. + +## v0.2.80 (2025-07-03) +- Corrected parameter passing in the `logger.ainfo()` API call to resolve a TypeError. + +## v0.2.79 (2025-07-02) +- Fixed a JsonDecodeError in checkpointing with remote graph by correcting JSON serialization to handle trailing slashes properly. +- Introduced a configuration flag to disable webhooks globally across all routes. + +## v0.2.78 (2025-07-02) +- Added timeout retries to webhook calls to improve reliability. +- Added HTTP request metrics, including a request count and latency histogram, for enhanced monitoring capabilities. + +## v0.2.77 (2025-07-02) +- Added HTTP metrics to improve performance monitoring. +- Changed the Redis cache delimiter to reduce conflicts with subgraph message names and updated caching behavior. + +## v0.2.76 (2025-07-01) +- Updated Redis cache delimiter to prevent conflicts with subgraph messages. + +## v0.2.74 (2025-06-30) +- Scheduled webhooks in an isolated loop to ensure thread-safe operations and prevent errors with PYTHONASYNCIODEBUG=1. + +## v0.2.73 (2025-06-27) +- Fixed an infinite frame loop issue and removed the dict_parser due to structlog's unexpected behavior. +- Throw a 409 error on deadlock occurrence during run cancellations to handle lock conflicts gracefully. + +## v0.2.72 (2025-06-27) +- Ensured compatibility with future langgraph versions. +- Implemented a 409 response status to handle deadlock issues during cancellation. + +## v0.2.71 (2025-06-26) +- Improved logging for better clarity and detail regarding log types. + +## v0.2.70 (2025-06-26) +- Improved error handling to better distinguish and log TimeoutErrors caused by users from internal run timeouts. + +## v0.2.69 (2025-06-26) +- Added sorting and pagination to the crons API and updated schema definitions for improved accuracy. + ## v0.2.66 (2025-06-26) - Fixed a 404 error when creating multiple runs with the same thread_id using `on_not_exist="create"`. From 8a9f3dbf6f657958064d581565d3dceb3bda1249 Mon Sep 17 00:00:00 2001 From: Sam Crowder Date: Wed, 9 Jul 2025 13:34:04 -0700 Subject: [PATCH 064/129] Update changelog via LangGraph Changelog Bot --- docs/docs/cloud/reference/langgraph_server_changelog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/docs/cloud/reference/langgraph_server_changelog.md b/docs/docs/cloud/reference/langgraph_server_changelog.md index 6df35f08d..d4cd12045 100644 --- a/docs/docs/cloud/reference/langgraph_server_changelog.md +++ b/docs/docs/cloud/reference/langgraph_server_changelog.md @@ -4,6 +4,9 @@ --- +## v0.2.84 (2025-07-09) +- Removed unnecessary status updates to streamline thread handling and updated version to 0.2.84. + ## v0.2.83 (2025-07-09) - Reduced the default time-to-live for resumable streams to 2 minutes. - Enhanced data submission logic to send data to both Beacon and LangSmith instance based on license configuration. From 5c45f7c330c0a90d71ee1eae4c507b482b6d63fa Mon Sep 17 00:00:00 2001 From: Sam Crowder Date: Wed, 9 Jul 2025 18:06:04 -0700 Subject: [PATCH 065/129] Update changelog via LangGraph Changelog Bot --- docs/docs/cloud/reference/langgraph_server_changelog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/docs/cloud/reference/langgraph_server_changelog.md b/docs/docs/cloud/reference/langgraph_server_changelog.md index d4cd12045..d4d4c2975 100644 --- a/docs/docs/cloud/reference/langgraph_server_changelog.md +++ b/docs/docs/cloud/reference/langgraph_server_changelog.md @@ -4,6 +4,9 @@ --- +## v0.2.85 (2025-07-10) +- Added support for the `on_disconnect` field to `runs/wait` and included disconnect logs for better debugging. + ## v0.2.84 (2025-07-09) - Removed unnecessary status updates to streamline thread handling and updated version to 0.2.84. From 67a86f2dc2e760abfbe2a09793dac771aa6b88c9 Mon Sep 17 00:00:00 2001 From: William FH <13333726+hinthornw@users.noreply.github.com> Date: Wed, 9 Jul 2025 19:07:48 -0700 Subject: [PATCH 066/129] fix[docs]: Add missing flags for langgraph up command (#5429) --- docs/docs/cloud/reference/cli.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/docs/cloud/reference/cli.md b/docs/docs/cloud/reference/cli.md index 2181f59e2..87f405cba 100644 --- a/docs/docs/cloud/reference/cli.md +++ b/docs/docs/cloud/reference/cli.md @@ -409,6 +409,8 @@ The LangGraph CLI requires a JSON configuration file that follows this [schema]( | Option | Default | Description | | ---------------------------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------------- | | `--wait` | | Wait for services to start before returning. Implies --detach | +| `--base-image TEXT` | `langchain/langgraph-api` | Base image to use for the LangGraph API server. Pin to specific versions using version tags. | +| `--image TEXT` | | Docker image to use for the langgraph-api service. If specified, skips building and uses this image directly. | | `--postgres-uri TEXT` | Local database | Postgres URI to use for the database. | | `--watch` | | Restart on file changes | | `--debugger-base-url TEXT` | `http://127.0.0.1:[PORT]` | URL used by the debugger to access LangGraph API. | @@ -436,6 +438,8 @@ The LangGraph CLI requires a JSON configuration file that follows this [schema]( | Option | Default | Description | | ---------------------------------------------------------------------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------------- | | `--wait` | | Wait for services to start before returning. Implies --detach | +| `--base-image TEXT` | `langchain/langgraph-api` | Base image to use for the LangGraph API server. Pin to specific versions using version tags. | +| `--image TEXT` | | Docker image to use for the langgraph-api service. If specified, skips building and uses this image directly. | | `--postgres-uri TEXT` | Local database | Postgres URI to use for the database. | | `--watch` | | Restart on file changes | | `-c, --config FILE` | `langgraph.json` | Path to configuration file declaring dependencies, graphs and environment variables. | From 9b9bf88aeec379fa25ec84d004de04349d21e69c Mon Sep 17 00:00:00 2001 From: William FH <13333726+hinthornw@users.noreply.github.com> Date: Thu, 10 Jul 2025 15:38:05 -0700 Subject: [PATCH 067/129] fix(checkpoint-postgres): Remove python invalid escape warning (#5441) --- libs/checkpoint-postgres/langgraph/store/postgres/base.py | 2 +- libs/checkpoint-postgres/pyproject.toml | 2 +- libs/checkpoint-postgres/uv.lock | 2 +- libs/langgraph/uv.lock | 2 +- libs/prebuilt/uv.lock | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libs/checkpoint-postgres/langgraph/store/postgres/base.py b/libs/checkpoint-postgres/langgraph/store/postgres/base.py index bf17c20cd..73d826d77 100644 --- a/libs/checkpoint-postgres/langgraph/store/postgres/base.py +++ b/libs/checkpoint-postgres/langgraph/store/postgres/base.py @@ -557,7 +557,7 @@ class BasePostgresStore(Generic[C]): ) -> list[tuple[str, Sequence]]: queries: list[tuple[str, Sequence]] = [] for _, op in list_ops: - query = """ + query = r""" SELECT DISTINCT ON (truncated_prefix) truncated_prefix, prefix FROM ( SELECT diff --git a/libs/checkpoint-postgres/pyproject.toml b/libs/checkpoint-postgres/pyproject.toml index 15e7b9aed..d512c4932 100644 --- a/libs/checkpoint-postgres/pyproject.toml +++ b/libs/checkpoint-postgres/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "langgraph-checkpoint-postgres" -version = "2.0.21" +version = "2.0.22" description = "Library with a Postgres implementation of LangGraph checkpoint saver." authors = [] requires-python = ">=3.9" diff --git a/libs/checkpoint-postgres/uv.lock b/libs/checkpoint-postgres/uv.lock index ff12c6faa..d34d05eb2 100644 --- a/libs/checkpoint-postgres/uv.lock +++ b/libs/checkpoint-postgres/uv.lock @@ -334,7 +334,7 @@ dev = [ [[package]] name = "langgraph-checkpoint-postgres" -version = "2.0.21" +version = "2.0.22" source = { editable = "." } dependencies = [ { name = "langgraph-checkpoint" }, diff --git a/libs/langgraph/uv.lock b/libs/langgraph/uv.lock index 4101e10e7..9fcc5350f 100644 --- a/libs/langgraph/uv.lock +++ b/libs/langgraph/uv.lock @@ -1331,7 +1331,7 @@ dev = [ [[package]] name = "langgraph-checkpoint-postgres" -version = "2.0.21" +version = "2.0.22" source = { editable = "../checkpoint-postgres" } dependencies = [ { name = "langgraph-checkpoint" }, diff --git a/libs/prebuilt/uv.lock b/libs/prebuilt/uv.lock index a81d27a3c..c7fc94f57 100644 --- a/libs/prebuilt/uv.lock +++ b/libs/prebuilt/uv.lock @@ -397,7 +397,7 @@ dev = [ [[package]] name = "langgraph-checkpoint-postgres" -version = "2.0.21" +version = "2.0.22" source = { editable = "../checkpoint-postgres" } dependencies = [ { name = "langgraph-checkpoint" }, From 0b6a9e345d3301705e884857d6710a1a84a8edaa Mon Sep 17 00:00:00 2001 From: jito Date: Fri, 11 Jul 2025 10:39:59 +0900 Subject: [PATCH 068/129] fix(langgraph): replace _state_schema to state_schema when accessing StateGraph (#5436) --- libs/langgraph/langgraph/graph/state.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/langgraph/langgraph/graph/state.py b/libs/langgraph/langgraph/graph/state.py index ac0a11e7d..f5e35c665 100644 --- a/libs/langgraph/langgraph/graph/state.py +++ b/libs/langgraph/langgraph/graph/state.py @@ -794,7 +794,7 @@ class StateGraph(Generic[StateT, InputT, OutputT]): interrupt_after: All | list[str] | None = None, debug: bool = False, name: str | None = None, - ) -> CompiledStateGraph[StateT, InputT]: + ) -> CompiledStateGraph[StateT, InputT, OutputT]: """Compiles the state graph into a `CompiledStateGraph` object. The compiled graph implements the `Runnable` interface and can be invoked, @@ -996,7 +996,7 @@ class CompiledStateGraph( writers=[ChannelWrite(write_entries)], ) elif node is not None: - input_schema = node.input if node else self.builder._state_schema + input_schema = node.input if node else self.builder.state_schema input_channels = list(self.builder.schemas[input_schema]) is_single_input = len(input_channels) == 1 and "__root__" in input_channels if input_schema in self.schema_to_mapper: From fbade9e300e5c163a74bf3cfbb10062dc47c0852 Mon Sep 17 00:00:00 2001 From: jito Date: Fri, 11 Jul 2025 23:57:49 +0900 Subject: [PATCH 069/129] docs: fix variable reference in agent evaluator example (#5434) Signed-off-by: jitokim --- docs/docs/agents/evals.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/agents/evals.md b/docs/docs/agents/evals.md index 74fdb5a63..ead956dd5 100644 --- a/docs/docs/agents/evals.md +++ b/docs/docs/agents/evals.md @@ -15,7 +15,7 @@ To evaluate your agent's performance you can use `LangSmith` [evaluations](https def evaluator(*, outputs: dict, reference_outputs: dict): # compare agent outputs against reference outputs output_messages = outputs["messages"] - reference_messages = reference["messages"] + reference_messages = reference_outputs["messages"] score = compare_messages(output_messages, reference_messages) return {"key": "evaluator_score", "score": score} ``` From c3d882e87a88e6975cd0bb0f7a4165182e8fcfb4 Mon Sep 17 00:00:00 2001 From: Sam Crowder Date: Fri, 11 Jul 2025 11:55:08 -0700 Subject: [PATCH 070/129] docs: [LangGraph Server Changelog Bot] Changelog updates for new version(s) (#5455) Update changelog via LangGraph Server Changelog Bot --- docs/docs/cloud/reference/langgraph_server_changelog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/docs/cloud/reference/langgraph_server_changelog.md b/docs/docs/cloud/reference/langgraph_server_changelog.md index d4d4c2975..369c21530 100644 --- a/docs/docs/cloud/reference/langgraph_server_changelog.md +++ b/docs/docs/cloud/reference/langgraph_server_changelog.md @@ -4,6 +4,9 @@ --- +## v0.2.86 (2025-07-11) +- Honored tool descriptions in the `/mcp` endpoint to align with expected functionality. + ## v0.2.85 (2025-07-10) - Added support for the `on_disconnect` field to `runs/wait` and included disconnect logs for better debugging. From 4da35babda464ab6d9ed17d99ae90fec438a047c Mon Sep 17 00:00:00 2001 From: Xin Jin <39755499+EugeneJinXin@users.noreply.github.com> Date: Fri, 11 Jul 2025 12:13:55 -0700 Subject: [PATCH 071/129] feat: add copy page button functionality and fix llms-text output (#5419) * feat: add copy page button functionality and fix llms-text output - Add copy page button with CSS and JS implementation - Implement copy page hooks for MkDocs integration - Fix HTML filtering and DOM text reinterpreted as HTML issues - Update llms-text target to generate docs/llm.txt instead of docs/llms-full.txt - Add necessary styling and package.json dependencies * fix missing button in preview * remove the over-processing * disable API reference --- docs/_scripts/copy_page_hooks.py | 162 +++++++++++++++++++++++++++++++ docs/mkdocs.yml | 1 + docs/overrides/copy-page.css | 16 +++ docs/overrides/copy-page.js | 38 ++++++++ docs/overrides/main.html | 135 ++++++++++++++++++++++++++ docs/package.json | 3 +- 6 files changed, 354 insertions(+), 1 deletion(-) create mode 100644 docs/_scripts/copy_page_hooks.py create mode 100644 docs/overrides/copy-page.css create mode 100644 docs/overrides/copy-page.js diff --git a/docs/_scripts/copy_page_hooks.py b/docs/_scripts/copy_page_hooks.py new file mode 100644 index 000000000..2dd42b29c --- /dev/null +++ b/docs/_scripts/copy_page_hooks.py @@ -0,0 +1,162 @@ +""" +Copy page functionality hooks for MkDocs. + +This module provides hooks to inject original markdown content into HTML pages +for the copy page functionality, allowing users to copy clean markdown content +optimized for LLMs. +""" + +import json +import re +from pathlib import Path +from typing import Optional + +from mkdocs.config.defaults import MkDocsConfig +from mkdocs.structure.pages import Page + + +def _process_includes(content: str, docs_dir: Path) -> str: + """Process MkDocs includes like {!../README.md!}.""" + include_pattern = r'\{!([^!]+)!\}' + + def replace_include(match): + include_path = match.group(1) + # Resolve relative path + if include_path.startswith('../'): + # Go up from docs dir + include_file = docs_dir.parent / include_path[3:] + else: + include_file = docs_dir / include_path + + try: + with open(include_file, 'r', encoding='utf-8') as f: + included_content = f.read() + # Remove frontmatter from included content to avoid duplication + included_content = re.sub(r'^---\n.*?\n---\n', '', included_content, flags=re.DOTALL) + return included_content + except: + return f"[Content from {include_path}]" + + return re.sub(include_pattern, replace_include, content) + + +def _clean_markdown(content: str) -> str: + """Minimal cleanup of markdown content - preserve original as much as possible.""" + # Remove frontmatter + content = re.sub(r'^---\n.*?\n---\n', '', content, flags=re.DOTALL) + + # Remove script tags (security) + content = re.sub(r']*>.*?', '', content, flags=re.DOTALL | re.IGNORECASE) + + # Remove style tags (security) + content = re.sub(r']*>.*?', '', content, flags=re.DOTALL | re.IGNORECASE) + + # Remove HTML comments + content = re.sub(r'', '', content, flags=re.DOTALL) + + # Just strip and return - preserve original structure + return content.strip() + + +def inject_markdown_content(html: str, page: Page, config: MkDocsConfig) -> str: + """ + Inject the original markdown content into the HTML for copy page functionality. + + Args: + html: The HTML content to inject into + page: The MkDocs page object + config: The MkDocs configuration + + Returns: + Modified HTML with markdown content injected as JSON + """ + if not hasattr(page, 'file') or not page.file: + return html + + # Get the original markdown file path + docs_dir = Path(config.get('docs_dir', 'docs')) + src_path = page.file.src_path + + # Handle different file types + if src_path.endswith('.ipynb'): + # For notebook files, we might want to use the converted markdown + # For now, just return the HTML as-is + return html + + markdown_file = docs_dir / src_path + + if not markdown_file.exists(): + return html + + try: + # Read the original markdown content + with open(markdown_file, 'r', encoding='utf-8') as f: + markdown_content = f.read() + + # Special handling for index page - use relative path to the actual README.md + if src_path == 'index.md': + # Relative path to the repository README.md file (go up two levels from docs/docs) + readme_path = docs_dir.parent.parent / 'README.md' + + try: + with open(readme_path, 'r', encoding='utf-8') as f: + readme_content = f.read() + # Remove frontmatter if present + processed_markdown = re.sub(r'^---\n.*?\n---\n', '', readme_content, flags=re.DOTALL) + processed_markdown = processed_markdown.strip() + except Exception as e: + # If we can't read the README, fallback to original behavior + processed_markdown = _process_includes(markdown_content, docs_dir) + processed_markdown = re.sub(r'^---\n.*?\n---\n', '', processed_markdown, flags=re.DOTALL) + processed_markdown = processed_markdown.strip() + else: + # Process any includes in the markdown to get the full content + processed_markdown = _process_includes(markdown_content, docs_dir) + # Clean up the processed markdown normally for other pages + processed_markdown = _clean_markdown(processed_markdown) + + # Create the JSON data + markdown_data = { + 'markdown': processed_markdown, + 'title': page.title or 'Page Content', + 'url': page.url or '' + } + + # Properly escape the JSON for HTML + json_content = json.dumps(markdown_data, ensure_ascii=False) + json_content = json_content.replace('{json_content}' + + # Insert before if it exists, otherwise before + if '' in html: + html = html.replace('', f'{script_content}') + elif '' in html: + html = html.replace('', f'{script_content}') + + except Exception as e: + # If anything goes wrong, just return the original HTML + # Could log the error here if needed + pass + + return html + + +def on_post_page(output: str, page: Page, config: MkDocsConfig) -> str: + """ + MkDocs hook to inject markdown content into HTML pages. + + This hook is called after each page is rendered and injects the original + markdown content as JSON for the copy page functionality. + + Args: + output: The HTML output of the page + page: The MkDocs page object + config: The MkDocs configuration + + Returns: + Modified HTML with markdown content injected + """ + return inject_markdown_content(output, page, config) \ No newline at end of file diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 2f8ddad26..745560fbc 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -362,6 +362,7 @@ markdown_extensions: - github-callouts hooks: - _scripts/notebook_hooks.py + - _scripts/copy_page_hooks.py extra: social: - icon: fontawesome/brands/js diff --git a/docs/overrides/copy-page.css b/docs/overrides/copy-page.css new file mode 100644 index 000000000..17360f4ba --- /dev/null +++ b/docs/overrides/copy-page.css @@ -0,0 +1,16 @@ +/* Minimal CSS for copy page button */ +.copy-page-btn { + background: transparent; + border: 1px solid var(--md-default-fg-color--lightest); + padding: 6px 12px; + margin-right: 8px; + border-radius: 4px; + cursor: pointer; + font-size: 14px; + color: var(--md-default-fg-color); + transition: all 0.2s ease; +} + +.copy-page-btn:hover { + background: var(--md-default-fg-color--lightest); +} \ No newline at end of file diff --git a/docs/overrides/copy-page.js b/docs/overrides/copy-page.js new file mode 100644 index 000000000..61afb1900 --- /dev/null +++ b/docs/overrides/copy-page.js @@ -0,0 +1,38 @@ +// Simple copy page functionality - just copy the markdown content +function copyPageAsMarkdown() { + const markdownScript = document.getElementById('page-markdown-content'); + if (!markdownScript) { + alert('Markdown content not available for this page'); + return; + } + + try { + const data = JSON.parse(markdownScript.textContent); + const content = `# ${data.title}\n\nSource: ${window.location.href}\n\n${data.markdown}`; + + navigator.clipboard.writeText(content).then(() => { + // Simple notification + const notification = document.createElement('div'); + notification.textContent = 'Page content copied to clipboard'; + notification.style.cssText = 'position:fixed;top:20px;right:20px;background:#4CAF50;color:white;padding:10px;border-radius:4px;z-index:9999;'; + document.body.appendChild(notification); + setTimeout(() => notification.remove(), 3000); + }).catch(() => { + alert('Failed to copy content'); + }); + } catch (e) { + alert('Failed to parse page content'); + } +} + +// Add button to header - simpler approach +document.addEventListener('DOMContentLoaded', function() { + const headerSource = document.querySelector('.md-header__source'); + if (headerSource) { + const button = document.createElement('button'); + button.textContent = 'Copy page'; + button.onclick = copyPageAsMarkdown; + button.style.cssText = 'background:none;border:1px solid #ddd;padding:6px 12px;margin-right:8px;border-radius:4px;cursor:pointer;'; + headerSource.parentNode.insertBefore(button, headerSource); + } +}); \ No newline at end of file diff --git a/docs/overrides/main.html b/docs/overrides/main.html index b3e63c56d..3e35ab581 100644 --- a/docs/overrides/main.html +++ b/docs/overrides/main.html @@ -13,6 +13,130 @@ j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= {% block extrahead %} + {% endblock %} diff --git a/docs/package.json b/docs/package.json index 1a5908a84..abcdef39c 100644 --- a/docs/package.json +++ b/docs/package.json @@ -9,7 +9,8 @@ "@langchain/core": "^0.3.38", "@langchain/openai": "^0.4.2", "msgpack-lite": "^0.1.26", - "nock": "^14.0.1" + "nock": "^14.0.1", + "he": "^1.2.0" }, "devDependencies": { "@tsconfig/recommended": "^1.0.8", From d166e9b8e9ab90cbf2a1828e553d628c4611c783 Mon Sep 17 00:00:00 2001 From: Xin Jin <39755499+EugeneJinXin@users.noreply.github.com> Date: Fri, 11 Jul 2025 13:40:37 -0700 Subject: [PATCH 072/129] fix: llm.txt url link broken (#5460) fix url issue --- docs/overrides/main.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/overrides/main.html b/docs/overrides/main.html index 3e35ab581..16aa71ce5 100644 --- a/docs/overrides/main.html +++ b/docs/overrides/main.html @@ -101,7 +101,7 @@ j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= }; option2.onmouseout = function() { this.style.background = 'transparent'; }; option2.onclick = function() { - window.open('/llms-txt-overview/', '_blank'); + window.open('/langgraph/llms-txt-overview/', '_blank'); dropdown.style.display = 'none'; }; From f59a1339c930601cf59f3c560f0664e76c20c45d Mon Sep 17 00:00:00 2001 From: Eugene Yurtsev Date: Fri, 11 Jul 2025 16:44:46 -0400 Subject: [PATCH 073/129] chore(docs): Consolidate hooks for copy markdown and notebooks (#5459) Consolidating the hooks to avoid duplication of logic We need this change for consolidating js and python content: we need include-markdown to run as a mkdocs plugin before our pipeline (rather than as markdown extension which runs after our hooks plugin). --- docs/_scripts/copy_page_hooks.py | 162 - docs/_scripts/notebook_hooks.py | 56 +- docs/docs/agents/models.md | 2 +- docs/docs/how-tos/graph-api.md | 2 +- .../docs/how-tos/memory/semantic-search.ipynb | 2 +- docs/docs/index.md | 2 +- docs/docs/snippets/chat_model_tabs.md | 87 + .../get-started/1-build-basic-chatbot.md | 2 +- .../docs/tutorials/get-started/2-add-tools.md | 4 +- .../tutorials/get-started/3-add-memory.md | 2 +- .../get-started/4-human-in-the-loop.md | 4 +- .../get-started/5-customize-state.md | 2 +- .../tutorials/get-started/6-time-travel.md | 2 +- .../tutorials/llm-compiler/LLMCompiler.ipynb | 16 +- .../plan-and-execute/plan-and-execute.ipynb | 2 +- docs/docs/tutorials/tnt-llm/tnt-llm.ipynb | 14 +- docs/mkdocs.yml | 4 +- docs/pyproject.toml | 3 +- docs/uv.lock | 3552 +++++++---------- 19 files changed, 1629 insertions(+), 2291 deletions(-) delete mode 100644 docs/_scripts/copy_page_hooks.py create mode 100644 docs/docs/snippets/chat_model_tabs.md diff --git a/docs/_scripts/copy_page_hooks.py b/docs/_scripts/copy_page_hooks.py deleted file mode 100644 index 2dd42b29c..000000000 --- a/docs/_scripts/copy_page_hooks.py +++ /dev/null @@ -1,162 +0,0 @@ -""" -Copy page functionality hooks for MkDocs. - -This module provides hooks to inject original markdown content into HTML pages -for the copy page functionality, allowing users to copy clean markdown content -optimized for LLMs. -""" - -import json -import re -from pathlib import Path -from typing import Optional - -from mkdocs.config.defaults import MkDocsConfig -from mkdocs.structure.pages import Page - - -def _process_includes(content: str, docs_dir: Path) -> str: - """Process MkDocs includes like {!../README.md!}.""" - include_pattern = r'\{!([^!]+)!\}' - - def replace_include(match): - include_path = match.group(1) - # Resolve relative path - if include_path.startswith('../'): - # Go up from docs dir - include_file = docs_dir.parent / include_path[3:] - else: - include_file = docs_dir / include_path - - try: - with open(include_file, 'r', encoding='utf-8') as f: - included_content = f.read() - # Remove frontmatter from included content to avoid duplication - included_content = re.sub(r'^---\n.*?\n---\n', '', included_content, flags=re.DOTALL) - return included_content - except: - return f"[Content from {include_path}]" - - return re.sub(include_pattern, replace_include, content) - - -def _clean_markdown(content: str) -> str: - """Minimal cleanup of markdown content - preserve original as much as possible.""" - # Remove frontmatter - content = re.sub(r'^---\n.*?\n---\n', '', content, flags=re.DOTALL) - - # Remove script tags (security) - content = re.sub(r']*>.*?', '', content, flags=re.DOTALL | re.IGNORECASE) - - # Remove style tags (security) - content = re.sub(r']*>.*?', '', content, flags=re.DOTALL | re.IGNORECASE) - - # Remove HTML comments - content = re.sub(r'', '', content, flags=re.DOTALL) - - # Just strip and return - preserve original structure - return content.strip() - - -def inject_markdown_content(html: str, page: Page, config: MkDocsConfig) -> str: - """ - Inject the original markdown content into the HTML for copy page functionality. - - Args: - html: The HTML content to inject into - page: The MkDocs page object - config: The MkDocs configuration - - Returns: - Modified HTML with markdown content injected as JSON - """ - if not hasattr(page, 'file') or not page.file: - return html - - # Get the original markdown file path - docs_dir = Path(config.get('docs_dir', 'docs')) - src_path = page.file.src_path - - # Handle different file types - if src_path.endswith('.ipynb'): - # For notebook files, we might want to use the converted markdown - # For now, just return the HTML as-is - return html - - markdown_file = docs_dir / src_path - - if not markdown_file.exists(): - return html - - try: - # Read the original markdown content - with open(markdown_file, 'r', encoding='utf-8') as f: - markdown_content = f.read() - - # Special handling for index page - use relative path to the actual README.md - if src_path == 'index.md': - # Relative path to the repository README.md file (go up two levels from docs/docs) - readme_path = docs_dir.parent.parent / 'README.md' - - try: - with open(readme_path, 'r', encoding='utf-8') as f: - readme_content = f.read() - # Remove frontmatter if present - processed_markdown = re.sub(r'^---\n.*?\n---\n', '', readme_content, flags=re.DOTALL) - processed_markdown = processed_markdown.strip() - except Exception as e: - # If we can't read the README, fallback to original behavior - processed_markdown = _process_includes(markdown_content, docs_dir) - processed_markdown = re.sub(r'^---\n.*?\n---\n', '', processed_markdown, flags=re.DOTALL) - processed_markdown = processed_markdown.strip() - else: - # Process any includes in the markdown to get the full content - processed_markdown = _process_includes(markdown_content, docs_dir) - # Clean up the processed markdown normally for other pages - processed_markdown = _clean_markdown(processed_markdown) - - # Create the JSON data - markdown_data = { - 'markdown': processed_markdown, - 'title': page.title or 'Page Content', - 'url': page.url or '' - } - - # Properly escape the JSON for HTML - json_content = json.dumps(markdown_data, ensure_ascii=False) - json_content = json_content.replace('{json_content}' - - # Insert before if it exists, otherwise before - if '' in html: - html = html.replace('', f'{script_content}') - elif '' in html: - html = html.replace('', f'{script_content}') - - except Exception as e: - # If anything goes wrong, just return the original HTML - # Could log the error here if needed - pass - - return html - - -def on_post_page(output: str, page: Page, config: MkDocsConfig) -> str: - """ - MkDocs hook to inject markdown content into HTML pages. - - This hook is called after each page is rendered and injects the original - markdown content as JSON for the copy page functionality. - - Args: - output: The HTML output of the page - page: The MkDocs page object - config: The MkDocs configuration - - Returns: - Modified HTML with markdown content injected - """ - return inject_markdown_content(output, page, config) \ No newline at end of file diff --git a/docs/_scripts/notebook_hooks.py b/docs/_scripts/notebook_hooks.py index db31e41ce..5ddb38289 100644 --- a/docs/_scripts/notebook_hooks.py +++ b/docs/_scripts/notebook_hooks.py @@ -3,6 +3,7 @@ Lifecycle events: https://www.mkdocs.org/dev-guide/plugins/#events """ +import json import logging import os import posixpath @@ -15,8 +16,8 @@ from mkdocs.structure.files import Files, File from mkdocs.structure.pages import Page from _scripts.generate_api_reference_links import update_markdown_with_imports -from _scripts.notebook_convert import convert_notebook from _scripts.link_map import JS_LINK_MAP +from _scripts.notebook_convert import convert_notebook logger = logging.getLogger(__name__) logging.basicConfig() @@ -356,12 +357,16 @@ def _on_page_markdown_with_config( def on_page_markdown(markdown: str, page: Page, **kwargs: Dict[str, Any]): - return _on_page_markdown_with_config( - markdown, - page, - add_api_references=True, - **kwargs, + finalized_markdown = ( + _on_page_markdown_with_config( + markdown, + page, + add_api_references=True, + **kwargs, + ) ) + page.meta["original_markdown"] = finalized_markdown + return finalized_markdown # redirects @@ -431,20 +436,51 @@ height="0" width="0" style="display:none;visibility:hidden"> else: return html # fallback if no found +def _inject_markdown_into_html(html: str, page: Page) -> str: + """Inject the original markdown content into the HTML page as JSON.""" + original_markdown = page.meta.get("original_markdown", "") + if not original_markdown: + return html + markdown_data = { + "markdown": original_markdown, + "title": page.title or "Page Content", + "url": page.url or "", + } -def on_post_page(output: str, page: Page, config: MkDocsConfig) -> str: + # Properly escape the JSON for HTML + json_content = json.dumps(markdown_data, ensure_ascii=False) + + json_content = ( + json_content.replace("{json_content}' + ) + + # Insert before if it exists, otherwise before + if "" not in html: + raise ValueError( + "HTML does not contain tag. Cannot inject markdown content." + ) + return html.replace("", f"{script_content}") + +def on_post_page(html: str, page: Page, config: MkDocsConfig) -> str: """Inject Google Tag Manager noscript tag immediately after . Args: - output: The HTML output of the page. + html: The HTML output of the page. page: The page instance. config: The MkDocs configuration object. Returns: modified HTML output with GTM code injected. """ - return _inject_gtm(output) - + html = _inject_markdown_into_html(html, page) + return _inject_gtm(html) # Create HTML files for redirects after site dir has been built def on_post_build(config): diff --git a/docs/docs/agents/models.md b/docs/docs/agents/models.md index 6b8af56a7..46db9c41d 100644 --- a/docs/docs/agents/models.md +++ b/docs/docs/agents/models.md @@ -7,7 +7,7 @@ LangGraph provides built-in support for [LLMs (language models)](https://python. Use [`init_chat_model`](https://python.langchain.com/docs/how_to/chat_models_universal_init/) to initialize models: -{!snippets/chat_model_tabs.md!} +{% include-markdown "../../snippets/chat_model_tabs.md" %} ### Instantiate a model directly diff --git a/docs/docs/how-tos/graph-api.md b/docs/docs/how-tos/graph-api.md index 4a71cc77d..6fa8bd241 100644 --- a/docs/docs/how-tos/graph-api.md +++ b/docs/docs/how-tos/graph-api.md @@ -1507,7 +1507,7 @@ Because many LangChain objects implement the [Runnable Protocol](https://python. See example below. To demonstrate async invocations of underlying LLMs, we will include a chat model: -{!snippets/chat_model_tabs.md!} +{% include-markdown "../../snippets/chat_model_tabs.md" %} ```python from langchain.chat_models import init_chat_model diff --git a/docs/docs/how-tos/memory/semantic-search.ipynb b/docs/docs/how-tos/memory/semantic-search.ipynb index 890363ef4..c952ac6ea 100644 --- a/docs/docs/how-tos/memory/semantic-search.ipynb +++ b/docs/docs/how-tos/memory/semantic-search.ipynb @@ -125,7 +125,7 @@ "memories = store.search((\"user_123\", \"memories\"), query=\"I like food?\", limit=5)\n", "\n", "for memory in memories:\n", - " print(f'Memory: {memory.value[\"text\"]} (similarity: {memory.score})')" + " print(f\"Memory: {memory.value['text']} (similarity: {memory.score})\")" ] }, { diff --git a/docs/docs/index.md b/docs/docs/index.md index 60ec1b509..db036367a 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -28,4 +28,4 @@ title: LangGraph } -{!../README.md!} \ No newline at end of file +{% include-markdown "../../README.md" %} \ No newline at end of file diff --git a/docs/docs/snippets/chat_model_tabs.md b/docs/docs/snippets/chat_model_tabs.md new file mode 100644 index 000000000..e984e1821 --- /dev/null +++ b/docs/docs/snippets/chat_model_tabs.md @@ -0,0 +1,87 @@ +=== "OpenAI" + + ```shell + pip install -U "langchain[openai]" + ``` + ```python + import os + from langchain.chat_models import init_chat_model + + os.environ["OPENAI_API_KEY"] = "sk-..." + + llm = init_chat_model("openai:gpt-4.1") + ``` + + 👉 Read the [OpenAI integration docs](https://python.langchain.com/docs/integrations/chat/openai/) + +=== "Anthropic" + + ```shell + pip install -U "langchain[anthropic]" + ``` + ```python + import os + from langchain.chat_models import init_chat_model + + os.environ["ANTHROPIC_API_KEY"] = "sk-..." + + llm = init_chat_model("anthropic:claude-3-5-sonnet-latest") + ``` + + 👉 Read the [Anthropic integration docs](https://python.langchain.com/docs/integrations/chat/anthropic/) + +=== "Azure" + + ```shell + pip install -U "langchain[openai]" + ``` + ```python + import os + from langchain.chat_models import init_chat_model + + os.environ["AZURE_OPENAI_API_KEY"] = "..." + os.environ["AZURE_OPENAI_ENDPOINT"] = "..." + os.environ["OPENAI_API_VERSION"] = "2025-03-01-preview" + + llm = init_chat_model( + "azure_openai:gpt-4.1", + azure_deployment=os.environ["AZURE_OPENAI_DEPLOYMENT_NAME"], + ) + ``` + + 👉 Read the [Azure integration docs](https://python.langchain.com/docs/integrations/chat/azure_chat_openai/) + +=== "Google Gemini" + + ```shell + pip install -U "langchain[google-genai]" + ``` + ```python + import os + from langchain.chat_models import init_chat_model + + os.environ["GOOGLE_API_KEY"] = "..." + + llm = init_chat_model("google_genai:gemini-2.0-flash") + ``` + + 👉 Read the [Google GenAI integration docs](https://python.langchain.com/docs/integrations/chat/google_generative_ai/) + +=== "AWS Bedrock" + + ```shell + pip install -U "langchain[aws]" + ``` + ```python + from langchain.chat_models import init_chat_model + + # Follow the steps here to configure your credentials: + # https://docs.aws.amazon.com/bedrock/latest/userguide/getting-started.html + + llm = init_chat_model( + "anthropic.claude-3-5-sonnet-20240620-v1:0", + model_provider="bedrock_converse", + ) + ``` + + 👉 Read the [AWS Bedrock integration docs](https://python.langchain.com/docs/integrations/chat/bedrock/) diff --git a/docs/docs/tutorials/get-started/1-build-basic-chatbot.md b/docs/docs/tutorials/get-started/1-build-basic-chatbot.md index 3304822c6..b32e42861 100644 --- a/docs/docs/tutorials/get-started/1-build-basic-chatbot.md +++ b/docs/docs/tutorials/get-started/1-build-basic-chatbot.md @@ -63,7 +63,7 @@ Next, add a "`chatbot`" node. **Nodes** represent units of work and are typicall Let's first select a chat model: -{!snippets/chat_model_tabs.md!} +{% include-markdown "../../../snippets/chat_model_tabs.md" %}
\n", - "

Set up LangSmith for LangGraph development

\n", - "

\n", - " Sign up for LangSmith to quickly spot issues and improve the performance of your LangGraph projects. LangSmith lets you use trace data to debug, test, and monitor your LLM apps built with LangGraph — read more about how to get started here. \n", - "

\n", - "

Set up LangSmith for better debugging